@fictjs/runtime 0.0.15 → 0.2.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.
- package/dist/advanced.cjs +8 -8
- package/dist/advanced.d.cts +3 -3
- package/dist/advanced.d.ts +3 -3
- package/dist/advanced.js +3 -3
- package/dist/{chunk-GJTYOFMO.cjs → chunk-527QSKFM.cjs} +16 -16
- package/dist/{chunk-GJTYOFMO.cjs.map → chunk-527QSKFM.cjs.map} +1 -1
- package/dist/{chunk-RY4WDS6R.js → chunk-5KXEEQUO.js} +115 -20
- package/dist/chunk-5KXEEQUO.js.map +1 -0
- package/dist/{chunk-624QY53A.cjs → chunk-BSUMPMKX.cjs} +7 -7
- package/dist/chunk-BSUMPMKX.cjs.map +1 -0
- package/dist/{chunk-IUZXKAAY.js → chunk-FG3M7EBL.js} +2 -2
- package/dist/{chunk-PMF6MWEV.cjs → chunk-J74L7UYP.cjs} +128 -33
- package/dist/chunk-J74L7UYP.cjs.map +1 -0
- package/dist/{chunk-F3AIYQB7.js → chunk-QV5GOCR5.js} +3 -3
- package/dist/chunk-QV5GOCR5.js.map +1 -0
- package/dist/{context-B7UYnfzM.d.ts → context-4woHo7-L.d.ts} +1 -1
- package/dist/{context-UXySaqI_.d.cts → context-9gFXOdJl.d.cts} +1 -1
- package/dist/{effect-Auji1rz9.d.cts → effect-ClARNUCc.d.cts} +23 -2
- package/dist/{effect-Auji1rz9.d.ts → effect-ClARNUCc.d.ts} +23 -2
- package/dist/index.cjs +51 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.dev.js +96 -28
- package/dist/index.dev.js.map +1 -1
- package/dist/index.js +10 -13
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +44 -35
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +9 -4
- package/dist/internal.d.ts +9 -4
- package/dist/internal.js +12 -3
- package/dist/internal.js.map +1 -1
- package/dist/jsx-runtime.d.cts +671 -0
- package/dist/jsx-runtime.d.ts +671 -0
- package/dist/{props-ES0Ag_Wd.d.ts → props-CBwuh35e.d.cts} +13 -6
- package/dist/{props-CrOMYbLv.d.cts → props-DAyeRPwH.d.ts} +13 -6
- package/dist/{scope-S6eAzBJZ.d.ts → scope-DvgMquEy.d.ts} +1 -1
- package/dist/{scope-DKYzWfTn.d.cts → scope-xmdo6lVU.d.cts} +1 -1
- package/package.json +1 -1
- package/src/binding.ts +62 -8
- package/src/constants.ts +2 -3
- package/src/dev-entry.ts +22 -0
- package/src/effect.ts +9 -2
- package/src/lifecycle.ts +24 -6
- package/src/list-helpers.ts +14 -3
- package/src/props.ts +29 -3
- package/src/scope.ts +1 -1
- package/src/signal.ts +43 -4
- package/src/suspense.ts +17 -13
- package/dist/chunk-624QY53A.cjs.map +0 -1
- package/dist/chunk-F3AIYQB7.js.map +0 -1
- package/dist/chunk-PMF6MWEV.cjs.map +0 -1
- package/dist/chunk-RY4WDS6R.js.map +0 -1
- /package/dist/{chunk-IUZXKAAY.js.map → chunk-FG3M7EBL.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/scope.ts"],"sourcesContent":["import { isReactive, type MaybeReactive } from './binding'\nimport { createEffect } from './effect'\nimport { createRoot, onCleanup, registerRootCleanup } from './lifecycle'\n\nexport { effectScope } from './signal'\n\nexport interface ReactiveScope {\n run<T>(fn: () => T): T\n stop(): void\n}\n\n/**\n * Create an explicit reactive scope that can contain effects/memos and be stopped manually.\n * The scope registers with the current root for cleanup.\n */\nexport function createScope(): ReactiveScope {\n let dispose: (() => void) | null = null\n\n const stop = () => {\n if (dispose) {\n dispose()\n dispose = null\n }\n }\n\n const run = <T>(fn: () => T): T => {\n stop()\n const { dispose: rootDispose, value } = createRoot(fn, { inherit: true })\n dispose = rootDispose\n return value\n }\n\n registerRootCleanup(stop)\n return { run, stop }\n}\n\n/**\n * Run a block of reactive code inside a managed scope that follows a boolean flag.\n * When the flag turns false, the scope is disposed and all contained effects/memos are cleaned up.\n */\nexport function runInScope(flag: MaybeReactive<boolean>, fn: () => void): void {\n const scope = createScope()\n const evaluate = () => (isReactive(flag) ? (flag as () => boolean)() : !!flag)\n\n createEffect(() => {\n const enabled = evaluate()\n if (enabled) {\n scope.run(fn)\n } else {\n scope.stop()\n }\n })\n\n onCleanup(scope.stop)\n}\n"],"mappings":";;;;;;;;;AAeO,SAAS,cAA6B;AAC3C,MAAI,UAA+B;AAEnC,QAAM,OAAO,MAAM;AACjB,QAAI,SAAS;AACX,cAAQ;AACR,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,MAAM,CAAI,OAAmB;AACjC,SAAK;AACL,UAAM,EAAE,SAAS,aAAa,MAAM,IAAI,WAAW,IAAI,EAAE,SAAS,KAAK,CAAC;AACxE,cAAU;AACV,WAAO;AAAA,EACT;AAEA,sBAAoB,IAAI;AACxB,SAAO,EAAE,KAAK,KAAK;AACrB;AAMO,SAAS,WAAW,MAA8B,IAAsB;AAC7E,QAAM,QAAQ,YAAY;AAC1B,QAAM,WAAW,MAAO,WAAW,IAAI,IAAK,KAAuB,IAAI,CAAC,CAAC;AAEzE,eAAa,MAAM;AACjB,UAAM,UAAU,SAAS;AACzB,QAAI,SAAS;AACX,YAAM,IAAI,EAAE;AAAA,IACd,OAAO;AACL,YAAM,KAAK;AAAA,IACb;AAAA,EACF,CAAC;AAED,YAAU,MAAM,IAAI;AACtB;","names":[]}
|
|
@@ -88,8 +88,29 @@ interface BindingHandle {
|
|
|
88
88
|
}
|
|
89
89
|
/** Managed child node with its dispose function */
|
|
90
90
|
/**
|
|
91
|
-
* Check if a value is reactive (a getter function)
|
|
92
|
-
*
|
|
91
|
+
* Check if a value is reactive (a getter function that returns a value).
|
|
92
|
+
*
|
|
93
|
+
* A value is considered reactive if:
|
|
94
|
+
* 1. It's a signal or computed value created by the runtime (marked with Symbol)
|
|
95
|
+
* 2. It's a zero-argument function (getter pattern used by the compiler)
|
|
96
|
+
*
|
|
97
|
+
* NOT considered reactive:
|
|
98
|
+
* - Event handlers (functions that take arguments)
|
|
99
|
+
* - Effect disposers (zero-arg but for cleanup, not value access)
|
|
100
|
+
* - Effect scopes (zero-arg but for scope management)
|
|
101
|
+
*
|
|
102
|
+
* @param value - The value to check
|
|
103
|
+
* @returns true if the value is a reactive getter
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* const [count, setCount] = createSignal(0)
|
|
108
|
+
* isReactive(count) // true - signal accessor
|
|
109
|
+
* isReactive(() => 42) // true - getter pattern
|
|
110
|
+
* isReactive((x) => x) // false - takes argument
|
|
111
|
+
* isReactive('hello') // false - not a function
|
|
112
|
+
* isReactive(effectDisposer) // false - effect cleanup function
|
|
113
|
+
* ```
|
|
93
114
|
*/
|
|
94
115
|
declare function isReactive(value: unknown): value is () => unknown;
|
|
95
116
|
/**
|
|
@@ -88,8 +88,29 @@ interface BindingHandle {
|
|
|
88
88
|
}
|
|
89
89
|
/** Managed child node with its dispose function */
|
|
90
90
|
/**
|
|
91
|
-
* Check if a value is reactive (a getter function)
|
|
92
|
-
*
|
|
91
|
+
* Check if a value is reactive (a getter function that returns a value).
|
|
92
|
+
*
|
|
93
|
+
* A value is considered reactive if:
|
|
94
|
+
* 1. It's a signal or computed value created by the runtime (marked with Symbol)
|
|
95
|
+
* 2. It's a zero-argument function (getter pattern used by the compiler)
|
|
96
|
+
*
|
|
97
|
+
* NOT considered reactive:
|
|
98
|
+
* - Event handlers (functions that take arguments)
|
|
99
|
+
* - Effect disposers (zero-arg but for cleanup, not value access)
|
|
100
|
+
* - Effect scopes (zero-arg but for scope management)
|
|
101
|
+
*
|
|
102
|
+
* @param value - The value to check
|
|
103
|
+
* @returns true if the value is a reactive getter
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* const [count, setCount] = createSignal(0)
|
|
108
|
+
* isReactive(count) // true - signal accessor
|
|
109
|
+
* isReactive(() => 42) // true - getter pattern
|
|
110
|
+
* isReactive((x) => x) // false - takes argument
|
|
111
|
+
* isReactive('hello') // false - not a function
|
|
112
|
+
* isReactive(effectDisposer) // false - effect cleanup function
|
|
113
|
+
* ```
|
|
93
114
|
*/
|
|
94
115
|
declare function isReactive(value: unknown): value is () => unknown;
|
|
95
116
|
/**
|
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunk527QSKFMcjs = require('./chunk-527QSKFM.cjs');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
@@ -34,7 +34,7 @@ var _chunkGJTYOFMOcjs = require('./chunk-GJTYOFMO.cjs');
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
var
|
|
37
|
+
var _chunkJ74L7UYPcjs = require('./chunk-J74L7UYP.cjs');
|
|
38
38
|
|
|
39
39
|
// src/ref.ts
|
|
40
40
|
function createRef() {
|
|
@@ -46,8 +46,8 @@ function ErrorBoundary(props) {
|
|
|
46
46
|
const fragment = document.createDocumentFragment();
|
|
47
47
|
const marker = document.createComment("fict:error-boundary");
|
|
48
48
|
fragment.appendChild(marker);
|
|
49
|
-
const currentView =
|
|
50
|
-
const hostRoot =
|
|
49
|
+
const currentView = _chunkJ74L7UYPcjs.signal.call(void 0, _nullishCoalesce(props.children, () => ( null)));
|
|
50
|
+
const hostRoot = _chunkJ74L7UYPcjs.getCurrentRoot.call(void 0, );
|
|
51
51
|
let cleanup;
|
|
52
52
|
let activeNodes = [];
|
|
53
53
|
let renderingFallback = false;
|
|
@@ -63,26 +63,26 @@ function ErrorBoundary(props) {
|
|
|
63
63
|
cleanup = void 0;
|
|
64
64
|
}
|
|
65
65
|
if (activeNodes.length) {
|
|
66
|
-
|
|
66
|
+
_chunkJ74L7UYPcjs.removeNodes.call(void 0, activeNodes);
|
|
67
67
|
activeNodes = [];
|
|
68
68
|
}
|
|
69
69
|
if (value == null || value === false) {
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
|
-
const root =
|
|
73
|
-
const prev =
|
|
72
|
+
const root = _chunkJ74L7UYPcjs.createRootContext.call(void 0, hostRoot);
|
|
73
|
+
const prev = _chunkJ74L7UYPcjs.pushRoot.call(void 0, root);
|
|
74
74
|
let nodes = [];
|
|
75
75
|
try {
|
|
76
|
-
const output =
|
|
77
|
-
nodes =
|
|
76
|
+
const output = _chunkJ74L7UYPcjs.createElement.call(void 0, value);
|
|
77
|
+
nodes = _chunkJ74L7UYPcjs.toNodeArray.call(void 0, output);
|
|
78
78
|
const parentNode = marker.parentNode;
|
|
79
79
|
if (parentNode) {
|
|
80
|
-
|
|
80
|
+
_chunkJ74L7UYPcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
|
|
81
81
|
}
|
|
82
82
|
} catch (err) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
_chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
|
|
84
|
+
_chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
|
|
85
|
+
_chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
|
|
86
86
|
if (renderingFallback) {
|
|
87
87
|
throw err;
|
|
88
88
|
}
|
|
@@ -97,19 +97,19 @@ function ErrorBoundary(props) {
|
|
|
97
97
|
}
|
|
98
98
|
return;
|
|
99
99
|
}
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
_chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
|
|
101
|
+
_chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
|
|
102
102
|
cleanup = () => {
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
_chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
|
|
104
|
+
_chunkJ74L7UYPcjs.removeNodes.call(void 0, nodes);
|
|
105
105
|
};
|
|
106
106
|
activeNodes = nodes;
|
|
107
107
|
};
|
|
108
|
-
|
|
108
|
+
_chunkJ74L7UYPcjs.createEffect.call(void 0, () => {
|
|
109
109
|
const value = currentView();
|
|
110
110
|
renderValue(value);
|
|
111
111
|
});
|
|
112
|
-
|
|
112
|
+
_chunkJ74L7UYPcjs.registerErrorHandler.call(void 0, (err) => {
|
|
113
113
|
renderValue(toView(err));
|
|
114
114
|
_optionalChain([props, 'access', _5 => _5.onError, 'optionalCall', _6 => _6(err)]);
|
|
115
115
|
return true;
|
|
@@ -118,7 +118,7 @@ function ErrorBoundary(props) {
|
|
|
118
118
|
const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
|
|
119
119
|
const getter = isGetter ? props.resetKeys : void 0;
|
|
120
120
|
let prev = isGetter ? getter() : props.resetKeys;
|
|
121
|
-
|
|
121
|
+
_chunkJ74L7UYPcjs.createEffect.call(void 0, () => {
|
|
122
122
|
const next = getter ? getter() : props.resetKeys;
|
|
123
123
|
if (prev !== next) {
|
|
124
124
|
prev = next;
|
|
@@ -147,58 +147,54 @@ function createSuspenseToken() {
|
|
|
147
147
|
}
|
|
148
148
|
var isThenable = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
|
|
149
149
|
function Suspense(props) {
|
|
150
|
-
const currentView =
|
|
151
|
-
const pending =
|
|
150
|
+
const currentView = _chunkJ74L7UYPcjs.signal.call(void 0, _nullishCoalesce(props.children, () => ( null)));
|
|
151
|
+
const pending = _chunkJ74L7UYPcjs.signal.call(void 0, 0);
|
|
152
152
|
let resolvedOnce = false;
|
|
153
153
|
let epoch = 0;
|
|
154
|
-
const hostRoot =
|
|
154
|
+
const hostRoot = _chunkJ74L7UYPcjs.getCurrentRoot.call(void 0, );
|
|
155
155
|
const toFallback = (err) => typeof props.fallback === "function" ? props.fallback(err) : props.fallback;
|
|
156
|
-
const switchView = (view) => {
|
|
157
|
-
currentView(view);
|
|
158
|
-
renderView(view);
|
|
159
|
-
};
|
|
160
156
|
const renderView = (view) => {
|
|
161
157
|
if (cleanup) {
|
|
162
158
|
cleanup();
|
|
163
159
|
cleanup = void 0;
|
|
164
160
|
}
|
|
165
161
|
if (activeNodes.length) {
|
|
166
|
-
|
|
162
|
+
_chunkJ74L7UYPcjs.removeNodes.call(void 0, activeNodes);
|
|
167
163
|
activeNodes = [];
|
|
168
164
|
}
|
|
169
165
|
if (view == null || view === false) {
|
|
170
166
|
return;
|
|
171
167
|
}
|
|
172
|
-
const root =
|
|
173
|
-
const prev =
|
|
168
|
+
const root = _chunkJ74L7UYPcjs.createRootContext.call(void 0, hostRoot);
|
|
169
|
+
const prev = _chunkJ74L7UYPcjs.pushRoot.call(void 0, root);
|
|
174
170
|
let nodes = [];
|
|
175
171
|
try {
|
|
176
|
-
const output =
|
|
177
|
-
nodes =
|
|
178
|
-
const suspendedAttempt = nodes.length > 0 && nodes.every((node) => node instanceof Comment && node.data === "fict:suspend");
|
|
172
|
+
const output = _chunkJ74L7UYPcjs.createElement.call(void 0, view);
|
|
173
|
+
nodes = _chunkJ74L7UYPcjs.toNodeArray.call(void 0, output);
|
|
174
|
+
const suspendedAttempt = root.suspended || nodes.length > 0 && nodes.every((node) => node instanceof Comment && node.data === "fict:suspend");
|
|
179
175
|
if (suspendedAttempt) {
|
|
180
|
-
|
|
181
|
-
|
|
176
|
+
_chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
|
|
177
|
+
_chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
|
|
182
178
|
return;
|
|
183
179
|
}
|
|
184
180
|
const parentNode = marker.parentNode;
|
|
185
181
|
if (parentNode) {
|
|
186
|
-
|
|
182
|
+
_chunkJ74L7UYPcjs.insertNodesBefore.call(void 0, parentNode, nodes, marker);
|
|
187
183
|
}
|
|
188
184
|
} catch (err) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (!
|
|
185
|
+
_chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
|
|
186
|
+
_chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
|
|
187
|
+
_chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
|
|
188
|
+
if (!_chunkJ74L7UYPcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
|
|
193
189
|
throw err;
|
|
194
190
|
}
|
|
195
191
|
return;
|
|
196
192
|
}
|
|
197
|
-
|
|
198
|
-
|
|
193
|
+
_chunkJ74L7UYPcjs.popRoot.call(void 0, prev);
|
|
194
|
+
_chunkJ74L7UYPcjs.flushOnMount.call(void 0, root);
|
|
199
195
|
cleanup = () => {
|
|
200
|
-
|
|
201
|
-
|
|
196
|
+
_chunkJ74L7UYPcjs.destroyRoot.call(void 0, root);
|
|
197
|
+
_chunkJ74L7UYPcjs.removeNodes.call(void 0, nodes);
|
|
202
198
|
};
|
|
203
199
|
activeNodes = nodes;
|
|
204
200
|
};
|
|
@@ -213,10 +209,11 @@ function Suspense(props) {
|
|
|
213
209
|
_optionalChain([props, 'access', _7 => _7.onResolve, 'optionalCall', _8 => _8()]);
|
|
214
210
|
}
|
|
215
211
|
};
|
|
216
|
-
|
|
212
|
+
_chunkJ74L7UYPcjs.registerSuspenseHandler.call(void 0, (token) => {
|
|
217
213
|
const tokenEpoch = epoch;
|
|
218
214
|
pending(pending() + 1);
|
|
219
|
-
|
|
215
|
+
currentView(toFallback());
|
|
216
|
+
renderView(toFallback());
|
|
220
217
|
const thenable = token.then ? token : isThenable(token) ? token : null;
|
|
221
218
|
if (thenable) {
|
|
222
219
|
thenable.then(
|
|
@@ -227,7 +224,8 @@ function Suspense(props) {
|
|
|
227
224
|
const newPending = Math.max(0, pending() - 1);
|
|
228
225
|
pending(newPending);
|
|
229
226
|
if (newPending === 0) {
|
|
230
|
-
|
|
227
|
+
currentView(_nullishCoalesce(props.children, () => ( null)));
|
|
228
|
+
renderView(_nullishCoalesce(props.children, () => ( null)));
|
|
231
229
|
onResolveMaybe();
|
|
232
230
|
}
|
|
233
231
|
},
|
|
@@ -238,7 +236,7 @@ function Suspense(props) {
|
|
|
238
236
|
const newPending = Math.max(0, pending() - 1);
|
|
239
237
|
pending(newPending);
|
|
240
238
|
_optionalChain([props, 'access', _9 => _9.onReject, 'optionalCall', _10 => _10(err)]);
|
|
241
|
-
if (!
|
|
239
|
+
if (!_chunkJ74L7UYPcjs.handleError.call(void 0, err, { source: "render" }, hostRoot)) {
|
|
242
240
|
throw err;
|
|
243
241
|
}
|
|
244
242
|
}
|
|
@@ -247,20 +245,19 @@ function Suspense(props) {
|
|
|
247
245
|
}
|
|
248
246
|
return false;
|
|
249
247
|
});
|
|
250
|
-
|
|
251
|
-
renderView(currentView());
|
|
252
|
-
});
|
|
248
|
+
renderView(_nullishCoalesce(props.children, () => ( null)));
|
|
253
249
|
if (props.resetKeys !== void 0) {
|
|
254
250
|
const isGetter = typeof props.resetKeys === "function" && props.resetKeys.length === 0;
|
|
255
251
|
const getter = isGetter ? props.resetKeys : void 0;
|
|
256
252
|
let prev = isGetter ? getter() : props.resetKeys;
|
|
257
|
-
|
|
253
|
+
_chunkJ74L7UYPcjs.createEffect.call(void 0, () => {
|
|
258
254
|
const next = getter ? getter() : props.resetKeys;
|
|
259
255
|
if (prev !== next) {
|
|
260
256
|
prev = next;
|
|
261
257
|
epoch++;
|
|
262
258
|
pending(0);
|
|
263
|
-
|
|
259
|
+
currentView(_nullishCoalesce(props.children, () => ( null)));
|
|
260
|
+
renderView(_nullishCoalesce(props.children, () => ( null)));
|
|
264
261
|
}
|
|
265
262
|
});
|
|
266
263
|
}
|
|
@@ -291,5 +288,5 @@ function Suspense(props) {
|
|
|
291
288
|
|
|
292
289
|
|
|
293
290
|
|
|
294
|
-
exports.ErrorBoundary = ErrorBoundary; exports.Fragment =
|
|
291
|
+
exports.ErrorBoundary = ErrorBoundary; exports.Fragment = _chunkJ74L7UYPcjs.Fragment; exports.Suspense = Suspense; exports.batch = _chunkJ74L7UYPcjs.batch2; exports.createContext = _chunk527QSKFMcjs.createContext; exports.createEffect = _chunkJ74L7UYPcjs.createEffect; exports.createElement = _chunkJ74L7UYPcjs.createElement; exports.createMemo = _chunkJ74L7UYPcjs.createMemo; exports.createPortal = _chunkJ74L7UYPcjs.createPortal; exports.createRef = createRef; exports.createRoot = _chunkJ74L7UYPcjs.createRoot; exports.createSuspenseToken = createSuspenseToken; exports.hasContext = _chunk527QSKFMcjs.hasContext; exports.mergeProps = _chunkJ74L7UYPcjs.mergeProps; exports.onCleanup = _chunkJ74L7UYPcjs.onCleanup; exports.onDestroy = _chunkJ74L7UYPcjs.onDestroy; exports.onMount = _chunkJ74L7UYPcjs.onMount; exports.prop = _chunkJ74L7UYPcjs.prop; exports.render = _chunkJ74L7UYPcjs.render; exports.startTransition = _chunkJ74L7UYPcjs.startTransition; exports.untrack = _chunkJ74L7UYPcjs.untrack2; exports.useContext = _chunk527QSKFMcjs.useContext; exports.useDeferredValue = _chunkJ74L7UYPcjs.useDeferredValue; exports.useTransition = _chunkJ74L7UYPcjs.useTransition;
|
|
295
292
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","../src/ref.ts","../src/error-boundary.ts","../src/suspense.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","sourcesContent":[null,"import type { RefObject } from './types'\n\n/**\n * Create a ref object for DOM element references.\n *\n * @returns A ref object with a `current` property initialized to `null`\n *\n * @example\n * ```tsx\n * import { createRef } from 'fict'\n *\n * function Component() {\n * const inputRef = createRef<HTMLInputElement>()\n *\n * $effect(() => {\n * inputRef.current?.focus()\n * })\n *\n * return <input ref={inputRef} />\n * }\n * ```\n */\nexport function createRef<T extends Element = HTMLElement>(): RefObject<T> {\n return { current: null }\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n pushRoot,\n popRoot,\n registerErrorHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode } from './types'\n\ninterface ErrorBoundaryProps extends BaseProps {\n fallback: FictNode | ((err: unknown) => FictNode)\n onError?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): FictNode {\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:error-boundary')\n fragment.appendChild(marker)\n\n const currentView = createSignal<FictNode | null>(props.children ?? null)\n const hostRoot = getCurrentRoot()\n\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n let renderingFallback = false\n\n const toView = (err: unknown | null): FictNode | null => {\n if (err != null) {\n return typeof props.fallback === 'function'\n ? (props.fallback as (e: unknown) => FictNode)(err)\n : props.fallback\n }\n return props.children ?? null\n }\n\n const renderValue = (value: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (value == null || value === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(value)\n nodes = toNodeArray(output)\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n flushOnMount(root)\n destroyRoot(root)\n // Fall back immediately on render errors, avoid infinite recursion\n if (renderingFallback) {\n throw err\n }\n // nested errors. If fallback rendering also throws, we should NOT reset\n // the flag until we're sure no more recursion is happening.\n renderingFallback = true\n try {\n renderValue(toView(err))\n // Only reset if successful - if renderValue threw, we want to keep\n // renderingFallback = true to prevent infinite recursion\n renderingFallback = false\n props.onError?.(err)\n } catch (fallbackErr) {\n // Fallback rendering failed - keep renderingFallback = true\n // to prevent further attempts, then rethrow\n // If fallback fails, report both errors\n props.onError?.(err)\n throw fallbackErr\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n createEffect(() => {\n const value = currentView()\n renderValue(value)\n })\n\n registerErrorHandler(err => {\n renderValue(toView(err))\n props.onError?.(err)\n return true\n })\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n renderValue(toView(null))\n }\n })\n }\n\n return fragment\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n handleError,\n pushRoot,\n popRoot,\n registerSuspenseHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode, SuspenseToken } from './types'\n\nexport interface SuspenseProps extends BaseProps {\n fallback: FictNode | ((err?: unknown) => FictNode)\n onResolve?: () => void\n onReject?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport interface SuspenseHandle {\n token: SuspenseToken\n resolve: () => void\n reject: (err: unknown) => void\n}\n\nexport function createSuspenseToken(): SuspenseHandle {\n let resolve!: () => void\n let reject!: (err: unknown) => void\n const promise = new Promise<void>((res, rej) => {\n resolve = res\n reject = rej\n })\n return {\n token: {\n then: promise.then.bind(promise),\n },\n resolve,\n reject,\n }\n}\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as PromiseLike<unknown>).then === 'function'\n\nexport function Suspense(props: SuspenseProps): FictNode {\n const currentView = createSignal<FictNode | null>(props.children ?? null)\n const pending = createSignal(0)\n let resolvedOnce = false\n let epoch = 0\n const hostRoot = getCurrentRoot()\n\n const toFallback = (err?: unknown) =>\n typeof props.fallback === 'function'\n ? (props.fallback as (e?: unknown) => FictNode)(err)\n : props.fallback\n\n const switchView = (view: FictNode | null) => {\n currentView(view)\n renderView(view)\n }\n\n const renderView = (view: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (view == null || view === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(view)\n nodes = toNodeArray(output)\n // Suspended view: child threw a suspense token and was handled upstream.\n // Avoid replacing existing fallback content; tear down this attempt.\n const suspendedAttempt =\n nodes.length > 0 &&\n nodes.every(node => node instanceof Comment && (node as Comment).data === 'fict:suspend')\n if (suspendedAttempt) {\n popRoot(prev)\n destroyRoot(root)\n return\n }\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n flushOnMount(root)\n destroyRoot(root)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:suspense')\n fragment.appendChild(marker)\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n\n const onResolveMaybe = () => {\n if (!resolvedOnce) {\n resolvedOnce = true\n props.onResolve?.()\n }\n }\n\n registerSuspenseHandler(token => {\n const tokenEpoch = epoch\n pending(pending() + 1)\n switchView(toFallback())\n\n const thenable = (token as SuspenseToken).then\n ? (token as SuspenseToken)\n : isThenable(token)\n ? token\n : null\n\n if (thenable) {\n thenable.then(\n () => {\n // This prevents stale token resolutions from affecting state after\n // a reset. The order is important: check epoch first, then update state.\n if (epoch !== tokenEpoch) {\n // Token is stale (from before a reset), ignore it completely\n return\n }\n // Use Math.max as a defensive measure - pending should never go below 0,\n // but this protects against edge cases where a token might resolve twice\n // or after the component has been reset.\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n if (newPending === 0) {\n switchView(props.children ?? null)\n onResolveMaybe()\n }\n },\n err => {\n // Same epoch check - ignore stale tokens\n if (epoch !== tokenEpoch) {\n return\n }\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n props.onReject?.(err)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n },\n )\n return true\n }\n\n return false\n })\n\n createEffect(() => {\n renderView(currentView())\n })\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n epoch++\n pending(0)\n switchView(props.children ?? null)\n }\n })\n }\n\n return fragment\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","../src/ref.ts","../src/error-boundary.ts","../src/suspense.ts"],"names":[],"mappings":"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","file":"/home/runner/work/fict/fict/packages/runtime/dist/index.cjs","sourcesContent":[null,"import type { RefObject } from './types'\n\n/**\n * Create a ref object for DOM element references.\n *\n * @returns A ref object with a `current` property initialized to `null`\n *\n * @example\n * ```tsx\n * import { createRef } from 'fict'\n *\n * function Component() {\n * const inputRef = createRef<HTMLInputElement>()\n *\n * $effect(() => {\n * inputRef.current?.focus()\n * })\n *\n * return <input ref={inputRef} />\n * }\n * ```\n */\nexport function createRef<T extends Element = HTMLElement>(): RefObject<T> {\n return { current: null }\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n pushRoot,\n popRoot,\n registerErrorHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode } from './types'\n\ninterface ErrorBoundaryProps extends BaseProps {\n fallback: FictNode | ((err: unknown) => FictNode)\n onError?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport function ErrorBoundary(props: ErrorBoundaryProps): FictNode {\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:error-boundary')\n fragment.appendChild(marker)\n\n const currentView = createSignal<FictNode | null>(props.children ?? null)\n const hostRoot = getCurrentRoot()\n\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n let renderingFallback = false\n\n const toView = (err: unknown | null): FictNode | null => {\n if (err != null) {\n return typeof props.fallback === 'function'\n ? (props.fallback as (e: unknown) => FictNode)(err)\n : props.fallback\n }\n return props.children ?? null\n }\n\n const renderValue = (value: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (value == null || value === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(value)\n nodes = toNodeArray(output)\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n flushOnMount(root)\n destroyRoot(root)\n // Fall back immediately on render errors, avoid infinite recursion\n if (renderingFallback) {\n throw err\n }\n // nested errors. If fallback rendering also throws, we should NOT reset\n // the flag until we're sure no more recursion is happening.\n renderingFallback = true\n try {\n renderValue(toView(err))\n // Only reset if successful - if renderValue threw, we want to keep\n // renderingFallback = true to prevent infinite recursion\n renderingFallback = false\n props.onError?.(err)\n } catch (fallbackErr) {\n // Fallback rendering failed - keep renderingFallback = true\n // to prevent further attempts, then rethrow\n // If fallback fails, report both errors\n props.onError?.(err)\n throw fallbackErr\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n createEffect(() => {\n const value = currentView()\n renderValue(value)\n })\n\n registerErrorHandler(err => {\n renderValue(toView(err))\n props.onError?.(err)\n return true\n })\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n renderValue(toView(null))\n }\n })\n }\n\n return fragment\n}\n","import { createElement } from './dom'\nimport { createEffect } from './effect'\nimport {\n createRootContext,\n destroyRoot,\n flushOnMount,\n getCurrentRoot,\n handleError,\n pushRoot,\n popRoot,\n registerSuspenseHandler,\n} from './lifecycle'\nimport { insertNodesBefore, removeNodes, toNodeArray } from './node-ops'\nimport { createSignal } from './signal'\nimport type { BaseProps, FictNode, SuspenseToken } from './types'\n\nexport interface SuspenseProps extends BaseProps {\n fallback: FictNode | ((err?: unknown) => FictNode)\n onResolve?: () => void\n onReject?: (err: unknown) => void\n resetKeys?: unknown | (() => unknown)\n}\n\nexport interface SuspenseHandle {\n token: SuspenseToken\n resolve: () => void\n reject: (err: unknown) => void\n}\n\nexport function createSuspenseToken(): SuspenseHandle {\n let resolve!: () => void\n let reject!: (err: unknown) => void\n const promise = new Promise<void>((res, rej) => {\n resolve = res\n reject = rej\n })\n return {\n token: {\n then: promise.then.bind(promise),\n },\n resolve,\n reject,\n }\n}\n\nconst isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as PromiseLike<unknown>).then === 'function'\n\nexport function Suspense(props: SuspenseProps): FictNode {\n const currentView = createSignal<FictNode | null>(props.children ?? null)\n const pending = createSignal(0)\n let resolvedOnce = false\n let epoch = 0\n const hostRoot = getCurrentRoot()\n\n const toFallback = (err?: unknown) =>\n typeof props.fallback === 'function'\n ? (props.fallback as (e?: unknown) => FictNode)(err)\n : props.fallback\n\n const renderView = (view: FictNode | null) => {\n if (cleanup) {\n cleanup()\n cleanup = undefined\n }\n if (activeNodes.length) {\n removeNodes(activeNodes)\n activeNodes = []\n }\n\n if (view == null || view === false) {\n return\n }\n\n const root = createRootContext(hostRoot)\n const prev = pushRoot(root)\n let nodes: Node[] = []\n try {\n const output = createElement(view)\n nodes = toNodeArray(output)\n // Suspended view: child threw a suspense token and was handled upstream.\n // Avoid replacing existing fallback content; tear down this attempt.\n const suspendedAttempt =\n root.suspended ||\n (nodes.length > 0 &&\n nodes.every(node => node instanceof Comment && (node as Comment).data === 'fict:suspend'))\n if (suspendedAttempt) {\n popRoot(prev)\n destroyRoot(root)\n return\n }\n const parentNode = marker.parentNode as (ParentNode & Node) | null\n if (parentNode) {\n insertNodesBefore(parentNode, nodes, marker)\n }\n } catch (err) {\n popRoot(prev)\n flushOnMount(root)\n destroyRoot(root)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n return\n }\n popRoot(prev)\n flushOnMount(root)\n\n cleanup = () => {\n destroyRoot(root)\n removeNodes(nodes)\n }\n activeNodes = nodes\n }\n\n const fragment = document.createDocumentFragment()\n const marker = document.createComment('fict:suspense')\n fragment.appendChild(marker)\n let cleanup: (() => void) | undefined\n let activeNodes: Node[] = []\n\n const onResolveMaybe = () => {\n if (!resolvedOnce) {\n resolvedOnce = true\n props.onResolve?.()\n }\n }\n\n registerSuspenseHandler(token => {\n const tokenEpoch = epoch\n pending(pending() + 1)\n // Directly render fallback instead of using switchView to avoid\n // triggering the effect which would cause duplicate renders\n currentView(toFallback())\n renderView(toFallback())\n\n const thenable = (token as SuspenseToken).then\n ? (token as SuspenseToken)\n : isThenable(token)\n ? token\n : null\n\n if (thenable) {\n thenable.then(\n () => {\n // This prevents stale token resolutions from affecting state after\n // a reset. The order is important: check epoch first, then update state.\n if (epoch !== tokenEpoch) {\n // Token is stale (from before a reset), ignore it completely\n return\n }\n // Use Math.max as a defensive measure - pending should never go below 0,\n // but this protects against edge cases where a token might resolve twice\n // or after the component has been reset.\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n if (newPending === 0) {\n // Directly render children instead of using switchView\n currentView(props.children ?? null)\n renderView(props.children ?? null)\n onResolveMaybe()\n }\n },\n err => {\n // Same epoch check - ignore stale tokens\n if (epoch !== tokenEpoch) {\n return\n }\n const newPending = Math.max(0, pending() - 1)\n pending(newPending)\n props.onReject?.(err)\n if (!handleError(err, { source: 'render' }, hostRoot)) {\n throw err\n }\n },\n )\n return true\n }\n\n return false\n })\n\n // Initial render - render children directly\n // Note: This will be called synchronously during component creation.\n // If children suspend, the handler above will be called and switch to fallback.\n renderView(props.children ?? null)\n\n if (props.resetKeys !== undefined) {\n const isGetter =\n typeof props.resetKeys === 'function' && (props.resetKeys as () => unknown).length === 0\n const getter = isGetter ? (props.resetKeys as () => unknown) : undefined\n let prev = isGetter ? getter!() : props.resetKeys\n createEffect(() => {\n const next = getter ? getter() : props.resetKeys\n if (prev !== next) {\n prev = next\n epoch++\n pending(0)\n // Directly render children instead of using switchView\n currentView(props.children ?? null)\n renderView(props.children ?? null)\n }\n })\n }\n\n return fragment\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { F as Fragment, J as JSX, M as Memo, e as createElement, c as createMemo, d as createRoot, m as mergeProps, b as onCleanup, a as onDestroy, o as onMount, p as prop, r as render } from './props-
|
|
2
|
-
import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-
|
|
3
|
-
export { p as ClassProp, C as Cleanup, l as Component, D as DOMElement, E as Effect, r as ErrorInfo, q as EventHandler, k as FictVNode, P as PropsWithChildren, m as Ref, n as RefCallback, o as StyleProp, h as createEffect, j as createPortal } from './effect-
|
|
4
|
-
export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-
|
|
1
|
+
export { F as Fragment, J as JSX, M as Memo, e as createElement, c as createMemo, d as createRoot, m as mergeProps, b as onCleanup, a as onDestroy, o as onMount, p as prop, r as render } from './props-CBwuh35e.cjs';
|
|
2
|
+
import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-ClARNUCc.cjs';
|
|
3
|
+
export { p as ClassProp, C as Cleanup, l as Component, D as DOMElement, E as Effect, r as ErrorInfo, q as EventHandler, k as FictVNode, P as PropsWithChildren, m as Ref, n as RefCallback, o as StyleProp, h as createEffect, j as createPortal } from './effect-ClARNUCc.cjs';
|
|
4
|
+
export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-9gFXOdJl.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Create a ref object for DOM element references.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { F as Fragment, J as JSX, M as Memo, e as createElement, c as createMemo, d as createRoot, m as mergeProps, b as onCleanup, a as onDestroy, o as onMount, p as prop, r as render } from './props-
|
|
2
|
-
import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-
|
|
3
|
-
export { p as ClassProp, C as Cleanup, l as Component, D as DOMElement, E as Effect, r as ErrorInfo, q as EventHandler, k as FictVNode, P as PropsWithChildren, m as Ref, n as RefCallback, o as StyleProp, h as createEffect, j as createPortal } from './effect-
|
|
4
|
-
export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-
|
|
1
|
+
export { F as Fragment, J as JSX, M as Memo, e as createElement, c as createMemo, d as createRoot, m as mergeProps, b as onCleanup, a as onDestroy, o as onMount, p as prop, r as render } from './props-DAyeRPwH.js';
|
|
2
|
+
import { R as RefObject, B as BaseProps, F as FictNode, S as SuspenseToken } from './effect-ClARNUCc.js';
|
|
3
|
+
export { p as ClassProp, C as Cleanup, l as Component, D as DOMElement, E as Effect, r as ErrorInfo, q as EventHandler, k as FictVNode, P as PropsWithChildren, m as Ref, n as RefCallback, o as StyleProp, h as createEffect, j as createPortal } from './effect-ClARNUCc.js';
|
|
4
|
+
export { C as Context, P as ProviderProps, c as createContext, h as hasContext, u as useContext } from './context-4woHo7-L.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Create a ref object for DOM element references.
|