@hedystia/view 2.1.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.
Files changed (102) hide show
  1. package/dist/constants.cjs +13 -0
  2. package/dist/constants.cjs.map +1 -0
  3. package/dist/constants.mjs +13 -0
  4. package/dist/constants.mjs.map +1 -0
  5. package/dist/context/context.cjs +51 -0
  6. package/dist/context/context.cjs.map +1 -0
  7. package/dist/context/context.d.cts +25 -0
  8. package/dist/context/context.d.mts +25 -0
  9. package/dist/context/context.mjs +50 -0
  10. package/dist/context/context.mjs.map +1 -0
  11. package/dist/fetch/resource.cjs +89 -0
  12. package/dist/fetch/resource.cjs.map +1 -0
  13. package/dist/fetch/resource.d.cts +14 -0
  14. package/dist/fetch/resource.d.mts +14 -0
  15. package/dist/fetch/resource.mjs +88 -0
  16. package/dist/fetch/resource.mjs.map +1 -0
  17. package/dist/index.cjs +58 -0
  18. package/dist/index.d.cts +15 -0
  19. package/dist/index.d.mts +15 -0
  20. package/dist/index.mjs +14 -0
  21. package/dist/jsx/element.cjs +201 -0
  22. package/dist/jsx/element.cjs.map +1 -0
  23. package/dist/jsx/element.d.cts +48 -0
  24. package/dist/jsx/element.d.mts +48 -0
  25. package/dist/jsx/element.mjs +199 -0
  26. package/dist/jsx/element.mjs.map +1 -0
  27. package/dist/jsx-dev-runtime.cjs +40 -0
  28. package/dist/jsx-dev-runtime.cjs.map +1 -0
  29. package/dist/jsx-dev-runtime.d.cts +21 -0
  30. package/dist/jsx-dev-runtime.d.mts +21 -0
  31. package/dist/jsx-dev-runtime.mjs +36 -0
  32. package/dist/jsx-dev-runtime.mjs.map +1 -0
  33. package/dist/jsx-runtime.cjs +5 -0
  34. package/dist/jsx-runtime.d.cts +3 -0
  35. package/dist/jsx-runtime.d.mts +3 -0
  36. package/dist/jsx-runtime.mjs +2 -0
  37. package/dist/jsx.d.cts +942 -0
  38. package/dist/jsx.d.mts +942 -0
  39. package/dist/lifecycle/hooks.cjs +56 -0
  40. package/dist/lifecycle/hooks.cjs.map +1 -0
  41. package/dist/lifecycle/hooks.d.cts +37 -0
  42. package/dist/lifecycle/hooks.d.mts +37 -0
  43. package/dist/lifecycle/hooks.mjs +54 -0
  44. package/dist/lifecycle/hooks.mjs.map +1 -0
  45. package/dist/render/engine.cjs +52 -0
  46. package/dist/render/engine.cjs.map +1 -0
  47. package/dist/render/engine.d.cts +31 -0
  48. package/dist/render/engine.d.mts +31 -0
  49. package/dist/render/engine.mjs +51 -0
  50. package/dist/render/engine.mjs.map +1 -0
  51. package/dist/render/flow.cjs +286 -0
  52. package/dist/render/flow.cjs.map +1 -0
  53. package/dist/render/flow.d.cts +64 -0
  54. package/dist/render/flow.d.mts +64 -0
  55. package/dist/render/flow.mjs +279 -0
  56. package/dist/render/flow.mjs.map +1 -0
  57. package/dist/scheduler/scheduler.cjs +61 -0
  58. package/dist/scheduler/scheduler.cjs.map +1 -0
  59. package/dist/scheduler/scheduler.d.cts +31 -0
  60. package/dist/scheduler/scheduler.d.mts +31 -0
  61. package/dist/scheduler/scheduler.mjs +59 -0
  62. package/dist/scheduler/scheduler.mjs.map +1 -0
  63. package/dist/signal/signal.cjs +387 -0
  64. package/dist/signal/signal.cjs.map +1 -0
  65. package/dist/signal/signal.d.cts +44 -0
  66. package/dist/signal/signal.d.mts +44 -0
  67. package/dist/signal/signal.mjs +370 -0
  68. package/dist/signal/signal.mjs.map +1 -0
  69. package/dist/store/index.cjs +1 -0
  70. package/dist/store/index.mjs +2 -0
  71. package/dist/store/store.cjs +94 -0
  72. package/dist/store/store.cjs.map +1 -0
  73. package/dist/store/store.d.cts +22 -0
  74. package/dist/store/store.d.mts +22 -0
  75. package/dist/store/store.mjs +91 -0
  76. package/dist/store/store.mjs.map +1 -0
  77. package/dist/style/computed.cjs +65 -0
  78. package/dist/style/computed.cjs.map +1 -0
  79. package/dist/style/computed.d.cts +18 -0
  80. package/dist/style/computed.d.mts +18 -0
  81. package/dist/style/computed.mjs +63 -0
  82. package/dist/style/computed.mjs.map +1 -0
  83. package/dist/text/text.cjs +74 -0
  84. package/dist/text/text.cjs.map +1 -0
  85. package/dist/text/text.d.cts +31 -0
  86. package/dist/text/text.d.mts +31 -0
  87. package/dist/text/text.mjs +72 -0
  88. package/dist/text/text.mjs.map +1 -0
  89. package/dist/types.d.cts +185 -0
  90. package/dist/types.d.mts +185 -0
  91. package/dist/utils/index.cjs +34 -0
  92. package/dist/utils/index.cjs.map +1 -0
  93. package/dist/utils/index.mjs +33 -0
  94. package/dist/utils/index.mjs.map +1 -0
  95. package/dist/watch/watcher.cjs +71 -0
  96. package/dist/watch/watcher.cjs.map +1 -0
  97. package/dist/watch/watcher.d.cts +17 -0
  98. package/dist/watch/watcher.d.mts +17 -0
  99. package/dist/watch/watcher.mjs +70 -0
  100. package/dist/watch/watcher.mjs.map +1 -0
  101. package/package.json +34 -0
  102. package/readme.md +395 -0
