rask-ui 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/component.d.ts +17 -0
- package/dist/component.d.ts.map +1 -1
- package/dist/component.js +4 -2
- package/dist/createAsync.d.ts +23 -0
- package/dist/createAsync.d.ts.map +1 -1
- package/dist/createAsync.js +23 -0
- package/dist/createAsync.test.d.ts +2 -0
- package/dist/createAsync.test.d.ts.map +1 -0
- package/dist/createAsync.test.js +110 -0
- package/dist/createContext.d.ts +26 -2
- package/dist/createContext.d.ts.map +1 -1
- package/dist/createContext.js +31 -5
- package/dist/createContext.test.d.ts +2 -0
- package/dist/createContext.test.d.ts.map +1 -0
- package/dist/createContext.test.js +136 -0
- package/dist/createMutation.d.ts +23 -0
- package/dist/createMutation.d.ts.map +1 -1
- package/dist/createMutation.js +23 -0
- package/dist/createMutation.test.d.ts +2 -0
- package/dist/createMutation.test.d.ts.map +1 -0
- package/dist/createMutation.test.js +168 -0
- package/dist/createQuery.d.ts +23 -0
- package/dist/createQuery.d.ts.map +1 -1
- package/dist/createQuery.js +23 -0
- package/dist/createQuery.test.d.ts +2 -0
- package/dist/createQuery.test.d.ts.map +1 -0
- package/dist/createQuery.test.js +156 -0
- package/dist/createRef.test.d.ts +2 -0
- package/dist/createRef.test.d.ts.map +1 -0
- package/dist/createRef.test.js +80 -0
- package/dist/createState.d.ts +24 -0
- package/dist/createState.d.ts.map +1 -1
- package/dist/createState.js +24 -0
- package/dist/createState.test.d.ts +2 -0
- package/dist/createState.test.d.ts.map +1 -0
- package/dist/createState.test.js +111 -0
- package/dist/createView.d.ts +54 -0
- package/dist/createView.d.ts.map +1 -0
- package/dist/createView.js +68 -0
- package/dist/createView.test.d.ts +2 -0
- package/dist/createView.test.d.ts.map +1 -0
- package/dist/createView.test.js +203 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +15 -2
- package/dist/error.test.d.ts +2 -0
- package/dist/error.test.d.ts.map +1 -0
- package/dist/error.test.js +144 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/integration.test.d.ts +2 -0
- package/dist/integration.test.d.ts.map +1 -0
- package/dist/integration.test.js +155 -0
- package/dist/jsx-dev-runtime.d.ts +3 -3
- package/dist/jsx-dev-runtime.d.ts.map +1 -1
- package/dist/jsx-dev-runtime.js +2 -2
- package/dist/jsx-runtime.d.ts +1 -4
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx-runtime.js +3 -14
- package/dist/observation.d.ts +1 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +5 -0
- package/dist/observation.test.d.ts +2 -0
- package/dist/observation.test.d.ts.map +1 -0
- package/dist/observation.test.js +150 -0
- package/dist/render-test.d.ts +2 -0
- package/dist/render-test.d.ts.map +1 -0
- package/dist/render-test.js +21 -0
- package/dist/render.d.ts +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +13 -1
- package/dist/test-setup.d.ts +16 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +39 -0
- package/dist/tests/class.test.d.ts +2 -0
- package/dist/tests/class.test.d.ts.map +1 -0
- package/dist/tests/class.test.js +143 -0
- package/dist/tests/complex-rendering.test.d.ts +2 -0
- package/dist/tests/complex-rendering.test.d.ts.map +1 -0
- package/dist/tests/complex-rendering.test.js +400 -0
- package/dist/tests/component.cleanup.test.d.ts +2 -0
- package/dist/tests/component.cleanup.test.d.ts.map +1 -0
- package/dist/tests/component.cleanup.test.js +325 -0
- package/dist/tests/component.counter.test.d.ts +2 -0
- package/dist/tests/component.counter.test.d.ts.map +1 -0
- package/dist/tests/component.counter.test.js +124 -0
- package/dist/tests/component.interaction.test.d.ts +2 -0
- package/dist/tests/component.interaction.test.d.ts.map +1 -0
- package/dist/tests/component.interaction.test.js +73 -0
- package/dist/tests/component.props.test.d.ts +2 -0
- package/dist/tests/component.props.test.d.ts.map +1 -0
- package/dist/tests/component.props.test.js +88 -0
- package/dist/tests/component.return-types.test.d.ts +2 -0
- package/dist/tests/component.return-types.test.d.ts.map +1 -0
- package/dist/tests/component.return-types.test.js +357 -0
- package/dist/tests/component.state.test.d.ts +2 -0
- package/dist/tests/component.state.test.d.ts.map +1 -0
- package/dist/tests/component.state.test.js +129 -0
- package/dist/tests/component.test.d.ts +2 -0
- package/dist/tests/component.test.d.ts.map +1 -0
- package/dist/tests/component.test.js +63 -0
- package/dist/tests/createAsync.test.d.ts +2 -0
- package/dist/tests/createAsync.test.d.ts.map +1 -0
- package/dist/tests/createAsync.test.js +110 -0
- package/dist/tests/createContext.test.d.ts +2 -0
- package/dist/tests/createContext.test.d.ts.map +1 -0
- package/dist/tests/createContext.test.js +141 -0
- package/dist/tests/createMutation.test.d.ts +2 -0
- package/dist/tests/createMutation.test.d.ts.map +1 -0
- package/dist/tests/createMutation.test.js +168 -0
- package/dist/tests/createQuery.test.d.ts +2 -0
- package/dist/tests/createQuery.test.d.ts.map +1 -0
- package/dist/tests/createQuery.test.js +156 -0
- package/dist/tests/createRef.test.d.ts +2 -0
- package/dist/tests/createRef.test.d.ts.map +1 -0
- package/dist/tests/createRef.test.js +84 -0
- package/dist/tests/createState.test.d.ts +2 -0
- package/dist/tests/createState.test.d.ts.map +1 -0
- package/dist/tests/createState.test.js +111 -0
- package/dist/tests/createView.test.d.ts +2 -0
- package/dist/tests/createView.test.d.ts.map +1 -0
- package/dist/tests/createView.test.js +203 -0
- package/dist/tests/edge-cases.test.d.ts +2 -0
- package/dist/tests/edge-cases.test.d.ts.map +1 -0
- package/dist/tests/edge-cases.test.js +637 -0
- package/dist/tests/error-no-boundary.test.d.ts +2 -0
- package/dist/tests/error-no-boundary.test.d.ts.map +1 -0
- package/dist/tests/error-no-boundary.test.js +174 -0
- package/dist/tests/error.test.d.ts +2 -0
- package/dist/tests/error.test.d.ts.map +1 -0
- package/dist/tests/error.test.js +199 -0
- package/dist/tests/fragment.test.d.ts +2 -0
- package/dist/tests/fragment.test.d.ts.map +1 -0
- package/dist/tests/fragment.test.js +618 -0
- package/dist/tests/integration.test.d.ts +2 -0
- package/dist/tests/integration.test.d.ts.map +1 -0
- package/dist/tests/integration.test.js +192 -0
- package/dist/tests/keys.test.d.ts +2 -0
- package/dist/tests/keys.test.d.ts.map +1 -0
- package/dist/tests/keys.test.js +293 -0
- package/dist/tests/mount.test.d.ts +2 -0
- package/dist/tests/mount.test.d.ts.map +1 -0
- package/dist/tests/mount.test.js +91 -0
- package/dist/tests/observation.test.d.ts +2 -0
- package/dist/tests/observation.test.d.ts.map +1 -0
- package/dist/tests/observation.test.js +150 -0
- package/dist/tests/patch.test.d.ts +2 -0
- package/dist/tests/patch.test.d.ts.map +1 -0
- package/dist/tests/patch.test.js +498 -0
- package/dist/tests/patchChildren.test.d.ts +2 -0
- package/dist/tests/patchChildren.test.d.ts.map +1 -0
- package/dist/tests/patchChildren.test.js +387 -0
- package/dist/tests/primitives.test.d.ts +2 -0
- package/dist/tests/primitives.test.d.ts.map +1 -0
- package/dist/tests/primitives.test.js +132 -0
- package/dist/vdom/AbstractVNode.d.ts +22 -0
- package/dist/vdom/AbstractVNode.d.ts.map +1 -0
- package/dist/vdom/AbstractVNode.js +106 -0
- package/dist/vdom/ComponentVNode.d.ts +48 -0
- package/dist/vdom/ComponentVNode.d.ts.map +1 -0
- package/dist/vdom/ComponentVNode.js +209 -0
- package/dist/vdom/ElementVNode.d.ts +24 -0
- package/dist/vdom/ElementVNode.d.ts.map +1 -0
- package/dist/vdom/ElementVNode.js +126 -0
- package/dist/vdom/FragmentVNode.d.ts +13 -0
- package/dist/vdom/FragmentVNode.d.ts.map +1 -0
- package/dist/vdom/FragmentVNode.js +34 -0
- package/dist/vdom/RootVNode.d.ts +22 -0
- package/dist/vdom/RootVNode.d.ts.map +1 -0
- package/dist/vdom/RootVNode.js +55 -0
- package/dist/vdom/TextVNode.d.ts +11 -0
- package/dist/vdom/TextVNode.d.ts.map +1 -0
- package/dist/vdom/TextVNode.js +32 -0
- package/dist/vdom/class.test.d.ts +2 -0
- package/dist/vdom/class.test.d.ts.map +1 -0
- package/dist/vdom/class.test.js +143 -0
- package/dist/vdom/complex-rendering.test.d.ts +2 -0
- package/dist/vdom/complex-rendering.test.d.ts.map +1 -0
- package/dist/vdom/complex-rendering.test.js +400 -0
- package/dist/vdom/component.cleanup.test.d.ts +2 -0
- package/dist/vdom/component.cleanup.test.d.ts.map +1 -0
- package/dist/vdom/component.cleanup.test.js +323 -0
- package/dist/vdom/component.counter.test.d.ts +2 -0
- package/dist/vdom/component.counter.test.d.ts.map +1 -0
- package/dist/vdom/component.counter.test.js +124 -0
- package/dist/vdom/component.interaction.test.d.ts +2 -0
- package/dist/vdom/component.interaction.test.d.ts.map +1 -0
- package/dist/vdom/component.interaction.test.js +73 -0
- package/dist/vdom/component.props.test.d.ts +2 -0
- package/dist/vdom/component.props.test.d.ts.map +1 -0
- package/dist/vdom/component.props.test.js +88 -0
- package/dist/vdom/component.return-types.test.d.ts +2 -0
- package/dist/vdom/component.return-types.test.d.ts.map +1 -0
- package/dist/vdom/component.return-types.test.js +357 -0
- package/dist/vdom/component.state.test.d.ts +2 -0
- package/dist/vdom/component.state.test.d.ts.map +1 -0
- package/dist/vdom/component.state.test.js +129 -0
- package/dist/vdom/component.test.d.ts +2 -0
- package/dist/vdom/component.test.d.ts.map +1 -0
- package/dist/vdom/component.test.js +63 -0
- package/dist/vdom/dom-utils.d.ts +9 -0
- package/dist/vdom/dom-utils.d.ts.map +1 -0
- package/dist/vdom/dom-utils.js +74 -0
- package/dist/vdom/edge-cases.test.d.ts +2 -0
- package/dist/vdom/edge-cases.test.d.ts.map +1 -0
- package/dist/vdom/edge-cases.test.js +637 -0
- package/dist/vdom/fragment.test.d.ts +2 -0
- package/dist/vdom/fragment.test.d.ts.map +1 -0
- package/dist/vdom/fragment.test.js +618 -0
- package/dist/vdom/index.d.ts +10 -0
- package/dist/vdom/index.d.ts.map +1 -0
- package/dist/vdom/index.js +26 -0
- package/dist/vdom/keys.test.d.ts +2 -0
- package/dist/vdom/keys.test.d.ts.map +1 -0
- package/dist/vdom/keys.test.js +293 -0
- package/dist/vdom/mount.test.d.ts +2 -0
- package/dist/vdom/mount.test.d.ts.map +1 -0
- package/dist/vdom/mount.test.js +91 -0
- package/dist/vdom/patch.test.d.ts +2 -0
- package/dist/vdom/patch.test.d.ts.map +1 -0
- package/dist/vdom/patch.test.js +498 -0
- package/dist/vdom/patchChildren.test.d.ts +2 -0
- package/dist/vdom/patchChildren.test.d.ts.map +1 -0
- package/dist/vdom/patchChildren.test.js +392 -0
- package/dist/vdom/primitives.test.d.ts +2 -0
- package/dist/vdom/primitives.test.d.ts.map +1 -0
- package/dist/vdom/primitives.test.js +132 -0
- package/dist/vdom/types.d.ts +8 -0
- package/dist/vdom/types.d.ts.map +1 -0
- package/dist/vdom/types.js +1 -0
- package/dist/vdom/utils.d.ts +6 -0
- package/dist/vdom/utils.d.ts.map +1 -0
- package/dist/vdom/utils.js +63 -0
- package/package.json +1 -4
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "./jsx-runtime";
|
|
2
|
+
import { describe, it, expect, vi } from "vitest";
|
|
3
|
+
import { onCleanup, onMount } from "./vdom/ComponentVNode";
|
|
4
|
+
import { render } from "./vdom";
|
|
5
|
+
import { createState } from "./createState";
|
|
6
|
+
import { createRef } from "./createRef";
|
|
7
|
+
import { createContext } from "./createContext";
|
|
8
|
+
import { ErrorBoundary } from "./error";
|
|
9
|
+
describe("Integration Tests", () => {
|
|
10
|
+
it("should render a simple component", () => {
|
|
11
|
+
function App() {
|
|
12
|
+
return () => _jsx("div", { children: "Hello World" });
|
|
13
|
+
}
|
|
14
|
+
const container = document.createElement("div");
|
|
15
|
+
document.body.appendChild(container);
|
|
16
|
+
render(_jsx(App, {}), container);
|
|
17
|
+
// After patch, container is replaced, so check body instead
|
|
18
|
+
expect(document.body.textContent).toContain("Hello World");
|
|
19
|
+
});
|
|
20
|
+
it("should handle reactive state updates", async () => {
|
|
21
|
+
function Counter() {
|
|
22
|
+
const state = createState({ count: 0 });
|
|
23
|
+
return () => (_jsxs("div", { children: [_jsxs("span", { children: ["Count: ", state.count] }), _jsx("button", { onClick: () => state.count++, children: "Increment" })] }));
|
|
24
|
+
}
|
|
25
|
+
const container = document.createElement("div");
|
|
26
|
+
document.body.appendChild(container);
|
|
27
|
+
render(_jsx(Counter, {}), container);
|
|
28
|
+
expect(document.body.textContent).toContain("Count: 0");
|
|
29
|
+
// Simulate click
|
|
30
|
+
const button = document.querySelector("button");
|
|
31
|
+
button?.click();
|
|
32
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
33
|
+
expect(document.body.textContent).toContain("Count: 1");
|
|
34
|
+
});
|
|
35
|
+
it("should work with refs", async () => {
|
|
36
|
+
function App() {
|
|
37
|
+
const ref = createRef();
|
|
38
|
+
onMount(() => {
|
|
39
|
+
expect(ref.current).not.toBeNull();
|
|
40
|
+
expect(ref.current?.tagName).toBe("DIV");
|
|
41
|
+
});
|
|
42
|
+
return () => _jsx("div", { ref: ref, children: "Test" });
|
|
43
|
+
}
|
|
44
|
+
const container = document.createElement("div");
|
|
45
|
+
document.body.appendChild(container);
|
|
46
|
+
render(_jsx(App, {}), container);
|
|
47
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
48
|
+
});
|
|
49
|
+
it("should handle context", () => {
|
|
50
|
+
const ThemeContext = createContext();
|
|
51
|
+
function Child() {
|
|
52
|
+
const theme = ThemeContext.get();
|
|
53
|
+
return () => _jsx("div", { class: "child", children: theme.theme });
|
|
54
|
+
}
|
|
55
|
+
function Parent() {
|
|
56
|
+
ThemeContext.inject({ theme: "dark" });
|
|
57
|
+
return () => _jsx(Child, {});
|
|
58
|
+
}
|
|
59
|
+
const container = document.createElement("div");
|
|
60
|
+
document.body.appendChild(container);
|
|
61
|
+
render(_jsx(Parent, {}), container);
|
|
62
|
+
expect(document.body.textContent).toContain("dark");
|
|
63
|
+
});
|
|
64
|
+
it("should handle error boundaries", async () => {
|
|
65
|
+
function ThrowingChild() {
|
|
66
|
+
return () => {
|
|
67
|
+
throw new Error("Test error");
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function App() {
|
|
71
|
+
return () => (_jsx(ErrorBoundary, { error: (error) => _jsxs("div", { class: "error", children: ["Error: ", String(error)] }), children: _jsx(ThrowingChild, {}) }));
|
|
72
|
+
}
|
|
73
|
+
const container = document.createElement("div");
|
|
74
|
+
document.body.appendChild(container);
|
|
75
|
+
render(_jsx(App, {}), container);
|
|
76
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
77
|
+
const errorDiv = document.querySelector(".error");
|
|
78
|
+
expect(errorDiv).not.toBeNull();
|
|
79
|
+
expect(errorDiv?.textContent).toContain("Test error");
|
|
80
|
+
});
|
|
81
|
+
it("should call onMount and onCleanup", async () => {
|
|
82
|
+
const mountFn = vi.fn();
|
|
83
|
+
const cleanupFn = vi.fn();
|
|
84
|
+
let stateFn;
|
|
85
|
+
function Component() {
|
|
86
|
+
onMount(mountFn);
|
|
87
|
+
onCleanup(cleanupFn);
|
|
88
|
+
return () => _jsx("div", { children: "Test" });
|
|
89
|
+
}
|
|
90
|
+
function App() {
|
|
91
|
+
const state = createState({ show: true });
|
|
92
|
+
stateFn = state;
|
|
93
|
+
return () => (state.show ? _jsx(Component, {}) : _jsx("div", { children: "Empty" }));
|
|
94
|
+
}
|
|
95
|
+
const container = document.createElement("div");
|
|
96
|
+
document.body.appendChild(container);
|
|
97
|
+
render(_jsx(App, {}), container);
|
|
98
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
99
|
+
expect(mountFn).toHaveBeenCalledTimes(1);
|
|
100
|
+
expect(cleanupFn).not.toHaveBeenCalled();
|
|
101
|
+
// Unmount by toggling state to render something else
|
|
102
|
+
stateFn.show = false;
|
|
103
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
104
|
+
expect(cleanupFn).toHaveBeenCalledTimes(1);
|
|
105
|
+
});
|
|
106
|
+
it("should handle nested components", () => {
|
|
107
|
+
function GrandChild() {
|
|
108
|
+
return () => _jsx("span", { children: "GrandChild" });
|
|
109
|
+
}
|
|
110
|
+
function Child() {
|
|
111
|
+
return () => (_jsxs("div", { children: ["Child ", _jsx(GrandChild, {})] }));
|
|
112
|
+
}
|
|
113
|
+
function Parent() {
|
|
114
|
+
return () => (_jsxs("div", { children: ["Parent ", _jsx(Child, {})] }));
|
|
115
|
+
}
|
|
116
|
+
const container = document.createElement("div");
|
|
117
|
+
document.body.appendChild(container);
|
|
118
|
+
render(_jsx(Parent, {}), container);
|
|
119
|
+
expect(document.body.textContent).toContain("Parent");
|
|
120
|
+
expect(document.body.textContent).toContain("Child");
|
|
121
|
+
expect(document.body.textContent).toContain("GrandChild");
|
|
122
|
+
});
|
|
123
|
+
it("should handle conditional rendering", async () => {
|
|
124
|
+
function App() {
|
|
125
|
+
const state = createState({ show: true });
|
|
126
|
+
return () => (_jsxs("div", { children: [_jsx("button", { onClick: () => (state.show = !state.show), children: "Toggle" }), state.show ? _jsx("div", { class: "content", children: "Content" }) : null] }));
|
|
127
|
+
}
|
|
128
|
+
const container = document.createElement("div");
|
|
129
|
+
document.body.appendChild(container);
|
|
130
|
+
render(_jsx(App, {}), container);
|
|
131
|
+
// Wait for initial render
|
|
132
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
133
|
+
expect(document.querySelector(".content")).not.toBeNull();
|
|
134
|
+
const button = document.querySelector("button");
|
|
135
|
+
button?.click();
|
|
136
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
137
|
+
expect(document.querySelector(".content")).toBeNull();
|
|
138
|
+
});
|
|
139
|
+
it("should handle list rendering", async () => {
|
|
140
|
+
function TodoList() {
|
|
141
|
+
const state = createState({ items: ["Item 1", "Item 2"] });
|
|
142
|
+
return () => (_jsxs("div", { children: [_jsx("button", { onClick: () => {
|
|
143
|
+
state.items.push(`Item ${state.items.length + 1}`);
|
|
144
|
+
}, children: "Add" }), _jsx("ul", { children: state.items.map((item) => (_jsx("li", { children: item }))) })] }));
|
|
145
|
+
}
|
|
146
|
+
const container = document.createElement("div");
|
|
147
|
+
document.body.appendChild(container);
|
|
148
|
+
render(_jsx(TodoList, {}), container);
|
|
149
|
+
expect(document.querySelectorAll("li").length).toBe(2);
|
|
150
|
+
const button = document.querySelector("button");
|
|
151
|
+
button?.click();
|
|
152
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
153
|
+
expect(document.querySelectorAll("li").length).toBe(3);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { jsx, jsxs, Fragment
|
|
2
|
-
export type { JSX } from
|
|
3
|
-
export { jsx as jsxDEV } from
|
|
1
|
+
export { jsx, jsxs, Fragment } from "./jsx-runtime";
|
|
2
|
+
export type { JSX } from "./jsx-runtime";
|
|
3
|
+
export { jsx as jsxDEV } from "./vdom";
|
|
4
4
|
//# sourceMappingURL=jsx-dev-runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-dev-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-dev-runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"jsx-dev-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-dev-runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAIzC,OAAO,EAAE,GAAG,IAAI,MAAM,EAAE,MAAM,QAAQ,CAAC"}
|
package/dist/jsx-dev-runtime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// JSX dev runtime - adds jsxDEV for development mode
|
|
2
|
-
export { jsx, jsxs, Fragment
|
|
2
|
+
export { jsx, jsxs, Fragment } from "./jsx-runtime";
|
|
3
3
|
// In development mode, TypeScript uses jsxDEV instead of jsx
|
|
4
4
|
// We just alias it to jsx since we don't need the extra dev-mode params
|
|
5
|
-
export { jsx as jsxDEV } from
|
|
5
|
+
export { jsx as jsxDEV } from "./vdom";
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JSXInternal } from "./jsx";
|
|
2
|
-
export
|
|
2
|
+
export { Fragment } from "./vdom/FragmentVNode";
|
|
3
3
|
export declare function jsx(type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record<string, any>, key?: string): any;
|
|
4
4
|
export declare function jsx<P>(type: (props: P) => any, props: P & {
|
|
5
5
|
children?: any;
|
|
@@ -8,8 +8,5 @@ export declare function jsxs(type: string, props: JSXInternal.HTMLAttributes & J
|
|
|
8
8
|
export declare function jsxs<P>(type: (props: P) => any, props: P & {
|
|
9
9
|
children?: any[];
|
|
10
10
|
}, key?: string): any;
|
|
11
|
-
export declare function Fragment(props?: {
|
|
12
|
-
children?: any;
|
|
13
|
-
}): any;
|
|
14
11
|
export type { JSXInternal as JSX } from "./jsx";
|
|
15
12
|
//# sourceMappingURL=jsx-runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAGzC,
|
|
1
|
+
{"version":3,"file":"jsx-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAGzC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,wBAAgB,GAAG,CACjB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,CAAC,cAAc,GAC/B,WAAW,CAAC,aAAa,GACzB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACrB,GAAG,CAAC,EAAE,MAAM,GACX,GAAG,CAAC;AACP,wBAAgB,GAAG,CAAC,CAAC,EACnB,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,GAAG,EACvB,KAAK,EAAE,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,GAAG,CAAA;CAAE,EAC7B,GAAG,CAAC,EAAE,MAAM,GACX,GAAG,CAAC;AAKP,wBAAgB,IAAI,CAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,CAAC,cAAc,GAC/B,WAAW,CAAC,aAAa,GACzB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACrB,GAAG,CAAC,EAAE,MAAM,GACX,GAAG,CAAC;AACP,wBAAgB,IAAI,CAAC,CAAC,EACpB,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,GAAG,EACvB,KAAK,EAAE,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,CAAA;CAAE,EAC/B,GAAG,CAAC,EAAE,MAAM,GACX,GAAG,CAAC;AAMP,YAAY,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,OAAO,CAAC"}
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
|
-
import { jsx as internalJsx } from "./
|
|
2
|
-
export
|
|
1
|
+
import { jsx as internalJsx } from "./vdom";
|
|
2
|
+
export { Fragment } from "./vdom/FragmentVNode";
|
|
3
3
|
export function jsx(type, props, key) {
|
|
4
|
-
|
|
5
|
-
const finalProps = key !== undefined ? { ...restProps, key } : restProps;
|
|
6
|
-
const finalChildren = Array.isArray(children)
|
|
7
|
-
? children
|
|
8
|
-
: children === undefined
|
|
9
|
-
? []
|
|
10
|
-
: [children];
|
|
11
|
-
return internalJsx(type, finalProps, finalChildren);
|
|
4
|
+
return internalJsx(type, props, key);
|
|
12
5
|
}
|
|
13
6
|
export function jsxs(type, props, key) {
|
|
14
7
|
return jsx(type, props, key);
|
|
15
8
|
}
|
|
16
|
-
export function Fragment(props) {
|
|
17
|
-
return props?.children;
|
|
18
|
-
}
|
|
19
|
-
Fragment.$$typeof = FragmentSymbol;
|
package/dist/observation.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,aAEjC;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,WAAW,CAAyB;IAC5C,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI;IAOxB,MAAM;CAGP;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,QAAQ,CAAS;gBACb,QAAQ,EAAE,MAAM,IAAI;
|
|
1
|
+
{"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,aAEjC;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,WAAW,CAAyB;IAC5C,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI;IAOxB,MAAM;CAGP;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,QAAQ,CAAS;gBACb,QAAQ,EAAE,MAAM,IAAI;IAmBhC,eAAe,CAAC,MAAM,EAAE,MAAM;IAG9B,OAAO;IAOP,OAAO;CAIR"}
|
package/dist/observation.js
CHANGED
|
@@ -15,6 +15,7 @@ export class Signal {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
export class Observer {
|
|
18
|
+
_isDisposed = false;
|
|
18
19
|
signalDisposers = new Set();
|
|
19
20
|
clearSignals() {
|
|
20
21
|
this.signalDisposers.forEach((dispose) => dispose());
|
|
@@ -29,6 +30,9 @@ export class Observer {
|
|
|
29
30
|
}
|
|
30
31
|
queueMicrotask(() => {
|
|
31
32
|
this.isQueued = false;
|
|
33
|
+
if (this._isDisposed) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
32
36
|
onNotify();
|
|
33
37
|
});
|
|
34
38
|
this.isQueued = true;
|
|
@@ -46,5 +50,6 @@ export class Observer {
|
|
|
46
50
|
}
|
|
47
51
|
dispose() {
|
|
48
52
|
this.clearSignals();
|
|
53
|
+
this._isDisposed = true;
|
|
49
54
|
}
|
|
50
55
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observation.test.d.ts","sourceRoot":"","sources":["../src/observation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { Signal, Observer, getCurrentObserver } from './observation';
|
|
3
|
+
describe('Signal', () => {
|
|
4
|
+
it('should allow subscribing to notifications', () => {
|
|
5
|
+
const signal = new Signal();
|
|
6
|
+
const callback = vi.fn();
|
|
7
|
+
signal.subscribe(callback);
|
|
8
|
+
signal.notify();
|
|
9
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
10
|
+
});
|
|
11
|
+
it('should return a disposer function', () => {
|
|
12
|
+
const signal = new Signal();
|
|
13
|
+
const callback = vi.fn();
|
|
14
|
+
const dispose = signal.subscribe(callback);
|
|
15
|
+
dispose();
|
|
16
|
+
signal.notify();
|
|
17
|
+
expect(callback).not.toHaveBeenCalled();
|
|
18
|
+
});
|
|
19
|
+
it('should handle multiple subscribers', () => {
|
|
20
|
+
const signal = new Signal();
|
|
21
|
+
const callback1 = vi.fn();
|
|
22
|
+
const callback2 = vi.fn();
|
|
23
|
+
signal.subscribe(callback1);
|
|
24
|
+
signal.subscribe(callback2);
|
|
25
|
+
signal.notify();
|
|
26
|
+
expect(callback1).toHaveBeenCalledTimes(1);
|
|
27
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
28
|
+
});
|
|
29
|
+
it('should allow unsubscribing individual callbacks', () => {
|
|
30
|
+
const signal = new Signal();
|
|
31
|
+
const callback1 = vi.fn();
|
|
32
|
+
const callback2 = vi.fn();
|
|
33
|
+
const dispose1 = signal.subscribe(callback1);
|
|
34
|
+
signal.subscribe(callback2);
|
|
35
|
+
dispose1();
|
|
36
|
+
signal.notify();
|
|
37
|
+
expect(callback1).not.toHaveBeenCalled();
|
|
38
|
+
expect(callback2).toHaveBeenCalledTimes(1);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('Observer', () => {
|
|
42
|
+
it('should queue notifications in microtasks', async () => {
|
|
43
|
+
let callCount = 0;
|
|
44
|
+
const observer = new Observer(() => {
|
|
45
|
+
callCount++;
|
|
46
|
+
});
|
|
47
|
+
const signal = new Signal();
|
|
48
|
+
const dispose = observer.observe();
|
|
49
|
+
observer.subscribeSignal(signal);
|
|
50
|
+
dispose();
|
|
51
|
+
// Trigger multiple notifications
|
|
52
|
+
signal.notify();
|
|
53
|
+
signal.notify();
|
|
54
|
+
signal.notify();
|
|
55
|
+
// Should not be called synchronously
|
|
56
|
+
expect(callCount).toBe(0);
|
|
57
|
+
// Wait for microtask
|
|
58
|
+
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
59
|
+
// Should be called only once due to queuing
|
|
60
|
+
expect(callCount).toBe(1);
|
|
61
|
+
});
|
|
62
|
+
it('should track signals during observation', () => {
|
|
63
|
+
const callback = vi.fn();
|
|
64
|
+
const observer = new Observer(callback);
|
|
65
|
+
const signal = new Signal();
|
|
66
|
+
const dispose = observer.observe();
|
|
67
|
+
observer.subscribeSignal(signal);
|
|
68
|
+
dispose();
|
|
69
|
+
signal.notify();
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
queueMicrotask(() => {
|
|
72
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
73
|
+
resolve(undefined);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
it('should clear signals when observing again', async () => {
|
|
78
|
+
let callCount = 0;
|
|
79
|
+
const observer = new Observer(() => {
|
|
80
|
+
callCount++;
|
|
81
|
+
});
|
|
82
|
+
const signal1 = new Signal();
|
|
83
|
+
const signal2 = new Signal();
|
|
84
|
+
// First observation
|
|
85
|
+
let dispose = observer.observe();
|
|
86
|
+
observer.subscribeSignal(signal1);
|
|
87
|
+
dispose();
|
|
88
|
+
// Second observation - should clear previous signals
|
|
89
|
+
dispose = observer.observe();
|
|
90
|
+
observer.subscribeSignal(signal2);
|
|
91
|
+
dispose();
|
|
92
|
+
// Notify first signal - should not trigger observer
|
|
93
|
+
signal1.notify();
|
|
94
|
+
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
95
|
+
expect(callCount).toBe(0);
|
|
96
|
+
// Notify second signal - should trigger observer
|
|
97
|
+
signal2.notify();
|
|
98
|
+
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
99
|
+
expect(callCount).toBe(1);
|
|
100
|
+
});
|
|
101
|
+
it('should dispose of all signal subscriptions', async () => {
|
|
102
|
+
const callback = vi.fn();
|
|
103
|
+
const observer = new Observer(callback);
|
|
104
|
+
const signal = new Signal();
|
|
105
|
+
const dispose = observer.observe();
|
|
106
|
+
observer.subscribeSignal(signal);
|
|
107
|
+
dispose();
|
|
108
|
+
observer.dispose();
|
|
109
|
+
signal.notify();
|
|
110
|
+
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
111
|
+
expect(callback).not.toHaveBeenCalled();
|
|
112
|
+
});
|
|
113
|
+
it('should set current observer during observation', () => {
|
|
114
|
+
const observer = new Observer(() => { });
|
|
115
|
+
expect(getCurrentObserver()).toBeUndefined();
|
|
116
|
+
const dispose = observer.observe();
|
|
117
|
+
expect(getCurrentObserver()).toBe(observer);
|
|
118
|
+
dispose();
|
|
119
|
+
expect(getCurrentObserver()).toBeUndefined();
|
|
120
|
+
});
|
|
121
|
+
it('should handle nested observations with stack', () => {
|
|
122
|
+
const observer1 = new Observer(() => { });
|
|
123
|
+
const observer2 = new Observer(() => { });
|
|
124
|
+
const dispose1 = observer1.observe();
|
|
125
|
+
expect(getCurrentObserver()).toBe(observer1);
|
|
126
|
+
const dispose2 = observer2.observe();
|
|
127
|
+
expect(getCurrentObserver()).toBe(observer2);
|
|
128
|
+
dispose2();
|
|
129
|
+
expect(getCurrentObserver()).toBe(observer1);
|
|
130
|
+
dispose1();
|
|
131
|
+
expect(getCurrentObserver()).toBeUndefined();
|
|
132
|
+
});
|
|
133
|
+
it('should prevent duplicate notifications while queued', async () => {
|
|
134
|
+
let callCount = 0;
|
|
135
|
+
const observer = new Observer(() => {
|
|
136
|
+
callCount++;
|
|
137
|
+
});
|
|
138
|
+
const signal = new Signal();
|
|
139
|
+
const dispose = observer.observe();
|
|
140
|
+
observer.subscribeSignal(signal);
|
|
141
|
+
dispose();
|
|
142
|
+
// Rapid-fire notifications
|
|
143
|
+
for (let i = 0; i < 100; i++) {
|
|
144
|
+
signal.notify();
|
|
145
|
+
}
|
|
146
|
+
await new Promise((resolve) => queueMicrotask(() => resolve()));
|
|
147
|
+
// Should only be called once
|
|
148
|
+
expect(callCount).toBe(1);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-test.d.ts","sourceRoot":"","sources":["../src/render-test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Quick test to understand Snabbdom's behavior
|
|
2
|
+
import { patch } from './render';
|
|
3
|
+
import { h } from 'snabbdom';
|
|
4
|
+
import { JSDOM } from 'jsdom';
|
|
5
|
+
const dom = new JSDOM('<!DOCTYPE html><html><body><div id="app"></div></body></html>');
|
|
6
|
+
global.window = dom.window;
|
|
7
|
+
global.document = dom.window.document;
|
|
8
|
+
const container = document.getElementById('app');
|
|
9
|
+
const parent = container.parentElement;
|
|
10
|
+
console.log('Before patch:');
|
|
11
|
+
console.log('Container id:', container.id);
|
|
12
|
+
console.log('Parent children:', parent.children.length);
|
|
13
|
+
console.log('Parent innerHTML:', parent.innerHTML);
|
|
14
|
+
const vnode = h('div', { props: { id: 'app' } }, [h('span', {}, 'Hello')]);
|
|
15
|
+
const result = patch(container, vnode);
|
|
16
|
+
console.log('\nAfter patch:');
|
|
17
|
+
console.log('Result:', result);
|
|
18
|
+
console.log('Result.elm:', result.elm);
|
|
19
|
+
console.log('Parent children:', parent.children.length);
|
|
20
|
+
console.log('Parent innerHTML:', parent.innerHTML);
|
|
21
|
+
console.log('Container still in DOM?:', document.getElementById('app'));
|
package/dist/render.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ import { type VNode } from "snabbdom";
|
|
|
2
2
|
import { type Component } from "./component";
|
|
3
3
|
export declare const patch: (oldVnode: VNode | Element | DocumentFragment, vnode: VNode) => VNode;
|
|
4
4
|
export type ChildNode = VNode | string | null | number;
|
|
5
|
-
export declare function render(vnode: VNode, container: HTMLElement):
|
|
5
|
+
export declare function render(vnode: VNode, container: HTMLElement): VNode;
|
|
6
6
|
export declare function jsx(type: string | Component<any>, props: Record<string, unknown>, children: ChildNode[]): VNode;
|
|
7
7
|
//# sourceMappingURL=render.d.ts.map
|
package/dist/render.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,KAAK,EAEX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE9D,eAAO,MAAM,KAAK,uEAOhB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvD,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,KAAK,EAEX,MAAM,UAAU,CAAC;AAClB,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE9D,eAAO,MAAM,KAAK,uEAOhB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAEvD,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,SAK1D;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,EAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,EAAE,SAAS,EAAE,SAyEtB"}
|
package/dist/render.js
CHANGED
|
@@ -12,7 +12,7 @@ export function render(vnode, container) {
|
|
|
12
12
|
const style = document.createElement("style");
|
|
13
13
|
style.innerHTML = "component { display: contents; }";
|
|
14
14
|
document.head.appendChild(style);
|
|
15
|
-
patch(container, vnode);
|
|
15
|
+
return patch(container, vnode);
|
|
16
16
|
}
|
|
17
17
|
export function jsx(type, props, children) {
|
|
18
18
|
let flatChildren = children.flat();
|
|
@@ -31,6 +31,18 @@ export function jsx(type, props, children) {
|
|
|
31
31
|
data.style = props[key];
|
|
32
32
|
continue;
|
|
33
33
|
}
|
|
34
|
+
if (key === "class") {
|
|
35
|
+
// Snabbdom's classModule expects an object like { 'class-name': true }
|
|
36
|
+
// If it's a string, convert it to the object format
|
|
37
|
+
const classValue = props[key];
|
|
38
|
+
if (typeof classValue === 'string') {
|
|
39
|
+
data.class = { [classValue]: true };
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
data.class = classValue;
|
|
43
|
+
}
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
34
46
|
if (key === "ref") {
|
|
35
47
|
data.hook = data.hook || {};
|
|
36
48
|
const existingInsertHook = data.hook?.insert;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { VNode } from "./vdom/types";
|
|
2
|
+
/**
|
|
3
|
+
* Test helper to render a component and provide easy cleanup
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const { container, unmount } = renderComponent(<MyComponent />);
|
|
7
|
+
* expect(container.textContent).toBe('hello');
|
|
8
|
+
* unmount();
|
|
9
|
+
*/
|
|
10
|
+
export declare function renderComponent(vnode: VNode): {
|
|
11
|
+
container: HTMLElement;
|
|
12
|
+
vnode: import("./vdom/RootVNode").RootVNode;
|
|
13
|
+
unmount: () => void;
|
|
14
|
+
rerender: (newVnode: VNode) => void;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=test-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-setup.d.ts","sourceRoot":"","sources":["../src/test-setup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAUrC;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK;;;;yBAmBnB,KAAK;EAI7B"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Test setup file for vitest
|
|
2
|
+
import { afterEach } from "vitest";
|
|
3
|
+
import { render } from "./vdom";
|
|
4
|
+
// Clean up after each test
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
document.body.innerHTML = "";
|
|
7
|
+
// Remove any style tags added by render function
|
|
8
|
+
document.querySelectorAll("style").forEach((style) => style.remove());
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Test helper to render a component and provide easy cleanup
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const { container, unmount } = renderComponent(<MyComponent />);
|
|
15
|
+
* expect(container.textContent).toBe('hello');
|
|
16
|
+
* unmount();
|
|
17
|
+
*/
|
|
18
|
+
export function renderComponent(vnode) {
|
|
19
|
+
const container = document.createElement("div");
|
|
20
|
+
document.body.appendChild(container);
|
|
21
|
+
let currentVnode = render(vnode, container);
|
|
22
|
+
const actualElement = currentVnode.elm;
|
|
23
|
+
return {
|
|
24
|
+
// The actual rendered DOM element (after patch replaces container)
|
|
25
|
+
container: actualElement,
|
|
26
|
+
// The vnode returned by render
|
|
27
|
+
vnode: currentVnode,
|
|
28
|
+
// Cleanup function
|
|
29
|
+
unmount: () => {
|
|
30
|
+
if (actualElement && actualElement.parentNode) {
|
|
31
|
+
actualElement.parentNode.removeChild(actualElement);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
// Re-render with new vnode
|
|
35
|
+
rerender: (newVnode) => {
|
|
36
|
+
currentVnode.patch(newVnode);
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class.test.d.ts","sourceRoot":"","sources":["../../src/tests/class.test.ts"],"names":[],"mappings":""}
|