@getforma/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +48 -0
- package/dist/chunk-27QSSN4E.cjs +1773 -0
- package/dist/chunk-27QSSN4E.cjs.map +1 -0
- package/dist/chunk-DB2ULMOM.js +1750 -0
- package/dist/chunk-DB2ULMOM.js.map +1 -0
- package/dist/chunk-FPSLC62A.cjs +31 -0
- package/dist/chunk-FPSLC62A.cjs.map +1 -0
- package/dist/chunk-KX5WRZH7.js +27 -0
- package/dist/chunk-KX5WRZH7.js.map +1 -0
- package/dist/formajs-runtime-hardened.global.js +2 -0
- package/dist/formajs-runtime-hardened.global.js.map +1 -0
- package/dist/formajs-runtime.global.js +2 -0
- package/dist/formajs-runtime.global.js.map +1 -0
- package/dist/formajs.global.js +2 -0
- package/dist/formajs.global.js.map +1 -0
- package/dist/index.cjs +1626 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1382 -0
- package/dist/index.d.ts +1382 -0
- package/dist/index.js +1482 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime-hardened.cjs +2805 -0
- package/dist/runtime-hardened.cjs.map +1 -0
- package/dist/runtime-hardened.js +2786 -0
- package/dist/runtime-hardened.js.map +1 -0
- package/dist/runtime.cjs +2531 -0
- package/dist/runtime.cjs.map +1 -0
- package/dist/runtime.d.cts +86 -0
- package/dist/runtime.d.ts +86 -0
- package/dist/runtime.js +2512 -0
- package/dist/runtime.js.map +1 -0
- package/dist/signal-CfLDwMyg.d.cts +29 -0
- package/dist/signal-CfLDwMyg.d.ts +29 -0
- package/dist/ssr/index.cjs +381 -0
- package/dist/ssr/index.cjs.map +1 -0
- package/dist/ssr/index.d.cts +154 -0
- package/dist/ssr/index.d.ts +154 -0
- package/dist/ssr/index.js +371 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/tc39-compat.cjs +45 -0
- package/dist/tc39-compat.cjs.map +1 -0
- package/dist/tc39-compat.d.cts +50 -0
- package/dist/tc39-compat.d.ts +50 -0
- package/dist/tc39-compat.js +42 -0
- package/dist/tc39-compat.js.map +1 -0
- package/package.json +122 -0
|
@@ -0,0 +1,1773 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkFPSLC62A_cjs = require('./chunk-FPSLC62A.cjs');
|
|
4
|
+
var alienSignals = require('alien-signals');
|
|
5
|
+
|
|
6
|
+
// src/reactive/root.ts
|
|
7
|
+
var currentRoot = null;
|
|
8
|
+
var rootStack = [];
|
|
9
|
+
function createRoot(fn) {
|
|
10
|
+
const scope = { disposers: [] };
|
|
11
|
+
rootStack.push(currentRoot);
|
|
12
|
+
currentRoot = scope;
|
|
13
|
+
const dispose = () => {
|
|
14
|
+
for (const d of scope.disposers) {
|
|
15
|
+
try {
|
|
16
|
+
d();
|
|
17
|
+
} catch {
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
scope.disposers.length = 0;
|
|
21
|
+
};
|
|
22
|
+
try {
|
|
23
|
+
return fn(dispose);
|
|
24
|
+
} finally {
|
|
25
|
+
currentRoot = rootStack.pop() ?? null;
|
|
26
|
+
if (rootStack.length === 0 && rootStack.length !== rootStack.__capacity) {
|
|
27
|
+
rootStack.length = 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function registerDisposer(dispose) {
|
|
32
|
+
if (currentRoot) {
|
|
33
|
+
currentRoot.disposers.push(dispose);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function hasActiveRoot() {
|
|
37
|
+
return currentRoot !== null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/reactive/cleanup.ts
|
|
41
|
+
var currentCleanupCollector = null;
|
|
42
|
+
function onCleanup(fn) {
|
|
43
|
+
currentCleanupCollector?.(fn);
|
|
44
|
+
}
|
|
45
|
+
function setCleanupCollector(collector) {
|
|
46
|
+
const prev = currentCleanupCollector;
|
|
47
|
+
currentCleanupCollector = collector;
|
|
48
|
+
return prev;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/reactive/dev.ts
|
|
52
|
+
var __DEV__ = typeof process !== "undefined" ? process.env?.NODE_ENV !== "production" : true;
|
|
53
|
+
var _errorHandler = null;
|
|
54
|
+
function onError(handler) {
|
|
55
|
+
_errorHandler = handler;
|
|
56
|
+
}
|
|
57
|
+
function reportError(error, source) {
|
|
58
|
+
if (_errorHandler) {
|
|
59
|
+
try {
|
|
60
|
+
_errorHandler(error, source ? { source } : {});
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (__DEV__) {
|
|
65
|
+
console.error(`[forma] ${source ?? "Unknown"} error:`, error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
var POOL_SIZE = 32;
|
|
69
|
+
var MAX_REENTRANT_RUNS = 100;
|
|
70
|
+
var pool = [];
|
|
71
|
+
for (let i = 0; i < POOL_SIZE; i++) pool.push([]);
|
|
72
|
+
var poolIdx = POOL_SIZE;
|
|
73
|
+
function acquireArray() {
|
|
74
|
+
if (poolIdx > 0) {
|
|
75
|
+
const arr = pool[--poolIdx];
|
|
76
|
+
arr.length = 0;
|
|
77
|
+
return arr;
|
|
78
|
+
}
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
function releaseArray(arr) {
|
|
82
|
+
arr.length = 0;
|
|
83
|
+
if (poolIdx < POOL_SIZE) {
|
|
84
|
+
pool[poolIdx++] = arr;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function runCleanup(fn) {
|
|
88
|
+
if (fn === void 0) return;
|
|
89
|
+
try {
|
|
90
|
+
fn();
|
|
91
|
+
} catch (e) {
|
|
92
|
+
reportError(e, "effect cleanup");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function runCleanups(bag) {
|
|
96
|
+
if (bag === void 0) return;
|
|
97
|
+
for (let i = 0; i < bag.length; i++) {
|
|
98
|
+
try {
|
|
99
|
+
bag[i]();
|
|
100
|
+
} catch (e) {
|
|
101
|
+
reportError(e, "effect cleanup");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function internalEffect(fn) {
|
|
106
|
+
const dispose = alienSignals.effect(fn);
|
|
107
|
+
if (hasActiveRoot()) {
|
|
108
|
+
registerDisposer(dispose);
|
|
109
|
+
}
|
|
110
|
+
return dispose;
|
|
111
|
+
}
|
|
112
|
+
function createEffect(fn) {
|
|
113
|
+
const shouldRegister = hasActiveRoot();
|
|
114
|
+
let cleanup2;
|
|
115
|
+
let cleanupBag;
|
|
116
|
+
let nextCleanup;
|
|
117
|
+
let nextCleanupBag;
|
|
118
|
+
const addCleanup = (cb) => {
|
|
119
|
+
if (nextCleanupBag !== void 0) {
|
|
120
|
+
nextCleanupBag.push(cb);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (nextCleanup !== void 0) {
|
|
124
|
+
const bag = acquireArray();
|
|
125
|
+
bag.push(nextCleanup, cb);
|
|
126
|
+
nextCleanup = void 0;
|
|
127
|
+
nextCleanupBag = bag;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
nextCleanup = cb;
|
|
131
|
+
};
|
|
132
|
+
let skipCleanupInfra = false;
|
|
133
|
+
let firstRun = true;
|
|
134
|
+
let running = false;
|
|
135
|
+
let rerunRequested = false;
|
|
136
|
+
const runOnce = () => {
|
|
137
|
+
if (cleanup2 !== void 0) {
|
|
138
|
+
runCleanup(cleanup2);
|
|
139
|
+
cleanup2 = void 0;
|
|
140
|
+
}
|
|
141
|
+
if (cleanupBag !== void 0) {
|
|
142
|
+
runCleanups(cleanupBag);
|
|
143
|
+
releaseArray(cleanupBag);
|
|
144
|
+
cleanupBag = void 0;
|
|
145
|
+
}
|
|
146
|
+
if (skipCleanupInfra) {
|
|
147
|
+
try {
|
|
148
|
+
fn();
|
|
149
|
+
} catch (e) {
|
|
150
|
+
reportError(e, "effect");
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
nextCleanup = void 0;
|
|
155
|
+
nextCleanupBag = void 0;
|
|
156
|
+
const prevCollector = setCleanupCollector(addCleanup);
|
|
157
|
+
try {
|
|
158
|
+
const result = fn();
|
|
159
|
+
if (typeof result === "function") {
|
|
160
|
+
addCleanup(result);
|
|
161
|
+
}
|
|
162
|
+
if (nextCleanup === void 0 && nextCleanupBag === void 0) {
|
|
163
|
+
if (firstRun) skipCleanupInfra = true;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (nextCleanupBag !== void 0) {
|
|
167
|
+
cleanupBag = nextCleanupBag;
|
|
168
|
+
} else {
|
|
169
|
+
cleanup2 = nextCleanup;
|
|
170
|
+
}
|
|
171
|
+
} catch (e) {
|
|
172
|
+
reportError(e, "effect");
|
|
173
|
+
if (nextCleanupBag !== void 0) {
|
|
174
|
+
cleanupBag = nextCleanupBag;
|
|
175
|
+
} else {
|
|
176
|
+
cleanup2 = nextCleanup;
|
|
177
|
+
}
|
|
178
|
+
} finally {
|
|
179
|
+
setCleanupCollector(prevCollector);
|
|
180
|
+
firstRun = false;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const safeFn = () => {
|
|
184
|
+
if (running) {
|
|
185
|
+
rerunRequested = true;
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
running = true;
|
|
189
|
+
try {
|
|
190
|
+
let reentrantRuns = 0;
|
|
191
|
+
do {
|
|
192
|
+
rerunRequested = false;
|
|
193
|
+
runOnce();
|
|
194
|
+
if (rerunRequested) {
|
|
195
|
+
reentrantRuns++;
|
|
196
|
+
if (reentrantRuns >= MAX_REENTRANT_RUNS) {
|
|
197
|
+
reportError(
|
|
198
|
+
new Error(`createEffect exceeded ${MAX_REENTRANT_RUNS} re-entrant runs`),
|
|
199
|
+
"effect"
|
|
200
|
+
);
|
|
201
|
+
rerunRequested = false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} while (rerunRequested);
|
|
205
|
+
} finally {
|
|
206
|
+
running = false;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const dispose = alienSignals.effect(safeFn);
|
|
210
|
+
let disposed = false;
|
|
211
|
+
const wrappedDispose = () => {
|
|
212
|
+
if (disposed) return;
|
|
213
|
+
disposed = true;
|
|
214
|
+
dispose();
|
|
215
|
+
if (cleanup2 !== void 0) {
|
|
216
|
+
runCleanup(cleanup2);
|
|
217
|
+
cleanup2 = void 0;
|
|
218
|
+
}
|
|
219
|
+
if (cleanupBag !== void 0) {
|
|
220
|
+
runCleanups(cleanupBag);
|
|
221
|
+
releaseArray(cleanupBag);
|
|
222
|
+
cleanupBag = void 0;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
if (shouldRegister) {
|
|
226
|
+
registerDisposer(wrappedDispose);
|
|
227
|
+
}
|
|
228
|
+
return wrappedDispose;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// src/reactive/memo.ts
|
|
232
|
+
var createMemo = chunkFPSLC62A_cjs.createComputed;
|
|
233
|
+
function batch(fn) {
|
|
234
|
+
alienSignals.startBatch();
|
|
235
|
+
try {
|
|
236
|
+
fn();
|
|
237
|
+
} finally {
|
|
238
|
+
alienSignals.endBatch();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function untrack(fn) {
|
|
242
|
+
alienSignals.pauseTracking();
|
|
243
|
+
try {
|
|
244
|
+
return fn();
|
|
245
|
+
} finally {
|
|
246
|
+
alienSignals.resumeTracking();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/reactive/on.ts
|
|
251
|
+
function on(deps, fn, options) {
|
|
252
|
+
let prev;
|
|
253
|
+
let isFirst = true;
|
|
254
|
+
return () => {
|
|
255
|
+
const value2 = deps();
|
|
256
|
+
if (options?.defer && isFirst) {
|
|
257
|
+
isFirst = false;
|
|
258
|
+
prev = value2;
|
|
259
|
+
return void 0;
|
|
260
|
+
}
|
|
261
|
+
const result = untrack(() => fn(value2, prev));
|
|
262
|
+
prev = value2;
|
|
263
|
+
return result;
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/reactive/ref.ts
|
|
268
|
+
function createRef(initialValue) {
|
|
269
|
+
return { current: initialValue };
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/reactive/reducer.ts
|
|
273
|
+
function createReducer(reducer, initialState) {
|
|
274
|
+
const [state, setState] = chunkFPSLC62A_cjs.createSignal(initialState);
|
|
275
|
+
const dispatch = (action) => {
|
|
276
|
+
setState((prev) => reducer(prev, action));
|
|
277
|
+
};
|
|
278
|
+
return [state, dispatch];
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/reactive/suspense-context.ts
|
|
282
|
+
var currentSuspenseContext = null;
|
|
283
|
+
var suspenseStack = [];
|
|
284
|
+
function pushSuspenseContext(ctx) {
|
|
285
|
+
suspenseStack.push(currentSuspenseContext);
|
|
286
|
+
currentSuspenseContext = ctx;
|
|
287
|
+
}
|
|
288
|
+
function popSuspenseContext() {
|
|
289
|
+
currentSuspenseContext = suspenseStack.pop() ?? null;
|
|
290
|
+
}
|
|
291
|
+
function getSuspenseContext() {
|
|
292
|
+
return currentSuspenseContext;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/reactive/resource.ts
|
|
296
|
+
function createResource(source, fetcher, options) {
|
|
297
|
+
const [data, setData] = chunkFPSLC62A_cjs.createSignal(options?.initialValue);
|
|
298
|
+
const [loading, setLoading] = chunkFPSLC62A_cjs.createValueSignal(false);
|
|
299
|
+
const [error, setError] = chunkFPSLC62A_cjs.createValueSignal(void 0);
|
|
300
|
+
const suspenseCtx = getSuspenseContext();
|
|
301
|
+
let abortController = null;
|
|
302
|
+
let fetchVersion = 0;
|
|
303
|
+
const doFetch = () => {
|
|
304
|
+
const sourceValue = untrack(source);
|
|
305
|
+
if (abortController) {
|
|
306
|
+
abortController.abort();
|
|
307
|
+
}
|
|
308
|
+
const controller = new AbortController();
|
|
309
|
+
abortController = controller;
|
|
310
|
+
const version = ++fetchVersion;
|
|
311
|
+
const isLatest = () => version === fetchVersion;
|
|
312
|
+
let suspensePending = false;
|
|
313
|
+
if (suspenseCtx) {
|
|
314
|
+
suspenseCtx.increment();
|
|
315
|
+
suspensePending = true;
|
|
316
|
+
}
|
|
317
|
+
setLoading(true);
|
|
318
|
+
setError(void 0);
|
|
319
|
+
Promise.resolve(fetcher(sourceValue)).then((result) => {
|
|
320
|
+
if (isLatest() && !controller.signal.aborted) {
|
|
321
|
+
setData(() => result);
|
|
322
|
+
}
|
|
323
|
+
}).catch((err) => {
|
|
324
|
+
if (isLatest() && !controller.signal.aborted) {
|
|
325
|
+
if (err?.name !== "AbortError") {
|
|
326
|
+
setError(err);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}).finally(() => {
|
|
330
|
+
if (suspensePending) suspenseCtx?.decrement();
|
|
331
|
+
if (isLatest()) {
|
|
332
|
+
setLoading(false);
|
|
333
|
+
if (abortController === controller) {
|
|
334
|
+
abortController = null;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
internalEffect(() => {
|
|
340
|
+
source();
|
|
341
|
+
doFetch();
|
|
342
|
+
});
|
|
343
|
+
const resource = (() => data());
|
|
344
|
+
resource.loading = loading;
|
|
345
|
+
resource.error = error;
|
|
346
|
+
resource.refetch = doFetch;
|
|
347
|
+
resource.mutate = (value2) => setData(() => value2);
|
|
348
|
+
return resource;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// src/dom/element.ts
|
|
352
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
353
|
+
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
354
|
+
var SVG_TAGS = /* @__PURE__ */ new Set([
|
|
355
|
+
"svg",
|
|
356
|
+
"path",
|
|
357
|
+
"circle",
|
|
358
|
+
"rect",
|
|
359
|
+
"line",
|
|
360
|
+
"polyline",
|
|
361
|
+
"polygon",
|
|
362
|
+
"ellipse",
|
|
363
|
+
"g",
|
|
364
|
+
"text",
|
|
365
|
+
"tspan",
|
|
366
|
+
"textPath",
|
|
367
|
+
"defs",
|
|
368
|
+
"use",
|
|
369
|
+
"symbol",
|
|
370
|
+
"clipPath",
|
|
371
|
+
"mask",
|
|
372
|
+
"pattern",
|
|
373
|
+
"marker",
|
|
374
|
+
"linearGradient",
|
|
375
|
+
"radialGradient",
|
|
376
|
+
"stop",
|
|
377
|
+
"filter",
|
|
378
|
+
"feGaussianBlur",
|
|
379
|
+
"feColorMatrix",
|
|
380
|
+
"feOffset",
|
|
381
|
+
"feBlend",
|
|
382
|
+
"feMerge",
|
|
383
|
+
"feMergeNode",
|
|
384
|
+
"feComposite",
|
|
385
|
+
"feFlood",
|
|
386
|
+
"feMorphology",
|
|
387
|
+
"feTurbulence",
|
|
388
|
+
"feDisplacementMap",
|
|
389
|
+
"feImage",
|
|
390
|
+
"foreignObject",
|
|
391
|
+
"animate",
|
|
392
|
+
"animateTransform",
|
|
393
|
+
"animateMotion",
|
|
394
|
+
"set",
|
|
395
|
+
"image",
|
|
396
|
+
"switch",
|
|
397
|
+
"desc",
|
|
398
|
+
"title",
|
|
399
|
+
"metadata"
|
|
400
|
+
]);
|
|
401
|
+
var BOOLEAN_ATTRS = /* @__PURE__ */ new Set([
|
|
402
|
+
"disabled",
|
|
403
|
+
"checked",
|
|
404
|
+
"readonly",
|
|
405
|
+
"required",
|
|
406
|
+
"autofocus",
|
|
407
|
+
"autoplay",
|
|
408
|
+
"controls",
|
|
409
|
+
"default",
|
|
410
|
+
"defer",
|
|
411
|
+
"formnovalidate",
|
|
412
|
+
"hidden",
|
|
413
|
+
"ismap",
|
|
414
|
+
"loop",
|
|
415
|
+
"multiple",
|
|
416
|
+
"muted",
|
|
417
|
+
"nomodule",
|
|
418
|
+
"novalidate",
|
|
419
|
+
"open",
|
|
420
|
+
"playsinline",
|
|
421
|
+
"reversed",
|
|
422
|
+
"selected",
|
|
423
|
+
"async"
|
|
424
|
+
]);
|
|
425
|
+
var ELEMENT_PROTOS = null;
|
|
426
|
+
function getProto(tag) {
|
|
427
|
+
if (!ELEMENT_PROTOS) {
|
|
428
|
+
ELEMENT_PROTOS = /* @__PURE__ */ Object.create(null);
|
|
429
|
+
for (const t of [
|
|
430
|
+
"div",
|
|
431
|
+
"span",
|
|
432
|
+
"p",
|
|
433
|
+
"a",
|
|
434
|
+
"li",
|
|
435
|
+
"ul",
|
|
436
|
+
"ol",
|
|
437
|
+
"button",
|
|
438
|
+
"input",
|
|
439
|
+
"label",
|
|
440
|
+
"h1",
|
|
441
|
+
"h2",
|
|
442
|
+
"h3",
|
|
443
|
+
"h4",
|
|
444
|
+
"h5",
|
|
445
|
+
"h6",
|
|
446
|
+
"section",
|
|
447
|
+
"header",
|
|
448
|
+
"footer",
|
|
449
|
+
"main",
|
|
450
|
+
"nav",
|
|
451
|
+
"table",
|
|
452
|
+
"tr",
|
|
453
|
+
"td",
|
|
454
|
+
"th",
|
|
455
|
+
"tbody",
|
|
456
|
+
"img",
|
|
457
|
+
"form",
|
|
458
|
+
"select",
|
|
459
|
+
"option",
|
|
460
|
+
"textarea",
|
|
461
|
+
"i",
|
|
462
|
+
"b",
|
|
463
|
+
"strong",
|
|
464
|
+
"em",
|
|
465
|
+
"small",
|
|
466
|
+
"article",
|
|
467
|
+
"aside",
|
|
468
|
+
"details",
|
|
469
|
+
"summary"
|
|
470
|
+
]) {
|
|
471
|
+
ELEMENT_PROTOS[t] = document.createElement(t);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return ELEMENT_PROTOS[tag] ?? (ELEMENT_PROTOS[tag] = document.createElement(tag));
|
|
475
|
+
}
|
|
476
|
+
var EVENT_NAMES = /* @__PURE__ */ Object.create(null);
|
|
477
|
+
function eventName(key) {
|
|
478
|
+
return EVENT_NAMES[key] ?? (EVENT_NAMES[key] = key.slice(2).toLowerCase());
|
|
479
|
+
}
|
|
480
|
+
var ABORT_SYM = /* @__PURE__ */ Symbol.for("forma-abort");
|
|
481
|
+
function getAbortController(el) {
|
|
482
|
+
let controller = el[ABORT_SYM];
|
|
483
|
+
if (!controller) {
|
|
484
|
+
controller = new AbortController();
|
|
485
|
+
el[ABORT_SYM] = controller;
|
|
486
|
+
}
|
|
487
|
+
return controller;
|
|
488
|
+
}
|
|
489
|
+
function cleanup(el) {
|
|
490
|
+
const controller = el[ABORT_SYM];
|
|
491
|
+
if (controller) {
|
|
492
|
+
controller.abort();
|
|
493
|
+
delete el[ABORT_SYM];
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
var CACHE_SYM = /* @__PURE__ */ Symbol.for("forma-attr-cache");
|
|
497
|
+
var DYNAMIC_CHILD_SYM = /* @__PURE__ */ Symbol.for("forma-dynamic-child");
|
|
498
|
+
function getCache(el) {
|
|
499
|
+
return el[CACHE_SYM] ?? (el[CACHE_SYM] = /* @__PURE__ */ Object.create(null));
|
|
500
|
+
}
|
|
501
|
+
function handleClass(el, _key, value2) {
|
|
502
|
+
if (typeof value2 === "function") {
|
|
503
|
+
internalEffect(() => {
|
|
504
|
+
const v = value2();
|
|
505
|
+
const cache = getCache(el);
|
|
506
|
+
if (cache["class"] === v) return;
|
|
507
|
+
cache["class"] = v;
|
|
508
|
+
if (el instanceof HTMLElement) {
|
|
509
|
+
el.className = v;
|
|
510
|
+
} else {
|
|
511
|
+
el.setAttribute("class", v);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
} else {
|
|
515
|
+
const cache = getCache(el);
|
|
516
|
+
if (cache["class"] === value2) return;
|
|
517
|
+
cache["class"] = value2;
|
|
518
|
+
if (el instanceof HTMLElement) {
|
|
519
|
+
el.className = value2;
|
|
520
|
+
} else {
|
|
521
|
+
el.setAttribute("class", value2);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function handleStyle(el, _key, value2) {
|
|
526
|
+
if (typeof value2 === "function") {
|
|
527
|
+
let prevKeys = [];
|
|
528
|
+
internalEffect(() => {
|
|
529
|
+
const v = value2();
|
|
530
|
+
if (typeof v === "string") {
|
|
531
|
+
const cache = getCache(el);
|
|
532
|
+
if (cache["style"] === v) return;
|
|
533
|
+
cache["style"] = v;
|
|
534
|
+
prevKeys = [];
|
|
535
|
+
el.style.cssText = v;
|
|
536
|
+
} else if (v && typeof v === "object") {
|
|
537
|
+
const style = el.style;
|
|
538
|
+
const nextKeys = Object.keys(v);
|
|
539
|
+
for (const k of prevKeys) {
|
|
540
|
+
if (!(k in v)) {
|
|
541
|
+
style.removeProperty(k.replace(/[A-Z]/g, (c) => "-" + c.toLowerCase()));
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
Object.assign(style, v);
|
|
545
|
+
prevKeys = nextKeys;
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
} else if (typeof value2 === "string") {
|
|
549
|
+
const cache = getCache(el);
|
|
550
|
+
if (cache["style"] === value2) return;
|
|
551
|
+
cache["style"] = value2;
|
|
552
|
+
el.style.cssText = value2;
|
|
553
|
+
} else if (value2 && typeof value2 === "object") {
|
|
554
|
+
Object.assign(el.style, value2);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
function handleEvent(el, key, value2) {
|
|
558
|
+
const controller = getAbortController(el);
|
|
559
|
+
el.addEventListener(
|
|
560
|
+
eventName(key),
|
|
561
|
+
value2,
|
|
562
|
+
{ signal: controller.signal }
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
function handleInnerHTML(el, _key, value2) {
|
|
566
|
+
const v = value2;
|
|
567
|
+
el.innerHTML = v.__html;
|
|
568
|
+
}
|
|
569
|
+
function handleXLink(el, key, value2) {
|
|
570
|
+
const localName = key.slice(6);
|
|
571
|
+
if (typeof value2 === "function") {
|
|
572
|
+
internalEffect(() => {
|
|
573
|
+
const v = value2();
|
|
574
|
+
if (v == null || v === false) {
|
|
575
|
+
el.removeAttributeNS(XLINK_NS, localName);
|
|
576
|
+
} else {
|
|
577
|
+
el.setAttributeNS(XLINK_NS, key, String(v));
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
} else {
|
|
581
|
+
if (value2 == null || value2 === false) {
|
|
582
|
+
el.removeAttributeNS(XLINK_NS, localName);
|
|
583
|
+
} else {
|
|
584
|
+
el.setAttributeNS(XLINK_NS, key, String(value2));
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
function handleBooleanAttr(el, key, value2) {
|
|
589
|
+
if (typeof value2 === "function") {
|
|
590
|
+
internalEffect(() => {
|
|
591
|
+
const v = value2();
|
|
592
|
+
const cache = getCache(el);
|
|
593
|
+
if (cache[key] === v) return;
|
|
594
|
+
cache[key] = v;
|
|
595
|
+
if (v) {
|
|
596
|
+
el.setAttribute(key, "");
|
|
597
|
+
} else {
|
|
598
|
+
el.removeAttribute(key);
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
} else {
|
|
602
|
+
const cache = getCache(el);
|
|
603
|
+
if (cache[key] === value2) return;
|
|
604
|
+
cache[key] = value2;
|
|
605
|
+
if (value2) {
|
|
606
|
+
el.setAttribute(key, "");
|
|
607
|
+
} else {
|
|
608
|
+
el.removeAttribute(key);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
function handleGenericAttr(el, key, value2) {
|
|
613
|
+
if (typeof value2 === "function") {
|
|
614
|
+
internalEffect(() => {
|
|
615
|
+
const v = value2();
|
|
616
|
+
if (v == null || v === false) {
|
|
617
|
+
const cache = getCache(el);
|
|
618
|
+
if (cache[key] === null) return;
|
|
619
|
+
cache[key] = null;
|
|
620
|
+
el.removeAttribute(key);
|
|
621
|
+
} else {
|
|
622
|
+
const strVal = String(v);
|
|
623
|
+
const cache = getCache(el);
|
|
624
|
+
if (cache[key] === strVal) return;
|
|
625
|
+
cache[key] = strVal;
|
|
626
|
+
el.setAttribute(key, strVal);
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
} else {
|
|
630
|
+
if (value2 == null || value2 === false) {
|
|
631
|
+
const cache = getCache(el);
|
|
632
|
+
if (cache[key] === null) return;
|
|
633
|
+
cache[key] = null;
|
|
634
|
+
el.removeAttribute(key);
|
|
635
|
+
} else {
|
|
636
|
+
const strVal = String(value2);
|
|
637
|
+
const cache = getCache(el);
|
|
638
|
+
if (cache[key] === strVal) return;
|
|
639
|
+
cache[key] = strVal;
|
|
640
|
+
el.setAttribute(key, strVal);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
var PROP_HANDLERS = /* @__PURE__ */ new Map();
|
|
645
|
+
PROP_HANDLERS.set("class", handleClass);
|
|
646
|
+
PROP_HANDLERS.set("className", handleClass);
|
|
647
|
+
PROP_HANDLERS.set("style", handleStyle);
|
|
648
|
+
PROP_HANDLERS.set("ref", () => {
|
|
649
|
+
});
|
|
650
|
+
PROP_HANDLERS.set("dangerouslySetInnerHTML", handleInnerHTML);
|
|
651
|
+
for (const attr of BOOLEAN_ATTRS) {
|
|
652
|
+
PROP_HANDLERS.set(attr, handleBooleanAttr);
|
|
653
|
+
}
|
|
654
|
+
function applyProp(el, key, value2) {
|
|
655
|
+
if (key === "class") {
|
|
656
|
+
handleClass(el, key, value2);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
if (key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key.length > 2) {
|
|
660
|
+
handleEvent(el, key, value2);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
const handler = PROP_HANDLERS.get(key);
|
|
664
|
+
if (handler) {
|
|
665
|
+
handler(el, key, value2);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
if (key.charCodeAt(0) === 120 && key.startsWith("xlink:")) {
|
|
669
|
+
handleXLink(el, key, value2);
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
handleGenericAttr(el, key, value2);
|
|
673
|
+
}
|
|
674
|
+
function applyStaticProp(el, key, value2) {
|
|
675
|
+
if (value2 == null || value2 === false) return;
|
|
676
|
+
if (key === "class" || key === "className") {
|
|
677
|
+
el.className = value2;
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
if (key === "style") {
|
|
681
|
+
if (typeof value2 === "string") {
|
|
682
|
+
el.style.cssText = value2;
|
|
683
|
+
} else if (value2 && typeof value2 === "object") {
|
|
684
|
+
Object.assign(el.style, value2);
|
|
685
|
+
}
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (key === "dangerouslySetInnerHTML") {
|
|
689
|
+
el.innerHTML = value2.__html;
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
if (key.charCodeAt(0) === 120 && key.startsWith("xlink:")) {
|
|
693
|
+
el.setAttributeNS(XLINK_NS, key, String(value2));
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
if (BOOLEAN_ATTRS.has(key)) {
|
|
697
|
+
if (value2) el.setAttribute(key, "");
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
if (value2 === true) {
|
|
701
|
+
el.setAttribute(key, "");
|
|
702
|
+
} else {
|
|
703
|
+
el.setAttribute(key, String(value2));
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
function appendChild(parent, child) {
|
|
707
|
+
if (child instanceof Node) {
|
|
708
|
+
parent.appendChild(child);
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
if (typeof child === "string") {
|
|
712
|
+
parent.appendChild(new Text(child));
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (child == null || child === false || child === true) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
if (typeof child === "number") {
|
|
719
|
+
parent.appendChild(new Text(String(child)));
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
if (typeof child === "function") {
|
|
723
|
+
if (parent instanceof Element) {
|
|
724
|
+
parent[DYNAMIC_CHILD_SYM] = true;
|
|
725
|
+
}
|
|
726
|
+
let currentNode = null;
|
|
727
|
+
internalEffect(() => {
|
|
728
|
+
const v = child();
|
|
729
|
+
if (v instanceof Node) {
|
|
730
|
+
if (currentNode) {
|
|
731
|
+
parent.replaceChild(v, currentNode);
|
|
732
|
+
} else {
|
|
733
|
+
parent.appendChild(v);
|
|
734
|
+
}
|
|
735
|
+
currentNode = v;
|
|
736
|
+
} else {
|
|
737
|
+
const text = typeof v === "symbol" ? String(v) : String(v ?? "");
|
|
738
|
+
if (!currentNode) {
|
|
739
|
+
currentNode = new Text(text);
|
|
740
|
+
parent.appendChild(currentNode);
|
|
741
|
+
} else if (currentNode.nodeType === 3) {
|
|
742
|
+
currentNode.data = text;
|
|
743
|
+
} else {
|
|
744
|
+
const tn = new Text(text);
|
|
745
|
+
parent.replaceChild(tn, currentNode);
|
|
746
|
+
currentNode = tn;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (Array.isArray(child)) {
|
|
753
|
+
for (const item of child) {
|
|
754
|
+
appendChild(parent, item);
|
|
755
|
+
}
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
function h(tag, props, ...children) {
|
|
760
|
+
if (hydrating) {
|
|
761
|
+
return { type: "element", tag, props: props ?? null, children };
|
|
762
|
+
}
|
|
763
|
+
let el;
|
|
764
|
+
if (ELEMENT_PROTOS && ELEMENT_PROTOS[tag]) {
|
|
765
|
+
el = ELEMENT_PROTOS[tag].cloneNode(false);
|
|
766
|
+
} else if (SVG_TAGS.has(tag)) {
|
|
767
|
+
el = document.createElementNS(SVG_NS, tag);
|
|
768
|
+
} else {
|
|
769
|
+
el = getProto(tag).cloneNode(false);
|
|
770
|
+
}
|
|
771
|
+
if (props) {
|
|
772
|
+
let hasDynamic = false;
|
|
773
|
+
for (const key in props) {
|
|
774
|
+
if (key === "ref") continue;
|
|
775
|
+
const value2 = props[key];
|
|
776
|
+
if (key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key.length > 2) {
|
|
777
|
+
handleEvent(el, key, value2);
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
if (typeof value2 === "function") {
|
|
781
|
+
if (!hasDynamic) {
|
|
782
|
+
el[CACHE_SYM] = /* @__PURE__ */ Object.create(null);
|
|
783
|
+
hasDynamic = true;
|
|
784
|
+
}
|
|
785
|
+
applyProp(el, key, value2);
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
applyStaticProp(el, key, value2);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
const childLen = children.length;
|
|
792
|
+
if (childLen === 1) {
|
|
793
|
+
const only = children[0];
|
|
794
|
+
if (typeof only === "string") {
|
|
795
|
+
el.textContent = only;
|
|
796
|
+
} else if (typeof only === "number") {
|
|
797
|
+
el.textContent = String(only);
|
|
798
|
+
} else {
|
|
799
|
+
appendChild(el, only);
|
|
800
|
+
}
|
|
801
|
+
} else if (childLen > 1) {
|
|
802
|
+
for (const child of children) {
|
|
803
|
+
appendChild(el, child);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
if (props && typeof props["ref"] === "function") {
|
|
807
|
+
props["ref"](el);
|
|
808
|
+
}
|
|
809
|
+
return el;
|
|
810
|
+
}
|
|
811
|
+
function fragment(...children) {
|
|
812
|
+
const frag = document.createDocumentFragment();
|
|
813
|
+
for (const child of children) {
|
|
814
|
+
appendChild(frag, child);
|
|
815
|
+
}
|
|
816
|
+
return frag;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// src/dom/show.ts
|
|
820
|
+
function createShow(when, thenFn, elseFn) {
|
|
821
|
+
if (hydrating) {
|
|
822
|
+
const branch = when() ? thenFn() : elseFn?.() ?? null;
|
|
823
|
+
return {
|
|
824
|
+
type: "show",
|
|
825
|
+
condition: when,
|
|
826
|
+
whenTrue: thenFn,
|
|
827
|
+
whenFalse: elseFn,
|
|
828
|
+
initialBranch: branch
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
const startMarker = document.createComment("forma-show");
|
|
832
|
+
const endMarker = document.createComment("/forma-show");
|
|
833
|
+
const fragment2 = document.createDocumentFragment();
|
|
834
|
+
fragment2.appendChild(startMarker);
|
|
835
|
+
fragment2.appendChild(endMarker);
|
|
836
|
+
let currentNode = null;
|
|
837
|
+
let lastTruthy = null;
|
|
838
|
+
let currentDispose = null;
|
|
839
|
+
const DEBUG_LABEL = thenFn.toString().slice(0, 60);
|
|
840
|
+
const showDispose = internalEffect(() => {
|
|
841
|
+
const truthy = !!when();
|
|
842
|
+
const DEBUG = typeof globalThis.__FORMA_DEBUG__ !== "undefined";
|
|
843
|
+
if (truthy === lastTruthy) {
|
|
844
|
+
if (DEBUG) console.log("[forma:show] skip (same)", truthy, DEBUG_LABEL);
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
if (DEBUG) console.log("[forma:show]", lastTruthy, "\u2192", truthy, DEBUG_LABEL);
|
|
848
|
+
lastTruthy = truthy;
|
|
849
|
+
const parent = startMarker.parentNode;
|
|
850
|
+
if (!parent) {
|
|
851
|
+
if (DEBUG) console.warn("[forma:show] parentNode is null! skipping.", DEBUG_LABEL);
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
if (DEBUG) console.log("[forma:show] parent:", parent.nodeName, "inDoc:", document.contains(parent));
|
|
855
|
+
if (currentDispose) {
|
|
856
|
+
currentDispose();
|
|
857
|
+
currentDispose = null;
|
|
858
|
+
}
|
|
859
|
+
if (currentNode) {
|
|
860
|
+
if (currentNode.parentNode === parent) {
|
|
861
|
+
parent.removeChild(currentNode);
|
|
862
|
+
} else {
|
|
863
|
+
while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {
|
|
864
|
+
parent.removeChild(startMarker.nextSibling);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
const branchFn = truthy ? thenFn : elseFn;
|
|
869
|
+
if (branchFn) {
|
|
870
|
+
let branchDispose;
|
|
871
|
+
currentNode = createRoot((dispose) => {
|
|
872
|
+
branchDispose = dispose;
|
|
873
|
+
return untrack(() => branchFn());
|
|
874
|
+
});
|
|
875
|
+
currentDispose = branchDispose;
|
|
876
|
+
} else {
|
|
877
|
+
currentNode = null;
|
|
878
|
+
}
|
|
879
|
+
if (currentNode) {
|
|
880
|
+
parent.insertBefore(currentNode, endMarker);
|
|
881
|
+
}
|
|
882
|
+
});
|
|
883
|
+
fragment2.__showDispose = () => {
|
|
884
|
+
showDispose();
|
|
885
|
+
if (currentDispose) {
|
|
886
|
+
currentDispose();
|
|
887
|
+
currentDispose = null;
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
return fragment2;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// src/dom/hydrate.ts
|
|
894
|
+
var hydrating = false;
|
|
895
|
+
function setHydrating(value2) {
|
|
896
|
+
hydrating = value2;
|
|
897
|
+
}
|
|
898
|
+
function isDescriptor(v) {
|
|
899
|
+
return v != null && typeof v === "object" && v.type === "element";
|
|
900
|
+
}
|
|
901
|
+
function isShowDescriptor(v) {
|
|
902
|
+
return v != null && typeof v === "object" && v.type === "show";
|
|
903
|
+
}
|
|
904
|
+
function isListDescriptor(v) {
|
|
905
|
+
return v != null && typeof v === "object" && v.type === "list";
|
|
906
|
+
}
|
|
907
|
+
function applyDynamicProps(el, props) {
|
|
908
|
+
if (!props) return;
|
|
909
|
+
for (const key in props) {
|
|
910
|
+
const value2 = props[key];
|
|
911
|
+
if (typeof value2 !== "function") continue;
|
|
912
|
+
if (key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key.length > 2) {
|
|
913
|
+
el.addEventListener(key.slice(2).toLowerCase(), value2);
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
const fn = value2;
|
|
917
|
+
const attrKey = key;
|
|
918
|
+
internalEffect(() => {
|
|
919
|
+
const v = fn();
|
|
920
|
+
if (v === false || v == null) {
|
|
921
|
+
el.removeAttribute(attrKey);
|
|
922
|
+
} else if (v === true) {
|
|
923
|
+
el.setAttribute(attrKey, "");
|
|
924
|
+
} else {
|
|
925
|
+
el.setAttribute(attrKey, String(v));
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
function ensureNode(value2) {
|
|
931
|
+
if (value2 instanceof Node) return value2;
|
|
932
|
+
if (value2 == null || value2 === false || value2 === true) return null;
|
|
933
|
+
if (typeof value2 === "string") return new Text(value2);
|
|
934
|
+
if (typeof value2 === "number") return new Text(String(value2));
|
|
935
|
+
if (isDescriptor(value2)) return descriptorToElement(value2);
|
|
936
|
+
if (isShowDescriptor(value2)) {
|
|
937
|
+
const prevH = hydrating;
|
|
938
|
+
hydrating = false;
|
|
939
|
+
try {
|
|
940
|
+
return createShow(
|
|
941
|
+
value2.condition,
|
|
942
|
+
() => ensureNode(value2.whenTrue()) ?? document.createComment("empty"),
|
|
943
|
+
value2.whenFalse ? () => ensureNode(value2.whenFalse()) ?? document.createComment("empty") : void 0
|
|
944
|
+
);
|
|
945
|
+
} finally {
|
|
946
|
+
hydrating = prevH;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
if (isListDescriptor(value2)) {
|
|
950
|
+
const prevH = hydrating;
|
|
951
|
+
hydrating = false;
|
|
952
|
+
try {
|
|
953
|
+
return createList(value2.items, value2.keyFn, value2.renderFn, value2.options);
|
|
954
|
+
} finally {
|
|
955
|
+
hydrating = prevH;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return null;
|
|
959
|
+
}
|
|
960
|
+
function descriptorToElement(desc) {
|
|
961
|
+
const prevHydrating = hydrating;
|
|
962
|
+
hydrating = false;
|
|
963
|
+
try {
|
|
964
|
+
const children = desc.children.map((child) => {
|
|
965
|
+
if (isDescriptor(child)) return descriptorToElement(child);
|
|
966
|
+
if (isShowDescriptor(child)) return ensureNode(child);
|
|
967
|
+
if (isListDescriptor(child)) return ensureNode(child);
|
|
968
|
+
return child;
|
|
969
|
+
});
|
|
970
|
+
return h(desc.tag, desc.props, ...children);
|
|
971
|
+
} finally {
|
|
972
|
+
hydrating = prevHydrating;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
function isIslandStart(data) {
|
|
976
|
+
return data.length >= 4 && data.charCodeAt(0) === 102 && data.charCodeAt(1) === 58 && data.charCodeAt(2) === 105;
|
|
977
|
+
}
|
|
978
|
+
function isShowStart(data) {
|
|
979
|
+
return data.length >= 4 && data.charCodeAt(0) === 102 && data.charCodeAt(1) === 58 && data.charCodeAt(2) === 115;
|
|
980
|
+
}
|
|
981
|
+
function isTextStart(data) {
|
|
982
|
+
return data.length >= 4 && data.charCodeAt(0) === 102 && data.charCodeAt(1) === 58 && data.charCodeAt(2) === 116;
|
|
983
|
+
}
|
|
984
|
+
function isListStart(data) {
|
|
985
|
+
return data.length >= 4 && data.charCodeAt(0) === 102 && data.charCodeAt(1) === 58 && data.charCodeAt(2) === 108;
|
|
986
|
+
}
|
|
987
|
+
function findClosingMarker(start) {
|
|
988
|
+
const closing = "/" + start.data;
|
|
989
|
+
let node = start.nextSibling;
|
|
990
|
+
while (node) {
|
|
991
|
+
if (node.nodeType === 8 && node.data === closing) {
|
|
992
|
+
return node;
|
|
993
|
+
}
|
|
994
|
+
node = node.nextSibling;
|
|
995
|
+
}
|
|
996
|
+
return null;
|
|
997
|
+
}
|
|
998
|
+
function findTextBetween(start, end) {
|
|
999
|
+
let node = start.nextSibling;
|
|
1000
|
+
while (node && node !== end) {
|
|
1001
|
+
if (node.nodeType === 3) return node;
|
|
1002
|
+
node = node.nextSibling;
|
|
1003
|
+
}
|
|
1004
|
+
return null;
|
|
1005
|
+
}
|
|
1006
|
+
function nextElementBetweenMarkers(start, end) {
|
|
1007
|
+
let node = start.nextSibling;
|
|
1008
|
+
while (node && node !== end) {
|
|
1009
|
+
if (node.nodeType === 1) return node;
|
|
1010
|
+
node = node.nextSibling;
|
|
1011
|
+
}
|
|
1012
|
+
return void 0;
|
|
1013
|
+
}
|
|
1014
|
+
function extractContentBetweenMarkers(start, end) {
|
|
1015
|
+
const frag = document.createDocumentFragment();
|
|
1016
|
+
let node = start.nextSibling;
|
|
1017
|
+
while (node && node !== end) {
|
|
1018
|
+
const next = node.nextSibling;
|
|
1019
|
+
frag.appendChild(node);
|
|
1020
|
+
node = next;
|
|
1021
|
+
}
|
|
1022
|
+
return frag;
|
|
1023
|
+
}
|
|
1024
|
+
function setupShowEffect(desc, marker) {
|
|
1025
|
+
let currentCondition = !!desc.condition();
|
|
1026
|
+
let thenFragment = null;
|
|
1027
|
+
let elseFragment = null;
|
|
1028
|
+
const hasSSRContent = marker.start.nextSibling !== marker.end;
|
|
1029
|
+
if (!hasSSRContent && currentCondition) {
|
|
1030
|
+
if (__DEV__) console.warn("[forma] Hydration: show condition mismatch \u2014 SSR empty but client condition is true");
|
|
1031
|
+
const trueBranch = desc.whenTrue();
|
|
1032
|
+
if (trueBranch instanceof Node) {
|
|
1033
|
+
marker.start.parentNode.insertBefore(trueBranch, marker.end);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
internalEffect(() => {
|
|
1037
|
+
const next = !!desc.condition();
|
|
1038
|
+
if (next === currentCondition) return;
|
|
1039
|
+
currentCondition = next;
|
|
1040
|
+
const parent = marker.start.parentNode;
|
|
1041
|
+
if (!parent) return;
|
|
1042
|
+
const current = extractContentBetweenMarkers(marker.start, marker.end);
|
|
1043
|
+
if (!next) {
|
|
1044
|
+
thenFragment = current;
|
|
1045
|
+
} else {
|
|
1046
|
+
elseFragment = current;
|
|
1047
|
+
}
|
|
1048
|
+
let branch = next ? thenFragment ?? desc.whenTrue() : desc.whenFalse ? elseFragment ?? desc.whenFalse() : null;
|
|
1049
|
+
if (next && thenFragment) thenFragment = null;
|
|
1050
|
+
if (!next && elseFragment) elseFragment = null;
|
|
1051
|
+
if (branch != null && !(branch instanceof Node)) {
|
|
1052
|
+
branch = ensureNode(branch);
|
|
1053
|
+
}
|
|
1054
|
+
if (branch instanceof Node) {
|
|
1055
|
+
parent.insertBefore(branch, marker.end);
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
function adoptBranchContent(desc, regionStart, regionEnd) {
|
|
1060
|
+
if (isDescriptor(desc)) {
|
|
1061
|
+
const el = nextElementBetweenMarkers(regionStart, regionEnd);
|
|
1062
|
+
if (el) adoptNode(desc, el);
|
|
1063
|
+
} else if (isShowDescriptor(desc)) {
|
|
1064
|
+
let node = regionStart.nextSibling;
|
|
1065
|
+
while (node && node !== regionEnd) {
|
|
1066
|
+
if (node.nodeType === 8 && isShowStart(node.data)) {
|
|
1067
|
+
const innerStart = node;
|
|
1068
|
+
const innerEnd = findClosingMarker(innerStart);
|
|
1069
|
+
if (innerEnd) {
|
|
1070
|
+
if (desc.initialBranch) {
|
|
1071
|
+
adoptBranchContent(desc.initialBranch, innerStart, innerEnd);
|
|
1072
|
+
}
|
|
1073
|
+
setupShowEffect(desc, { start: innerStart, end: innerEnd});
|
|
1074
|
+
}
|
|
1075
|
+
break;
|
|
1076
|
+
}
|
|
1077
|
+
node = node.nextSibling;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
function adoptNode(desc, ssrEl) {
|
|
1082
|
+
if (!ssrEl || ssrEl.tagName !== desc.tag.toUpperCase()) {
|
|
1083
|
+
console.warn(`Hydration mismatch: expected <${desc.tag}>, got <${ssrEl?.tagName?.toLowerCase() ?? "nothing"}>`);
|
|
1084
|
+
const fresh = descriptorToElement(desc);
|
|
1085
|
+
if (ssrEl) ssrEl.replaceWith(fresh);
|
|
1086
|
+
return;
|
|
1087
|
+
}
|
|
1088
|
+
applyDynamicProps(ssrEl, desc.props);
|
|
1089
|
+
let cursor = ssrEl.firstChild;
|
|
1090
|
+
for (const child of desc.children) {
|
|
1091
|
+
if (child === false || child == null) continue;
|
|
1092
|
+
if (isDescriptor(child)) {
|
|
1093
|
+
while (cursor && cursor.nodeType === 3 && !cursor.data.trim()) {
|
|
1094
|
+
cursor = cursor.nextSibling;
|
|
1095
|
+
}
|
|
1096
|
+
while (cursor && cursor.nodeType === 1 && cursor.hasAttribute("data-forma-island")) {
|
|
1097
|
+
cursor = cursor.nextSibling;
|
|
1098
|
+
}
|
|
1099
|
+
if (!cursor) {
|
|
1100
|
+
ssrEl.appendChild(descriptorToElement(child));
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
if (cursor.nodeType === 1) {
|
|
1104
|
+
const el = cursor;
|
|
1105
|
+
cursor = cursor.nextSibling;
|
|
1106
|
+
adoptNode(child, el);
|
|
1107
|
+
} else if (cursor.nodeType === 8 && isIslandStart(cursor.data)) {
|
|
1108
|
+
const end = findClosingMarker(cursor);
|
|
1109
|
+
const fresh = descriptorToElement(child);
|
|
1110
|
+
if (end) {
|
|
1111
|
+
end.parentNode.insertBefore(fresh, end);
|
|
1112
|
+
cursor = end.nextSibling;
|
|
1113
|
+
} else {
|
|
1114
|
+
ssrEl.appendChild(fresh);
|
|
1115
|
+
cursor = null;
|
|
1116
|
+
}
|
|
1117
|
+
} else {
|
|
1118
|
+
ssrEl.appendChild(descriptorToElement(child));
|
|
1119
|
+
}
|
|
1120
|
+
} else if (isShowDescriptor(child)) {
|
|
1121
|
+
while (cursor && !(cursor.nodeType === 8 && isShowStart(cursor.data))) {
|
|
1122
|
+
cursor = cursor.nextSibling;
|
|
1123
|
+
}
|
|
1124
|
+
if (cursor) {
|
|
1125
|
+
const start = cursor;
|
|
1126
|
+
const end = findClosingMarker(start);
|
|
1127
|
+
if (end) {
|
|
1128
|
+
if (child.initialBranch) {
|
|
1129
|
+
adoptBranchContent(child.initialBranch, start, end);
|
|
1130
|
+
}
|
|
1131
|
+
setupShowEffect(child, { start, end});
|
|
1132
|
+
cursor = end.nextSibling;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
} else if (isListDescriptor(child)) {
|
|
1136
|
+
while (cursor && !(cursor.nodeType === 8 && isListStart(cursor.data))) {
|
|
1137
|
+
cursor = cursor.nextSibling;
|
|
1138
|
+
}
|
|
1139
|
+
if (cursor) {
|
|
1140
|
+
const start = cursor;
|
|
1141
|
+
const end = findClosingMarker(start);
|
|
1142
|
+
if (end) {
|
|
1143
|
+
const ssrKeyMap = /* @__PURE__ */ new Map();
|
|
1144
|
+
const ssrElements = [];
|
|
1145
|
+
let node = start.nextSibling;
|
|
1146
|
+
while (node && node !== end) {
|
|
1147
|
+
if (node.nodeType === 1) {
|
|
1148
|
+
const el = node;
|
|
1149
|
+
ssrElements.push(el);
|
|
1150
|
+
const key = el.getAttribute("data-forma-key");
|
|
1151
|
+
if (key != null) {
|
|
1152
|
+
ssrKeyMap.set(key, el);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
node = node.nextSibling;
|
|
1156
|
+
}
|
|
1157
|
+
const currentItems = untrack(() => child.items());
|
|
1158
|
+
const listKeyFn = child.keyFn;
|
|
1159
|
+
const listRenderFn = child.renderFn;
|
|
1160
|
+
const useIndexFallback = ssrKeyMap.size === 0 && ssrElements.length > 0;
|
|
1161
|
+
const adoptedNodes = [];
|
|
1162
|
+
const adoptedItems = [];
|
|
1163
|
+
const usedIndices = /* @__PURE__ */ new Set();
|
|
1164
|
+
for (let i = 0; i < currentItems.length; i++) {
|
|
1165
|
+
const item = currentItems[i];
|
|
1166
|
+
const key = listKeyFn(item);
|
|
1167
|
+
let ssrNode;
|
|
1168
|
+
if (useIndexFallback) {
|
|
1169
|
+
if (i < ssrElements.length) {
|
|
1170
|
+
ssrNode = ssrElements[i];
|
|
1171
|
+
usedIndices.add(i);
|
|
1172
|
+
}
|
|
1173
|
+
} else {
|
|
1174
|
+
ssrNode = ssrKeyMap.get(String(key));
|
|
1175
|
+
if (ssrNode) ssrKeyMap.delete(String(key));
|
|
1176
|
+
}
|
|
1177
|
+
if (ssrNode) {
|
|
1178
|
+
adoptedNodes.push(ssrNode);
|
|
1179
|
+
adoptedItems.push(item);
|
|
1180
|
+
} else {
|
|
1181
|
+
if (__DEV__) console.warn(`[FormaJS] Hydration: list item key "${key}" not found in SSR \u2014 rendering fresh`);
|
|
1182
|
+
const prevHydrating = hydrating;
|
|
1183
|
+
hydrating = false;
|
|
1184
|
+
try {
|
|
1185
|
+
const [getIndex] = chunkFPSLC62A_cjs.createSignal(i);
|
|
1186
|
+
const fresh = listRenderFn(item, getIndex);
|
|
1187
|
+
end.parentNode.insertBefore(fresh, end);
|
|
1188
|
+
adoptedNodes.push(fresh);
|
|
1189
|
+
adoptedItems.push(item);
|
|
1190
|
+
} finally {
|
|
1191
|
+
hydrating = prevHydrating;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
if (useIndexFallback) {
|
|
1196
|
+
for (let i = 0; i < ssrElements.length; i++) {
|
|
1197
|
+
if (!usedIndices.has(i) && ssrElements[i].parentNode) {
|
|
1198
|
+
ssrElements[i].parentNode.removeChild(ssrElements[i]);
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
} else {
|
|
1202
|
+
for (const [unusedKey, unusedNode] of ssrKeyMap) {
|
|
1203
|
+
if (__DEV__) console.warn(`[FormaJS] Hydration: removing extra SSR list item with key "${unusedKey}"`);
|
|
1204
|
+
if (unusedNode.parentNode) {
|
|
1205
|
+
unusedNode.parentNode.removeChild(unusedNode);
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
const parent = start.parentNode;
|
|
1210
|
+
for (const adoptedNode of adoptedNodes) {
|
|
1211
|
+
parent.insertBefore(adoptedNode, end);
|
|
1212
|
+
}
|
|
1213
|
+
let cache = /* @__PURE__ */ new Map();
|
|
1214
|
+
for (let i = 0; i < adoptedItems.length; i++) {
|
|
1215
|
+
const item = adoptedItems[i];
|
|
1216
|
+
const key = listKeyFn(item);
|
|
1217
|
+
const [getIndex, setIndex] = chunkFPSLC62A_cjs.createSignal(i);
|
|
1218
|
+
cache.set(key, {
|
|
1219
|
+
element: adoptedNodes[i],
|
|
1220
|
+
item,
|
|
1221
|
+
getIndex,
|
|
1222
|
+
setIndex
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
let reconcileNodes = adoptedNodes.slice();
|
|
1226
|
+
let reconcileItems = adoptedItems.slice();
|
|
1227
|
+
internalEffect(() => {
|
|
1228
|
+
const newItems = child.items();
|
|
1229
|
+
const parent2 = start.parentNode;
|
|
1230
|
+
if (!parent2) return;
|
|
1231
|
+
const result = reconcileList(
|
|
1232
|
+
parent2,
|
|
1233
|
+
reconcileItems,
|
|
1234
|
+
newItems,
|
|
1235
|
+
reconcileNodes,
|
|
1236
|
+
listKeyFn,
|
|
1237
|
+
(item) => {
|
|
1238
|
+
const prevHydrating = hydrating;
|
|
1239
|
+
hydrating = false;
|
|
1240
|
+
try {
|
|
1241
|
+
const key = listKeyFn(item);
|
|
1242
|
+
const [getIndex, setIndex] = chunkFPSLC62A_cjs.createSignal(0);
|
|
1243
|
+
const element = untrack(() => listRenderFn(item, getIndex));
|
|
1244
|
+
cache.set(key, { element, item, getIndex, setIndex });
|
|
1245
|
+
return element;
|
|
1246
|
+
} finally {
|
|
1247
|
+
hydrating = prevHydrating;
|
|
1248
|
+
}
|
|
1249
|
+
},
|
|
1250
|
+
(_node, item) => {
|
|
1251
|
+
const key = listKeyFn(item);
|
|
1252
|
+
const cached = cache.get(key);
|
|
1253
|
+
if (cached) cached.item = item;
|
|
1254
|
+
},
|
|
1255
|
+
end
|
|
1256
|
+
);
|
|
1257
|
+
const newCache = /* @__PURE__ */ new Map();
|
|
1258
|
+
for (let i = 0; i < newItems.length; i++) {
|
|
1259
|
+
const key = listKeyFn(newItems[i]);
|
|
1260
|
+
const cached = cache.get(key);
|
|
1261
|
+
if (cached) {
|
|
1262
|
+
cached.setIndex(i);
|
|
1263
|
+
newCache.set(key, cached);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
cache = newCache;
|
|
1267
|
+
reconcileNodes = result.nodes;
|
|
1268
|
+
reconcileItems = result.items;
|
|
1269
|
+
});
|
|
1270
|
+
cursor = end.nextSibling;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
} else if (typeof child === "function") {
|
|
1274
|
+
while (cursor && cursor.nodeType === 3 && !cursor.data.trim()) {
|
|
1275
|
+
cursor = cursor.nextSibling;
|
|
1276
|
+
}
|
|
1277
|
+
if (cursor && cursor.nodeType === 1) {
|
|
1278
|
+
const initial = child();
|
|
1279
|
+
if (isDescriptor(initial)) {
|
|
1280
|
+
const el = cursor;
|
|
1281
|
+
cursor = cursor.nextSibling;
|
|
1282
|
+
adoptNode(initial, el);
|
|
1283
|
+
continue;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
if (cursor && cursor.nodeType === 8) {
|
|
1287
|
+
const data = cursor.data;
|
|
1288
|
+
if (isTextStart(data)) {
|
|
1289
|
+
const endMarker = findClosingMarker(cursor);
|
|
1290
|
+
let textNode = cursor.nextSibling;
|
|
1291
|
+
if (!textNode || textNode.nodeType !== 3) {
|
|
1292
|
+
if (__DEV__) console.warn(`[FormaJS] Hydration: created text node for marker ${data} \u2014 SSR walker should emit content between markers`);
|
|
1293
|
+
const created = document.createTextNode("");
|
|
1294
|
+
cursor.parentNode.insertBefore(created, endMarker || cursor.nextSibling);
|
|
1295
|
+
textNode = created;
|
|
1296
|
+
}
|
|
1297
|
+
internalEffect(() => {
|
|
1298
|
+
textNode.data = String(child());
|
|
1299
|
+
});
|
|
1300
|
+
cursor = endMarker ? endMarker.nextSibling : textNode.nextSibling;
|
|
1301
|
+
} else if (isShowStart(data)) {
|
|
1302
|
+
const start = cursor;
|
|
1303
|
+
const end = findClosingMarker(start);
|
|
1304
|
+
if (end) {
|
|
1305
|
+
let textNode = findTextBetween(start, end);
|
|
1306
|
+
if (!textNode) {
|
|
1307
|
+
if (__DEV__) console.warn(`[FormaJS] Hydration: created text node for show marker ${start.data} \u2014 SSR walker should emit content between markers`);
|
|
1308
|
+
textNode = document.createTextNode("");
|
|
1309
|
+
start.parentNode.insertBefore(textNode, end);
|
|
1310
|
+
}
|
|
1311
|
+
internalEffect(() => {
|
|
1312
|
+
textNode.data = String(child());
|
|
1313
|
+
});
|
|
1314
|
+
cursor = end.nextSibling;
|
|
1315
|
+
} else {
|
|
1316
|
+
cursor = cursor.nextSibling;
|
|
1317
|
+
}
|
|
1318
|
+
} else {
|
|
1319
|
+
cursor = cursor.nextSibling;
|
|
1320
|
+
}
|
|
1321
|
+
} else if (cursor && cursor.nodeType === 3) {
|
|
1322
|
+
const textNode = cursor;
|
|
1323
|
+
cursor = cursor.nextSibling;
|
|
1324
|
+
internalEffect(() => {
|
|
1325
|
+
textNode.data = String(child());
|
|
1326
|
+
});
|
|
1327
|
+
} else {
|
|
1328
|
+
if (__DEV__) console.warn(`[FormaJS] Hydration: created text node in empty <${ssrEl.tagName.toLowerCase()}> \u2014 IR may not cover this component`);
|
|
1329
|
+
const textNode = document.createTextNode("");
|
|
1330
|
+
ssrEl.appendChild(textNode);
|
|
1331
|
+
internalEffect(() => {
|
|
1332
|
+
textNode.data = String(child());
|
|
1333
|
+
});
|
|
1334
|
+
}
|
|
1335
|
+
} else if (typeof child === "string" || typeof child === "number") {
|
|
1336
|
+
if (cursor && cursor.nodeType === 3) {
|
|
1337
|
+
cursor = cursor.nextSibling;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
function hydrateIsland(component, target) {
|
|
1343
|
+
const hasSSRContent = target.childElementCount > 0 || target.childNodes.length > 0 && Array.from(target.childNodes).some((n) => n.nodeType === 1 || n.nodeType === 3 && n.data.trim());
|
|
1344
|
+
if (!hasSSRContent) {
|
|
1345
|
+
if (__DEV__) {
|
|
1346
|
+
const name = target.getAttribute("data-forma-component") || "unknown";
|
|
1347
|
+
console.warn(
|
|
1348
|
+
`[forma] Island "${name}" has no SSR content \u2014 falling back to CSR. This means the IR walker did not render content between ISLAND_START and ISLAND_END.`
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
const result = component();
|
|
1352
|
+
if (result instanceof Element) {
|
|
1353
|
+
for (const attr of Array.from(target.attributes)) {
|
|
1354
|
+
if (attr.name.startsWith("data-forma-")) {
|
|
1355
|
+
result.setAttribute(attr.name, attr.value);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
target.replaceWith(result);
|
|
1359
|
+
return result;
|
|
1360
|
+
} else if (result instanceof Node) {
|
|
1361
|
+
target.appendChild(result);
|
|
1362
|
+
}
|
|
1363
|
+
return target;
|
|
1364
|
+
}
|
|
1365
|
+
setHydrating(true);
|
|
1366
|
+
let descriptor;
|
|
1367
|
+
try {
|
|
1368
|
+
descriptor = component();
|
|
1369
|
+
} finally {
|
|
1370
|
+
setHydrating(false);
|
|
1371
|
+
}
|
|
1372
|
+
if (!descriptor || !isDescriptor(descriptor)) {
|
|
1373
|
+
target.removeAttribute("data-forma-ssr");
|
|
1374
|
+
return target;
|
|
1375
|
+
}
|
|
1376
|
+
if (target.hasAttribute("data-forma-island")) {
|
|
1377
|
+
adoptNode(descriptor, target);
|
|
1378
|
+
} else {
|
|
1379
|
+
adoptNode(descriptor, target.children[0]);
|
|
1380
|
+
}
|
|
1381
|
+
target.removeAttribute("data-forma-ssr");
|
|
1382
|
+
return target;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
// src/dom/list.ts
|
|
1386
|
+
function longestIncreasingSubsequence(arr) {
|
|
1387
|
+
const n = arr.length;
|
|
1388
|
+
if (n === 0) return [];
|
|
1389
|
+
const tails = new Int32Array(n);
|
|
1390
|
+
const tailIndices = new Int32Array(n);
|
|
1391
|
+
const predecessor = new Int32Array(n).fill(-1);
|
|
1392
|
+
let tailsLen = 0;
|
|
1393
|
+
for (let i = 0; i < n; i++) {
|
|
1394
|
+
const val = arr[i];
|
|
1395
|
+
let lo = 0, hi = tailsLen;
|
|
1396
|
+
while (lo < hi) {
|
|
1397
|
+
const mid = lo + hi >> 1;
|
|
1398
|
+
if (tails[mid] < val) lo = mid + 1;
|
|
1399
|
+
else hi = mid;
|
|
1400
|
+
}
|
|
1401
|
+
tails[lo] = val;
|
|
1402
|
+
tailIndices[lo] = i;
|
|
1403
|
+
if (lo > 0) predecessor[i] = tailIndices[lo - 1];
|
|
1404
|
+
if (lo >= tailsLen) tailsLen++;
|
|
1405
|
+
}
|
|
1406
|
+
const result = new Array(tailsLen);
|
|
1407
|
+
let idx = tailIndices[tailsLen - 1];
|
|
1408
|
+
for (let i = tailsLen - 1; i >= 0; i--) {
|
|
1409
|
+
result[i] = idx;
|
|
1410
|
+
idx = predecessor[idx];
|
|
1411
|
+
}
|
|
1412
|
+
return result;
|
|
1413
|
+
}
|
|
1414
|
+
var SMALL_LIST_THRESHOLD = 32;
|
|
1415
|
+
var ABORT_SYM2 = /* @__PURE__ */ Symbol.for("forma-abort");
|
|
1416
|
+
var CACHE_SYM2 = /* @__PURE__ */ Symbol.for("forma-attr-cache");
|
|
1417
|
+
var DYNAMIC_CHILD_SYM2 = /* @__PURE__ */ Symbol.for("forma-dynamic-child");
|
|
1418
|
+
function canPatchStaticElement(target, source) {
|
|
1419
|
+
return target instanceof HTMLElement && source instanceof HTMLElement && target.tagName === source.tagName && !target[ABORT_SYM2] && !target[CACHE_SYM2] && !target[DYNAMIC_CHILD_SYM2] && !source[ABORT_SYM2] && !source[CACHE_SYM2] && !source[DYNAMIC_CHILD_SYM2];
|
|
1420
|
+
}
|
|
1421
|
+
function patchStaticElement(target, source) {
|
|
1422
|
+
const sourceAttrNames = /* @__PURE__ */ new Set();
|
|
1423
|
+
for (const attr of Array.from(source.attributes)) {
|
|
1424
|
+
sourceAttrNames.add(attr.name);
|
|
1425
|
+
if (target.getAttribute(attr.name) !== attr.value) {
|
|
1426
|
+
target.setAttribute(attr.name, attr.value);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
for (const attr of Array.from(target.attributes)) {
|
|
1430
|
+
if (!sourceAttrNames.has(attr.name)) {
|
|
1431
|
+
target.removeAttribute(attr.name);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
target.replaceChildren(...Array.from(source.childNodes));
|
|
1435
|
+
}
|
|
1436
|
+
function reconcileSmall(parent, oldItems, newItems, oldNodes, keyFn, createFn, updateFn, beforeNode, hooks) {
|
|
1437
|
+
const oldLen = oldItems.length;
|
|
1438
|
+
const newLen = newItems.length;
|
|
1439
|
+
const oldKeys = new Array(oldLen);
|
|
1440
|
+
for (let i = 0; i < oldLen; i++) {
|
|
1441
|
+
oldKeys[i] = keyFn(oldItems[i]);
|
|
1442
|
+
}
|
|
1443
|
+
const oldIndices = new Array(newLen);
|
|
1444
|
+
const oldUsed = new Uint8Array(oldLen);
|
|
1445
|
+
for (let i = 0; i < newLen; i++) {
|
|
1446
|
+
const key = keyFn(newItems[i]);
|
|
1447
|
+
let found = -1;
|
|
1448
|
+
for (let j = 0; j < oldLen; j++) {
|
|
1449
|
+
if (!oldUsed[j] && oldKeys[j] === key) {
|
|
1450
|
+
found = j;
|
|
1451
|
+
oldUsed[j] = 1;
|
|
1452
|
+
break;
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
oldIndices[i] = found;
|
|
1456
|
+
}
|
|
1457
|
+
for (let i = 0; i < oldLen; i++) {
|
|
1458
|
+
if (!oldUsed[i]) {
|
|
1459
|
+
if (hooks?.onBeforeRemove) {
|
|
1460
|
+
const node = oldNodes[i];
|
|
1461
|
+
hooks.onBeforeRemove(node, () => {
|
|
1462
|
+
if (node.parentNode) node.parentNode.removeChild(node);
|
|
1463
|
+
});
|
|
1464
|
+
} else {
|
|
1465
|
+
parent.removeChild(oldNodes[i]);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
if (oldLen === newLen) {
|
|
1470
|
+
let allSameOrder = true;
|
|
1471
|
+
for (let i = 0; i < newLen; i++) {
|
|
1472
|
+
if (oldIndices[i] !== i) {
|
|
1473
|
+
allSameOrder = false;
|
|
1474
|
+
break;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
if (allSameOrder) {
|
|
1478
|
+
const nodes = new Array(newLen);
|
|
1479
|
+
for (let i = 0; i < newLen; i++) {
|
|
1480
|
+
const node = oldNodes[i];
|
|
1481
|
+
updateFn(node, newItems[i]);
|
|
1482
|
+
nodes[i] = node;
|
|
1483
|
+
}
|
|
1484
|
+
return { nodes, items: newItems };
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
const reusedIndices = [];
|
|
1488
|
+
const reusedPositions = [];
|
|
1489
|
+
for (let i = 0; i < newLen; i++) {
|
|
1490
|
+
if (oldIndices[i] !== -1) {
|
|
1491
|
+
reusedIndices.push(oldIndices[i]);
|
|
1492
|
+
reusedPositions.push(i);
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
const lisOfReused = longestIncreasingSubsequence(reusedIndices);
|
|
1496
|
+
const lisFlags = new Uint8Array(newLen);
|
|
1497
|
+
for (const li of lisOfReused) {
|
|
1498
|
+
lisFlags[reusedPositions[li]] = 1;
|
|
1499
|
+
}
|
|
1500
|
+
const newNodes = new Array(newLen);
|
|
1501
|
+
let nextSibling = beforeNode ?? null;
|
|
1502
|
+
for (let i = newLen - 1; i >= 0; i--) {
|
|
1503
|
+
let node;
|
|
1504
|
+
let isNew = false;
|
|
1505
|
+
if (oldIndices[i] === -1) {
|
|
1506
|
+
node = createFn(newItems[i]);
|
|
1507
|
+
isNew = true;
|
|
1508
|
+
} else {
|
|
1509
|
+
node = oldNodes[oldIndices[i]];
|
|
1510
|
+
updateFn(node, newItems[i]);
|
|
1511
|
+
if (lisFlags[i]) {
|
|
1512
|
+
newNodes[i] = node;
|
|
1513
|
+
nextSibling = node;
|
|
1514
|
+
continue;
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
if (nextSibling) {
|
|
1518
|
+
parent.insertBefore(node, nextSibling);
|
|
1519
|
+
} else {
|
|
1520
|
+
parent.appendChild(node);
|
|
1521
|
+
}
|
|
1522
|
+
if (isNew) hooks?.onInsert?.(node);
|
|
1523
|
+
newNodes[i] = node;
|
|
1524
|
+
nextSibling = node;
|
|
1525
|
+
}
|
|
1526
|
+
return { nodes: newNodes, items: newItems };
|
|
1527
|
+
}
|
|
1528
|
+
function reconcileList(parent, oldItems, newItems, oldNodes, keyFn, createFn, updateFn, beforeNode, hooks) {
|
|
1529
|
+
const oldLen = oldItems.length;
|
|
1530
|
+
const newLen = newItems.length;
|
|
1531
|
+
if (newLen === 0) {
|
|
1532
|
+
for (let i = 0; i < oldLen; i++) {
|
|
1533
|
+
if (hooks?.onBeforeRemove) {
|
|
1534
|
+
const node = oldNodes[i];
|
|
1535
|
+
hooks.onBeforeRemove(node, () => {
|
|
1536
|
+
if (node.parentNode) node.parentNode.removeChild(node);
|
|
1537
|
+
});
|
|
1538
|
+
} else {
|
|
1539
|
+
parent.removeChild(oldNodes[i]);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
return { nodes: [], items: [] };
|
|
1543
|
+
}
|
|
1544
|
+
if (oldLen === 0) {
|
|
1545
|
+
const nodes = new Array(newLen);
|
|
1546
|
+
for (let i = 0; i < newLen; i++) {
|
|
1547
|
+
const node = createFn(newItems[i]);
|
|
1548
|
+
if (beforeNode) {
|
|
1549
|
+
parent.insertBefore(node, beforeNode);
|
|
1550
|
+
} else {
|
|
1551
|
+
parent.appendChild(node);
|
|
1552
|
+
}
|
|
1553
|
+
hooks?.onInsert?.(node);
|
|
1554
|
+
nodes[i] = node;
|
|
1555
|
+
}
|
|
1556
|
+
return { nodes, items: newItems };
|
|
1557
|
+
}
|
|
1558
|
+
if (oldLen < SMALL_LIST_THRESHOLD) {
|
|
1559
|
+
return reconcileSmall(parent, oldItems, newItems, oldNodes, keyFn, createFn, updateFn, beforeNode, hooks);
|
|
1560
|
+
}
|
|
1561
|
+
const oldKeyMap = /* @__PURE__ */ new Map();
|
|
1562
|
+
for (let i = 0; i < oldLen; i++) {
|
|
1563
|
+
oldKeyMap.set(keyFn(oldItems[i]), i);
|
|
1564
|
+
}
|
|
1565
|
+
const oldIndices = new Array(newLen);
|
|
1566
|
+
const oldUsed = new Uint8Array(oldLen);
|
|
1567
|
+
for (let i = 0; i < newLen; i++) {
|
|
1568
|
+
const key = keyFn(newItems[i]);
|
|
1569
|
+
const oldIdx = oldKeyMap.get(key);
|
|
1570
|
+
if (oldIdx !== void 0) {
|
|
1571
|
+
oldIndices[i] = oldIdx;
|
|
1572
|
+
oldUsed[oldIdx] = 1;
|
|
1573
|
+
} else {
|
|
1574
|
+
oldIndices[i] = -1;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
for (let i = 0; i < oldLen; i++) {
|
|
1578
|
+
if (!oldUsed[i]) {
|
|
1579
|
+
if (hooks?.onBeforeRemove) {
|
|
1580
|
+
const node = oldNodes[i];
|
|
1581
|
+
hooks.onBeforeRemove(node, () => {
|
|
1582
|
+
if (node.parentNode) node.parentNode.removeChild(node);
|
|
1583
|
+
});
|
|
1584
|
+
} else {
|
|
1585
|
+
parent.removeChild(oldNodes[i]);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
if (oldLen === newLen) {
|
|
1590
|
+
let allSameOrder = true;
|
|
1591
|
+
for (let i = 0; i < newLen; i++) {
|
|
1592
|
+
if (oldIndices[i] !== i) {
|
|
1593
|
+
allSameOrder = false;
|
|
1594
|
+
break;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
if (allSameOrder) {
|
|
1598
|
+
const nodes = new Array(newLen);
|
|
1599
|
+
for (let i = 0; i < newLen; i++) {
|
|
1600
|
+
const node = oldNodes[i];
|
|
1601
|
+
updateFn(node, newItems[i]);
|
|
1602
|
+
nodes[i] = node;
|
|
1603
|
+
}
|
|
1604
|
+
return { nodes, items: newItems };
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
const reusedIndices = [];
|
|
1608
|
+
const reusedPositions = [];
|
|
1609
|
+
for (let i = 0; i < newLen; i++) {
|
|
1610
|
+
if (oldIndices[i] !== -1) {
|
|
1611
|
+
reusedIndices.push(oldIndices[i]);
|
|
1612
|
+
reusedPositions.push(i);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
const lisOfReused = longestIncreasingSubsequence(reusedIndices);
|
|
1616
|
+
const lisFlags = new Uint8Array(newLen);
|
|
1617
|
+
for (const li of lisOfReused) {
|
|
1618
|
+
lisFlags[reusedPositions[li]] = 1;
|
|
1619
|
+
}
|
|
1620
|
+
const newNodes = new Array(newLen);
|
|
1621
|
+
let nextSibling = beforeNode ?? null;
|
|
1622
|
+
for (let i = newLen - 1; i >= 0; i--) {
|
|
1623
|
+
let node;
|
|
1624
|
+
let isNew = false;
|
|
1625
|
+
if (oldIndices[i] === -1) {
|
|
1626
|
+
node = createFn(newItems[i]);
|
|
1627
|
+
isNew = true;
|
|
1628
|
+
} else {
|
|
1629
|
+
node = oldNodes[oldIndices[i]];
|
|
1630
|
+
updateFn(node, newItems[i]);
|
|
1631
|
+
if (lisFlags[i]) {
|
|
1632
|
+
newNodes[i] = node;
|
|
1633
|
+
nextSibling = node;
|
|
1634
|
+
continue;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
if (nextSibling) {
|
|
1638
|
+
parent.insertBefore(node, nextSibling);
|
|
1639
|
+
} else {
|
|
1640
|
+
parent.appendChild(node);
|
|
1641
|
+
}
|
|
1642
|
+
if (isNew) hooks?.onInsert?.(node);
|
|
1643
|
+
newNodes[i] = node;
|
|
1644
|
+
nextSibling = node;
|
|
1645
|
+
}
|
|
1646
|
+
return { nodes: newNodes, items: newItems };
|
|
1647
|
+
}
|
|
1648
|
+
function createList(items, keyFn, renderFn, options) {
|
|
1649
|
+
if (hydrating) {
|
|
1650
|
+
return { type: "list", items, keyFn, renderFn, options };
|
|
1651
|
+
}
|
|
1652
|
+
const startMarker = document.createComment("forma-list-start");
|
|
1653
|
+
const endMarker = document.createComment("forma-list-end");
|
|
1654
|
+
const fragment2 = document.createDocumentFragment();
|
|
1655
|
+
fragment2.appendChild(startMarker);
|
|
1656
|
+
fragment2.appendChild(endMarker);
|
|
1657
|
+
let cache = /* @__PURE__ */ new Map();
|
|
1658
|
+
let currentNodes = [];
|
|
1659
|
+
let currentItems = [];
|
|
1660
|
+
const updateOnItemChange = options?.updateOnItemChange ?? "none";
|
|
1661
|
+
internalEffect(() => {
|
|
1662
|
+
const newItems = items();
|
|
1663
|
+
const parent = startMarker.parentNode;
|
|
1664
|
+
if (!parent) {
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
if (!Array.isArray(newItems)) {
|
|
1668
|
+
if (__DEV__) {
|
|
1669
|
+
console.warn("[forma] createList: value is not an array, treating as empty");
|
|
1670
|
+
}
|
|
1671
|
+
for (const node of currentNodes) {
|
|
1672
|
+
if (node.parentNode === parent) parent.removeChild(node);
|
|
1673
|
+
}
|
|
1674
|
+
cache = /* @__PURE__ */ new Map();
|
|
1675
|
+
currentNodes = [];
|
|
1676
|
+
currentItems = [];
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1679
|
+
let cleanItems = newItems;
|
|
1680
|
+
for (let i = 0; i < newItems.length; i++) {
|
|
1681
|
+
if (newItems[i] == null) {
|
|
1682
|
+
cleanItems = newItems.filter((item) => item != null);
|
|
1683
|
+
break;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
if (__DEV__) {
|
|
1687
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1688
|
+
for (const item of cleanItems) {
|
|
1689
|
+
const key = keyFn(item);
|
|
1690
|
+
if (seen.has(key)) {
|
|
1691
|
+
console.warn("[forma] createList: duplicate key detected:", key);
|
|
1692
|
+
}
|
|
1693
|
+
seen.add(key);
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
const updateRow = updateOnItemChange === "rerender" ? (node, item) => {
|
|
1697
|
+
const key = keyFn(item);
|
|
1698
|
+
const cached = cache.get(key);
|
|
1699
|
+
if (!cached) return;
|
|
1700
|
+
if (cached.item === item) return;
|
|
1701
|
+
cached.item = item;
|
|
1702
|
+
if (!(node instanceof HTMLElement)) return;
|
|
1703
|
+
if (node[ABORT_SYM2] || node[CACHE_SYM2] || node[DYNAMIC_CHILD_SYM2]) {
|
|
1704
|
+
return;
|
|
1705
|
+
}
|
|
1706
|
+
const next = untrack(() => renderFn(item, cached.getIndex));
|
|
1707
|
+
if (canPatchStaticElement(node, next)) {
|
|
1708
|
+
patchStaticElement(node, next);
|
|
1709
|
+
cached.element = node;
|
|
1710
|
+
}
|
|
1711
|
+
} : (_node, item) => {
|
|
1712
|
+
const key = keyFn(item);
|
|
1713
|
+
const cached = cache.get(key);
|
|
1714
|
+
if (cached) cached.item = item;
|
|
1715
|
+
};
|
|
1716
|
+
const result = reconcileList(
|
|
1717
|
+
parent,
|
|
1718
|
+
currentItems,
|
|
1719
|
+
cleanItems,
|
|
1720
|
+
currentNodes,
|
|
1721
|
+
keyFn,
|
|
1722
|
+
// createFn: create element + cache entry
|
|
1723
|
+
(item) => {
|
|
1724
|
+
const key = keyFn(item);
|
|
1725
|
+
const [getIndex, setIndex] = chunkFPSLC62A_cjs.createSignal(0);
|
|
1726
|
+
const element = untrack(() => renderFn(item, getIndex));
|
|
1727
|
+
cache.set(key, { element, item, getIndex, setIndex });
|
|
1728
|
+
return element;
|
|
1729
|
+
},
|
|
1730
|
+
updateRow,
|
|
1731
|
+
// beforeNode: insert items before the end marker
|
|
1732
|
+
endMarker
|
|
1733
|
+
);
|
|
1734
|
+
const newCache = /* @__PURE__ */ new Map();
|
|
1735
|
+
for (let i = 0; i < cleanItems.length; i++) {
|
|
1736
|
+
const key = keyFn(cleanItems[i]);
|
|
1737
|
+
const cached = cache.get(key);
|
|
1738
|
+
if (cached) {
|
|
1739
|
+
cached.setIndex(i);
|
|
1740
|
+
newCache.set(key, cached);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
cache = newCache;
|
|
1744
|
+
currentNodes = result.nodes;
|
|
1745
|
+
currentItems = result.items;
|
|
1746
|
+
});
|
|
1747
|
+
return fragment2;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
exports.batch = batch;
|
|
1751
|
+
exports.cleanup = cleanup;
|
|
1752
|
+
exports.createEffect = createEffect;
|
|
1753
|
+
exports.createList = createList;
|
|
1754
|
+
exports.createMemo = createMemo;
|
|
1755
|
+
exports.createReducer = createReducer;
|
|
1756
|
+
exports.createRef = createRef;
|
|
1757
|
+
exports.createResource = createResource;
|
|
1758
|
+
exports.createRoot = createRoot;
|
|
1759
|
+
exports.createShow = createShow;
|
|
1760
|
+
exports.fragment = fragment;
|
|
1761
|
+
exports.h = h;
|
|
1762
|
+
exports.hydrateIsland = hydrateIsland;
|
|
1763
|
+
exports.internalEffect = internalEffect;
|
|
1764
|
+
exports.longestIncreasingSubsequence = longestIncreasingSubsequence;
|
|
1765
|
+
exports.on = on;
|
|
1766
|
+
exports.onCleanup = onCleanup;
|
|
1767
|
+
exports.onError = onError;
|
|
1768
|
+
exports.popSuspenseContext = popSuspenseContext;
|
|
1769
|
+
exports.pushSuspenseContext = pushSuspenseContext;
|
|
1770
|
+
exports.reconcileList = reconcileList;
|
|
1771
|
+
exports.untrack = untrack;
|
|
1772
|
+
//# sourceMappingURL=chunk-27QSSN4E.cjs.map
|
|
1773
|
+
//# sourceMappingURL=chunk-27QSSN4E.cjs.map
|