@trops/dash-core 0.1.428 → 0.1.431

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
@@ -28734,8 +28734,16 @@ var WorkspaceModel = function WorkspaceModel(workspaceItem) {
28734
28734
  // Skip items already produced by LayoutModel (idempotent: LayoutModel
28735
28735
  // is safe to call on its own output).
28736
28736
  var wsId = "id" in obj ? obj["id"] : workspace.id;
28737
+ // LayoutModel returns null when an item can't be normalized (e.g.
28738
+ // throw inside its catch). A null in the layout array crashes
28739
+ // downstream forEach/map consumers with `Cannot read properties of
28740
+ // null (reading 'type')`. Filter nulls so the renderer never sees
28741
+ // them — the original raw item is already lost at that point, so
28742
+ // dropping it is the only safe action.
28737
28743
  workspace.layout = rawLayout.map(function (item) {
28738
28744
  return LayoutModel(item, rawLayout, wsId);
28745
+ }).filter(function (item) {
28746
+ return item != null;
28739
28747
  });
28740
28748
  workspace.pages = "pages" in obj ? obj["pages"] : [];
28741
28749
  workspace.activePageId = "activePageId" in obj ? obj["activePageId"] : null;
@@ -40421,36 +40429,57 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40421
40429
  depSelections = _useState28[0],
40422
40430
  setDepSelections = _useState28[1];
40423
40431
 
40424
- // Step 5: Publish
40425
- var _useState29 = useState(false),
40432
+ // Step 5: Defaults verification — surfaced values from each owned
40433
+ // widget package's `.dash.js` userConfig[field].defaultValue. Lets
40434
+ // the publisher review (and optionally blank/edit) values set
40435
+ // during development before the ZIP ships.
40436
+ // defaultsByPackage: { [packageId]: Array<{widgetName, field, currentDefault, displayName, type, instructions}> }
40437
+ // defaultsOverrides: { [packageId]: { [widgetName]: { [field]: newValue } } }
40438
+ // — only fields the user actually edited appear here. Undefined
40439
+ // = "no change"; explicit empty-string = "blank it out".
40440
+ var _useState29 = useState({}),
40426
40441
  _useState30 = _slicedToArray(_useState29, 2),
40427
- isPublishing = _useState30[0],
40428
- setIsPublishing = _useState30[1];
40429
- var _useState31 = useState(null),
40442
+ defaultsByPackage = _useState30[0],
40443
+ setDefaultsByPackage = _useState30[1];
40444
+ var _useState31 = useState(false),
40430
40445
  _useState32 = _slicedToArray(_useState31, 2),
40431
- result = _useState32[0],
40432
- setResult = _useState32[1];
40433
- // Per-step progress during batch publish
40434
- var _useState33 = useState([]),
40446
+ defaultsLoading = _useState32[0],
40447
+ setDefaultsLoading = _useState32[1];
40448
+ var _useState33 = useState({}),
40435
40449
  _useState34 = _slicedToArray(_useState33, 2),
40436
- publishSteps = _useState34[0],
40437
- setPublishSteps = _useState34[1];
40450
+ defaultsOverrides = _useState34[0],
40451
+ setDefaultsOverrides = _useState34[1];
40438
40452
 
40439
- // Visibility chosen on the Details step. Defaults to public.
40440
- var _useState35 = useState("public"),
40453
+ // Step 6: Publish
40454
+ var _useState35 = useState(false),
40441
40455
  _useState36 = _slicedToArray(_useState35, 2),
40442
- visibility = _useState36[0],
40443
- setVisibility = _useState36[1];
40456
+ isPublishing = _useState36[0],
40457
+ setIsPublishing = _useState36[1];
40458
+ var _useState37 = useState(null),
40459
+ _useState38 = _slicedToArray(_useState37, 2),
40460
+ result = _useState38[0],
40461
+ setResult = _useState38[1];
40462
+ // Per-step progress during batch publish
40463
+ var _useState39 = useState([]),
40464
+ _useState40 = _slicedToArray(_useState39, 2),
40465
+ publishSteps = _useState40[0],
40466
+ setPublishSteps = _useState40[1];
40467
+
40468
+ // Visibility — chosen on the Details step. Defaults to public.
40469
+ var _useState41 = useState("public"),
40470
+ _useState42 = _slicedToArray(_useState41, 2),
40471
+ visibility = _useState42[0],
40472
+ setVisibility = _useState42[1];
40444
40473
 
40445
40474
  // Dashboard version bump — chosen on the Details step. Defaults to
40446
40475
  // "patch" so repeat-publishes auto-increment the registry's
40447
40476
  // latestVersion. Without this, every republish used the same
40448
40477
  // version string, the registry never saw a new version, and update
40449
40478
  // notifications never fired on installers.
40450
- var _useState37 = useState("patch"),
40451
- _useState38 = _slicedToArray(_useState37, 2),
40452
- dashboardBump = _useState38[0],
40453
- setDashboardBump = _useState38[1];
40479
+ var _useState43 = useState("patch"),
40480
+ _useState44 = _slicedToArray(_useState43, 2),
40481
+ dashboardBump = _useState44[0],
40482
+ setDashboardBump = _useState44[1];
40454
40483
 
40455
40484
  // Fetch publish preview (widget names) on open
40456
40485
  useEffect(function () {
@@ -40586,6 +40615,97 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40586
40615
  });
40587
40616
  // eslint-disable-next-line react-hooks/exhaustive-deps
40588
40617
  }, [step, isOpen]);
