@fictjs/runtime 0.2.2 → 0.3.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 (58) hide show
  1. package/dist/advanced.cjs +10 -8
  2. package/dist/advanced.cjs.map +1 -1
  3. package/dist/advanced.d.cts +10 -16
  4. package/dist/advanced.d.ts +10 -16
  5. package/dist/advanced.js +5 -3
  6. package/dist/advanced.js.map +1 -1
  7. package/dist/{chunk-3U7EBKEU.cjs → chunk-ID3WBWNO.cjs} +559 -319
  8. package/dist/chunk-ID3WBWNO.cjs.map +1 -0
  9. package/dist/{chunk-3A4VW6AK.cjs → chunk-L4DIV3RC.cjs} +7 -7
  10. package/dist/{chunk-3A4VW6AK.cjs.map → chunk-L4DIV3RC.cjs.map} +1 -1
  11. package/dist/{chunk-URDFDRHR.cjs → chunk-M2TSXZ4C.cjs} +16 -16
  12. package/dist/{chunk-URDFDRHR.cjs.map → chunk-M2TSXZ4C.cjs.map} +1 -1
  13. package/dist/{chunk-YVS4WJ2W.js → chunk-SO6X7G5S.js} +558 -318
  14. package/dist/chunk-SO6X7G5S.js.map +1 -0
  15. package/dist/{chunk-LU2LD2WJ.js → chunk-TWELIZRY.js} +2 -2
  16. package/dist/{chunk-TEYUDPTA.js → chunk-XLIZJMMJ.js} +2 -2
  17. package/dist/{context-9gFXOdJl.d.cts → context-B25xyQrJ.d.cts} +36 -2
  18. package/dist/{context-4woHo7-L.d.ts → context-CGdP7_Jb.d.ts} +36 -2
  19. package/dist/{effect-ClARNUCc.d.cts → effect-D6kaLM2-.d.cts} +80 -1
  20. package/dist/{effect-ClARNUCc.d.ts → effect-D6kaLM2-.d.ts} +80 -1
  21. package/dist/index.cjs +40 -38
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +4 -4
  24. package/dist/index.d.ts +4 -4
  25. package/dist/index.dev.js +430 -246
  26. package/dist/index.dev.js.map +1 -1
  27. package/dist/index.js +4 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/internal.cjs +39 -35
  30. package/dist/internal.cjs.map +1 -1
  31. package/dist/internal.d.cts +8 -6
  32. package/dist/internal.d.ts +8 -6
  33. package/dist/internal.js +7 -3
  34. package/dist/internal.js.map +1 -1
  35. package/dist/{props-DAyeRPwH.d.ts → props-BEgIVMRx.d.ts} +8 -15
  36. package/dist/{props-CBwuh35e.d.cts → props-BIfromL0.d.cts} +8 -15
  37. package/dist/scope-Cx_3CjIZ.d.cts +18 -0
  38. package/dist/scope-CzNkn587.d.ts +18 -0
  39. package/package.json +1 -1
  40. package/src/advanced.ts +1 -0
  41. package/src/binding.ts +30 -4
  42. package/src/constants.ts +5 -0
  43. package/src/cycle-guard.ts +164 -103
  44. package/src/devtools.ts +22 -2
  45. package/src/dom.ts +84 -10
  46. package/src/hooks.ts +60 -13
  47. package/src/index.ts +3 -1
  48. package/src/internal.ts +2 -2
  49. package/src/lifecycle.ts +13 -5
  50. package/src/memo.ts +3 -4
  51. package/src/props.ts +16 -0
  52. package/src/signal.ts +204 -36
  53. package/dist/chunk-3U7EBKEU.cjs.map +0 -1
  54. package/dist/chunk-YVS4WJ2W.js.map +0 -1
  55. package/dist/scope-DvgMquEy.d.ts +0 -55
  56. package/dist/scope-xmdo6lVU.d.cts +0 -55
  57. /package/dist/{chunk-LU2LD2WJ.js.map → chunk-TWELIZRY.js.map} +0 -0
  58. /package/dist/{chunk-TEYUDPTA.js.map → chunk-XLIZJMMJ.js.map} +0 -0
@@ -25,7 +25,7 @@ var DelegatedEventNames = [
25
25
  ];
26
26
 
27
27
  // src/constants.ts
