@praxisjs/runtime 0.7.1 → 0.8.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.
Files changed (138) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/children.d.ts.map +1 -1
  3. package/dist/children.js +2 -1
  4. package/dist/children.js.map +1 -1
  5. package/dist/component.d.ts +2 -3
  6. package/dist/component.d.ts.map +1 -1
  7. package/dist/component.js +133 -60
  8. package/dist/component.js.map +1 -1
  9. package/dist/context.d.ts +13 -0
  10. package/dist/context.d.ts.map +1 -1
  11. package/dist/context.js +24 -2
  12. package/dist/context.js.map +1 -1
  13. package/dist/dom/constants.d.ts +1 -1
  14. package/dist/dom/constants.d.ts.map +1 -1
  15. package/dist/dom/constants.js +24 -83
  16. package/dist/dom/constants.js.map +1 -1
  17. package/dist/dom/create.d.ts +1 -1
  18. package/dist/dom/create.d.ts.map +1 -1
  19. package/dist/dom/create.js +3 -3
  20. package/dist/dom/create.js.map +1 -1
  21. package/dist/dom/events.d.ts +28 -0
  22. package/dist/dom/events.d.ts.map +1 -1
  23. package/dist/dom/events.js +163 -17
  24. package/dist/dom/events.js.map +1 -1
  25. package/dist/dom/props.d.ts +4 -0
  26. package/dist/dom/props.d.ts.map +1 -1
  27. package/dist/dom/props.js +61 -8
  28. package/dist/dom/props.js.map +1 -1
  29. package/dist/dom/range.d.ts +4 -0
  30. package/dist/dom/range.d.ts.map +1 -0
  31. package/dist/dom/range.js +43 -0
  32. package/dist/dom/range.js.map +1 -0
  33. package/dist/dom/remove.d.ts.map +1 -1
  34. package/dist/dom/remove.js +2 -8
  35. package/dist/dom/remove.js.map +1 -1
  36. package/dist/element.d.ts.map +1 -1
  37. package/dist/element.js +7 -5
  38. package/dist/element.js.map +1 -1
  39. package/dist/hmr.d.ts +35 -0
  40. package/dist/hmr.d.ts.map +1 -0
  41. package/dist/hmr.js +85 -0
  42. package/dist/hmr.js.map +1 -0
  43. package/dist/hydration-context.d.ts +9 -1
  44. package/dist/hydration-context.d.ts.map +1 -1
  45. package/dist/hydration-context.js +34 -13
  46. package/dist/hydration-context.js.map +1 -1
  47. package/dist/hydration.d.ts.map +1 -1
  48. package/dist/hydration.js +4 -11
  49. package/dist/hydration.js.map +1 -1
  50. package/dist/index.d.ts +16 -5
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +31 -7
  53. package/dist/index.js.map +1 -1
  54. package/dist/list.d.ts +72 -0
  55. package/dist/list.d.ts.map +1 -0
  56. package/dist/list.js +786 -0
  57. package/dist/list.js.map +1 -0
  58. package/dist/portal.d.ts.map +1 -1
  59. package/dist/portal.js +3 -0
  60. package/dist/portal.js.map +1 -1
  61. package/dist/reactive.d.ts +2 -2
  62. package/dist/reactive.d.ts.map +1 -1
  63. package/dist/reactive.js +109 -34
  64. package/dist/reactive.js.map +1 -1
  65. package/dist/scope.d.ts +14 -4
  66. package/dist/scope.d.ts.map +1 -1
  67. package/dist/scope.js +55 -15
  68. package/dist/scope.js.map +1 -1
  69. package/dist/template.d.ts +48 -0
  70. package/dist/template.d.ts.map +1 -0
  71. package/dist/template.js +270 -0
  72. package/dist/template.js.map +1 -0
  73. package/package.json +15 -6
  74. package/src/children.ts +2 -1
  75. package/src/component.ts +135 -63
  76. package/src/context.ts +35 -4
  77. package/src/dom/constants.ts +25 -82
  78. package/src/dom/create.ts +3 -3
  79. package/src/dom/events.ts +184 -16
  80. package/src/dom/props.ts +70 -9
  81. package/src/dom/range.ts +45 -0
  82. package/src/dom/remove.ts +3 -7
  83. package/src/element.ts +8 -6
  84. package/src/hmr.ts +110 -0
  85. package/src/hydration-context.ts +34 -13
  86. package/src/hydration.ts +4 -9
  87. package/src/index.ts +54 -7
  88. package/src/list.ts +886 -0
  89. package/src/portal.ts +3 -0
  90. package/src/reactive.ts +147 -40
  91. package/src/scope.ts +63 -16
  92. package/src/template.ts +271 -0
  93. package/dist/__tests__/children.test.d.ts +0 -2
  94. package/dist/__tests__/children.test.d.ts.map +0 -1
  95. package/dist/__tests__/children.test.js +0 -241
  96. package/dist/__tests__/children.test.js.map +0 -1
  97. package/dist/__tests__/component.test.d.ts +0 -2
  98. package/dist/__tests__/component.test.d.ts.map +0 -1
  99. package/dist/__tests__/component.test.js +0 -347
  100. package/dist/__tests__/component.test.js.map +0 -1
  101. package/dist/__tests__/context.test.d.ts +0 -2
  102. package/dist/__tests__/context.test.d.ts.map +0 -1
  103. package/dist/__tests__/context.test.js +0 -111
  104. package/dist/__tests__/context.test.js.map +0 -1
  105. package/dist/__tests__/dom.test.d.ts +0 -2
  106. package/dist/__tests__/dom.test.d.ts.map +0 -1
  107. package/dist/__tests__/dom.test.js +0 -429
  108. package/dist/__tests__/dom.test.js.map +0 -1
  109. package/dist/__tests__/hydration.test.d.ts +0 -2
  110. package/dist/__tests__/hydration.test.d.ts.map +0 -1
  111. package/dist/__tests__/hydration.test.js +0 -299
  112. package/dist/__tests__/hydration.test.js.map +0 -1
  113. package/dist/__tests__/portal.test.d.ts +0 -2
  114. package/dist/__tests__/portal.test.d.ts.map +0 -1
  115. package/dist/__tests__/portal.test.js +0 -157
  116. package/dist/__tests__/portal.test.js.map +0 -1
  117. package/dist/__tests__/remove.test.d.ts +0 -2
  118. package/dist/__tests__/remove.test.d.ts.map +0 -1
  119. package/dist/__tests__/remove.test.js +0 -45
  120. package/dist/__tests__/remove.test.js.map +0 -1
  121. package/dist/__tests__/render.test.d.ts +0 -2
  122. package/dist/__tests__/render.test.d.ts.map +0 -1
  123. package/dist/__tests__/render.test.js +0 -97
  124. package/dist/__tests__/render.test.js.map +0 -1
  125. package/dist/__tests__/scope.test.d.ts +0 -2
  126. package/dist/__tests__/scope.test.d.ts.map +0 -1
  127. package/dist/__tests__/scope.test.js +0 -110
  128. package/dist/__tests__/scope.test.js.map +0 -1
  129. package/src/__tests__/children.test.ts +0 -276
  130. package/src/__tests__/component.test.ts +0 -381
  131. package/src/__tests__/context.test.ts +0 -128
  132. package/src/__tests__/dom.test.ts +0 -483
  133. package/src/__tests__/hydration.test.ts +0 -360
  134. package/src/__tests__/portal.test.ts +0 -177
  135. package/src/__tests__/remove.test.ts +0 -51
  136. package/src/__tests__/render.test.ts +0 -119
  137. package/src/__tests__/scope.test.ts +0 -120
  138. package/tsconfig.json +0 -8
