@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.
- package/dist/constants.cjs +13 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.mjs +13 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/context/context.cjs +51 -0
- package/dist/context/context.cjs.map +1 -0
- package/dist/context/context.d.cts +25 -0
- package/dist/context/context.d.mts +25 -0
- package/dist/context/context.mjs +50 -0
- package/dist/context/context.mjs.map +1 -0
- package/dist/fetch/resource.cjs +89 -0
- package/dist/fetch/resource.cjs.map +1 -0
- package/dist/fetch/resource.d.cts +14 -0
- package/dist/fetch/resource.d.mts +14 -0
- package/dist/fetch/resource.mjs +88 -0
- package/dist/fetch/resource.mjs.map +1 -0
- package/dist/index.cjs +58 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.mts +15 -0
- package/dist/index.mjs +14 -0
- package/dist/jsx/element.cjs +201 -0
- package/dist/jsx/element.cjs.map +1 -0
- package/dist/jsx/element.d.cts +48 -0
- package/dist/jsx/element.d.mts +48 -0
- package/dist/jsx/element.mjs +199 -0
- package/dist/jsx/element.mjs.map +1 -0
- package/dist/jsx-dev-runtime.cjs +40 -0
- package/dist/jsx-dev-runtime.cjs.map +1 -0
- package/dist/jsx-dev-runtime.d.cts +21 -0
- package/dist/jsx-dev-runtime.d.mts +21 -0
- package/dist/jsx-dev-runtime.mjs +36 -0
- package/dist/jsx-dev-runtime.mjs.map +1 -0
- package/dist/jsx-runtime.cjs +5 -0
- package/dist/jsx-runtime.d.cts +3 -0
- package/dist/jsx-runtime.d.mts +3 -0
- package/dist/jsx-runtime.mjs +2 -0
- package/dist/jsx.d.cts +942 -0
- package/dist/jsx.d.mts +942 -0
- package/dist/lifecycle/hooks.cjs +56 -0
- package/dist/lifecycle/hooks.cjs.map +1 -0
- package/dist/lifecycle/hooks.d.cts +37 -0
- package/dist/lifecycle/hooks.d.mts +37 -0
- package/dist/lifecycle/hooks.mjs +54 -0
- package/dist/lifecycle/hooks.mjs.map +1 -0
- package/dist/render/engine.cjs +52 -0
- package/dist/render/engine.cjs.map +1 -0
- package/dist/render/engine.d.cts +31 -0
- package/dist/render/engine.d.mts +31 -0
- package/dist/render/engine.mjs +51 -0
- package/dist/render/engine.mjs.map +1 -0
- package/dist/render/flow.cjs +286 -0
- package/dist/render/flow.cjs.map +1 -0
- package/dist/render/flow.d.cts +64 -0
- package/dist/render/flow.d.mts +64 -0
- package/dist/render/flow.mjs +279 -0
- package/dist/render/flow.mjs.map +1 -0
- package/dist/scheduler/scheduler.cjs +61 -0
- package/dist/scheduler/scheduler.cjs.map +1 -0
- package/dist/scheduler/scheduler.d.cts +31 -0
- package/dist/scheduler/scheduler.d.mts +31 -0
- package/dist/scheduler/scheduler.mjs +59 -0
- package/dist/scheduler/scheduler.mjs.map +1 -0
- package/dist/signal/signal.cjs +387 -0
- package/dist/signal/signal.cjs.map +1 -0
- package/dist/signal/signal.d.cts +44 -0
- package/dist/signal/signal.d.mts +44 -0
- package/dist/signal/signal.mjs +370 -0
- package/dist/signal/signal.mjs.map +1 -0
- package/dist/store/index.cjs +1 -0
- package/dist/store/index.mjs +2 -0
- package/dist/store/store.cjs +94 -0
- package/dist/store/store.cjs.map +1 -0
- package/dist/store/store.d.cts +22 -0
- package/dist/store/store.d.mts +22 -0
- package/dist/store/store.mjs +91 -0
- package/dist/store/store.mjs.map +1 -0
- package/dist/style/computed.cjs +65 -0
- package/dist/style/computed.cjs.map +1 -0
- package/dist/style/computed.d.cts +18 -0
- package/dist/style/computed.d.mts +18 -0
- package/dist/style/computed.mjs +63 -0
- package/dist/style/computed.mjs.map +1 -0
- package/dist/text/text.cjs +74 -0
- package/dist/text/text.cjs.map +1 -0
- package/dist/text/text.d.cts +31 -0
- package/dist/text/text.d.mts +31 -0
- package/dist/text/text.mjs +72 -0
- package/dist/text/text.mjs.map +1 -0
- package/dist/types.d.cts +185 -0
- package/dist/types.d.mts +185 -0
- package/dist/utils/index.cjs +34 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.mjs +33 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/watch/watcher.cjs +71 -0
- package/dist/watch/watcher.cjs.map +1 -0
- package/dist/watch/watcher.d.cts +17 -0
- package/dist/watch/watcher.d.mts +17 -0
- package/dist/watch/watcher.mjs +70 -0
- package/dist/watch/watcher.mjs.map +1 -0
- package/package.json +34 -0
- 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
|