@trops/dash-core 0.1.326 → 0.1.327

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.js CHANGED
@@ -27609,15 +27609,22 @@ var DashboardModel = /*#__PURE__*/function () {
27609
27609
  this.sidebarLayout = "sidebarLayout" in obj ? obj.sidebarLayout : [];
27610
27610
  this.sidebarWidth = "sidebarWidth" in obj ? obj.sidebarWidth : 280;
27611
27611
 
27612
- // Multi-page support: migrate single-page workspaces
27612
+ // Multi-page support: every workspace always has at least one page.
27613
+ // Existing multi-page workspaces load as-is; single-page workspaces
27614
+ // are auto-migrated by wrapping their layout into a page.
27613
27615
  if ("pages" in obj && Array.isArray(obj.pages) && obj.pages.length > 0) {
27614
27616
  this.pages = obj.pages;
27615
27617
  this.activePageId = obj.activePageId || obj.pages[0].id;
27616
27618
  } else {
27617
- // Single-page workspace no migration yet, pages stay empty
27618
- // Pages are created on demand when user clicks "Add Page"
27619
- this.pages = [];
27620
- this.activePageId = null;
27619
+ // Auto-migrate: wrap existing layout into a single page
27620
+ var page = {
27621
+ id: "page-".concat(this.id || Date.now()),
27622
+ name: this.name || "Page 1",
27623
+ order: 0,
27624
+ layout: this.layout
27625
+ };
27626
+ this.pages = [page];
27627
+ this.activePageId = page.id;
27621
27628
  }
27622
27629
  obj = null;
27623
27630
 
@@ -27630,12 +27637,12 @@ var DashboardModel = /*#__PURE__*/function () {
27630
27637
  _step;
27631
27638
  try {
27632
27639
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
27633
- var page = _step.value;
27634
- if (page.layout) {
27640
+ var _page = _step.value;
27641
+ if (_page.layout) {
27635
27642
  var saved = this.layout;
27636
- this.layout = page.layout;
27643
+ this.layout = _page.layout;
27637
27644
  this._normalizeAllGrids();
27638
- page.layout = this.layout;
27645
+ _page.layout = this.layout;
27639
27646
  this.layout = saved;
27640
27647
  }
27641
27648
  }
@@ -27709,10 +27716,8 @@ var DashboardModel = /*#__PURE__*/function () {
27709
27716
  themeKey: this.themeKey,
27710
27717
  selectedProviders: this.selectedProviders
27711
27718
  };
27712
- if (this.pages && this.pages.length > 0) {
27713
- ws.pages = this.pages;
27714
- ws.activePageId = this.activePageId;
27715
- }
27719
+ ws.pages = this.pages;
27720
+ ws.activePageId = this.activePageId;
27716
27721
  if (this.sidebarEnabled || ((_this$sidebarLayout = this.sidebarLayout) === null || _this$sidebarLayout === void 0 ? void 0 : _this$sidebarLayout.length) > 0) {
27717
27722
  ws.sidebarEnabled = this.sidebarEnabled;
27718
27723
  ws.sidebarLayout = this.sidebarLayout;
@@ -48804,7 +48809,11 @@ var PageTabBar = function PageTabBar(_ref) {
48804
48809
  _ref$onReorderPages = _ref.onReorderPages,
48805
48810
  onReorderPages = _ref$onReorderPages === void 0 ? null : _ref$onReorderPages,
48806
48811
  _ref$editMode = _ref.editMode,
48807
- editMode = _ref$editMode === void 0 ? false : _ref$editMode;
48812
+ editMode = _ref$editMode === void 0 ? false : _ref$editMode,
48813
+ _ref$scrollableEnable = _ref.scrollableEnabled,
48814
+ scrollableEnabled = _ref$scrollableEnable === void 0 ? false : _ref$scrollableEnable,
48815
+ _ref$onScrollableChan = _ref.onScrollableChange,
48816
+ onScrollableChange = _ref$onScrollableChan === void 0 ? null : _ref$onScrollableChan;
48808
48817
  var _useContext = React.useContext(DashReact.ThemeContext),
48809
48818
  currentTheme = _useContext.currentTheme;
48810
48819
  var _useState = React.useState(null),
@@ -48957,6 +48966,13 @@ var PageTabBar = function PageTabBar(_ref) {
48957
48966
  }), /*#__PURE__*/jsxRuntime.jsx("span", {
48958
48967
  children: "Add Page"
48959
48968
  })]
48969
+ }), editMode && onScrollableChange && /*#__PURE__*/jsxRuntime.jsx("div", {
48970
+ className: "ml-auto flex items-center shrink-0",
48971
+ children: /*#__PURE__*/jsxRuntime.jsx(DashReact.Toggle, {
48972
+ text: "Scrollable",
48973
+ enabled: scrollableEnabled,
48974
+ setEnabled: onScrollableChange
48975
+ })
48960
48976
  })]
