@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.
package/dist/all.d.ts CHANGED
@@ -13594,6 +13594,10 @@ declare function getStateSpecInPlasmicProxy(obj: any, path: ObjectPath): {
13594
13594
  isImplicitStateArray: boolean;
13595
13595
  } | undefined;
13596
13596
  declare function getCurrentInitialValue(obj: any, path: ObjectPath): any;
13597
+ /** Whether the runtime guard has detected instability in this initializer.
13598
+ * Canvas edits clear the diagnostic when the initializer hash changes.
13599
+ */
13600
+ declare function hasUnstableStateInitializer(obj: any, path: ObjectPath): boolean;
13597
13601
  declare function resetToInitialValue(obj: any, path: ObjectPath): void;
13598
13602
  /**
13599
13603
  * Forked from https://github.com/lukeed/dset
@@ -15387,4 +15391,4 @@ interface TriggeredOverlayContextValue {
15387
15391
  }
15388
15392
  declare const TriggeredOverlayContext: React$1.Context<TriggeredOverlayContextValue | undefined>;
15389
15393
 
15390
- export { $State, $StateSpec, BaseButtonProps, BaseMenuButtonProps, BaseMenuGroupProps, BaseMenuItemProps, BaseMenuProps, BaseSelectOptionGroupProps, BaseSelectOptionProps, BaseSelectProps, BaseTextInputProps, BaseTriggeredOverlayProps, ButtonRef, CheckboxProps, CheckboxRef, CheckboxRefValue, DropdownMenu, Flex, HTMLElementRefOf, HtmlAnchorOnlyProps, HtmlButtonOnlyProps, InitFunc, MenuButtonRef, MenuButtonRefValue, MenuRef, MenuRefValue, MultiChoiceArg, ParamsRecord, PlasmicDataSourceContextProvider, PlasmicHead, PlasmicIcon, PlasmicImg, PlasmicLink, PlasmicPageGuard, PlasmicPageProps, PlasmicRootProvider, PlasmicSlot, PlasmicTranslator, PlumeButtonProps, PlumeTextInputProps, SelectContext, SelectOptionRef, SelectRef, SelectRefValue, SingleBooleanChoiceArg, SingleChoiceArg, Stack, StrictProps, SwitchProps, SwitchRef, SwitchRefValue, TextInputRef, TextInputRefValue, Trans, TriggeredOverlayConfig, TriggeredOverlayContext, TriggeredOverlayRef, classNames, createPlasmicElementProxy, createStyleTokensProvider, createUseGlobalVariants, createUseScreenVariants, createUseStyleTokens, deriveRenderOpts, ensureGlobalVariants, genTranslatableString, generateOnMutateForSpec, generateStateOnChangeProp, generateStateOnChangePropForCodeComponents, generateStateValueProp, dlv as get, getCurrentInitialValue, getDataProps, getStateCellsInPlasmicProxy, getStateSpecInPlasmicProxy, hasVariant, initializeCodeComponentStates, initializePlasmicStates, is$StateProxy, isPlasmicStateProxy, makeFragment, mergeVariantsWithStates, omit, pick, plasmicHeadMeta, renderPlasmicSlot, resetToInitialValue, set, setPlumeStrictMode, useButton, useCheckbox, useCurrentUser, useDollarState, useIsSSR, useMenu, useMenuButton, useMenuGroup, useMenuItem, usePlasmicTranslator, useSelect, useSelectOption, useSelectOptionGroup, useSwitch, useTextInput, useTrigger, useTriggeredOverlay, withPlasmicPageGuard, wrapWithClassName };
15394
+ export { $State, $StateSpec, BaseButtonProps, BaseMenuButtonProps, BaseMenuGroupProps, BaseMenuItemProps, BaseMenuProps, BaseSelectOptionGroupProps, BaseSelectOptionProps, BaseSelectProps, BaseTextInputProps, BaseTriggeredOverlayProps, ButtonRef, CheckboxProps, CheckboxRef, CheckboxRefValue, DropdownMenu, Flex, HTMLElementRefOf, HtmlAnchorOnlyProps, HtmlButtonOnlyProps, InitFunc, MenuButtonRef, MenuButtonRefValue, MenuRef, MenuRefValue, MultiChoiceArg, ParamsRecord, PlasmicDataSourceContextProvider, PlasmicHead, PlasmicIcon, PlasmicImg, PlasmicLink, PlasmicPageGuard, PlasmicPageProps, PlasmicRootProvider, PlasmicSlot, PlasmicTranslator, PlumeButtonProps, PlumeTextInputProps, SelectContext, SelectOptionRef, SelectRef, SelectRefValue, SingleBooleanChoiceArg, SingleChoiceArg, Stack, StrictProps, SwitchProps, SwitchRef, SwitchRefValue, TextInputRef, TextInputRefValue, Trans, TriggeredOverlayConfig, TriggeredOverlayContext, TriggeredOverlayRef, classNames, createPlasmicElementProxy, createStyleTokensProvider, createUseGlobalVariants, createUseScreenVariants, createUseStyleTokens, deriveRenderOpts, ensureGlobalVariants, genTranslatableString, generateOnMutateForSpec, generateStateOnChangeProp, generateStateOnChangePropForCodeComponents, generateStateValueProp, dlv as get, getCurrentInitialValue, getDataProps, getStateCellsInPlasmicProxy, getStateSpecInPlasmicProxy, hasUnstableStateInitializer, hasVariant, initializeCodeComponentStates, initializePlasmicStates, is$StateProxy, isPlasmicStateProxy, makeFragment, mergeVariantsWithStates, omit, pick, plasmicHeadMeta, renderPlasmicSlot, resetToInitialValue, set, setPlumeStrictMode, useButton, useCheckbox, useCurrentUser, useDollarState, useIsSSR, useMenu, useMenuButton, useMenuGroup, useMenuItem, usePlasmicTranslator, useSelect, useSelectOption, useSelectOptionGroup, useSwitch, useTextInput, useTrigger, useTriggeredOverlay, withPlasmicPageGuard, wrapWithClassName };
package/dist/index.cjs.js CHANGED
@@ -2276,7 +2276,6 @@ function ensureStateCell(target, property, path, node) {
2276
2276
  var stateCell = proxyObjToStateCell.get(target);
2277
2277
  if (!(property in stateCell)) {
2278
2278
  stateCell[property] = {
2279
- listeners: [],
2280
2279
  initialValue: UNINITIALIZED,
2281
2280
  path: path,
2282
2281
  node: node,
@@ -2334,7 +2333,6 @@ function subscribeToValtio($$state, statePath, node) {
2334
2333
  function initializeStateValue($$state, initialStateCell, proxyRoot) {
2335
2334
  var _a;
2336
2335
  var initialStateName = initialStateCell.node.getSpec().path;
2337
- var stateAccess = new Set();
2338
2336
  $$state.stateInitializationEnv.visited.add(initialStateName);
2339
2337
  $$state.stateInitializationEnv.stack.push(initialStateName);
2340
2338
  var $state = create$StateProxy($$state, function (internalStateCell) { return ({
@@ -2356,7 +2354,6 @@ function initializeStateValue($$state, initialStateCell, proxyRoot) {
2356
2354
  throw new UnknownError("Internal error: cycle not found");
2357
2355
  }
2358
2356
  var stateCell = getStateCellFrom$StateRoot(proxyRoot, internalStateCell.path);
2359
- stateAccess.add({ stateCell: stateCell });
2360
2357
  if (spec.valueProp) {
2361
2358
  return $$state.env.$props[spec.valueProp];
2362
2359
  }
@@ -2369,14 +2366,6 @@ function initializeStateValue($$state, initialStateCell, proxyRoot) {
2369
2366
  throw new InvalidOperation("Cannot update state values during initialization");
2370
2367
  },
2371
2368
  }); });
2372
- stateAccess.forEach(function (_a) {
2373
- var stateCell = _a.stateCell;
2374
- stateCell.listeners.push(function () {
2375
- var _a;
2376
- var newValue = invokeInitFunc(initialStateCell.node.getSpec().initFunc, __assign({ $state: $state }, ((_a = initialStateCell.overrideEnv) !== null && _a !== void 0 ? _a : $$state.env)));
2377
- set(proxyRoot, initialStateCell.path, newValue);
2378
- });
2379
- });
2380
2369
  var initialValue = invokeInitFunc(initialStateCell.initFunc, __assign({ $state: $state }, ((_a = initialStateCell.overrideEnv) !== null && _a !== void 0 ? _a : $$state.env)));
2381
2370
  var initialSpec = initialStateCell.node.getSpec();
2382
2371
  // Try to clone initialValue. It can fail if it's a PlasmicUndefinedDataProxy
@@ -2561,6 +2550,83 @@ function extractDollarStateParametersBackwardCompatible() {
2561
2550
  function invokeInitFunc(initFunc, env) {
2562
2551
  return initFunc(env);
2563
2552
  }
2553
+ function initFuncEnv($$state, stateCell, $state) {
2554
+ var _a;
2555
+ return __assign({ $state: $state }, ((_a = stateCell.overrideEnv) !== null && _a !== void 0 ? _a : $$state.env));
2556
+ }
2557
+ // Pure check with no effect on the reset budget; the layout scan decides.
2558
+ function initValueChanged($$state, stateCell, $state) {
2559
+ try {
2560
+ return !deepEqual(invokeInitFunc(stateCell.initFunc, initFuncEnv($$state, stateCell, $state)), stateCell.initialValue);
2561
+ }
2562
+ catch (_a) {
2563
+ return false;
2564
+ }
2565
+ }
2566
+ // Bound consecutive resets without a settled evaluation, even on slow renders.
2567
+ var MAX_UNSETTLED_RESETS = 5;
2568
+ function warnUnstableInitFunc(stateCell, reason) {
2569
+ if (stateCell.warnedUnstableInitFunc) {
2570
+ return;
2571
+ }
2572
+ stateCell.warnedUnstableInitFunc = true;
2573
+ 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."));
2574
+ }
2575
+ /**
2576
+ * Whether `stateCell` should be reset to what `initFunc` now returns. An
2577
+ * initFunc that returns a new value every time it runs would reset on every
2578
+ * render, and each reset renders again, so the loop never ends. We refuse to
2579
+ * reset in two cases:
2580
+ *
2581
+ * - Two back-to-back calls disagree, indicating an unstable initializer.
2582
+ * - Too many resets occur without a settled evaluation. This also catches
2583
+ * values that are stable within a render but drift between renders.
2584
+ *
2585
+ * This is a circuit breaker, not a proof of determinism: legitimate feedback
2586
+ * chains can also exceed the budget, and unstable functions can return equal
2587
+ * values by chance. Initializers must be pure and deterministic for fixed inputs.
2588
+ *
2589
+ * Rejected probes never change the installed initial value used by preview
2590
+ * reset. A rejected value that repeats on a later render can reopen the budget.
2591
+ */
2592
+ function shouldReInitialize(stateCell, initFunc, env) {
2593
+ var _a;
2594
+ var newInit;
2595
+ var repeats;
2596
+ try {
2597
+ newInit = invokeInitFunc(initFunc, env);
2598
+ if (deepEqual(newInit, stateCell.initialValue)) {
2599
+ stateCell.unsettledResetCount = undefined;
2600
+ stateCell.rejectedInitProbe = undefined;
2601
+ return false;
2602
+ }
2603
+ repeats = deepEqual(invokeInitFunc(initFunc, env), newInit);
2604
+ }
2605
+ catch (_b) {
2606
+ // initFunc can throw, e.g. if it tries to access loading $queries. Swallow here
2607
+ // since we only care whether the init value changed, not error handling.
2608
+ return false;
2609
+ }
2610
+ var reason;
2611
+ if (!repeats) {
2612
+ reason = "is not deterministic";
2613
+ }
2614
+ else {
2615
+ var rejectedInitProbe = stateCell.rejectedInitProbe;
2616
+ var reopened = rejectedInitProbe && deepEqual(newInit, rejectedInitProbe.value);
2617
+ stateCell.unsettledResetCount = reopened
2618
+ ? 1
2619
+ : ((_a = stateCell.unsettledResetCount) !== null && _a !== void 0 ? _a : 0) + 1;
2620
+ if (stateCell.unsettledResetCount > MAX_UNSETTLED_RESETS) {
2621
+ reason = "keeps changing";
2622
+ }
2623
+ }
2624
+ stateCell.rejectedInitProbe = reason ? { value: newInit } : undefined;
2625
+ if (reason) {
2626
+ warnUnstableInitFunc(stateCell, reason);
2627
+ }
2628
+ return !reason;
2629
+ }
2564
2630
  function useDollarState(specs) {
2565
2631
  var rest = [];
2566
2632
  for (var _i = 1; _i < arguments.length; _i++) {
@@ -2568,6 +2634,10 @@ function useDollarState(specs) {
2568
2634
  }
2569
2635
  var _a = extractDollarStateParametersBackwardCompatible.apply(void 0, __spreadArray([], __read(rest), false)), env = _a.env, opts = _a.opts;
2570
2636
  var _b = __read(React.useState(), 2), setState = _b[1];
2637
+ // Set for the whole render pass and cleared by the layout effect, which applies
2638
+ // registrations. One that arrives outside a render must schedule a render to be applied.
2639
+ var rendering = React.useRef(false);
2640
+ rendering.current = true;
2571
2641
  var mountedRef = React.useRef(false);
2572
2642
  var isMounted = React.useCallback(function () { return mountedRef.current; }, []);
2573
2643
  React.useEffect(function () {
@@ -2592,14 +2662,11 @@ function useDollarState(specs) {
2592
2662
  specTreeLeaves: getSpecTreeLeaves(rootSpecTree),
2593
2663
  stateValues: valtio.proxy({}),
2594
2664
  env: envFieldsAreNonNill(env),
2595
- specs: [],
2596
- registrationsQueue: [],
2597
2665
  stateInitializationEnv: { stack: [], visited: new Set() },
2598
2666
  initializedLeafPaths: new Set(),
2599
2667
  };
2600
2668
  })()).current;
2601
2669
  $$state.env = envFieldsAreNonNill(env);
2602
- $$state.specs = specs;
2603
2670
  var create$State = React.useCallback(function () {
2604
2671
  var $state = Object.assign(create$StateProxy($$state, function (stateCell) {
2605
2672
  var spec = stateCell.node.getSpec();
@@ -2625,24 +2692,21 @@ function useDollarState(specs) {
2625
2692
  },
2626
2693
  };
2627
2694
  }), __assign({ registerInitFunc: function (pathStr, f, repetitionIndex, overrideEnv) {
2628
- var _a = findStateCell($$state.rootSpecTree, pathStr, repetitionIndex), node = _a.node, realPath = _a.realPath;
2695
+ var realPath = findStateCell($$state.rootSpecTree, pathStr, repetitionIndex).realPath;
2629
2696
  var stateCell = getStateCellFrom$StateRoot($state, realPath);
2630
- var innerEnv = overrideEnv
2697
+ // The first initializer always applies, even if unstable, like the
2698
+ // lazy initialization of a spec initFunc.
2699
+ stateCell.pendingInit || (stateCell.pendingInit = !stateCell.initFunc);
2700
+ stateCell.initFunc = f;
2701
+ stateCell.overrideEnv = overrideEnv
2631
2702
  ? envFieldsAreNonNill(overrideEnv)
2632
- : $$state.env;
2633
- if (!deepEqual(stateCell.initialValue, f(__assign({ $state: $state }, innerEnv)))) {
2634
- $$state.registrationsQueue.push({
2635
- node: node,
2636
- path: realPath,
2637
- f: f,
2638
- overrideEnv: overrideEnv
2639
- ? envFieldsAreNonNill(overrideEnv)
2640
- : undefined,
2641
- });
2642
- if (!pendingUpdate.current) {
2643
- pendingUpdate.current = true;
2644
- forceUpdate();
2645
- }
2703
+ : undefined;
2704
+ if (!rendering.current &&
2705
+ !pendingUpdate.current &&
2706
+ (stateCell.pendingInit ||
2707
+ initValueChanged($$state, stateCell, $state))) {
2708
+ pendingUpdate.current = true;
2709
+ forceUpdate();
2646
2710
  }
2647
2711
  } }, ((opts === null || opts === void 0 ? void 0 : opts.inCanvas)
2648
2712
  ? {
@@ -2663,6 +2727,9 @@ function useDollarState(specs) {
2663
2727
  }
2664
2728
  stateCell.initFunc = newSpec.initFunc;
2665
2729
  stateCell.initFuncHash = (_b = newSpec.initFuncHash) !== null && _b !== void 0 ? _b : "";
2730
+ stateCell.unsettledResetCount = undefined;
2731
+ stateCell.warnedUnstableInitFunc = undefined;
2732
+ stateCell.rejectedInitProbe = undefined;
2666
2733
  var init = spec.valueProp
2667
2734
  ? $$state.env.$props[spec.valueProp]
2668
2735
  : spec.initFunc
@@ -2698,47 +2765,24 @@ function useDollarState(specs) {
2698
2765
  });
2699
2766
  }
2700
2767
  }
2701
- var reInitializeState = function (stateCell) {
2702
- var _a, _b;
2703
- var newInit = initializeStateValue($$state, stateCell, $state);
2704
- var spec = stateCell.node.getSpec();
2705
- if (spec.onChangeProp) {
2706
- (_b = (_a = $$state.env.$props)[spec.onChangeProp]) === null || _b === void 0 ? void 0 : _b.call(_a, newInit);
2707
- }
2708
- };
2709
2768
  useIsomorphicLayoutEffect(function () {
2710
- // For each spec with an initFunc, evaluate it and see if
2711
- // the init value has changed. If so, reset its state.
2712
- var resetSpecs = [];
2713
- getStateCells($state, $$state.rootSpecTree).forEach(function (stateCell) {
2714
- var _a;
2715
- if (stateCell.initFunc) {
2716
- try {
2717
- var newInit = invokeInitFunc(stateCell.initFunc, __assign({ $state: $state }, ((_a = stateCell.overrideEnv) !== null && _a !== void 0 ? _a : envFieldsAreNonNill(env))));
2718
- if (!deepEqual(newInit, stateCell.initialValue)) {
2719
- resetSpecs.push({ stateCell: stateCell });
2720
- }
2721
- }
2722
- catch (_b) {
2723
- // Exception may be thrown from initFunc -- for example, if it tries to access $queries
2724
- // that are still loading. We swallow those here, since we're only interested in
2725
- // checking if the init value has changed, not in handling these errors.
2726
- }
2727
- }
2769
+ rendering.current = false;
2770
+ // Scan every cell before resetting any, so each initFunc sees the same
2771
+ // pre-reset state.
2772
+ var resetCells = getStateCells($state, $$state.rootSpecTree).filter(function (stateCell) {
2773
+ return stateCell.pendingInit ||
2774
+ (stateCell.initFunc &&
2775
+ shouldReInitialize(stateCell, stateCell.initFunc, initFuncEnv($$state, stateCell, $state)));
2728
2776
  });
2729
- resetSpecs.forEach(function (_a) {
2730
- var stateCell = _a.stateCell;
2731
- reInitializeState(stateCell);
2777
+ resetCells.forEach(function (stateCell) {
2778
+ var _a, _b;
2779
+ stateCell.pendingInit = undefined;
2780
+ var newInit = initializeStateValue($$state, stateCell, $state);
2781
+ var spec = stateCell.node.getSpec();
2782
+ if (spec.onChangeProp) {
2783
+ (_b = (_a = $$state.env.$props)[spec.onChangeProp]) === null || _b === void 0 ? void 0 : _b.call(_a, newInit);
2784
+ }
2732
2785
  });
2733
- }, [env.$props, $state, $$state, reInitializeState]);
2734
- useIsomorphicLayoutEffect(function () {
2735
- while ($$state.registrationsQueue.length) {
2736
- var _a = $$state.registrationsQueue.shift(), path = _a.path, f = _a.f, overrideEnv = _a.overrideEnv;
2737
- var stateCell = getStateCellFrom$StateRoot($state, path);
2738
- stateCell.initFunc = f;
2739
- stateCell.overrideEnv = overrideEnv;
2740
- reInitializeState(stateCell);
2741
- }
2742
2786
  });
2743
2787
  // immediately initialize exposed non-private states
2744
2788
  useIsomorphicLayoutEffect(function () {
@@ -2849,11 +2893,15 @@ function getStateCells($state, root) {
2849
2893
  try {
2850
2894
  for (var _c = __values(root.edges().entries()), _d = _c.next(); !_d.done; _d = _c.next()) {
2851
2895
  var _e = __read(_d.value, 2), key = _e[0], child = _e[1];
2852
- if (typeof key === "string" && key in $state) {
2896
+ if (typeof key !== "string") {
2897
+ continue;
2898
+ }
2899
+ // A leaf cell can exist without a local value, e.g. a valueProp state.
2900
+ if (key in stateCell) {
2901
+ stateCells.push(stateCell[key]);
2902
+ }
2903
+ else if (key in $state) {
2853
2904
  stateCells.push.apply(stateCells, __spreadArray([], __read(getStateCells($state[key], child)), false));
2854
- if (key in stateCell) {
2855
- stateCells.push(stateCell[key]);
2856
- }
2857
2905
  }
2858
2906
  }
2859
2907
  }
@@ -2902,6 +2950,16 @@ function getCurrentInitialValue(obj, path) {
2902
2950
  }
2903
2951
  return (_a = tryGetStateCellFrom$StateRoot(obj, path)) === null || _a === void 0 ? void 0 : _a.initialValue;
2904
2952
  }
2953
+ /** Whether the runtime guard has detected instability in this initializer.
2954
+ * Canvas edits clear the diagnostic when the initializer hash changes.
2955
+ */
2956
+ function hasUnstableStateInitializer(obj, path) {
2957
+ var _a;
2958
+ if (!isPlasmicStateProxy(obj)) {
2959
+ return false;
2960
+ }
2961
+ return !!((_a = tryGetStateCellFrom$StateRoot(obj, path)) === null || _a === void 0 ? void 0 : _a.warnedUnstableInitFunc);
2962
+ }
2905
2963
  function resetToInitialValue(obj, path) {
2906
2964
  var stateCell = tryGetStateCellFrom$StateRoot(obj, path);
2907
2965
  if (stateCell) {
@@ -4367,6 +4425,7 @@ exports.getCurrentInitialValue = getCurrentInitialValue;
4367
4425
  exports.getDataProps = getDataProps;
4368
4426
  exports.getStateCellsInPlasmicProxy = getStateCellsInPlasmicProxy;
4369
4427
  exports.getStateSpecInPlasmicProxy = getStateSpecInPlasmicProxy;
4428
+ exports.hasUnstableStateInitializer = hasUnstableStateInitializer;
4370
4429
  exports.hasVariant = hasVariant;
4371
4430
  exports.initializeCodeComponentStates = initializeCodeComponentStates;
4372
4431
  exports.initializePlasmicStates = initializePlasmicStates;