rask-ui 0.1.1 → 0.2.1
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/README.md +923 -185
- package/dist/component.d.ts +17 -0
- package/dist/component.d.ts.map +1 -1
- package/dist/createAsync.d.ts +23 -0
- package/dist/createAsync.d.ts.map +1 -1
- package/dist/createAsync.js +23 -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/createQuery.d.ts +23 -0
- package/dist/createQuery.d.ts.map +1 -1
- package/dist/createQuery.js +23 -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/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 +4 -5
- 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/test-setup.d.ts +3 -3
- package/dist/test-setup.d.ts.map +1 -1
- package/dist/test-setup.js +7 -8
- 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 +185 -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 +334 -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 +135 -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 +103 -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 +84 -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 +4 -6
|
@@ -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
|
}
|
package/dist/test-setup.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { VNode } from "./vdom/types";
|
|
2
2
|
/**
|
|
3
3
|
* Test helper to render a component and provide easy cleanup
|
|
4
4
|
*
|
|
@@ -9,8 +9,8 @@ import type { VNode } from 'snabbdom';
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function renderComponent(vnode: VNode): {
|
|
11
11
|
container: HTMLElement;
|
|
12
|
-
vnode:
|
|
12
|
+
vnode: import("./vdom/RootVNode").RootVNode;
|
|
13
13
|
unmount: () => void;
|
|
14
|
-
rerender: (newVnode: VNode) =>
|
|
14
|
+
rerender: (newVnode: VNode) => void;
|
|
15
15
|
};
|
|
16
16
|
//# sourceMappingURL=test-setup.d.ts.map
|
package/dist/test-setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-setup.d.ts","sourceRoot":"","sources":["../src/test-setup.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
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"}
|
package/dist/test-setup.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Test setup file for vitest
|
|
2
|
-
import { afterEach } from
|
|
3
|
-
import { render
|
|
2
|
+
import { afterEach } from "vitest";
|
|
3
|
+
import { render } from "./vdom";
|
|
4
4
|
// Clean up after each test
|
|
5
5
|
afterEach(() => {
|
|
6
|
-
document.body.innerHTML =
|
|
6
|
+
document.body.innerHTML = "";
|
|
7
7
|
// Remove any style tags added by render function
|
|
8
|
-
document.querySelectorAll(
|
|
8
|
+
document.querySelectorAll("style").forEach((style) => style.remove());
|
|
9
9
|
});
|
|
10
10
|
/**
|
|
11
11
|
* Test helper to render a component and provide easy cleanup
|
|
@@ -16,7 +16,7 @@ afterEach(() => {
|
|
|
16
16
|
* unmount();
|
|
17
17
|
*/
|
|
18
18
|
export function renderComponent(vnode) {
|
|
19
|
-
const container = document.createElement(
|
|
19
|
+
const container = document.createElement("div");
|
|
20
20
|
document.body.appendChild(container);
|
|
21
21
|
let currentVnode = render(vnode, container);
|
|
22
22
|
const actualElement = currentVnode.elm;
|
|
@@ -33,8 +33,7 @@ export function renderComponent(vnode) {
|
|
|
33
33
|
},
|
|
34
34
|
// Re-render with new vnode
|
|
35
35
|
rerender: (newVnode) => {
|
|
36
|
-
currentVnode
|
|
37
|
-
|
|
38
|
-
}
|
|
36
|
+
currentVnode.patch(newVnode);
|
|
37
|
+
},
|
|
39
38
|
};
|
|
40
39
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"class.test.d.ts","sourceRoot":"","sources":["../../src/tests/class.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { jsx, render } from "../vdom";
|
|
3
|
+
import { createState } from "../createState";
|
|
4
|
+
describe("Class Property Support", () => {
|
|
5
|
+
it("should map string class to className", () => {
|
|
6
|
+
const container = document.createElement("div");
|
|
7
|
+
render(jsx("div", { class: "test-class" }), container);
|
|
8
|
+
const div = container.querySelector("div");
|
|
9
|
+
expect(div?.className).toBe("test-class");
|
|
10
|
+
});
|
|
11
|
+
it("should handle multiple classes as string", () => {
|
|
12
|
+
const container = document.createElement("div");
|
|
13
|
+
render(jsx("div", { class: "class-1 class-2 class-3" }), container);
|
|
14
|
+
const div = container.querySelector("div");
|
|
15
|
+
expect(div?.className).toBe("class-1 class-2 class-3");
|
|
16
|
+
});
|
|
17
|
+
it("should handle object notation with true values", () => {
|
|
18
|
+
const container = document.createElement("div");
|
|
19
|
+
render(jsx("div", {
|
|
20
|
+
class: {
|
|
21
|
+
active: true,
|
|
22
|
+
visible: true,
|
|
23
|
+
hidden: false,
|
|
24
|
+
},
|
|
25
|
+
}), container);
|
|
26
|
+
const div = container.querySelector("div");
|
|
27
|
+
expect(div?.classList.contains("active")).toBe(true);
|
|
28
|
+
expect(div?.classList.contains("visible")).toBe(true);
|
|
29
|
+
expect(div?.classList.contains("hidden")).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
it("should handle mixed object notation", () => {
|
|
32
|
+
const container = document.createElement("div");
|
|
33
|
+
render(jsx("div", {
|
|
34
|
+
class: {
|
|
35
|
+
"class-1": true,
|
|
36
|
+
"class-2": false,
|
|
37
|
+
"class-3": true,
|
|
38
|
+
"class-4": false,
|
|
39
|
+
},
|
|
40
|
+
}), container);
|
|
41
|
+
const div = container.querySelector("div");
|
|
42
|
+
expect(div?.className).toBe("class-1 class-3");
|
|
43
|
+
});
|
|
44
|
+
it("should handle empty object notation", () => {
|
|
45
|
+
const container = document.createElement("div");
|
|
46
|
+
render(jsx("div", { class: {} }), container);
|
|
47
|
+
const div = container.querySelector("div");
|
|
48
|
+
expect(div?.className).toBe("");
|
|
49
|
+
expect(div?.hasAttribute("class")).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
it("should handle all false object notation", () => {
|
|
52
|
+
const container = document.createElement("div");
|
|
53
|
+
render(jsx("div", {
|
|
54
|
+
class: {
|
|
55
|
+
"class-1": false,
|
|
56
|
+
"class-2": false,
|
|
57
|
+
},
|
|
58
|
+
}), container);
|
|
59
|
+
const div = container.querySelector("div");
|
|
60
|
+
expect(div?.className).toBe("");
|
|
61
|
+
expect(div?.hasAttribute("class")).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
it("should update classes when object notation changes", async () => {
|
|
64
|
+
const container = document.createElement("div");
|
|
65
|
+
let stateFn;
|
|
66
|
+
const App = () => {
|
|
67
|
+
const state = createState({ isActive: true, isVisible: false });
|
|
68
|
+
stateFn = state;
|
|
69
|
+
return () => jsx("div", {
|
|
70
|
+
class: {
|
|
71
|
+
active: state.isActive,
|
|
72
|
+
visible: state.isVisible,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
render(jsx(App, {}), container);
|
|
77
|
+
const div = container.querySelector("div");
|
|
78
|
+
expect(div?.classList.contains("active")).toBe(true);
|
|
79
|
+
expect(div?.classList.contains("visible")).toBe(false);
|
|
80
|
+
stateFn.isActive = false;
|
|
81
|
+
stateFn.isVisible = true;
|
|
82
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
83
|
+
expect(div?.classList.contains("active")).toBe(false);
|
|
84
|
+
expect(div?.classList.contains("visible")).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
it("should handle hyphenated class names in object notation", () => {
|
|
87
|
+
const container = document.createElement("div");
|
|
88
|
+
render(jsx("div", {
|
|
89
|
+
class: {
|
|
90
|
+
"my-custom-class": true,
|
|
91
|
+
"another-class-name": true,
|
|
92
|
+
"disabled-class": false,
|
|
93
|
+
},
|
|
94
|
+
}), container);
|
|
95
|
+
const div = container.querySelector("div");
|
|
96
|
+
expect(div?.classList.contains("my-custom-class")).toBe(true);
|
|
97
|
+
expect(div?.classList.contains("another-class-name")).toBe(true);
|
|
98
|
+
expect(div?.classList.contains("disabled-class")).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
it("should prefer class over className when both provided", () => {
|
|
101
|
+
const container = document.createElement("div");
|
|
102
|
+
render(jsx("div", { class: "from-class", className: "from-className" }), container);
|
|
103
|
+
const div = container.querySelector("div");
|
|
104
|
+
// class should take precedence
|
|
105
|
+
expect(div?.className).toBe("from-class");
|
|
106
|
+
});
|
|
107
|
+
it("should work with nested components", () => {
|
|
108
|
+
const container = document.createElement("div");
|
|
109
|
+
const Child = () => {
|
|
110
|
+
return () => jsx("span", { class: "child-class" });
|
|
111
|
+
};
|
|
112
|
+
const Parent = () => {
|
|
113
|
+
return () => jsx("div", {
|
|
114
|
+
class: "parent-class",
|
|
115
|
+
children: jsx(Child, {}),
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
render(jsx(Parent, {}), container);
|
|
119
|
+
const parentDiv = container.querySelector("div");
|
|
120
|
+
const childSpan = container.querySelector("span");
|
|
121
|
+
expect(parentDiv?.className).toBe("parent-class");
|
|
122
|
+
expect(childSpan?.className).toBe("child-class");
|
|
123
|
+
});
|
|
124
|
+
it("should handle undefined and null class values", () => {
|
|
125
|
+
const container = document.createElement("div");
|
|
126
|
+
render(jsx("div", { class: undefined }), container);
|
|
127
|
+
const div = container.querySelector("div");
|
|
128
|
+
expect(div?.className).toBe("");
|
|
129
|
+
expect(div?.hasAttribute("class")).toBe(false);
|
|
130
|
+
});
|
|
131
|
+
it("should remove class attribute when empty string is provided", () => {
|
|
132
|
+
const container = document.createElement("div");
|
|
133
|
+
render(jsx("div", { class: "" }), container);
|
|
134
|
+
const div = container.querySelector("div");
|
|
135
|
+
expect(div?.hasAttribute("class")).toBe(false);
|
|
136
|
+
});
|
|
137
|
+
it("should remove class attribute when null is provided", () => {
|
|
138
|
+
const container = document.createElement("div");
|
|
139
|
+
render(jsx("div", { class: null }), container);
|
|
140
|
+
const div = container.querySelector("div");
|
|
141
|
+
expect(div?.hasAttribute("class")).toBe(false);
|
|
142
|
+
});
|
|
143
|
+
it("should remove class attribute when object notation results in empty string", () => {
|
|
144
|
+
const container = document.createElement("div");
|
|
145
|
+
render(jsx("div", {
|
|
146
|
+
class: {
|
|
147
|
+
active: false,
|
|
148
|
+
visible: false,
|
|
149
|
+
},
|
|
150
|
+
}), container);
|
|
151
|
+
const div = container.querySelector("div");
|
|
152
|
+
expect(div?.hasAttribute("class")).toBe(false);
|
|
153
|
+
});
|
|
154
|
+
it("should remove class attribute when updating from non-empty to empty string", async () => {
|
|
155
|
+
const container = document.createElement("div");
|
|
156
|
+
let stateFn;
|
|
157
|
+
const App = () => {
|
|
158
|
+
const state = createState({ className: "initial" });
|
|
159
|
+
stateFn = state;
|
|
160
|
+
return () => jsx("div", { class: state.className });
|
|
161
|
+
};
|
|
162
|
+
render(jsx(App, {}), container);
|
|
163
|
+
const div = container.querySelector("div");
|
|
164
|
+
expect(div?.className).toBe("initial");
|
|
165
|
+
expect(div?.hasAttribute("class")).toBe(true);
|
|
166
|
+
stateFn.className = "";
|
|
167
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
168
|
+
expect(div?.hasAttribute("class")).toBe(false);
|
|
169
|
+
});
|
|
170
|
+
it("should handle dynamic string class updates", async () => {
|
|
171
|
+
const container = document.createElement("div");
|
|
172
|
+
let stateFn;
|
|
173
|
+
const App = () => {
|
|
174
|
+
const state = createState({ className: "initial" });
|
|
175
|
+
stateFn = state;
|
|
176
|
+
return () => jsx("div", { class: state.className });
|
|
177
|
+
};
|
|
178
|
+
render(jsx(App, {}), container);
|
|
179
|
+
const div = container.querySelector("div");
|
|
180
|
+
expect(div?.className).toBe("initial");
|
|
181
|
+
stateFn.className = "updated";
|
|
182
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
183
|
+
expect(div?.className).toBe("updated");
|
|
184
|
+
});
|
|
185
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complex-rendering.test.d.ts","sourceRoot":"","sources":["../../src/tests/complex-rendering.test.ts"],"names":[],"mappings":""}
|