diff options
| -rw-r--r-- | TODO.norg | 17 | ||||
| -rw-r--r-- | examples/form/signup.css | 17 | ||||
| -rw-r--r-- | examples/form/style.css | 17 | ||||
| -rw-r--r-- | examples/todo-list/style.css | 11 | ||||
| -rw-r--r-- | src/index.ts | 30 |
5 files changed, 55 insertions, 37 deletions
@@ -19,17 +19,14 @@ - (x) `add-element` & `remove-element` - (x) conditionals - (x) on update - - ( ) children of instance must also be instantiated - - ( ) access child from an instance (update checkbox) - - ( ) access instance from child (delete task) - - ( ) filter for on update on specific properties - - ( ) eval - - ( ) update property on child on update of parent - - ( ) functions/lazy properties? - - ( ) string concatenation - - ( ) `request` error handling + - (x) access child from an instance (update checkbox) + - (x) access instance from child (delete task) + - ( ) Update --cssx-text on update - ( ) keyboard events + - ( ) string concatenation + - ( ) eval - ( ) Code cleanup + - ( ) `request` error handling * Later - ( ) `add-class` & `remove-class` should use self if id is not specified? @@ -37,6 +34,8 @@ - ( ) access an instance of component - ( ) Additional events - ( ) Improve error messages + - ( ) filter for on update on specific properties + - ( ) update property on child on update of parent * Maybe - ( ) `list` & `tuple` data structures? diff --git a/examples/form/signup.css b/examples/form/signup.css index e633243..3433b87 100644 --- a/examples/form/signup.css +++ b/examples/form/signup.css @@ -4,10 +4,11 @@ max-width: 700px; margin: 1rem auto; - --cssx-disgustingly-set-innerhtml: "<h1 class='form-title'>Sign-<b>Up</b></h1>"; + --count: '0'; + --cssx-disgustingly-set-innerhtml: + "<h1 class='form-title'>Sign-<b>Up</b></h1>"; --cssx-children: form#form; - --count: '0'; } .form-title { @@ -25,11 +26,15 @@ #form { display: block; - --cssx-on-submit: prevent-default() add-class(form, 'submitting') - request('/examples/') remove-class(form, 'submitting') - add-class(form, 'submitted'); + --cssx-on-submit: + prevent-default() + add-class(form, 'submitting') + request('/examples/') + remove-class(form, 'submitting') + add-class(form, 'submitted') + ; - --cssx-children: input#input-email input#input-password actions #message; + --cssx-children: input#input-email input#input-password #actions #message; } #form.submitted #message::after { display: block; diff --git a/examples/form/style.css b/examples/form/style.css index 63f758b..8229ef0 100644 --- a/examples/form/style.css +++ b/examples/form/style.css @@ -1,9 +1,7 @@ body { - --cssx-children: button#signup-btn signup-page; -} -body * { - box-sizing: border-box; + --cssx-children: button#signup-btn #signup-page; } +body * { box-sizing: border-box; } #signup-btn { display: inline-block; @@ -14,10 +12,13 @@ body * { padding: 0.5rem 1rem; cursor: pointer; - --cssx-on-click: add-class(signup-page, 'loading') - add-class(signup-btn, 'loading') delay(0.5s) + --cssx-on-click: + add-class(signup-page, 'loading') + add-class(signup-btn, 'loading') + delay(0.5s) load-cssx(signup-page-content, './signup.css') - remove-class(signup-page, 'loading') remove-class(signup-btn, 'loading'); + remove-class(signup-page, 'loading') + remove-class(signup-btn, 'loading'); } #signup-btn::after { content: 'Register now to start your free trial for $99'; @@ -31,7 +32,7 @@ body * { } #signup-page { - --cssx-children: signup-page-content; + --cssx-children: div#signup-page-content; } #signup-page.loading::after { content: 'Loading...'; diff --git a/examples/todo-list/style.css b/examples/todo-list/style.css index b3b9d07..d4cd391 100644 --- a/examples/todo-list/style.css +++ b/examples/todo-list/style.css @@ -87,8 +87,10 @@ body * { box-sizing: border-box; } width: 100%; align-items: center; + --cssx-on-mount: update(--task-item-id, attr(data-element)); + --cssx-on-click: update(--done, if(get-var(--done), "false", "true")); - --cssx-on-update: update(checkbox, --checked, if(get-var(--done), true, false)); + --cssx-on-update: update(":scope [data-element=checkbox]", --checked, if(get-var(--done), true, false)); --cssx-children: div#checkbox div#task-text button#delete-task; } @@ -97,7 +99,7 @@ body * { box-sizing: border-box; } flex: 2; } [data-instance=task-item] [data-element=task-text]::after { - content: "[" var(--done) "] " var(--text); + content: var(--text); padding-left: 0.8rem; } @@ -115,11 +117,10 @@ body * { box-sizing: border-box; } background-color: transparent; --cssx-on-update: - update(background-color, if(get-var(--checked), get-var(--color-accent), transparent)) - ; + update(background-color, if(get-var(--checked), get-var(--color-accent), transparent)); } [data-instance=task-item] [data-element=delete-task] { --cssx-text: 'Delete'; - --cssx-on-click: remove-element(task-item); + --cssx-on-click: remove-element(get-var(--task-item-id)); } diff --git a/src/index.ts b/src/index.ts index c1b997d..2392c9e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -64,15 +64,27 @@ export const getDeclarations = ( return extractDeclaration(value, actions) } +const getElement = ( + id: string, + $node: HTMLElement | Document = document, +): HTMLElement | null => { + // TODO: Please no ternary + const [$element, selector] = /^('|")?[a-z0-9_-]+\1$/gi.test(id) + ? [document, `[data-element=${id}]`] + : /^:scope/i.test(id) + ? [$node, id] + : [document, id] + return $element.querySelector<HTMLElement>(selector) +} + const getEvalActions = ( $element: HTMLElement, { event = null, pure = false }: { event?: any; pure?: boolean }, ): EvalActions => { const actions: EvalActions = { - addClass: async (id, cls) => - document.getElementById(id)?.classList.add(cls), + addClass: async (id, cls) => getElement(id, $element)?.classList.add(cls), removeClass: async (id, cls) => - document.getElementById(id)?.classList.remove(cls), + getElement(id, $element)?.classList.remove(cls), delay: delay => new Promise(res => setTimeout(res, delay)), jsEval: async js => !pure && (0, eval)(js), loadCssx: async (id, url) => @@ -84,7 +96,7 @@ const getEvalActions = ( rel: 'stylesheet', }) $link.onload = () => { - const $el = document.getElementById(id) + const $el = getElement(id, $element) if ($el) { manageElement($el) resolve(id) @@ -97,7 +109,7 @@ const getEvalActions = ( }), getVariable: async varName => getPropertyValue($element, varName), updateVariable: async (targetId, varName, value) => { - const $el = targetId ? document.getElementById(targetId) : $element + const $el = targetId ? getElement(targetId, $element) : $element const isCustomProp = varName.startsWith('--') if ($el) { const prevValue = getPropertyValue($el, varName) @@ -114,7 +126,7 @@ const getEvalActions = ( } }, setAttribute: async (id, name, value) => { - const $el = id ? document.getElementById(id) : $element + const $el = id ? getElement(id, $element) : $element if (name === 'value') { ;($el as any).value = value } else if (value) { @@ -124,7 +136,7 @@ const getEvalActions = ( } }, getAttribute: async (id, name) => { - const $el = id ? document.getElementById(id) : $element + const $el = id ? getElement(id, $element) : $element if (name === 'value') return ($el as any).value return $el?.getAttribute(name) ?? undefined }, @@ -139,12 +151,12 @@ const getEvalActions = ( // TODO: Handle response? }, addChildren: async (id, children) => { - const $el = document.getElementById(id) + const $el = getElement(id, $element) const declarations = await expressionsToDeclrs(children, actions) $el && createLayer(declarations, $el) }, removeElement: async id => { - const $el = id ? document.getElementById(id) : $element + const $el = id ? getElement(id, $element) : $element $el?.parentNode?.removeChild($el) }, } |
