@trops/dash-core 0.1.563 → 0.1.564

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/index.esm.js CHANGED
@@ -11697,7 +11697,9 @@ var PanelEditItem = function PanelEditItem(_ref) {
11697
11697
  var workspace = _ref.workspace,
11698
11698
  onUpdate = _ref.onUpdate,
11699
11699
  _ref$item = _ref.item,
11700
- item = _ref$item === void 0 ? null : _ref$item;
11700
+ item = _ref$item === void 0 ? null : _ref$item,
11701
+ _ref$flushRef = _ref.flushRef,
11702
+ flushRef = _ref$flushRef === void 0 ? null : _ref$flushRef;
11701
11703
  var _useState = useState(item),
11702
11704
  _useState2 = _slicedToArray(_useState, 2),
11703
11705
  itemSelected = _useState2[0],
@@ -11712,6 +11714,23 @@ var PanelEditItem = function PanelEditItem(_ref) {
11712
11714
  var forceUpdate = useCallback(function () {
11713
11715
  return updateState({});
11714
11716
  }, []);
11717
+
11718
+ // Refs that mirror the latest local state. Used by the unmount
11719
+ // cleanup and the flush handler — both run outside the normal
11720
+ // render cycle and can't rely on the closed-over state, since
11721
+ // closures capture state at the moment the function was created.
11722
+ var itemSelectedRef = useRef(itemSelected);
11723
+ var workspaceSelectedRef = useRef(workspaceSelected);
11724
+ var onUpdateRef = useRef(onUpdate);
11725
+ itemSelectedRef.current = itemSelected;
11726
+ workspaceSelectedRef.current = workspaceSelected;
11727
+ onUpdateRef.current = onUpdate;
11728
+
11729
+ // True when local edits have not yet been propagated to the parent.
11730
+ // Set by handleTextChangeCustom, cleared by flushPending. The
11731
+ // unmount cleanup (below) consults this so a tab switch or modal
11732
+ // close doesn't drop the user's last few keystrokes.
11733
+ var dirtyRef = useRef(false);
11715
11734
  useEffect(function () {
11716
11735
  if (deepEqual(item, itemSelected) === false) {
11717
11736
  setItemSelected(function () {
@@ -11727,13 +11746,55 @@ var PanelEditItem = function PanelEditItem(_ref) {
11727
11746
  }
11728
11747
  // eslint-disable-next-line react-hooks/exhaustive-deps
11729
11748
  }, [workspace, item]);
11730
- function handleUpdate(e, data) {
11731
- var workspaceTemp = WorkspaceModel(workspaceSelected);
11732
- var newLayout = replaceItemInLayout(workspaceTemp.layout, data["id"], data);
11749
+
11750
+ // Build the fresh workspace from the latest local item + propagate
11751
+ // to the parent. Returns `{item, workspace}` so callers (the
11752
+ // modal's Save handler) can read the new workspace synchronously,
11753
+ // sidestepping React's async setState — the parent's
11754
+ // workspaceSelected state won't reflect this call until the next
11755
+ // render, but the caller already has the new value in hand.
11756
+ //
11757
+ // Returns null when there's nothing to flush.
11758
+ function flushPending() {
11759
+ if (!dirtyRef.current) return null;
11760
+ var latestItem = itemSelectedRef.current;
11761
+ var latestWorkspace = workspaceSelectedRef.current;
11762
+ if (!latestItem || !latestWorkspace) return null;
11763
+ var workspaceTemp = WorkspaceModel(latestWorkspace);
11764
+ var newLayout = replaceItemInLayout(workspaceTemp.layout, latestItem["id"], latestItem);
11733
11765
  workspaceTemp.layout = newLayout;
11734
- onUpdate(data, workspaceTemp);
11735
- forceUpdate();
11766
+ dirtyRef.current = false;
11767
+ onUpdateRef.current(latestItem, workspaceTemp);
11768
+ return {
11769
+ item: latestItem,
11770
+ workspace: workspaceTemp
11771
+ };
11736
11772
  }
11773
+
11774
+ // Expose flushPending via the ref the modal passes in. This is how
11775
+ // the modal's Save handler triggers one final propagation before
11776
+ // calling onSaveWorkspace — without it, the modal would save the
11777
+ // workspace as it stood before the user's last typing burst.
11778
+ useEffect(function () {
11779
+ if (!flushRef) return undefined;
11780
+ flushRef.current = flushPending;
11781
+ return function () {
11782
+ if (flushRef.current === flushPending) flushRef.current = null;
11783
+ };
11784
+ // eslint-disable-next-line react-hooks/exhaustive-deps
11785
+ }, [flushRef]);
11786
+
11787
+ // Final flush on unmount. Triggers when the user switches sidebar
11788
+ // tabs (the modal conditionally renders only the active section,
11789
+ // so switching unmounts PanelEditItem) or closes the modal without
11790
+ // saving. The parent modal is still mounted at this point, so
11791
+ // calling onUpdate from cleanup is safe.
11792
+ useEffect(function () {
11793
+ return function () {
11794
+ if (dirtyRef.current) flushPending();
11795
+ };
11796
+ // eslint-disable-next-line react-hooks/exhaustive-deps
11797
+ }, []);
11737
11798
  function renderCustomSettings() {
11738
11799
  if (itemSelected) {
11739
11800
  var componentConfig = ComponentManager.getComponent(itemSelected.component);
@@ -11742,8 +11803,15 @@ var PanelEditItem = function PanelEditItem(_ref) {
11742
11803
  }
11743
11804
  if ("userConfig" in componentConfig) {
11744
11805
  var userConfig = componentConfig["userConfig"];
11745
- var layoutItem = LayoutModel(itemSelected, workspaceSelected);
11746
- var userPrefs = layoutItem.userPrefs;
11806
+ // Read userPrefs straight off the locally-tracked itemSelected.
11807
+ // LayoutModel() resets `userPrefs` to widgetConfig template
11808
+ // defaults and only merges back `obj.userConfigValues` (the
11809
+ // EnhancedWidgetDropdown add-time field), silently dropping
11810
+ // `obj.userPrefs`. Piping through it on every render strips
11811
+ // the in-flight typed value and snaps the controlled InputText
11812
+ // back to "", which is what made these inputs untypeable —
11813
+ // user typing "airports" was seeing only the last char land.
11814
+ var userPrefs = itemSelected.userPrefs && _typeof(itemSelected.userPrefs) === "object" ? itemSelected.userPrefs : {};
11747
11815
  return Object.keys(userConfig).map(function (key) {
11748
11816
  if (key in userPrefs) {
11749
11817
  var configItem = userConfig[key];
@@ -11764,7 +11832,18 @@ var PanelEditItem = function PanelEditItem(_ref) {
11764
11832
  newItem["userPrefs"] = {};
11765
11833
  }
11766
11834
  newItem["userPrefs"][key] = value;
11767
- handleUpdate(null, newItem);
11835
+ // Update LOCAL state synchronously so the controlled InputText
11836
+ // reflects the typed character on the very next render. The
11837
+ // expensive workspace clone + parent-tree re-render is DEFERRED
11838
+ // until Save (via flushRef) or unmount (tab switch). Pre-defer
11839
+ // behavior: every keystroke deep-cloned the workspace and
11840
+ // re-rendered the whole modal subtree (sidebar + body + footer),
11841
+ // which made even short strings feel sluggish — characters
11842
+ // landed but the input lagged.
11843
+ setItemSelected(function () {
11844
+ return newItem;
11845
+ });
11846
+ dirtyRef.current = true;
11768
11847
  }
11769
11848
  function renderFormItem(displayName, key, instructions, required, value, _onChange, configItem) {
11770
11849
  var _configItem$step;
@@ -14566,6 +14645,11 @@ var LayoutBuilderConfigModal = function LayoutBuilderConfigModal(_ref) {
14566
14645
  var forceUpdate = useCallback(function () {
14567
14646
  return updateState({});
14568
14647
  }, []);
14648
+
14649
+ // PanelEditItem defers per-keystroke propagation to keep typing
14650
+ // snappy. This ref lets us trigger one final flush right before
14651
+ // Save so the saved workspace includes any in-flight edits.
14652
+ var panelEditFlushRef = useRef(null);
14569
14653
  useEffect(function () {
14570
14654
  if (item !== itemSelected) {
14571
14655
  setItemSelected(function () {
@@ -14597,7 +14681,17 @@ var LayoutBuilderConfigModal = function LayoutBuilderConfigModal(_ref) {
14597
14681
  forceUpdate();
14598
14682
  }
14599
14683
  function handleSaveConfig() {
14600
- onSaveWorkspace(workspaceSelected);
14684
+ // Pull any pending edits out of PanelEditItem before saving.
14685
+ // The panel propagates back via onUpdate (which sets our
14686
+ // workspaceSelected state) but setState is async — so we read
14687
+ // the flushed workspace directly from the return value to avoid
14688
+ // saving a stale snapshot on the very first Save after typing.
14689
+ var workspaceToSave = workspaceSelected;
14690
+ if (typeof panelEditFlushRef.current === "function") {
14691
+ var flushed = panelEditFlushRef.current();
14692
+ if (flushed && flushed.workspace) workspaceToSave = flushed.workspace;
14693
+ }
14694
+ onSaveWorkspace(workspaceToSave);
14601
14695
  }
14602
14696
  var sections = itemSelected ? getSections(itemSelected) : [];
14603
14697
  var activeDef = sections.find(function (s) {
@@ -14662,7 +14756,8 @@ var LayoutBuilderConfigModal = function LayoutBuilderConfigModal(_ref) {
14662
14756
  children: [activeSection === "edit" && /*#__PURE__*/jsx(PanelEditItem, {
14663
14757
  item: itemSelected,
14664
14758
  onUpdate: handleEditChange,
14665
- workspace: workspaceSelected
14759
+ workspace: workspaceSelected,
14760
+ flushRef: panelEditFlushRef
14666
14761
  }), activeSection === "grid_layout" && /*#__PURE__*/jsx(PanelEditItemGrid, {
14667
14762
  item: itemSelected,
14668
14763
  onUpdate: handleEditChange,