@@ -1,119 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { describe, it, expect } from "vitest";
3
-
4
- import { signal } from "@praxisjs/core/internal";
5
-
6
- import { render, mountElement } from "../index";
7
- import { Scope } from "../scope";
8
-
9
- // ── mountElement ─────────────────────────────────────────────────────────────
10
-
11
- describe("mountElement", () => {
12
- it("creates an element with the given tag", () => {
13
- const scope = new Scope();
14
- const el = mountElement("section", {}, scope);
15
- expect(el.tagName.toLowerCase()).toBe("section");
16
- });
17
-
18
- it("applies static props", () => {
19
- const scope = new Scope();
20
- const el = mountElement("p", { id: "para", class: "text" }, scope) as HTMLElement;
21
- expect(el.id).toBe("para");
22
- expect(el.getAttribute("class")).toBe("text");
23
- });
24
-
25
- it("mounts string children", () => {
26
- const scope = new Scope();
27
- const el = mountElement("p", { children: "hello" }, scope);
28
- expect(el.textContent).toBe("hello");
29
- });
30
-
31
- it("mounts reactive prop — updates when signal changes", () => {
32
- const scope = new Scope();
33
- const cls = signal("a");
34
- const el = mountElement("div", { class: () => cls() }, scope);
35
- expect(el.getAttribute("class")).toBe("a");
36
- cls.set("b");
37
- expect(el.getAttribute("class")).toBe("b");
38
- scope.dispose();
39
- });
40
- });
41
-
42
- // ── render ───────────────────────────────────────────────────────────────────
43
-
44
- describe("render", () => {
45
- it("mounts content into container", () => {
46
- const container = document.createElement("div");
47
- document.body.appendChild(container);
48
-
49
- const scope = new Scope();
50
- render(() => {
51
- const el = mountElement("h1", { children: "Hello" }, scope);
52
- return el;
53
- }, container);
54
-
55
- expect(container.textContent).toBe("Hello");
56
- document.body.removeChild(container);
57
- });
58
-
59
- it("clears container on unmount", () => {
60
- const container = document.createElement("div");
61
- document.body.appendChild(container);
62
-
63
- const unmount = render(() => {
64
- const scope = new Scope();
65
- return mountElement("p", { children: "bye" }, scope);
66
- }, container);
67
-
68
- expect(container.textContent).toBe("bye");
69
- unmount();
70
- expect(container.innerHTML).toBe("");
71
- document.body.removeChild(container);
72
- });
73
-
74
- it("render() factory function throws — container remains cleared, error propagates", () => {
75
- const container = document.createElement("div");
76
- container.innerHTML = "<p>old content</p>";
77
- document.body.appendChild(container);
78
-
79
- expect(() => {
80
- render(() => {
81
- throw new Error("factory error");
82
- }, container);
83
- }).toThrow("factory error");
84
-
85
- // container was cleared before factory ran
86
- expect(container.innerHTML).toBe("");
87
- document.body.removeChild(container);
88
- });
89
-
90
- it("unmount() called twice — does not crash", () => {
91
- const container = document.createElement("div");
92
- document.body.appendChild(container);
93
-
94
- const unmount = render(() => {
95
- const scope = new Scope();
96
- return mountElement("p", { children: "hi" }, scope);
97
- }, container);
98
-
99
- unmount();
100
- expect(() => unmount()).not.toThrow();
101
- document.body.removeChild(container);
102
- });
103
-
104
- it("reactive content re-renders on signal change", () => {
105
- const container = document.createElement("div");
106
- document.body.appendChild(container);
107
- const text = signal("initial");
108
-
109
- render(() => {
110
- const scope = new Scope();
111
- return mountElement("span", { children: () => text() }, scope);
112
- }, container);
113
-
114
- expect(container.textContent).toBe("initial");
115
- text.set("updated");
116
- expect(container.textContent).toBe("updated");
117
- document.body.removeChild(container);
118
- });
119
- });
@@ -1,120 +0,0 @@
1
- import { describe, it, expect, vi } from "vitest";
2
-
3
- import { Scope } from "../scope";
4
-
5
- describe("Scope", () => {
6
- it("add() registers a cleanup fn that runs on dispose()", () => {
7
- const scope = new Scope();
8
- const cleanup = vi.fn();
9
- scope.add(cleanup);
10
- scope.dispose();
11
- expect(cleanup).toHaveBeenCalledOnce();
12
- });
13
-
14
- it("dispose() runs all cleanups in order", () => {
15
- const scope = new Scope();
16
- const order: number[] = [];
17
- scope.add(() => order.push(1));
18
- scope.add(() => order.push(2));
19
- scope.add(() => order.push(3));
20
- scope.dispose();
21
- expect(order).toEqual([1, 2, 3]);
22
- });
23
-
24
- it("dispose() clears cleanups — second dispose() is a no-op", () => {
25
- const scope = new Scope();
26
- const fn = vi.fn();
27
- scope.add(fn);
28
- scope.dispose();
29
- scope.dispose();
30
- expect(fn).toHaveBeenCalledOnce();
31
- });
32
-
33
- it("effect() registers a reactive effect and its cleanup", () => {
34
- const scope = new Scope();
35
- const ran: number[] = [];
36
- scope.effect(() => {
37
- ran.push(1);
38
- });
39
- expect(ran).toHaveLength(1); // runs immediately
40
- scope.dispose();
41
- });
42
-
43
- it("fork() creates a child scope that disposes when parent disposes", () => {
44
- const parent = new Scope();
45
- const child = parent.fork();
46
- const childCleanup = vi.fn();
47
- child.add(childCleanup);
48
- parent.dispose();
49
- expect(childCleanup).toHaveBeenCalledOnce();
50
- });
51
-
52
- it("cleanup that throws does not prevent other cleanups from running", () => {
53
- const scope = new Scope();
54
- const ran: number[] = [];
55
- scope.add(() => { ran.push(1); });
56
- scope.add(() => { throw new Error("boom"); });
57
- scope.add(() => { ran.push(3); });
58
- expect(() => { scope.dispose(); }).toThrow();
59
- expect(ran).toEqual([1, 3]);
60
- });
61
-
62
- it("grandchild scopes: parent.fork().fork() — disposing parent disposes all descendants", () => {
63
- const parent = new Scope();
64
- const child = parent.fork();
65
- const grandchild = child.fork();
66
- const grandchildFn = vi.fn();
67
- const childFn = vi.fn();
68
- grandchild.add(grandchildFn);
69
- child.add(childFn);
70
- parent.dispose();
71
- expect(childFn).toHaveBeenCalledOnce();
72
- expect(grandchildFn).toHaveBeenCalledOnce();
73
- });
74
-
75
- it("dispose() called during a cleanup does not crash", () => {
76
- const scope = new Scope();
77
- scope.add(() => {
78
- // calling dispose() again during a cleanup — should be safe (no-op, cleanups already cleared)
79
- scope.dispose();
80
- });
81
- expect(() => { scope.dispose(); }).not.toThrow();
82
- });
83
-
84
- it("cleanup added inside a cleanup is NOT called in the same dispose cycle", () => {
85
- const scope = new Scope();
86
- const inner = vi.fn();
87
- scope.add(() => {
88
- scope.add(inner);
89
- });
90
- scope.dispose();
91
- expect(inner).not.toHaveBeenCalled();
92
- });
93
-
94
- it("multiple throwing cleanups — AggregateError is thrown with all errors", () => {
95
- const scope = new Scope();
96
- scope.add(() => { throw new Error("error 1"); });
97
- scope.add(() => { throw new Error("error 2"); });
98
- expect(() => { scope.dispose(); }).toThrow(AggregateError);
99
- try {
100
- const s2 = new Scope();
101
- s2.add(() => { throw new Error("e1"); });
102
- s2.add(() => { throw new Error("e2"); });
103
- s2.dispose();
104
- } catch (err) {
105
- expect(err).toBeInstanceOf(AggregateError);
106
- expect((err as AggregateError).errors).toHaveLength(2);
107
- }
108
- });
109
-
110
- it("fork() child can be disposed independently before parent", () => {
111
- const parent = new Scope();
112
- const child = parent.fork();
113
- const childFn = vi.fn();
114
- child.add(childFn);
115
- child.dispose();
116
- expect(childFn).toHaveBeenCalledOnce();
117
- // parent dispose should not throw even though child is already disposed
118
- expect(() => { parent.dispose(); }).not.toThrow();
119
- });
120
- });
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "./dist",
5
- "rootDir": "./src"
6
- },
7
- "include": ["src"]
8
- }