Skip to content

Commit

Permalink
Bug fixes (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
tchak committed May 7, 2024
2 parents 06c5723 + 8092cc7 commit 78a5e8f
Show file tree
Hide file tree
Showing 7 changed files with 1,700 additions and 67 deletions.
5 changes: 5 additions & 0 deletions .changeset/wise-keys-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@coldwired/react": patch
---

fix some bugs
3 changes: 2 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"@types/react": "^18.2.45",
"@types/react-dom": "^18.2.18",
"html-entities": "^2.4.0",
"zod": "^3.23.4"
"zod": "^3.23.4",
"react-aria-components": "^1.2.0"
},
"peerDependencies": {
"react": "^18.0.0",
Expand Down
10 changes: 6 additions & 4 deletions packages/react/src/react-tree-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,8 @@ export function hydrate(
manifest: Manifest,
schema?: Partial<Schema>,
): ReactNode {
const schema_ = Object.assign({}, defaultSchema, schema);
const childNodes = getChildNodes(documentOrFragment);
const { children } = hydrateChildNodes(childNodes, schema_);
const { children } = hydrateChildNodes(childNodes, Object.assign({}, defaultSchema, schema));
return createReactTree(children, manifest);
}

Expand Down Expand Up @@ -103,8 +102,11 @@ type HydrateResult = {
function hydrateChildNodes(childNodes: NodeListOf<ChildNode>, schema: Schema): HydrateResult {
const result: HydrateResult = { children: [], props: {} };
childNodes.forEach((childNode) => {
if (isTextNode(childNode) && childNode.textContent) {
result.children.push(childNode.textContent);
if (isTextNode(childNode)) {
const text = childNode.textContent;
if (text?.trim()) {
result.children.push(text);
}
} else if (isElementNode(childNode)) {
const tagName = childNode.tagName.toLowerCase();
const { children, props } = hydrateChildNodes(childNode.childNodes, schema);
Expand Down
66 changes: 66 additions & 0 deletions packages/react/src/root-schema.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { describe, it, expect } from 'vitest';
import { useState } from 'react';

import { createRoot, defaultSchema, type Manifest } from '.';

const NAME_ATTRIBUTE = defaultSchema.nameAttribute;
const REACT_COMPONENT_TAG = 'react-component';
const DEFAULT_TAG_NAME = 'react-fragment';

const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount((count) => count + 1)}>Increment</button>
</div>
);
};
const manifest: Manifest = { Counter };

describe('@coldwired/react', () => {
describe('root with custom schema', () => {
it('render simple fragment', async () => {
document.body.innerHTML = `<${DEFAULT_TAG_NAME}><div class="title">Hello</div></${DEFAULT_TAG_NAME}><div id="root"></div>`;
const root = createRoot(document.getElementById('root')!, {
loader: (name) => Promise.resolve(manifest[name]),
schema: {
fragmentTagName: DEFAULT_TAG_NAME,
componentTagName: REACT_COMPONENT_TAG,
},
});
await root.mount();
await root.render(document.body).done;

expect(document.body.innerHTML).toEqual(
`<${DEFAULT_TAG_NAME}><div class="title">Hello</div></${DEFAULT_TAG_NAME}><div id="root"></div>`,
);

await root.render(document.body.firstElementChild!, `<div class="title">Hello World!</div>`)
.done;
expect(document.body.innerHTML).toEqual(
`<${DEFAULT_TAG_NAME}><div class="title">Hello World!</div></${DEFAULT_TAG_NAME}><div id="root"></div>`,
);
expect(root.getCache().size).toEqual(1);
root.destroy();
});

it('render fragment with component', async () => {
document.body.innerHTML = `<${DEFAULT_TAG_NAME}><${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="Counter"></${REACT_COMPONENT_TAG}></${DEFAULT_TAG_NAME}><div id="root"></div>`;
const root = createRoot(document.getElementById('root')!, {
loader: (name) => Promise.resolve(manifest[name]),
schema: {
fragmentTagName: DEFAULT_TAG_NAME,
componentTagName: REACT_COMPONENT_TAG,
},
});
await root.mount();
await root.render(document.body).done;

expect(document.body.innerHTML).toEqual(
`<${DEFAULT_TAG_NAME}><div><p>Count: 0</p><button>Increment</button></div></${DEFAULT_TAG_NAME}><div id="root"></div>`,
);
root.destroy();
});
});
});
29 changes: 28 additions & 1 deletion packages/react/src/root.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, it, expect } from 'vitest';
import { useState } from 'react';
import { ComboBox, ListBox, ListBoxItem, Popover, Label, Input } from 'react-aria-components';

import { createRoot, defaultSchema, type Manifest } from '.';

Expand All @@ -16,7 +17,7 @@ const Counter = () => {
</div>
);
};
const manifest: Manifest = { Counter };
const manifest: Manifest = { Counter, ComboBox, ListBox, ListBoxItem, Popover, Label, Input };

describe('@coldwired/react', () => {
describe('root', () => {
Expand Down Expand Up @@ -54,5 +55,31 @@ describe('@coldwired/react', () => {
);
root.destroy();
});

it('render fragment with react aria component', async () => {
document.body.innerHTML = `<${DEFAULT_TAG_NAME}>
<${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="ComboBox">
<${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="Label">Test</${REACT_COMPONENT_TAG}>
<${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="Input"></${REACT_COMPONENT_TAG}>
<${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="Popover">
<${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="ListBox">
<${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="ListBoxItem">One</${REACT_COMPONENT_TAG}>
<${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="ListBoxItem">Two </${REACT_COMPONENT_TAG}>
<${REACT_COMPONENT_TAG} ${NAME_ATTRIBUTE}="ListBoxItem">Three</${REACT_COMPONENT_TAG}>
</${REACT_COMPONENT_TAG}>
</${REACT_COMPONENT_TAG}>
</${REACT_COMPONENT_TAG}>
</${DEFAULT_TAG_NAME}><div id="root"></div>`;
const root = createRoot(document.getElementById('root')!, {
loader: (name) => Promise.resolve(manifest[name]),
});
await root.mount();
await root.render(document.body).done;

expect(document.body.innerHTML).toEqual(
`<${DEFAULT_TAG_NAME}><div class="react-aria-ComboBox" data-rac=""><label class="react-aria-Label" id="react-aria-:rc:" for="react-aria-:rb:">Test</label><input type="text" aria-autocomplete="list" autocomplete="off" id="react-aria-:rb:" aria-labelledby="react-aria-:rc:" role="combobox" aria-expanded="false" autocorrect="off" spellcheck="false" class="react-aria-Input" data-rac="" value="" title=""></div></${DEFAULT_TAG_NAME}><div id="root"></div>`,
);
root.destroy();
});
});
});
4 changes: 2 additions & 2 deletions packages/react/src/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ export function createRoot(container: Element, options: RootOptions): Root {
if (isElement(fragment) && fragment.tagName.toLowerCase() != schema.fragmentTagName) {
throw new Error('Cannot rerender with a non-fragment element');
}
await preload(fragment, (names) => manifestLoader(names, loader, manifest));
const tree = hydrate(fragment, manifest);
await preload(fragment, (names) => manifestLoader(names, loader, manifest), schema);
const tree = hydrate(fragment, manifest, schema);
if (reset) {
element.innerHTML = '';
}
Expand Down
Loading

0 comments on commit 78a5e8f

Please sign in to comment.