diff options
| author | Akshay Nair <phenax5@gmail.com> | 2023-08-11 12:08:29 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2023-08-11 12:08:29 +0530 |
| commit | dfd4da6ca2d06c9d05d5c7e297304316da211dd4 (patch) | |
| tree | 767357e8b739be3551b3a6b9ade4ddc02867044f /src/index.ts | |
| parent | 8572af0d04d0c5112f79f770197bb6422fc507d4 (diff) | |
| download | css-everything-dfd4da6ca2d06c9d05d5c7e297304316da211dd4.tar.gz css-everything-dfd4da6ca2d06c9d05d5c7e297304316da211dd4.zip | |
feat: supports hydration for repeat renders
Diffstat (limited to '')
| -rw-r--r-- | src/index.ts | 93 |
1 files changed, 48 insertions, 45 deletions
diff --git a/src/index.ts b/src/index.ts index f09d940..4987e65 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,90 +1,93 @@ -import { Dependencies, evalExpr } from "./eval"; -import { parse } from "./parser"; +import { Dependencies, evalExpr } from './eval' +import { parse } from './parser' -const UNSET_PROPERTY_VALUE = '<unset>'; +const UNSET_PROPERTY_VALUE = '<unset>' const EVENT_HANDLERS = { click: '--cssx-on-click', load: '--cssx-on-load', } const injectStyles = () => { - const STYLE_TAG_CLASS = 'cssx-style-root'; - if (document.querySelector(`.${STYLE_TAG_CLASS}`)) return; + const STYLE_TAG_CLASS = 'cssx-style-root' + if (document.querySelector(`.${STYLE_TAG_CLASS}`)) return - const $style = document.createElement('style'); - $style.className = STYLE_TAG_CLASS; + const $style = document.createElement('style') + $style.className = STYLE_TAG_CLASS - const properties = [ - '--cssx-children', - ...Object.values(EVENT_HANDLERS), - ]; + const properties = ['--cssx-children', ...Object.values(EVENT_HANDLERS)] $style.textContent = `.cssx-layer { - ${properties.map(p => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')} - }`; + ${properties.map((p) => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')} + }` - document.body.appendChild($style); + document.body.appendChild($style) } -const getPropertyValue = ($element: HTMLElement, prop: string) => { +const getPropertyValue = ($element: Element, prop: string) => { const value = `${getComputedStyle($element).getPropertyValue(prop)}`.trim() - return !value || value === UNSET_PROPERTY_VALUE ? '' : value; -}; + return !value || value === UNSET_PROPERTY_VALUE ? '' : value +} -const getChildrenIds = ($element: HTMLElement) => { +const getChildrenIds = ($element: Element) => { const value = getPropertyValue($element, '--cssx-children') return value.split(/(\s*,\s*)|\s+/g).filter(Boolean) } -const evalDeps = (_el: HTMLElement): Dependencies => ({ +const evalDeps = (_el: Element): Dependencies => ({ addClass: async (id, cls) => document.getElementById(id)?.classList.add(cls), - removeClass: async (id, cls) => document.getElementById(id)?.classList.remove(cls), - delay: delay => new Promise((res) => setTimeout(res, delay)), - jsEval: async js => (0, eval)(js), + removeClass: async (id, cls) => + document.getElementById(id)?.classList.remove(cls), + delay: (delay) => new Promise((res) => setTimeout(res, delay)), + jsEval: async (js) => (0, eval)(js), }) -const handleEvents = async ($element: HTMLElement) => { +const handleEvents = async ($element: Element) => { for (const [event, property] of Object.entries(EVENT_HANDLERS)) { - const handlerExpr = getPropertyValue($element, property); + const handlerExpr = getPropertyValue($element, property) if (handlerExpr) { - ($element as any)[`on${event}`] = async () => { + ;($element as any)[`on${event}`] = async () => { console.log(`Triggered event: ${event}`) const exprs = parse(handlerExpr) for (const expr of exprs) { await evalExpr(expr, evalDeps($element)) } - }; + } } } -}; +} -let iters = 0; -const manageElement = async ($element: HTMLElement) => { - if (iters++ > 100) return; // NOTE: Temporary. To prevent infinite rec +let nodeCount = 0 +const manageElement = async ($element: Element) => { + if (nodeCount++ > 100) return // NOTE: Temporary. To prevent infinite rec - await handleEvents($element); + await handleEvents($element) + const childrenIds = getChildrenIds($element) - const $childrenRoot = Object.assign(document.createElement('div'), { - className: 'cssx-layer', - }); - $element.appendChild($childrenRoot); + if (childrenIds.length > 0) { + const $childrenRoot = + $element.querySelector(':scope > .cssx-layer') ?? + Object.assign(document.createElement('div'), { + className: 'cssx-layer', + }) + $element.appendChild($childrenRoot) - const childrenIds = getChildrenIds($element); - for (const id of childrenIds) { - const $child = Object.assign(document.createElement('div'), { id }); - $childrenRoot.appendChild($child); - await manageElement($child); + for (const id of childrenIds) { + const $child = + $childrenRoot.querySelector(`:scope > #${id}`) ?? + Object.assign(document.createElement('div'), { id }) + $childrenRoot.appendChild($child) + await manageElement($child) + } } } interface Options { - root?: HTMLElement; + root?: HTMLElement } const render = async ({ root = document.body }: Options = {}) => { - injectStyles(); - await manageElement(root); + injectStyles() + await manageElement(root) } -render(); - +render() |
