@getforma/core 0.3.1 → 0.8.1
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/README.md +279 -20
- package/dist/chunk-3U57L2TY.cjs +38 -0
- package/dist/chunk-3U57L2TY.cjs.map +1 -0
- package/dist/{chunk-5H52PKGF.js → chunk-N522P3G6.js} +37 -19
- package/dist/chunk-N522P3G6.js.map +1 -0
- package/dist/chunk-OZCHIVAZ.js +35 -0
- package/dist/chunk-OZCHIVAZ.js.map +1 -0
- package/dist/{chunk-TSQ7AKFT.cjs → chunk-YMIMKO4W.cjs} +66 -25
- package/dist/chunk-YMIMKO4W.cjs.map +1 -0
- package/dist/forma-runtime-csp.js +1 -1
- package/dist/forma-runtime.js +1 -1
- package/dist/formajs-runtime-hardened.global.js +1 -1
- package/dist/formajs-runtime-hardened.global.js.map +1 -1
- package/dist/formajs-runtime.global.js +1 -1
- package/dist/formajs-runtime.global.js.map +1 -1
- package/dist/formajs.global.js +1 -1
- package/dist/formajs.global.js.map +1 -1
- package/dist/index.cjs +142 -118
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +70 -29
- package/dist/index.d.ts +70 -29
- package/dist/index.js +64 -60
- package/dist/index.js.map +1 -1
- package/dist/runtime-hardened.cjs +166 -39
- package/dist/runtime-hardened.cjs.map +1 -1
- package/dist/runtime-hardened.js +167 -40
- package/dist/runtime-hardened.js.map +1 -1
- package/dist/runtime.cjs +184 -57
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +162 -35
- package/dist/runtime.js.map +1 -1
- package/dist/signal-B4_wQJHs.d.cts +53 -0
- package/dist/signal-B4_wQJHs.d.ts +53 -0
- package/dist/ssr/index.cjs +37 -12
- package/dist/ssr/index.cjs.map +1 -1
- package/dist/ssr/index.js +37 -12
- package/dist/ssr/index.js.map +1 -1
- package/dist/tc39-compat.cjs +4 -12
- package/dist/tc39-compat.cjs.map +1 -1
- package/dist/tc39-compat.d.cts +1 -1
- package/dist/tc39-compat.d.ts +1 -1
- package/dist/tc39-compat.js +3 -11
- package/dist/tc39-compat.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-5H52PKGF.js.map +0 -1
- package/dist/chunk-FPSLC62A.cjs +0 -31
- package/dist/chunk-FPSLC62A.cjs.map +0 -1
- package/dist/chunk-KX5WRZH7.js +0 -27
- package/dist/chunk-KX5WRZH7.js.map +0 -1
- package/dist/chunk-TSQ7AKFT.cjs.map +0 -1
- package/dist/signal-CfLDwMyg.d.cts +0 -29
- package/dist/signal-CfLDwMyg.d.ts +0 -29
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference path="./jsx.d.ts" />
|
|
2
|
-
import { S as SignalGetter } from './signal-
|
|
3
|
-
export { c as createSignal } from './signal-
|
|
2
|
+
import { S as SignalGetter } from './signal-B4_wQJHs.cjs';
|
|
3
|
+
export { c as createSignal } from './signal-B4_wQJHs.cjs';
|
|
4
|
+
export { getBatchDepth, isComputed, isEffect, isEffectScope, isSignal, trigger } from 'alien-signals';
|
|
4
5
|
|
|
5
6
|
declare function createEffect(fn: () => void | (() => void)): () => void;
|
|
6
7
|
|
|
@@ -16,6 +17,14 @@ declare function createEffect(fn: () => void | (() => void)): () => void;
|
|
|
16
17
|
/**
|
|
17
18
|
* Create a lazy, cached computed value.
|
|
18
19
|
*
|
|
20
|
+
* Note: Unlike SolidJS's createComputed (which is an eager synchronous
|
|
21
|
+
* side effect), this is a lazy cached derivation — equivalent to
|
|
22
|
+
* SolidJS's createMemo. Both createComputed and createMemo in FormaJS
|
|
23
|
+
* are identical.
|
|
24
|
+
*
|
|
25
|
+
* The getter receives the previous value as an argument, enabling
|
|
26
|
+
* efficient diffing patterns without a separate signal:
|
|
27
|
+
*
|
|
19
28
|
* ```ts
|
|
20
29
|
* const [count, setCount] = createSignal(0);
|
|
21
30
|
* const doubled = createComputed(() => count() * 2);
|
|
@@ -23,8 +32,18 @@ declare function createEffect(fn: () => void | (() => void)): () => void;
|
|
|
23
32
|
* setCount(5);
|
|
24
33
|
* console.log(doubled()); // 10
|
|
25
34
|
* ```
|
|
35
|
+
*
|
|
36
|
+
* With previous value (for diffing):
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* const changes = createComputed((prev) => {
|
|
40
|
+
* const next = items();
|
|
41
|
+
* if (prev) console.log(`changed from ${prev.length} to ${next.length} items`);
|
|
42
|
+
* return next;
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
26
45
|
*/
|
|
27
|
-
declare function createComputed<T>(fn: () => T): () => T;
|
|
46
|
+
declare function createComputed<T>(fn: (previousValue?: T) => T): () => T;
|
|
28
47
|
|
|
29
48
|
/**
|
|
30
49
|
* Forma Reactive - Memo
|
|
@@ -39,6 +58,11 @@ declare function createComputed<T>(fn: () => T): () => T;
|
|
|
39
58
|
* Create a memoized computed value.
|
|
40
59
|
* Identical to `createComputed` — provided for React/SolidJS familiarity.
|
|
41
60
|
*
|
|
61
|
+
* Note: Unlike SolidJS's createComputed (which is an eager synchronous
|
|
62
|
+
* side effect), both createComputed and createMemo in FormaJS are lazy
|
|
63
|
+
* cached derivations — equivalent to SolidJS's createMemo. They are
|
|
64
|
+
* identical.
|
|
65
|
+
*
|
|
42
66
|
* The computation runs lazily and caches the result. It only recomputes
|
|
43
67
|
* when a signal it reads during computation changes.
|
|
44
68
|
*
|
|
@@ -106,13 +130,17 @@ declare function untrack<T>(fn: () => T): T;
|
|
|
106
130
|
* Explicit reactive ownership scope. All effects created inside a root
|
|
107
131
|
* are automatically disposed when the root is torn down.
|
|
108
132
|
*
|
|
109
|
-
*
|
|
133
|
+
* Uses alien-signals' `effectScope` under the hood for native graph-level
|
|
134
|
+
* effect tracking, with a userland disposer list for non-effect cleanup
|
|
135
|
+
* (e.g., event listeners, DOM references, timers).
|
|
110
136
|
*/
|
|
111
137
|
/**
|
|
112
138
|
* Create a reactive root scope.
|
|
113
139
|
*
|
|
114
|
-
* All effects created (via `createEffect`) inside the callback are tracked
|
|
115
|
-
*
|
|
140
|
+
* All effects created (via `createEffect`) inside the callback are tracked
|
|
141
|
+
* at both the reactive graph level (via alien-signals effectScope) and the
|
|
142
|
+
* userland level (via registerDisposer). The returned `dispose` function
|
|
143
|
+
* tears down everything.
|
|
116
144
|
*
|
|
117
145
|
* ```ts
|
|
118
146
|
* const dispose = createRoot(() => {
|
|
@@ -380,6 +408,7 @@ declare function cleanup(el: Element): void;
|
|
|
380
408
|
* )
|
|
381
409
|
* ```
|
|
382
410
|
*/
|
|
411
|
+
declare function h(tag: (props: Record<string, unknown>) => unknown, props?: Record<string, unknown> | null, ...children: unknown[]): Node;
|
|
383
412
|
declare function h(tag: typeof Fragment, props?: null, ...children: unknown[]): DocumentFragment;
|
|
384
413
|
declare function h(tag: string, props?: Record<string, unknown> | null, ...children: unknown[]): HTMLElement;
|
|
385
414
|
/**
|
|
@@ -473,12 +502,6 @@ interface CreateListOptions {
|
|
|
473
502
|
*/
|
|
474
503
|
updateOnItemChange?: 'none' | 'rerender';
|
|
475
504
|
}
|
|
476
|
-
/**
|
|
477
|
-
* Find the longest increasing subsequence.
|
|
478
|
-
* Returns indices into the input array.
|
|
479
|
-
* O(n log n) time, O(n) space.
|
|
480
|
-
*/
|
|
481
|
-
declare function longestIncreasingSubsequence(arr: number[]): number[];
|
|
482
505
|
/**
|
|
483
506
|
* Reconcile a DOM parent's children to match a new array of items.
|
|
484
507
|
* Uses keyed reconciliation with LIS for minimum DOM operations.
|
|
@@ -712,8 +735,20 @@ declare function hydrateIsland(component: () => unknown, target: Element): Eleme
|
|
|
712
735
|
* loads props (inline or script_tag), and hydrates each island inside
|
|
713
736
|
* an independent createRoot scope with try/catch error isolation.
|
|
714
737
|
*/
|
|
715
|
-
/**
|
|
716
|
-
|
|
738
|
+
/**
|
|
739
|
+
* Function that hydrates an island.
|
|
740
|
+
*
|
|
741
|
+
* @param el The root element of the island (`[data-forma-island]`).
|
|
742
|
+
* Useful for layout measurement, focus management, CSS class
|
|
743
|
+
* toggling, third-party library init, or reading extra `data-*`
|
|
744
|
+
* attributes from the server-rendered shell.
|
|
745
|
+
* @param props Parsed props from `data-forma-props` (inline or script block),
|
|
746
|
+
* or `null` if no props were provided.
|
|
747
|
+
* @returns A component tree (from `h()` calls) for descriptor-based
|
|
748
|
+
* hydration, or `undefined` for imperative islands that set up
|
|
749
|
+
* their own effects.
|
|
750
|
+
*/
|
|
751
|
+
type IslandHydrateFn = (el: HTMLElement, props: Record<string, unknown> | null) => unknown;
|
|
717
752
|
/**
|
|
718
753
|
* Discover and activate all SSR-rendered islands on the page.
|
|
719
754
|
*
|
|
@@ -723,6 +758,21 @@ type IslandHydrateFn = (props: Record<string, unknown> | null) => unknown;
|
|
|
723
758
|
* @param registry Map of component names to hydration functions.
|
|
724
759
|
*/
|
|
725
760
|
declare function activateIslands(registry: Record<string, IslandHydrateFn>): void;
|
|
761
|
+
/**
|
|
762
|
+
* Dispose a single island, tearing down its reactive root and all effects.
|
|
763
|
+
*
|
|
764
|
+
* Safe to call multiple times (idempotent). Sets `data-forma-status` to
|
|
765
|
+
* `"disposed"` so the island can be distinguished from active/error states.
|
|
766
|
+
*/
|
|
767
|
+
declare function deactivateIsland(el: HTMLElement): void;
|
|
768
|
+
/**
|
|
769
|
+
* Dispose ALL active islands under a root element (or the whole document).
|
|
770
|
+
*
|
|
771
|
+
* Use this when swapping module content — e.g., replacing the contents of
|
|
772
|
+
* a `<forma-stage>` Shadow DOM during AI generation. Prevents leaked effects
|
|
773
|
+
* and event listeners from accumulating across swaps.
|
|
774
|
+
*/
|
|
775
|
+
declare function deactivateAllIslands(root?: Element | Document): void;
|
|
726
776
|
|
|
727
777
|
/**
|
|
728
778
|
* Forma Component - Define
|
|
@@ -866,6 +916,11 @@ type StoreSetter<T extends object> = (partial: Partial<T> | ((prev: T) => Partia
|
|
|
866
916
|
* // Array mutations
|
|
867
917
|
* state.items.push({ text: 'Walk dog', done: false });
|
|
868
918
|
* ```
|
|
919
|
+
*
|
|
920
|
+
* **Limitation:** `Object.keys(state)`, `for...in`, and spread (`{...state}`)
|
|
921
|
+
* are NOT reactive. Adding or removing a property will not trigger effects
|
|
922
|
+
* that iterated over keys. Use signals or explicit arrays for collections
|
|
923
|
+
* that need to react to membership changes.
|
|
869
924
|
*/
|
|
870
925
|
declare function createStore<T extends object>(initial: T): [get: T, set: StoreSetter<T>];
|
|
871
926
|
|
|
@@ -1393,18 +1448,4 @@ declare function createRPCMiddleware(): (req: {
|
|
|
1393
1448
|
};
|
|
1394
1449
|
}) => Promise<void>;
|
|
1395
1450
|
|
|
1396
|
-
|
|
1397
|
-
interface Window {
|
|
1398
|
-
__FORMA_WASM__?: {
|
|
1399
|
-
loader: string;
|
|
1400
|
-
binary: string;
|
|
1401
|
-
ir: string;
|
|
1402
|
-
};
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
/** Full page render via WASM. */
|
|
1406
|
-
declare function renderLocal(slotsJson: string): Promise<string>;
|
|
1407
|
-
/** Fragment render (single island) via WASM. */
|
|
1408
|
-
declare function renderIsland(slotsJson: string, islandId: number): Promise<string>;
|
|
1409
|
-
|
|
1410
|
-
export { $, $$, $$serverFunction, type Action, type ActionOptions, Fragment, type IslandHydrateFn, type MutationResponse, type RPCRequest, type RPCResponse, activateIslands, addClass, applyRevalidation, batch, children, cleanup, closest, createAction, createBus, createComputed, createContext, createEffect, createErrorBoundary, createFetch, createHistory, createIndexedDB, createList, createLocalStorage, createMemo, createPortal, createRPCMiddleware, createReducer, createRef, createResource, createRoot, createSSE, createSessionStorage, createShow, createStore, createSuspense, createSwitch, createText, createWebSocket, defineComponent, delegate, disposeComponent, enableAutoRevalidation, fetchJSON, fragment, getRegisteredEndpoints, getServerFunction, h, handleRPC, hydrateIsland, inject, longestIncreasingSubsequence, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, registerResource, registerServerFunction, removeClass, renderIsland, renderLocal, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, untrack, withRevalidation };
|
|
1451
|
+
export { $, $$, $$serverFunction, type Action, type ActionOptions, Fragment, type IslandHydrateFn, type MutationResponse, type RPCRequest, type RPCResponse, activateIslands, addClass, applyRevalidation, batch, children, cleanup, closest, createAction, createBus, createComputed, createContext, createEffect, createErrorBoundary, createFetch, createHistory, createIndexedDB, createList, createLocalStorage, createMemo, createPortal, createRPCMiddleware, createReducer, createRef, createResource, createRoot, createSSE, createSessionStorage, createShow, createStore, createSuspense, createSwitch, createText, createWebSocket, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, enableAutoRevalidation, fetchJSON, fragment, getRegisteredEndpoints, getServerFunction, h, handleRPC, hydrateIsland, inject, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, registerResource, registerServerFunction, removeClass, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, untrack, withRevalidation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference path="./jsx.d.ts" />
|
|
2
|
-
import { S as SignalGetter } from './signal-
|
|
3
|
-
export { c as createSignal } from './signal-
|
|
2
|
+
import { S as SignalGetter } from './signal-B4_wQJHs.js';
|
|
3
|
+
export { c as createSignal } from './signal-B4_wQJHs.js';
|
|
4
|
+
export { getBatchDepth, isComputed, isEffect, isEffectScope, isSignal, trigger } from 'alien-signals';
|
|
4
5
|
|
|
5
6
|
declare function createEffect(fn: () => void | (() => void)): () => void;
|
|
6
7
|
|
|
@@ -16,6 +17,14 @@ declare function createEffect(fn: () => void | (() => void)): () => void;
|
|
|
16
17
|
/**
|
|
17
18
|
* Create a lazy, cached computed value.
|
|
18
19
|
*
|
|
20
|
+
* Note: Unlike SolidJS's createComputed (which is an eager synchronous
|
|
21
|
+
* side effect), this is a lazy cached derivation — equivalent to
|
|
22
|
+
* SolidJS's createMemo. Both createComputed and createMemo in FormaJS
|
|
23
|
+
* are identical.
|
|
24
|
+
*
|
|
25
|
+
* The getter receives the previous value as an argument, enabling
|
|
26
|
+
* efficient diffing patterns without a separate signal:
|
|
27
|
+
*
|
|
19
28
|
* ```ts
|
|
20
29
|
* const [count, setCount] = createSignal(0);
|
|
21
30
|
* const doubled = createComputed(() => count() * 2);
|
|
@@ -23,8 +32,18 @@ declare function createEffect(fn: () => void | (() => void)): () => void;
|
|
|
23
32
|
* setCount(5);
|
|
24
33
|
* console.log(doubled()); // 10
|
|
25
34
|
* ```
|
|
35
|
+
*
|
|
36
|
+
* With previous value (for diffing):
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* const changes = createComputed((prev) => {
|
|
40
|
+
* const next = items();
|
|
41
|
+
* if (prev) console.log(`changed from ${prev.length} to ${next.length} items`);
|
|
42
|
+
* return next;
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
26
45
|
*/
|
|
27
|
-
declare function createComputed<T>(fn: () => T): () => T;
|
|
46
|
+
declare function createComputed<T>(fn: (previousValue?: T) => T): () => T;
|
|
28
47
|
|
|
29
48
|
/**
|
|
30
49
|
* Forma Reactive - Memo
|
|
@@ -39,6 +58,11 @@ declare function createComputed<T>(fn: () => T): () => T;
|
|
|
39
58
|
* Create a memoized computed value.
|
|
40
59
|
* Identical to `createComputed` — provided for React/SolidJS familiarity.
|
|
41
60
|
*
|
|
61
|
+
* Note: Unlike SolidJS's createComputed (which is an eager synchronous
|
|
62
|
+
* side effect), both createComputed and createMemo in FormaJS are lazy
|
|
63
|
+
* cached derivations — equivalent to SolidJS's createMemo. They are
|
|
64
|
+
* identical.
|
|
65
|
+
*
|
|
42
66
|
* The computation runs lazily and caches the result. It only recomputes
|
|
43
67
|
* when a signal it reads during computation changes.
|
|
44
68
|
*
|
|
@@ -106,13 +130,17 @@ declare function untrack<T>(fn: () => T): T;
|
|
|
106
130
|
* Explicit reactive ownership scope. All effects created inside a root
|
|
107
131
|
* are automatically disposed when the root is torn down.
|
|
108
132
|
*
|
|
109
|
-
*
|
|
133
|
+
* Uses alien-signals' `effectScope` under the hood for native graph-level
|
|
134
|
+
* effect tracking, with a userland disposer list for non-effect cleanup
|
|
135
|
+
* (e.g., event listeners, DOM references, timers).
|
|
110
136
|
*/
|
|
111
137
|
/**
|
|
112
138
|
* Create a reactive root scope.
|
|
113
139
|
*
|
|
114
|
-
* All effects created (via `createEffect`) inside the callback are tracked
|
|
115
|
-
*
|
|
140
|
+
* All effects created (via `createEffect`) inside the callback are tracked
|
|
141
|
+
* at both the reactive graph level (via alien-signals effectScope) and the
|
|
142
|
+
* userland level (via registerDisposer). The returned `dispose` function
|
|
143
|
+
* tears down everything.
|
|
116
144
|
*
|
|
117
145
|
* ```ts
|
|
118
146
|
* const dispose = createRoot(() => {
|
|
@@ -380,6 +408,7 @@ declare function cleanup(el: Element): void;
|
|
|
380
408
|
* )
|
|
381
409
|
* ```
|
|
382
410
|
*/
|
|
411
|
+
declare function h(tag: (props: Record<string, unknown>) => unknown, props?: Record<string, unknown> | null, ...children: unknown[]): Node;
|
|
383
412
|
declare function h(tag: typeof Fragment, props?: null, ...children: unknown[]): DocumentFragment;
|
|
384
413
|
declare function h(tag: string, props?: Record<string, unknown> | null, ...children: unknown[]): HTMLElement;
|
|
385
414
|
/**
|
|
@@ -473,12 +502,6 @@ interface CreateListOptions {
|
|
|
473
502
|
*/
|
|
474
503
|
updateOnItemChange?: 'none' | 'rerender';
|
|
475
504
|
}
|
|
476
|
-
/**
|
|
477
|
-
* Find the longest increasing subsequence.
|
|
478
|
-
* Returns indices into the input array.
|
|
479
|
-
* O(n log n) time, O(n) space.
|
|
480
|
-
*/
|
|
481
|
-
declare function longestIncreasingSubsequence(arr: number[]): number[];
|
|
482
505
|
/**
|
|
483
506
|
* Reconcile a DOM parent's children to match a new array of items.
|
|
484
507
|
* Uses keyed reconciliation with LIS for minimum DOM operations.
|
|
@@ -712,8 +735,20 @@ declare function hydrateIsland(component: () => unknown, target: Element): Eleme
|
|
|
712
735
|
* loads props (inline or script_tag), and hydrates each island inside
|
|
713
736
|
* an independent createRoot scope with try/catch error isolation.
|
|
714
737
|
*/
|
|
715
|
-
/**
|
|
716
|
-
|
|
738
|
+
/**
|
|
739
|
+
* Function that hydrates an island.
|
|
740
|
+
*
|
|
741
|
+
* @param el The root element of the island (`[data-forma-island]`).
|
|
742
|
+
* Useful for layout measurement, focus management, CSS class
|
|
743
|
+
* toggling, third-party library init, or reading extra `data-*`
|
|
744
|
+
* attributes from the server-rendered shell.
|
|
745
|
+
* @param props Parsed props from `data-forma-props` (inline or script block),
|
|
746
|
+
* or `null` if no props were provided.
|
|
747
|
+
* @returns A component tree (from `h()` calls) for descriptor-based
|
|
748
|
+
* hydration, or `undefined` for imperative islands that set up
|
|
749
|
+
* their own effects.
|
|
750
|
+
*/
|
|
751
|
+
type IslandHydrateFn = (el: HTMLElement, props: Record<string, unknown> | null) => unknown;
|
|
717
752
|
/**
|
|
718
753
|
* Discover and activate all SSR-rendered islands on the page.
|
|
719
754
|
*
|
|
@@ -723,6 +758,21 @@ type IslandHydrateFn = (props: Record<string, unknown> | null) => unknown;
|
|
|
723
758
|
* @param registry Map of component names to hydration functions.
|
|
724
759
|
*/
|
|
725
760
|
declare function activateIslands(registry: Record<string, IslandHydrateFn>): void;
|
|
761
|
+
/**
|
|
762
|
+
* Dispose a single island, tearing down its reactive root and all effects.
|
|
763
|
+
*
|
|
764
|
+
* Safe to call multiple times (idempotent). Sets `data-forma-status` to
|
|
765
|
+
* `"disposed"` so the island can be distinguished from active/error states.
|
|
766
|
+
*/
|
|
767
|
+
declare function deactivateIsland(el: HTMLElement): void;
|
|
768
|
+
/**
|
|
769
|
+
* Dispose ALL active islands under a root element (or the whole document).
|
|
770
|
+
*
|
|
771
|
+
* Use this when swapping module content — e.g., replacing the contents of
|
|
772
|
+
* a `<forma-stage>` Shadow DOM during AI generation. Prevents leaked effects
|
|
773
|
+
* and event listeners from accumulating across swaps.
|
|
774
|
+
*/
|
|
775
|
+
declare function deactivateAllIslands(root?: Element | Document): void;
|
|
726
776
|
|
|
727
777
|
/**
|
|
728
778
|
* Forma Component - Define
|
|
@@ -866,6 +916,11 @@ type StoreSetter<T extends object> = (partial: Partial<T> | ((prev: T) => Partia
|
|
|
866
916
|
* // Array mutations
|
|
867
917
|
* state.items.push({ text: 'Walk dog', done: false });
|
|
868
918
|
* ```
|
|
919
|
+
*
|
|
920
|
+
* **Limitation:** `Object.keys(state)`, `for...in`, and spread (`{...state}`)
|
|
921
|
+
* are NOT reactive. Adding or removing a property will not trigger effects
|
|
922
|
+
* that iterated over keys. Use signals or explicit arrays for collections
|
|
923
|
+
* that need to react to membership changes.
|
|
869
924
|
*/
|
|
870
925
|
declare function createStore<T extends object>(initial: T): [get: T, set: StoreSetter<T>];
|
|
871
926
|
|
|
@@ -1393,18 +1448,4 @@ declare function createRPCMiddleware(): (req: {
|
|
|
1393
1448
|
};
|
|
1394
1449
|
}) => Promise<void>;
|
|
1395
1450
|
|
|
1396
|
-
|
|
1397
|
-
interface Window {
|
|
1398
|
-
__FORMA_WASM__?: {
|
|
1399
|
-
loader: string;
|
|
1400
|
-
binary: string;
|
|
1401
|
-
ir: string;
|
|
1402
|
-
};
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
/** Full page render via WASM. */
|
|
1406
|
-
declare function renderLocal(slotsJson: string): Promise<string>;
|
|
1407
|
-
/** Fragment render (single island) via WASM. */
|
|
1408
|
-
declare function renderIsland(slotsJson: string, islandId: number): Promise<string>;
|
|
1409
|
-
|
|
1410
|
-
export { $, $$, $$serverFunction, type Action, type ActionOptions, Fragment, type IslandHydrateFn, type MutationResponse, type RPCRequest, type RPCResponse, activateIslands, addClass, applyRevalidation, batch, children, cleanup, closest, createAction, createBus, createComputed, createContext, createEffect, createErrorBoundary, createFetch, createHistory, createIndexedDB, createList, createLocalStorage, createMemo, createPortal, createRPCMiddleware, createReducer, createRef, createResource, createRoot, createSSE, createSessionStorage, createShow, createStore, createSuspense, createSwitch, createText, createWebSocket, defineComponent, delegate, disposeComponent, enableAutoRevalidation, fetchJSON, fragment, getRegisteredEndpoints, getServerFunction, h, handleRPC, hydrateIsland, inject, longestIncreasingSubsequence, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, registerResource, registerServerFunction, removeClass, renderIsland, renderLocal, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, untrack, withRevalidation };
|
|
1451
|
+
export { $, $$, $$serverFunction, type Action, type ActionOptions, Fragment, type IslandHydrateFn, type MutationResponse, type RPCRequest, type RPCResponse, activateIslands, addClass, applyRevalidation, batch, children, cleanup, closest, createAction, createBus, createComputed, createContext, createEffect, createErrorBoundary, createFetch, createHistory, createIndexedDB, createList, createLocalStorage, createMemo, createPortal, createRPCMiddleware, createReducer, createRef, createResource, createRoot, createSSE, createSessionStorage, createShow, createStore, createSuspense, createSwitch, createText, createWebSocket, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, enableAutoRevalidation, fetchJSON, fragment, getRegisteredEndpoints, getServerFunction, h, handleRPC, hydrateIsland, inject, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, registerResource, registerServerFunction, removeClass, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, untrack, withRevalidation };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { internalEffect, createRoot, hydrateIsland, untrack, createEffect, pushSuspenseContext, popSuspenseContext, __DEV__, batch } from './chunk-
|
|
2
|
-
export { Fragment, batch, cleanup, createEffect, createList, createMemo, createReducer, createRef, createResource, createRoot, createShow, fragment, h, hydrateIsland,
|
|
3
|
-
import { createSignal
|
|
4
|
-
export { createComputed, createSignal } from './chunk-
|
|
1
|
+
import { internalEffect, createRoot, hydrateIsland, untrack, createEffect, pushSuspenseContext, popSuspenseContext, __DEV__, reportError, batch } from './chunk-N522P3G6.js';
|
|
2
|
+
export { Fragment, batch, cleanup, createEffect, createList, createMemo, createReducer, createRef, createResource, createRoot, createShow, fragment, getBatchDepth, h, hydrateIsland, isComputed, isEffect, isEffectScope, isSignal, on, onCleanup, onError, reconcileList, trigger, untrack } from './chunk-N522P3G6.js';
|
|
3
|
+
import { createSignal } from './chunk-OZCHIVAZ.js';
|
|
4
|
+
export { createComputed, createSignal } from './chunk-OZCHIVAZ.js';
|
|
5
5
|
|
|
6
6
|
// src/dom/text.ts
|
|
7
7
|
function createText(value) {
|
|
@@ -219,13 +219,20 @@ function createSuspense(fallback, children2) {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
// src/dom/activate.ts
|
|
222
|
+
var FORBIDDEN_PROP_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
223
|
+
function sanitizeProps(obj) {
|
|
224
|
+
for (const key of FORBIDDEN_PROP_KEYS) {
|
|
225
|
+
if (key in obj) delete obj[key];
|
|
226
|
+
}
|
|
227
|
+
return obj;
|
|
228
|
+
}
|
|
222
229
|
function loadIslandProps(root, id, sharedProps) {
|
|
223
230
|
const inline = root.getAttribute("data-forma-props");
|
|
224
231
|
if (inline) {
|
|
225
|
-
return JSON.parse(inline);
|
|
232
|
+
return sanitizeProps(JSON.parse(inline));
|
|
226
233
|
}
|
|
227
234
|
if (sharedProps && String(id) in sharedProps) {
|
|
228
|
-
return sharedProps[String(id)];
|
|
235
|
+
return sanitizeProps(sharedProps[String(id)]);
|
|
229
236
|
}
|
|
230
237
|
return null;
|
|
231
238
|
}
|
|
@@ -242,11 +249,8 @@ function activateIslands(registry2) {
|
|
|
242
249
|
root.setAttribute("data-forma-status", "error");
|
|
243
250
|
continue;
|
|
244
251
|
}
|
|
245
|
-
const
|
|
246
|
-
if (
|
|
247
|
-
if (__DEV__) console.warn(`[forma] Trigger "${trigger}" not yet implemented for island "${componentName}" (id=${id}), falling back to load`);
|
|
248
|
-
}
|
|
249
|
-
if (trigger === "visible") {
|
|
252
|
+
const trigger2 = root.getAttribute("data-forma-hydrate") || "load";
|
|
253
|
+
if (trigger2 === "visible") {
|
|
250
254
|
const observer = new IntersectionObserver(
|
|
251
255
|
(entries) => {
|
|
252
256
|
for (const entry of entries) {
|
|
@@ -258,18 +262,47 @@ function activateIslands(registry2) {
|
|
|
258
262
|
{ rootMargin: "200px" }
|
|
259
263
|
);
|
|
260
264
|
observer.observe(root);
|
|
265
|
+
} else if (trigger2 === "idle") {
|
|
266
|
+
const hydrate = () => hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
|
|
267
|
+
if (typeof requestIdleCallback === "function") {
|
|
268
|
+
requestIdleCallback(hydrate);
|
|
269
|
+
} else {
|
|
270
|
+
setTimeout(hydrate, 200);
|
|
271
|
+
}
|
|
272
|
+
} else if (trigger2 === "interaction") {
|
|
273
|
+
const hydrate = () => {
|
|
274
|
+
root.removeEventListener("pointerdown", hydrate, true);
|
|
275
|
+
root.removeEventListener("focusin", hydrate, true);
|
|
276
|
+
hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
|
|
277
|
+
};
|
|
278
|
+
root.addEventListener("pointerdown", hydrate, { capture: true, once: true });
|
|
279
|
+
root.addEventListener("focusin", hydrate, { capture: true, once: true });
|
|
261
280
|
} else {
|
|
262
281
|
hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
|
|
263
282
|
}
|
|
264
283
|
}
|
|
265
284
|
}
|
|
285
|
+
function deactivateIsland(el) {
|
|
286
|
+
const dispose = el.__formaDispose;
|
|
287
|
+
if (typeof dispose === "function") {
|
|
288
|
+
dispose();
|
|
289
|
+
delete el.__formaDispose;
|
|
290
|
+
el.setAttribute("data-forma-status", "disposed");
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function deactivateAllIslands(root = document) {
|
|
294
|
+
const islands = root.querySelectorAll('[data-forma-status="active"]');
|
|
295
|
+
for (const island of islands) {
|
|
296
|
+
deactivateIsland(island);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
266
299
|
function hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps) {
|
|
267
300
|
try {
|
|
268
301
|
const props = loadIslandProps(root, id, sharedProps);
|
|
269
302
|
root.setAttribute("data-forma-status", "hydrating");
|
|
270
303
|
let activeRoot = root;
|
|
271
304
|
createRoot((dispose) => {
|
|
272
|
-
activeRoot = hydrateIsland(() => hydrateFn(props), root);
|
|
305
|
+
activeRoot = hydrateIsland(() => hydrateFn(root, props), root);
|
|
273
306
|
activeRoot.__formaDispose = dispose;
|
|
274
307
|
});
|
|
275
308
|
activeRoot.setAttribute("data-forma-status", "active");
|
|
@@ -322,13 +355,15 @@ function defineComponent(setupOrDef) {
|
|
|
322
355
|
for (const cb of ctx.unmountCallbacks) {
|
|
323
356
|
try {
|
|
324
357
|
cb();
|
|
325
|
-
} catch {
|
|
358
|
+
} catch (e) {
|
|
359
|
+
reportError(e, "onUnmount");
|
|
326
360
|
}
|
|
327
361
|
}
|
|
328
362
|
for (const d of ctx.disposers) {
|
|
329
363
|
try {
|
|
330
364
|
d();
|
|
331
|
-
} catch {
|
|
365
|
+
} catch (e) {
|
|
366
|
+
reportError(e, "component disposer");
|
|
332
367
|
}
|
|
333
368
|
}
|
|
334
369
|
ctx.disposers.length = 0;
|
|
@@ -342,7 +377,8 @@ function defineComponent(setupOrDef) {
|
|
|
342
377
|
if (typeof cleanup2 === "function") {
|
|
343
378
|
ctx.unmountCallbacks.push(cleanup2);
|
|
344
379
|
}
|
|
345
|
-
} catch {
|
|
380
|
+
} catch (e) {
|
|
381
|
+
reportError(e, "onMount");
|
|
346
382
|
}
|
|
347
383
|
}
|
|
348
384
|
return dom;
|
|
@@ -416,13 +452,15 @@ function shouldWrap(v) {
|
|
|
416
452
|
if (v[PROXY]) return false;
|
|
417
453
|
return true;
|
|
418
454
|
}
|
|
419
|
-
function deepClone(obj) {
|
|
420
|
-
if (obj
|
|
421
|
-
if (
|
|
422
|
-
if (obj
|
|
455
|
+
function deepClone(obj, seen) {
|
|
456
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
457
|
+
if (!seen) seen = /* @__PURE__ */ new WeakSet();
|
|
458
|
+
if (seen.has(obj)) return obj;
|
|
459
|
+
seen.add(obj);
|
|
460
|
+
if (Array.isArray(obj)) return obj.map((item) => deepClone(item, seen));
|
|
423
461
|
const out = {};
|
|
424
462
|
for (const key of Object.keys(obj)) {
|
|
425
|
-
out[key] = deepClone(obj[key]);
|
|
463
|
+
out[key] = deepClone(obj[key], seen);
|
|
426
464
|
}
|
|
427
465
|
return out;
|
|
428
466
|
}
|
|
@@ -616,9 +654,9 @@ function createHistory(source, options) {
|
|
|
616
654
|
const maxLength = options?.maxLength ?? 100;
|
|
617
655
|
let _stack = [sourceGet()];
|
|
618
656
|
let _cursor = 0;
|
|
619
|
-
const [stackSignal, setStackSignal] =
|
|
620
|
-
const [cursorSignal, setCursorSignal] =
|
|
621
|
-
const [stackLenSignal, setStackLenSignal] =
|
|
657
|
+
const [stackSignal, setStackSignal] = createSignal([..._stack]);
|
|
658
|
+
const [cursorSignal, setCursorSignal] = createSignal(_cursor);
|
|
659
|
+
const [stackLenSignal, setStackLenSignal] = createSignal(_stack.length);
|
|
622
660
|
function syncSignals() {
|
|
623
661
|
batch(() => {
|
|
624
662
|
setStackSignal([..._stack]);
|
|
@@ -1315,8 +1353,8 @@ function createWebSocket(url, options) {
|
|
|
1315
1353
|
|
|
1316
1354
|
// src/server/action.ts
|
|
1317
1355
|
function createAction(serverFn, options) {
|
|
1318
|
-
const [pending, setPending] =
|
|
1319
|
-
const [error, setError] =
|
|
1356
|
+
const [pending, setPending] = createSignal(false);
|
|
1357
|
+
const [error, setError] = createSignal(void 0);
|
|
1320
1358
|
const action = async (...args) => {
|
|
1321
1359
|
setPending(true);
|
|
1322
1360
|
setError(void 0);
|
|
@@ -1473,40 +1511,6 @@ function createRPCMiddleware() {
|
|
|
1473
1511
|
};
|
|
1474
1512
|
}
|
|
1475
1513
|
|
|
1476
|
-
|
|
1477
|
-
var wasmModule = null;
|
|
1478
|
-
var irCache = /* @__PURE__ */ new Map();
|
|
1479
|
-
async function ensureWasm() {
|
|
1480
|
-
if (wasmModule) return wasmModule;
|
|
1481
|
-
const config = window.__FORMA_WASM__;
|
|
1482
|
-
if (!config) throw new Error("No __FORMA_WASM__ config");
|
|
1483
|
-
const mod = await import(
|
|
1484
|
-
/* @vite-ignore */
|
|
1485
|
-
config.loader
|
|
1486
|
-
);
|
|
1487
|
-
await mod.default(config.binary);
|
|
1488
|
-
wasmModule = mod;
|
|
1489
|
-
return wasmModule;
|
|
1490
|
-
}
|
|
1491
|
-
async function getIR() {
|
|
1492
|
-
const config = window.__FORMA_WASM__;
|
|
1493
|
-
if (!config) throw new Error("No __FORMA_WASM__ config");
|
|
1494
|
-
const cached = irCache.get(config.ir);
|
|
1495
|
-
if (cached) return cached;
|
|
1496
|
-
const response = await fetch(config.ir);
|
|
1497
|
-
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
1498
|
-
irCache.set(config.ir, bytes);
|
|
1499
|
-
return bytes;
|
|
1500
|
-
}
|
|
1501
|
-
async function renderLocal(slotsJson) {
|
|
1502
|
-
const [wasm, ir] = await Promise.all([ensureWasm(), getIR()]);
|
|
1503
|
-
return wasm.render(ir, slotsJson);
|
|
1504
|
-
}
|
|
1505
|
-
async function renderIsland(slotsJson, islandId) {
|
|
1506
|
-
const [wasm, ir] = await Promise.all([ensureWasm(), getIR()]);
|
|
1507
|
-
return wasm.render_island(ir, slotsJson, islandId);
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
export { $, $$, $$serverFunction, activateIslands, addClass, applyRevalidation, children, closest, createAction, createBus, createContext, createErrorBoundary, createFetch, createHistory, createIndexedDB, createLocalStorage, createPortal, createRPCMiddleware, createSSE, createSessionStorage, createStore, createSuspense, createSwitch, createText, createWebSocket, defineComponent, delegate, disposeComponent, enableAutoRevalidation, fetchJSON, getRegisteredEndpoints, getServerFunction, handleRPC, inject, mount, nextSibling, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, registerResource, registerServerFunction, removeClass, renderIsland, renderLocal, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, withRevalidation };
|
|
1514
|
+
export { $, $$, $$serverFunction, activateIslands, addClass, applyRevalidation, children, closest, createAction, createBus, createContext, createErrorBoundary, createFetch, createHistory, createIndexedDB, createLocalStorage, createPortal, createRPCMiddleware, createSSE, createSessionStorage, createStore, createSuspense, createSwitch, createText, createWebSocket, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, enableAutoRevalidation, fetchJSON, getRegisteredEndpoints, getServerFunction, handleRPC, inject, mount, nextSibling, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, registerResource, registerServerFunction, removeClass, setAttr, setHTML, setHTMLUnsafe, setStyle, setText, siblings, toggleClass, trackDisposer, unprovide, unregisterResource, withRevalidation };
|
|
1511
1515
|
//# sourceMappingURL=index.js.map
|
|
1512
1516
|
//# sourceMappingURL=index.js.map
|