28
- var isDev = true ? false : typeof process === "undefined" || _optionalChain([process, 'access', _2 => _2.env, 'optionalAccess', _3 => _3.NODE_ENV]) !== "production";
28
+ var isDev = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || _optionalChain([process, 'access', _2 => _2.env, 'optionalAccess', _3 => _3.NODE_ENV]) !== "production";
29
29
  var booleans = isDev ? [
30
30
  "allowfullscreen",
31
31
  "async",
@@ -387,7 +387,7 @@ function getDevtoolsHook() {
387
387
  }
388
388
 
389
389
  // src/cycle-guard.ts
390
- var isDev2 = true ? false : typeof process === "undefined" || _optionalChain([process, 'access', _4 => _4.env, 'optionalAccess', _5 => _5.NODE_ENV]) !== "production";
390
+ var isDev2 = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || _optionalChain([process, 'access', _4 => _4.env, 'optionalAccess', _5 => _5.NODE_ENV]) !== "production";
391
391
  var setCycleProtectionOptions = () => {
392
392
  };
393
393
  var resetCycleProtectionStateForTests = () => {
@@ -400,113 +400,161 @@ var endFlushGuard = () => {
400
400
  var enterRootGuard = () => true;
401
401
  var exitRootGuard = () => {
402
402
  };
403
- if (isDev2) {
404
- const defaultOptions = {
405
- maxFlushCyclesPerMicrotask: 1e4,
406
- maxEffectRunsPerFlush: 2e4,
407
- windowSize: 5,
408
- highUsageRatio: 0.8,
409
- maxRootReentrantDepth: 10,
410
- enableWindowWarning: true,
411
- devMode: false
412
- };
413
- let options = {
414
- ...defaultOptions
415
- };
416
- let effectRunsThisFlush = 0;
417
- let windowUsage = [];
418
- let rootDepth = /* @__PURE__ */ new WeakMap();
419
- let flushWarned = false;
420
- let rootWarned = false;
421
- let windowWarned = false;
422
- setCycleProtectionOptions = exports.setCycleProtectionOptions = (opts) => {
423
- options = { ...options, ...opts };
424
- };
425
- resetCycleProtectionStateForTests = () => {
426
- options = { ...defaultOptions };
427
- effectRunsThisFlush = 0;
428
- windowUsage = [];
429
- rootDepth = /* @__PURE__ */ new WeakMap();
430
- flushWarned = false;
431
- rootWarned = false;
432
- windowWarned = false;
433
- };
434
- beginFlushGuard = () => {
435
- effectRunsThisFlush = 0;
436
- flushWarned = false;
437
- windowWarned = false;
438
- };
439
- beforeEffectRunGuard = () => {
440
- const next = ++effectRunsThisFlush;
441
- if (next > options.maxFlushCyclesPerMicrotask || next > options.maxEffectRunsPerFlush) {
442
- const message = `[fict] cycle protection triggered: flush-budget-exceeded`;
443
- if (options.devMode) {
444
- throw new Error(message);
445
- }
446
- if (!flushWarned) {
447
- flushWarned = true;
448
- console.warn(message, { effectRuns: next });
449
- }
450
- return false;
403
+ var defaultOptions = {
404
+ enabled: true,
405
+ maxFlushCyclesPerMicrotask: 1e4,
406
+ maxEffectRunsPerFlush: 2e4,
407
+ windowSize: 5,
408
+ highUsageRatio: 0.8,
409
+ maxRootReentrantDepth: 10,
410
+ enableWindowWarning: true,
411
+ devMode: isDev2,
412
+ // Backoff warning options
413
+ enableBackoffWarning: isDev2,
414
+ backoffWarningRatio: 0.5
415
+ };
416
+ var enabled = defaultOptions.enabled;
417
+ var options = {
418
+ ...defaultOptions
419
+ };
420
+ var effectRunsThisFlush = 0;
421
+ var windowUsage = [];
422
+ var rootDepth = /* @__PURE__ */ new WeakMap();
423
+ var flushWarned = false;
424
+ var rootWarned = false;
425
+ var windowWarned = false;
426
+ var backoffWarned50 = false;
427
+ var backoffWarned75 = false;
428
+ setCycleProtectionOptions = exports.setCycleProtectionOptions = (opts) => {
429
+ if (typeof opts.enabled === "boolean") {
430
+ enabled = opts.enabled;
431
+ }
432
+ options = { ...options, ...opts };
433
+ };
434
+ resetCycleProtectionStateForTests = () => {
435
+ options = { ...defaultOptions };
436
+ enabled = defaultOptions.enabled;
437
+ effectRunsThisFlush = 0;
438
+ windowUsage = [];
439
+ rootDepth = /* @__PURE__ */ new WeakMap();
440
+ flushWarned = false;
441
+ rootWarned = false;
442
+ windowWarned = false;
443
+ backoffWarned50 = false;
444
+ backoffWarned75 = false;
445
+ };
446
+ beginFlushGuard = () => {
447
+ if (!enabled) return;
448
+ effectRunsThisFlush = 0;
449
+ flushWarned = false;
450
+ windowWarned = false;
451
+ backoffWarned50 = false;
452
+ backoffWarned75 = false;
453
+ };
454
+ beforeEffectRunGuard = () => {
455
+ if (!enabled) return true;
456
+ const next = ++effectRunsThisFlush;
457
+ const limit = Math.min(options.maxFlushCyclesPerMicrotask, options.maxEffectRunsPerFlush);
458
+ if (options.enableBackoffWarning && isDev2) {
459
+ const ratio = next / limit;
460
+ const backoffRatio = _nullishCoalesce(options.backoffWarningRatio, () => ( 0.5));
461
+ if (!backoffWarned50 && ratio >= backoffRatio && ratio < backoffRatio + 0.25) {
462
+ backoffWarned50 = true;
463
+ console.warn(
464
+ `[fict] cycle guard: approaching effect limit (${Math.round(ratio * 100)}% of budget used)
465
+ - Current: ${next} effects, Limit: ${limit}
466
+ - Tip: Check for effects that trigger other effects in a loop.
467
+ - Common causes: signal updates inside effects that read and write the same signal.`
468
+ );
469
+ } else if (!backoffWarned75 && ratio >= backoffRatio + 0.25 && ratio < 1) {
470
+ backoffWarned75 = true;
471
+ console.warn(
472
+ `[fict] cycle guard: nearing effect limit (${Math.round(ratio * 100)}% of budget used)
473
+ - Current: ${next} effects, Limit: ${limit}
474
+ - Warning: Consider breaking the reactive dependency cycle.
475
+ - Debug: Use browser devtools to identify the recursive effect chain.`
476
+ );
451
477
  }
452
- return true;
453
- };
454
- endFlushGuard = () => {
455
- recordWindowUsage(effectRunsThisFlush, options.maxFlushCyclesPerMicrotask);
456
- effectRunsThisFlush = 0;
457
- };
458
- enterRootGuard = (root) => {
459
- const depth = (_nullishCoalesce(rootDepth.get(root), () => ( 0))) + 1;
460
- if (depth > options.maxRootReentrantDepth) {
461
- const message = `[fict] cycle protection triggered: root-reentry`;
462
- if (options.devMode) {
463
- throw new Error(message);
464
- }
465
- if (!rootWarned) {
466
- rootWarned = true;
467
- console.warn(message, { depth });
468
- }
469
- return false;
478
+ }
479
+ if (next > limit) {
480
+ const message = `[fict] cycle protection triggered: flush-budget-exceeded`;
481
+ if (options.devMode) {
482
+ throw new Error(
483
+ message + `
484
+ - Effect runs: ${next}, Limit: ${limit}
485
+ - This indicates a reactive cycle where effects keep triggering each other.
486
+ - Check for patterns like: createEffect(() => { signal(); signal(newValue); })`
487
+ );
470
488
  }
471
- rootDepth.set(root, depth);
472
- return true;
473
- };
474
- exitRootGuard = (root) => {
475
- const depth = rootDepth.get(root);
476
- if (depth === void 0) return;
477
- if (depth <= 1) {
478
- rootDepth.delete(root);
479
- } else {
480
- rootDepth.set(root, depth - 1);
489
+ if (!flushWarned) {
490
+ flushWarned = true;
491
+ console.warn(message, { effectRuns: next, limit });
481
492
  }
482
- };
483
- const recordWindowUsage = (used, budget) => {
484
- if (!options.enableWindowWarning) return;
485
- const entry = { used, budget };
486
- windowUsage.push(entry);
487
- if (windowUsage.length > options.windowSize) {
488
- windowUsage.shift();
489
- }
490
- if (windowWarned) return;
491
- if (windowUsage.length >= options.windowSize && windowUsage.every(
492
- (item) => item.budget > 0 && item.used / item.budget >= options.highUsageRatio
493
- )) {
494
- windowWarned = true;
495
- reportCycle("high-usage-window", {
496
- windowSize: options.windowSize,
497
- ratio: options.highUsageRatio
498
- });
493
+ return false;
494
+ }
495
+ return true;
496
+ };
497
+ endFlushGuard = () => {
498
+ if (!enabled) return;
499
+ recordWindowUsage(effectRunsThisFlush, options.maxFlushCyclesPerMicrotask);
500
+ effectRunsThisFlush = 0;
501
+ };
502
+ enterRootGuard = (root) => {
503
+ if (!enabled) return true;
504
+ const depth = (_nullishCoalesce(rootDepth.get(root), () => ( 0))) + 1;
505
+ if (depth > options.maxRootReentrantDepth) {
506
+ const message = `[fict] cycle protection triggered: root-reentry`;
507
+ if (options.devMode) {
508
+ throw new Error(
509
+ message + `
510
+ - Re-entry depth: ${depth}, Max allowed: ${options.maxRootReentrantDepth}
511
+ - This indicates recursive render() or component initialization.
512
+ - Check for components that trigger re-renders during their own render phase.`
513
+ );
499
514
  }
500
- };
501
- const reportCycle = (reason, detail = void 0) => {
502
- const hook = getDevtoolsHook();
503
- _optionalChain([hook, 'optionalAccess', _6 => _6.cycleDetected, 'optionalCall', _7 => _7(detail ? { reason, detail } : { reason })]);
504
- console.warn(`[fict] cycle protection triggered: ${reason}`, _nullishCoalesce(detail, () => ( "")));
505
- };
506
- }
515
+ if (!rootWarned) {
516
+ rootWarned = true;
517
+ console.warn(message, { depth, maxAllowed: options.maxRootReentrantDepth });
518
+ }
519
+ return false;
520
+ }
521
+ rootDepth.set(root, depth);
522
+ return true;
523
+ };
524
+ exitRootGuard = (root) => {
525
+ if (!enabled) return;
526
+ const depth = rootDepth.get(root);
527
+ if (depth === void 0) return;
528
+ if (depth <= 1) {
529
+ rootDepth.delete(root);
530
+ } else {
531
+ rootDepth.set(root, depth - 1);
532
+ }
533
+ };
534
+ var recordWindowUsage = (used, budget) => {
535
+ if (!options.enableWindowWarning) return;
536
+ const entry = { used, budget };
537
+ windowUsage.push(entry);
538
+ if (windowUsage.length > options.windowSize) {
539
+ windowUsage.shift();
540
+ }
541
+ if (windowWarned) return;
542
+ if (windowUsage.length >= options.windowSize && windowUsage.every((item) => item.budget > 0 && item.used / item.budget >= options.highUsageRatio)) {
543
+ windowWarned = true;
544
+ reportCycle("high-usage-window", {
545
+ windowSize: options.windowSize,
546
+ ratio: options.highUsageRatio
547
+ });
548
+ }
549
+ };
550
+ var reportCycle = (reason, detail = void 0) => {
551
+ const hook = getDevtoolsHook();
552
+ _optionalChain([hook, 'optionalAccess', _6 => _6.cycleDetected, 'optionalCall', _7 => _7(detail ? { reason, detail } : { reason })]);
553
+ console.warn(`[fict] cycle protection triggered: ${reason}`, _nullishCoalesce(detail, () => ( "")));
554
+ };
507
555
 
508
556
  // src/lifecycle.ts
509
- var isDev3 = true ? false : typeof process === "undefined" || _optionalChain([process, 'access', _8 => _8.env, 'optionalAccess', _9 => _9.NODE_ENV]) !== "production";
557
+ var isDev3 = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || _optionalChain([process, 'access', _8 => _8.env, 'optionalAccess', _9 => _9.NODE_ENV]) !== "production";
510
558
  var currentRoot;
511
559
  var currentEffectCleanups;
512
560
  var globalErrorHandlers = /* @__PURE__ */ new WeakMap();
@@ -552,13 +600,19 @@ function onCleanup(fn) {
552
600
  function flushOnMount(root) {
553
601
  const cbs = root.onMountCallbacks;
554
602
  if (!cbs || cbs.length === 0) return;
555
- for (let i = 0; i < cbs.length; i++) {
556
- const cleanup = cbs[i]();
557
- if (typeof cleanup === "function") {
558
- root.cleanups.push(cleanup);
603
+ const prevRoot = currentRoot;
604
+ currentRoot = root;
605
+ try {
606
+ for (let i = 0; i < cbs.length; i++) {
607
+ const cleanup = cbs[i]();
608
+ if (typeof cleanup === "function") {
609
+ root.cleanups.push(cleanup);
610
+ }
559
611
  }
612
+ } finally {
613
+ currentRoot = prevRoot;
614
+ cbs.length = 0;
560
615
  }
561
- cbs.length = 0;
562
616
  }
563
617
  function registerRootCleanup(fn) {
564
618
  if (currentRoot) {
@@ -587,8 +641,8 @@ function destroyRoot(root) {
587
641
  globalSuspenseHandlers.delete(root);
588
642
  }
589
643
  }
590
- function createRoot(fn, options) {
591
- const parent = _optionalChain([options, 'optionalAccess', _10 => _10.inherit]) ? currentRoot : void 0;
644
+ function createRoot(fn, options2) {
645
+ const parent = _optionalChain([options2, 'optionalAccess', _10 => _10.inherit]) ? currentRoot : void 0;
592
646
  const root = createRootContext(parent);
593
647
  const prev = pushRoot(root);
594
648
  let value;
@@ -743,8 +797,164 @@ function handleSuspend(token, startRoot) {
743
797
  return false;
744
798
  }
745
799
 
800
+ // src/effect.ts
801
+ function createEffect(fn) {
802
+ let cleanups = [];
803
+ const rootForError = getCurrentRoot();
804
+ const doCleanup = () => {
805
+ runCleanupList(cleanups);
806
+ cleanups = [];
807
+ };
808
+ const run = () => {
809
+ const bucket = [];
810
+ withEffectCleanups(bucket, () => {
811
+ try {
812
+ const maybeCleanup = fn();
813
+ if (typeof maybeCleanup === "function") {
814
+ bucket.push(maybeCleanup);
815
+ }
816
+ } catch (err) {
817
+ if (handleSuspend(err, rootForError)) {
818
+ return;
819
+ }
820
+ if (handleError(err, { source: "effect" }, rootForError)) {
821
+ return;
822
+ }
823
+ throw err;
824
+ }
825
+ });
826
+ cleanups = bucket;
827
+ };
828
+ const disposeEffect = effectWithCleanup(run, doCleanup, rootForError);
829
+ const teardown = () => {
830
+ runCleanupList(cleanups);
831
+ disposeEffect();
832
+ };
833
+ registerRootCleanup(teardown);
834
+ return teardown;
835
+ }
836
+ function createRenderEffect(fn) {
837
+ let cleanup;
838
+ const rootForError = getCurrentRoot();
839
+ const doCleanup = () => {
840
+ if (cleanup) {
841
+ cleanup();
842
+ cleanup = void 0;
843
+ }
844
+ };
845
+ const run = () => {
846
+ try {
847
+ const maybeCleanup = fn();
848
+ if (typeof maybeCleanup === "function") {
849
+ cleanup = maybeCleanup;
850
+ }
851
+ } catch (err) {
852
+ if (handleSuspend(err, rootForError)) {
853
+ return;
854
+ }
855
+ const handled = handleError(err, { source: "effect" }, rootForError);
856
+ if (handled) {
857
+ return;
858
+ }
859
+ throw err;
860
+ }
861
+ };
862
+ const disposeEffect = effectWithCleanup(run, doCleanup, rootForError);
863
+ const teardown = () => {
864
+ if (cleanup) {
865
+ cleanup();
866
+ cleanup = void 0;
867
+ }
868
+ disposeEffect();
869
+ };
870
+ registerRootCleanup(teardown);
871
+ return teardown;
872
+ }
873
+
874
+ // src/hooks.ts
875
+ var isDev4 = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || _optionalChain([process, 'access', _11 => _11.env, 'optionalAccess', _12 => _12.NODE_ENV]) !== "production";
876
+ var ctxStack = [];
877
+ function assertRenderContext(ctx, hookName) {
878
+ if (!ctx.rendering) {
879
+ const message = isDev4 ? `${hookName} can only be used during render execution` : "FICT:E_HOOK_RENDER";
880
+ throw new Error(message);
881
+ }
882
+ }
883
+ function __fictUseContext() {
884
+ if (ctxStack.length === 0) {
885
+ const message = isDev4 ? "Invalid hook call: hooks can only be used while rendering a component. Make sure you are not calling hooks in event handlers or outside of components." : "FICT:E_HOOK_OUTSIDE_RENDER";
886
+ throw new Error(message);
887
+ }
888
+ const ctx = ctxStack[ctxStack.length - 1];
889
+ if (!ctx.rendering) {
890
+ ctx.cursor = 0;
891
+ ctx.rendering = true;
892
+ }
893
+ return ctx;
894
+ }
895
+ function __fictPushContext() {
896
+ const ctx = { slots: [], cursor: 0 };
897
+ ctxStack.push(ctx);
898
+ return ctx;
899
+ }
900
+ function __fictGetCurrentComponentId() {
901
+ return _optionalChain([ctxStack, 'access', _13 => _13[ctxStack.length - 1], 'optionalAccess', _14 => _14.componentId]);
902
+ }
903
+ function __fictPopContext() {
904
+ const ctx = ctxStack.pop();
905
+ if (ctx) ctx.rendering = false;
906
+ }
907
+ function __fictResetContext() {
908
+ ctxStack.length = 0;
909
+ }
910
+ function __fictUseSignal(ctx, initial, optionsOrSlot, slot) {
911
+ assertRenderContext(ctx, "__fictUseSignal");
912
+ const options2 = typeof optionsOrSlot === "number" ? void 0 : optionsOrSlot;
913
+ const resolvedSlot = typeof optionsOrSlot === "number" ? optionsOrSlot : slot;
914
+ const index = _nullishCoalesce(resolvedSlot, () => ( ctx.cursor++));
915
+ if (!ctx.slots[index]) {
916
+ ctx.slots[index] = signal(initial, options2);
917
+ }
918
+ return ctx.slots[index];
919
+ }
920
+ function __fictUseMemo(ctx, fn, optionsOrSlot, slot) {
921
+ assertRenderContext(ctx, "__fictUseMemo");
922
+ const options2 = typeof optionsOrSlot === "number" ? void 0 : optionsOrSlot;
923
+ const resolvedSlot = typeof optionsOrSlot === "number" ? optionsOrSlot : slot;
924
+ const index = _nullishCoalesce(resolvedSlot, () => ( ctx.cursor++));
925
+ if (!ctx.slots[index]) {
926
+ ctx.slots[index] = createMemo(fn, options2);
927
+ }
928
+ return ctx.slots[index];
929
+ }
930
+ function __fictUseEffect(ctx, fn, slot) {
931
+ if (slot !== void 0) {
932
+ if (ctx.slots[slot]) {
933
+ return;
934
+ }
935
+ ctx.slots[slot] = createEffect(fn);
936
+ return;
937
+ }
938
+ assertRenderContext(ctx, "__fictUseEffect");
939
+ const index = ctx.cursor++;
940
+ if (!ctx.slots[index]) {
941
+ ctx.slots[index] = createEffect(fn);
942
+ }
943
+ }
944
+ function __fictRender(ctx, fn) {
945
+ ctxStack.push(ctx);
946
+ ctx.cursor = 0;
947
+ ctx.rendering = true;
948
+ try {
949
+ return fn();
950
+ } finally {
951
+ ctx.rendering = false;
952
+ ctxStack.pop();
953
+ }
954
+ }
955
+
746
956
  // src/signal.ts
747
- var isDev4 = true ? false : typeof process === "undefined" || _optionalChain([process, 'access', _11 => _11.env, 'optionalAccess', _12 => _12.NODE_ENV]) !== "production";
957
+ var isDev5 = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || _optionalChain([process, 'access', _15 => _15.env, 'optionalAccess', _16 => _16.NODE_ENV]) !== "production";
748
958
  var Mutable = 1;
749
959
  var Watching = 2;
750
960
  var Running = 4;
@@ -789,6 +999,7 @@ function link(dep, sub, version) {
789
999
  else sub.deps = newLink;
790
1000
  if (prevSub !== void 0) prevSub.nextSub = newLink;
791
1001
  else dep.subs = newLink;
1002
+ if (isDev5) trackDependencyDevtools(dep, sub);
792
1003
  }
793
1004
  function unlink(lnk, sub = lnk.sub) {
794
1005
  const dep = lnk.dep;
@@ -804,6 +1015,7 @@ function unlink(lnk, sub = lnk.sub) {
804
1015
  else dep.subsTail = prevSub;
805
1016
  if (prevSub !== void 0) prevSub.nextSub = nextSub;
806
1017
  else if ((dep.subs = nextSub) === void 0) unwatched(dep);
1018
+ if (isDev5) untrackDependencyDevtools(dep, sub);
807
1019
  return nextDep;
808
1020
  }
809
1021
  function unwatched(dep) {
@@ -960,6 +1172,11 @@ function shallowPropagate(firstLink) {
960
1172
  function update(node) {
961
1173
  return "getter" in node && node.getter !== void 0 ? updateComputed(node) : updateSignal(node);
962
1174
  }
1175
+ function valuesDiffer(node, prev, next) {
1176
+ if (node.equals === false) return true;
1177
+ if (typeof node.equals === "function") return !node.equals(prev, next);
1178
+ return prev !== next;
1179
+ }
963
1180
  function notify(effect2) {
964
1181
  effect2.flags &= ~Watching;
965
1182
  const effects = [];
@@ -996,7 +1213,7 @@ function updateSignal(s) {
996
1213
  s.flags = Mutable;
997
1214
  const current = s.currentValue;
998
1215
  const pending = s.pendingValue;
999
- if (current !== pending) {
1216
+ if (valuesDiffer(s, current, pending)) {
1000
1217
  s.currentValue = pending;
1001
1218
  return true;
1002
1219
  }
@@ -1014,8 +1231,9 @@ function updateComputed(c) {
1014
1231
  activeSub = prevSub;
1015
1232
  c.flags &= ~Running;
1016
1233
  purgeDeps(c);
1017
- if (oldValue !== newValue) {
1234
+ if (valuesDiffer(c, oldValue, newValue)) {
1018
1235
  c.value = newValue;
1236
+ if (isDev5) updateComputedDevtools(c, newValue);
1019
1237
  return true;
1020
1238
  }
1021
1239
  return false;
@@ -1037,7 +1255,7 @@ function runEffect(e) {
1037
1255
  }
1038
1256
  }
1039
1257
  ++cycle;
1040
- effectRunDevtools(e);
1258
+ if (isDev5) effectRunDevtools(e);
1041
1259
  e.depsTail = void 0;
1042
1260
  e.flags = WatchingRunning;
1043
1261
  const prevSub = activeSub;
@@ -1081,7 +1299,7 @@ function runEffect(e) {
1081
1299
  }
1082
1300
  if (isDirty) {
1083
1301
  ++cycle;
1084
- effectRunDevtools(e);
1302
+ if (isDev5) effectRunDevtools(e);
1085
1303
  e.depsTail = void 0;
1086
1304
  e.flags = WatchingRunning;
1087
1305
  const prevSub = activeSub;
@@ -1130,10 +1348,21 @@ function flush() {
1130
1348
  while (highIndex < highPriorityQueue.length) {
1131
1349
  const e = highPriorityQueue[highIndex];
1132
1350
  if (!beforeEffectRunGuard()) {
1133
- if (highIndex > 0) {
1134
- highPriorityQueue.copyWithin(0, highIndex);
1135
- highPriorityQueue.length -= highIndex;
1351
+ for (let i = 0; i < highPriorityQueue.length; i++) {
1352
+ const queued = highPriorityQueue[i];
1353
+ if (queued && queued.flags !== 0) {
1354
+ queued.flags = Watching;
1355
+ }
1136
1356
  }
1357
+ for (let i = 0; i < lowPriorityQueue.length; i++) {
1358
+ const queued = lowPriorityQueue[i];
1359
+ if (queued && queued.flags !== 0) {
1360
+ queued.flags = Watching;
1361
+ }
1362
+ }
1363
+ highPriorityQueue.length = 0;
1364
+ lowPriorityQueue.length = 0;
1365
+ flushScheduled = false;
1137
1366
  endFlushGuard();
1138
1367
  return;
1139
1368
  }
@@ -1154,10 +1383,21 @@ function flush() {
1154
1383
  }
1155
1384
  const e = lowPriorityQueue[lowIndex];
1156
1385
  if (!beforeEffectRunGuard()) {
1157
- if (lowIndex > 0) {
1158
- lowPriorityQueue.copyWithin(0, lowIndex);
1159
- lowPriorityQueue.length -= lowIndex;
1386
+ for (let i = 0; i < highPriorityQueue.length; i++) {
1387
+ const queued = highPriorityQueue[i];
1388
+ if (queued && queued.flags !== 0) {
1389
+ queued.flags = Watching;
1390
+ }
1160
1391
  }
1392
+ for (let i = 0; i < lowPriorityQueue.length; i++) {
1393
+ const queued = lowPriorityQueue[i];
1394
+ if (queued && queued.flags !== 0) {
1395
+ queued.flags = Watching;
1396
+ }
1397
+ }
1398
+ highPriorityQueue.length = 0;
1399
+ lowPriorityQueue.length = 0;
1400
+ flushScheduled = false;
1161
1401
  endFlushGuard();
1162
1402
  return;
1163
1403
  }
@@ -1167,26 +1407,31 @@ function flush() {
1167
1407
  lowPriorityQueue.length = 0;
1168
1408
  endFlushGuard();
1169
1409
  }
1170
- function signal(initialValue) {
1410
+ function signal(initialValue, options2) {
1171
1411
  const s = {
1172
1412
  currentValue: initialValue,
1173
1413
  pendingValue: initialValue,
1174
1414
  subs: void 0,
1175
1415
  subsTail: void 0,
1176
1416
  flags: Mutable,
1177
- __id: void 0
1417
+ __id: void 0,
1418
+ ..._optionalChain([options2, 'optionalAccess', _17 => _17.equals]) !== void 0 ? { equals: options2.equals } : {},
1419
+ ..._optionalChain([options2, 'optionalAccess', _18 => _18.name]) !== void 0 ? { name: options2.name } : {},
1420
+ ..._optionalChain([options2, 'optionalAccess', _19 => _19.devToolsSource]) !== void 0 ? { devToolsSource: options2.devToolsSource } : {}
1178
1421
  };
1179
- registerSignalDevtools(initialValue, s);
1422
+ if (isDev5) registerSignalDevtools(s);
1180
1423
  const accessor = signalOper.bind(s);
1181
1424
  accessor[SIGNAL_MARKER] = true;
1182
1425
  return accessor;
1183
1426
  }
1184
1427
  function signalOper(value) {
1185
1428
  if (arguments.length > 0) {
1186
- if (this.pendingValue !== value) {
1187
- this.pendingValue = value;
1429
+ const next = value;
1430
+ const prev = this.pendingValue;
1431
+ if (valuesDiffer(this, prev, next)) {
1432
+ this.pendingValue = next;
1188
1433
  this.flags = MutableDirty;
1189
- updateSignalDevtools(this, value);
1434
+ if (isDev5) updateSignalDevtools(this, next);
1190
1435
  const subs = this.subs;
1191
1436
  if (subs !== void 0) {
1192
1437
  propagate(subs);
@@ -1213,7 +1458,7 @@ function signalOper(value) {
1213
1458
  }
1214
1459
  return this.currentValue;
1215
1460
  }
1216
- function computed(getter) {
1461
+ function computed(getter, options2) {
1217
1462
  const c = {
1218
1463
  value: void 0,
1219
1464
  subs: void 0,
@@ -1221,13 +1466,21 @@ function computed(getter) {
1221
1466
  deps: void 0,
1222
1467
  depsTail: void 0,
1223
1468
  flags: 0,
1224
- getter
1469
+ getter,
1470
+ __id: void 0,
1471
+ ..._optionalChain([options2, 'optionalAccess', _20 => _20.equals]) !== void 0 ? { equals: options2.equals } : {},
1472
+ ..._optionalChain([options2, 'optionalAccess', _21 => _21.name]) !== void 0 ? { name: options2.name } : {},
1473
+ ..._optionalChain([options2, 'optionalAccess', _22 => _22.devToolsSource]) !== void 0 ? { devToolsSource: options2.devToolsSource } : {}
1225
1474
  };
1226
- const bound = computedOper.bind(c);
1475
+ if (isDev5) registerComputedDevtools(c);
1476
+ const bound = computedOper.bind(
1477
+ c
1478
+ );
1227
1479
  bound[COMPUTED_MARKER] = true;
1228
1480
  return bound;
1229
1481
  }
1230
1482
  function computedOper() {
1483
+ if (inCleanup) return this.value;
1231
1484
  const flags = this.flags;
1232
1485
  if (flags & Dirty) {
1233
1486
  if (updateComputed(this)) {
@@ -1248,6 +1501,7 @@ function computedOper() {
1248
1501
  const prevSub = setActiveSub(this);
1249
1502
  try {
1250
1503
  this.value = this.getter(void 0);
1504
+ if (isDev5) updateComputedDevtools(this, this.value);
1251
1505
  } finally {
1252
1506
  setActiveSub(prevSub);
1253
1507
  this.flags &= ~Running;
@@ -1270,12 +1524,12 @@ function effect(fn) {
1270
1524
  if (root) {
1271
1525
  e.root = root;
1272
1526
  }
1273
- registerEffectDevtools(e);
1527
+ if (isDev5) registerEffectDevtools(e);
1274
1528
  const prevSub = activeSub;
1275
1529
  if (prevSub !== void 0) link(e, prevSub, 0);
1276
1530
  activeSub = e;
1277
1531
  try {
1278
- effectRunDevtools(e);
1532
+ if (isDev5) effectRunDevtools(e);
1279
1533
  fn();
1280
1534
  } finally {
1281
1535
  activeSub = prevSub;
@@ -1300,12 +1554,12 @@ function effectWithCleanup(fn, cleanupRunner, root) {
1300
1554
  if (resolvedRoot) {
1301
1555
  e.root = resolvedRoot;
1302
1556
  }
1303
- registerEffectDevtools(e);
1557
+ if (isDev5) registerEffectDevtools(e);
1304
1558
  const prevSub = activeSub;
1305
1559
  if (prevSub !== void 0) link(e, prevSub, 0);
1306
1560
  activeSub = e;
1307
1561
  try {
1308
- effectRunDevtools(e);
1562
+ if (isDev5) effectRunDevtools(e);
1309
1563
  fn();
1310
1564
  } finally {
1311
1565
  activeSub = prevSub;
@@ -1365,6 +1619,16 @@ function setActiveSub(sub) {
1365
1619
  activeSub = sub;
1366
1620
  return prev;
1367
1621
  }
1622
+ function __resetReactiveState() {
1623
+ highPriorityQueue.length = 0;
1624
+ lowPriorityQueue.length = 0;
1625
+ batchDepth = 0;
1626
+ activeSub = void 0;
1627
+ flushScheduled = false;
1628
+ isInTransition = false;
1629
+ inCleanup = false;
1630
+ cycle = 0;
1631
+ }
1368
1632
  function untrack(fn) {
1369
1633
  const prev = activeSub;
1370
1634
  activeSub = void 0;
@@ -1394,17 +1658,28 @@ function setTransitionContext(value) {
1394
1658
  var registerSignalDevtools = () => void 0;
1395
1659
  var updateSignalDevtools = () => {
1396
1660
  };
1661
+ var registerComputedDevtools = () => void 0;
1662
+ var updateComputedDevtools = () => {
1663
+ };
1397
1664
  var registerEffectDevtools = () => void 0;
1398
1665
  var effectRunDevtools = () => {
1399
1666
  };
1400
- if (isDev4) {
1401
- let devtoolsSignalId = 0;
1402
- let devtoolsEffectId = 0;
1403
- registerSignalDevtools = (value, node) => {
1667
+ var trackDependencyDevtools = () => {
1668
+ };
1669
+ var untrackDependencyDevtools = () => {
1670
+ };
1671
+ if (isDev5) {
1672
+ let nextDevtoolsId = 0;
1673
+ registerSignalDevtools = (node) => {
1404
1674
  const hook = getDevtoolsHook();
1405
1675
  if (!hook) return void 0;
1406
- const id = ++devtoolsSignalId;
1407
- hook.registerSignal(id, value);
1676
+ const id = ++nextDevtoolsId;
1677
+ const options2 = {};
1678
+ if (node.name !== void 0) options2.name = node.name;
1679
+ if (node.devToolsSource !== void 0) options2.source = node.devToolsSource;
1680
+ const ownerId = __fictGetCurrentComponentId();
1681
+ if (ownerId !== void 0) options2.ownerId = ownerId;
1682
+ hook.registerSignal(id, node.currentValue, options2);
1408
1683
  node.__id = id;
1409
1684
  return id;
1410
1685
  };
@@ -1414,11 +1689,32 @@ if (isDev4) {
1414
1689
  const id = node.__id;
1415
1690
  if (id) hook.updateSignal(id, value);
1416
1691
  };
1692
+ registerComputedDevtools = (node) => {
1693
+ const hook = getDevtoolsHook();
1694
+ if (!hook) return void 0;
1695
+ const id = ++nextDevtoolsId;
1696
+ const options2 = {};
1697
+ if (node.name !== void 0) options2.name = node.name;
1698
+ if (node.devToolsSource !== void 0) options2.source = node.devToolsSource;
1699
+ const ownerId = __fictGetCurrentComponentId();
1700
+ if (ownerId !== void 0) options2.ownerId = ownerId;
1701
+ options2.hasValue = false;
1702
+ hook.registerComputed(id, node.value, options2);
1703
+ node.__id = id;
1704
+ return id;
1705
+ };
1706
+ updateComputedDevtools = (node, value) => {
1707
+ const hook = getDevtoolsHook();
1708
+ if (!hook) return;
1709
+ const id = node.__id;
1710
+ if (id) hook.updateComputed(id, value);
1711
+ };
1417
1712
  registerEffectDevtools = (node) => {
1418
1713
  const hook = getDevtoolsHook();
1419
1714
  if (!hook) return void 0;
1420
- const id = ++devtoolsEffectId;
1421
- hook.registerEffect(id);
1715
+ const id = ++nextDevtoolsId;
1716
+ const ownerId = __fictGetCurrentComponentId();
1717
+ hook.registerEffect(id, ownerId !== void 0 ? { ownerId } : void 0);
1422
1718
  node.__id = id;
1423
1719
  return id;
1424
1720
  };
@@ -1428,6 +1724,20 @@ if (isDev4) {
1428
1724
  const id = node.__id;
1429
1725
  if (id) hook.effectRun(id);
1430
1726
  };
1727
+ trackDependencyDevtools = (dep, sub) => {
1728
+ const hook = getDevtoolsHook();
1729
+ if (!_optionalChain([hook, 'optionalAccess', _23 => _23.trackDependency])) return;
1730
+ const depId = dep.__id;
1731
+ const subId = sub.__id;
1732
+ if (depId && subId) hook.trackDependency(subId, depId);
1733
+ };
1734
+ untrackDependencyDevtools = (dep, sub) => {
1735
+ const hook = getDevtoolsHook();
1736
+ if (!_optionalChain([hook, 'optionalAccess', _24 => _24.untrackDependency])) return;
1737
+ const depId = dep.__id;
1738
+ const subId = sub.__id;
1739
+ if (depId && subId) hook.untrackDependency(subId, depId);
1740
+ };
1431
1741
  }
1432
1742
  function createSelector(source, equalityFn = (a, b) => a === b) {
1433
1743
  let current = source();
@@ -1456,78 +1766,9 @@ function createSelector(source, equalityFn = (a, b) => a === b) {
1456
1766
  };
1457
1767
  }
1458
1768
 
1459
- // src/effect.ts
1460
- function createEffect(fn) {
1461
- let cleanups = [];
1462
- const rootForError = getCurrentRoot();
1463
- const doCleanup = () => {
1464
- runCleanupList(cleanups);
1465
- cleanups = [];
1466
- };
1467
- const run = () => {
1468
- const bucket = [];
1469
- withEffectCleanups(bucket, () => {
1470
- try {
1471
- const maybeCleanup = fn();
1472
- if (typeof maybeCleanup === "function") {
1473
- bucket.push(maybeCleanup);
1474
- }
1475
- } catch (err) {
1476
- if (handleSuspend(err, rootForError)) {
1477
- return;
1478
- }
1479
- if (handleError(err, { source: "effect" }, rootForError)) {
1480
- return;
1481
- }
1482
- throw err;
1483
- }
1484
- });
1485
- cleanups = bucket;
1486
- };
1487
- const disposeEffect = effectWithCleanup(run, doCleanup, rootForError);
1488
- const teardown = () => {
1489
- runCleanupList(cleanups);
1490
- disposeEffect();
1491
- };
1492
- registerRootCleanup(teardown);
1493
- return teardown;
1494
- }
1495
- function createRenderEffect(fn) {
1496
- let cleanup;
1497
- const rootForError = getCurrentRoot();
1498
- const doCleanup = () => {
1499
- if (cleanup) {
1500
- cleanup();
1501
- cleanup = void 0;
1502
- }
1503
- };
1504
- const run = () => {
1505
- try {
1506
- const maybeCleanup = fn();
1507
- if (typeof maybeCleanup === "function") {
1508
- cleanup = maybeCleanup;
1509
- }
1510
- } catch (err) {
1511
- if (handleSuspend(err, rootForError)) {
1512
- return;
1513
- }
1514
- const handled = handleError(err, { source: "effect" }, rootForError);
1515
- if (handled) {
1516
- return;
1517
- }
1518
- throw err;
1519
- }
1520
- };
1521
- const disposeEffect = effectWithCleanup(run, doCleanup, rootForError);
1522
- const teardown = () => {
1523
- if (cleanup) {
1524
- cleanup();
1525
- cleanup = void 0;
1526
- }
1527
- disposeEffect();
1528
- };
1529
- registerRootCleanup(teardown);
1530
- return teardown;
1769
+ // src/memo.ts
1770
+ function createMemo(fn, options2) {
1771
+ return computed(fn, options2);
1531
1772
  }
1532
1773
 
1533
1774
  // src/jsx.ts
@@ -1672,7 +1913,7 @@ function insertNodesBefore(parent, nodes, anchor) {
1672
1913
  }
1673
1914
  function removeNodes(nodes) {
1674
1915
  for (const node of nodes) {
1675
- _optionalChain([node, 'access', _13 => _13.parentNode, 'optionalAccess', _14 => _14.removeChild, 'call', _15 => _15(node)]);
1916
+ _optionalChain([node, 'access', _25 => _25.parentNode, 'optionalAccess', _26 => _26.removeChild, 'call', _27 => _27(node)]);
1676
1917
  }
1677
1918
  }
1678
1919
 
@@ -1723,13 +1964,22 @@ function untrack2(fn) {
1723
1964
  }
1724
1965
 
1725
1966
  // src/binding.ts
1726
- var isDev5 = true ? false : typeof process === "undefined" || _optionalChain([process, 'access', _16 => _16.env, 'optionalAccess', _17 => _17.NODE_ENV]) !== "production";
1967
+ var isDev6 = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || _optionalChain([process, 'access', _28 => _28.env, 'optionalAccess', _29 => _29.NODE_ENV]) !== "production";
1727
1968
  function isReactive(value) {
1728
1969
  if (typeof value !== "function") return false;
1729
1970
  if (isSignal(value) || isComputed(value)) return true;
1730
1971
  if (isEffect(value) || isEffectScope(value)) return false;
1731
1972
  return value.length === 0;
1732
1973
  }
1974
+ function isStrictlyReactive(value) {
1975
+ if (typeof value !== "function") return false;
1976
+ return isSignal(value) || isComputed(value) || isPropGetterFn(value);
1977
+ }
1978
+ var PROP_GETTER_MARKER = Symbol.for("fict:prop-getter");
1979
+ function isPropGetterFn(value) {
1980
+ if (typeof value !== "function") return false;
1981
+ return value[PROP_GETTER_MARKER] === true;
1982
+ }
1733
1983
  function unwrap(value) {
1734
1984
  return isReactive(value) ? value() : value;
1735
1985
  }
@@ -1896,7 +2146,7 @@ function applyStyle(el, value, prev) {
1896
2146
  }
1897
2147
  }
1898
2148
  }
1899
- var isUnitlessStyleProperty = isDev5 ? (prop2) => UnitlessStyles.has(prop2) : (prop2) => prop2 === "opacity" || prop2 === "zIndex";
2149
+ var isUnitlessStyleProperty = isDev6 ? (prop2) => UnitlessStyles.has(prop2) : (prop2) => prop2 === "opacity" || prop2 === "zIndex";
1900
2150
  function createClassBinding(el, value) {
1901
2151
  if (isReactive(value)) {
1902
2152
  let prev = {};
@@ -2094,7 +2344,7 @@ function insert(parent, getValue, markerOrCreateElement, createElementFn) {
2094
2344
  }
2095
2345
  clearCurrentNodes();
2096
2346
  if (ownsMarker) {
2097
- _optionalChain([marker, 'access', _18 => _18.parentNode, 'optionalAccess', _19 => _19.removeChild, 'call', _20 => _20(marker)]);
2347
+ _optionalChain([marker, 'access', _30 => _30.parentNode, 'optionalAccess', _31 => _31.removeChild, 'call', _32 => _32(marker)]);
2098
2348
  }
2099
2349
  };
2100
2350
  }
@@ -2145,7 +2395,7 @@ function createChildBinding(parent, getValue, createElementFn) {
2145
2395
  marker,
2146
2396
  dispose: () => {
2147
2397
  dispose();
2148
- _optionalChain([marker, 'access', _21 => _21.parentNode, 'optionalAccess', _22 => _22.removeChild, 'call', _23 => _23(marker)]);
2398
+ _optionalChain([marker, 'access', _33 => _33.parentNode, 'optionalAccess', _34 => _34.removeChild, 'call', _35 => _35(marker)]);
2149
2399
  }
2150
2400
  };
2151
2401
  }
@@ -2275,15 +2525,15 @@ function addEventListener(node, name, handler, delegate) {
2275
2525
  node.addEventListener(name, handler);
2276
2526
  }
2277
2527
  }
2278
- function bindEvent(el, eventName, handler, options) {
2528
+ function bindEvent(el, eventName, handler, options2) {
2279
2529
  if (handler == null) return () => {
2280
2530
  };
2281
2531
  const rootRef = getCurrentRoot();
2282
- const shouldDelegate = options == null && DelegatedEvents.has(eventName);
2532
+ const shouldDelegate = options2 == null && DelegatedEvents.has(eventName);
2283
2533
  if (shouldDelegate) {
2284
2534
  const key = `$$${eventName}`;
2285
2535
  delegateEvents([eventName]);
2286
- const resolveHandler = isReactive(handler) ? handler : () => handler;
2536
+ const resolveHandler = isStrictlyReactive(handler) ? handler : () => handler;
2287
2537
  el[key] = function(...args) {
2288
2538
  try {
2289
2539
  const fn = resolveHandler();
@@ -2298,7 +2548,7 @@ function bindEvent(el, eventName, handler, options) {
2298
2548
  el[key] = void 0;
2299
2549
  };
2300
2550
  }
2301
- const getHandler = isReactive(handler) ? handler : () => handler;
2551
+ const getHandler = isStrictlyReactive(handler) ? handler : () => handler;
2302
2552
  const wrapped = (event) => {
2303
2553
  try {
2304
2554
  const resolved = getHandler();
@@ -2310,8 +2560,8 @@ function bindEvent(el, eventName, handler, options) {
2310
2560
  throw err;
2311
2561
  }
2312
2562
  };
2313
- el.addEventListener(eventName, wrapped, options);
2314
- const cleanup = () => el.removeEventListener(eventName, wrapped, options);
2563
+ el.addEventListener(eventName, wrapped, options2);
2564
+ const cleanup = () => el.removeEventListener(eventName, wrapped, options2);
2315
2565
  registerRootCleanup(cleanup);
2316
2566
  return cleanup;
2317
2567
  }
@@ -2460,9 +2710,9 @@ function assignProp(node, prop2, value, prev, isSVG, skipRef, props) {
2460
2710
  }
2461
2711
  const isCE = node.nodeName.includes("-") || "is" in props;
2462
2712
  if (!isSVG) {
2463
- const propAlias = isDev5 ? getPropAlias(prop2, node.tagName) : void 0;
2464
- const isProperty = isDev5 ? Properties.has(prop2) : prop2 in node;
2465
- const isChildProp = isDev5 ? ChildProperties.has(prop2) : prop2 === "innerHTML" || prop2 === "textContent" || prop2 === "innerText" || prop2 === "children";
2713
+ const propAlias = isDev6 ? getPropAlias(prop2, node.tagName) : void 0;
2714
+ const isProperty = isDev6 ? Properties.has(prop2) : prop2 in node;
2715
+ const isChildProp = isDev6 ? ChildProperties.has(prop2) : prop2 === "innerHTML" || prop2 === "textContent" || prop2 === "innerText" || prop2 === "children";
2466
2716
  if (propAlias || isProperty || isChildProp || isCE) {
2467
2717
  const propName = propAlias || prop2;
2468
2718
  if (isCE && !isProperty && !isChildProp && !propAlias) {
@@ -2577,8 +2827,8 @@ function createConditional(condition, renderTrue, createElementFn, renderFalse)
2577
2827
  }
2578
2828
  removeNodes(currentNodes);
2579
2829
  currentNodes = [];
2580
- _optionalChain([startMarker, 'access', _24 => _24.parentNode, 'optionalAccess', _25 => _25.removeChild, 'call', _26 => _26(startMarker)]);
2581
- _optionalChain([endMarker, 'access', _27 => _27.parentNode, 'optionalAccess', _28 => _28.removeChild, 'call', _29 => _29(endMarker)]);
2830
+ _optionalChain([startMarker, 'access', _36 => _36.parentNode, 'optionalAccess', _37 => _37.removeChild, 'call', _38 => _38(startMarker)]);
2831
+ _optionalChain([endMarker, 'access', _39 => _39.parentNode, 'optionalAccess', _40 => _40.removeChild, 'call', _41 => _41(endMarker)]);
2582
2832
  }
2583
2833
  };
2584
2834
  }
@@ -2648,7 +2898,7 @@ function createPortal(container, render2, createElementFn) {
2648
2898
  if (currentNodes.length > 0) {
2649
2899
  removeNodes(currentNodes);
2650
2900
  }
2651
- _optionalChain([marker, 'access', _30 => _30.parentNode, 'optionalAccess', _31 => _31.removeChild, 'call', _32 => _32(marker)]);
2901
+ _optionalChain([marker, 'access', _42 => _42.parentNode, 'optionalAccess', _43 => _43.removeChild, 'call', _44 => _44(marker)]);
2652
2902
  };
2653
2903
  if (parentRoot) {
2654
2904
  parentRoot.destroyCallbacks.push(portalDispose);
@@ -2659,79 +2909,8 @@ function createPortal(container, render2, createElementFn) {
2659
2909
  };
2660
2910
  }
2661
2911
 
2662
- // src/memo.ts
2663
- function createMemo(fn) {
2664
- return computed(fn);
2665
- }
2666
-
2667
- // src/hooks.ts
2668
- var isDev6 = true ? false : typeof process === "undefined" || _optionalChain([process, 'access', _33 => _33.env, 'optionalAccess', _34 => _34.NODE_ENV]) !== "production";
2669
- var ctxStack = [];
2670
- function assertRenderContext(ctx, hookName) {
2671
- if (!ctx.rendering) {
2672
- const message = isDev6 ? `${hookName} can only be used during render execution` : "FICT:E_HOOK_RENDER";
2673
- throw new Error(message);
2674
- }
2675
- }
2676
- function __fictUseContext() {
2677
- if (ctxStack.length === 0) {
2678
- const ctx2 = { slots: [], cursor: 0, rendering: true };
2679
- ctxStack.push(ctx2);
2680
- return ctx2;
2681
- }
2682
- const ctx = ctxStack[ctxStack.length - 1];
2683
- ctx.cursor = 0;
2684
- ctx.rendering = true;
2685
- return ctx;
2686
- }
2687
- function __fictPushContext() {
2688
- const ctx = { slots: [], cursor: 0 };
2689
- ctxStack.push(ctx);
2690
- return ctx;
2691
- }
2692
- function __fictPopContext() {
2693
- ctxStack.pop();
2694
- }
2695
- function __fictResetContext() {
2696
- ctxStack.length = 0;
2697
- }
2698
- function __fictUseSignal(ctx, initial, slot) {
2699
- assertRenderContext(ctx, "__fictUseSignal");
2700
- const index = _nullishCoalesce(slot, () => ( ctx.cursor++));
2701
- if (!ctx.slots[index]) {
2702
- ctx.slots[index] = signal(initial);
2703
- }
2704
- return ctx.slots[index];
2705
- }
2706
- function __fictUseMemo(ctx, fn, slot) {
2707
- assertRenderContext(ctx, "__fictUseMemo");
2708
- const index = _nullishCoalesce(slot, () => ( ctx.cursor++));
2709
- if (!ctx.slots[index]) {
2710
- ctx.slots[index] = createMemo(fn);
2711
- }
2712
- return ctx.slots[index];
2713
- }
2714
- function __fictUseEffect(ctx, fn, slot) {
2715
- assertRenderContext(ctx, "__fictUseEffect");
2716
- const index = _nullishCoalesce(slot, () => ( ctx.cursor++));
2717
- if (!ctx.slots[index]) {
2718
- ctx.slots[index] = createEffect(fn);
2719
- }
2720
- }
2721
- function __fictRender(ctx, fn) {
2722
- ctxStack.push(ctx);
2723
- ctx.cursor = 0;
2724
- ctx.rendering = true;
2725
- try {
2726
- return fn();
2727
- } finally {
2728
- ctx.rendering = false;
2729
- ctxStack.pop();
2730
- }
2731
- }
2732
-
2733
2912
  // src/props.ts
2734
- var PROP_GETTER_MARKER = Symbol.for("fict:prop-getter");
2913
+ var PROP_GETTER_MARKER2 = Symbol.for("fict:prop-getter");
2735
2914
  var propGetters = /* @__PURE__ */ new WeakSet();
2736
2915
  var rawToProxy = /* @__PURE__ */ new WeakMap();
2737
2916
  var proxyToRaw = /* @__PURE__ */ new WeakMap();
@@ -2741,7 +2920,7 @@ function __fictProp(getter) {
2741
2920
  if (Object.isExtensible(getter)) {
2742
2921
  try {
2743
2922
  ;
2744
- getter[PROP_GETTER_MARKER] = true;
2923
+ getter[PROP_GETTER_MARKER2] = true;
2745
2924
  } catch (e11) {
2746
2925
  }
2747
2926
  }
@@ -2751,7 +2930,7 @@ function __fictProp(getter) {
2751
2930
  function isPropGetter(value) {
2752
2931
  if (typeof value !== "function") return false;
2753
2932
  const fn = value;
2754
- return propGetters.has(fn) || fn[PROP_GETTER_MARKER] === true;
2933
+ return propGetters.has(fn) || fn[PROP_GETTER_MARKER2] === true;
2755
2934
  }
2756
2935
  function createPropsProxy(props) {
2757
2936
  if (!props || typeof props !== "object") {
@@ -2875,12 +3054,19 @@ function mergeProps(...sources) {
2875
3054
  }
2876
3055
  });
2877
3056
  }
2878
- function prop(getter, options) {
3057
+ function keyed(target, key, options2) {
3058
+ return prop(() => {
3059
+ const resolvedTarget = isPropGetter(target) ? target() : target;
3060
+ const resolvedKey = typeof key === "function" ? key() : key;
3061
+ return resolvedTarget[resolvedKey];
3062
+ }, options2);
3063
+ }
3064
+ function prop(getter, options2) {
2879
3065
  if (isPropGetter(getter)) {
2880
3066
  return getter;
2881
3067
  }
2882
3068
  const fn = getter;
2883
- const unwrap2 = _optionalChain([options, 'optionalAccess', _35 => _35.unwrap]) !== false;
3069
+ const unwrap2 = _optionalChain([options2, 'optionalAccess', _45 => _45.unwrap]) !== false;
2884
3070
  return __fictProp(
2885
3071
  createMemo(() => {
2886
3072
  const value = fn();
@@ -2895,7 +3081,8 @@ function prop(getter, options) {
2895
3081
  // src/dom.ts
2896
3082
  var SVG_NS = "http://www.w3.org/2000/svg";
2897
3083
  var MATHML_NS = "http://www.w3.org/1998/Math/MathML";
2898
- var isDev7 = true ? false : typeof process === "undefined" || _optionalChain([process, 'access', _36 => _36.env, 'optionalAccess', _37 => _37.NODE_ENV]) !== "production";
3084
+ var isDev7 = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process === "undefined" || _optionalChain([process, 'access', _46 => _46.env, 'optionalAccess', _47 => _47.NODE_ENV]) !== "production";
3085
+ var nextComponentId = 1;
2899
3086
  function render(view, container) {
2900
3087
  const root = createRootContext();
2901
3088
  const prev = pushRoot(root);
@@ -2988,9 +3175,27 @@ function createElementWithContext(node, namespace) {
2988
3175
  }
2989
3176
  });
2990
3177
  const props = createPropsProxy(baseProps);
2991
- __fictPushContext();
3178
+ const hook = isDev7 ? getDevtoolsHook() : void 0;
3179
+ const parentId = hook ? __fictGetCurrentComponentId() : void 0;
3180
+ const componentId = hook ? nextComponentId++ : void 0;
3181
+ if (_optionalChain([hook, 'optionalAccess', _48 => _48.registerComponent]) && componentId !== void 0) {
3182
+ hook.registerComponent(componentId, vnode.type.name || "Anonymous", parentId);
3183
+ }
3184
+ const ctx = __fictPushContext();
3185
+ if (componentId !== void 0) {
3186
+ ctx.componentId = componentId;
3187
+ if (parentId !== void 0) {
3188
+ ctx.parentId = parentId;
3189
+ }
3190
+ }
2992
3191
  try {
2993
3192
  const rendered = vnode.type(props);
3193
+ if (hook && componentId !== void 0) {
3194
+ onMount(() => {
3195
+ _optionalChain([hook, 'access', _49 => _49.componentMount, 'optionalCall', _50 => _50(componentId)]);
3196
+ });
3197
+ onCleanup(() => _optionalChain([hook, 'access', _51 => _51.componentUnmount, 'optionalCall', _52 => _52(componentId)]));
3198
+ }
2994
3199
  return createElementWithContext(rendered, namespace);
2995
3200
  } catch (err) {
2996
3201
  if (handleSuspend(err)) {
@@ -3004,7 +3209,7 @@ function createElementWithContext(node, namespace) {
3004
3209
  }
3005
3210
  if (vnode.type === Fragment) {
3006
3211
  const frag = document.createDocumentFragment();
3007
- const children = _optionalChain([vnode, 'access', _38 => _38.props, 'optionalAccess', _39 => _39.children]);
3212
+ const children = _optionalChain([vnode, 'access', _53 => _53.props, 'optionalAccess', _54 => _54.children]);
3008
3213
  appendChildren(frag, children, namespace);
3009
3214
  return frag;
3010
3215
  }
@@ -3014,7 +3219,7 @@ function createElementWithContext(node, namespace) {
3014
3219
  applyProps(el, _nullishCoalesce(vnode.props, () => ( {})), resolvedNamespace === "svg");
3015
3220
  appendChildren(
3016
3221
  el,
3017
- _optionalChain([vnode, 'access', _40 => _40.props, 'optionalAccess', _41 => _41.children]),
3222
+ _optionalChain([vnode, 'access', _55 => _55.props, 'optionalAccess', _56 => _56.children]),
3018
3223
  tagName === "foreignObject" ? null : resolvedNamespace
3019
3224
  );
3020
3225
  return el;
@@ -3022,15 +3227,48 @@ function createElementWithContext(node, namespace) {
3022
3227
  function template(html, isImportNode, isSVG, isMathML) {
3023
3228
  let node = null;
3024
3229
  const create = () => {
3025
- const t = isMathML ? document.createElementNS(MATHML_NS, "template") : document.createElement("template");
3026
- t.innerHTML = html;
3230
+ const t = document.createElement("template");
3027
3231
  if (isSVG) {
3028
- return t.content.firstChild.firstChild;
3232
+ t.innerHTML = `<svg>${html}</svg>`;
3233
+ const wrapper = t.content.firstChild;
3234
+ if (isDev7 && wrapper.childNodes.length !== 1) {
3235
+ console.warn(
3236
+ `[fict] template() received multi-root SVG content (${wrapper.childNodes.length} nodes). Returning a DocumentFragment. This may indicate a compiler bug or invalid JSX structure.`
3237
+ );
3238
+ }
3239
+ if (wrapper.childNodes.length === 1) {
3240
+ return wrapper.firstChild;
3241
+ }
3242
+ const fragment = document.createDocumentFragment();
3243
+ fragment.append(...Array.from(wrapper.childNodes));
3244
+ return fragment;
3029
3245
  }
3030
3246
  if (isMathML) {
3031
- return t.firstChild;
3247
+ t.innerHTML = `<math>${html}</math>`;
3248
+ const wrapper = t.content.firstChild;
3249
+ if (isDev7 && wrapper.childNodes.length !== 1) {
3250
+ console.warn(
3251
+ `[fict] template() received multi-root MathML content (${wrapper.childNodes.length} nodes). Returning a DocumentFragment. This may indicate a compiler bug or invalid JSX structure.`
3252
+ );
3253
+ }
3254
+ if (wrapper.childNodes.length === 1) {
3255
+ return wrapper.firstChild;
3256
+ }
3257
+ const fragment = document.createDocumentFragment();
3258
+ fragment.append(...Array.from(wrapper.childNodes));
3259
+ return fragment;
3032
3260
  }
3033
- return t.content.firstChild;
3261
+ t.innerHTML = html;
3262
+ const content = t.content;
3263
+ if (isDev7 && content.childNodes.length !== 1) {
3264
+ console.warn(
3265
+ `[fict] template() received multi-root content (${content.childNodes.length} nodes). Returning a DocumentFragment. This may indicate a compiler bug or invalid JSX structure.`
3266
+ );
3267
+ }
3268
+ if (content.childNodes.length === 1) {
3269
+ return content.firstChild;
3270
+ }
3271
+ return content;
3034
3272
  };
3035
3273
  const fn = isImportNode ? () => untrack2(() => document.importNode(node || (node = create()), true)) : () => (node || (node = create())).cloneNode(true);
3036
3274
  fn.cloneNode = fn;
@@ -3045,7 +3283,7 @@ function appendChildNode(parent, child, namespace) {
3045
3283
  }
3046
3284
  if (isBindingHandle(child)) {
3047
3285
  appendChildNode(parent, child.marker, namespace);
3048
- _optionalChain([child, 'access', _42 => _42.flush, 'optionalCall', _43 => _43()]);
3286
+ _optionalChain([child, 'access', _57 => _57.flush, 'optionalCall', _58 => _58()]);
3049
3287
  return;
3050
3288
  }
3051
3289
  if (typeof child === "function" && child.length === 0) {
@@ -3394,5 +3632,7 @@ function eventNameFromProp(key) {
3394
3632
 
3395
3633
 
3396
3634
 
3397
- exports.BooleanAttributes = BooleanAttributes; exports.Properties = Properties; exports.ChildProperties = ChildProperties; exports.Aliases = Aliases; exports.getPropAlias = getPropAlias; exports.DelegatedEvents = DelegatedEvents; exports.SVGElements = SVGElements; exports.SVGNamespace = SVGNamespace; exports.UnitlessStyles = UnitlessStyles; exports.getDevtoolsHook = getDevtoolsHook; exports.setCycleProtectionOptions = setCycleProtectionOptions; exports.createRootContext = createRootContext; exports.pushRoot = pushRoot; exports.getCurrentRoot = getCurrentRoot; exports.popRoot = popRoot; exports.onMount = onMount; exports.onDestroy = onDestroy; exports.onCleanup = onCleanup; exports.flushOnMount = flushOnMount; exports.registerRootCleanup = registerRootCleanup; exports.destroyRoot = destroyRoot; exports.createRoot = createRoot; exports.registerErrorHandler = registerErrorHandler; exports.registerSuspenseHandler = registerSuspenseHandler; exports.handleError = handleError; exports.flush = flush; exports.signal = signal; exports.effectScope = effectScope; exports.batch = batch; exports.setActiveSub = setActiveSub; exports.untrack = untrack; exports.createSelector = createSelector; exports.createEffect = createEffect; exports.createRenderEffect = createRenderEffect; exports.Fragment = Fragment; exports.toNodeArray = toNodeArray; exports.insertNodesBefore = insertNodesBefore; exports.removeNodes = removeNodes; exports.startTransition = startTransition; exports.useTransition = useTransition; exports.useDeferredValue = useDeferredValue; exports.batch2 = batch2; exports.untrack2 = untrack2; exports.isReactive = isReactive; exports.unwrap = unwrap; exports.callEventHandler = callEventHandler; exports.createTextBinding = createTextBinding; exports.bindText = bindText; exports.createAttributeBinding = createAttributeBinding; exports.bindAttribute = bindAttribute; exports.bindProperty = bindProperty; exports.createStyleBinding = createStyleBinding; exports.bindStyle = bindStyle; exports.createClassBinding = createClassBinding; exports.bindClass = bindClass; exports.classList = classList; exports.insert = insert; exports.createChildBinding = createChildBinding; exports.delegateEvents = delegateEvents; exports.clearDelegatedEvents = clearDelegatedEvents; exports.addEventListener = addEventListener; exports.bindEvent = bindEvent; exports.bindRef = bindRef; exports.spread = spread; exports.assign = assign; exports.createConditional = createConditional; exports.createShow = createShow; exports.createPortal = createPortal; exports.createMemo = createMemo; exports.__fictUseContext = __fictUseContext; exports.__fictPushContext = __fictPushContext; exports.__fictPopContext = __fictPopContext; exports.__fictResetContext = __fictResetContext; exports.__fictUseSignal = __fictUseSignal; exports.__fictUseMemo = __fictUseMemo; exports.__fictUseEffect = __fictUseEffect; exports.__fictRender = __fictRender; exports.__fictProp = __fictProp; exports.createPropsProxy = createPropsProxy; exports.__fictPropsRest = __fictPropsRest; exports.mergeProps = mergeProps; exports.prop = prop; exports.render = render; exports.createElement = createElement; exports.template = template;
3398
- //# sourceMappingURL=chunk-3U7EBKEU.cjs.map
3635
+
3636
+
3637
+ exports.BooleanAttributes = BooleanAttributes; exports.Properties = Properties; exports.ChildProperties = ChildProperties; exports.Aliases = Aliases; exports.getPropAlias = getPropAlias; exports.DelegatedEvents = DelegatedEvents; exports.SVGElements = SVGElements; exports.SVGNamespace = SVGNamespace; exports.UnitlessStyles = UnitlessStyles; exports.getDevtoolsHook = getDevtoolsHook; exports.setCycleProtectionOptions = setCycleProtectionOptions; exports.createRootContext = createRootContext; exports.pushRoot = pushRoot; exports.getCurrentRoot = getCurrentRoot; exports.popRoot = popRoot; exports.onMount = onMount; exports.onDestroy = onDestroy; exports.onCleanup = onCleanup; exports.flushOnMount = flushOnMount; exports.registerRootCleanup = registerRootCleanup; exports.destroyRoot = destroyRoot; exports.createRoot = createRoot; exports.registerErrorHandler = registerErrorHandler; exports.registerSuspenseHandler = registerSuspenseHandler; exports.handleError = handleError; exports.createMemo = createMemo; exports.__fictUseContext = __fictUseContext; exports.__fictPushContext = __fictPushContext; exports.__fictPopContext = __fictPopContext; exports.__fictResetContext = __fictResetContext; exports.__fictUseSignal = __fictUseSignal; exports.__fictUseMemo = __fictUseMemo; exports.__fictUseEffect = __fictUseEffect; exports.__fictRender = __fictRender; exports.flush = flush; exports.signal = signal; exports.effectScope = effectScope; exports.batch = batch; exports.setActiveSub = setActiveSub; exports.__resetReactiveState = __resetReactiveState; exports.untrack = untrack; exports.createSelector = createSelector; exports.createEffect = createEffect; exports.createRenderEffect = createRenderEffect; exports.Fragment = Fragment; exports.toNodeArray = toNodeArray; exports.insertNodesBefore = insertNodesBefore; exports.removeNodes = removeNodes; exports.startTransition = startTransition; exports.useTransition = useTransition; exports.useDeferredValue = useDeferredValue; exports.batch2 = batch2; exports.untrack2 = untrack2; exports.isReactive = isReactive; exports.unwrap = unwrap; exports.callEventHandler = callEventHandler; exports.createTextBinding = createTextBinding; exports.bindText = bindText; exports.createAttributeBinding = createAttributeBinding; exports.bindAttribute = bindAttribute; exports.bindProperty = bindProperty; exports.createStyleBinding = createStyleBinding; exports.bindStyle = bindStyle; exports.createClassBinding = createClassBinding; exports.bindClass = bindClass; exports.classList = classList; exports.insert = insert; exports.createChildBinding = createChildBinding; exports.delegateEvents = delegateEvents; exports.clearDelegatedEvents = clearDelegatedEvents; exports.addEventListener = addEventListener; exports.bindEvent = bindEvent; exports.bindRef = bindRef; exports.spread = spread; exports.assign = assign; exports.createConditional = createConditional; exports.createShow = createShow; exports.createPortal = createPortal; exports.__fictProp = __fictProp; exports.createPropsProxy = createPropsProxy; exports.__fictPropsRest = __fictPropsRest; exports.mergeProps = mergeProps; exports.keyed = keyed; exports.prop = prop; exports.render = render; exports.createElement = createElement; exports.template = template;
3638
+ //# sourceMappingURL=chunk-ID3WBWNO.cjs.map