@fictjs/runtime 0.0.13 → 0.0.15

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 (52) hide show
  1. package/dist/advanced.cjs +79 -0
  2. package/dist/advanced.cjs.map +1 -0
  3. package/dist/advanced.d.cts +50 -0
  4. package/dist/advanced.d.ts +50 -0
  5. package/dist/advanced.js +79 -0
  6. package/dist/advanced.js.map +1 -0
  7. package/dist/chunk-624QY53A.cjs +45 -0
  8. package/dist/chunk-624QY53A.cjs.map +1 -0
  9. package/dist/chunk-F3AIYQB7.js +45 -0
  10. package/dist/chunk-F3AIYQB7.js.map +1 -0
  11. package/dist/chunk-GJTYOFMO.cjs +109 -0
  12. package/dist/chunk-GJTYOFMO.cjs.map +1 -0
  13. package/dist/chunk-IUZXKAAY.js +109 -0
  14. package/dist/chunk-IUZXKAAY.js.map +1 -0
  15. package/dist/chunk-PMF6MWEV.cjs +3301 -0
  16. package/dist/chunk-PMF6MWEV.cjs.map +1 -0
  17. package/dist/chunk-RY4WDS6R.js +3301 -0
  18. package/dist/chunk-RY4WDS6R.js.map +1 -0
  19. package/dist/context-B7UYnfzM.d.ts +153 -0
  20. package/dist/context-UXySaqI_.d.cts +153 -0
  21. package/dist/effect-Auji1rz9.d.cts +350 -0
  22. package/dist/effect-Auji1rz9.d.ts +350 -0
  23. package/dist/index.cjs +98 -3558
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +5 -1358
  26. package/dist/index.d.ts +5 -1358
  27. package/dist/index.dev.js +240 -1698
  28. package/dist/index.dev.js.map +1 -1
  29. package/dist/index.js +63 -3435
  30. package/dist/index.js.map +1 -1
  31. package/dist/internal.cjs +901 -0
  32. package/dist/internal.cjs.map +1 -0
  33. package/dist/internal.d.cts +158 -0
  34. package/dist/internal.d.ts +158 -0
  35. package/dist/internal.js +901 -0
  36. package/dist/internal.js.map +1 -0
  37. package/dist/{jsx-dev-runtime.d.ts → props-CrOMYbLv.d.cts} +107 -18
  38. package/dist/{jsx-dev-runtime.d.cts → props-ES0Ag_Wd.d.ts} +107 -18
  39. package/dist/scope-DKYzWfTn.d.cts +55 -0
  40. package/dist/scope-S6eAzBJZ.d.ts +55 -0
  41. package/package.json +11 -1
  42. package/src/advanced.ts +101 -0
  43. package/src/constants.ts +3 -26
  44. package/src/context.ts +300 -0
  45. package/src/delegated-events.ts +24 -0
  46. package/src/index.ts +41 -112
  47. package/src/internal.ts +130 -0
  48. package/src/props.ts +48 -46
  49. package/src/store.ts +47 -7
  50. package/src/versioned-signal.ts +3 -3
  51. package/dist/jsx-runtime.d.cts +0 -671
  52. package/dist/jsx-runtime.d.ts +0 -671
