Skip to content

Instantly share code, notes, and snippets.

@mariusandra
Last active April 27, 2023 11:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mariusandra/ed989e0a362cb9beb30526abf85b1021 to your computer and use it in GitHub Desktop.
Save mariusandra/ed989e0a362cb9beb30526abf85b1021 to your computer and use it in GitHub Desktop.
dimensions plugin for kea
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