40618
+
40619
+ // Load per-package default-value scans when the user arrives at the
40620
+ // Defaults step. We only scan packages that are actually going to be
40621
+ // republished (include + owned) to keep the step focused — a
40622
+ // third-party package the user isn't republishing can't have its
40623
+ // defaults changed anyway.
40624
+ useEffect(function () {
40625
+ if (!isOpen || step !== 5 || !plan || defaultsLoading) return;
40626
+ var packagesToScan = [];
40627
+ var _iterator2 = _createForOfIteratorHelper$c(plan.widgets || []),
40628
+ _step2;
40629
+ try {
40630
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
40631
+ var w = _step2.value;
40632
+ if (!w.scope || !w.packageName) continue;
40633
+ var key = "".concat(w.scope, "/").concat(w.packageName);
40634
+ var sel = depSelections[key];
40635
+ if (!(sel !== null && sel !== void 0 && sel.include) || !(sel !== null && sel !== void 0 && sel.owned)) continue;
40636
+ // Resolve the local package id the scanner expects — same shape
40637
+ // the inspect IPC already takes.
40638
+ var localPkgId = w.packageId || "@".concat(w.scope, "/").concat(w.packageName);
40639
+ if (!defaultsByPackage[localPkgId]) packagesToScan.push(localPkgId);
40640
+ }
40641
+ } catch (err) {
40642
+ _iterator2.e(err);
40643
+ } finally {
40644
+ _iterator2.f();
40645
+ }
40646
+ if (packagesToScan.length === 0) return;
40647
+ setDefaultsLoading(true);
40648
+ Promise.all(packagesToScan.map(function (pkgId) {
40649
+ return window.mainApi.registry.scanWidgetDefaults(pkgId).then(function (res) {
40650
+ return {
40651
+ pkgId: pkgId,
40652
+ res: res
40653
+ };
40654
+ })["catch"](function (err) {
40655
+ return {
40656
+ pkgId: pkgId,
40657
+ res: {
40658
+ success: false,
40659
+ error: (err === null || err === void 0 ? void 0 : err.message) || String(err)
40660
+ }
40661
+ };
40662
+ });
40663
+ })).then(function (results) {
40664
+ setDefaultsByPackage(function (prev) {
40665
+ var next = _objectSpread$r({}, prev);
40666
+ var _iterator3 = _createForOfIteratorHelper$c(results),
40667
+ _step3;
40668
+ try {
40669
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
40670
+ var _step3$value = _step3.value,
40671
+ pkgId = _step3$value.pkgId,
40672
+ res = _step3$value.res;
40673
+ next[pkgId] = res !== null && res !== void 0 && res.success ? res.defaults || [] : [];
40674
+ }
40675
+ } catch (err) {
40676
+ _iterator3.e(err);
40677
+ } finally {
40678
+ _iterator3.f();
40679
+ }
40680
+ return next;
40681
+ });
40682
+ setDefaultsLoading(false);
40683
+ });
40684
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40685
+ }, [step, isOpen, plan, depSelections]);
40686
+ function setDefaultOverride(packageId, widgetName, field, newValue) {
40687
+ setDefaultsOverrides(function (prev) {
40688
+ var next = _objectSpread$r({}, prev);
40689
+ var forPkg = _objectSpread$r({}, next[packageId] || {});
40690
+ var forWidget = _objectSpread$r({}, forPkg[widgetName] || {});
40691
+ if (newValue === undefined) {
40692
+ delete forWidget[field];
40693
+ } else {
40694
+ forWidget[field] = newValue;
40695
+ }
40696
+ if (Object.keys(forWidget).length === 0) {
40697
+ delete forPkg[widgetName];
40698
+ } else {
40699
+ forPkg[widgetName] = forWidget;
40700
+ }
40701
+ if (Object.keys(forPkg).length === 0) {
40702
+ delete next[packageId];
40703
+ } else {
40704
+ next[packageId] = forPkg;
40705
+ }
40706
+ return next;
40707
+ });
40708
+ }
40589
40709
  function updateDepSelection(key, patch) {
40590
40710
  setDepSelections(function (prev) {
40591
40711
  return _objectSpread$r(_objectSpread$r({}, prev), {}, _defineProperty({}, key, _objectSpread$r(_objectSpread$r({}, prev[key]), patch)));
@@ -40603,7 +40723,7 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40603
40723
  }
40604
40724
  function _handlePublish() {
40605
40725
  _handlePublish = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
40606
- var steps, seenPackages, _iterator2, _step2, w, _key2, _sel, key, sel, updateStep, i, _step3, _res$manifest, bump, options, res, _res, _options, _res2, _t2, _t3;
40726
+ var steps, seenPackages, _iterator4, _step4, w, _key2, _sel, key, sel, updateStep, i, _step5, _res$manifest, bump, options, res, _res, _options, _res2, _t2, _t3;
40607
40727
  return _regeneratorRuntime.wrap(function (_context2) {
40608
40728
  while (1) switch (_context2.prev = _context2.next) {
40609
40729
  case 0:
@@ -40625,15 +40745,15 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40625
40745
  break;
40626
40746
  }
40627
40747
  seenPackages = new Set();
40628
- _iterator2 = _createForOfIteratorHelper$c(plan.widgets || []);
40748
+ _iterator4 = _createForOfIteratorHelper$c(plan.widgets || []);
40629
40749
  _context2.prev = 2;
40630
- _iterator2.s();
40750
+ _iterator4.s();
40631
40751
  case 3:
40632
- if ((_step2 = _iterator2.n()).done) {
40752
+ if ((_step4 = _iterator4.n()).done) {
40633
40753
  _context2.next = 8;
40634
40754
  break;
40635
40755
  }
40636
- w = _step2.value;
40756
+ w = _step4.value;
40637
40757
  if (!(!w.scope || !w.packageName)) {
40638
40758
  _context2.next = 4;
40639
40759
  break;
@@ -40671,10 +40791,10 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40671
40791
  case 9:
40672
40792
  _context2.prev = 9;
40673
40793
  _t2 = _context2["catch"](2);
40674
- _iterator2.e(_t2);
40794
+ _iterator4.e(_t2);
40675
40795
  case 10:
40676
40796
  _context2.prev = 10;
40677
- _iterator2.f();
40797
+ _iterator4.f();
40678
40798
  return _context2.finish(10);
40679
40799
  case 11:
40680
40800
  if (plan.theme && plan.theme.scope && plan.theme.name) {
@@ -40718,28 +40838,30 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40718
40838
  _context2.next = 24;
40719
40839
  break;
40720
40840
  }
40721
- _step3 = steps[i];
40841
+ _step5 = steps[i];
40722
40842
  updateStep(i, {
40723
40843
  status: "running"
40724
40844
  });
40725
- if (!(_step3.kind === "widget")) {
40845
+ if (!(_step5.kind === "widget")) {
40726
40846
  _context2.next = 17;
40727
40847
  break;
40728
40848
  }
40729
- bump = _step3.selection.bump;
40849
+ bump = _step5.selection.bump;
40730
40850
  options = _objectSpread$r(_objectSpread$r({}, bump && bump !== "none" ? {
40731
40851
  bump: bump
40732
40852
  } : {}), {}, {
40733
- visibility: _step3.selection.visibility,
40853
+ visibility: _step5.selection.visibility,
40734
40854
  // Plumb the publisher's display name through to the widget
40735
40855
  // publish call so the manifest — and the rewritten dash.json
40736
40856
  // inside the zipped package — records the actual human who
40737
40857
  // published, not the AI Widget Builder's "AI Assistant"
40738
40858
  // placeholder.
40739
40859
  authorName: authorName.trim() || undefined
40740
- });
40860
+ }, defaultsOverrides[_step5.packageId] ? {
40861
+ defaultsOverride: defaultsOverrides[_step5.packageId]
40862
+ } : {});
40741
40863
  _context2.next = 15;
40742
- return window.mainApi.registry.publishWidget(appId, _step3.packageId, options);
40864
+ return window.mainApi.registry.publishWidget(appId, _step5.packageId, options);
40743
40865
  case 15:
40744
40866
  res = _context2.sent;
40745
40867
  if (res !== null && res !== void 0 && res.success) {
@@ -40752,7 +40874,7 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40752
40874
  });
40753
40875
  setResult({
40754
40876
  success: false,
40755
- error: "Failed to publish widget ".concat(_step3.key, ": ").concat((res === null || res === void 0 ? void 0 : res.error) || "unknown error")
40877
+ error: "Failed to publish widget ".concat(_step5.key, ": ").concat((res === null || res === void 0 ? void 0 : res.error) || "unknown error")
40756
40878
  });
40757
40879
  setIsPublishing(false);
40758
40880
  return _context2.abrupt("return");
@@ -40764,13 +40886,13 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40764
40886
  _context2.next = 23;
40765
40887
  break;
40766
40888
  case 17:
40767
- if (!(_step3.kind === "theme")) {
40889
+ if (!(_step5.kind === "theme")) {
40768
40890
  _context2.next = 20;
40769
40891
  break;
40770
40892
  }
40771
40893
  _context2.next = 18;
40772
- return window.mainApi.themes.publishTheme(appId, _step3.themeKey, {
40773
- visibility: _step3.selection.visibility
40894
+ return window.mainApi.themes.publishTheme(appId, _step5.themeKey, {
40895
+ visibility: _step5.selection.visibility
40774
40896
  });
40775
40897
  case 18:
40776
40898
  _res = _context2.sent;
@@ -40784,7 +40906,7 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40784
40906
  });
40785
40907
  setResult({
40786
40908
  success: false,
40787
- error: "Failed to publish theme ".concat(_step3.themeKey, ": ").concat((_res === null || _res === void 0 ? void 0 : _res.error) || "unknown error")
40909
+ error: "Failed to publish theme ".concat(_step5.themeKey, ": ").concat((_res === null || _res === void 0 ? void 0 : _res.error) || "unknown error")
40788
40910
  });
40789
40911
  setIsPublishing(false);
40790
40912
  return _context2.abrupt("return");
@@ -40796,7 +40918,7 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40796
40918
  _context2.next = 23;
40797
40919
  break;
40798
40920
  case 20:
40799
- if (!(_step3.kind === "dashboard")) {
40921
+ if (!(_step5.kind === "dashboard")) {
40800
40922
  _context2.next = 23;
40801
40923
  break;
40802
40924
  }
@@ -40950,7 +41072,7 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40950
41072
  }
40951
41073
  function handleSignOut() {
40952
41074
  return _handleSignOut.apply(this, arguments);
40953
- } // Steps: 0=Account, 1=Details, 2=Tags, 3=Icon, 4=Dependencies, 5=Publish
41075
+ } // Steps: 0=Account, 1=Details, 2=Tags, 3=Icon, 4=Dependencies, 5=Defaults, 6=Publish
40954
41076
  function _handleSignOut() {
40955
41077
  _handleSignOut = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
40956
41078
  return _regeneratorRuntime.wrap(function (_context5) {
@@ -40975,8 +41097,8 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
40975
41097
  }));
40976
41098
  return _handleSignOut.apply(this, arguments);
40977
41099
  }
40978
- var isLastStep = step === 5;
40979
- var canAdvance = step === 0 ? authStatus === "authenticated" : step === 1 ? !!authorName.trim() : step === 2 ? selectedTags.length > 0 : step === 4 ? !planLoading : true;
41100
+ var isLastStep = step === 6;
41101
+ var canAdvance = step === 0 ? authStatus === "authenticated" : step === 1 ? !!authorName.trim() : step === 2 ? selectedTags.length > 0 : step === 4 ? !planLoading : step === 5 ? !defaultsLoading : true;
40980
41102
  return /*#__PURE__*/jsx(Modal, {
40981
41103
  isOpen: isOpen,
40982
41104
  setIsOpen: handleClose,
@@ -41237,6 +41359,26 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
41237
41359
  onChange: updateDepSelection
41238
41360
  })]
41239
41361
  })
41362
+ }), /*#__PURE__*/jsx(Stepper.Step, {
41363
+ label: "Defaults",
41364
+ children: /*#__PURE__*/jsxs("div", {
41365
+ className: "flex-1 min-h-0 overflow-y-auto pb-4 space-y-4",
41366
+ children: [/*#__PURE__*/jsxs("p", {
41367
+ className: "text-sm opacity-70",
41368
+ children: ["Review ", /*#__PURE__*/jsx("code", {
41369
+ children: "userConfig"
41370
+ }), " default values the widget's dev-time dash.js ships. Anything you leave as-is gets published as the current default. Values you blank or edit here get rewritten in a staged copy before the ZIP is built \u2014 your local source files are untouched."]
41371
+ }), defaultsLoading && /*#__PURE__*/jsx("div", {
41372
+ className: "text-sm opacity-60 py-6 text-center",
41373
+ children: "Scanning widget configs for default values\u2026"
41374
+ }), !defaultsLoading && /*#__PURE__*/jsx(DefaultsReviewList, {
41375
+ plan: plan,
41376
+ depSelections: depSelections,
41377
+ defaultsByPackage: defaultsByPackage,
41378
+ overrides: defaultsOverrides,
41379
+ onChange: setDefaultOverride
41380
+ })]
41381
+ })
41240
41382
  }), /*#__PURE__*/jsx(Stepper.Step, {
41241
41383
  label: "Publish",
41242
41384
  children: /*#__PURE__*/jsxs("div", {
@@ -41426,7 +41568,7 @@ var PublishDashboardModal = function PublishDashboardModal(_ref) {
41426
41568
  className: "flex-1 text-center",
41427
41569
  children: /*#__PURE__*/jsxs("span", {
41428
41570
  className: "text-xs opacity-40",
41429
- children: ["Step ", step + 1, " of 6"]
41571
+ children: ["Step ", step + 1, " of 7"]
41430
41572
  })
41431
41573
  }), /*#__PURE__*/jsx("div", {
41432
41574
  className: "flex flex-row gap-2",
@@ -41515,11 +41657,11 @@ function DependencyTable(_ref4) {
41515
41657
  // row. Each row shows the list of component widgets that live inside it
41516
41658
  // so the user knows what's getting published.
41517
41659
  var byKey = new Map();
41518
- var _iterator3 = _createForOfIteratorHelper$c(plan.widgets || []),
41519
- _step4;
41660
+ var _iterator5 = _createForOfIteratorHelper$c(plan.widgets || []),
41661
+ _step6;
41520
41662
  try {
41521
- for (_iterator3.s(); !(_step4 = _iterator3.n()).done;) {
41522
- var w = _step4.value;
41663
+ for (_iterator5.s(); !(_step6 = _iterator5.n()).done;) {
41664
+ var w = _step6.value;
41523
41665
  if (!w.scope || !w.packageName) continue;
41524
41666
  var _key3 = "".concat(w.scope, "/").concat(w.packageName);
41525
41667
  var entry = byKey.get(_key3) || {
@@ -41532,9 +41674,9 @@ function DependencyTable(_ref4) {
41532
41674
  byKey.set(_key3, entry);
41533
41675
  }
41534
41676
  } catch (err) {
41535
- _iterator3.e(err);
41677
+ _iterator5.e(err);
41536
41678
  } finally {
41537
- _iterator3.f();
41679
+ _iterator5.f();
41538
41680
  }
41539
41681
  var rows = Array.from(byKey.values()).map(function (e) {
41540
41682
  return _objectSpread$r(_objectSpread$r({}, e), {}, {
@@ -41668,6 +41810,134 @@ function DependencyTable(_ref4) {
41668
41810
  });
41669
41811
  }
41670
41812
 
41813
+ /**
41814
+ * Per-package editable list of every non-empty userConfig default.
41815
+ * Renders once per owned package selected for republish. Edits are
41816
+ * two-way: typing into a field stages an override; hitting "Reset"
41817
+ * clears the override so the original defaultValue ships. The
41818
+ * outside world treats `overrides[packageId][widgetName][field]` as
41819
+ * the source of truth for the publish call.
41820
+ */
41821
+ function DefaultsReviewList(_ref6) {
41822
+ var plan = _ref6.plan,
41823
+ depSelections = _ref6.depSelections,
41824
+ defaultsByPackage = _ref6.defaultsByPackage,
41825
+ overrides = _ref6.overrides,
41826
+ _onChange2 = _ref6.onChange;
41827
+ // Collect the packages we're actually about to republish so the UI
41828
+ // stays aligned with Dependencies — no surprises about WHICH
41829
+ // package's defaults you're editing.
41830
+ var rows = [];
41831
+ var _iterator6 = _createForOfIteratorHelper$c((plan === null || plan === void 0 ? void 0 : plan.widgets) || []),
41832
+ _step7;
41833
+ try {
41834
+ for (_iterator6.s(); !(_step7 = _iterator6.n()).done;) {
41835
+ var w = _step7.value;
41836
+ if (!w.scope || !w.packageName) continue;
41837
+ var key = "".concat(w.scope, "/").concat(w.packageName);
41838
+ var sel = depSelections[key];
41839
+ if (!(sel !== null && sel !== void 0 && sel.include) || !(sel !== null && sel !== void 0 && sel.owned)) continue;
41840
+ var localPkgId = w.packageId || "@".concat(w.scope, "/").concat(w.packageName);
41841
+ var defaults = defaultsByPackage[localPkgId];
41842
+ if (!Array.isArray(defaults)) continue;
41843
+ rows.push({
41844
+ key: key,
41845
+ localPkgId: localPkgId,
41846
+ label: "@".concat(w.scope, "/").concat(w.packageName),
41847
+ defaults: defaults
41848
+ });
41849
+ }
41850
+ } catch (err) {
41851
+ _iterator6.e(err);
41852
+ } finally {
41853
+ _iterator6.f();
41854
+ }
41855
+ if (rows.length === 0) {
41856
+ return /*#__PURE__*/jsx("div", {
41857
+ className: "text-sm opacity-60 py-6 text-center",
41858
+ children: "No non-empty defaults found in any owned widget. Nothing to review."
41859
+ });
41860
+ }
41861
+ return /*#__PURE__*/jsx("div", {
41862
+ className: "flex flex-col gap-4",
41863
+ children: rows.map(function (_ref7) {
41864
+ var key = _ref7.key,
41865
+ localPkgId = _ref7.localPkgId,
41866
+ label = _ref7.label,
41867
+ defaults = _ref7.defaults;
41868
+ if (defaults.length === 0) {
41869
+ return /*#__PURE__*/jsxs("div", {
41870
+ className: "border border-white/10 rounded-lg px-4 py-3 bg-white/5",
41871
+ children: [/*#__PURE__*/jsx("div", {
41872
+ className: "text-sm font-semibold font-mono",
41873
+ children: label
41874
+ }), /*#__PURE__*/jsxs("div", {
41875
+ className: "text-xs opacity-60 mt-1",
41876
+ children: ["No non-empty ", /*#__PURE__*/jsx("code", {
41877
+ children: "defaultValue"
41878
+ }), " entries detected."]
41879
+ })]
41880
+ }, key);
41881
+ }
41882
+ return /*#__PURE__*/jsxs("div", {
41883
+ className: "border border-white/10 rounded-lg px-4 py-3 bg-white/5",
41884
+ children: [/*#__PURE__*/jsx("div", {
41885
+ className: "text-sm font-semibold font-mono mb-2",
41886
+ children: label
41887
+ }), /*#__PURE__*/jsx("div", {
41888
+ className: "flex flex-col gap-3",
41889
+ children: defaults.map(function (d) {
41890
+ var _overrides$localPkgId, _d$currentDefault;
41891
+ var overriddenValue = overrides === null || overrides === void 0 || (_overrides$localPkgId = overrides[localPkgId]) === null || _overrides$localPkgId === void 0 || (_overrides$localPkgId = _overrides$localPkgId[d.widgetName]) === null || _overrides$localPkgId === void 0 ? void 0 : _overrides$localPkgId[d.field];
41892
+ var isOverridden = overriddenValue !== undefined;
41893
+ var displayValue = isOverridden ? String(overriddenValue !== null && overriddenValue !== void 0 ? overriddenValue : "") : String((_d$currentDefault = d.currentDefault) !== null && _d$currentDefault !== void 0 ? _d$currentDefault : "");
41894
+ return /*#__PURE__*/jsxs("div", {
41895
+ className: "flex flex-col gap-1",
41896
+ children: [/*#__PURE__*/jsxs("div", {
41897
+ className: "flex items-center gap-2 flex-wrap",
41898
+ children: [/*#__PURE__*/jsxs("code", {
41899
+ className: "text-xs opacity-70",
41900
+ children: [d.widgetName, ".", d.field]
41901
+ }), /*#__PURE__*/jsxs("span", {
41902
+ className: "text-[10px] opacity-50",
41903
+ children: ["(", d.type, ")"]
41904
+ }), /*#__PURE__*/jsx("span", {
41905
+ className: "text-[10px] opacity-50",
41906
+ children: d.displayName
41907
+ }), isOverridden && /*#__PURE__*/jsx("span", {
41908
+ className: "text-[10px] uppercase tracking-wide px-1.5 py-0.5 rounded bg-amber-900/40 text-amber-200",
41909
+ children: "edited"
41910
+ })]
41911
+ }), /*#__PURE__*/jsxs("div", {
41912
+ className: "flex items-center gap-2",
41913
+ children: [/*#__PURE__*/jsx("input", {
41914
+ type: "text",
41915
+ value: displayValue,
41916
+ onChange: function onChange(e) {
41917
+ return _onChange2(localPkgId, d.widgetName, d.field, e.target.value);
41918
+ },
41919
+ className: "flex-1 bg-gray-900 border border-white/10 rounded px-2 py-1 text-xs font-mono"
41920
+ }), isOverridden && /*#__PURE__*/jsx("button", {
41921
+ type: "button",
41922
+ onClick: function onClick() {
41923
+ return _onChange2(localPkgId, d.widgetName, d.field, undefined);
41924
+ },
41925
+ className: "text-xs opacity-60 hover:opacity-100 underline underline-offset-2",
41926
+ title: "Discard edit \u2014 ship the original defaultValue",
41927
+ children: "Reset"
41928
+ })]
41929
+ }), d.instructions && /*#__PURE__*/jsx("div", {
41930
+ className: "text-[10px] opacity-50",
41931
+ children: d.instructions
41932
+ })]
41933
+ }, "".concat(d.widgetName, "|").concat(d.field));
41934
+ })
41935
+ })]
41936
+ }, key);
41937
+ })
41938
+ });
41939
+ }
41940
+
41671
41941
  function ownKeys$q(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
41672
41942
  function _objectSpread$q(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$q(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$q(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
41673
41943
  var LayoutPreview = function LayoutPreview(_ref) {
@@ -57144,26 +57414,36 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
57144
57414
  try {
57145
57415
  var _message$workspaces;
57146
57416
  var workspaces = deepCopy(message["workspaces"]);
57417
+ // LayoutModel returns null when normalization throws (e.g. a
57418
+ // widget config that references a component the registry can't
57419
+ // resolve yet — common right after a fresh dashboard install
57420
+ // where some widgets are still downloading). Filter nulls so
57421
+ // every renderer that walks the layout sees only well-formed
57422
+ // items and never crashes on `Cannot read properties of null
57423
+ // (reading 'type')` or similar.
57147
57424
  var workspacesTemp = workspaces.map(function (ws) {
57148
- var tempLayout = ws["layout"].map(function (layoutOG) {
57425
+ ws["layout"] = (ws["layout"] || []).map(function (layoutOG) {
57149
57426
  return LayoutModel(layoutOG, workspaces, ws["id"]);
57427
+ }).filter(function (item) {
57428
+ return item != null;
57150
57429
  });
57151
- ws["layout"] = tempLayout;
57152
- // Normalize page layouts too
57153
57430
  if (ws.pages && Array.isArray(ws.pages)) {
57154
57431
  ws.pages = ws.pages.map(function (page) {
57155
57432
  if (page.layout && Array.isArray(page.layout)) {
57156
57433
  page.layout = page.layout.map(function (layoutOG) {
57157
57434
  return LayoutModel(layoutOG, workspaces, ws["id"]);
57435
+ }).filter(function (item) {
57436
+ return item != null;
57158
57437
  });
57159
57438
  }
57160
57439
  return page;
57161
57440
  });
57162
57441
  }
57163
- // Normalize sidebar layout
57164
57442
  if (ws.sidebarLayout && Array.isArray(ws.sidebarLayout)) {
57165
57443
  ws.sidebarLayout = ws.sidebarLayout.map(function (layoutOG) {
57166
57444
  return LayoutModel(layoutOG, workspaces, ws["id"]);
57445
+ }).filter(function (item) {
57446
+ return item != null;
57167
57447
  });
57168
57448
  }
57169
57449
  return WorkspaceModel(ws);
@@ -57947,13 +58227,16 @@ var DashboardStageInner = function DashboardStageInner(_ref3) {
57947
58227
  }
57948
58228
  function handleSaveWorkspaceComplete(e, message) {
57949
58229
 
57950
- // Reconstruct workspaces through LayoutModel (same as load path)
58230
+ // Reconstruct workspaces through LayoutModel (same as load path).
58231
+ // Filter nulls so a partially-failed normalize doesn't poison the
58232
+ // layout array — see handleLoadWorkspacesComplete for the rationale.
57951
58233
  var workspaces = deepCopy(message["workspaces"]);
57952
58234
  var workspacesTemp = workspaces.map(function (ws) {
57953
- var tempLayout = ws["layout"].map(function (layoutOG) {
58235
+ ws["layout"] = (ws["layout"] || []).map(function (layoutOG) {
57954
58236
  return LayoutModel(layoutOG, workspaces, ws["id"]);
58237
+ }).filter(function (item) {
58238
+ return item != null;
57955
58239
  });
57956
- ws["layout"] = tempLayout;
57957
58240
  return WorkspaceModel(ws);
57958
58241
  });
57959
58242
  pub.pub("dashboard.workspaceChange", {