@plasmicapp/react-web 1.0.38 → 1.0.39

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.
@@ -2257,7 +2257,6 @@ function ensureStateCell(target, property, path, node) {
2257
2257
  var stateCell = proxyObjToStateCell.get(target);
2258
2258
  if (!(property in stateCell)) {
2259
2259
  stateCell[property] = {
2260
- listeners: [],
2261
2260
  initialValue: UNINITIALIZED,
2262
2261
  path: path,
2263
2262
  node: node,
@@ -2315,7 +2314,6 @@ function subscribeToValtio($$state, statePath, node) {
2315
2314
  function initializeStateValue($$state, initialStateCell, proxyRoot) {
2316
2315
  var _a;
2317
2316
  var initialStateName = initialStateCell.node.getSpec().path;
2318
- var stateAccess = new Set();
2319
2317
  $$state.stateInitializationEnv.visited.add(initialStateName);
2320
2318
  $$state.stateInitializationEnv.stack.push(initialStateName);
2321
2319
  var $state = create$StateProxy($$state, function (internalStateCell) { return ({
@@ -2337,7 +2335,6 @@ function initializeStateValue($$state, initialStateCell, proxyRoot) {
2337
2335
  throw new UnknownError("Internal error: cycle not found");
2338
2336
  }
2339
2337
  var stateCell = getStateCellFrom$StateRoot(proxyRoot, internalStateCell.path);
2340
- stateAccess.add({ stateCell: stateCell });
2341
2338
  if (spec.valueProp) {
2342
2339
  return $$state.env.$props[spec.valueProp];
2343
2340
  }
@@ -2350,14 +2347,6 @@ function initializeStateValue($$state, initialStateCell, proxyRoot) {
2350
2347
  throw new InvalidOperation("Cannot update state values during initialization");
2351
2348
  },
2352
2349
  }); });
2353
- stateAccess.forEach(function (_a) {
2354
- var stateCell = _a.stateCell;
2355
- stateCell.listeners.push(function () {
2356
- var _a;
2357
- var newValue = invokeInitFunc(initialStateCell.node.getSpec().initFunc, __assign({ $state: $state }, ((_a = initialStateCell.overrideEnv) !== null && _a !== void 0 ? _a : $$state.env)));
2358
- set(proxyRoot, initialStateCell.path, newValue);
2359
- });
2360
- });
2361
2350
  var initialValue = invokeInitFunc(initialStateCell.initFunc, __assign({ $state: $state }, ((_a = initialStateCell.overrideEnv) !== null && _a !== void 0 ? _a : $$state.env)));
2362
2351
  var initialSpec = initialStateCell.node.getSpec();
2363
2352
  // Try to clone initialValue. It can fail if it's a PlasmicUndefinedDataProxy
@@ -2542,6 +2531,83 @@ function extractDollarStateParametersBackwardCompatible() {
2542
2531
  function invokeInitFunc(initFunc, env) {
2543
2532
  return initFunc(env);
2544
2533
  }
2534
+ function initFuncEnv($$state, stateCell, $state) {
2535
+ var _a;
2536
+ return __assign({ $state: $state }, ((_a = stateCell.overrideEnv) !== null && _a !== void 0 ? _a : $$state.env));
2537
+ }
2538
+ // Pure check with no effect on the reset budget; the layout scan decides.
2539
+ function initValueChanged($$state, stateCell, $state) {
2540
+ try {
2541
+ return !deepEqual(invokeInitFunc(stateCell.initFunc, initFuncEnv($$state, stateCell, $state)), stateCell.initialValue);
2542
+ }
2543
+ catch (_a) {
2544
+ return false;
2545
+ }
2546
+ }
2547
+ // Bound consecutive resets without a settled evaluation, even on slow renders.
2548
+ var MAX_UNSETTLED_RESETS = 5;
2549
+ function warnUnstableInitFunc(stateCell, reason) {
2550
+ if (stateCell.warnedUnstableInitFunc) {
2551
+ return;
2552
+ }
2553
+ stateCell.warnedUnstableInitFunc = true;
2554
+ console.warn("Plasmic: the initial value of state \"".concat(stateCell.path.join("."), "\" ").concat(reason, ", so it is kept at its current value instead of being reset. To set a random or time-based value, run an interaction from a Side Effect component instead."));
2555
+ }
2556
+ /**
2557
+ * Whether `stateCell` should be reset to what `initFunc` now returns. An
2558
+ * initFunc that returns a new value every time it runs would reset on every
2559
+ * render, and each reset renders again, so the loop never ends. We refuse to
2560
+ * reset in two cases:
2561
+ *
2562
+ * - Two back-to-back calls disagree, indicating an unstable initializer.
2563
+ * - Too many resets occur without a settled evaluation. This also catches
2564
+ * values that are stable within a render but drift between renders.
2565
+ *
2566
+ * This is a circuit breaker, not a proof of determinism: legitimate feedback
2567
+ * chains can also exceed the budget, and unstable functions can return equal
2568
+ * values by chance. Initializers must be pure and deterministic for fixed inputs.
2569
+ *
2570
+ * Rejected probes never change the installed initial value used by preview
2571
+ * reset. A rejected value that repeats on a later render can reopen the budget.
2572
+ */
2573
+ function shouldReInitialize(stateCell, initFunc, env) {
2574
+ var _a;
2575
+ var newInit;
2576
+ var repeats;
2577
+ try {
2578
+ newInit = invokeInitFunc(initFunc, env);
2579
+ if (deepEqual(newInit, stateCell.initialValue)) {
2580
+ stateCell.unsettledResetCount = undefined;
2581
+ stateCell.rejectedInitProbe = undefined;
2582
+ return false;
2583
+ }
2584
+ repeats = deepEqual(invokeInitFunc(initFunc, env), newInit);
2585
+ }
2586
+ catch (_b) {
2587
+ // initFunc can throw, e.g. if it tries to access loading $queries. Swallow here
2588
+ // since we only care whether the init value changed, not error handling.
2589
+ return false;
2590
+ }
2591
+ var reason;
2592
+ if (!repeats) {
2593
+ reason = "is not deterministic";
2594
+ }
2595
+ else {
2596
+ var rejectedInitProbe = stateCell.rejectedInitProbe;
2597
+ var reopened = rejectedInitProbe && deepEqual(newInit, rejectedInitProbe.value);
2598
+ stateCell.unsettledResetCount = reopened
2599
+ ? 1
2600
+ : ((_a = stateCell.unsettledResetCount) !== null && _a !== void 0 ? _a : 0) + 1;
2601
+ if (stateCell.unsettledResetCount > MAX_UNSETTLED_RESETS) {
2602
+ reason = "keeps changing";
2603
+ }
2604
+ }
2605
+ stateCell.rejectedInitProbe = reason ? { value: newInit } : undefined;
2606
+ if (reason) {
2607
+ warnUnstableInitFunc(stateCell, reason);
2608
+ }
2609
+ return !reason;
2610
+ }
2545
2611
  function useDollarState(specs) {
2546
2612
  var rest = [];
2547
2613
  for (var _i = 1; _i < arguments.length; _i++) {
@@ -2549,6 +2615,10 @@ function useDollarState(specs) {
2549
2615
  }
2550
2616
  var _a = extractDollarStateParametersBackwardCompatible.apply(void 0, __spreadArray([], __read(rest), false)), env = _a.env, opts = _a.opts;
2551
2617
  var _b = __read(React__default.useState(), 2), setState = _b[1];
2618
+ // Set for the whole render pass and cleared by the layout effect, which applies
2619
+ // registrations. One that arrives outside a render must schedule a render to be applied.
2620
+ var rendering = React__default.useRef(false);
2621
+ rendering.current = true;
2552
2622
  var mountedRef = React__default.useRef(false);
2553
2623
  var isMounted = React__default.useCallback(function () { return mountedRef.current; }, []);
2554
2624
  React__default.useEffect(function () {
@@ -2573,14 +2643,11 @@ function useDollarState(specs) {
2573
2643
  specTreeLeaves: getSpecTreeLeaves(rootSpecTree),
2574
2644
  stateValues: proxy({}),
2575
2645
  env: envFieldsAreNonNill(env),
2576
- specs: [],
2577
- registrationsQueue: [],
2578
2646
  stateInitializationEnv: { stack: [], visited: new Set() },
2579
2647
  initializedLeafPaths: new Set(),
2580
2648
  };
2581
2649
  })()).current;
2582
2650
  $$state.env = envFieldsAreNonNill(env);
2583
- $$state.specs = specs;
2584
2651
  var create$State = React__default.useCallback(function () {
2585
2652
  var $state = Object.assign(create$StateProxy($$state, function (stateCell) {
2586
2653
  var spec = stateCell.node.getSpec();
@@ -2606,24 +2673,21 @@ function useDollarState(specs) {
2606
2673
  },
2607
2674
  };
2608
2675
  }), __assign({ registerInitFunc: function (pathStr, f, repetitionIndex, overrideEnv) {
2609
- var _a = findStateCell($$state.rootSpecTree, pathStr, repetitionIndex), node = _a.node, realPath = _a.realPath;
2676
+ var realPath = findStateCell($$state.rootSpecTree, pathStr, repetitionIndex).realPath;
2610
2677
  var stateCell = getStateCellFrom$StateRoot($state, realPath);
2611
- var innerEnv = overrideEnv
2678
+ // The first initializer always applies, even if unstable, like the
2679
+ // lazy initialization of a spec initFunc.
2680
+ stateCell.pendingInit || (stateCell.pendingInit = !stateCell.initFunc);
2681
+ stateCell.initFunc = f;
2682
+ stateCell.overrideEnv = overrideEnv
2612
2683
  ? envFieldsAreNonNill(overrideEnv)
2613
- : $$state.env;
2614
- if (!deepEqual(stateCell.initialValue, f(__assign({ $state: $state }, innerEnv)))) {
2615
- $$state.registrationsQueue.push({
2616
- node: node,
2617
- path: realPath,
2618
- f: f,
2619
- overrideEnv: overrideEnv
2620
- ? envFieldsAreNonNill(overrideEnv)
2621
- : undefined,
2622
- });
2623
- if (!pendingUpdate.current) {
2624
- pendingUpdate.current = true;
2625
- forceUpdate();
2626
- }
2684
+ : undefined;
2685
+ if (!rendering.current &&
2686
+ !pendingUpdate.current &&
2687
+ (stateCell.pendingInit ||
2688
+ initValueChanged($$state, stateCell, $state))) {
2689
+ pendingUpdate.current = true;
2690
+ forceUpdate();
2627
2691
  }
2628
2692
  } }, ((opts === null || opts === void 0 ? void 0 : opts.inCanvas)
2629
2693
  ? {
@@ -2644,6 +2708,9 @@ function useDollarState(specs) {
2644
2708
  }
2645
2709
  stateCell.initFunc = newSpec.initFunc;
2646
2710
  stateCell.initFuncHash = (_b = newSpec.initFuncHash) !== null && _b !== void 0 ? _b : "";
2711
+ stateCell.unsettledResetCount = undefined;
2712
+ stateCell.warnedUnstableInitFunc = undefined;
2713
+ stateCell.rejectedInitProbe = undefined;
2647
2714
  var init = spec.valueProp
2648
2715
  ? $$state.env.$props[spec.valueProp]
2649
2716
  : spec.initFunc
@@ -2679,47 +2746,24 @@ function useDollarState(specs) {
2679
2746
  });
2680
2747
  }
2681
2748
  }
2682
- var reInitializeState = function (stateCell) {
2683
- var _a, _b;
2684
- var newInit = initializeStateValue($$state, stateCell, $state);
2685
- var spec = stateCell.node.getSpec();
2686
- if (spec.onChangeProp) {
2687
- (_b = (_a = $$state.env.$props)[spec.onChangeProp]) === null || _b === void 0 ? void 0 : _b.call(_a, newInit);
2688
- }
2689
- };
2690
2749
  useIsomorphicLayoutEffect(function () {
2691
- // For each spec with an initFunc, evaluate it and see if
2692
- // the init value has changed. If so, reset its state.
2693
- var resetSpecs = [];
2694
- getStateCells($state, $$state.rootSpecTree).forEach(function (stateCell) {
2695
- var _a;
2696
- if (stateCell.initFunc) {
2697
- try {
2698
- var newInit = invokeInitFunc(stateCell.initFunc, __assign({ $state: $state }, ((_a = stateCell.overrideEnv) !== null && _a !== void 0 ? _a : envFieldsAreNonNill(env))));
2699
- if (!deepEqual(newInit, stateCell.initialValue)) {
2700
- resetSpecs.push({ stateCell: stateCell });
2701
- }
2702
- }
2703
- catch (_b) {
2704
- // Exception may be thrown from initFunc -- for example, if it tries to access $queries
2705
- // that are still loading. We swallow those here, since we're only interested in
2706
- // checking if the init value has changed, not in handling these errors.
2707
- }
2708
- }
2750
+ rendering.current = false;
2751
+ // Scan every cell before resetting any, so each initFunc sees the same
2752
+ // pre-reset state.
2753
+ var resetCells = getStateCells($state, $$state.rootSpecTree).filter(function (stateCell) {
2754
+ return stateCell.pendingInit ||
2755
+ (stateCell.initFunc &&
2756
+ shouldReInitialize(stateCell, stateCell.initFunc, initFuncEnv($$state, stateCell, $state)));
2709
2757
  });
2710
- resetSpecs.forEach(function (_a) {
2711
- var stateCell = _a.stateCell;
2712
- reInitializeState(stateCell);
2758
+ resetCells.forEach(function (stateCell) {
2759
+ var _a, _b;
2760
+ stateCell.pendingInit = undefined;
2761
+ var newInit = initializeStateValue($$state, stateCell, $state);
2762
+ var spec = stateCell.node.getSpec();
2763
+ if (spec.onChangeProp) {
2764
+ (_b = (_a = $$state.env.$props)[spec.onChangeProp]) === null || _b === void 0 ? void 0 : _b.call(_a, newInit);
2765
+ }
2713
2766
  });
2714
- }, [env.$props, $state, $$state, reInitializeState]);
2715
- useIsomorphicLayoutEffect(function () {
2716
- while ($$state.registrationsQueue.length) {
2717
- var _a = $$state.registrationsQueue.shift(), path = _a.path, f = _a.f, overrideEnv = _a.overrideEnv;
2718
- var stateCell = getStateCellFrom$StateRoot($state, path);
2719
- stateCell.initFunc = f;
2720
- stateCell.overrideEnv = overrideEnv;
2721
- reInitializeState(stateCell);
2722
- }
2723
2767
  });
2724
2768
  // immediately initialize exposed non-private states
2725
2769
  useIsomorphicLayoutEffect(function () {
@@ -2830,11 +2874,15 @@ function getStateCells($state, root) {
2830
2874
  try {
2831
2875
  for (var _c = __values(root.edges().entries()), _d = _c.next(); !_d.done; _d = _c.next()) {
2832
2876
  var _e = __read(_d.value, 2), key = _e[0], child = _e[1];
2833
- if (typeof key === "string" && key in $state) {
2877
+ if (typeof key !== "string") {
2878
+ continue;
2879
+ }
2880
+ // A leaf cell can exist without a local value, e.g. a valueProp state.
2881
+ if (key in stateCell) {
2882
+ stateCells.push(stateCell[key]);
2883
+ }
2884
+ else if (key in $state) {
2834
2885
  stateCells.push.apply(stateCells, __spreadArray([], __read(getStateCells($state[key], child)), false));
2835
- if (key in stateCell) {
2836
- stateCells.push(stateCell[key]);
2837
- }
2838
2886
  }
2839
2887
  }
2840
2888
  }
@@ -2883,6 +2931,16 @@ function getCurrentInitialValue(obj, path) {
2883
2931
  }
2884
2932
  return (_a = tryGetStateCellFrom$StateRoot(obj, path)) === null || _a === void 0 ? void 0 : _a.initialValue;
2885
2933
  }
2934
+ /** Whether the runtime guard has detected instability in this initializer.
2935
+ * Canvas edits clear the diagnostic when the initializer hash changes.
2936
+ */
2937
+ function hasUnstableStateInitializer(obj, path) {
2938
+ var _a;
2939
+ if (!isPlasmicStateProxy(obj)) {
2940
+ return false;
2941
+ }
2942
+ return !!((_a = tryGetStateCellFrom$StateRoot(obj, path)) === null || _a === void 0 ? void 0 : _a.warnedUnstableInitFunc);
2943
+ }
2886
2944
  function resetToInitialValue(obj, path) {
2887
2945
  var stateCell = tryGetStateCellFrom$StateRoot(obj, path);
2888
2946
  if (stateCell) {
@@ -4310,5 +4368,5 @@ function useTriggeredOverlay(plasmicClass, props, config, outerRef, isDismissabl
4310
4368
  };
4311
4369
  }
4312
4370
 
4313
- export { DropdownMenu, PlasmicHead, PlasmicIcon, PlasmicImg, PlasmicLink, PlasmicPageGuard, PlasmicRootProvider, PlasmicSlot, SelectContext, Stack, Trans, TriggeredOverlayContext, classNames, createPlasmicElementProxy, createStyleTokensProvider, createUseGlobalVariants, createUseScreenVariants, createUseStyleTokens, deriveRenderOpts, ensureGlobalVariants, genTranslatableString, generateOnMutateForSpec, generateStateOnChangeProp, generateStateOnChangePropForCodeComponents, generateStateValueProp, getCurrentInitialValue, getDataProps, getStateCellsInPlasmicProxy, getStateSpecInPlasmicProxy, hasVariant, initializeCodeComponentStates, initializePlasmicStates, is$StateProxy, isPlasmicStateProxy, makeFragment, mergeVariantsWithStates, omit, pick, plasmicHeadMeta, renderPlasmicSlot, resetToInitialValue, set, setPlumeStrictMode, useButton, useCheckbox, useDollarState, useIsSSR, useMenu, useMenuButton, useMenuGroup, useMenuItem, usePlasmicTranslator, useSelect, useSelectOption, useSelectOptionGroup, useSwitch, useTextInput, useTrigger, useTriggeredOverlay, withPlasmicPageGuard, wrapWithClassName };
4371
+ export { DropdownMenu, PlasmicHead, PlasmicIcon, PlasmicImg, PlasmicLink, PlasmicPageGuard, PlasmicRootProvider, PlasmicSlot, SelectContext, Stack, Trans, TriggeredOverlayContext, classNames, createPlasmicElementProxy, createStyleTokensProvider, createUseGlobalVariants, createUseScreenVariants, createUseStyleTokens, deriveRenderOpts, ensureGlobalVariants, genTranslatableString, generateOnMutateForSpec, generateStateOnChangeProp, generateStateOnChangePropForCodeComponents, generateStateValueProp, getCurrentInitialValue, getDataProps, getStateCellsInPlasmicProxy, getStateSpecInPlasmicProxy, hasUnstableStateInitializer, hasVariant, initializeCodeComponentStates, initializePlasmicStates, is$StateProxy, isPlasmicStateProxy, makeFragment, mergeVariantsWithStates, omit, pick, plasmicHeadMeta, renderPlasmicSlot, resetToInitialValue, set, setPlumeStrictMode, useButton, useCheckbox, useDollarState, useIsSSR, useMenu, useMenuButton, useMenuGroup, useMenuItem, usePlasmicTranslator, useSelect, useSelectOption, useSelectOptionGroup, useSwitch, useTextInput, useTrigger, useTriggeredOverlay, withPlasmicPageGuard, wrapWithClassName };
4314
4372
  //# sourceMappingURL=react-web.esm.js.map