@fictjs/runtime 0.0.12 → 0.0.13

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/slim.d.cts DELETED
@@ -1,504 +0,0 @@
1
- /**
2
- * Signal accessor - function to get/set signal value
3
- */
4
- interface SignalAccessor<T> {
5
- (): T;
6
- (value: T): void;
7
- }
8
- /**
9
- * Computed accessor - function to get computed value
10
- */
11
- type ComputedAccessor<T> = () => T;
12
- /**
13
- * Effect scope disposer - function to dispose an effect scope
14
- */
15
- type EffectScopeDisposer = () => void;
16
- /**
17
- * Create a reactive signal
18
- * @param initialValue - The initial value
19
- * @returns A signal accessor function
20
- */
21
- declare function signal<T>(initialValue: T): SignalAccessor<T>;
22
- /**
23
- * Create a reactive effect scope
24
- * @param fn - The scope function
25
- * @returns An effect scope disposer function
26
- */
27
- declare function effectScope(fn: () => void): EffectScopeDisposer;
28
- declare const $state: <T>(value: T) => T;
29
- /**
30
- * Create a selector signal that efficiently updates only when the selected key matches.
31
- * Useful for large lists where only one item is selected.
32
- *
33
- * @param source - The source signal returning the current key
34
- * @param equalityFn - Optional equality function
35
- * @returns A selector function that takes a key and returns a boolean signal accessor
36
- */
37
- declare function createSelector<T>(source: () => T, equalityFn?: (a: T, b: T) => boolean): (key: T) => boolean;
38
-
39
- type Memo<T> = () => T;
40
- declare function createMemo<T>(fn: () => T): Memo<T>;
41
-
42
- /** Any DOM node that can be rendered */
43
- type DOMElement = Node;
44
- /** Cleanup function type */
45
- type Cleanup = () => void;
46
- /** Fict Virtual Node - represents a component or element in the virtual tree */
47
- interface FictVNode {
48
- /** Element type: tag name, Fragment symbol, or component function */
49
- type: string | symbol | ((props: Record<string, unknown>) => FictNode);
50
- /** Props passed to the element/component */
51
- props: Record<string, unknown> | null;
52
- /** Optional key for list rendering optimization */
53
- key?: string | undefined;
54
- }
55
- /**
56
- * Fict Node - represents any renderable value
57
- * This type covers all possible values that can appear in JSX
58
- */
59
- type FictNode = FictVNode | FictNode[] | Node | string | number | boolean | null | undefined;
60
- interface ErrorInfo {
61
- source: 'render' | 'effect' | 'event' | 'renderChild' | 'cleanup';
62
- componentName?: string;
63
- eventName?: string;
64
- }
65
- interface SuspenseToken {
66
- then: Promise<unknown>['then'];
67
- }
68
-
69
- type Effect = () => void | Cleanup;
70
- declare function createEffect(fn: Effect): () => void;
71
- declare function createRenderEffect(fn: Effect): () => void;
72
-
73
- /**
74
- * Fict Reactive DOM Binding System
75
- *
76
- * This module provides the core mechanisms for reactive DOM updates.
77
- * It bridges the gap between Fict's reactive system (signals, effects)
78
- * and the DOM, enabling fine-grained updates without a virtual DOM.
79
- *
80
- * Design Philosophy:
81
- * - Values wrapped in functions `() => T` are treated as reactive
82
- * - Static values are applied once without tracking
83
- * - The compiler transforms JSX expressions to use these primitives
84
- */
85
-
86
- /** A reactive value that can be either static or a getter function */
87
- type MaybeReactive<T> = T | (() => T);
88
- /** Internal type for createElement function reference */
89
- type CreateElementFn = (node: FictNode) => Node;
90
- /** Handle returned by conditional/list bindings for cleanup */
91
- interface BindingHandle {
92
- /** Marker node(s) used for positioning */
93
- marker: Comment | DocumentFragment;
94
- /** Flush pending content - call after markers are inserted into DOM */
95
- flush?: () => void;
96
- /** Dispose function to clean up the binding */
97
- dispose: Cleanup;
98
- }
99
- /**
100
- * Bind a reactive value to an existing text node.
101
- * This is a convenience function for binding to existing DOM nodes.
102
- */
103
- declare function bindText(textNode: Text, getValue: () => unknown): Cleanup;
104
- /**
105
- * Bind a reactive value to an element's attribute.
106
- */
107
- declare function bindAttribute(el: Element, key: string, getValue: () => unknown): Cleanup;
108
- /**
109
- * Bind a reactive value to an element's property.
110
- */
111
- declare function bindProperty(el: Element, key: string, getValue: () => unknown): Cleanup;
112
- /**
113
- * Bind a reactive style value to an existing element.
114
- */
115
- declare function bindStyle(el: Element, getValue: () => string | Record<string, string | number> | null | undefined): Cleanup;
116
- /**
117
- * Bind a reactive class value to an existing element.
118
- */
119
- declare function bindClass(el: Element, getValue: () => string | Record<string, boolean> | null | undefined): Cleanup;
120
- /**
121
- * Insert reactive content into a parent element.
122
- * This is a simpler API than createChildBinding for basic cases.
123
- *
124
- * @param parent - The parent element to insert into
125
- * @param getValue - Function that returns the value to render
126
- * @param markerOrCreateElement - Optional marker node to insert before, or createElementFn
127
- * @param createElementFn - Optional function to create DOM elements (when marker is provided)
128
- */
129
- declare function insert(parent: ParentNode & Node, getValue: () => FictNode, markerOrCreateElement?: Node | CreateElementFn, createElementFn?: CreateElementFn): Cleanup;
130
- declare global {
131
- interface Element {
132
- _$host?: Element;
133
- [key: `$$${string}`]: EventListener | [EventListener, unknown] | undefined;
134
- [key: `$$${string}Data`]: unknown;
135
- }
136
- interface Document extends Record<string, unknown> {
137
- }
138
- }
139
- /**
140
- * Initialize event delegation for a set of event names.
141
- * Events will be handled at the document level and dispatched to the appropriate handlers.
142
- *
143
- * @param eventNames - Array of event names to delegate
144
- * @param doc - The document to attach handlers to (default: window.document)
145
- *
146
- * @example
147
- * ```ts
148
- * // Called automatically by the compiler for delegated events
149
- * delegateEvents(['click', 'input', 'keydown'])
150
- * ```
151
- */
152
- declare function delegateEvents(eventNames: string[], doc?: Document): void;
153
- /**
154
- * Clear all delegated event handlers from a document.
155
- *
156
- * @param doc - The document to clear handlers from (default: window.document)
157
- */
158
- declare function clearDelegatedEvents(doc?: Document): void;
159
- /**
160
- * Bind an event listener to an element.
161
- * Uses event delegation for better performance when applicable.
162
- *
163
- * @example
164
- * ```ts
165
- * // Static event
166
- * bindEvent(button, 'click', handleClick)
167
- *
168
- * // Reactive event (compiler output)
169
- * bindEvent(button, 'click', () => $handler())
170
- *
171
- * // With modifiers
172
- * bindEvent(button, 'click', handler, { capture: true, passive: true, once: true })
173
- * ```
174
- */
175
- declare function bindEvent(el: Element, eventName: string, handler: EventListenerOrEventListenerObject | null | undefined, options?: boolean | AddEventListenerOptions): Cleanup;
176
- /**
177
- * Bind a ref to an element.
178
- * Supports both callback refs and ref objects.
179
- *
180
- * @param el - The element to bind the ref to
181
- * @param ref - Either a callback function, a ref object, or a reactive getter
182
- * @returns Cleanup function
183
- *
184
- * @example
185
- * ```ts
186
- * // Callback ref
187
- * bindRef(el, (element) => { store.input = element })
188
- *
189
- * // Ref object
190
- * const inputRef = createRef()
191
- * bindRef(el, inputRef)
192
- *
193
- * // Reactive ref (compiler output)
194
- * bindRef(el, () => props.ref)
195
- * ```
196
- */
197
- declare function bindRef(el: Element, ref: unknown): Cleanup;
198
- /**
199
- * Create a conditional rendering binding.
200
- * Efficiently renders one of two branches based on a condition.
201
- *
202
- * This is an optimized version for `{condition ? <A /> : <B />}` patterns
203
- * where both branches are known statically.
204
- *
205
- * @example
206
- * ```ts
207
- * // Compiler output for {show ? <A /> : <B />}
208
- * createConditional(
209
- * () => $show(),
210
- * () => jsx(A, {}),
211
- * () => jsx(B, {}),
212
- * createElement
213
- * )
214
- * ```
215
- */
216
- declare function createConditional(condition: () => boolean, renderTrue: () => FictNode, createElementFn: CreateElementFn, renderFalse?: () => FictNode): BindingHandle;
217
- /** Key extractor function type */
218
- type KeyFn<T> = (item: T, index: number) => string | number;
219
- /**
220
- * Create a reactive list rendering binding with optional keying.
221
- * The render callback receives signal accessors for the item and index.
222
- */
223
- declare function createList<T>(items: () => T[], renderItem: (item: SignalAccessor<T>, index: SignalAccessor<number>) => FictNode, createElementFn: CreateElementFn, getKey?: KeyFn<T>): BindingHandle;
224
-
225
- interface ReactiveScope {
226
- run<T>(fn: () => T): T;
227
- stop(): void;
228
- }
229
- /**
230
- * Create an explicit reactive scope that can contain effects/memos and be stopped manually.
231
- * The scope registers with the current root for cleanup.
232
- */
233
- declare function createScope(): ReactiveScope;
234
- /**
235
- * Run a block of reactive code inside a managed scope that follows a boolean flag.
236
- * When the flag turns false, the scope is disposed and all contained effects/memos are cleaned up.
237
- */
238
- declare function runInScope(flag: MaybeReactive<boolean>, fn: () => void): void;
239
-
240
- declare function batch<T>(fn: () => T): T;
241
- declare function untrack<T>(fn: () => T): T;
242
-
243
- /**
244
- * Fict DOM Rendering System
245
- *
246
- * This module provides DOM rendering capabilities with reactive bindings.
247
- * It transforms JSX virtual nodes into actual DOM elements, automatically
248
- * setting up reactive updates for dynamic values.
249
- *
250
- * Key Features:
251
- * - Reactive text content: `{count}` updates when count changes
252
- * - Reactive attributes: `disabled={!isValid}` updates reactively
253
- * - Reactive children: `{show && <Modal />}` handles conditionals
254
- * - List rendering: `{items.map(...)}` with efficient keyed updates
255
- */
256
-
257
- /**
258
- * Render a Fict view into a container element.
259
- *
260
- * @param view - A function that returns the view to render
261
- * @param container - The DOM container to render into
262
- * @returns A teardown function to unmount the view
263
- *
264
- * @example
265
- * ```ts
266
- * const unmount = render(() => <App />, document.getElementById('root')!)
267
- * // Later: unmount()
268
- * ```
269
- */
270
- declare function render(view: () => FictNode, container: HTMLElement): () => void;
271
- /**
272
- * Create a DOM element from a Fict node.
273
- * This is the main entry point for converting virtual nodes to real DOM.
274
- *
275
- * Supports:
276
- * - Native DOM nodes (passed through)
277
- * - Null/undefined/false (empty text node)
278
- * - Arrays (DocumentFragment)
279
- * - Strings/numbers (text nodes)
280
- * - Booleans (empty text node)
281
- * - VNodes (components or HTML elements)
282
- * - Reactive values (functions returning any of the above)
283
- */
284
- declare function createElement(node: FictNode): DOMElement;
285
- /**
286
- * Create a template cloning factory from an HTML string.
287
- * Used by the compiler for efficient DOM generation.
288
- *
289
- * @param html - The HTML string to create a template from
290
- * @param isImportNode - Use importNode for elements like img/iframe
291
- * @param isSVG - Whether the template is SVG content
292
- * @param isMathML - Whether the template is MathML content
293
- */
294
- declare function template(html: string, isImportNode?: boolean, isSVG?: boolean, isMathML?: boolean): () => Node;
295
-
296
- declare const Fragment: unique symbol;
297
-
298
- type LifecycleFn = () => void | Cleanup;
299
- interface RootContext {
300
- parent?: RootContext | undefined;
301
- onMountCallbacks?: LifecycleFn[];
302
- cleanups: Cleanup[];
303
- destroyCallbacks: Cleanup[];
304
- errorHandlers?: ErrorHandler[];
305
- suspenseHandlers?: SuspenseHandler[];
306
- }
307
- type ErrorHandler = (err: unknown, info?: ErrorInfo) => boolean | void;
308
- type SuspenseHandler = (token: SuspenseToken | PromiseLike<unknown>) => boolean | void;
309
- declare function onDestroy(fn: LifecycleFn): void;
310
-
311
- /**
312
- * Low-level DOM node helpers shared across runtime modules.
313
- * Keep this file dependency-free to avoid module cycles.
314
- */
315
- /**
316
- * Convert a value to a flat array of DOM nodes.
317
- * Defensively handles proxies and non-DOM values.
318
- */
319
- declare function toNodeArray(node: Node | Node[] | unknown): Node[];
320
- /**
321
- * Insert nodes before an anchor node, preserving order.
322
- * Uses DocumentFragment for batch insertion when inserting multiple nodes.
323
- */
324
- declare function insertNodesBefore(parent: ParentNode & Node, nodes: Node[], anchor: Node | null): void;
325
- /**
326
- * Remove an array of nodes from the DOM.
327
- */
328
- declare function removeNodes(nodes: Node[]): void;
329
-
330
- /**
331
- * List Helpers for Compiler-Generated Fine-Grained Updates
332
- *
333
- * These helpers are used by the compiler to generate efficient keyed list rendering.
334
- * They provide low-level primitives for DOM node manipulation without rebuilding.
335
- */
336
-
337
- /**
338
- * A keyed block represents a single item in a list with its associated DOM nodes and state
339
- */
340
- interface KeyedBlock<T = unknown> {
341
- /** Unique key for this block */
342
- key: string | number;
343
- /** DOM nodes belonging to this block */
344
- nodes: Node[];
345
- /** Root context for lifecycle management */
346
- root: RootContext;
347
- /** Signal containing the current item value */
348
- item: SignalAccessor<T>;
349
- /** Signal containing the current index */
350
- index: SignalAccessor<number>;
351
- /** Last raw item value assigned to this block */
352
- rawItem: T;
353
- /** Last raw index value assigned to this block */
354
- rawIndex: number;
355
- }
356
- /**
357
- * Container for managing keyed list blocks
358
- */
359
- interface KeyedListContainer<T = unknown> {
360
- /** Start marker comment node */
361
- startMarker: Comment;
362
- /** End marker comment node */
363
- endMarker: Comment;
364
- /** Map of key to block */
365
- blocks: Map<string | number, KeyedBlock<T>>;
366
- /** Scratch map reused for the next render */
367
- nextBlocks: Map<string | number, KeyedBlock<T>>;
368
- /** Current nodes in DOM order (including markers) */
369
- currentNodes: Node[];
370
- /** Next-frame node buffer to avoid reallocations */
371
- nextNodes: Node[];
372
- /** Ordered blocks in current DOM order */
373
- orderedBlocks: KeyedBlock<T>[];
374
- /** Next-frame ordered block buffer to avoid reallocations */
375
- nextOrderedBlocks: KeyedBlock<T>[];
376
- /** Track position of keys in the ordered buffer to handle duplicates */
377
- orderedIndexByKey: Map<string | number, number>;
378
- /** Cleanup function */
379
- dispose: () => void;
380
- }
381
- /**
382
- * Binding handle returned by createKeyedList for compiler-generated code
383
- */
384
- interface KeyedListBinding {
385
- /** Document fragment placeholder inserted by the compiler/runtime */
386
- marker: DocumentFragment;
387
- /** Start marker comment node */
388
- startMarker: Comment;
389
- /** End marker comment node */
390
- endMarker: Comment;
391
- /** Flush pending items - call after markers are inserted into DOM */
392
- flush?: () => void;
393
- /** Cleanup function */
394
- dispose: () => void;
395
- }
396
- type FineGrainedRenderItem<T> = (itemSig: SignalAccessor<T>, indexSig: SignalAccessor<number>, key: string | number) => Node[];
397
- /**
398
- * A block identified by start/end comment markers.
399
- */
400
- interface MarkerBlock {
401
- start: Comment;
402
- end: Comment;
403
- root?: RootContext;
404
- }
405
- /**
406
- * Remove an array of nodes from the DOM
407
- *
408
- * @param nodes - Array of nodes to remove
409
- */
410
- /**
411
- * Move an entire marker-delimited block (including markers) before the anchor.
412
- */
413
- declare function moveMarkerBlock(parent: Node, block: MarkerBlock, anchor: Node | null): void;
414
- /**
415
- * Destroy a marker-delimited block, removing nodes and destroying the associated root.
416
- */
417
- declare function destroyMarkerBlock(block: MarkerBlock): void;
418
- /**
419
- * Create a container for managing a keyed list.
420
- * This sets up the marker nodes and provides cleanup.
421
- *
422
- * @returns Container object with markers, blocks map, and dispose function
423
- */
424
- declare function createKeyedListContainer<T = unknown>(): KeyedListContainer<T>;
425
- /**
426
- * Create a new keyed block with the given render function
427
- *
428
- * @param key - Unique key for this block
429
- * @param item - Initial item value
430
- * @param index - Initial index
431
- * @param render - Function that creates the DOM nodes and sets up bindings
432
- * @returns New KeyedBlock
433
- */
434
- declare function createKeyedBlock<T>(key: string | number, item: T, index: number, render: (item: SignalAccessor<T>, index: SignalAccessor<number>, key: string | number) => Node[], needsIndex?: boolean, hostRoot?: RootContext): KeyedBlock<T>;
435
- /**
436
- * Find the first node after the start marker (for getting current anchor)
437
- */
438
- declare function getFirstNodeAfter(marker: Comment): Node | null;
439
- /**
440
- * Create a keyed list binding with automatic diffing and DOM updates.
441
- * This is used by compiler-generated code for efficient list rendering.
442
- *
443
- * @param getItems - Function that returns the current array of items
444
- * @param keyFn - Function to extract unique key from each item
445
- * @param renderItem - Function that creates DOM nodes for each item
446
- * @returns Binding handle with markers and dispose function
447
- */
448
- declare function createKeyedList<T>(getItems: () => T[], keyFn: (item: T, index: number) => string | number, renderItem: FineGrainedRenderItem<T>, needsIndex?: boolean): KeyedListBinding;
449
-
450
- interface HookContext {
451
- slots: unknown[];
452
- cursor: number;
453
- rendering?: boolean;
454
- }
455
- declare function __fictUseContext(): HookContext;
456
- declare function __fictPushContext(): HookContext;
457
- declare function __fictPopContext(): void;
458
- declare function __fictResetContext(): void;
459
- declare function __fictUseSignal<T>(ctx: HookContext, initial: T, slot?: number): SignalAccessor<T>;
460
- declare function __fictUseMemo<T>(ctx: HookContext, fn: () => T, slot?: number): ComputedAccessor<T>;
461
- declare function __fictUseEffect(ctx: HookContext, fn: () => void, slot?: number): void;
462
- declare function __fictRender<T>(ctx: HookContext, fn: () => T): T;
463
-
464
- /**
465
- * @internal
466
- * Marks a zero-arg getter so props proxy can lazily evaluate it.
467
- * Users normally never call this directly; the compiler injects it.
468
- */
469
- declare function __fictProp<T>(getter: () => T): () => T;
470
- declare function createPropsProxy<T extends Record<string, unknown>>(props: T): T;
471
- /**
472
- * Create a rest-like props object while preserving prop getters.
473
- * Excludes the specified keys from the returned object.
474
- */
475
- declare function __fictPropsRest<T extends Record<string, unknown>>(props: T, exclude: (string | number | symbol)[]): Record<string, unknown>;
476
- /**
477
- * Merge multiple props-like objects while preserving lazy getters.
478
- * Later sources override earlier ones.
479
- *
480
- * Uses lazy lookup strategy - properties are only accessed when read,
481
- * avoiding upfront iteration of all keys.
482
- */
483
- type MergeSource<T extends Record<string, unknown>> = T | (() => T);
484
- declare function mergeProps<T extends Record<string, unknown>>(...sources: (MergeSource<T> | null | undefined)[]): Record<string, unknown>;
485
- type PropGetter<T> = (() => T) & {
486
- __fictProp: true;
487
- };
488
- /**
489
- * Memoize a prop getter to cache expensive computations.
490
- * Use when prop expressions involve heavy calculations.
491
- *
492
- * @example
493
- * ```tsx
494
- * // Without useProp - recomputes on every access
495
- * <Child data={expensiveComputation(list, filter)} />
496
- *
497
- * // With useProp - cached until dependencies change, auto-unwrapped by props proxy
498
- * const memoizedData = useProp(() => expensiveComputation(list, filter))
499
- * <Child data={memoizedData} />
500
- * ```
501
- */
502
- declare function useProp<T>(getter: () => T): PropGetter<T>;
503
-
504
- export { $state, Fragment, type ReactiveScope, __fictPopContext, __fictProp, __fictPropsRest, __fictPushContext, __fictRender, __fictResetContext, __fictUseContext, __fictUseEffect, __fictUseMemo, __fictUseSignal, batch, bindAttribute, bindClass, bindEvent, bindProperty, bindRef, bindStyle, bindText, clearDelegatedEvents, createConditional, createEffect, createElement, createKeyedBlock, createKeyedList, createKeyedListContainer, createList, createMemo, createPropsProxy, createRenderEffect, createScope, createSelector, signal as createSignal, delegateEvents, destroyMarkerBlock, effectScope, getFirstNodeAfter, insert, insertNodesBefore, mergeProps, moveMarkerBlock, onDestroy, __fictProp as prop, removeNodes, render, runInScope, template, toNodeArray, untrack, useProp };