Last active
April 27, 2023 11:35
-
-
Save mariusandra/ed989e0a362cb9beb30526abf85b1021 to your computer and use it in GitHub Desktop.
dimensions plugin for kea
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { setPluginContext, getPluginContext, useMountedLogic } from 'kea' | |
import { useEffect } from 'react' | |
/* | |
usage: | |
kea({ | |
dimensions: { | |
// key: [defaultValue, calcFunction], | |
isSmallScreen: [false, window => window.innerWidth < 640], | |
windowWidth: [window.innterWidth, window => window.innerWidth], | |
} | |
}) | |
*/ | |
export default { | |
name: 'dimensions', | |
defaults: () => ({ | |
dimensionsInput: false | |
}), | |
events: { | |
afterPlugin () { | |
setPluginContext('dimensions', { | |
listener: undefined, | |
mounted: {} | |
}) | |
}, | |
beforeCloseContext () { | |
const { listener } = getPluginContext('dimensions') | |
if (listener) { | |
window.removeEventListener('scroll', listener) | |
window.removeEventListener('resize', listener) | |
} | |
}, | |
beforeLogic (logic, input) { | |
if (input.dimensions) { | |
logic.extend({ | |
actions: () => ({ | |
updateDimensionsPluginObjects: values => ({ values }) | |
}), | |
reducers: ({ actions }) => { | |
let reducers = {} | |
Object.entries(input.dimensions).forEach(([key, [defaultValue, _]]) => { | |
reducers[key] = [ | |
defaultValue, | |
{ | |
[actions.updateDimensionsPluginObjects]: (state, payload) => | |
typeof payload.values[key] === 'undefined' ? state : payload.values[key] | |
} | |
] | |
}) | |
return reducers | |
} | |
}) | |
logic.dimensionsInput = { ...(logic.dimensionsInput || {}), ...input.dimensions } | |
} | |
}, | |
afterMount (logic) { | |
if (!logic.dimensionsInput || typeof window === 'undefined') { | |
return | |
} | |
const pluginContext = getPluginContext('dimensions') | |
pluginContext.mounted[logic.pathString] = () => { | |
let updates = {} | |
Object.entries(logic.dimensionsInput).forEach(([key, [_, calcFunction]]) => { | |
const oldValue = logic.values[key] | |
const newValue = calcFunction(window) | |
if (oldValue !== newValue) { | |
updates[key] = newValue | |
} | |
}) | |
if (Object.keys(updates).length > 0) { | |
logic.actions.updateDimensionsPluginObjects(updates) | |
} | |
} | |
if (!pluginContext.listener) { | |
pluginContext.listener = function (e) { | |
Object.values(pluginContext.mounted).forEach(l => l()) | |
} | |
window.addEventListener('scroll', pluginContext.listener) | |
window.addEventListener('resize', pluginContext.listener) | |
} | |
}, | |
beforeUnmount (logic) { | |
if (!logic.dimensionsInput || typeof window === 'undefined') { | |
return | |
} | |
const { mounted, listener } = getPluginContext('dimensions') | |
delete mounted[logic.pathString] | |
if (listener && Object.keys(mounted).length === 0) { | |
window.removeEventListener('scroll', listener) | |
window.removeEventListener('resize', listener) | |
} | |
}, | |
beforeRender (logic, props) { | |
if (!logic.dimensionsInput || typeof window === 'undefined') { | |
return | |
} | |
useUpdateDimensions(logic) | |
} | |
} | |
} | |
export function useUpdateDimensions (logic) { | |
useMountedLogic(logic) | |
useEffect(() => { | |
const { mounted } = getPluginContext('dimensions') | |
mounted[logic.pathString] && mounted[logic.pathString]() | |
}, [logic, logic.pathString]) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment