Skip to content

Commit

Permalink
fix(jsx): props are set as properties
Browse files Browse the repository at this point in the history
  • Loading branch information
kasperskei committed Jan 6, 2025
1 parent 0439318 commit 427b844
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 73 deletions.
54 changes: 8 additions & 46 deletions packages/jsx/src/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <div id={val} prop:prp={prp} attr:atr={atr} />
const element = <div id={prp} attr:class={atr} />

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) => {
Expand Down Expand Up @@ -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 = (<div css={css} class={cls}></div>)
const ref2 = (<div class={cls} css={css}></div>)
const ref1 = (<div css={css} className={cls}></div>)
const ref2 = (<div className={cls} css={css}></div>)

const component = (
<div>
Expand Down Expand Up @@ -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 = (<div class={classAtom}></div>)
const ref2 = (<div className={classAtom}></div>)

const component = (
<div>
{ref1}
{ref2}
</div>
)

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[] = []

Expand Down
38 changes: 11 additions & 27 deletions packages/jsx/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,13 @@ const walkLinkedList = (ctx: Ctx, el: JSX.Element, list: Atom<LinkedList<LLNode<
}

export const reatomJsx = (ctx: Ctx, DOM: DomApis = globalThis.window) => {
const StylesheetId = 'reatom-jsx-styles'
let styles: Rec<string> = {}
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)
Expand All @@ -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)
Expand All @@ -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
}
}

Expand Down

0 comments on commit 427b844

Please sign in to comment.