From 72b401bdd9e38a2203687f16311aecc13e639a38 Mon Sep 17 00:00:00 2001 From: kasperskei Date: Thu, 6 Jun 2024 15:28:17 +0300 Subject: [PATCH] feat(jsx): handle falsy like React --- packages/jsx/src/index.test.tsx | 82 +++++++++++++++++++++++++++++++++ packages/jsx/src/index.ts | 6 ++- packages/jsx/src/jsx.d.ts | 2 +- 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/packages/jsx/src/index.test.tsx b/packages/jsx/src/index.test.tsx index 3409b5e8e..d76d317ff 100644 --- a/packages/jsx/src/index.test.tsx +++ b/packages/jsx/src/index.test.tsx @@ -262,4 +262,86 @@ test('linked list', () => { // assert.not.ok(isConnected(ctx, jsxList)) }) +test('boolean as child', () => { + const { h, hf } = setup() + + const trueAtom = atom(true, 'true') + const trueValue = true + const falseAtom = atom(false, 'false') + const falseValue = false + + const element =
+ {trueAtom} + {trueValue} + {falseAtom} + {falseValue} +
+ + assert.is(element.childNodes.length, 2) + assert.is(element.textContent, '') +}) + +test('null as child', () => { + const { h, hf } = setup() + + const nullAtom = atom(null, 'null') + const nullValue = null + + const element =
+ {nullAtom} + {nullValue} +
+ + assert.is(element.childNodes.length, 1) + assert.is(element.textContent, '') +}) + +test('undefined as child', () => { + const { h, hf } = setup() + + const undefinedAtom = atom(undefined, 'undefined') + const undefinedValue = undefined + + const element =
+ {undefinedAtom} + {undefinedValue} +
+ + assert.is(element.childNodes.length, 1) + assert.is(element.textContent, '') +}) + +test('empty string as child', () => { + const { h, hf } = setup() + + const emptyStringAtom = atom('', 'emptyString') + const emptyStringValue = '' + + const element =
+ {emptyStringAtom} + {emptyStringValue} +
+ + assert.is(element.childNodes.length, 1) + assert.is(element.textContent, '') +}) + +test('update skipped atom', () => { + const { ctx, h, hf, mount, parent } = setup() + + const valueAtom = atom(undefined, 'value') + + const element =
{valueAtom}
+ + mount(parent, element) + + assert.is(parent.childNodes.length, 1) + assert.is(parent.textContent, '') + + valueAtom(ctx, 123) + + assert.is(parent.childNodes.length, 1) + assert.is(parent.textContent, '123') +}) + test.run() diff --git a/packages/jsx/src/index.ts b/packages/jsx/src/index.ts index 7f21a777b..36154e80a 100644 --- a/packages/jsx/src/index.ts +++ b/packages/jsx/src/index.ts @@ -32,6 +32,8 @@ type DomApis = Pick< | 'DocumentFragment' > +const isSkipped = (value: unknown): value is boolean | '' | null | undefined => typeof value === 'boolean' || value === '' || value == null + let unsubscribesMap = new WeakMap>() let unlink = (parent: any, un: Unsubscribe) => { // check the connection in the next tick @@ -241,7 +243,7 @@ export const reatomJsx = (ctx: Ctx, DOM: DomApis = globalThis.window) => { } } else { // TODO more tests - innerChild.textContent = String(v) + innerChild.textContent = isSkipped(v) ? '' : String(v) } } } catch (e) { @@ -251,7 +253,7 @@ export const reatomJsx = (ctx: Ctx, DOM: DomApis = globalThis.window) => { if (error) throw error unlink(element, un) element.appendChild(innerChild) - } else { + } else if (!isSkipped(child)) { element.appendChild( isObject(child) && 'nodeType' in child ? (child as JSX.Element) diff --git a/packages/jsx/src/jsx.d.ts b/packages/jsx/src/jsx.d.ts index 5cf8dcd28..fc484582a 100644 --- a/packages/jsx/src/jsx.d.ts +++ b/packages/jsx/src/jsx.d.ts @@ -1,4 +1,4 @@ -/* +/* Respectfully copied from https://github.com/ryansolid/dom-expressions/blob/ae71a417aa13b33517082628aff09513629df8b2/packages/dom-expressions/src/jsx.d.ts */