diff --git a/src/__tests__/attributes.test.ts b/src/__tests__/attributes.test.ts index 3d66c0b..da93add 100644 --- a/src/__tests__/attributes.test.ts +++ b/src/__tests__/attributes.test.ts @@ -42,4 +42,12 @@ describe('attributes.ts', () => { expect(el.hasAttribute('mounted')).toBe(false); }); + + test("doesn't add `keep` as an attribute", () => { + const el = document.createElement('div'); + + addAttribute(el, 'keep', true); + + expect(el.hasAttribute('keep')).toBe(false); + }); }); diff --git a/src/__tests__/component.test.ts b/src/__tests__/component.test.ts index dfdd6ca..d78e6cf 100644 --- a/src/__tests__/component.test.ts +++ b/src/__tests__/component.test.ts @@ -1,7 +1,13 @@ import { mount } from '../mount'; import { tags } from '../tags'; import { type Component } from '../types'; -import { getByText, getByTestId, fireEvent } from '@testing-library/dom'; +import { + getByText, + getByTestId, + fireEvent, + getByRole, + queryByText, +} from '@testing-library/dom'; const { div, p, button } = tags; @@ -76,4 +82,34 @@ describe('components', () => { expect(el).toBeDefined(); }); + + test('keep', () => { + const KeepComponent: Component<{ count: number }> = { + state: { count: 0 }, + view({ state }) { + return div( + div( + [ + `Don't change me ${state.count}`, + button('Increment', { + onclick: () => state.count++, + }), + ], + { keep: true }, + ), + ); + }, + }; + + mount(document.body, KeepComponent); + + const btn = getByRole(document.body, 'button'); + + expect(btn).toBeDefined(); + + fireEvent.click(btn); + + expect(queryByText(document.body, /Don't change me 0/)).toBeTruthy(); + expect(queryByText(document.body, /Don't change me 1/)).toBeNull(); + }); }); diff --git a/src/attributes.ts b/src/attributes.ts index db716eb..c8ada1c 100644 --- a/src/attributes.ts +++ b/src/attributes.ts @@ -5,7 +5,7 @@ function addAttribute( key: string, value: TagAttrsValues, ) { - if (key === 'mounted') { + if (key === 'mounted' || key === 'keep') { return; } diff --git a/src/types.ts b/src/types.ts index 23f2b9d..ccdba0e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -14,18 +14,27 @@ export type TentNode = Node & Element & HTMLElement & { $tent: { - attributes: object; + attributes: Record & { + mounted?: ({ el }: { el: TentNode }) => void; + keep?: boolean; + }; }; dataset: A & DOMStringMap; children: TentNode[]; }; -export type Children = string | number | TentNode | (Node | string | Context)[]; +export type Children = + | string + | number + | TentNode + | Element + | (Node | string | Context)[]; export type Context = [string, Children, TagAttrs | undefined]; export type TagAttrsValues = string | boolean | number | Function; type TagAttrs = Record & { mounted?: ({ el }: { el: TentNode }) => void; + keep?: boolean; }; export type Tags = Record< string, diff --git a/src/walker.ts b/src/walker.ts index 07181ac..bed4b7b 100644 --- a/src/walker.ts +++ b/src/walker.ts @@ -46,6 +46,7 @@ function walker(oldNode: TentNode, newNode: TentNode) { } if (oc.length === 0 && nc.length === 0) return; + if (oldNode.$tent.attributes.keep) return; if (oc.length < nc.length) { for (let i = 0; i < nc.length; i++) {