48961
48977
  });
48962
48978
  };
@@ -51471,37 +51487,23 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
51471
51487
  activePageId = _useState48[0],
51472
51488
  setActivePageId = _useState48[1];
51473
51489
  var workspacePages = (workspaceSelected === null || workspaceSelected === void 0 ? void 0 : workspaceSelected.pages) || [];
51474
- var hasPages = workspacePages.length > 0;
51475
51490
 
51476
51491
  // Memoize sorted pages so page object references stay stable across re-renders
51477
51492
  var sortedPagesForRender = React.useMemo(function () {
51478
- return hasPages ? _toConsumableArray(workspacePages).sort(function (a, b) {
51493
+ return _toConsumableArray(workspacePages).sort(function (a, b) {
51479
51494
  return (a.order || 0) - (b.order || 0);
51480
- }) : [];
51495
+ });
51481
51496
  },
51482
51497
  // eslint-disable-next-line react-hooks/exhaustive-deps
51483
- [hasPages, workspacePages.length,
51498
+ [workspacePages.length,
51484
51499
  // Re-sort when page names/order change but not on every parent render
51485
51500
  workspacePages.map(function (p) {
51486
51501
  return "".concat(p.id, ":").concat(p.order, ":").concat(p.name);
51487
51502
  }).join(",")]);
51488
51503
  var currentActivePageId = activePageId || (workspaceSelected === null || workspaceSelected === void 0 ? void 0 : workspaceSelected.activePageId) || ((_workspacePages$0$id = (_workspacePages$ = workspacePages[0]) === null || _workspacePages$ === void 0 ? void 0 : _workspacePages$.id) !== null && _workspacePages$0$id !== void 0 ? _workspacePages$0$id : null);
51489
51504
  function handleAddPage() {
51490
- var _workspaceSelected$la;
51491
51505
  if (!workspaceSelected) return;
51492
51506
  var existingPages = _toConsumableArray(workspacePages);
51493
-
51494
- // If this is the first time adding a page to a single-page dashboard,
51495
- // migrate the existing layout into page 1 first.
51496
- if (existingPages.length === 0 && ((_workspaceSelected$la = workspaceSelected.layout) === null || _workspaceSelected$la === void 0 ? void 0 : _workspaceSelected$la.length) > 0) {
51497
- var page1 = {
51498
- id: "page-".concat(Date.now() - 1),
51499
- name: workspaceSelected.name || "Page 1",
51500
- order: 0,
51501
- layout: workspaceSelected.layout
51502
- };
51503
- existingPages = [page1];
51504
- }
51505
51507
  var newPage = DashboardModel.createPage("Page ".concat(existingPages.length + 1));
51506
51508
  newPage.order = existingPages.length;
51507
51509
  var updatedWorkspace = _objectSpread$5(_objectSpread$5({}, workspaceSelected), {}, {
@@ -51533,17 +51535,6 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
51533
51535
  });
51534
51536
  var newActiveId = currentActivePageId === pageId ? (_updatedPages$ = updatedPages[0]) === null || _updatedPages$ === void 0 ? void 0 : _updatedPages$.id : currentActivePageId;
51535
51537
  setActivePageId(newActiveId);
51536
-
51537
- // If only one page remains, convert back to single-page mode
51538
- if (updatedPages.length === 1) {
51539
- handleWorkspaceChange(_objectSpread$5(_objectSpread$5({}, workspaceSelected), {}, {
51540
- layout: updatedPages[0].layout,
51541
- pages: [],
51542
- activePageId: null
51543
- }));
51544
- setActivePageId(null);
51545
- return;
51546
- }
51547
51538
  handleWorkspaceChange(_objectSpread$5(_objectSpread$5({}, workspaceSelected), {}, {
51548
51539
  pages: updatedPages,
51549
51540
  activePageId: newActiveId
@@ -51602,45 +51593,28 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
51602
51593
  function renderComponent(workspaceItem) {
51603
51594
  try {
51604
51595
  if (workspaceItem === undefined) return null;
51605
-
51606
- // Multi-page mode
51607
- if (hasPages) {
51608
- return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
51609
- children: sortedPagesForRender.map(function (page) {
51610
- var isActive = page.id === currentActivePageId;
51611
- return /*#__PURE__*/jsxRuntime.jsx("div", {
51612
- style: {
51613
- display: isActive ? "flex" : "none"
51614
- },
51615
- className: "flex-col w-full flex-1",
51616
- children: /*#__PURE__*/jsxRuntime.jsx(PageLayoutBuilder, {
51617
- page: page,
51618
- workspaceItem: workspaceItem,
51619
- previewMode: previewMode,
51620
- editMode: editMode,
51621
- onPageWorkspaceChange: handlePageWorkspaceChange,
51622
- onProviderSelect: stableProviderSelect,
51623
- onTogglePreview: stableTogglePreview,
51624
- workspaceRef: getPageRef(page.id),
51625
- onWidgetPopout: stableWidgetPopout
51626
- })
51627
- }, page.id);
51628
- })
51629
- });
51630
- }
51631
-
51632
- // Single-page mode (backward compatible)
51633
- return /*#__PURE__*/jsxRuntime.jsx(LayoutBuilder, {
51634
- dashboardId: workspaceItem["id"],
51635
- preview: previewMode,
51636
- workspace: workspaceItem,
51637
- onWorkspaceChange: handleWorkspaceChange,
51638
- onProviderSelect: handleProviderSelect,
51639
- onTogglePreview: handleToggleEditMode,
51640
- editMode: editMode,
51641
- workspaceRef: currentWorkspaceRef,
51642
- onWidgetPopout: popout ? null : handleWidgetPopout
51643
- }, "LayoutBuilder-".concat(workspaceItem["id"]));
51596
+ return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
51597
+ children: sortedPagesForRender.map(function (page) {
51598
+ var isActive = page.id === currentActivePageId;
51599
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
51600
+ style: {
51601
+ display: isActive ? "flex" : "none"
51602
+ },
51603
+ className: "flex-col w-full flex-1",
51604
+ children: /*#__PURE__*/jsxRuntime.jsx(PageLayoutBuilder, {
51605
+ page: page,
51606
+ workspaceItem: workspaceItem,
51607
+ previewMode: previewMode,
51608
+ editMode: editMode,
51609
+ onPageWorkspaceChange: handlePageWorkspaceChange,
51610
+ onProviderSelect: stableProviderSelect,
51611
+ onTogglePreview: stableTogglePreview,
51612
+ workspaceRef: getPageRef(page.id),
51613
+ onWidgetPopout: stableWidgetPopout
51614
+ })
51615
+ }, page.id);
51616
+ })
51617
+ });
51644
51618
  } catch (e) {
51645
51619
  return null;
51646
51620
  }
