From 427b84490375a8c42fa419f6d5642a3cf0085a10 Mon Sep 17 00:00:00 2001 From: kasperskei Date: Mon, 6 Jan 2025 02:59:55 +0200 Subject: [PATCH] fix(jsx): props are set as properties --- packages/jsx/src/index.test.tsx | 54 +++++---------------------------- packages/jsx/src/index.ts | 38 +++++++---------------- 2 files changed, 19 insertions(+), 73 deletions(-) diff --git a/packages/jsx/src/index.test.tsx b/packages/jsx/src/index.test.tsx index 5c65dbf1d..a9f1ed224 100644 --- a/packages/jsx/src/index.test.tsx +++ b/packages/jsx/src/index.test.tsx @@ -38,27 +38,21 @@ it('static props & children', setup((ctx, h, hf, mount, parent) => { })) it('dynamic props', setup((ctx, h, hf, mount, parent) => { - const val = atom('val', 'val') const prp = atom('prp', 'prp') const atr = atom('atr', 'atr') - const element =
+ const element =
mount(parent, element) - assert.is(element.id, 'val') - // @ts-expect-error `dunno` can't be inferred - assert.is(element.prp, 'prp') - assert.is(element.getAttribute('atr'), 'atr') + assert.is(element.id, 'prp') + assert.is(element.getAttribute('class'), 'atr') - val(ctx, 'val1') prp(ctx, 'prp1') atr(ctx, 'atr1') - assert.is(element.id, 'val1') - // @ts-expect-error `dunno` can't be inferred - assert.is(element.prp, 'prp1') - assert.is(element.getAttribute('atr'), 'atr1') + assert.is(element.id, 'prp1') + assert.is(element.getAttribute('class'), 'atr1') })) it('children updates', setup((ctx, h, hf, mount, parent) => { @@ -390,12 +384,12 @@ it('same arguments in ref mount and unmount hooks', setup(async (ctx, h, hf, mou assert.is(unmountArgs[1], component) })) -it('css property and class attribute', setup(async (ctx, h, hf, mount, parent) => { +it('css property and className property', setup(async (ctx, h, hf, mount, parent) => { const cls = 'class' const css = 'color: red;' - const ref1 = (
) - const ref2 = (
) + const ref1 = (
) + const ref2 = (
) const component = (
@@ -445,38 +439,6 @@ it('css custom property', setup(async (ctx, h, hf, mount, parent) => { assert.is(component.style.getPropertyValue('--secondProperty'), '') })) -it('class and className attribute', setup(async (ctx, h, hf, mount, parent) => { - const classAtom = atom('' as string | undefined) - - const ref1 = (
) - const ref2 = (
) - - const component = ( -
- {ref1} - {ref2} -
- ) - - mount(parent, component) - await sleep() - - assert.ok(ref1.hasAttribute('class')) - assert.ok(ref2.hasAttribute('class')) - - classAtom(ctx, 'cls') - assert.is(ref1.className, 'cls') - assert.is(ref2.className, 'cls') - assert.ok(ref1.hasAttribute('class')) - assert.ok(ref2.hasAttribute('class')) - - classAtom(ctx, undefined) - assert.is(ref1.className, '') - assert.is(ref2.className, '') - assert.ok(!ref1.hasAttribute('class')) - assert.ok(!ref2.hasAttribute('class')) -})) - it('ref mount and unmount callbacks order', setup(async (ctx, h, hf, mount, parent) => { const order: number[] = [] diff --git a/packages/jsx/src/index.ts b/packages/jsx/src/index.ts index 97d42d1e5..45f39b88d 100644 --- a/packages/jsx/src/index.ts +++ b/packages/jsx/src/index.ts @@ -84,11 +84,13 @@ const walkLinkedList = (ctx: Ctx, el: JSX.Element, list: Atom { - const StylesheetId = 'reatom-jsx-styles' let styles: Rec = {} - let stylesheet: HTMLStyleElement | undefined + let stylesheet: HTMLStyleElement = DOM.document.createElement('style') + stylesheet.id = 'reatom-jsx-styles' let name = '' + DOM.document.head.appendChild(stylesheet) + let set = (element: JSX.Element, key: string, val: any) => { if (key.startsWith('on:')) { key = key.slice(3) @@ -100,17 +102,10 @@ export const reatomJsx = (ctx: Ctx, DOM: DomApis = globalThis.window) => { if (val == null) element.style.removeProperty(key) else element.style.setProperty(key, String(val)) } else if (key === 'css') { - stylesheet ??= DOM.document.getElementById(StylesheetId) as any - if (!stylesheet) { - stylesheet = DOM.document.createElement('style') - stylesheet.id = StylesheetId - DOM.document.head.appendChild(stylesheet) - } - let styleId = styles[val] if (!styleId) { styleId = styles[val] = `${name ? name + '.' : ''}${random(0, 1e6).toString()}` - stylesheet.innerText += '[data-reatom="' + styleId + '"]{' + val + '}\n' + stylesheet!.innerText += '[data-reatom="' + styleId + '"]{' + val + '}\n' } /** @see https://measurethat.net/Benchmarks/Show/11819 */ element.setAttribute('data-reatom', styleId) @@ -119,24 +114,13 @@ export const reatomJsx = (ctx: Ctx, DOM: DomApis = globalThis.window) => { if (val[key] == null) element.style.removeProperty(key) else element.style.setProperty(key, val[key]) } - } else if (key.startsWith('prop:')) { - // @ts-expect-error - element[key.slice(5)] = val - } else { - if (key.startsWith('attr:')) { - key = key.slice(5) - } - if (key === 'className') key = 'class' + } else if (key.startsWith('attr:')) { + key = key.slice(5) if (val == null || val === false) element.removeAttribute(key) - else { - val = val === true ? '' : String(val) - /** - * @see https://measurethat.net/Benchmarks/Show/54 - * @see https://measurethat.net/Benchmarks/Show/31249 - */ - if (key === 'class' && element instanceof HTMLElement) element.className = val - else element.setAttribute(key, val) - } + else element.setAttribute(key, val === true ? '' : String(val)) + } else { + // @ts-expect-error + element[key] = val } }