@luna_ui/luna 0.11.0 → 0.20.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/api-DAWeanTX.js +1 -0
- package/dist/api-qXll116-.d.ts +80 -0
- package/dist/cli.mjs +27 -22
- package/dist/css/index.js +1 -0
- package/dist/event-utils.d.ts +1 -1
- package/dist/event-utils.js +1 -1
- package/dist/{index-BZoM-af5.d.ts → index-VY8G32hr.d.ts} +16 -76
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1 -1
- package/dist/jsx-dev-runtime.js +1 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +1 -1
- package/dist/raw.d.ts +2 -0
- package/dist/raw.js +1 -0
- package/dist/resource.d.ts +41 -0
- package/dist/resource.js +1 -0
- package/dist/router-lite.d.ts +44 -0
- package/dist/router-lite.js +1 -0
- package/dist/signals-shared.d.ts +12 -0
- package/dist/signals-shared.js +1 -0
- package/dist/signals.d.ts +2 -3
- package/dist/signals.js +1 -1
- package/dist/vite-plugin.d.ts +7708 -2
- package/dist/vite-plugin.js +7 -6
- package/package.json +30 -11
- package/dist/event-utils-9cHYnvun.js +0 -1
- package/dist/src-BFWjzzPo.js +0 -1
- package/src/css/extract.ts +0 -798
- package/src/css/index.ts +0 -10
- package/src/css/inject.ts +0 -205
- package/src/css/inline.ts +0 -182
- package/src/css/minify.ts +0 -70
- package/src/css/optimizer.ts +0 -6
- package/src/css/runtime.ts +0 -344
- package/src/css-optimizer/README.md +0 -353
- package/src/css-optimizer/cooccurrence.ts +0 -100
- package/src/css-optimizer/core.ts +0 -263
- package/src/css-optimizer/extractors.ts +0 -243
- package/src/css-optimizer/hash.ts +0 -54
- package/src/css-optimizer/index.ts +0 -129
- package/src/css-optimizer/merge.ts +0 -109
- package/src/css-optimizer/moonbit-analyzer.ts +0 -210
- package/src/css-optimizer/parser.ts +0 -120
- package/src/css-optimizer/pattern.ts +0 -171
- package/src/css-optimizer/transformers.ts +0 -301
- package/src/css-optimizer/types.ts +0 -128
- package/src/event-utils.ts +0 -227
- package/src/hydration/createHydrator.ts +0 -62
- package/src/hydration/delegate.ts +0 -62
- package/src/hydration/drag.ts +0 -214
- package/src/hydration/index.ts +0 -12
- package/src/hydration/keyboard.ts +0 -64
- package/src/hydration/toggle.ts +0 -101
- package/src/index.ts +0 -908
- package/src/jsx-dev-runtime.ts +0 -2
- package/src/jsx-runtime.ts +0 -398
- package/src/signals.ts +0 -113
- package/src/vite-plugin.ts +0 -718
- package/tests/__screenshots__/apg.test.ts/APG-Components---Accessibility-Tests-Button-Pattern-disabled-button-has-aria-disabled-1.png +0 -0
- package/tests/__screenshots__/resource.test.ts/Resource-API--SolidJS-style--createResource-error-is-undefined-when-pending-1.png +0 -0
- package/tests/__screenshots__/resource.test.ts/Resource-API--SolidJS-style--createResource-transitions-to-success-on-resolve-1.png +0 -0
- package/tests/apg.test.ts +0 -466
- package/tests/context.test.ts +0 -118
- package/tests/css-optimizer-extractors.test.ts +0 -264
- package/tests/css-optimizer-integration.test.ts +0 -566
- package/tests/css-optimizer-transformers.test.ts +0 -301
- package/tests/css-optimizer.test.ts +0 -646
- package/tests/css-runtime.bench.ts +0 -442
- package/tests/css-runtime.test.ts +0 -342
- package/tests/debounced.test.ts +0 -165
- package/tests/dom.test.ts +0 -873
- package/tests/integration.test.ts +0 -405
- package/tests/issue-11-show-null-to-truthy.test.ts +0 -176
- package/tests/issue-5-for-infinite-loop.test.ts +0 -516
- package/tests/jsx-runtime.test.tsx +0 -393
- package/tests/lifecycle.test.ts +0 -833
- package/tests/move-before.bench.ts +0 -304
- package/tests/preact-signals-comparison.test.ts +0 -1608
- package/tests/resource.test.ts +0 -170
- package/tests/router.test.ts +0 -117
- package/tests/show-initial-mount-leak.test.tsx +0 -182
- package/tests/solidjs-api.test.ts +0 -660
- package/tests/static-perf.bench.ts +0 -64
- package/tests/store.test.ts +0 -263
- package/tests/tsx-syntax.test.tsx +0 -404
- /package/dist/{event-utils-BkTM7rk5.d.ts → event-utils-BvAf0NwN.d.ts} +0 -0
|
@@ -1,393 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "vitest";
|
|
2
|
-
import "global-jsdom/register";
|
|
3
|
-
import { jsx, jsxs, Fragment, type JSX } from "../src/jsx-runtime";
|
|
4
|
-
import { createSignal, createMemo, get, set, For, Show, render } from "../src/index";
|
|
5
|
-
|
|
6
|
-
describe("JSX Runtime", () => {
|
|
7
|
-
test("jsx creates element", () => {
|
|
8
|
-
const node = jsx("div", { className: "test" });
|
|
9
|
-
expect(node).toBeDefined();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test("jsx with children", () => {
|
|
13
|
-
const node = jsx("div", {
|
|
14
|
-
children: jsx("span", { children: "hello" }),
|
|
15
|
-
});
|
|
16
|
-
expect(node).toBeDefined();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("jsxs with multiple children", () => {
|
|
20
|
-
const node = jsxs("div", {
|
|
21
|
-
children: [
|
|
22
|
-
jsx("span", { children: "first" }),
|
|
23
|
-
jsx("span", { children: "second" }),
|
|
24
|
-
],
|
|
25
|
-
});
|
|
26
|
-
expect(node).toBeDefined();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test("Fragment returns DomNode", () => {
|
|
30
|
-
const node = Fragment({
|
|
31
|
-
children: [
|
|
32
|
-
jsx("div", { children: "a" }),
|
|
33
|
-
jsx("div", { children: "b" }),
|
|
34
|
-
],
|
|
35
|
-
});
|
|
36
|
-
// Fragment should return a DomNode (not an array)
|
|
37
|
-
expect(node).toBeDefined();
|
|
38
|
-
expect(Array.isArray(node)).toBe(false);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("function component", () => {
|
|
42
|
-
function MyComponent(props: { name: string }) {
|
|
43
|
-
return jsx("div", { children: `Hello, ${props.name}!` });
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const node = jsx(MyComponent, { name: "World" });
|
|
47
|
-
expect(node).toBeDefined();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("renders to DOM", () => {
|
|
51
|
-
const node = jsx("div", {
|
|
52
|
-
id: "test-root",
|
|
53
|
-
className: "container",
|
|
54
|
-
children: jsxs("p", {
|
|
55
|
-
children: ["Hello ", "World"],
|
|
56
|
-
}),
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const container = document.createElement("div");
|
|
60
|
-
render(container, node);
|
|
61
|
-
|
|
62
|
-
expect(container.innerHTML).toContain("test-root");
|
|
63
|
-
expect(container.innerHTML).toContain("container");
|
|
64
|
-
expect(container.innerHTML).toContain("Hello");
|
|
65
|
-
expect(container.innerHTML).toContain("World");
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("reactive className", () => {
|
|
69
|
-
const [isActive, setIsActive] = createSignal(false);
|
|
70
|
-
|
|
71
|
-
const node = jsx("div", {
|
|
72
|
-
className: () => (isActive() ? "active" : "inactive"),
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
expect(node).toBeDefined();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("event handlers", () => {
|
|
79
|
-
let clicked = false;
|
|
80
|
-
|
|
81
|
-
const node = jsx("button", {
|
|
82
|
-
onClick: () => {
|
|
83
|
-
clicked = true;
|
|
84
|
-
},
|
|
85
|
-
children: "Click me",
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
expect(node).toBeDefined();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test("input with value", () => {
|
|
92
|
-
const node = jsx("input", {
|
|
93
|
-
type: "text",
|
|
94
|
-
placeholder: "Enter text",
|
|
95
|
-
value: "initial",
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
expect(node).toBeDefined();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test("self-closing elements", () => {
|
|
102
|
-
const br = jsx("br", {});
|
|
103
|
-
const hr = jsx("hr", {});
|
|
104
|
-
const img = jsx("img", { src: "test.png", alt: "Test" });
|
|
105
|
-
|
|
106
|
-
expect(br).toBeDefined();
|
|
107
|
-
expect(hr).toBeDefined();
|
|
108
|
-
expect(img).toBeDefined();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test("style object is converted to CSS string", () => {
|
|
112
|
-
const node = jsx("div", {
|
|
113
|
-
style: { padding: "20px", backgroundColor: "red", maxWidth: "600px" },
|
|
114
|
-
children: "styled",
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
const container = document.createElement("div");
|
|
118
|
-
render(container, node);
|
|
119
|
-
|
|
120
|
-
const div = container.querySelector("div");
|
|
121
|
-
expect(div).toBeDefined();
|
|
122
|
-
// Check that style is applied (camelCase converted to kebab-case)
|
|
123
|
-
expect(div?.getAttribute("style")).toContain("padding: 20px");
|
|
124
|
-
expect(div?.getAttribute("style")).toContain("background-color: red");
|
|
125
|
-
expect(div?.getAttribute("style")).toContain("max-width: 600px");
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test("style string is passed through", () => {
|
|
129
|
-
const node = jsx("div", {
|
|
130
|
-
style: "color: blue; margin: 10px",
|
|
131
|
-
children: "styled",
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
const container = document.createElement("div");
|
|
135
|
-
render(container, node);
|
|
136
|
-
|
|
137
|
-
const div = container.querySelector("div");
|
|
138
|
-
expect(div?.getAttribute("style")).toBe("color: blue; margin: 10px");
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
test("onClick handler is triggered", () => {
|
|
142
|
-
let clicked = false;
|
|
143
|
-
|
|
144
|
-
const node = jsx("button", {
|
|
145
|
-
onClick: () => {
|
|
146
|
-
clicked = true;
|
|
147
|
-
},
|
|
148
|
-
children: "Click me",
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const container = document.createElement("div");
|
|
152
|
-
render(container, node);
|
|
153
|
-
|
|
154
|
-
const button = container.querySelector("button");
|
|
155
|
-
expect(button).toBeDefined();
|
|
156
|
-
|
|
157
|
-
// Simulate click
|
|
158
|
-
button?.click();
|
|
159
|
-
expect(clicked).toBe(true);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
test("onInput handler is triggered", () => {
|
|
163
|
-
let inputValue = "";
|
|
164
|
-
|
|
165
|
-
const node = jsx("input", {
|
|
166
|
-
type: "text",
|
|
167
|
-
onInput: (e: Event) => {
|
|
168
|
-
inputValue = (e.target as HTMLInputElement).value;
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
const container = document.createElement("div");
|
|
173
|
-
render(container, node);
|
|
174
|
-
|
|
175
|
-
const input = container.querySelector("input") as HTMLInputElement;
|
|
176
|
-
expect(input).toBeDefined();
|
|
177
|
-
|
|
178
|
-
// Simulate input using native setter and event
|
|
179
|
-
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
|
|
180
|
-
window.HTMLInputElement.prototype,
|
|
181
|
-
"value"
|
|
182
|
-
)?.set;
|
|
183
|
-
nativeInputValueSetter?.call(input, "test");
|
|
184
|
-
input.dispatchEvent(new window.Event("input", { bubbles: true }));
|
|
185
|
-
expect(inputValue).toBe("test");
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
test("signal accessor renders as dynamic text", () => {
|
|
189
|
-
const [count, setCount] = createSignal(0);
|
|
190
|
-
|
|
191
|
-
const node = jsx("div", {
|
|
192
|
-
children: [
|
|
193
|
-
"Count: ",
|
|
194
|
-
count, // signal accessor as child
|
|
195
|
-
],
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
const container = document.createElement("div");
|
|
199
|
-
render(container, node);
|
|
200
|
-
|
|
201
|
-
expect(container.textContent).toContain("Count: 0");
|
|
202
|
-
|
|
203
|
-
// Update signal
|
|
204
|
-
setCount(5);
|
|
205
|
-
expect(container.textContent).toContain("Count: 5");
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
test("memo accessor renders as dynamic text", () => {
|
|
209
|
-
const [count, setCount] = createSignal(2);
|
|
210
|
-
const doubled = createMemo(() => count() * 2);
|
|
211
|
-
|
|
212
|
-
const node = jsx("div", {
|
|
213
|
-
children: ["Doubled: ", doubled],
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
const container = document.createElement("div");
|
|
217
|
-
render(container, node);
|
|
218
|
-
|
|
219
|
-
expect(container.textContent).toContain("Doubled: 4");
|
|
220
|
-
|
|
221
|
-
setCount(5);
|
|
222
|
-
expect(container.textContent).toContain("Doubled: 10");
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test("inline function renders as dynamic text", () => {
|
|
226
|
-
const [isEven, setIsEven] = createSignal(true);
|
|
227
|
-
|
|
228
|
-
const node = jsx("div", {
|
|
229
|
-
children: [() => (isEven() ? "Even" : "Odd")],
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
const container = document.createElement("div");
|
|
233
|
-
render(container, node);
|
|
234
|
-
|
|
235
|
-
expect(container.textContent).toBe("Even");
|
|
236
|
-
|
|
237
|
-
setIsEven(false);
|
|
238
|
-
expect(container.textContent).toBe("Odd");
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
test("render function (with args) is passed through to For", () => {
|
|
242
|
-
const [items, setItems] = createSignal(["a", "b", "c"]);
|
|
243
|
-
|
|
244
|
-
const node = jsx(For, {
|
|
245
|
-
each: items,
|
|
246
|
-
children: (item: string) => jsx("li", { children: item }),
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
const container = document.createElement("ul");
|
|
250
|
-
render(container, node);
|
|
251
|
-
|
|
252
|
-
expect(container.querySelectorAll("li").length).toBe(3);
|
|
253
|
-
expect(container.textContent).toContain("a");
|
|
254
|
-
expect(container.textContent).toContain("b");
|
|
255
|
-
expect(container.textContent).toContain("c");
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
test("Show component with JSX", () => {
|
|
259
|
-
const [visible, setVisible] = createSignal(true);
|
|
260
|
-
|
|
261
|
-
const node = jsx(Show, {
|
|
262
|
-
when: visible,
|
|
263
|
-
children: jsx("div", { children: "Visible content" }),
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
const container = document.createElement("div");
|
|
267
|
-
render(container, node);
|
|
268
|
-
|
|
269
|
-
expect(container.textContent).toContain("Visible content");
|
|
270
|
-
|
|
271
|
-
setVisible(false);
|
|
272
|
-
expect(container.textContent).not.toContain("Visible content");
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
describe("JSX Counter Example", () => {
|
|
277
|
-
test("counter increments and decrements", () => {
|
|
278
|
-
const [count, setCount] = createSignal(0);
|
|
279
|
-
const doubled = createMemo(() => count() * 2);
|
|
280
|
-
|
|
281
|
-
const Counter = () =>
|
|
282
|
-
jsx("div", {
|
|
283
|
-
children: [
|
|
284
|
-
jsx("p", { children: ["Count: ", count] }),
|
|
285
|
-
jsx("p", { children: ["Doubled: ", doubled] }),
|
|
286
|
-
jsx("button", {
|
|
287
|
-
id: "decrement",
|
|
288
|
-
onClick: () => setCount((c) => c - 1),
|
|
289
|
-
children: "-",
|
|
290
|
-
}),
|
|
291
|
-
jsx("button", {
|
|
292
|
-
id: "increment",
|
|
293
|
-
onClick: () => setCount((c) => c + 1),
|
|
294
|
-
children: "+",
|
|
295
|
-
}),
|
|
296
|
-
jsx("button", {
|
|
297
|
-
id: "reset",
|
|
298
|
-
onClick: () => setCount(0),
|
|
299
|
-
children: "Reset",
|
|
300
|
-
}),
|
|
301
|
-
],
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
const container = document.createElement("div");
|
|
305
|
-
render(container, jsx(Counter, {}));
|
|
306
|
-
|
|
307
|
-
// Initial state
|
|
308
|
-
expect(container.textContent).toContain("Count: 0");
|
|
309
|
-
expect(container.textContent).toContain("Doubled: 0");
|
|
310
|
-
|
|
311
|
-
// Increment
|
|
312
|
-
container.querySelector<HTMLButtonElement>("#increment")?.click();
|
|
313
|
-
expect(container.textContent).toContain("Count: 1");
|
|
314
|
-
expect(container.textContent).toContain("Doubled: 2");
|
|
315
|
-
|
|
316
|
-
// Increment again
|
|
317
|
-
container.querySelector<HTMLButtonElement>("#increment")?.click();
|
|
318
|
-
expect(container.textContent).toContain("Count: 2");
|
|
319
|
-
expect(container.textContent).toContain("Doubled: 4");
|
|
320
|
-
|
|
321
|
-
// Decrement
|
|
322
|
-
container.querySelector<HTMLButtonElement>("#decrement")?.click();
|
|
323
|
-
expect(container.textContent).toContain("Count: 1");
|
|
324
|
-
expect(container.textContent).toContain("Doubled: 2");
|
|
325
|
-
|
|
326
|
-
// Reset
|
|
327
|
-
container.querySelector<HTMLButtonElement>("#reset")?.click();
|
|
328
|
-
expect(container.textContent).toContain("Count: 0");
|
|
329
|
-
expect(container.textContent).toContain("Doubled: 0");
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
describe("JSX Todo Example", () => {
|
|
334
|
-
test("todo list add and remove", () => {
|
|
335
|
-
const [todos, setTodos] = createSignal<
|
|
336
|
-
{ id: number; text: string; done: boolean }[]
|
|
337
|
-
>([]);
|
|
338
|
-
let nextId = 1;
|
|
339
|
-
|
|
340
|
-
const addTodo = (text: string) => {
|
|
341
|
-
setTodos((t) => [...t, { id: nextId++, text, done: false }]);
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
const removeTodo = (id: number) => {
|
|
345
|
-
setTodos((t) => t.filter((todo) => todo.id !== id));
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
const TodoApp = () =>
|
|
349
|
-
jsxs("div", {
|
|
350
|
-
children: [
|
|
351
|
-
jsx("button", {
|
|
352
|
-
id: "add-btn",
|
|
353
|
-
onClick: () => addTodo("New todo"),
|
|
354
|
-
children: "Add",
|
|
355
|
-
}),
|
|
356
|
-
jsx(For, {
|
|
357
|
-
each: todos,
|
|
358
|
-
children: (todo: { id: number; text: string; done: boolean }) =>
|
|
359
|
-
jsx("div", {
|
|
360
|
-
className: "todo-item",
|
|
361
|
-
children: [
|
|
362
|
-
jsx("span", { children: todo.text }),
|
|
363
|
-
jsx("button", {
|
|
364
|
-
className: "remove-btn",
|
|
365
|
-
onClick: () => removeTodo(todo.id),
|
|
366
|
-
children: "x",
|
|
367
|
-
}),
|
|
368
|
-
],
|
|
369
|
-
}),
|
|
370
|
-
}),
|
|
371
|
-
],
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
const container = document.createElement("div");
|
|
375
|
-
render(container, jsx(TodoApp, {}));
|
|
376
|
-
|
|
377
|
-
// Initially empty
|
|
378
|
-
expect(container.querySelectorAll(".todo-item").length).toBe(0);
|
|
379
|
-
|
|
380
|
-
// Add first todo
|
|
381
|
-
container.querySelector<HTMLButtonElement>("#add-btn")?.click();
|
|
382
|
-
expect(container.querySelectorAll(".todo-item").length).toBe(1);
|
|
383
|
-
expect(container.textContent).toContain("New todo");
|
|
384
|
-
|
|
385
|
-
// Add second todo
|
|
386
|
-
container.querySelector<HTMLButtonElement>("#add-btn")?.click();
|
|
387
|
-
expect(container.querySelectorAll(".todo-item").length).toBe(2);
|
|
388
|
-
|
|
389
|
-
// Remove first todo
|
|
390
|
-
container.querySelector<HTMLButtonElement>(".remove-btn")?.click();
|
|
391
|
-
expect(container.querySelectorAll(".todo-item").length).toBe(1);
|
|
392
|
-
});
|
|
393
|
-
});
|