@fictjs/runtime 0.7.0 → 0.9.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.
Files changed (74) hide show
  1. package/README.md +46 -0
  2. package/dist/advanced.cjs +9 -9
  3. package/dist/advanced.d.cts +4 -4
  4. package/dist/advanced.d.ts +4 -4
  5. package/dist/advanced.js +4 -4
  6. package/dist/{effect-DAzpH7Mm.d.cts → binding-BWchH3Kp.d.cts} +33 -24
  7. package/dist/{effect-DAzpH7Mm.d.ts → binding-BWchH3Kp.d.ts} +33 -24
  8. package/dist/{chunk-7YQK3XKY.js → chunk-DXG3TARY.js} +520 -518
  9. package/dist/chunk-DXG3TARY.js.map +1 -0
  10. package/dist/{chunk-TLDT76RV.js → chunk-FVX77557.js} +3 -3
  11. package/dist/{chunk-WRU3IZOA.js → chunk-JVYH76ZX.js} +3 -3
  12. package/dist/chunk-LBE6DC3V.cjs +768 -0
  13. package/dist/chunk-LBE6DC3V.cjs.map +1 -0
  14. package/dist/chunk-N6ODUM2Y.js +768 -0
  15. package/dist/chunk-N6ODUM2Y.js.map +1 -0
  16. package/dist/{chunk-PRF4QG73.cjs → chunk-OAM7HABA.cjs} +423 -246
  17. package/dist/chunk-OAM7HABA.cjs.map +1 -0
  18. package/dist/{chunk-CEV6TO5U.cjs → chunk-PD6IQY2Y.cjs} +8 -8
  19. package/dist/{chunk-CEV6TO5U.cjs.map → chunk-PD6IQY2Y.cjs.map} +1 -1
  20. package/dist/{chunk-HHDHQGJY.cjs → chunk-PG4QX2I2.cjs} +17 -17
  21. package/dist/{chunk-HHDHQGJY.cjs.map → chunk-PG4QX2I2.cjs.map} +1 -1
  22. package/dist/{chunk-4LCHQ7U4.js → chunk-T2LNV5Q5.js} +271 -94
  23. package/dist/chunk-T2LNV5Q5.js.map +1 -0
  24. package/dist/{chunk-FSCBL7RI.cjs → chunk-UBFDB6OL.cjs} +521 -519
  25. package/dist/chunk-UBFDB6OL.cjs.map +1 -0
  26. package/dist/{context-C4vBQbb4.d.ts → devtools-5AipK9CX.d.cts} +35 -35
  27. package/dist/{context-BFbHf9nC.d.cts → devtools-BDp76luf.d.ts} +35 -35
  28. package/dist/index.cjs +42 -42
  29. package/dist/index.d.cts +4 -4
  30. package/dist/index.d.ts +4 -4
  31. package/dist/index.dev.js +3 -3
  32. package/dist/index.dev.js.map +1 -1
  33. package/dist/index.js +3 -3
  34. package/dist/internal-list.cjs +12 -0
  35. package/dist/internal-list.cjs.map +1 -0
  36. package/dist/internal-list.d.cts +2 -0
  37. package/dist/internal-list.d.ts +2 -0
  38. package/dist/internal-list.js +12 -0
  39. package/dist/internal-list.js.map +1 -0
  40. package/dist/internal.cjs +6 -746
  41. package/dist/internal.cjs.map +1 -1
  42. package/dist/internal.d.cts +6 -74
  43. package/dist/internal.d.ts +6 -74
  44. package/dist/internal.js +12 -752
  45. package/dist/internal.js.map +1 -1
  46. package/dist/list-DL5DOFcO.d.ts +71 -0
  47. package/dist/list-hP7hQ9Vk.d.cts +71 -0
  48. package/dist/loader.cjs +94 -15
  49. package/dist/loader.cjs.map +1 -1
  50. package/dist/loader.d.cts +16 -2
  51. package/dist/loader.d.ts +16 -2
  52. package/dist/loader.js +87 -8
  53. package/dist/loader.js.map +1 -1
  54. package/dist/{props-84UJeWO8.d.cts → props-BpZz0AOq.d.cts} +2 -2
  55. package/dist/{props-BRhFK50f.d.ts → props-CjLH0JE-.d.ts} +2 -2
  56. package/dist/{resume-i-A3EFox.d.cts → resume-BJ4oHLi_.d.cts} +3 -1
  57. package/dist/{resume-CqeQ3v_q.d.ts → resume-CuyJWXP_.d.ts} +3 -1
  58. package/dist/{scope-DlCBL1Ft.d.cts → scope-BJCtq8hJ.d.cts} +1 -1
  59. package/dist/{scope-D3DpsfoG.d.ts → scope-jPt5DHRT.d.ts} +1 -1
  60. package/package.json +8 -1
  61. package/src/binding.ts +113 -36
  62. package/src/cycle-guard.ts +3 -3
  63. package/src/internal/list.ts +7 -0
  64. package/src/internal.ts +1 -0
  65. package/src/list-helpers.ts +1 -1
  66. package/src/loader.ts +119 -9
  67. package/src/resume.ts +6 -3
  68. package/src/signal.ts +8 -1
  69. package/dist/chunk-4LCHQ7U4.js.map +0 -1
  70. package/dist/chunk-7YQK3XKY.js.map +0 -1
  71. package/dist/chunk-FSCBL7RI.cjs.map +0 -1
  72. package/dist/chunk-PRF4QG73.cjs.map +0 -1
  73. /package/dist/{chunk-TLDT76RV.js.map → chunk-FVX77557.js.map} +0 -0
  74. /package/dist/{chunk-WRU3IZOA.js.map → chunk-JVYH76ZX.js.map} +0 -0