@@ -0,0 +1,350 @@
1
+ /** Any DOM node that can be rendered */
2
+ type DOMElement = Node;
3
+ /** Cleanup function type */
4
+ type Cleanup = () => void;
5
+ /** Fict Virtual Node - represents a component or element in the virtual tree */
6
+ interface FictVNode {
7
+ /** Element type: tag name, Fragment symbol, or component function */
8
+ type: string | symbol | ((props: Record<string, unknown>) => FictNode);
9
+ /** Props passed to the element/component */
10
+ props: Record<string, unknown> | null;
11
+ /** Optional key for list rendering optimization */
12
+ key?: string | undefined;
13
+ }
14
+ /**
15
+ * Fict Node - represents any renderable value
16
+ * This type covers all possible values that can appear in JSX
17
+ */
18
+ type FictNode = FictVNode | FictNode[] | Node | string | number | boolean | null | undefined;
19
+ /** Props that all components receive */
20
+ interface BaseProps {
21
+ /** Optional key for list rendering */
22
+ key?: string | number;
23
+ /** Optional children */
24
+ children?: FictNode | FictNode[];
25
+ }
26
+ /** A Fict component function */
27
+ type Component<P extends Record<string, unknown> = Record<string, unknown>> = (props: P & BaseProps) => FictNode;
28
+ /** Props with children */
29
+ type PropsWithChildren<P = unknown> = P & {
30
+ children?: FictNode | FictNode[];
31
+ };
32
+ interface ErrorInfo {
33
+ source: 'render' | 'effect' | 'event' | 'renderChild' | 'cleanup';
34
+ componentName?: string;
35
+ eventName?: string;
36
+ }
37
+ /** Event handler type for type-safe event handling */
38
+ type EventHandler<E extends Event = Event> = (event: E) => void;
39
+ /** Ref callback type */
40
+ type RefCallback<T extends Element = HTMLElement> = (element: T) => void;
41
+ /** Ref object type (for future use with createRef) */
42
+ interface RefObject<T extends Element = HTMLElement> {
43
+ current: T | null;
44
+ }
45
+ /** Ref type that can be either callback or object */
46
+ type Ref<T extends Element = HTMLElement> = RefCallback<T> | RefObject<T>;
47
+ /** CSS style value - can be string or number (number becomes px) */
48
+ type StyleValue = string | number;
49
+ /** CSS style object */
50
+ type CSSStyleObject = {
51
+ [K in keyof CSSStyleDeclaration]?: StyleValue;
52
+ } & Record<string, StyleValue>;
53
+ /** Style prop type - can be string or object */
54
+ type StyleProp = string | CSSStyleObject | null | undefined;
55
+ /** Class object for conditional classes */
56
+ type ClassObject = Record<string, boolean | undefined | null>;
57
+ /** Class prop type - can be string or object */
58
+ type ClassProp = string | ClassObject | null | undefined;
59
+ interface SuspenseToken {
60
+ then: Promise<unknown>['then'];
61
+ }
62
+
63
+ /**
64
+ * Fict Reactive DOM Binding System
65
+ *
66
+ * This module provides the core mechanisms for reactive DOM updates.
67
+ * It bridges the gap between Fict's reactive system (signals, effects)
68
+ * and the DOM, enabling fine-grained updates without a virtual DOM.
69
+ *
70
+ * Design Philosophy:
71
+ * - Values wrapped in functions `() => T` are treated as reactive
72
+ * - Static values are applied once without tracking
73
+ * - The compiler transforms JSX expressions to use these primitives
74
+ */
75
+
76
+ /** A reactive value that can be either static or a getter function */
77
+ type MaybeReactive<T> = T | (() => T);
78
+ /** Internal type for createElement function reference */
79
+ type CreateElementFn = (node: FictNode) => Node;
80
+ /** Handle returned by conditional/list bindings for cleanup */
81
+ interface BindingHandle {
82
+ /** Marker node(s) used for positioning */
83
+ marker: Comment | DocumentFragment;
84
+ /** Flush pending content - call after markers are inserted into DOM */
85
+ flush?: () => void;
86
+ /** Dispose function to clean up the binding */
87
+ dispose: Cleanup;
88
+ }
89
+ /** Managed child node with its dispose function */
90
+ /**
91
+ * Check if a value is reactive (a getter function)
92
+ * Note: Event handlers (functions that take arguments) are NOT reactive values
93
+ */
94
+ declare function isReactive(value: unknown): value is () => unknown;
95
+ /**
96
+ * Unwrap a potentially reactive value to get the actual value
97
+ */
98
+ declare function unwrap<T>(value: MaybeReactive<T>): T;
99
+ /**
100
+ * Invoke an event handler or handler accessor in a safe way.
101
+ * Supports handlers that return another handler and handlers that expect an
102
+ * optional data payload followed by the event.
103
+ */
104
+ declare function callEventHandler(handler: EventListenerOrEventListenerObject | null | undefined, event: Event, node?: EventTarget | null, data?: unknown): void;
105
+ /**
106
+ * Create a text node that reactively updates when the value changes.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * // Static text
111
+ * createTextBinding("Hello")
112
+ *
113
+ * // Reactive text (compiler output)
114
+ * createTextBinding(() => $count())
115
+ * ```
116
+ */
117
+ declare function createTextBinding(value: MaybeReactive<unknown>): Text;
118
+ /**
119
+ * Bind a reactive value to an existing text node.
120
+ * This is a convenience function for binding to existing DOM nodes.
121
+ */
122
+ declare function bindText(textNode: Text, getValue: () => unknown): Cleanup;
123
+ /** Attribute setter function type */
124
+ type AttributeSetter = (el: Element, key: string, value: unknown) => void;
125
+ /**
126
+ * Create a reactive attribute binding on an element.
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * // Static attribute
131
+ * createAttributeBinding(button, 'disabled', false, setAttribute)
132
+ *
133
+ * // Reactive attribute (compiler output)
134
+ * createAttributeBinding(button, 'disabled', () => !$isValid(), setAttribute)
135
+ * ```
136
+ */
137
+ declare function createAttributeBinding(el: Element, key: string, value: MaybeReactive<unknown>, setter: AttributeSetter): void;
138
+ /**
139
+ * Bind a reactive value to an element's attribute.
140
+ */
141
+ declare function bindAttribute(el: Element, key: string, getValue: () => unknown): Cleanup;
142
+ /**
143
+ * Bind a reactive value to an element's property.
144
+ */
145
+ declare function bindProperty(el: Element, key: string, getValue: () => unknown): Cleanup;
146
+ /**
147
+ * Apply styles to an element, supporting reactive style objects/strings.
148
+ */
149
+ declare function createStyleBinding(el: Element, value: MaybeReactive<string | Record<string, string | number> | null | undefined>): void;
150
+ /**
151
+ * Bind a reactive style value to an existing element.
152
+ */
153
+ declare function bindStyle(el: Element, getValue: () => string | Record<string, string | number> | null | undefined): Cleanup;
154
+ /**
155
+ * Apply class to an element, supporting reactive class values.
156
+ */
157
+ declare function createClassBinding(el: Element, value: MaybeReactive<string | Record<string, boolean> | null | undefined>): void;
158
+ /**
159
+ * Bind a reactive class value to an existing element.
160
+ */
161
+ declare function bindClass(el: Element, getValue: () => string | Record<string, boolean> | null | undefined): Cleanup;
162
+ /**
163
+ * Exported classList function for direct use (compatible with dom-expressions)
164
+ */
165
+ declare function classList(node: Element, value: Record<string, boolean> | null | undefined, prev?: Record<string, boolean>): Record<string, boolean>;
166
+ /**
167
+ * Insert reactive content into a parent element.
168
+ * This is a simpler API than createChildBinding for basic cases.
169
+ *
170
+ * @param parent - The parent element to insert into
171
+ * @param getValue - Function that returns the value to render
172
+ * @param markerOrCreateElement - Optional marker node to insert before, or createElementFn
173
+ * @param createElementFn - Optional function to create DOM elements (when marker is provided)
174
+ */
175
+ declare function insert(parent: ParentNode & Node, getValue: () => FictNode, markerOrCreateElement?: Node | CreateElementFn, createElementFn?: CreateElementFn): Cleanup;
176
+ /**
177
+ * Create a reactive child binding that updates when the child value changes.
178
+ * This is used for dynamic expressions like `{show && <Modal />}` or `{items.map(...)}`.
179
+ *
180
+ * @example
181
+ * ```ts
182
+ * // Reactive child (compiler output for {count})
183
+ * createChildBinding(parent, () => $count(), createElement)
184
+ *
185
+ * // Reactive conditional (compiler output for {show && <Modal />})
186
+ * createChildBinding(parent, () => $show() && jsx(Modal, {}), createElement)
187
+ * ```
188
+ */
189
+ declare function createChildBinding(parent: ParentNode & Node, getValue: () => FictNode, createElementFn: CreateElementFn): BindingHandle;
190
+ declare global {
191
+ interface Element {
192
+ _$host?: Element;
193
+ [key: `$$${string}`]: EventListener | [EventListener, unknown] | undefined;
194
+ [key: `$$${string}Data`]: unknown;
195
+ }
196
+ interface Document extends Record<string, unknown> {
197
+ }
198
+ }
199
+ /**
200
+ * Initialize event delegation for a set of event names.
201
+ * Events will be handled at the document level and dispatched to the appropriate handlers.
202
+ *
203
+ * @param eventNames - Array of event names to delegate
204
+ * @param doc - The document to attach handlers to (default: window.document)
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * // Called automatically by the compiler for delegated events
209
+ * delegateEvents(['click', 'input', 'keydown'])
210
+ * ```
211
+ */
212
+ declare function delegateEvents(eventNames: string[], doc?: Document): void;
213
+ /**
214
+ * Clear all delegated event handlers from a document.
215
+ *
216
+ * @param doc - The document to clear handlers from (default: window.document)
217
+ */
218
+ declare function clearDelegatedEvents(doc?: Document): void;
219
+ /**
220
+ * Add an event listener to an element.
221
+ * If the event is in DelegatedEvents, it uses event delegation for better performance.
222
+ *
223
+ * @param node - The element to add the listener to
224
+ * @param name - The event name (lowercase)
225
+ * @param handler - The event handler or [handler, data] tuple
226
+ * @param delegate - Whether to use delegation (auto-detected based on event name)
227
+ */
228
+ declare function addEventListener(node: Element, name: string, handler: EventListener | [EventListener, unknown] | null | undefined, delegate?: boolean): void;
229
+ /**
230
+ * Bind an event listener to an element.
231
+ * Uses event delegation for better performance when applicable.
232
+ *
233
+ * @example
234
+ * ```ts
235
+ * // Static event
236
+ * bindEvent(button, 'click', handleClick)
237
+ *
238
+ * // Reactive event (compiler output)
239
+ * bindEvent(button, 'click', () => $handler())
240
+ *
241
+ * // With modifiers
242
+ * bindEvent(button, 'click', handler, { capture: true, passive: true, once: true })
243
+ * ```
244
+ */
245
+ declare function bindEvent(el: Element, eventName: string, handler: EventListenerOrEventListenerObject | null | undefined, options?: boolean | AddEventListenerOptions): Cleanup;
246
+ /**
247
+ * Bind a ref to an element.
248
+ * Supports both callback refs and ref objects.
249
+ *
250
+ * @param el - The element to bind the ref to
251
+ * @param ref - Either a callback function, a ref object, or a reactive getter
252
+ * @returns Cleanup function
253
+ *
254
+ * @example
255
+ * ```ts
256
+ * // Callback ref
257
+ * bindRef(el, (element) => { store.input = element })
258
+ *
259
+ * // Ref object
260
+ * const inputRef = createRef()
261
+ * bindRef(el, inputRef)
262
+ *
263
+ * // Reactive ref (compiler output)
264
+ * bindRef(el, () => props.ref)
265
+ * ```
266
+ */
267
+ declare function bindRef(el: Element, ref: unknown): Cleanup;
268
+ /**
269
+ * Apply spread props to an element with reactive updates.
270
+ * This handles dynamic spread like `<div {...props}>`.
271
+ *
272
+ * @param node - The element to apply props to
273
+ * @param props - The props object (may have reactive getters)
274
+ * @param isSVG - Whether this is an SVG element
275
+ * @param skipChildren - Whether to skip children handling
276
+ * @returns The previous props for tracking changes
277
+ *
278
+ * @example
279
+ * ```ts
280
+ * // Compiler output for <div {...props} />
281
+ * spread(el, props, false, false)
282
+ * ```
283
+ */
284
+ declare function spread(node: Element, props?: Record<string, unknown>, isSVG?: boolean, skipChildren?: boolean): Record<string, unknown>;
285
+ /**
286
+ * Assign props to a node, tracking previous values for efficient updates.
287
+ * This is the core prop assignment logic used by spread.
288
+ *
289
+ * @param node - The element to assign props to
290
+ * @param props - New props object
291
+ * @param isSVG - Whether this is an SVG element
292
+ * @param skipChildren - Whether to skip children handling
293
+ * @param prevProps - Previous props for comparison
294
+ * @param skipRef - Whether to skip ref handling
295
+ */
296
+ declare function assign(node: Element, props: Record<string, unknown>, isSVG?: boolean, skipChildren?: boolean, prevProps?: Record<string, unknown>, skipRef?: boolean): void;
297
+ /**
298
+ * Create a conditional rendering binding.
299
+ * Efficiently renders one of two branches based on a condition.
300
+ *
301
+ * This is an optimized version for `{condition ? <A /> : <B />}` patterns
302
+ * where both branches are known statically.
303
+ *
304
+ * @example
305
+ * ```ts
306
+ * // Compiler output for {show ? <A /> : <B />}
307
+ * createConditional(
308
+ * () => $show(),
309
+ * () => jsx(A, {}),
310
+ * () => jsx(B, {}),
311
+ * createElement
312
+ * )
313
+ * ```
314
+ */
315
+ declare function createConditional(condition: () => boolean, renderTrue: () => FictNode, createElementFn: CreateElementFn, renderFalse?: () => FictNode): BindingHandle;
316
+ /**
317
+ * Create a show/hide binding that uses CSS display instead of DOM manipulation.
318
+ * More efficient than conditional when the content is expensive to create.
319
+ *
320
+ * @example
321
+ * ```ts
322
+ * createShow(container, () => $visible())
323
+ * ```
324
+ */
325
+ declare function createShow(el: Element & {
326
+ style: CSSStyleDeclaration;
327
+ }, condition: () => boolean, displayValue?: string): void;
328
+ /**
329
+ * Create a portal that renders content into a different DOM container.
330
+ *
331
+ * @example
332
+ * ```ts
333
+ * createPortal(
334
+ * document.body,
335
+ * () => jsx(Modal, { children: 'Hello' }),
336
+ * createElement
337
+ * )
338
+ * ```
339
+ */
340
+ declare function createPortal(container: ParentNode & Node, render: () => FictNode, createElementFn: CreateElementFn): BindingHandle;
341
+
342
+ /**
343
+ * Effect callback run synchronously; async callbacks are not tracked after the first await.
344
+ * TypeScript will reject `async () => {}` here—split async work or read signals before awaiting.
345
+ */
346
+ type Effect = () => void | Cleanup;
347
+ declare function createEffect(fn: Effect): () => void;
348
+ declare function createRenderEffect(fn: Effect): () => void;
349
+
350
+ export { bindRef as A, type BaseProps as B, type Cleanup as C, type DOMElement as D, type Effect as E, type FictNode as F, insert as G, createConditional as H, spread as I, assign as J, classList as K, delegateEvents as L, clearDelegatedEvents as M, addEventListener as N, type MaybeReactive as O, type PropsWithChildren as P, type BindingHandle as Q, type RefObject as R, type SuspenseToken as S, type CreateElementFn as T, type AttributeSetter as U, createChildBinding as a, createAttributeBinding as b, createTextBinding as c, createStyleBinding as d, createClassBinding as e, createShow as f, createRenderEffect as g, createEffect as h, isReactive as i, createPortal as j, type FictVNode as k, type Component as l, type Ref as m, type RefCallback as n, type StyleProp as o, type ClassProp as p, type EventHandler as q, type ErrorInfo as r, bindText as s, bindAttribute as t, unwrap as u, bindStyle as v, bindClass as w, bindEvent as x, callEventHandler as y, bindProperty as z };