@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 @@
1
+ {"version":3,"file":"flow.cjs","names":["memo","sig","val"],"sources":["../../src/render/flow.ts"],"sourcesContent":["/**\n * Flow components for @hedystia/view\n *\n * Provides Show, For, Index, Switch, Match, Portal, Suspense, ErrorBoundary.\n */\n\nimport { tick } from \"../scheduler\";\nimport { createRoot, memo, sig, onCleanup as signalOnCleanup, val } from \"../signal\";\nimport type { Accessor } from \"../types\";\n\n/**\n * Conditionally render children based on a condition\n */\nexport function Show<T>(props: { when: T | Accessor<T>; fallback?: any; children: any }): any {\n const container = document.createComment(\"show\");\n let rendered: HTMLElement | null = null;\n let fallbackNode: HTMLElement | null = null;\n const _initialized = false;\n\n const getCondition = (): any => {\n return typeof props.when === \"function\" ? (props.when as Accessor<T>)() : props.when;\n };\n\n const runEffect = () => {\n const cond = getCondition();\n if (cond) {\n if (fallbackNode) {\n fallbackNode.parentNode?.removeChild(fallbackNode);\n fallbackNode = null;\n }\n if (!rendered && props.children) {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered && !rendered.parentNode) {\n // Defer insertion until container has a parent\n if (container.parentNode) {\n container.parentNode.insertBefore(rendered, container.nextSibling);\n } else {\n queueMicrotask(() => {\n if (rendered && !rendered.parentNode && container.parentNode) {\n container.parentNode.insertBefore(rendered, container.nextSibling);\n }\n });\n }\n }\n }\n } else {\n if (rendered) {\n rendered.parentNode?.removeChild(rendered);\n rendered = null;\n }\n if (props.fallback && !fallbackNode) {\n fallbackNode =\n typeof props.fallback === \"function\"\n ? (props.fallback() as HTMLElement)\n : (props.fallback as HTMLElement);\n if (fallbackNode && !fallbackNode.parentNode) {\n if (container.parentNode) {\n container.parentNode.insertBefore(fallbackNode, container.nextSibling);\n } else {\n queueMicrotask(() => {\n if (fallbackNode && !fallbackNode.parentNode && container.parentNode) {\n container.parentNode.insertBefore(fallbackNode, container.nextSibling);\n }\n });\n }\n }\n }\n }\n };\n\n const tracker = memo(() => {\n runEffect();\n return true;\n });\n\n // Run effect synchronously\n val(tracker);\n\n return container;\n}\n\n/**\n * Render a list with keyed items for efficient updates\n */\nexport function For<T>(props: {\n each: T[] | Accessor<T[]>;\n key?: (item: T) => string | number;\n children: (item: Accessor<T>, index: Accessor<number>) => any;\n}): any {\n const container = document.createComment(\"for\");\n const nodes = new Map<string | number, HTMLElement>();\n const order: Array<string | number> = [];\n\n const getEach = (): T[] => {\n return typeof props.each === \"function\" ? (props.each as Accessor<T[]>)() : props.each;\n };\n\n const runEffect = () => {\n const items = getEach();\n const newOrder: Array<string | number> = [];\n const newNodes = new Map<string | number, HTMLElement>();\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i]!;\n const key = props.key ? props.key(item) : i;\n newOrder.push(key);\n\n if (nodes.has(key)) {\n newNodes.set(key, nodes.get(key)!);\n } else {\n const itemSig = sig(item);\n const indexSig = sig(i);\n const child = props.children(\n () => val(itemSig),\n () => val(indexSig),\n ) as HTMLElement;\n newNodes.set(key, child);\n }\n }\n\n for (const key of order) {\n if (!newNodes.has(key)) {\n const node = nodes.get(key);\n if (node?.parentNode) {\n node.parentNode.removeChild(node);\n }\n }\n }\n\n const insertNodes = () => {\n if (container.parentNode) {\n let prevSibling = container.nextSibling;\n for (const key of newOrder) {\n const node = newNodes.get(key)!;\n if (!nodes.has(key) && !node.parentNode) {\n container.parentNode!.insertBefore(node, prevSibling);\n } else if (prevSibling !== node) {\n container.parentNode!.insertBefore(node, prevSibling);\n }\n prevSibling = node.nextSibling;\n }\n }\n };\n\n if (container.parentNode) {\n insertNodes();\n } else {\n queueMicrotask(insertNodes);\n }\n\n order.length = 0;\n order.push(...newOrder);\n nodes.clear();\n for (const [k, v] of newNodes) {\n nodes.set(k, v);\n }\n };\n\n const tracker = memo(() => {\n runEffect();\n return true;\n });\n\n // Run effect synchronously\n val(tracker);\n\n return container;\n}\n\n/**\n * Render a list with index-based tracking\n */\nexport function Index<T>(props: {\n each: T[] | Accessor<T[]>;\n children: (item: Accessor<T>, index: number) => any;\n}): any {\n const container = document.createComment(\"index\");\n const nodes: Array<HTMLElement | null> = [];\n\n const getEach = (): T[] => {\n return typeof props.each === \"function\" ? (props.each as Accessor<T[]>)() : props.each;\n };\n\n const runEffect = () => {\n const items = getEach();\n\n while (nodes.length > items.length) {\n const node = nodes.pop();\n if (node?.parentNode) {\n node.parentNode.removeChild(node);\n }\n }\n\n const insertNodes = () => {\n if (container.parentNode) {\n for (let i = 0; i < items.length; i++) {\n if (nodes[i] === undefined) {\n const itemSig = sig(items[i]!);\n const child = props.children(() => val(itemSig), i) as HTMLElement;\n nodes[i] = child;\n if (!child.parentNode) {\n container.parentNode.insertBefore(child, container.nextSibling);\n }\n }\n }\n }\n };\n\n if (container.parentNode) {\n insertNodes();\n } else {\n queueMicrotask(insertNodes);\n }\n };\n\n const tracker = memo(() => {\n runEffect();\n return true;\n });\n\n // Run effect synchronously\n val(tracker);\n\n return container;\n}\n\n/**\n * Switch component for mutually exclusive conditions\n */\nexport function Switch(props: { fallback?: any; children: any }): any {\n const container = document.createComment(\"switch\");\n let rendered: HTMLElement | null = null;\n\n const evaluate = (): any => {\n const children = props.children;\n if (Array.isArray(children)) {\n for (const child of children) {\n if (child && (child as any)._matchWhen) {\n const when = (child as any)._matchWhen;\n const condition = typeof when === \"function\" ? when() : when;\n if (condition) {\n return (child as any)._matchChildren;\n }\n }\n }\n }\n return props.fallback;\n };\n\n const runEffect = () => {\n const content = evaluate();\n if (rendered) {\n rendered.parentNode?.removeChild(rendered);\n rendered = null;\n }\n if (content) {\n rendered =\n typeof content === \"function\" ? (content() as HTMLElement) : (content as HTMLElement);\n if (rendered && !rendered.parentNode) {\n const insertNode = () => {\n if (rendered && container.parentNode && !rendered.parentNode) {\n container.parentNode.insertBefore(rendered, container.nextSibling);\n }\n };\n if (container.parentNode) {\n insertNode();\n } else {\n queueMicrotask(insertNode);\n }\n }\n }\n };\n\n const tracker = memo(() => {\n runEffect();\n return true;\n });\n\n // Run effect synchronously\n val(tracker);\n\n return container;\n}\n\n/**\n * Match component for use inside Switch\n */\nexport function Match<T>(props: { when: T | Accessor<T>; children: any }): any {\n const marker = document.createComment(\"match\");\n (marker as any)._matchWhen = typeof props.when === \"function\" ? props.when : () => props.when;\n (marker as any)._matchChildren = props.children;\n return marker;\n}\n\n/**\n * Portal component for rendering outside the current DOM hierarchy\n */\nexport function Portal(props: { mount?: HTMLElement; children: any }): any {\n const container = document.createComment(\"portal\");\n const mountPoint = props.mount || document.body;\n let rendered: HTMLElement | null = null;\n\n createRoot(() => {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered) {\n mountPoint.appendChild(rendered);\n }\n\n signalOnCleanup(() => {\n if (rendered && rendered.parentNode === mountPoint) {\n mountPoint.removeChild(rendered);\n }\n });\n });\n\n return container;\n}\n\n/**\n * Suspense component for async loading states\n */\nexport function Suspense(props: { fallback?: any; children: any }): any {\n const container = document.createComment(\"suspense\");\n let rendered: HTMLElement | null = null;\n let fallbackNode: HTMLElement | null = null;\n\n tick(() => {\n try {\n if (fallbackNode) {\n container.parentNode?.removeChild(fallbackNode);\n fallbackNode = null;\n }\n if (!rendered && props.children) {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n }\n } catch {\n if (rendered) {\n container.parentNode?.removeChild(rendered);\n rendered = null;\n }\n if (props.fallback && !fallbackNode) {\n fallbackNode =\n typeof props.fallback === \"function\"\n ? (props.fallback() as HTMLElement)\n : (props.fallback as HTMLElement);\n if (fallbackNode) {\n container.parentNode?.insertBefore(fallbackNode, container.nextSibling);\n }\n }\n }\n });\n\n return container;\n}\n\n/**\n * ErrorBoundary component for catching render errors\n */\nexport function ErrorBoundary(props: {\n fallback: (err: Error, reset: () => void) => any;\n children: any;\n}): any {\n const container = document.createComment(\"error-boundary\");\n let rendered: HTMLElement | null = null;\n let error: Error | null = null;\n\n const reset = () => {\n error = null;\n if (rendered) {\n container.parentNode?.removeChild(rendered);\n rendered = null;\n }\n tick(() => {\n try {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n } catch (e) {\n error = e instanceof Error ? e : new Error(String(e));\n if (rendered) {\n container.parentNode?.removeChild(rendered);\n rendered = null;\n }\n const fallback = props.fallback(error, reset);\n rendered =\n typeof fallback === \"function\" ? (fallback() as HTMLElement) : (fallback as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n }\n });\n };\n\n tick(() => {\n try {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n } catch (e) {\n error = e instanceof Error ? e : new Error(String(e));\n const fallback = props.fallback(error, reset);\n rendered =\n typeof fallback === \"function\" ? (fallback() as HTMLElement) : (fallback as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n }\n });\n\n return container;\n}\n"],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import { Accessor } from "../types.cjs";
2
+
3
+ //#region src/render/flow.d.ts
4
+ /**
5
+ * Conditionally render children based on a condition
6
+ */
7
+ declare function Show<T>(props: {
8
+ when: T | Accessor<T>;
9
+ fallback?: any;
10
+ children: any;
11
+ }): any;
12
+ /**
13
+ * Render a list with keyed items for efficient updates
14
+ */
15
+ declare function For<T>(props: {
16
+ each: T[] | Accessor<T[]>;
17
+ key?: (item: T) => string | number;
18
+ children: (item: Accessor<T>, index: Accessor<number>) => any;
19
+ }): any;
20
+ /**
21
+ * Render a list with index-based tracking
22
+ */
23
+ declare function Index<T>(props: {
24
+ each: T[] | Accessor<T[]>;
25
+ children: (item: Accessor<T>, index: number) => any;
26
+ }): any;
27
+ /**
28
+ * Switch component for mutually exclusive conditions
29
+ */
30
+ declare function Switch(props: {
31
+ fallback?: any;
32
+ children: any;
33
+ }): any;
34
+ /**
35
+ * Match component for use inside Switch
36
+ */
37
+ declare function Match<T>(props: {
38
+ when: T | Accessor<T>;
39
+ children: any;
40
+ }): any;
41
+ /**
42
+ * Portal component for rendering outside the current DOM hierarchy
43
+ */
44
+ declare function Portal(props: {
45
+ mount?: HTMLElement;
46
+ children: any;
47
+ }): any;
48
+ /**
49
+ * Suspense component for async loading states
50
+ */
51
+ declare function Suspense(props: {
52
+ fallback?: any;
53
+ children: any;
54
+ }): any;
55
+ /**
56
+ * ErrorBoundary component for catching render errors
57
+ */
58
+ declare function ErrorBoundary(props: {
59
+ fallback: (err: Error, reset: () => void) => any;
60
+ children: any;
61
+ }): any;
62
+ //#endregion
63
+ export { ErrorBoundary, For, Index, Match, Portal, Show, Suspense, Switch };
64
+ //# sourceMappingURL=flow.d.cts.map
@@ -0,0 +1,64 @@
1
+ import { Accessor } from "../types.mjs";
2
+
3
+ //#region src/render/flow.d.ts
4
+ /**
5
+ * Conditionally render children based on a condition
6
+ */
7
+ declare function Show<T>(props: {
8
+ when: T | Accessor<T>;
9
+ fallback?: any;
10
+ children: any;
11
+ }): any;
12
+ /**
13
+ * Render a list with keyed items for efficient updates
14
+ */
15
+ declare function For<T>(props: {
16
+ each: T[] | Accessor<T[]>;
17
+ key?: (item: T) => string | number;
18
+ children: (item: Accessor<T>, index: Accessor<number>) => any;
19
+ }): any;
20
+ /**
21
+ * Render a list with index-based tracking
22
+ */
23
+ declare function Index<T>(props: {
24
+ each: T[] | Accessor<T[]>;
25
+ children: (item: Accessor<T>, index: number) => any;
26
+ }): any;
27
+ /**
28
+ * Switch component for mutually exclusive conditions
29
+ */
30
+ declare function Switch(props: {
31
+ fallback?: any;
32
+ children: any;
33
+ }): any;
34
+ /**
35
+ * Match component for use inside Switch
36
+ */
37
+ declare function Match<T>(props: {
38
+ when: T | Accessor<T>;
39
+ children: any;
40
+ }): any;
41
+ /**
42
+ * Portal component for rendering outside the current DOM hierarchy
43
+ */
44
+ declare function Portal(props: {
45
+ mount?: HTMLElement;
46
+ children: any;
47
+ }): any;
48
+ /**
49
+ * Suspense component for async loading states
50
+ */
51
+ declare function Suspense(props: {
52
+ fallback?: any;
53
+ children: any;
54
+ }): any;
55
+ /**
56
+ * ErrorBoundary component for catching render errors
57
+ */
58
+ declare function ErrorBoundary(props: {
59
+ fallback: (err: Error, reset: () => void) => any;
60
+ children: any;
61
+ }): any;
62
+ //#endregion
63
+ export { ErrorBoundary, For, Index, Match, Portal, Show, Suspense, Switch };
64
+ //# sourceMappingURL=flow.d.mts.map
@@ -0,0 +1,279 @@
1
+ import { createRoot, memo, onCleanup, sig, val } from "../signal/signal.mjs";
2
+ import { tick } from "../scheduler/scheduler.mjs";
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
+ val(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 = sig(item);
73
+ const indexSig = sig(i);
74
+ const child = props.children(() => val(itemSig), () => 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
+ val(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 = sig(items[i]);
125
+ const child = props.children(() => 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
+ val(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
+ val(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
+ createRoot(() => {
196
+ rendered = typeof props.children === "function" ? props.children() : props.children;
197
+ if (rendered) mountPoint.appendChild(rendered);
198
+ 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
+ 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
+ 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
+ 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
+ export { ErrorBoundary, For, Index, Match, Portal, Show, Suspense, Switch };
278
+
279
+ //# sourceMappingURL=flow.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.mjs","names":[],"sources":["../../src/render/flow.ts"],"sourcesContent":["/**\n * Flow components for @hedystia/view\n *\n * Provides Show, For, Index, Switch, Match, Portal, Suspense, ErrorBoundary.\n */\n\nimport { tick } from \"../scheduler\";\nimport { createRoot, memo, sig, onCleanup as signalOnCleanup, val } from \"../signal\";\nimport type { Accessor } from \"../types\";\n\n/**\n * Conditionally render children based on a condition\n */\nexport function Show<T>(props: { when: T | Accessor<T>; fallback?: any; children: any }): any {\n const container = document.createComment(\"show\");\n let rendered: HTMLElement | null = null;\n let fallbackNode: HTMLElement | null = null;\n const _initialized = false;\n\n const getCondition = (): any => {\n return typeof props.when === \"function\" ? (props.when as Accessor<T>)() : props.when;\n };\n\n const runEffect = () => {\n const cond = getCondition();\n if (cond) {\n if (fallbackNode) {\n fallbackNode.parentNode?.removeChild(fallbackNode);\n fallbackNode = null;\n }\n if (!rendered && props.children) {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered && !rendered.parentNode) {\n // Defer insertion until container has a parent\n if (container.parentNode) {\n container.parentNode.insertBefore(rendered, container.nextSibling);\n } else {\n queueMicrotask(() => {\n if (rendered && !rendered.parentNode && container.parentNode) {\n container.parentNode.insertBefore(rendered, container.nextSibling);\n }\n });\n }\n }\n }\n } else {\n if (rendered) {\n rendered.parentNode?.removeChild(rendered);\n rendered = null;\n }\n if (props.fallback && !fallbackNode) {\n fallbackNode =\n typeof props.fallback === \"function\"\n ? (props.fallback() as HTMLElement)\n : (props.fallback as HTMLElement);\n if (fallbackNode && !fallbackNode.parentNode) {\n if (container.parentNode) {\n container.parentNode.insertBefore(fallbackNode, container.nextSibling);\n } else {\n queueMicrotask(() => {\n if (fallbackNode && !fallbackNode.parentNode && container.parentNode) {\n container.parentNode.insertBefore(fallbackNode, container.nextSibling);\n }\n });\n }\n }\n }\n }\n };\n\n const tracker = memo(() => {\n runEffect();\n return true;\n });\n\n // Run effect synchronously\n val(tracker);\n\n return container;\n}\n\n/**\n * Render a list with keyed items for efficient updates\n */\nexport function For<T>(props: {\n each: T[] | Accessor<T[]>;\n key?: (item: T) => string | number;\n children: (item: Accessor<T>, index: Accessor<number>) => any;\n}): any {\n const container = document.createComment(\"for\");\n const nodes = new Map<string | number, HTMLElement>();\n const order: Array<string | number> = [];\n\n const getEach = (): T[] => {\n return typeof props.each === \"function\" ? (props.each as Accessor<T[]>)() : props.each;\n };\n\n const runEffect = () => {\n const items = getEach();\n const newOrder: Array<string | number> = [];\n const newNodes = new Map<string | number, HTMLElement>();\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i]!;\n const key = props.key ? props.key(item) : i;\n newOrder.push(key);\n\n if (nodes.has(key)) {\n newNodes.set(key, nodes.get(key)!);\n } else {\n const itemSig = sig(item);\n const indexSig = sig(i);\n const child = props.children(\n () => val(itemSig),\n () => val(indexSig),\n ) as HTMLElement;\n newNodes.set(key, child);\n }\n }\n\n for (const key of order) {\n if (!newNodes.has(key)) {\n const node = nodes.get(key);\n if (node?.parentNode) {\n node.parentNode.removeChild(node);\n }\n }\n }\n\n const insertNodes = () => {\n if (container.parentNode) {\n let prevSibling = container.nextSibling;\n for (const key of newOrder) {\n const node = newNodes.get(key)!;\n if (!nodes.has(key) && !node.parentNode) {\n container.parentNode!.insertBefore(node, prevSibling);\n } else if (prevSibling !== node) {\n container.parentNode!.insertBefore(node, prevSibling);\n }\n prevSibling = node.nextSibling;\n }\n }\n };\n\n if (container.parentNode) {\n insertNodes();\n } else {\n queueMicrotask(insertNodes);\n }\n\n order.length = 0;\n order.push(...newOrder);\n nodes.clear();\n for (const [k, v] of newNodes) {\n nodes.set(k, v);\n }\n };\n\n const tracker = memo(() => {\n runEffect();\n return true;\n });\n\n // Run effect synchronously\n val(tracker);\n\n return container;\n}\n\n/**\n * Render a list with index-based tracking\n */\nexport function Index<T>(props: {\n each: T[] | Accessor<T[]>;\n children: (item: Accessor<T>, index: number) => any;\n}): any {\n const container = document.createComment(\"index\");\n const nodes: Array<HTMLElement | null> = [];\n\n const getEach = (): T[] => {\n return typeof props.each === \"function\" ? (props.each as Accessor<T[]>)() : props.each;\n };\n\n const runEffect = () => {\n const items = getEach();\n\n while (nodes.length > items.length) {\n const node = nodes.pop();\n if (node?.parentNode) {\n node.parentNode.removeChild(node);\n }\n }\n\n const insertNodes = () => {\n if (container.parentNode) {\n for (let i = 0; i < items.length; i++) {\n if (nodes[i] === undefined) {\n const itemSig = sig(items[i]!);\n const child = props.children(() => val(itemSig), i) as HTMLElement;\n nodes[i] = child;\n if (!child.parentNode) {\n container.parentNode.insertBefore(child, container.nextSibling);\n }\n }\n }\n }\n };\n\n if (container.parentNode) {\n insertNodes();\n } else {\n queueMicrotask(insertNodes);\n }\n };\n\n const tracker = memo(() => {\n runEffect();\n return true;\n });\n\n // Run effect synchronously\n val(tracker);\n\n return container;\n}\n\n/**\n * Switch component for mutually exclusive conditions\n */\nexport function Switch(props: { fallback?: any; children: any }): any {\n const container = document.createComment(\"switch\");\n let rendered: HTMLElement | null = null;\n\n const evaluate = (): any => {\n const children = props.children;\n if (Array.isArray(children)) {\n for (const child of children) {\n if (child && (child as any)._matchWhen) {\n const when = (child as any)._matchWhen;\n const condition = typeof when === \"function\" ? when() : when;\n if (condition) {\n return (child as any)._matchChildren;\n }\n }\n }\n }\n return props.fallback;\n };\n\n const runEffect = () => {\n const content = evaluate();\n if (rendered) {\n rendered.parentNode?.removeChild(rendered);\n rendered = null;\n }\n if (content) {\n rendered =\n typeof content === \"function\" ? (content() as HTMLElement) : (content as HTMLElement);\n if (rendered && !rendered.parentNode) {\n const insertNode = () => {\n if (rendered && container.parentNode && !rendered.parentNode) {\n container.parentNode.insertBefore(rendered, container.nextSibling);\n }\n };\n if (container.parentNode) {\n insertNode();\n } else {\n queueMicrotask(insertNode);\n }\n }\n }\n };\n\n const tracker = memo(() => {\n runEffect();\n return true;\n });\n\n // Run effect synchronously\n val(tracker);\n\n return container;\n}\n\n/**\n * Match component for use inside Switch\n */\nexport function Match<T>(props: { when: T | Accessor<T>; children: any }): any {\n const marker = document.createComment(\"match\");\n (marker as any)._matchWhen = typeof props.when === \"function\" ? props.when : () => props.when;\n (marker as any)._matchChildren = props.children;\n return marker;\n}\n\n/**\n * Portal component for rendering outside the current DOM hierarchy\n */\nexport function Portal(props: { mount?: HTMLElement; children: any }): any {\n const container = document.createComment(\"portal\");\n const mountPoint = props.mount || document.body;\n let rendered: HTMLElement | null = null;\n\n createRoot(() => {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered) {\n mountPoint.appendChild(rendered);\n }\n\n signalOnCleanup(() => {\n if (rendered && rendered.parentNode === mountPoint) {\n mountPoint.removeChild(rendered);\n }\n });\n });\n\n return container;\n}\n\n/**\n * Suspense component for async loading states\n */\nexport function Suspense(props: { fallback?: any; children: any }): any {\n const container = document.createComment(\"suspense\");\n let rendered: HTMLElement | null = null;\n let fallbackNode: HTMLElement | null = null;\n\n tick(() => {\n try {\n if (fallbackNode) {\n container.parentNode?.removeChild(fallbackNode);\n fallbackNode = null;\n }\n if (!rendered && props.children) {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n }\n } catch {\n if (rendered) {\n container.parentNode?.removeChild(rendered);\n rendered = null;\n }\n if (props.fallback && !fallbackNode) {\n fallbackNode =\n typeof props.fallback === \"function\"\n ? (props.fallback() as HTMLElement)\n : (props.fallback as HTMLElement);\n if (fallbackNode) {\n container.parentNode?.insertBefore(fallbackNode, container.nextSibling);\n }\n }\n }\n });\n\n return container;\n}\n\n/**\n * ErrorBoundary component for catching render errors\n */\nexport function ErrorBoundary(props: {\n fallback: (err: Error, reset: () => void) => any;\n children: any;\n}): any {\n const container = document.createComment(\"error-boundary\");\n let rendered: HTMLElement | null = null;\n let error: Error | null = null;\n\n const reset = () => {\n error = null;\n if (rendered) {\n container.parentNode?.removeChild(rendered);\n rendered = null;\n }\n tick(() => {\n try {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n } catch (e) {\n error = e instanceof Error ? e : new Error(String(e));\n if (rendered) {\n container.parentNode?.removeChild(rendered);\n rendered = null;\n }\n const fallback = props.fallback(error, reset);\n rendered =\n typeof fallback === \"function\" ? (fallback() as HTMLElement) : (fallback as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n }\n });\n };\n\n tick(() => {\n try {\n rendered =\n typeof props.children === \"function\"\n ? (props.children() as HTMLElement)\n : (props.children as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n } catch (e) {\n error = e instanceof Error ? e : new Error(String(e));\n const fallback = props.fallback(error, reset);\n rendered =\n typeof fallback === \"function\" ? (fallback() as HTMLElement) : (fallback as HTMLElement);\n if (rendered) {\n container.parentNode?.insertBefore(rendered, container.nextSibling);\n }\n }\n });\n\n return container;\n}\n"],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ //#region src/scheduler/scheduler.ts
2
+ /**
3
+ * Frame scheduler for @hedystia/view
4
+ *
5
+ * Provides requestAnimationFrame-based batching for visual updates.
6
+ */
7
+ let scheduledRaf = null;
8
+ let rafCallbacks = [];
9
+ /**
10
+ * Schedule a callback for the next animation frame
11
+ * @param {() => void} fn - The callback to run on next frame
12
+ * @example
13
+ * tick(() => {
14
+ * // DOM updates here
15
+ * });
16
+ */
17
+ function tick(fn) {
18
+ rafCallbacks.push(fn);
19
+ if (scheduledRaf === null) scheduledRaf = requestAnimationFrame(flushRaf);
20
+ }
21
+ /**
22
+ * Wait for the next animation frame
23
+ * @returns {Promise<void>} A promise that resolves on next frame
24
+ * @example
25
+ * await nextFrame();
26
+ */
27
+ function nextFrame() {
28
+ return new Promise((resolve) => {
29
+ tick(resolve);
30
+ });
31
+ }
32
+ /** @internal */
33
+ function flushRaf() {
34
+ scheduledRaf = null;
35
+ const callbacks = rafCallbacks;
36
+ rafCallbacks = [];
37
+ for (let i = 0; i < callbacks.length; i++) callbacks[i]();
38
+ }
39
+ /**
40
+ * Force flush all pending RAF callbacks synchronously (for testing)
41
+ * @example
42
+ * await tick(); // forces flush
43
+ */
44
+ function forceFlush() {
45
+ return new Promise((resolve) => {
46
+ if (scheduledRaf !== null) {
47
+ cancelAnimationFrame(scheduledRaf);
48
+ scheduledRaf = null;
49
+ }
50
+ const callbacks = rafCallbacks;
51
+ rafCallbacks = [];
52
+ for (let i = 0; i < callbacks.length; i++) callbacks[i]();
53
+ resolve();
54
+ });
55
+ }
56
+ //#endregion
57
+ exports.forceFlush = forceFlush;
58
+ exports.nextFrame = nextFrame;
59
+ exports.tick = tick;
60
+
61
+ //# sourceMappingURL=scheduler.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.cjs","names":[],"sources":["../../src/scheduler/scheduler.ts"],"sourcesContent":["/**\n * Frame scheduler for @hedystia/view\n *\n * Provides requestAnimationFrame-based batching for visual updates.\n */\n\nlet scheduledRaf: number | null = null;\nlet rafCallbacks: Array<() => void> = [];\n\n/**\n * Schedule a callback for the next animation frame\n * @param {() => void} fn - The callback to run on next frame\n * @example\n * tick(() => {\n * // DOM updates here\n * });\n */\nexport function tick(fn: () => void): void {\n rafCallbacks.push(fn);\n if (scheduledRaf === null) {\n scheduledRaf = requestAnimationFrame(flushRaf);\n }\n}\n\n/**\n * Wait for the next animation frame\n * @returns {Promise<void>} A promise that resolves on next frame\n * @example\n * await nextFrame();\n */\nexport function nextFrame(): Promise<void> {\n return new Promise((resolve) => {\n tick(resolve);\n });\n}\n\n/** @internal */\nfunction flushRaf(): void {\n scheduledRaf = null;\n const callbacks = rafCallbacks;\n rafCallbacks = [];\n for (let i = 0; i < callbacks.length; i++) {\n callbacks[i]!();\n }\n}\n\n/**\n * Force flush all pending RAF callbacks synchronously (for testing)\n * @example\n * await tick(); // forces flush\n */\nexport function forceFlush(): Promise<void> {\n return new Promise((resolve) => {\n if (scheduledRaf !== null) {\n cancelAnimationFrame(scheduledRaf);\n scheduledRaf = null;\n }\n const callbacks = rafCallbacks;\n rafCallbacks = [];\n for (let i = 0; i < callbacks.length; i++) {\n callbacks[i]!();\n }\n resolve();\n });\n}\n"],"mappings":";;;;;;AAMA,IAAI,eAA8B;AAClC,IAAI,eAAkC,EAAE;;;;;;;;;AAUxC,SAAgB,KAAK,IAAsB;AACzC,cAAa,KAAK,GAAG;AACrB,KAAI,iBAAiB,KACnB,gBAAe,sBAAsB,SAAS;;;;;;;;AAUlD,SAAgB,YAA2B;AACzC,QAAO,IAAI,SAAS,YAAY;AAC9B,OAAK,QAAQ;GACb;;;AAIJ,SAAS,WAAiB;AACxB,gBAAe;CACf,MAAM,YAAY;AAClB,gBAAe,EAAE;AACjB,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,IACpC,WAAU,IAAK;;;;;;;AASnB,SAAgB,aAA4B;AAC1C,QAAO,IAAI,SAAS,YAAY;AAC9B,MAAI,iBAAiB,MAAM;AACzB,wBAAqB,aAAa;AAClC,kBAAe;;EAEjB,MAAM,YAAY;AAClB,iBAAe,EAAE;AACjB,OAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,IACpC,WAAU,IAAK;AAEjB,WAAS;GACT"}
@@ -0,0 +1,31 @@
1
+ //#region src/scheduler/scheduler.d.ts
2
+ /**
3
+ * Frame scheduler for @hedystia/view
4
+ *
5
+ * Provides requestAnimationFrame-based batching for visual updates.
6
+ */
7
+ /**
8
+ * Schedule a callback for the next animation frame
9
+ * @param {() => void} fn - The callback to run on next frame
10
+ * @example
11
+ * tick(() => {
12
+ * // DOM updates here
13
+ * });
14
+ */
15
+ declare function tick(fn: () => void): void;
16
+ /**
17
+ * Wait for the next animation frame
18
+ * @returns {Promise<void>} A promise that resolves on next frame
19
+ * @example
20
+ * await nextFrame();
21
+ */
22
+ declare function nextFrame(): Promise<void>;
23
+ /**
24
+ * Force flush all pending RAF callbacks synchronously (for testing)
25
+ * @example
26
+ * await tick(); // forces flush
27
+ */
28
+ declare function forceFlush(): Promise<void>;
29
+ //#endregion
30
+ export { forceFlush, nextFrame, tick };
31
+ //# sourceMappingURL=scheduler.d.cts.map
@@ -0,0 +1,31 @@
1
+ //#region src/scheduler/scheduler.d.ts
2
+ /**
3
+ * Frame scheduler for @hedystia/view
4
+ *
5
+ * Provides requestAnimationFrame-based batching for visual updates.
6
+ */
7
+ /**
8
+ * Schedule a callback for the next animation frame
9
+ * @param {() => void} fn - The callback to run on next frame
10
+ * @example
11
+ * tick(() => {
12
+ * // DOM updates here
13
+ * });
14
+ */
15
+ declare function tick(fn: () => void): void;
16
+ /**
17
+ * Wait for the next animation frame
18
+ * @returns {Promise<void>} A promise that resolves on next frame
19
+ * @example
20
+ * await nextFrame();
21
+ */
22
+ declare function nextFrame(): Promise<void>;
23
+ /**
24
+ * Force flush all pending RAF callbacks synchronously (for testing)
25
+ * @example
26
+ * await tick(); // forces flush
27
+ */
28
+ declare function forceFlush(): Promise<void>;
29
+ //#endregion
30
+ export { forceFlush, nextFrame, tick };
31
+ //# sourceMappingURL=scheduler.d.mts.map