@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,185 @@
1
+ import { JSX } from "./jsx.mjs";
2
+
3
+ //#region src/types.d.ts
4
+ /**
5
+ * Function that returns a value of type T - used for reactive accessors
6
+ */
7
+ type Accessor<T> = () => T;
8
+ /**
9
+ * Mutable reactive signal holding a value of type T
10
+ */
11
+ interface Signal<T> {
12
+ /** @internal */
13
+ _value: T;
14
+ /** @internal */
15
+ _observers: Computation<any>[] | null;
16
+ /** @internal */
17
+ _observerSlots: number[] | null;
18
+ /** @internal */
19
+ _comparator?: (prev: T, next: T) => boolean;
20
+ }
21
+ /**
22
+ * Read-only derived reactive signal computed from other signals
23
+ */
24
+ interface Computed<T> {
25
+ /** @internal */
26
+ _value: T;
27
+ /** @internal */
28
+ _fn: () => T;
29
+ /** @internal */
30
+ _observers: Computation<any>[] | null;
31
+ /** @internal */
32
+ _observerSlots: number[] | null;
33
+ /** @internal */
34
+ _sources: Signal<any>[] | null;
35
+ /** @internal */
36
+ _sourceSlots: number[] | null;
37
+ /** @internal */
38
+ _comparator?: (prev: T, next: T) => boolean;
39
+ /** @internal */
40
+ _state: 0 | 1 | 2;
41
+ /** Call to get the current value */
42
+ (): T;
43
+ }
44
+ /**
45
+ * Union type for reading signal values
46
+ */
47
+ type ReadonlySignal<T> = Signal<T> | Computed<T>;
48
+ /**
49
+ * Internal computation node in the reactive graph
50
+ */
51
+ interface Computation<T> {
52
+ /** @internal */
53
+ _fn: EffectFunction<T>;
54
+ /** @internal */
55
+ _value: T | undefined;
56
+ /** @internal */
57
+ _sources: Signal<any>[] | null;
58
+ /** @internal */
59
+ _sourceSlots: number[] | null;
60
+ /** @internal */
61
+ _observers: Computation<any>[] | null;
62
+ /** @internal */
63
+ _observerSlots: number[] | null;
64
+ /** @internal */
65
+ _owner: Owner | null;
66
+ /** @internal */
67
+ _cleanups: (() => void)[] | null;
68
+ /** @internal */
69
+ _context: any | null;
70
+ /** @internal */
71
+ _suspense: SuspenseContextType | null;
72
+ /** @internal */
73
+ _user: boolean;
74
+ /** @internal */
75
+ _pure: boolean;
76
+ /** @internal */
77
+ _state: 0 | 1 | 2;
78
+ /** @internal */
79
+ _updatedAt: number | null;
80
+ }
81
+ /**
82
+ * Reactive owner/context node
83
+ */
84
+ interface Owner {
85
+ /** @internal */
86
+ _owned: Computation<any>[] | null;
87
+ /** @internal */
88
+ _cleanups: (() => void)[] | null;
89
+ /** @internal */
90
+ _owner: Owner | null;
91
+ /** @internal */
92
+ _context: any | null;
93
+ }
94
+ /**
95
+ * Effect function type for computations
96
+ */
97
+ type EffectFunction<T> = (prev?: T) => T;
98
+ /**
99
+ * Options for creating a signal
100
+ */
101
+ interface SignalOptions<T> {
102
+ equals?: false | ((prev: T, next: T) => boolean);
103
+ name?: string;
104
+ }
105
+ /**
106
+ * Component function type
107
+ */
108
+ type Component<P extends Record<string, any> = {}> = (props: P) => JSX.Element;
109
+ /**
110
+ * Component that accepts children
111
+ */
112
+ type ParentComponent<P extends Record<string, any> = {}> = Component<P & {
113
+ children?: JSX.Children;
114
+ }>;
115
+ /**
116
+ * Component that requires children
117
+ */
118
+ type FlowComponent<P extends Record<string, any> = {}, C = JSX.Children> = Component<P & {
119
+ children: C;
120
+ }>;
121
+ /**
122
+ * Context object for provider/consumer pattern
123
+ */
124
+ interface Context<T> {
125
+ _id: symbol;
126
+ _defaultValue: T | undefined;
127
+ Provider: Component<{
128
+ value: T;
129
+ children: JSX.Element;
130
+ }>;
131
+ }
132
+ /**
133
+ * Suspense context type for error boundaries and suspense
134
+ */
135
+ interface SuspenseContextType {
136
+ increment: () => void;
137
+ decrement: () => void;
138
+ resolved: boolean;
139
+ }
140
+ /**
141
+ * Resource object returned by load()
142
+ */
143
+ interface Resource<T> {
144
+ (): T | undefined;
145
+ readonly state: Signal<"unresolved" | "pending" | "ready" | "refreshing" | "errored">;
146
+ readonly loading: Signal<boolean>;
147
+ readonly error: Signal<Error | undefined>;
148
+ readonly data: Signal<T | undefined>;
149
+ readonly ready: boolean;
150
+ }
151
+ /**
152
+ * Action object for mutations
153
+ */
154
+ interface Action<T, A> {
155
+ (args: A): Promise<T>;
156
+ run: (args: A) => Promise<T>;
157
+ readonly loading: Signal<boolean>;
158
+ readonly error: Signal<Error | undefined>;
159
+ readonly data: Signal<T | undefined>;
160
+ }
161
+ /**
162
+ * Style properties type
163
+ */
164
+ type StyleProps = Record<string, string | number | Accessor<string | number> | undefined>;
165
+ /**
166
+ * Computed style object
167
+ */
168
+ type ComputedStyle<T extends StyleProps> = () => T;
169
+ /**
170
+ * Store value types
171
+ */
172
+ type StoreValue = string | number | boolean | null | undefined | object | StoreValue[];
173
+ /**
174
+ * Store node type for nested access
175
+ */
176
+ type StoreNode<T> = T extends object ? Record<keyof T, StoreNode<T[keyof T]>> : Signal<T>;
177
+ /**
178
+ * Store object
179
+ */
180
+ interface Store<T extends Record<string, StoreValue>> {
181
+ [key: string]: StoreNode<T[string]>;
182
+ }
183
+ //#endregion
184
+ export { Accessor, Action, Component, Computed, ComputedStyle, Context, FlowComponent, Owner, ParentComponent, ReadonlySignal, Resource, Signal, SignalOptions, Store, StoreNode, StoreValue, StyleProps };
185
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1,34 @@
1
+ //#region src/utils/index.ts
2
+ /**
3
+ * Internal utilities for @hedystia/view
4
+ */
5
+ /**
6
+ * Equality comparison function for signals
7
+ */
8
+ function equalFn(a, b) {
9
+ return a === b;
10
+ }
11
+ /**
12
+ * Creates a shallow clone of an object
13
+ */
14
+ function shallowClone(obj) {
15
+ const target = {};
16
+ for (const key in obj) if (Object.hasOwn(obj, key)) target[key] = obj[key];
17
+ return target;
18
+ }
19
+ /**
20
+ * Merges two style objects, with the second taking precedence
21
+ */
22
+ function mergeStyles(base, override) {
23
+ const result = shallowClone(base);
24
+ for (const key in override) if (Object.hasOwn(override, key)) {
25
+ const value = override[key];
26
+ if (value !== void 0) result[key] = value;
27
+ }
28
+ return result;
29
+ }
30
+ //#endregion
31
+ exports.equalFn = equalFn;
32
+ exports.mergeStyles = mergeStyles;
33
+
34
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../src/utils/index.ts"],"sourcesContent":["/**\n * Internal utilities for @hedystia/view\n */\n\n/**\n * Equality comparison function for signals\n */\nexport function equalFn<T>(a: T, b: T): boolean {\n return a === b;\n}\n\n/**\n * Creates a shallow clone of an object\n */\nexport function shallowClone<T extends object>(obj: T): T {\n const target = {} as any;\n for (const key in obj) {\n if (Object.hasOwn(obj, key)) {\n target[key] = obj[key];\n }\n }\n return target;\n}\n\n/**\n * Merges two style objects, with the second taking precedence\n */\nexport function mergeStyles(\n base: Record<string, any>,\n override: Record<string, any>,\n): Record<string, any> {\n const result = shallowClone(base);\n for (const key in override) {\n if (Object.hasOwn(override, key)) {\n const value = override[key];\n if (value !== undefined) {\n result[key] = value;\n }\n }\n }\n return result;\n}\n\n/**\n * Checks if a value is a function\n */\nexport function isFunction(value: unknown): value is Function {\n return typeof value === \"function\";\n}\n\n/**\n * Checks if a value is an object (not null)\n */\nexport function isObject(value: unknown): value is object {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * No-op function\n */\nexport function noop(): void {}\n"],"mappings":";;;;;;;AAOA,SAAgB,QAAW,GAAM,GAAe;AAC9C,QAAO,MAAM;;;;;AAMf,SAAgB,aAA+B,KAAW;CACxD,MAAM,SAAS,EAAE;AACjB,MAAK,MAAM,OAAO,IAChB,KAAI,OAAO,OAAO,KAAK,IAAI,CACzB,QAAO,OAAO,IAAI;AAGtB,QAAO;;;;;AAMT,SAAgB,YACd,MACA,UACqB;CACrB,MAAM,SAAS,aAAa,KAAK;AACjC,MAAK,MAAM,OAAO,SAChB,KAAI,OAAO,OAAO,UAAU,IAAI,EAAE;EAChC,MAAM,QAAQ,SAAS;AACvB,MAAI,UAAU,KAAA,EACZ,QAAO,OAAO;;AAIpB,QAAO"}
@@ -0,0 +1,33 @@
1
+ //#region src/utils/index.ts
2
+ /**
3
+ * Internal utilities for @hedystia/view
4
+ */
5
+ /**
6
+ * Equality comparison function for signals
7
+ */
8
+ function equalFn(a, b) {
9
+ return a === b;
10
+ }
11
+ /**
12
+ * Creates a shallow clone of an object
13
+ */
14
+ function shallowClone(obj) {
15
+ const target = {};
16
+ for (const key in obj) if (Object.hasOwn(obj, key)) target[key] = obj[key];
17
+ return target;
18
+ }
19
+ /**
20
+ * Merges two style objects, with the second taking precedence
21
+ */
22
+ function mergeStyles(base, override) {
23
+ const result = shallowClone(base);
24
+ for (const key in override) if (Object.hasOwn(override, key)) {
25
+ const value = override[key];
26
+ if (value !== void 0) result[key] = value;
27
+ }
28
+ return result;
29
+ }
30
+ //#endregion
31
+ export { equalFn, mergeStyles };
32
+
33
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/index.ts"],"sourcesContent":["/**\n * Internal utilities for @hedystia/view\n */\n\n/**\n * Equality comparison function for signals\n */\nexport function equalFn<T>(a: T, b: T): boolean {\n return a === b;\n}\n\n/**\n * Creates a shallow clone of an object\n */\nexport function shallowClone<T extends object>(obj: T): T {\n const target = {} as any;\n for (const key in obj) {\n if (Object.hasOwn(obj, key)) {\n target[key] = obj[key];\n }\n }\n return target;\n}\n\n/**\n * Merges two style objects, with the second taking precedence\n */\nexport function mergeStyles(\n base: Record<string, any>,\n override: Record<string, any>,\n): Record<string, any> {\n const result = shallowClone(base);\n for (const key in override) {\n if (Object.hasOwn(override, key)) {\n const value = override[key];\n if (value !== undefined) {\n result[key] = value;\n }\n }\n }\n return result;\n}\n\n/**\n * Checks if a value is a function\n */\nexport function isFunction(value: unknown): value is Function {\n return typeof value === \"function\";\n}\n\n/**\n * Checks if a value is an object (not null)\n */\nexport function isObject(value: unknown): value is object {\n return typeof value === \"object\" && value !== null;\n}\n\n/**\n * No-op function\n */\nexport function noop(): void {}\n"],"mappings":";;;;;;;AAOA,SAAgB,QAAW,GAAM,GAAe;AAC9C,QAAO,MAAM;;;;;AAMf,SAAgB,aAA+B,KAAW;CACxD,MAAM,SAAS,EAAE;AACjB,MAAK,MAAM,OAAO,IAChB,KAAI,OAAO,OAAO,KAAK,IAAI,CACzB,QAAO,OAAO,IAAI;AAGtB,QAAO;;;;;AAMT,SAAgB,YACd,MACA,UACqB;CACrB,MAAM,SAAS,aAAa,KAAK;AACjC,MAAK,MAAM,OAAO,SAChB,KAAI,OAAO,OAAO,UAAU,IAAI,EAAE;EAChC,MAAM,QAAQ,SAAS;AACvB,MAAI,UAAU,KAAA,EACZ,QAAO,OAAO;;AAIpB,QAAO"}
@@ -0,0 +1,71 @@
1
+ const require_signal = require("../signal/signal.cjs");
2
+ //#region src/watch/watcher.ts
3
+ /**
4
+ * Watchers and reactive effects for @hedystia/view
5
+ *
6
+ * Provides effect tracking and reactive subscriptions.
7
+ */
8
+ /**
9
+ * Create a reactive effect that runs when dependencies change
10
+ */
11
+ function on(track, run) {
12
+ let cleanup;
13
+ let prevValue;
14
+ let hasRun = false;
15
+ let stopped = false;
16
+ const computation = {
17
+ _fn: () => {
18
+ if (stopped) return;
19
+ const value = track();
20
+ require_signal.untrack(() => {
21
+ if (cleanup) {
22
+ cleanup();
23
+ cleanup = void 0;
24
+ }
25
+ const result = run(value, hasRun ? prevValue : value);
26
+ if (typeof result === "function") cleanup = result;
27
+ });
28
+ prevValue = value;
29
+ hasRun = true;
30
+ },
31
+ _value: void 0,
32
+ _sources: null,
33
+ _sourceSlots: null,
34
+ _observers: null,
35
+ _observerSlots: null,
36
+ _owner: require_signal.Owner,
37
+ _cleanups: null,
38
+ _context: null,
39
+ _suspense: null,
40
+ _user: true,
41
+ _pure: false,
42
+ _state: 0,
43
+ _updatedAt: null
44
+ };
45
+ require_signal.runComputation(computation);
46
+ return () => {
47
+ stopped = true;
48
+ require_signal.cleanupSources(computation);
49
+ if (cleanup) {
50
+ cleanup();
51
+ cleanup = void 0;
52
+ }
53
+ };
54
+ }
55
+ /**
56
+ * Create a one-time effect that runs once and disposes
57
+ */
58
+ function once(track, run) {
59
+ let hasRun = false;
60
+ return on(track, (value) => {
61
+ if (!hasRun) {
62
+ hasRun = true;
63
+ run(value);
64
+ }
65
+ });
66
+ }
67
+ //#endregion
68
+ exports.on = on;
69
+ exports.once = once;
70
+
71
+ //# sourceMappingURL=watcher.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.cjs","names":["Owner"],"sources":["../../src/watch/watcher.ts"],"sourcesContent":["/**\n * Watchers and reactive effects for @hedystia/view\n *\n * Provides effect tracking and reactive subscriptions.\n */\n\nimport { cleanupSources, Owner, runComputation, untrack } from \"../signal\";\nimport type { Computation } from \"../types\";\n\n/**\n * Create a reactive effect that runs when dependencies change\n */\nexport function on<T>(track: () => T, run: (value: T, prev: T) => any | (() => void)): () => void {\n let cleanup: (() => void) | undefined;\n let prevValue: T | undefined;\n let hasRun = false;\n let stopped = false;\n\n const computation: Computation<any> = {\n _fn: () => {\n if (stopped) {\n return undefined;\n }\n\n // Track dependencies from the track function\n const value = track();\n\n // Run callback untracked so reads inside run() don't become dependencies\n untrack(() => {\n if (cleanup) {\n cleanup();\n cleanup = undefined;\n }\n\n const result = run(value, hasRun ? prevValue! : value);\n if (typeof result === \"function\") {\n cleanup = result;\n }\n });\n\n prevValue = value;\n hasRun = true;\n return undefined;\n },\n _value: undefined,\n _sources: null,\n _sourceSlots: null,\n _observers: null,\n _observerSlots: null,\n _owner: Owner,\n _cleanups: null,\n _context: null,\n _suspense: null,\n _user: true,\n _pure: false,\n _state: 0,\n _updatedAt: null,\n };\n\n // Run initial execution with proper Listener tracking\n runComputation(computation);\n\n return () => {\n stopped = true;\n cleanupSources(computation);\n if (cleanup) {\n cleanup();\n cleanup = undefined;\n }\n };\n}\n\n/**\n * Create a one-time effect that runs once and disposes\n */\nexport function once<T>(track: () => T, run: (value: T) => void): () => void {\n let hasRun = false;\n return on(track, (value) => {\n if (!hasRun) {\n hasRun = true;\n run(value);\n }\n });\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,GAAM,OAAgB,KAA4D;CAChG,IAAI;CACJ,IAAI;CACJ,IAAI,SAAS;CACb,IAAI,UAAU;CAEd,MAAM,cAAgC;EACpC,WAAW;AACT,OAAI,QACF;GAIF,MAAM,QAAQ,OAAO;AAGrB,kBAAA,cAAc;AACZ,QAAI,SAAS;AACX,cAAS;AACT,eAAU,KAAA;;IAGZ,MAAM,SAAS,IAAI,OAAO,SAAS,YAAa,MAAM;AACtD,QAAI,OAAO,WAAW,WACpB,WAAU;KAEZ;AAEF,eAAY;AACZ,YAAS;;EAGX,QAAQ,KAAA;EACR,UAAU;EACV,cAAc;EACd,YAAY;EACZ,gBAAgB;EAChB,QAAQA,eAAAA;EACR,WAAW;EACX,UAAU;EACV,WAAW;EACX,OAAO;EACP,OAAO;EACP,QAAQ;EACR,YAAY;EACb;AAGD,gBAAA,eAAe,YAAY;AAE3B,cAAa;AACX,YAAU;AACV,iBAAA,eAAe,YAAY;AAC3B,MAAI,SAAS;AACX,YAAS;AACT,aAAU,KAAA;;;;;;;AAQhB,SAAgB,KAAQ,OAAgB,KAAqC;CAC3E,IAAI,SAAS;AACb,QAAO,GAAG,QAAQ,UAAU;AAC1B,MAAI,CAAC,QAAQ;AACX,YAAS;AACT,OAAI,MAAM;;GAEZ"}
@@ -0,0 +1,17 @@
1
+ //#region src/watch/watcher.d.ts
2
+ /**
3
+ * Watchers and reactive effects for @hedystia/view
4
+ *
5
+ * Provides effect tracking and reactive subscriptions.
6
+ */
7
+ /**
8
+ * Create a reactive effect that runs when dependencies change
9
+ */
10
+ declare function on<T>(track: () => T, run: (value: T, prev: T) => any | (() => void)): () => void;
11
+ /**
12
+ * Create a one-time effect that runs once and disposes
13
+ */
14
+ declare function once<T>(track: () => T, run: (value: T) => void): () => void;
15
+ //#endregion
16
+ export { on, once };
17
+ //# sourceMappingURL=watcher.d.cts.map
@@ -0,0 +1,17 @@
1
+ //#region src/watch/watcher.d.ts
2
+ /**
3
+ * Watchers and reactive effects for @hedystia/view
4
+ *
5
+ * Provides effect tracking and reactive subscriptions.
6
+ */
7
+ /**
8
+ * Create a reactive effect that runs when dependencies change
9
+ */
10
+ declare function on<T>(track: () => T, run: (value: T, prev: T) => any | (() => void)): () => void;
11
+ /**
12
+ * Create a one-time effect that runs once and disposes
13
+ */
14
+ declare function once<T>(track: () => T, run: (value: T) => void): () => void;
15
+ //#endregion
16
+ export { on, once };
17
+ //# sourceMappingURL=watcher.d.mts.map
@@ -0,0 +1,70 @@
1
+ import { Owner, cleanupSources, runComputation, untrack } from "../signal/signal.mjs";
2
+ //#region src/watch/watcher.ts
3
+ /**
4
+ * Watchers and reactive effects for @hedystia/view
5
+ *
6
+ * Provides effect tracking and reactive subscriptions.
7
+ */
8
+ /**
9
+ * Create a reactive effect that runs when dependencies change
10
+ */
11
+ function on(track, run) {
12
+ let cleanup;
13
+ let prevValue;
14
+ let hasRun = false;
15
+ let stopped = false;
16
+ const computation = {
17
+ _fn: () => {
18
+ if (stopped) return;
19
+ const value = track();
20
+ untrack(() => {
21
+ if (cleanup) {
22
+ cleanup();
23
+ cleanup = void 0;
24
+ }
25
+ const result = run(value, hasRun ? prevValue : value);
26
+ if (typeof result === "function") cleanup = result;
27
+ });
28
+ prevValue = value;
29
+ hasRun = true;
30
+ },
31
+ _value: void 0,
32
+ _sources: null,
33
+ _sourceSlots: null,
34
+ _observers: null,
35
+ _observerSlots: null,
36
+ _owner: Owner,
37
+ _cleanups: null,
38
+ _context: null,
39
+ _suspense: null,
40
+ _user: true,
41
+ _pure: false,
42
+ _state: 0,
43
+ _updatedAt: null
44
+ };
45
+ runComputation(computation);
46
+ return () => {
47
+ stopped = true;
48
+ cleanupSources(computation);
49
+ if (cleanup) {
50
+ cleanup();
51
+ cleanup = void 0;
52
+ }
53
+ };
54
+ }
55
+ /**
56
+ * Create a one-time effect that runs once and disposes
57
+ */
58
+ function once(track, run) {
59
+ let hasRun = false;
60
+ return on(track, (value) => {
61
+ if (!hasRun) {
62
+ hasRun = true;
63
+ run(value);
64
+ }
65
+ });
66
+ }
67
+ //#endregion
68
+ export { on, once };
69
+
70
+ //# sourceMappingURL=watcher.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.mjs","names":[],"sources":["../../src/watch/watcher.ts"],"sourcesContent":["/**\n * Watchers and reactive effects for @hedystia/view\n *\n * Provides effect tracking and reactive subscriptions.\n */\n\nimport { cleanupSources, Owner, runComputation, untrack } from \"../signal\";\nimport type { Computation } from \"../types\";\n\n/**\n * Create a reactive effect that runs when dependencies change\n */\nexport function on<T>(track: () => T, run: (value: T, prev: T) => any | (() => void)): () => void {\n let cleanup: (() => void) | undefined;\n let prevValue: T | undefined;\n let hasRun = false;\n let stopped = false;\n\n const computation: Computation<any> = {\n _fn: () => {\n if (stopped) {\n return undefined;\n }\n\n // Track dependencies from the track function\n const value = track();\n\n // Run callback untracked so reads inside run() don't become dependencies\n untrack(() => {\n if (cleanup) {\n cleanup();\n cleanup = undefined;\n }\n\n const result = run(value, hasRun ? prevValue! : value);\n if (typeof result === \"function\") {\n cleanup = result;\n }\n });\n\n prevValue = value;\n hasRun = true;\n return undefined;\n },\n _value: undefined,\n _sources: null,\n _sourceSlots: null,\n _observers: null,\n _observerSlots: null,\n _owner: Owner,\n _cleanups: null,\n _context: null,\n _suspense: null,\n _user: true,\n _pure: false,\n _state: 0,\n _updatedAt: null,\n };\n\n // Run initial execution with proper Listener tracking\n runComputation(computation);\n\n return () => {\n stopped = true;\n cleanupSources(computation);\n if (cleanup) {\n cleanup();\n cleanup = undefined;\n }\n };\n}\n\n/**\n * Create a one-time effect that runs once and disposes\n */\nexport function once<T>(track: () => T, run: (value: T) => void): () => void {\n let hasRun = false;\n return on(track, (value) => {\n if (!hasRun) {\n hasRun = true;\n run(value);\n }\n });\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,GAAM,OAAgB,KAA4D;CAChG,IAAI;CACJ,IAAI;CACJ,IAAI,SAAS;CACb,IAAI,UAAU;CAEd,MAAM,cAAgC;EACpC,WAAW;AACT,OAAI,QACF;GAIF,MAAM,QAAQ,OAAO;AAGrB,iBAAc;AACZ,QAAI,SAAS;AACX,cAAS;AACT,eAAU,KAAA;;IAGZ,MAAM,SAAS,IAAI,OAAO,SAAS,YAAa,MAAM;AACtD,QAAI,OAAO,WAAW,WACpB,WAAU;KAEZ;AAEF,eAAY;AACZ,YAAS;;EAGX,QAAQ,KAAA;EACR,UAAU;EACV,cAAc;EACd,YAAY;EACZ,gBAAgB;EAChB,QAAQ;EACR,WAAW;EACX,UAAU;EACV,WAAW;EACX,OAAO;EACP,OAAO;EACP,QAAQ;EACR,YAAY;EACb;AAGD,gBAAe,YAAY;AAE3B,cAAa;AACX,YAAU;AACV,iBAAe,YAAY;AAC3B,MAAI,SAAS;AACX,YAAS;AACT,aAAU,KAAA;;;;;;;AAQhB,SAAgB,KAAQ,OAAgB,KAAqC;CAC3E,IAAI,SAAS;AACb,QAAO,GAAG,QAAQ,UAAU;AAC1B,MAAI,CAAC,QAAQ;AACX,YAAS;AACT,OAAI,MAAM;;GAEZ"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@hedystia/view",
3
+ "version": "2.1.0",
4
+ "description": "Reactive UI engine — fine-grained signals, no Virtual DOM, real DOM nodes",
5
+ "type": "commonjs",
6
+ "types": "./dist/index.d.cts",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.mjs",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.cts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./jsx-runtime": {
16
+ "types": "./dist/jsx-runtime.d.cts",
17
+ "import": "./dist/jsx-runtime.mjs",
18
+ "require": "./dist/jsx-runtime.cjs"
19
+ },
20
+ "./jsx-dev-runtime": {
21
+ "types": "./dist/jsx-dev-runtime.d.cts",
22
+ "import": "./dist/jsx-dev-runtime.mjs",
23
+ "require": "./dist/jsx-dev-runtime.cjs"
24
+ }
25
+ },
26
+ "scripts": {
27
+ "build": "tsdown --config-loader unrun",
28
+ "release:pkg": "bun publish --provenance --access public",
29
+ "dev": "tsdown --watch"
30
+ },
31
+ "peerDependencies": {
32
+ "typescript": ">= 6.0.0"
33
+ }
34
+ }