@@ -51734,27 +51708,43 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
51734
51708
  updateTabWorkspace(tempWorkspace);
51735
51709
  }
51736
51710
  function handleScrollableChange(enabled) {
51737
- var _tempWorkspace$layout;
51738
51711
  if (!workspaceSelected) return;
51739
51712
  var tempWorkspace = DashReact.deepCopy(currentWorkspaceRef.current || workspaceSelected);
51740
- // Find the root grid container layout item
51741
- var rootItem = (_tempWorkspace$layout = tempWorkspace.layout) === null || _tempWorkspace$layout === void 0 ? void 0 : _tempWorkspace$layout.find(function (item) {
51742
- return item.parent === 0;
51713
+ // Update the active page's root layout item
51714
+ tempWorkspace.pages = (tempWorkspace.pages || []).map(function (page) {
51715
+ if (page.id !== currentActivePageId) return page;
51716
+ return _objectSpread$5(_objectSpread$5({}, page), {}, {
51717
+ layout: (page.layout || []).map(function (item) {
51718
+ return item.parent === 0 ? _objectSpread$5(_objectSpread$5({}, item), {}, {
51719
+ scrollable: enabled
51720
+ }) : item;
51721
+ })
51722
+ });
51743
51723
  });
51744
- if (rootItem) {
51745
- rootItem.scrollable = enabled;
51724
+ // Update page ref immediately so getRootScrollable() reads the new value
51725
+ var pageRef = pageRefsMap.current[currentActivePageId];
51726
+ if (pageRef !== null && pageRef !== void 0 && pageRef.current) {
51727
+ pageRef.current.layout = (pageRef.current.layout || []).map(function (item) {
51728
+ return item.parent === 0 ? _objectSpread$5(_objectSpread$5({}, item), {}, {
51729
+ scrollable: enabled
51730
+ }) : item;
51731
+ });
51746
51732
  }
51747
- // Update ref immediately so getRootScrollable() reads the new value
51748
- // before LayoutBuilder's async useEffect syncs it
51749
51733
  currentWorkspaceRef.current = tempWorkspace;
51750
51734
  updateTabWorkspace(tempWorkspace);
51751
51735
  }
51752
51736
 
51753
- // Derive scrollable state from root layout item
51737
+ // Derive scrollable state from the active page's root layout item
51754
51738
  function getRootScrollable() {
51739
+ var _pageRef$current, _ws$pages;
51755
51740
  var ws = currentWorkspaceRef.current || workspaceSelected;
51756
- if (!(ws !== null && ws !== void 0 && ws.layout)) return false;
51757
- var rootItem = ws.layout.find(function (item) {
51741
+ if (!ws) return false;
51742
+ var pageRef = pageRefsMap.current[currentActivePageId];
51743
+ var layout = (pageRef === null || pageRef === void 0 || (_pageRef$current = pageRef.current) === null || _pageRef$current === void 0 ? void 0 : _pageRef$current.layout) || ((_ws$pages = ws.pages) === null || _ws$pages === void 0 || (_ws$pages = _ws$pages.find(function (p) {
51744
+ return p.id === currentActivePageId;
51745
+ })) === null || _ws$pages === void 0 ? void 0 : _ws$pages.layout);
51746
+ if (!layout) return false;
51747
+ var rootItem = layout.find(function (item) {
51758
51748
  return item.parent === 0;
51759
51749
  });
51760
51750
  return (rootItem === null || rootItem === void 0 ? void 0 : rootItem.scrollable) || false;
@@ -51764,48 +51754,27 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
51764
51754
  var _sidebarWorkspaceRef$;
51765
51755
  // we have to remove the widgetConfig which contains the component
51766
51756
  // sanitize the workspace layout remove widgetConfig items
51767
- var workspaceToSave;
51768
- if (hasPages) {
51769
- // Multi-page: gather latest layout from each page's LayoutBuilder ref
51770
- workspaceToSave = DashReact.deepCopy(workspaceSelected);
51771
- workspaceToSave.pages = (workspaceToSave.pages || []).map(function (page) {
51772
- var _pageRef$current;
51773
- var pageRef = pageRefsMap.current[page.id];
51774
- var latestLayout = (pageRef === null || pageRef === void 0 || (_pageRef$current = pageRef.current) === null || _pageRef$current === void 0 ? void 0 : _pageRef$current.layout) || page.layout || [];
51775
- return _objectSpread$5(_objectSpread$5({}, page), {}, {
51776
- layout: latestLayout.map(function (item) {
51777
- var copy = _objectSpread$5({}, item);
51778
- delete copy.widgetConfig;
51779
- return copy;
51780
- })
51781
- });
51782
- });
51783
- workspaceToSave.activePageId = currentActivePageId;
51784
- // Also sanitize the root layout (may be stale from pre-pages era)
51785
- workspaceToSave.layout = (workspaceToSave.layout || []).map(function (item) {
51786
- var copy = _objectSpread$5({}, item);
51787
- delete copy.widgetConfig;
51788
- return copy;
51757
+ // Gather latest layout from each page's LayoutBuilder ref
51758
+ var workspaceToSave = DashReact.deepCopy(workspaceSelected);
51759
+ workspaceToSave.pages = (workspaceToSave.pages || []).map(function (page) {
51760
+ var _pageRef$current2;
51761
+ var pageRef = pageRefsMap.current[page.id];
51762
+ var latestLayout = (pageRef === null || pageRef === void 0 || (_pageRef$current2 = pageRef.current) === null || _pageRef$current2 === void 0 ? void 0 : _pageRef$current2.layout) || page.layout || [];
51763
+ return _objectSpread$5(_objectSpread$5({}, page), {}, {
51764
+ layout: latestLayout.map(function (item) {
51765
+ var copy = _objectSpread$5({}, item);
51766
+ delete copy.widgetConfig;
51767
+ return copy;
51768
+ })
51789
51769
  });
51790
- } else {
51791
- var _currentWorkspaceRef$;
51792
- // Single-page: merge workspace-level properties (themeKey, name, menuId, etc.)
51793
- // from workspaceSelected with the latest layout from currentWorkspaceRef.
51794
- // The ref only tracks layout changes; header-level property changes
51795
- // (theme, folder, scrollable) are tracked in workspaceSelected.
51796
- workspaceToSave = DashReact.deepCopy(workspaceSelected);
51797
- var refLayout = (_currentWorkspaceRef$ = currentWorkspaceRef.current) === null || _currentWorkspaceRef$ === void 0 ? void 0 : _currentWorkspaceRef$.layout;
51798
- if (refLayout) {
51799
- workspaceToSave["layout"] = refLayout.map(function (layoutItem) {
51800
- delete layoutItem["widgetConfig"];
51801
- return layoutItem;
51802
- });
51803
- } else {
51804
- workspaceToSave["layout"] = (workspaceToSave["layout"] || []).map(function (layoutItem) {
51805
- delete layoutItem["widgetConfig"];
51806
- return layoutItem;
51807
- });
51808
- }
51770
+ });
51771
+ workspaceToSave.activePageId = currentActivePageId;
51772
+ // Sync root layout from active page for backward compat
51773
+ var activePage = workspaceToSave.pages.find(function (p) {
51774
+ return p.id === currentActivePageId;
51775
+ });
51776
+ if (activePage) {
51777
+ workspaceToSave.layout = activePage.layout;
51809
51778
  }
51810
51779
 
51811
51780
  // Gather sidebar layout from its LayoutBuilder ref
@@ -52055,8 +52024,6 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
52055
52024
  themes: themes || {},
52056
52025
  onFolderChange: popout ? null : handleWorkspaceFolderChange,
52057
52026
  onThemeChange: popout ? null : handleWorkspaceThemeChange,
52058
- scrollableEnabled: getRootScrollable(),
52059
- onScrollableChange: popout ? null : handleScrollableChange,
52060
52027
  sidebarEnabled: sidebarEnabled,
52061
52028
  onSidebarChange: popout ? null : handleSidebarToggle
52062
52029
  }), /*#__PURE__*/jsxRuntime.jsxs(DashboardThemeProvider, {
@@ -52089,7 +52056,7 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
52089
52056
  className: "h-3 w-3"
52090
52057
  })
52091
52058
  })]
52092
- }), (hasPages || !previewMode) && /*#__PURE__*/jsxRuntime.jsx(PageTabBar, {
52059
+ }), /*#__PURE__*/jsxRuntime.jsx(PageTabBar, {
52093
52060
  pages: workspacePages,
52094
52061
  activePageId: currentActivePageId,
52095
52062
  onSwitchPage: handleSwitchPage,
@@ -52097,7 +52064,9 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
52097
52064
  onRenamePage: handleRenamePage,
52098
52065
  onDeletePage: handleDeletePage,
52099
52066
  onReorderPages: handleReorderPages,
52100
- editMode: !previewMode
52067
+ editMode: !previewMode,
52068
+ scrollableEnabled: getRootScrollable(),
52069
+ onScrollableChange: popout ? null : handleScrollableChange
52101
52070
  }), /*#__PURE__*/jsxRuntime.jsxs("div", {
52102
52071
  className: "flex flex-row flex-1 min-h-0 overflow-hidden",
52103
52072
  children: [sidebarEnabled && !popout && /*#__PURE__*/jsxRuntime.jsx(PinnedSidebar, {