@trops/dash-core 0.1.595 → 0.1.596

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
@@ -60497,24 +60497,40 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
60497
60497
 
60498
60498
  // ─── Unsaved-changes guard (Phase 2B) ────────────────────────────
60499
60499
  // Single source of truth for "is the user mid-edit with un-saved
60500
- // work?". Edit mode (`previewMode === false`) is necessary; a
60501
- // populated `currentWorkspaceRef` is sufficient the layout
60502
- // builder mutates that ref on every drag/drop/widget change.
60500
+ // work?". A state variable NOT a derived ref check — because the
60501
+ // useEffect that mirrors this to `globalThis.__dashboardIsDirty`
60502
+ // must re-run when the value changes, and `useRef` mutations don't
60503
+ // trigger re-renders.
60503
60504
  //
60504
- // The flag is mirrored to `globalThis.__dashboardIsDirty` so the
60505
- // Electron main process can poll it synchronously during window
60506
- // close + app-quit handlers without an IPC round-trip.
60505
+ // Mutations that flip it true:
60506
+ // - LayoutBuilder.onWorkspaceChange (widget drag/drop/swap/delete)
60507
+ // via `handleWorkspaceChange`
60508
+ // - Header title rename via `handleWorkspaceNameChange`
60509
+ // - Folder / theme changes via `handleWorkspaceFolderChange`,
60510
+ // `handleWorkspaceThemeChange`
60511
+ //
60512
+ // Mutations that reset to false:
60513
+ // - Successful save (`handleSaveWorkspaceComplete`)
60514
+ // - Cancel/discard (`performCancelEdit` + the discard modal path)
60515
+ // - Re-entering edit mode (`handleToggleEditMode` enter branch)
60516
+ //
60517
+ // Mirrored to `globalThis.__dashboardIsDirty` so the Electron main
60518
+ // process can poll synchronously during window close + app-quit
60519
+ // handlers without an IPC round-trip.
60507
60520
  //
60508
60521
  // A `pendingNavigation` object captures a navigation request that
60509
60522
  // arrived while dirty so the user can choose to discard or keep
60510
60523
  // editing. Shapes:
60511
60524
  // { kind: "open-workspace", workspace } — sidebar switch
60512
60525
  // { kind: "cancel-edit" } — Cancel button
60513
- var _useState57 = useState(null),
60526
+ var _useState57 = useState(false),
60514
60527
  _useState58 = _slicedToArray(_useState57, 2),
60515
- pendingNavigation = _useState58[0],
60516
- setPendingNavigation = _useState58[1];
60517
- var isDirty = previewMode === false && currentWorkspaceRef.current !== null;
60528
+ isDirty = _useState58[0],
60529
+ setIsDirty = _useState58[1];
60530
+ var _useState59 = useState(null),
60531
+ _useState60 = _slicedToArray(_useState59, 2),
60532
+ pendingNavigation = _useState60[0],
60533
+ setPendingNavigation = _useState60[1];
60518
60534
  useEffect(function () {
60519
60535
  if (typeof globalThis !== "undefined") {
60520
60536
  globalThis.__dashboardIsDirty = isDirty;
@@ -60612,10 +60628,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
60612
60628
  // We record the requested ID and open it once it appears in
60613
60629
  // workspaceConfig — handles the case where the workspace was just
60614
60630
  // created and the config reload is still in flight.
60615
- var _useState59 = useState(null),
60616
- _useState60 = _slicedToArray(_useState59, 2),
60617
- pendingOpenWorkspaceId = _useState60[0],
60618
- setPendingOpenWorkspaceId = _useState60[1];
60631
+ var _useState61 = useState(null),
60632
+ _useState62 = _slicedToArray(_useState61, 2),
60633
+ pendingOpenWorkspaceId = _useState62[0],
60634
+ setPendingOpenWorkspaceId = _useState62[1];
60619
60635
  useEffect(function () {
60620
60636
  var handler = function handler(e) {
60621
60637
  var _e$detail2;
@@ -61036,6 +61052,9 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
61036
61052
  setPreviewMode(function () {
61037
61053
  return false;
61038
61054
  });
61055
+ // LayoutBuilder fired a mutation (widget drag/drop/swap/delete).
61056
+ // Mark the workspace dirty so the navigation + close guards fire.
61057
+ setIsDirty(true);
61039
61058
 
61040
61059
  // Update the tab's workspace reference
61041
61060
  if (activeTabId) {
@@ -61239,10 +61258,10 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
61239
61258
  }
61240
61259
 
61241
61260
  // ─── Page State ──────────────────────────────────────────────────
61242
- var _useState61 = useState(null),
61243
- _useState62 = _slicedToArray(_useState61, 2),
61244
- activePageId = _useState62[0],
61245
- setActivePageId = _useState62[1];
61261
+ var _useState63 = useState(null),
61262
+ _useState64 = _slicedToArray(_useState63, 2),
61263
+ activePageId = _useState64[0],
61264
+ setActivePageId = _useState64[1];
61246
61265
 
61247
61266
  // Page history stack for goBack() — pushes the previous page id
61248
61267
  // whenever a navigation happens through navigateToPage().
@@ -61638,12 +61657,15 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
61638
61657
  }
61639
61658
  currentWorkspaceRef.current = null;
61640
61659
  originalWorkspaceRef.current = null;
61660
+ setIsDirty(false);
61641
61661
  setPreviewMode(true);
61642
61662
  }
61643
61663
  function handleToggleEditMode() {
61644
61664
  if (previewMode) {
61645
- // Entering edit mode — snapshot the current workspace
61665
+ // Entering edit mode — snapshot the current workspace and
61666
+ // reset the dirty flag so we start from a clean slate.
61646
61667
  originalWorkspaceRef.current = deepCopy(workspaceSelected);
61668
+ setIsDirty(false);
61647
61669
  setPreviewMode(false);
61648
61670
  return;
61649
61671
  }
@@ -61665,6 +61687,9 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
61665
61687
 
61666
61688
  // Update the tab name and workspace reference
61667
61689
  updateTabWorkspace(tempWorkspace);
61690
+ // Header rename counts as a workspace mutation; mark dirty so
61691
+ // navigation + close guards fire.
61692
+ setIsDirty(true);
61668
61693
  }
61669
61694
  function handleWorkspaceFolderChange(menuId) {
61670
61695
  if (!workspaceSelected) return;
@@ -61828,6 +61853,7 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
61828
61853
  // Clear edit-mode refs — edits are now persisted
61829
61854
  currentWorkspaceRef.current = null;
61830
61855
  originalWorkspaceRef.current = null;
61856
+ setIsDirty(false);
61831
61857
  setPreviewMode(function () {
61832
61858
  return true;
61833
61859
  });
@@ -62344,10 +62370,11 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
62344
62370
  if (pending.kind === "cancel-edit") {
62345
62371
  performCancelEdit();
62346
62372
  } else if (pending.kind === "open-workspace") {
62347
- // Clear edit refs before navigating so the new workspace
62348
- // mount doesn't inherit dirty state.
62373
+ // Clear edit refs + dirty flag before navigating so the
62374
+ // new workspace mount doesn't inherit dirty state.
62349
62375
  currentWorkspaceRef.current = null;
62350
62376
  originalWorkspaceRef.current = null;
62377
+ setIsDirty(false);
62351
62378
  setPreviewMode(true);
62352
62379
  handleOpenTab(pending.workspace);
62353
62380
  }