@@ -0,0 +1,56 @@
1
+ const require_signal = require("../signal/signal.cjs");
2
+ //#region src/lifecycle/hooks.ts
3
+ /**
4
+ * Component lifecycle hooks for @hedystia/view
5
+ *
6
+ * Provides onMount, onCleanup, and onReady hooks for component lifecycle.
7
+ */
8
+ const currentOwner = null;
9
+ /**
10
+ * Register a callback to run when the component mounts
11
+ * @param {() => void | (() => void)} fn - The mount callback, optionally returning cleanup
12
+ * @example
13
+ * onMount(() => {
14
+ * console.log("mounted");
15
+ * return () => console.log("unmounted");
16
+ * });
17
+ */
18
+ function onMount(fn) {
19
+ if (currentOwner === null) {
20
+ require_signal.createRoot(() => {
21
+ const result = fn();
22
+ if (typeof result === "function") require_signal.onCleanup(result);
23
+ });
24
+ return;
25
+ }
26
+ const result = fn();
27
+ if (typeof result === "function") require_signal.onCleanup(result);
28
+ }
29
+ /**
30
+ * Register a callback to run when the component unmounts
31
+ * @param {() => void} fn - The cleanup callback
32
+ * @example
33
+ * onCleanup(() => {
34
+ * console.log("cleaning up");
35
+ * });
36
+ */
37
+ function onCleanup(fn) {
38
+ require_signal.onCleanup(fn);
39
+ }
40
+ /**
41
+ * Register a callback to run when the component is ready (after first render)
42
+ * @param {() => void} fn - The ready callback
43
+ * @example
44
+ * onReady(() => {
45
+ * console.log("component is ready");
46
+ * });
47
+ */
48
+ function onReady(fn) {
49
+ queueMicrotask(fn);
50
+ }
51
+ //#endregion
52
+ exports.onCleanup = onCleanup;
53
+ exports.onMount = onMount;
54
+ exports.onReady = onReady;
55
+
56
+ //# sourceMappingURL=hooks.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.cjs","names":[],"sources":["../../src/lifecycle/hooks.ts"],"sourcesContent":["/**\n * Component lifecycle hooks for @hedystia/view\n *\n * Provides onMount, onCleanup, and onReady hooks for component lifecycle.\n */\n\nimport { createRoot, onCleanup as signalOnCleanup } from \"../signal\";\nimport type { Owner } from \"../types\";\n\nconst currentOwner: Owner | null = null;\n\n/**\n * Register a callback to run when the component mounts\n * @param {() => void | (() => void)} fn - The mount callback, optionally returning cleanup\n * @example\n * onMount(() => {\n * console.log(\"mounted\");\n * return () => console.log(\"unmounted\");\n * });\n */\nexport function onMount(fn: () => undefined | (() => void)): void {\n if (currentOwner === null) {\n createRoot(() => {\n const result = fn();\n if (typeof result === \"function\") {\n signalOnCleanup(result);\n }\n });\n return;\n }\n\n const result = fn();\n if (typeof result === \"function\") {\n signalOnCleanup(result);\n }\n}\n\n/**\n * Register a callback to run when the component unmounts\n * @param {() => void} fn - The cleanup callback\n * @example\n * onCleanup(() => {\n * console.log(\"cleaning up\");\n * });\n */\nexport function onCleanup(fn: () => void): void {\n signalOnCleanup(fn);\n}\n\n/**\n * Register a callback to run when the component is ready (after first render)\n * @param {() => void} fn - The ready callback\n * @example\n * onReady(() => {\n * console.log(\"component is ready\");\n * });\n */\nexport function onReady(fn: () => void): void {\n queueMicrotask(fn);\n}\n"],"mappings":";;;;;;;AASA,MAAM,eAA6B;;;;;;;;;;AAWnC,SAAgB,QAAQ,IAA0C;AAChE,KAAI,iBAAiB,MAAM;AACzB,iBAAA,iBAAiB;GACf,MAAM,SAAS,IAAI;AACnB,OAAI,OAAO,WAAW,WACpB,gBAAA,UAAgB,OAAO;IAEzB;AACF;;CAGF,MAAM,SAAS,IAAI;AACnB,KAAI,OAAO,WAAW,WACpB,gBAAA,UAAgB,OAAO;;;;;;;;;;AAY3B,SAAgB,UAAU,IAAsB;AAC9C,gBAAA,UAAgB,GAAG;;;;;;;;;;AAWrB,SAAgB,QAAQ,IAAsB;AAC5C,gBAAe,GAAG"}
@@ -0,0 +1,37 @@
1
+ //#region src/lifecycle/hooks.d.ts
2
+ /**
3
+ * Component lifecycle hooks for @hedystia/view
4
+ *
5
+ * Provides onMount, onCleanup, and onReady hooks for component lifecycle.
6
+ */
7
+ /**
8
+ * Register a callback to run when the component mounts
9
+ * @param {() => void | (() => void)} fn - The mount callback, optionally returning cleanup
10
+ * @example
11
+ * onMount(() => {
12
+ * console.log("mounted");
13
+ * return () => console.log("unmounted");
14
+ * });
15
+ */
16
+ declare function onMount(fn: () => undefined | (() => void)): void;
17
+ /**
18
+ * Register a callback to run when the component unmounts
19
+ * @param {() => void} fn - The cleanup callback
20
+ * @example
21
+ * onCleanup(() => {
22
+ * console.log("cleaning up");
23
+ * });
24
+ */
25
+ declare function onCleanup(fn: () => void): void;
26
+ /**
27
+ * Register a callback to run when the component is ready (after first render)
28
+ * @param {() => void} fn - The ready callback
29
+ * @example
30
+ * onReady(() => {
31
+ * console.log("component is ready");
32
+ * });
33
+ */
34
+ declare function onReady(fn: () => void): void;
35
+ //#endregion
36
+ export { onCleanup, onMount, onReady };
37
+ //# sourceMappingURL=hooks.d.cts.map
@@ -0,0 +1,37 @@
1
+ //#region src/lifecycle/hooks.d.ts
2
+ /**
3
+ * Component lifecycle hooks for @hedystia/view
4
+ *
5
+ * Provides onMount, onCleanup, and onReady hooks for component lifecycle.
6
+ */
7
+ /**
8
+ * Register a callback to run when the component mounts
9
+ * @param {() => void | (() => void)} fn - The mount callback, optionally returning cleanup
10
+ * @example
11
+ * onMount(() => {
12
+ * console.log("mounted");
13
+ * return () => console.log("unmounted");
14
+ * });
15
+ */
16
+ declare function onMount(fn: () => undefined | (() => void)): void;
17
+ /**
18
+ * Register a callback to run when the component unmounts
19
+ * @param {() => void} fn - The cleanup callback
20
+ * @example
21
+ * onCleanup(() => {
22
+ * console.log("cleaning up");
23
+ * });
24
+ */
25
+ declare function onCleanup(fn: () => void): void;
26
+ /**
27
+ * Register a callback to run when the component is ready (after first render)
28
+ * @param {() => void} fn - The ready callback
29
+ * @example
30
+ * onReady(() => {
31
+ * console.log("component is ready");
32
+ * });
33
+ */
34
+ declare function onReady(fn: () => void): void;
35
+ //#endregion
36
+ export { onCleanup, onMount, onReady };
37
+ //# sourceMappingURL=hooks.d.mts.map
@@ -0,0 +1,54 @@
1
+ import { createRoot, onCleanup as onCleanup$1 } from "../signal/signal.mjs";
2
+ //#region src/lifecycle/hooks.ts
3
+ /**
4
+ * Component lifecycle hooks for @hedystia/view
5
+ *
6
+ * Provides onMount, onCleanup, and onReady hooks for component lifecycle.
7
+ */
8
+ const currentOwner = null;
9
+ /**
10
+ * Register a callback to run when the component mounts
11
+ * @param {() => void | (() => void)} fn - The mount callback, optionally returning cleanup
12
+ * @example
13
+ * onMount(() => {
14
+ * console.log("mounted");
15
+ * return () => console.log("unmounted");
16
+ * });
17
+ */
18
+ function onMount(fn) {
19
+ if (currentOwner === null) {
20
+ createRoot(() => {
21
+ const result = fn();
22
+ if (typeof result === "function") onCleanup$1(result);
23
+ });
24
+ return;
25
+ }
26
+ const result = fn();
27
+ if (typeof result === "function") onCleanup$1(result);
28
+ }
29
+ /**
30
+ * Register a callback to run when the component unmounts
31
+ * @param {() => void} fn - The cleanup callback
32
+ * @example
33
+ * onCleanup(() => {
34
+ * console.log("cleaning up");
35
+ * });
36
+ */
37
+ function onCleanup(fn) {
38
+ onCleanup$1(fn);
39
+ }
40
+ /**
41
+ * Register a callback to run when the component is ready (after first render)
42
+ * @param {() => void} fn - The ready callback
43
+ * @example
44
+ * onReady(() => {
45
+ * console.log("component is ready");
46
+ * });
47
+ */
48
+ function onReady(fn) {
49
+ queueMicrotask(fn);
50
+ }
51
+ //#endregion
52
+ export { onCleanup, onMount, onReady };
53
+
54
+ //# sourceMappingURL=hooks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.mjs","names":[],"sources":["../../src/lifecycle/hooks.ts"],"sourcesContent":["/**\n * Component lifecycle hooks for @hedystia/view\n *\n * Provides onMount, onCleanup, and onReady hooks for component lifecycle.\n */\n\nimport { createRoot, onCleanup as signalOnCleanup } from \"../signal\";\nimport type { Owner } from \"../types\";\n\nconst currentOwner: Owner | null = null;\n\n/**\n * Register a callback to run when the component mounts\n * @param {() => void | (() => void)} fn - The mount callback, optionally returning cleanup\n * @example\n * onMount(() => {\n * console.log(\"mounted\");\n * return () => console.log(\"unmounted\");\n * });\n */\nexport function onMount(fn: () => undefined | (() => void)): void {\n if (currentOwner === null) {\n createRoot(() => {\n const result = fn();\n if (typeof result === \"function\") {\n signalOnCleanup(result);\n }\n });\n return;\n }\n\n const result = fn();\n if (typeof result === \"function\") {\n signalOnCleanup(result);\n }\n}\n\n/**\n * Register a callback to run when the component unmounts\n * @param {() => void} fn - The cleanup callback\n * @example\n * onCleanup(() => {\n * console.log(\"cleaning up\");\n * });\n */\nexport function onCleanup(fn: () => void): void {\n signalOnCleanup(fn);\n}\n\n/**\n * Register a callback to run when the component is ready (after first render)\n * @param {() => void} fn - The ready callback\n * @example\n * onReady(() => {\n * console.log(\"component is ready\");\n * });\n */\nexport function onReady(fn: () => void): void {\n queueMicrotask(fn);\n}\n"],"mappings":";;;;;;;AASA,MAAM,eAA6B;;;;;;;;;;AAWnC,SAAgB,QAAQ,IAA0C;AAChE,KAAI,iBAAiB,MAAM;AACzB,mBAAiB;GACf,MAAM,SAAS,IAAI;AACnB,OAAI,OAAO,WAAW,WACpB,aAAgB,OAAO;IAEzB;AACF;;CAGF,MAAM,SAAS,IAAI;AACnB,KAAI,OAAO,WAAW,WACpB,aAAgB,OAAO;;;;;;;;;;AAY3B,SAAgB,UAAU,IAAsB;AAC9C,aAAgB,GAAG;;;;;;;;;;AAWrB,SAAgB,QAAQ,IAAsB;AAC5C,gBAAe,GAAG"}
@@ -0,0 +1,52 @@
1
+ const require_signal = require("../signal/signal.cjs");
2
+ //#region src/render/engine.ts
3
+ /**
4
+ * Render engine for @hedystia/view
5
+ *
6
+ * Mounts components to the DOM and manages the render cycle.
7
+ */
8
+ const currentOwner = null;
9
+ /**
10
+ * Mount a component to a target DOM element
11
+ * @param {Component<{}>} component - The component to mount
12
+ * @param {HTMLElement} target - The target element
13
+ * @returns {ViewApp} The application instance
14
+ * @example
15
+ * const app = mount(App, document.getElementById("root")!);
16
+ * app.dispose();
17
+ */
18
+ function mount(component, target) {
19
+ target.innerHTML = "";
20
+ let dispose = null;
21
+ let root = null;
22
+ require_signal.createRoot((disposeFn) => {
23
+ dispose = disposeFn;
24
+ root = currentOwner;
25
+ const element = component({});
26
+ if (element) target.appendChild(element);
27
+ });
28
+ return {
29
+ dispose: () => {
30
+ if (dispose) dispose();
31
+ target.innerHTML = "";
32
+ },
33
+ root
34
+ };
35
+ }
36
+ /**
37
+ * Render a component to a string (for SSR)
38
+ * @param {Component<{}>} component - The component to render
39
+ * @returns {string} The rendered HTML string
40
+ * @example
41
+ * const html = renderToString(App);
42
+ */
43
+ function renderToString(component) {
44
+ const element = component({});
45
+ if (element instanceof HTMLElement) return element.outerHTML;
46
+ return "";
47
+ }
48
+ //#endregion
49
+ exports.mount = mount;
50
+ exports.renderToString = renderToString;
51
+
52
+ //# sourceMappingURL=engine.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.cjs","names":[],"sources":["../../src/render/engine.ts"],"sourcesContent":["/**\n * Render engine for @hedystia/view\n *\n * Mounts components to the DOM and manages the render cycle.\n */\n\nimport { createRoot } from \"../signal\";\nimport type { Component, Owner } from \"../types\";\n\n/**\n * Application instance returned by mount\n */\nexport interface ViewApp {\n dispose: () => void;\n root: Owner | null;\n}\n\nconst currentOwner: Owner | null = null;\n\n/**\n * Mount a component to a target DOM element\n * @param {Component<{}>} component - The component to mount\n * @param {HTMLElement} target - The target element\n * @returns {ViewApp} The application instance\n * @example\n * const app = mount(App, document.getElementById(\"root\")!);\n * app.dispose();\n */\nexport function mount(component: Component<{}>, target: HTMLElement): ViewApp {\n target.innerHTML = \"\";\n\n let dispose: (() => void) | null = null;\n let root: Owner | null = null;\n\n createRoot((disposeFn) => {\n dispose = disposeFn;\n root = currentOwner;\n const element = component({}) as HTMLElement;\n if (element) {\n target.appendChild(element);\n }\n });\n\n return {\n dispose: () => {\n if (dispose) {\n dispose();\n }\n target.innerHTML = \"\";\n },\n root,\n };\n}\n\n/**\n * Render a component to a string (for SSR)\n * @param {Component<{}>} component - The component to render\n * @returns {string} The rendered HTML string\n * @example\n * const html = renderToString(App);\n */\nexport function renderToString(component: Component<{}>): string {\n const element = component({});\n if (element instanceof HTMLElement) {\n return element.outerHTML;\n }\n return \"\";\n}\n"],"mappings":";;;;;;;AAiBA,MAAM,eAA6B;;;;;;;;;;AAWnC,SAAgB,MAAM,WAA0B,QAA8B;AAC5E,QAAO,YAAY;CAEnB,IAAI,UAA+B;CACnC,IAAI,OAAqB;AAEzB,gBAAA,YAAY,cAAc;AACxB,YAAU;AACV,SAAO;EACP,MAAM,UAAU,UAAU,EAAE,CAAC;AAC7B,MAAI,QACF,QAAO,YAAY,QAAQ;GAE7B;AAEF,QAAO;EACL,eAAe;AACb,OAAI,QACF,UAAS;AAEX,UAAO,YAAY;;EAErB;EACD;;;;;;;;;AAUH,SAAgB,eAAe,WAAkC;CAC/D,MAAM,UAAU,UAAU,EAAE,CAAC;AAC7B,KAAI,mBAAmB,YACrB,QAAO,QAAQ;AAEjB,QAAO"}
@@ -0,0 +1,31 @@
1
+ import { Component, Owner } from "../types.cjs";
2
+
3
+ //#region src/render/engine.d.ts
4
+ /**
5
+ * Application instance returned by mount
6
+ */
7
+ interface ViewApp {
8
+ dispose: () => void;
9
+ root: Owner | null;
10
+ }
11
+ /**
12
+ * Mount a component to a target DOM element
13
+ * @param {Component<{}>} component - The component to mount
14
+ * @param {HTMLElement} target - The target element
15
+ * @returns {ViewApp} The application instance
16
+ * @example
17
+ * const app = mount(App, document.getElementById("root")!);
18
+ * app.dispose();
19
+ */
20
+ declare function mount(component: Component<{}>, target: HTMLElement): ViewApp;
21
+ /**
22
+ * Render a component to a string (for SSR)
23
+ * @param {Component<{}>} component - The component to render
24
+ * @returns {string} The rendered HTML string
25
+ * @example
26
+ * const html = renderToString(App);
27
+ */
28
+ declare function renderToString(component: Component<{}>): string;
29
+ //#endregion
30
+ export { ViewApp, mount, renderToString };
31
+ //# sourceMappingURL=engine.d.cts.map
@@ -0,0 +1,31 @@
1
+ import { Component, Owner } from "../types.mjs";
2
+
3
+ //#region src/render/engine.d.ts
4
+ /**
5
+ * Application instance returned by mount
6
+ */
7
+ interface ViewApp {
8
+ dispose: () => void;
9
+ root: Owner | null;
10
+ }
11
+ /**
12
+ * Mount a component to a target DOM element
13
+ * @param {Component<{}>} component - The component to mount
14
+ * @param {HTMLElement} target - The target element
15
+ * @returns {ViewApp} The application instance
16
+ * @example
17
+ * const app = mount(App, document.getElementById("root")!);
18
+ * app.dispose();
19
+ */
20
+ declare function mount(component: Component<{}>, target: HTMLElement): ViewApp;
21
+ /**
22
+ * Render a component to a string (for SSR)
23
+ * @param {Component<{}>} component - The component to render
24
+ * @returns {string} The rendered HTML string
25
+ * @example
26
+ * const html = renderToString(App);
27
+ */
28
+ declare function renderToString(component: Component<{}>): string;
29
+ //#endregion
30
+ export { ViewApp, mount, renderToString };
31
+ //# sourceMappingURL=engine.d.mts.map
@@ -0,0 +1,51 @@
1
+ import { createRoot } from "../signal/signal.mjs";
2
+ //#region src/render/engine.ts
3
+ /**
4
+ * Render engine for @hedystia/view
5
+ *
6
+ * Mounts components to the DOM and manages the render cycle.
7
+ */
8
+ const currentOwner = null;
9
+ /**
10
+ * Mount a component to a target DOM element
11
+ * @param {Component<{}>} component - The component to mount
12
+ * @param {HTMLElement} target - The target element
13
+ * @returns {ViewApp} The application instance
14
+ * @example
15
+ * const app = mount(App, document.getElementById("root")!);
16
+ * app.dispose();
17
+ */
18
+ function mount(component, target) {
19
+ target.innerHTML = "";
20
+ let dispose = null;
21
+ let root = null;
22
+ createRoot((disposeFn) => {
23
+ dispose = disposeFn;
24
+ root = currentOwner;
25
+ const element = component({});
26
+ if (element) target.appendChild(element);
27
+ });
28
+ return {
29
+ dispose: () => {
30
+ if (dispose) dispose();
31
+ target.innerHTML = "";
32
+ },
33
+ root
34
+ };
35
+ }
36
+ /**
37
+ * Render a component to a string (for SSR)
38
+ * @param {Component<{}>} component - The component to render
39
+ * @returns {string} The rendered HTML string
40
+ * @example
41
+ * const html = renderToString(App);
42
+ */
43
+ function renderToString(component) {
44
+ const element = component({});
45
+ if (element instanceof HTMLElement) return element.outerHTML;
46
+ return "";
47
+ }
48
+ //#endregion
49
+ export { mount, renderToString };
50
+
51
+ //# sourceMappingURL=engine.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.mjs","names":[],"sources":["../../src/render/engine.ts"],"sourcesContent":["/**\n * Render engine for @hedystia/view\n *\n * Mounts components to the DOM and manages the render cycle.\n */\n\nimport { createRoot } from \"../signal\";\nimport type { Component, Owner } from \"../types\";\n\n/**\n * Application instance returned by mount\n */\nexport interface ViewApp {\n dispose: () => void;\n root: Owner | null;\n}\n\nconst currentOwner: Owner | null = null;\n\n/**\n * Mount a component to a target DOM element\n * @param {Component<{}>} component - The component to mount\n * @param {HTMLElement} target - The target element\n * @returns {ViewApp} The application instance\n * @example\n * const app = mount(App, document.getElementById(\"root\")!);\n * app.dispose();\n */\nexport function mount(component: Component<{}>, target: HTMLElement): ViewApp {\n target.innerHTML = \"\";\n\n let dispose: (() => void) | null = null;\n let root: Owner | null = null;\n\n createRoot((disposeFn) => {\n dispose = disposeFn;\n root = currentOwner;\n const element = component({}) as HTMLElement;\n if (element) {\n target.appendChild(element);\n }\n });\n\n return {\n dispose: () => {\n if (dispose) {\n dispose();\n }\n target.innerHTML = \"\";\n },\n root,\n };\n}\n\n/**\n * Render a component to a string (for SSR)\n * @param {Component<{}>} component - The component to render\n * @returns {string} The rendered HTML string\n * @example\n * const html = renderToString(App);\n */\nexport function renderToString(component: Component<{}>): string {\n const element = component({});\n if (element instanceof HTMLElement) {\n return element.outerHTML;\n }\n return \"\";\n}\n"],"mappings":";;;;;;;AAiBA,MAAM,eAA6B;;;;;;;;;;AAWnC,SAAgB,MAAM,WAA0B,QAA8B;AAC5E,QAAO,YAAY;CAEnB,IAAI,UAA+B;CACnC,IAAI,OAAqB;AAEzB,aAAY,cAAc;AACxB,YAAU;AACV,SAAO;EACP,MAAM,UAAU,UAAU,EAAE,CAAC;AAC7B,MAAI,QACF,QAAO,YAAY,QAAQ;GAE7B;AAEF,QAAO;EACL,eAAe;AACb,OAAI,QACF,UAAS;AAEX,UAAO,YAAY;;EAErB;EACD;;;;;;;;;AAUH,SAAgB,eAAe,WAAkC;CAC/D,MAAM,UAAU,UAAU,EAAE,CAAC;AAC7B,KAAI,mBAAmB,YACrB,QAAO,QAAQ;AAEjB,QAAO"}
@@ -0,0 +1,286 @@
1
+ const require_signal = require("../signal/signal.cjs");
2
+ const require_scheduler = require("../scheduler/scheduler.cjs");
3
+ //#region src/render/flow.ts
4
+ /**
5
+ * Flow components for @hedystia/view
6
+ *
7
+ * Provides Show, For, Index, Switch, Match, Portal, Suspense, ErrorBoundary.
8
+ */
9
+ /**
10
+ * Conditionally render children based on a condition
11
+ */
12
+ function Show(props) {
13
+ const container = document.createComment("show");
14
+ let rendered = null;
15
+ let fallbackNode = null;
16
+ const getCondition = () => {
17
+ return typeof props.when === "function" ? props.when() : props.when;
18
+ };
19
+ const runEffect = () => {
20
+ if (getCondition()) {
21
+ if (fallbackNode) {
22
+ fallbackNode.parentNode?.removeChild(fallbackNode);
23
+ fallbackNode = null;
24
+ }
25
+ if (!rendered && props.children) {
26
+ rendered = typeof props.children === "function" ? props.children() : props.children;
27
+ if (rendered && !rendered.parentNode) if (container.parentNode) container.parentNode.insertBefore(rendered, container.nextSibling);
28
+ else queueMicrotask(() => {
29
+ if (rendered && !rendered.parentNode && container.parentNode) container.parentNode.insertBefore(rendered, container.nextSibling);
30
+ });
31
+ }
32
+ } else {
33
+ if (rendered) {
34
+ rendered.parentNode?.removeChild(rendered);
35
+ rendered = null;
36
+ }
37
+ if (props.fallback && !fallbackNode) {
38
+ fallbackNode = typeof props.fallback === "function" ? props.fallback() : props.fallback;
39
+ if (fallbackNode && !fallbackNode.parentNode) if (container.parentNode) container.parentNode.insertBefore(fallbackNode, container.nextSibling);
40
+ else queueMicrotask(() => {
41
+ if (fallbackNode && !fallbackNode.parentNode && container.parentNode) container.parentNode.insertBefore(fallbackNode, container.nextSibling);
42
+ });
43
+ }
44
+ }
45
+ };
46
+ require_signal.val(require_signal.memo(() => {
47
+ runEffect();
48
+ return true;
49
+ }));
50
+ return container;
51
+ }
52
+ /**
53
+ * Render a list with keyed items for efficient updates
54
+ */
55
+ function For(props) {
56
+ const container = document.createComment("for");
57
+ const nodes = /* @__PURE__ */ new Map();
58
+ const order = [];
59
+ const getEach = () => {
60
+ return typeof props.each === "function" ? props.each() : props.each;
61
+ };
62
+ const runEffect = () => {
63
+ const items = getEach();
64
+ const newOrder = [];
65
+ const newNodes = /* @__PURE__ */ new Map();
66
+ for (let i = 0; i < items.length; i++) {
67
+ const item = items[i];
68
+ const key = props.key ? props.key(item) : i;
69
+ newOrder.push(key);
70
+ if (nodes.has(key)) newNodes.set(key, nodes.get(key));
71
+ else {
72
+ const itemSig = require_signal.sig(item);
73
+ const indexSig = require_signal.sig(i);
74
+ const child = props.children(() => require_signal.val(itemSig), () => require_signal.val(indexSig));
75
+ newNodes.set(key, child);
76
+ }
77
+ }
78
+ for (const key of order) if (!newNodes.has(key)) {
79
+ const node = nodes.get(key);
80
+ if (node?.parentNode) node.parentNode.removeChild(node);
81
+ }
82
+ const insertNodes = () => {
83
+ if (container.parentNode) {
84
+ let prevSibling = container.nextSibling;
85
+ for (const key of newOrder) {
86
+ const node = newNodes.get(key);
87
+ if (!nodes.has(key) && !node.parentNode) container.parentNode.insertBefore(node, prevSibling);
88
+ else if (prevSibling !== node) container.parentNode.insertBefore(node, prevSibling);
89
+ prevSibling = node.nextSibling;
90
+ }
91
+ }
92
+ };
93
+ if (container.parentNode) insertNodes();
94
+ else queueMicrotask(insertNodes);
95
+ order.length = 0;
96
+ order.push(...newOrder);
97
+ nodes.clear();
98
+ for (const [k, v] of newNodes) nodes.set(k, v);
99
+ };
100
+ require_signal.val(require_signal.memo(() => {
101
+ runEffect();
102
+ return true;
103
+ }));
104
+ return container;
105
+ }
106
+ /**
107
+ * Render a list with index-based tracking
108
+ */
109
+ function Index(props) {
110
+ const container = document.createComment("index");
111
+ const nodes = [];
112
+ const getEach = () => {
113
+ return typeof props.each === "function" ? props.each() : props.each;
114
+ };
115
+ const runEffect = () => {
116
+ const items = getEach();
117
+ while (nodes.length > items.length) {
118
+ const node = nodes.pop();
119
+ if (node?.parentNode) node.parentNode.removeChild(node);
120
+ }
121
+ const insertNodes = () => {
122
+ if (container.parentNode) {
123
+ for (let i = 0; i < items.length; i++) if (nodes[i] === void 0) {
124
+ const itemSig = require_signal.sig(items[i]);
125
+ const child = props.children(() => require_signal.val(itemSig), i);
126
+ nodes[i] = child;
127
+ if (!child.parentNode) container.parentNode.insertBefore(child, container.nextSibling);
128
+ }
129
+ }
130
+ };
131
+ if (container.parentNode) insertNodes();
132
+ else queueMicrotask(insertNodes);
133
+ };
134
+ require_signal.val(require_signal.memo(() => {
135
+ runEffect();
136
+ return true;
137
+ }));
138
+ return container;
139
+ }
140
+ /**
141
+ * Switch component for mutually exclusive conditions
142
+ */
143
+ function Switch(props) {
144
+ const container = document.createComment("switch");
145
+ let rendered = null;
146
+ const evaluate = () => {
147
+ const children = props.children;
148
+ if (Array.isArray(children)) {
149
+ for (const child of children) if (child && child._matchWhen) {
150
+ const when = child._matchWhen;
151
+ if (typeof when === "function" ? when() : when) return child._matchChildren;
152
+ }
153
+ }
154
+ return props.fallback;
155
+ };
156
+ const runEffect = () => {
157
+ const content = evaluate();
158
+ if (rendered) {
159
+ rendered.parentNode?.removeChild(rendered);
160
+ rendered = null;
161
+ }
162
+ if (content) {
163
+ rendered = typeof content === "function" ? content() : content;
164
+ if (rendered && !rendered.parentNode) {
165
+ const insertNode = () => {
166
+ if (rendered && container.parentNode && !rendered.parentNode) container.parentNode.insertBefore(rendered, container.nextSibling);
167
+ };
168
+ if (container.parentNode) insertNode();
169
+ else queueMicrotask(insertNode);
170
+ }
171
+ }
172
+ };
173
+ require_signal.val(require_signal.memo(() => {
174
+ runEffect();
175
+ return true;
176
+ }));
177
+ return container;
178
+ }
179
+ /**
180
+ * Match component for use inside Switch
181
+ */
182
+ function Match(props) {
183
+ const marker = document.createComment("match");
184
+ marker._matchWhen = typeof props.when === "function" ? props.when : () => props.when;
185
+ marker._matchChildren = props.children;
186
+ return marker;
187
+ }
188
+ /**
189
+ * Portal component for rendering outside the current DOM hierarchy
190
+ */
191
+ function Portal(props) {
192
+ const container = document.createComment("portal");
193
+ const mountPoint = props.mount || document.body;
194
+ let rendered = null;
195
+ require_signal.createRoot(() => {
196
+ rendered = typeof props.children === "function" ? props.children() : props.children;
197
+ if (rendered) mountPoint.appendChild(rendered);
198
+ require_signal.onCleanup(() => {
199
+ if (rendered && rendered.parentNode === mountPoint) mountPoint.removeChild(rendered);
200
+ });
201
+ });
202
+ return container;
203
+ }
204
+ /**
205
+ * Suspense component for async loading states
206
+ */
207
+ function Suspense(props) {
208
+ const container = document.createComment("suspense");
209
+ let rendered = null;
210
+ let fallbackNode = null;
211
+ require_scheduler.tick(() => {
212
+ try {
213
+ if (fallbackNode) {
214
+ container.parentNode?.removeChild(fallbackNode);
215
+ fallbackNode = null;
216
+ }
217
+ if (!rendered && props.children) {
218
+ rendered = typeof props.children === "function" ? props.children() : props.children;
219
+ if (rendered) container.parentNode?.insertBefore(rendered, container.nextSibling);
220
+ }
221
+ } catch {
222
+ if (rendered) {
223
+ container.parentNode?.removeChild(rendered);
224
+ rendered = null;
225
+ }
226
+ if (props.fallback && !fallbackNode) {
227
+ fallbackNode = typeof props.fallback === "function" ? props.fallback() : props.fallback;
228
+ if (fallbackNode) container.parentNode?.insertBefore(fallbackNode, container.nextSibling);
229
+ }
230
+ }
231
+ });
232
+ return container;
233
+ }
234
+ /**
235
+ * ErrorBoundary component for catching render errors
236
+ */
237
+ function ErrorBoundary(props) {
238
+ const container = document.createComment("error-boundary");
239
+ let rendered = null;
240
+ let error = null;
241
+ const reset = () => {
242
+ error = null;
243
+ if (rendered) {
244
+ container.parentNode?.removeChild(rendered);
245
+ rendered = null;
246
+ }
247
+ require_scheduler.tick(() => {
248
+ try {
249
+ rendered = typeof props.children === "function" ? props.children() : props.children;
250
+ if (rendered) container.parentNode?.insertBefore(rendered, container.nextSibling);
251
+ } catch (e) {
252
+ error = e instanceof Error ? e : new Error(String(e));
253
+ if (rendered) {
254
+ container.parentNode?.removeChild(rendered);
255
+ rendered = null;
256
+ }
257
+ const fallback = props.fallback(error, reset);
258
+ rendered = typeof fallback === "function" ? fallback() : fallback;
259
+ if (rendered) container.parentNode?.insertBefore(rendered, container.nextSibling);
260
+ }
261
+ });
262
+ };
263
+ require_scheduler.tick(() => {
264
+ try {
265
+ rendered = typeof props.children === "function" ? props.children() : props.children;
266
+ if (rendered) container.parentNode?.insertBefore(rendered, container.nextSibling);
267
+ } catch (e) {
268
+ error = e instanceof Error ? e : new Error(String(e));
269
+ const fallback = props.fallback(error, reset);
270
+ rendered = typeof fallback === "function" ? fallback() : fallback;
271
+ if (rendered) container.parentNode?.insertBefore(rendered, container.nextSibling);
272
+ }
273
+ });
274
+ return container;
275
+ }
276
+ //#endregion
277
+ exports.ErrorBoundary = ErrorBoundary;
278
+ exports.For = For;
279
+ exports.Index = Index;
280
+ exports.Match = Match;
281
+ exports.Portal = Portal;
282
+ exports.Show = Show;
283
+ exports.Suspense = Suspense;
284
+ exports.Switch = Switch;
285
+
286
+ //# sourceMappingURL=flow.cjs.map