package/dist/internal.js CHANGED
@@ -1,13 +1,18 @@
1
+ import {
2
+ createKeyedList,
3
+ isNodeBetweenMarkers,
4
+ moveNodesBefore,
5
+ reconcileArrays
6
+ } from "./chunk-N6ODUM2Y.js";
1
7
  import {
2
8
  runInScope
3
- } from "./chunk-TLDT76RV.js";
9
+ } from "./chunk-FVX77557.js";
4
10
  import {
5
11
  Fragment,
6
12
  __fictProp,
7
13
  __fictPropsRest,
8
14
  addEventListener,
9
15
  assign,
10
- batch,
11
16
  bindAttribute,
12
17
  bindClass,
13
18
  bindEvent,
@@ -28,7 +33,6 @@ import {
28
33
  insert,
29
34
  insertBetween,
30
35
  insertNodesBefore,
31
- isHydratingActive,
32
36
  isReactive,
33
37
  keyed,
34
38
  mergeProps,
@@ -46,14 +50,14 @@ import {
46
50
  spread,
47
51
  template,
48
52
  toNodeArray,
49
- unwrap,
50
- withHydrationRange
51
- } from "./chunk-4LCHQ7U4.js";
53
+ unwrap
54
+ } from "./chunk-T2LNV5Q5.js";
52
55
  import {
53
56
  Aliases,
54
57
  BooleanAttributes,
55
58
  ChildProperties,
56
59
  DelegatedEvents,
60
+ FICT_SSR_SNAPSHOT_SCHEMA_VERSION,
57
61
  Properties,
58
62
  SVGElements,
59
63
  SVGNamespace,
@@ -96,766 +100,22 @@ import {
96
100
  createEffect,
97
101
  createMemo,
98
102
  createRenderEffect,
99
- createRootContext,
100
103
  createSelector,
101
104
  createStore,
102
105
  deserializeValue,
103
- destroyRoot,
104
- effectScope,
105
- flush,
106
- flushOnMount,
107
- getCurrentRoot,
108
106
  getPropAlias,
109
107
  isStoreProxy,
110
108
  onDestroy,
111
- popRoot,
112
- pushRoot,
113
109
  serializeValue,
114
- setActiveSub,
115
110
  signal,
116
111
  unwrapStore
117
- } from "./chunk-7YQK3XKY.js";
118
-
119
- // src/reconcile.ts
120
- function reconcileArrays(parentNode, a, b) {
121
- const bLength = b.length;
122
- let aEnd = a.length;
123
- let bEnd = bLength;
124
- let aStart = 0;
125
- let bStart = 0;
126
- const after = aEnd > 0 ? a[aEnd - 1].nextSibling : null;
127
- let map = null;
128
- while (aStart < aEnd || bStart < bEnd) {
129
- if (a[aStart] === b[bStart]) {
130
- aStart++;
131
- bStart++;
132
- continue;
133
- }
134
- while (a[aEnd - 1] === b[bEnd - 1]) {
135
- aEnd--;
136
- bEnd--;
137
- }
138
- if (aEnd === aStart) {
139
- const node = bEnd < bLength ? bStart ? b[bStart - 1].nextSibling : b[bEnd - bStart] ?? null : after;
140
- const count = bEnd - bStart;
141
- const doc = parentNode.ownerDocument;
142
- if (count > 1 && doc) {
143
- const frag = doc.createDocumentFragment();
144
- for (let i = bStart; i < bEnd; i++) {
145
- frag.appendChild(b[i]);
146
- }
147
- parentNode.insertBefore(frag, node);
148
- bStart = bEnd;
149
- } else {
150
- while (bStart < bEnd) {
151
- parentNode.insertBefore(b[bStart++], node);
152
- }
153
- }
154
- } else if (bEnd === bStart) {
155
- while (aStart < aEnd) {
156
- const nodeToRemove = a[aStart];
157
- if (!map || !map.has(nodeToRemove)) {
158
- nodeToRemove.parentNode?.removeChild(nodeToRemove);
159
- }
160
- aStart++;
161
- }
162
- } else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {
163
- const node = a[--aEnd].nextSibling;
164
- parentNode.insertBefore(b[bStart++], a[aStart++].nextSibling);
165
- parentNode.insertBefore(b[--bEnd], node);
166
- a[aEnd] = b[bEnd];
167
- } else {
168
- if (!map) {
169
- map = /* @__PURE__ */ new Map();
170
- let i = bStart;
171
- while (i < bEnd) {
172
- map.set(b[i], i++);
173
- }
174
- }
175
- const index = map.get(a[aStart]);
176
- if (index != null) {
177
- if (bStart < index && index < bEnd) {
178
- let i = aStart;
179
- let sequence = 1;
180
- let t;
181
- while (++i < aEnd && i < bEnd) {
182
- t = map.get(a[i]);
183
- if (t == null || t !== index + sequence) break;
184
- sequence++;
185
- }
186
- if (sequence > index - bStart) {
187
- const node = a[aStart];
188
- while (bStart < index) {
189
- parentNode.insertBefore(b[bStart++], node);
190
- }
191
- } else {
192
- parentNode.replaceChild(b[bStart++], a[aStart++]);
193
- }
194
- } else {
195
- aStart++;
196
- }
197
- } else {
198
- const nodeToRemove = a[aStart++];
199
- nodeToRemove.parentNode?.removeChild(nodeToRemove);
200
- }
201
- }
202
- }
203
- }
204
-
205
- // src/list-helpers.ts
206
- var isDev = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || process.env?.NODE_ENV !== "production";
207
- var isShadowRoot = (node) => typeof ShadowRoot !== "undefined" && node instanceof ShadowRoot;
208
- function moveNodesBefore(parent, nodes, anchor) {
209
- for (let i = nodes.length - 1; i >= 0; i--) {
210
- const node = nodes[i];
211
- if (!node || !(node instanceof Node)) {
212
- const message = isDev ? "Invalid node in moveNodesBefore" : "FICT:E_NODE";
213
- throw new Error(message);
214
- }
215
- if (node.nextSibling !== anchor) {
216
- if (node.ownerDocument !== parent.ownerDocument && parent.ownerDocument) {
217
- parent.ownerDocument.adoptNode(node);
218
- }
219
- try {
220
- parent.insertBefore(node, anchor);
221
- } catch (e) {
222
- if (parent.ownerDocument) {
223
- try {
224
- const clone = parent.ownerDocument.importNode(node, true);
225
- parent.insertBefore(clone, anchor);
226
- nodes[i] = clone;
227
- if (isDev) {
228
- console.warn(
229
- `[fict] Node cloning fallback triggered during list reordering. This may indicate cross-document node insertion. The node reference has been updated to the clone.`
230
- );
231
- }
232
- anchor = clone;
233
- continue;
234
- } catch {
235
- }
236
- }
237
- throw e;
238
- }
239
- }
240
- anchor = node;
241
- }
242
- }
243
- var MAX_SAFE_VERSION = 9007199254740991;
244
- function createVersionedSignalAccessor(initialValue) {
245
- let current = initialValue;
246
- let version = 0;
247
- const track = signal(version);
248
- function accessor(value) {
249
- if (arguments.length === 0) {
250
- track();
251
- return current;
252
- }
253
- current = value;
254
- version = version >= MAX_SAFE_VERSION ? 1 : version + 1;
255
- track(version);
256
- }
257
- return accessor;
258
- }
259
- function createKeyedListContainer(startOverride, endOverride) {
260
- const startMarker = startOverride ?? document.createComment("fict:list:start");
261
- const endMarker = endOverride ?? document.createComment("fict:list:end");
262
- const dispose = () => {
263
- for (const block of container.blocks.values()) {
264
- destroyRoot(block.root);
265
- }
266
- container.blocks.clear();
267
- container.nextBlocks.clear();
268
- if (!startMarker.parentNode || !endMarker.parentNode) {
269
- container.currentNodes = [];
270
- container.nextNodes = [];
271
- container.orderedBlocks.length = 0;
272
- container.nextOrderedBlocks.length = 0;
273
- container.orderedIndexByKey.clear();
274
- return;
275
- }
276
- const range = document.createRange();
277
- range.setStartBefore(startMarker);
278
- range.setEndAfter(endMarker);
279
- range.deleteContents();
280
- container.currentNodes = [];
281
- container.nextNodes = [];
282
- container.nextBlocks.clear();
283
- container.orderedBlocks.length = 0;
284
- container.nextOrderedBlocks.length = 0;
285
- container.orderedIndexByKey.clear();
286
- };
287
- const container = {
288
- startMarker,
289
- endMarker,
290
- blocks: /* @__PURE__ */ new Map(),
291
- nextBlocks: /* @__PURE__ */ new Map(),
292
- currentNodes: [startMarker, endMarker],
293
- nextNodes: [],
294
- orderedBlocks: [],
295
- nextOrderedBlocks: [],
296
- orderedIndexByKey: /* @__PURE__ */ new Map(),
297
- dispose
298
- };
299
- return container;
300
- }
301
- function createKeyedBlock(key, item, index, render2, needsIndex = true, hostRoot) {
302
- const itemSig = createVersionedSignalAccessor(item);
303
- const indexSig = needsIndex ? signal(index) : ((next) => {
304
- if (arguments.length === 0) return index;
305
- index = next;
306
- return index;
307
- });
308
- const root = createRootContext(hostRoot);
309
- const prevRoot = pushRoot(root);
310
- let nodes = [];
311
- let scopeDispose;
312
- const prevSub = setActiveSub(void 0);
313
- try {
314
- scopeDispose = effectScope(() => {
315
- const rendered = render2(itemSig, indexSig, key);
316
- if (rendered instanceof Node || Array.isArray(rendered) && rendered.every((n) => n instanceof Node)) {
317
- nodes = toNodeArray(rendered);
318
- } else {
319
- const element = createElement(rendered);
320
- nodes = toNodeArray(element);
321
- }
322
- });
323
- if (scopeDispose) {
324
- root.cleanups.push(scopeDispose);
325
- }
326
- } finally {
327
- setActiveSub(prevSub);
328
- popRoot(prevRoot);
329
- }
330
- return {
331
- key,
332
- nodes,
333
- root,
334
- item: itemSig,
335
- index: indexSig,
336
- rawItem: item,
337
- rawIndex: index
338
- };
339
- }
340
- function isNodeBetweenMarkers(node, startMarker, endMarker) {
341
- let current = startMarker.nextSibling;
342
- while (current && current !== endMarker) {
343
- if (current === node) return true;
344
- current = current.nextSibling;
345
- }
346
- return false;
347
- }
348
- function reorderBySwap(parent, first, second) {
349
- if (first === second) return false;
350
- const firstNodes = first.nodes;
351
- const secondNodes = second.nodes;
352
- if (firstNodes.length === 0 || secondNodes.length === 0) return false;
353
- const lastFirst = firstNodes[firstNodes.length - 1];
354
- const lastSecond = secondNodes[secondNodes.length - 1];
355
- const afterFirst = lastFirst.nextSibling;
356
- const afterSecond = lastSecond.nextSibling;
357
- moveNodesBefore(parent, firstNodes, afterSecond);
358
- moveNodesBefore(parent, secondNodes, afterFirst);
359
- return true;
360
- }
361
- function getLISIndices(sequence) {
362
- const predecessors = new Array(sequence.length);
363
- const result = [];
364
- for (let i = 0; i < sequence.length; i++) {
365
- const value = sequence[i];
366
- if (value < 0) {
367
- predecessors[i] = -1;
368
- continue;
369
- }
370
- let low = 0;
371
- let high = result.length;
372
- while (low < high) {
373
- const mid = low + high >> 1;
374
- if (sequence[result[mid]] < value) {
375
- low = mid + 1;
376
- } else {
377
- high = mid;
378
- }
379
- }
380
- predecessors[i] = low > 0 ? result[low - 1] : -1;
381
- if (low === result.length) {
382
- result.push(i);
383
- } else {
384
- result[low] = i;
385
- }
386
- }
387
- const lis = new Array(result.length);
388
- let k = result.length > 0 ? result[result.length - 1] : -1;
389
- for (let i = result.length - 1; i >= 0; i--) {
390
- lis[i] = k;
391
- k = predecessors[k];
392
- }
393
- return lis;
394
- }
395
- function reorderByLIS(parent, endMarker, prev, next) {
396
- const positions = /* @__PURE__ */ new Map();
397
- for (let i = 0; i < prev.length; i++) {
398
- positions.set(prev[i], i);
399
- }
400
- const sequence = new Array(next.length);
401
- for (let i = 0; i < next.length; i++) {
402
- const position = positions.get(next[i]);
403
- if (position === void 0) return false;
404
- sequence[i] = position;
405
- }
406
- const lisIndices = getLISIndices(sequence);
407
- if (lisIndices.length === sequence.length) return true;
408
- const inLIS = new Array(sequence.length).fill(false);
409
- for (let i = 0; i < lisIndices.length; i++) {
410
- inLIS[lisIndices[i]] = true;
411
- }
412
- let anchor = endMarker;
413
- let moved = false;
414
- for (let i = next.length - 1; i >= 0; i--) {
415
- const block = next[i];
416
- const nodes = block.nodes;
417
- if (nodes.length === 0) continue;
418
- if (inLIS[i]) {
419
- anchor = nodes[0];
420
- continue;
421
- }
422
- moveNodesBefore(parent, nodes, anchor);
423
- anchor = nodes[0];
424
- moved = true;
425
- }
426
- return moved;
427
- }
428
- function createKeyedList(getItems, keyFn, renderItem, needsIndex, startMarker, endMarker) {
429
- const resolvedNeedsIndex = arguments.length >= 4 ? !!needsIndex : renderItem.length > 1;
430
- return createFineGrainedKeyedList(
431
- getItems,
432
- keyFn,
433
- renderItem,
434
- resolvedNeedsIndex,
435
- startMarker,
436
- endMarker
437
- );
438
- }
439
- function createFineGrainedKeyedList(getItems, keyFn, renderItem, needsIndex, startOverride, endOverride) {
440
- const container = createKeyedListContainer(startOverride, endOverride);
441
- const hostRoot = getCurrentRoot();
442
- const useProvided = !!(startOverride && endOverride);
443
- const fragment = useProvided ? container.startMarker : document.createDocumentFragment();
444
- if (!useProvided) {
445
- ;
446
- fragment.append(container.startMarker, container.endMarker);
447
- }
448
- let disposed = false;
449
- let effectDispose;
450
- let connectObserver = null;
451
- let effectStarted = false;
452
- let startScheduled = false;
453
- let initialHydrating = __fictIsHydrating();
454
- const collectBetween = () => {
455
- const nodes = [];
456
- let cursor = container.startMarker.nextSibling;
457
- while (cursor && cursor !== container.endMarker) {
458
- nodes.push(cursor);
459
- cursor = cursor.nextSibling;
460
- }
461
- return nodes;
462
- };
463
- const getConnectedParent = () => {
464
- const endParent = container.endMarker.parentNode;
465
- const startParent = container.startMarker.parentNode;
466
- if (endParent && startParent && endParent === startParent && endParent.nodeType !== 11) {
467
- const parentNode = endParent;
468
- if ("isConnected" in parentNode && !parentNode.isConnected) return null;
469
- return parentNode;
470
- }
471
- if (endParent && startParent && endParent === startParent && isShadowRoot(endParent)) {
472
- const shadowRoot = endParent;
473
- const host = shadowRoot.host;
474
- if ("isConnected" in host && !host.isConnected) return null;
475
- return shadowRoot;
476
- }
477
- return null;
478
- };
479
- const performDiff = () => {
480
- if (disposed) return;
481
- const isSSR = __fictIsSSR();
482
- const parent = isSSR ? container.startMarker.parentNode : getConnectedParent();
483
- if (!parent) return;
484
- batch(() => {
485
- const oldBlocks = container.blocks;
486
- const newBlocks = container.nextBlocks;
487
- const prevOrderedBlocks = container.orderedBlocks;
488
- const nextOrderedBlocks = container.nextOrderedBlocks;
489
- const orderedIndexByKey = container.orderedIndexByKey;
490
- const newItems = getItems();
491
- if (initialHydrating && isHydratingActive()) {
492
- initialHydrating = false;
493
- newBlocks.clear();
494
- nextOrderedBlocks.length = 0;
495
- orderedIndexByKey.clear();
496
- if (newItems.length === 0) {
497
- oldBlocks.clear();
498
- prevOrderedBlocks.length = 0;
499
- container.currentNodes = [container.startMarker, container.endMarker];
500
- container.nextNodes.length = 0;
501
- return;
502
- }
503
- const createdBlocks2 = [];
504
- withHydrationRange(
505
- container.startMarker.nextSibling,
506
- container.endMarker,
507
- parent.ownerDocument ?? document,
508
- () => {
509
- for (let index = 0; index < newItems.length; index++) {
510
- const item = newItems[index];
511
- const key = keyFn(item, index);
512
- if (newBlocks.has(key)) {
513
- if (isDev) {
514
- console.warn(
515
- `[fict] Duplicate key "${String(key)}" detected in list hydration. Each item should have a unique key.`
516
- );
517
- }
518
- const existing = newBlocks.get(key);
519
- if (existing) {
520
- destroyRoot(existing.root);
521
- removeNodes(existing.nodes);
522
- }
523
- }
524
- const block = createKeyedBlock(key, item, index, renderItem, needsIndex, hostRoot);
525
- createdBlocks2.push(block);
526
- newBlocks.set(key, block);
527
- orderedIndexByKey.set(key, nextOrderedBlocks.length);
528
- nextOrderedBlocks.push(block);
529
- }
530
- }
531
- );
532
- container.blocks = newBlocks;
533
- container.nextBlocks = oldBlocks;
534
- container.orderedBlocks = nextOrderedBlocks;
535
- container.nextOrderedBlocks = prevOrderedBlocks;
536
- oldBlocks.clear();
537
- prevOrderedBlocks.length = 0;
538
- container.currentNodes = [container.startMarker, ...collectBetween(), container.endMarker];
539
- container.nextNodes.length = 0;
540
- for (const block of createdBlocks2) {
541
- if (newBlocks.get(block.key) === block) {
542
- flushOnMount(block.root);
543
- }
544
- }
545
- return;
546
- }
547
- if (newItems.length === 0) {
548
- if (oldBlocks.size > 0) {
549
- for (const block of oldBlocks.values()) {
550
- destroyRoot(block.root);
551
- }
552
- const range = document.createRange();
553
- range.setStartAfter(container.startMarker);
554
- range.setEndBefore(container.endMarker);
555
- range.deleteContents();
556
- }
557
- oldBlocks.clear();
558
- newBlocks.clear();
559
- prevOrderedBlocks.length = 0;
560
- nextOrderedBlocks.length = 0;
561
- orderedIndexByKey.clear();
562
- container.currentNodes.length = 0;
563
- container.currentNodes.push(container.startMarker, container.endMarker);
564
- container.nextNodes.length = 0;
565
- return;
566
- }
567
- const prevCount = prevOrderedBlocks.length;
568
- if (prevCount > 0 && newItems.length === prevCount && orderedIndexByKey.size === prevCount) {
569
- let stableOrder = true;
570
- const seen = /* @__PURE__ */ new Set();
571
- for (let i = 0; i < prevCount; i++) {
572
- const item = newItems[i];
573
- const key = keyFn(item, i);
574
- if (seen.has(key) || prevOrderedBlocks[i].key !== key) {
575
- stableOrder = false;
576
- break;
577
- }
578
- seen.add(key);
579
- }
580
- if (stableOrder) {
581
- for (let i = 0; i < prevCount; i++) {
582
- const item = newItems[i];
583
- const block = prevOrderedBlocks[i];
584
- if (block.rawItem !== item) {
585
- block.rawItem = item;
586
- block.item(item);
587
- }
588
- if (needsIndex && block.rawIndex !== i) {
589
- block.rawIndex = i;
590
- block.index(i);
591
- }
592
- }
593
- return;
594
- }
595
- }
596
- newBlocks.clear();
597
- nextOrderedBlocks.length = 0;
598
- orderedIndexByKey.clear();
599
- const createdBlocks = [];
600
- let appendCandidate = prevCount > 0 && newItems.length >= prevCount;
601
- const appendedBlocks = [];
602
- let mismatchCount = 0;
603
- let mismatchFirst = -1;
604
- let mismatchSecond = -1;
605
- let hasDuplicateKey = false;
606
- newItems.forEach((item, index) => {
607
- const key = keyFn(item, index);
608
- let block = oldBlocks.get(key);
609
- const existed = block !== void 0;
610
- if (block) {
611
- if (block.rawItem !== item) {
612
- block.rawItem = item;
613
- block.item(item);
614
- }
615
- if (needsIndex && block.rawIndex !== index) {
616
- block.rawIndex = index;
617
- block.index(index);
618
- }
619
- }
620
- if (block) {
621
- newBlocks.set(key, block);
622
- oldBlocks.delete(key);
623
- } else {
624
- const existingBlock = newBlocks.get(key);
625
- if (existingBlock) {
626
- if (isDev) {
627
- console.warn(
628
- `[fict] Duplicate key "${String(key)}" detected in list rendering. Each item should have a unique key. The previous item with this key will be replaced.`
629
- );
630
- }
631
- destroyRoot(existingBlock.root);
632
- removeNodes(existingBlock.nodes);
633
- }
634
- block = createKeyedBlock(key, item, index, renderItem, needsIndex, hostRoot);
635
- createdBlocks.push(block);
636
- }
637
- const resolvedBlock = block;
638
- newBlocks.set(key, resolvedBlock);
639
- const position = orderedIndexByKey.get(key);
640
- if (position !== void 0) {
641
- appendCandidate = false;
642
- hasDuplicateKey = true;
643
- const prior = nextOrderedBlocks[position];
644
- if (prior && prior !== resolvedBlock) {
645
- destroyRoot(prior.root);
646
- removeNodes(prior.nodes);
647
- }
648
- nextOrderedBlocks[position] = resolvedBlock;
649
- } else {
650
- if (appendCandidate) {
651
- if (index < prevCount) {
652
- if (!prevOrderedBlocks[index] || prevOrderedBlocks[index].key !== key) {
653
- appendCandidate = false;
654
- }
655
- } else if (existed) {
656
- appendCandidate = false;
657
- }
658
- }
659
- const nextIndex = nextOrderedBlocks.length;
660
- orderedIndexByKey.set(key, nextIndex);
661
- nextOrderedBlocks.push(resolvedBlock);
662
- if (mismatchCount < 3 && (nextIndex >= prevCount || prevOrderedBlocks[nextIndex] !== resolvedBlock)) {
663
- if (mismatchCount === 0) {
664
- mismatchFirst = nextIndex;
665
- } else if (mismatchCount === 1) {
666
- mismatchSecond = nextIndex;
667
- }
668
- mismatchCount++;
669
- }
670
- }
671
- if (appendCandidate && index >= prevCount) {
672
- appendedBlocks.push(resolvedBlock);
673
- }
674
- });
675
- const canAppend = appendCandidate && prevCount > 0 && newItems.length > prevCount && oldBlocks.size === 0 && appendedBlocks.length > 0;
676
- if (canAppend) {
677
- const appendedNodes = [];
678
- for (const block of appendedBlocks) {
679
- for (let i = 0; i < block.nodes.length; i++) {
680
- appendedNodes.push(block.nodes[i]);
681
- }
682
- }
683
- if (appendedNodes.length > 0) {
684
- insertNodesBefore(parent, appendedNodes, container.endMarker);
685
- const currentNodes = container.currentNodes;
686
- currentNodes.pop();
687
- for (let i = 0; i < appendedNodes.length; i++) {
688
- currentNodes.push(appendedNodes[i]);
689
- }
690
- currentNodes.push(container.endMarker);
691
- }
692
- container.blocks = newBlocks;
693
- container.nextBlocks = oldBlocks;
694
- container.orderedBlocks = nextOrderedBlocks;
695
- container.nextOrderedBlocks = prevOrderedBlocks;
696
- for (const block of createdBlocks) {
697
- if (newBlocks.get(block.key) === block) {
698
- flushOnMount(block.root);
699
- }
700
- }
701
- return;
702
- }
703
- if (oldBlocks.size > 0) {
704
- for (const block of oldBlocks.values()) {
705
- destroyRoot(block.root);
706
- removeNodes(block.nodes);
707
- }
708
- oldBlocks.clear();
709
- }
710
- const canReorderInPlace = createdBlocks.length === 0 && oldBlocks.size === 0 && nextOrderedBlocks.length === prevOrderedBlocks.length;
711
- let skipReconcile = false;
712
- let updateNodeBuffer = true;
713
- if (canReorderInPlace && nextOrderedBlocks.length > 0 && !hasDuplicateKey) {
714
- if (mismatchCount === 0) {
715
- skipReconcile = true;
716
- updateNodeBuffer = false;
717
- } else if (mismatchCount === 2 && prevOrderedBlocks[mismatchFirst] === nextOrderedBlocks[mismatchSecond] && prevOrderedBlocks[mismatchSecond] === nextOrderedBlocks[mismatchFirst]) {
718
- if (reorderBySwap(
719
- parent,
720
- prevOrderedBlocks[mismatchFirst],
721
- prevOrderedBlocks[mismatchSecond]
722
- )) {
723
- skipReconcile = true;
724
- }
725
- } else if (reorderByLIS(parent, container.endMarker, prevOrderedBlocks, nextOrderedBlocks)) {
726
- skipReconcile = true;
727
- }
728
- }
729
- if (!skipReconcile && (newBlocks.size > 0 || container.currentNodes.length > 0)) {
730
- const prevNodes = container.currentNodes;
731
- const nextNodes = container.nextNodes;
732
- nextNodes.length = 0;
733
- nextNodes.push(container.startMarker);
734
- for (let i = 0; i < nextOrderedBlocks.length; i++) {
735
- const nodes = nextOrderedBlocks[i].nodes;
736
- for (let j = 0; j < nodes.length; j++) {
737
- nextNodes.push(nodes[j]);
738
- }
739
- }
740
- nextNodes.push(container.endMarker);
741
- reconcileArrays(parent, prevNodes, nextNodes);
742
- container.currentNodes = nextNodes;
743
- container.nextNodes = prevNodes;
744
- } else if (skipReconcile && updateNodeBuffer) {
745
- const prevNodes = container.currentNodes;
746
- const nextNodes = container.nextNodes;
747
- nextNodes.length = 0;
748
- nextNodes.push(container.startMarker);
749
- for (let i = 0; i < nextOrderedBlocks.length; i++) {
750
- const nodes = nextOrderedBlocks[i].nodes;
751
- for (let j = 0; j < nodes.length; j++) {
752
- nextNodes.push(nodes[j]);
753
- }
754
- }
755
- nextNodes.push(container.endMarker);
756
- container.currentNodes = nextNodes;
757
- container.nextNodes = prevNodes;
758
- }
759
- container.blocks = newBlocks;
760
- container.nextBlocks = oldBlocks;
761
- container.orderedBlocks = nextOrderedBlocks;
762
- container.nextOrderedBlocks = prevOrderedBlocks;
763
- for (const block of createdBlocks) {
764
- if (newBlocks.get(block.key) === block) {
765
- flushOnMount(block.root);
766
- }
767
- }
768
- });
769
- };
770
- const disconnectObserver = () => {
771
- connectObserver?.disconnect();
772
- connectObserver = null;
773
- };
774
- const ensureEffectStarted = () => {
775
- if (disposed || effectStarted) return effectStarted;
776
- const isSSR = __fictIsSSR();
777
- const parent = isSSR ? container.startMarker.parentNode : getConnectedParent();
778
- if (!parent) return false;
779
- const start = () => {
780
- effectDispose = createRenderEffect(performDiff);
781
- effectStarted = true;
782
- };
783
- if (hostRoot) {
784
- const prev = pushRoot(hostRoot);
785
- try {
786
- start();
787
- } finally {
788
- popRoot(prev);
789
- }
790
- } else {
791
- start();
792
- }
793
- return true;
794
- };
795
- const waitForConnection = () => {
796
- if (connectObserver || typeof MutationObserver === "undefined") return;
797
- const root = container.startMarker.getRootNode?.() ?? document;
798
- const shadowRoot = root && root.nodeType === 11 && isShadowRoot(root) ? root : null;
799
- connectObserver = new MutationObserver(() => {
800
- if (disposed) return;
801
- if (getConnectedParent()) {
802
- disconnectObserver();
803
- if (ensureEffectStarted()) {
804
- flush();
805
- }
806
- }
807
- });
808
- connectObserver.observe(document, { childList: true, subtree: true });
809
- if (shadowRoot) {
810
- connectObserver.observe(shadowRoot, { childList: true, subtree: true });
811
- }
812
- };
813
- const scheduleStart = () => {
814
- if (startScheduled || disposed || effectStarted) return;
815
- startScheduled = true;
816
- const run = () => {
817
- startScheduled = false;
818
- if (!ensureEffectStarted()) {
819
- waitForConnection();
820
- }
821
- };
822
- if (typeof queueMicrotask === "function") {
823
- queueMicrotask(run);
824
- } else {
825
- Promise.resolve().then(run).catch(() => void 0);
826
- }
827
- };
828
- scheduleStart();
829
- return {
830
- get marker() {
831
- scheduleStart();
832
- return fragment;
833
- },
834
- startMarker: container.startMarker,
835
- endMarker: container.endMarker,
836
- // Flush pending items - call after markers are inserted into DOM
837
- flush: () => {
838
- if (disposed) return;
839
- scheduleStart();
840
- if (ensureEffectStarted()) {
841
- flush();
842
- } else {
843
- waitForConnection();
844
- }
845
- },
846
- dispose: () => {
847
- disposed = true;
848
- effectDispose?.();
849
- disconnectObserver();
850
- container.dispose();
851
- }
852
- };
853
- }
112
+ } from "./chunk-DXG3TARY.js";
854
113
  export {
855
114
  Aliases,
856
115
  BooleanAttributes,
857
116
  ChildProperties,
858
117
  DelegatedEvents,
118
+ FICT_SSR_SNAPSHOT_SCHEMA_VERSION,
859
119
  Fragment,
860
120
  Properties,
861
121
  SVGElements,