@trops/dash-core 0.1.662 → 0.1.663

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
@@ -61188,6 +61188,68 @@ function renderFormItem(displayName, key, instructions, required, value, _onChan
61188
61188
  }, "config-item-".concat(key));
61189
61189
  }
61190
61190
 
61191
+ function useConfigTokens() {
61192
+ var _ref = useContext(ThemeContext) || {},
61193
+ _ref$currentTheme = _ref.currentTheme,
61194
+ currentTheme = _ref$currentTheme === void 0 ? {} : _ref$currentTheme;
61195
+ return {
61196
+ muted: currentTheme["text-neutral-medium"] || "text-gray-400",
61197
+ strong: currentTheme["text-neutral-light"] || "text-gray-200",
61198
+ hairline: currentTheme["border-neutral-dark"] || "border-gray-700",
61199
+ selectedBg: currentTheme["bg-neutral-very-dark"] || "bg-gray-800",
61200
+ selectedBorder: currentTheme["border-primary-dark"] || "border-gray-600",
61201
+ fieldBg: currentTheme["bg-neutral-very-dark"] || "bg-gray-900"
61202
+ };
61203
+ }
61204
+
61205
+ /**
61206
+ * A row in one of the modal's left-hand lists (provider types, widgets,
61207
+ * event handlers) — styled like the Bots view's team list.
61208
+ *
61209
+ * @param {{ title: React.ReactNode, subtitle?: React.ReactNode,
61210
+ * meta?: React.ReactNode, badge?: React.ReactNode,
61211
+ * active?: boolean, mono?: boolean, onClick: () => void }} props
61212
+ * `subtitle` is a registry id (monospace); `meta` a muted count line.
61213
+ */
61214
+ var ConfigListRow = function ConfigListRow(_ref2) {
61215
+ var title = _ref2.title,
61216
+ _ref2$subtitle = _ref2.subtitle,
61217
+ subtitle = _ref2$subtitle === void 0 ? null : _ref2$subtitle,
61218
+ _ref2$meta = _ref2.meta,
61219
+ meta = _ref2$meta === void 0 ? null : _ref2$meta,
61220
+ _ref2$badge = _ref2.badge,
61221
+ badge = _ref2$badge === void 0 ? null : _ref2$badge,
61222
+ _ref2$active = _ref2.active,
61223
+ active = _ref2$active === void 0 ? false : _ref2$active,
61224
+ _ref2$mono = _ref2.mono,
61225
+ mono = _ref2$mono === void 0 ? false : _ref2$mono,
61226
+ onClick = _ref2.onClick;
61227
+ var _useConfigTokens = useConfigTokens(),
61228
+ muted = _useConfigTokens.muted,
61229
+ selectedBg = _useConfigTokens.selectedBg,
61230
+ selectedBorder = _useConfigTokens.selectedBorder;
61231
+ return /*#__PURE__*/jsxs("button", {
61232
+ type: "button",
61233
+ onClick: onClick,
61234
+ "aria-current": active ? "true" : undefined,
61235
+ className: "w-full text-left rounded-lg px-3 py-2 border ".concat(active ? "".concat(selectedBg, " ").concat(selectedBorder) : "border-transparent"),
61236
+ children: [/*#__PURE__*/jsxs("div", {
61237
+ className: "flex flex-row items-center justify-between gap-2 min-w-0",
61238
+ children: [/*#__PURE__*/jsx("span", {
61239
+ className: "text-sm font-medium truncate ".concat(mono ? "font-mono" : ""),
61240
+ children: title
61241
+ }), badge]
61242
+ }), subtitle ? /*#__PURE__*/jsx("div", {
61243
+ className: "text-xs font-mono truncate mt-0.5 ".concat(muted),
61244
+ title: typeof subtitle === "string" ? subtitle : undefined,
61245
+ children: subtitle
61246
+ }) : null, meta ? /*#__PURE__*/jsx("div", {
61247
+ className: "text-xs mt-0.5 ".concat(muted),
61248
+ children: meta
61249
+ }) : null]
61250
+ });
61251
+ };
61252
+
61191
61253
  function ownKeys$g(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; }
61192
61254
  function _objectSpread$g(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$g(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$g(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
61193
61255
  function _createForOfIteratorHelper$b(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$b(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
@@ -61223,6 +61285,9 @@ var WidgetsTab = function WidgetsTab(_ref) {
61223
61285
  stagedPrefs = _ref.stagedPrefs,
61224
61286
  stagePrefField = _ref.stagePrefField,
61225
61287
  stagePrefFieldForAll = _ref.stagePrefFieldForAll;
61288
+ var _useConfigTokens = useConfigTokens(),
61289
+ muted = _useConfigTokens.muted,
61290
+ hairline = _useConfigTokens.hairline;
61226
61291
  // Flatten every widget on the workspace, preserving which layout
61227
61292
  // section each came from (Main / Page N / Sidebar) so the left
61228
61293
  // column can group them cleanly. forEachWidget already dedupes.
@@ -61343,67 +61408,55 @@ var WidgetsTab = function WidgetsTab(_ref) {
61343
61408
  return /*#__PURE__*/jsxs("div", {
61344
61409
  className: "flex h-full min-h-0",
61345
61410
  children: [/*#__PURE__*/jsxs("div", {
61346
- className: "w-64 border-r border-white/10 overflow-y-auto flex-shrink-0",
61347
- children: [sharedFields.length > 0 && /*#__PURE__*/jsxs("button", {
61348
- onClick: function onClick() {
61349
- return setSelectedId(ALL_WIDGETS_ID);
61350
- },
61351
- className: "w-full text-left px-4 py-3 border-b border-white/10 transition-colors ".concat(isAllMode ? "bg-indigo-600/20 text-indigo-200" : "hover:bg-white/5 text-gray-300"),
61352
- children: [/*#__PURE__*/jsxs("div", {
61353
- className: "flex items-center gap-2",
61411
+ className: "w-64 border-r overflow-y-auto flex-shrink-0 p-3 flex flex-col gap-1 ".concat(hairline),
61412
+ children: [sharedFields.length > 0 && /*#__PURE__*/jsx(ConfigListRow, {
61413
+ title: /*#__PURE__*/jsxs("span", {
61414
+ className: "flex flex-row items-center gap-2",
61354
61415
  children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
61355
61416
  icon: "layer-group",
61356
61417
  className: "h-3.5 w-3.5"
61357
- }), /*#__PURE__*/jsx("span", {
61358
- className: "font-semibold text-sm",
61359
- children: "All Widgets"
61360
- })]
61361
- }), /*#__PURE__*/jsxs("div", {
61362
- className: "text-[11px] text-gray-500 mt-0.5",
61363
- children: [sharedFields.length, " shared field", sharedFields.length === 1 ? "" : "s", " \xB7 bulk edit"]
61364
- })]
61418
+ }), "All Widgets"]
61419
+ }),
61420
+ meta: "".concat(sharedFields.length, " shared field").concat(sharedFields.length === 1 ? "" : "s", " \xB7 bulk edit"),
61421
+ active: isAllMode,
61422
+ onClick: function onClick() {
61423
+ return setSelectedId(ALL_WIDGETS_ID);
61424
+ }
61365
61425
  }), groupedWidgets.map(function (_ref2) {
61366
61426
  var _ref3 = _slicedToArray(_ref2, 2),
61367
61427
  section = _ref3[0],
61368
61428
  sectionWidgets = _ref3[1];
61369
61429
  return /*#__PURE__*/jsxs("div", {
61370
- children: [/*#__PURE__*/jsx("div", {
61371
- className: "px-4 pt-3 pb-1 text-[10px] uppercase tracking-wider text-gray-600 font-semibold",
61430
+ className: "flex flex-col gap-1",
61431
+ children: [/*#__PURE__*/jsx(SectionLabel, {
61432
+ className: "px-3 pt-3 pb-1",
61372
61433
  children: section
61373
61434
  }), sectionWidgets.map(function (w) {
61374
61435
  var fieldCount = Object.keys(w.userConfig).length;
61375
61436
  var stagedForWidget = stagedPrefs !== null && stagedPrefs !== void 0 && stagedPrefs[w.id] ? Object.keys(stagedPrefs[w.id]).length : 0;
61376
- var isSel = selectedId === w.id;
61377
- return /*#__PURE__*/jsxs("button", {
61437
+ return /*#__PURE__*/jsx(ConfigListRow, {
61438
+ title: w.displayName,
61439
+ subtitle: w.widgetRef || null,
61440
+ meta: fieldCount === 0 ? "No configurable fields" : "".concat(fieldCount, " field").concat(fieldCount === 1 ? "" : "s"),
61441
+ badge: stagedForWidget > 0 ? /*#__PURE__*/jsxs("span", {
61442
+ className: "flex flex-row items-center gap-1.5 text-xs text-amber-400 flex-shrink-0",
61443
+ title: "Unsaved changes",
61444
+ children: [/*#__PURE__*/jsx("span", {
61445
+ className: "inline-block h-1.5 w-1.5 rounded-full bg-amber-400"
61446
+ }), stagedForWidget]
61447
+ }) : null,
61448
+ active: selectedId === w.id,
61378
61449
  onClick: function onClick() {
61379
61450
  return setSelectedId(w.id);
61380
- },
61381
- className: "w-full text-left px-4 py-2 transition-colors ".concat(isSel ? "bg-indigo-600/20 text-indigo-200" : "hover:bg-white/5 text-gray-300"),
61382
- children: [/*#__PURE__*/jsxs("div", {
61383
- className: "flex items-center justify-between",
61384
- children: [/*#__PURE__*/jsx("span", {
61385
- className: "text-sm truncate",
61386
- children: w.displayName
61387
- }), stagedForWidget > 0 && /*#__PURE__*/jsx("span", {
61388
- className: "text-[10px] bg-amber-500/20 text-amber-300 px-1.5 rounded",
61389
- children: stagedForWidget
61390
- })]
61391
- }), w.widgetRef && /*#__PURE__*/jsx("div", {
61392
- className: "text-[10px] text-gray-500 font-mono truncate mt-0.5",
61393
- title: w.widgetRef,
61394
- children: w.widgetRef
61395
- }), /*#__PURE__*/jsx("div", {
61396
- className: "text-[10px] text-gray-600 mt-0.5",
61397
- children: fieldCount === 0 ? "No configurable fields" : "".concat(fieldCount, " field").concat(fieldCount === 1 ? "" : "s")
61398
- })]
61451
+ }
61399
61452
  }, w.id);
61400
61453
  })]
61401
61454
  }, section);
61402
61455
  })]
61403
61456
  }), /*#__PURE__*/jsxs("div", {
61404
- className: "flex-1 overflow-y-auto p-4 min-w-0",
61457
+ className: "flex-1 overflow-y-auto p-5 min-w-0",
61405
61458
  children: [!selectedId && /*#__PURE__*/jsx("div", {
61406
- className: "text-sm text-gray-500 italic",
61459
+ className: "text-sm italic ".concat(muted),
61407
61460
  children: "Select a widget from the list."
61408
61461
  }), isAllMode && /*#__PURE__*/jsx(BulkEditPane, {
61409
61462
  sharedFields: sharedFields,
@@ -61423,19 +61476,22 @@ function SingleWidgetPane(_ref4) {
61423
61476
  var widget = _ref4.widget,
61424
61477
  effectivePrefs = _ref4.effectivePrefs,
61425
61478
  onFieldChange = _ref4.onFieldChange;
61479
+ var _useConfigTokens2 = useConfigTokens(),
61480
+ muted = _useConfigTokens2.muted,
61481
+ strong = _useConfigTokens2.strong;
61426
61482
  var hasFields = Object.keys(widget.userConfig).length > 0;
61427
61483
  return /*#__PURE__*/jsxs("div", {
61428
61484
  children: [/*#__PURE__*/jsxs("div", {
61429
61485
  className: "mb-3",
61430
61486
  children: [/*#__PURE__*/jsx("div", {
61431
- className: "text-gray-200 font-semibold",
61487
+ className: "font-semibold ".concat(strong),
61432
61488
  children: widget.displayName
61433
61489
  }), widget.widgetRef && /*#__PURE__*/jsx("div", {
61434
- className: "text-xs text-gray-500 font-mono truncate mt-0.5",
61490
+ className: "text-xs font-mono truncate mt-0.5 ".concat(muted),
61435
61491
  title: widget.widgetRef,
61436
61492
  children: widget.widgetRef
61437
61493
  }), /*#__PURE__*/jsx("div", {
61438
- className: "text-xs text-gray-600 mt-0.5",
61494
+ className: "text-xs mt-0.5 ".concat(muted),
61439
61495
  children: widget.section
61440
61496
  })]
61441
61497
  }), hasFields ? /*#__PURE__*/jsx(PanelEditForm, {
@@ -61443,7 +61499,7 @@ function SingleWidgetPane(_ref4) {
61443
61499
  userPrefs: effectivePrefs,
61444
61500
  onFieldChange: onFieldChange
61445
61501
  }) : /*#__PURE__*/jsx("div", {
61446
- className: "text-sm text-gray-500 italic",
61502
+ className: "text-sm italic ".concat(muted),
61447
61503
  children: "This widget has no configurable fields. It may be event-driven \u2014 pair it with a widget that publishes the events it listens for."
61448
61504
  })]
61449
61505
  });
@@ -61452,14 +61508,17 @@ function BulkEditPane(_ref5) {
61452
61508
  var sharedFields = _ref5.sharedFields,
61453
61509
  stagedPrefs = _ref5.stagedPrefs,
61454
61510
  onApplyAll = _ref5.onApplyAll;
61511
+ var _useConfigTokens3 = useConfigTokens(),
61512
+ muted = _useConfigTokens3.muted,
61513
+ strong = _useConfigTokens3.strong;
61455
61514
  return /*#__PURE__*/jsxs("div", {
61456
61515
  children: [/*#__PURE__*/jsxs("div", {
61457
61516
  className: "mb-3",
61458
61517
  children: [/*#__PURE__*/jsx("div", {
61459
- className: "text-gray-200 font-semibold",
61518
+ className: "font-semibold ".concat(strong),
61460
61519
  children: "All Widgets"
61461
61520
  }), /*#__PURE__*/jsx("div", {
61462
- className: "text-xs text-gray-500",
61521
+ className: "text-xs ".concat(muted),
61463
61522
  children: "Fields declared by 2+ widgets on this dashboard. Apply once to update every matching widget."
61464
61523
  })]
61465
61524
  }), /*#__PURE__*/jsxs("div", {
@@ -61471,7 +61530,7 @@ function BulkEditPane(_ref5) {
61471
61530
  onApplyAll: onApplyAll
61472
61531
  }, "".concat(field.key, "::").concat(field.schema.type));
61473
61532
  }), sharedFields.length === 0 && /*#__PURE__*/jsx("div", {
61474
- className: "text-sm text-gray-500 italic",
61533
+ className: "text-sm italic ".concat(muted),
61475
61534
  children: "No shared fields across widgets on this dashboard."
61476
61535
  })]
61477
61536
  })]
@@ -61498,32 +61557,38 @@ function SharedFieldRow(_ref6) {
61498
61557
  if (allSame) setDraft(distinctValues[0]);
61499
61558
  // eslint-disable-next-line react-hooks/exhaustive-deps
61500
61559
  }, [allSame, distinctValues[0]]);
61560
+ var _useConfigTokens4 = useConfigTokens(),
61561
+ muted = _useConfigTokens4.muted,
61562
+ strong = _useConfigTokens4.strong,
61563
+ hairline = _useConfigTokens4.hairline,
61564
+ fieldBg = _useConfigTokens4.fieldBg;
61565
+ var fieldClass = "w-full px-2 py-1.5 rounded-lg border text-sm ".concat(fieldBg, " ").concat(hairline, " ").concat(strong);
61501
61566
  return /*#__PURE__*/jsxs("div", {
61502
- className: "border border-white/10 rounded p-3",
61567
+ className: "rounded-lg border p-3 ".concat(hairline),
61503
61568
  children: [/*#__PURE__*/jsxs("div", {
61504
61569
  className: "flex items-start justify-between gap-3 mb-2",
61505
61570
  children: [/*#__PURE__*/jsxs("div", {
61506
61571
  className: "flex-1 min-w-0",
61507
61572
  children: [/*#__PURE__*/jsx("div", {
61508
- className: "text-sm text-gray-200 font-semibold",
61573
+ className: "text-sm font-semibold ".concat(strong),
61509
61574
  children: field.schema.displayName || field.key
61510
61575
  }), /*#__PURE__*/jsxs("div", {
61511
- className: "text-[11px] text-gray-500",
61576
+ className: "text-xs ".concat(muted),
61512
61577
  children: ["Applies to ", field.widgets.length, " widgets", allSame ? "" : " \xB7 ".concat(distinctValues.length, " distinct values in use")]
61513
61578
  })]
61514
- }), /*#__PURE__*/jsx("button", {
61579
+ }), /*#__PURE__*/jsx(Button3, {
61580
+ title: "Apply to all",
61581
+ size: "sm",
61515
61582
  onClick: function onClick() {
61516
61583
  return onApplyAll(field.widgets, field.key, draft);
61517
- },
61518
- className: "px-3 py-1 text-xs bg-indigo-600 hover:bg-indigo-500 text-white rounded transition-colors",
61519
- children: "Apply to all"
61584
+ }
61520
61585
  })]
61521
61586
  }), field.schema.type === "select" ? /*#__PURE__*/jsx("select", {
61522
61587
  value: draft,
61523
61588
  onChange: function onChange(e) {
61524
61589
  return setDraft(e.target.value);
61525
61590
  },
61526
- className: "w-full px-2 py-1.5 bg-gray-900 border border-white/10 rounded text-sm text-gray-200",
61591
+ className: fieldClass,
61527
61592
  children: (field.schema.options || []).map(function (opt) {
61528
61593
  return /*#__PURE__*/jsx("option", {
61529
61594
  value: opt.value,
@@ -61537,7 +61602,7 @@ function SharedFieldRow(_ref6) {
61537
61602
  return setDraft(e.target.value);
61538
61603
  },
61539
61604
  placeholder: allSame ? "" : "(multiple values — set one for all)",
61540
- className: "w-full px-2 py-1.5 bg-gray-900 border border-white/10 rounded text-sm text-gray-200"
61605
+ className: fieldClass
61541
61606
  })]
61542
61607
  });
61543
61608
  }
@@ -62796,30 +62861,88 @@ function _unsupportedIterableToArray$9(r, a) { if (r) { if ("string" == typeof r
62796
62861
  function _arrayLikeToArray$9(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
62797
62862
  function ownKeys$e(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; }
62798
62863
  function _objectSpread$e(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$e(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$e(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
62799
- var DashboardConfigModal = function DashboardConfigModal(_ref) {
62800
- var isOpen = _ref.isOpen,
62801
- setIsOpen = _ref.setIsOpen,
62802
- workspace = _ref.workspace;
62803
- _ref.workspaces;
62804
- var appProviders = _ref.appProviders,
62805
- getWidgetRequirements = _ref.getWidgetRequirements,
62806
- _ref$getWidgetConfig = _ref.getWidgetConfig,
62807
- getWidgetConfig = _ref$getWidgetConfig === void 0 ? null : _ref$getWidgetConfig,
62808
- onSaveBindings = _ref.onSaveBindings,
62809
- onSaveListeners = _ref.onSaveListeners,
62810
- _ref$onSaveUserPrefs = _ref.onSaveUserPrefs,
62811
- onSaveUserPrefs = _ref$onSaveUserPrefs === void 0 ? null : _ref$onSaveUserPrefs,
62812
- _ref$onSkip = _ref.onSkip,
62813
- onSkip = _ref$onSkip === void 0 ? null : _ref$onSkip,
62814
- _ref$initialTab = _ref.initialTab,
62815
- initialTab = _ref$initialTab === void 0 ? "providers" : _ref$initialTab,
62816
- _ref$onOpenBotsView = _ref.onOpenBotsView,
62817
- onOpenBotsView = _ref$onOpenBotsView === void 0 ? null : _ref$onOpenBotsView;
62864
+ var ConfigTab = function ConfigTab(_ref) {
62865
+ var active = _ref.active,
62866
+ onClick = _ref.onClick,
62867
+ children = _ref.children;
62868
+ var _useConfigTokens = useConfigTokens(),
62869
+ muted = _useConfigTokens.muted;
62870
+ return /*#__PURE__*/jsx("button", {
62871
+ type: "button",
62872
+ role: "tab",
62873
+ "aria-selected": active,
62874
+ onClick: onClick,
62875
+ className: "py-2.5 text-sm font-medium -mb-px border-b-2 ".concat(active ? "border-indigo-400" : "border-transparent ".concat(muted)),
62876
+ children: children
62877
+ });
62878
+ };
62879
+
62880
+ /**
62881
+ * DashboardConfigModal
62882
+ *
62883
+ * Workspace-scoped wiring panel. Lets a user assign providers to every
62884
+ * widget in the current workspace from one place instead of opening each
62885
+ * widget's settings individually. v1 ships the Providers tab; Listeners
62886
+ * tab lands in a follow-up PR (data model needs more exploration).
62887
+ *
62888
+ * Auto-opens on dashboard install when any required provider is still
62889
+ * unresolved after applying app-wide defaults. Also openable manually
62890
+ * via the dashboard toolbar's config button.
62891
+ *
62892
+ * @param {boolean} isOpen
62893
+ * @param {(open: boolean) => void} setIsOpen
62894
+ * @param {object} workspace Current workspace (layout/pages/sidebarLayout/selectedProviders).
62895
+ * @param {object|Array} appProviders Either a map keyed by provider name, or an array. Each entry has
62896
+ * at least { name?, type, providerClass, isDefaultForType }.
62897
+ * @param {(componentName: string) => Array} getWidgetRequirements
62898
+ * Called per widget instance. Should return the `providers: [...]`
62899
+ * array from the component's .dash.js. Usually backed by
62900
+ * ComponentManager.componentMap().
62901
+ * @param {(componentName: string) => object | null} getWidgetConfig
62902
+ * Called per widget instance. Returns the full ComponentManager
62903
+ * entry (events, eventHandlers, displayName, …). Used by the
62904
+ * Listeners tab to discover what each widget emits/handles.
62905
+ * @param {(changes: Array<{widgetId, providerType, providerName}>) => void} onSaveBindings
62906
+ * Called with the staged provider changes on Save. The parent persists
62907
+ * by forwarding to its existing `handleProviderSelect` /
62908
+ * `saveWorkspace` plumbing.
62909
+ * @param {(changes: {adds: Array, removes: Array}) => void} onSaveListeners
62910
+ * Called with the staged listener changes on Save. Each entry is
62911
+ * `{ receiverItemId, handlerName, sourceComponent, sourceItemId, eventName }`.
62912
+ * Parent uses `applyWiringChanges` + saveWorkspace.
62913
+ * @param {(changes: Array<{widgetId, key, value}>) => void} onSaveUserPrefs
62914
+ * Called with the staged widget userPrefs changes on Save. Parent
62915
+ * applies them to workspace + persists via saveWorkspace. Enables
62916
+ * bulk-edit of fields shared across widgets (e.g. basePath).
62917
+ * @param {"providers"|"listeners"|"widgets"} initialTab Which tab to focus when the modal opens.
62918
+ */
62919
+ var DashboardConfigModal = function DashboardConfigModal(_ref2) {
62920
+ var isOpen = _ref2.isOpen,
62921
+ setIsOpen = _ref2.setIsOpen,
62922
+ workspace = _ref2.workspace;
62923
+ _ref2.workspaces;
62924
+ var appProviders = _ref2.appProviders,
62925
+ getWidgetRequirements = _ref2.getWidgetRequirements,
62926
+ _ref2$getWidgetConfig = _ref2.getWidgetConfig,
62927
+ getWidgetConfig = _ref2$getWidgetConfig === void 0 ? null : _ref2$getWidgetConfig,
62928
+ onSaveBindings = _ref2.onSaveBindings,
62929
+ onSaveListeners = _ref2.onSaveListeners,
62930
+ _ref2$onSaveUserPrefs = _ref2.onSaveUserPrefs,
62931
+ onSaveUserPrefs = _ref2$onSaveUserPrefs === void 0 ? null : _ref2$onSaveUserPrefs,
62932
+ _ref2$onSkip = _ref2.onSkip,
62933
+ onSkip = _ref2$onSkip === void 0 ? null : _ref2$onSkip,
62934
+ _ref2$initialTab = _ref2.initialTab,
62935
+ initialTab = _ref2$initialTab === void 0 ? "providers" : _ref2$initialTab,
62936
+ _ref2$onOpenBotsView = _ref2.onOpenBotsView,
62937
+ onOpenBotsView = _ref2$onOpenBotsView === void 0 ? null : _ref2$onOpenBotsView;
62818
62938
  var _useContext = useContext(ThemeContext),
62819
62939
  currentTheme = _useContext.currentTheme;
62820
62940
  var panelStyles = getStylesForItem(themeObjects.PANEL, currentTheme, {
62821
62941
  grow: false
62822
62942
  });
62943
+ var _useConfigTokens2 = useConfigTokens(),
62944
+ muted = _useConfigTokens2.muted,
62945
+ hairline = _useConfigTokens2.hairline;
62823
62946
 
62824
62947
  // Active tab. Defaults to whatever the parent requested via
62825
62948
  // `initialTab`. Resets on each open via the modal's mount cycle.
@@ -63028,10 +63151,10 @@ var DashboardConfigModal = function DashboardConfigModal(_ref) {
63028
63151
  }
63029
63152
  return Array.from(byPackage.values()).map(function (e) {
63030
63153
  return _objectSpread$e(_objectSpread$e({}, e), {}, {
63031
- components: Array.from(e.components.entries()).map(function (_ref2) {
63032
- var _ref3 = _slicedToArray(_ref2, 2),
63033
- component = _ref3[0],
63034
- count = _ref3[1];
63154
+ components: Array.from(e.components.entries()).map(function (_ref3) {
63155
+ var _ref4 = _slicedToArray(_ref3, 2),
63156
+ component = _ref4[0],
63157
+ count = _ref4[1];
63035
63158
  return {
63036
63159
  component: component,
63037
63160
  count: count
@@ -63352,80 +63475,84 @@ var DashboardConfigModal = function DashboardConfigModal(_ref) {
63352
63475
  children: /*#__PURE__*/jsxs("div", {
63353
63476
  className: "flex flex-col h-full w-full rounded-lg overflow-clip border ".concat(panelStyles.backgroundColor || "", " ").concat(panelStyles.borderColor || "", " ").concat(panelStyles.textColor || ""),
63354
63477
  children: [/*#__PURE__*/jsxs("div", {
63355
- className: "flex-shrink-0 flex flex-row items-center justify-between p-4",
63478
+ className: "flex-shrink-0 flex flex-row items-start justify-between px-5 pt-4",
63356
63479
  children: [/*#__PURE__*/jsxs("div", {
63357
- className: "flex items-center gap-3",
63358
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
63359
- icon: "sliders",
63360
- className: "h-4 w-4 opacity-70"
63361
- }), /*#__PURE__*/jsx("span", {
63362
- className: "text-lg font-semibold",
63363
- children: "Dashboard Config"
63364
- }), unresolvedCount > 0 && /*#__PURE__*/jsx(Tag, {
63365
- text: "".concat(unresolvedCount, " unresolved"),
63366
- className: "bg-amber-900/40 text-amber-200"
63367
- })]
63480
+ className: "flex flex-col gap-0.5 min-w-0",
63481
+ children: [/*#__PURE__*/jsxs("div", {
63482
+ className: "flex flex-row items-center gap-3",
63483
+ children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
63484
+ icon: "sliders",
63485
+ className: "h-4 w-4 opacity-70"
63486
+ }), /*#__PURE__*/jsx("span", {
63487
+ className: "text-lg font-semibold",
63488
+ children: "Dashboard Config"
63489
+ }), unresolvedCount > 0 && /*#__PURE__*/jsxs("span", {
63490
+ "data-testid": "config-unresolved",
63491
+ className: "flex flex-row items-center gap-1.5 text-sm text-amber-400",
63492
+ children: [/*#__PURE__*/jsx("span", {
63493
+ className: "inline-block h-1.5 w-1.5 rounded-full bg-amber-400"
63494
+ }), unresolvedCount, " unresolved"]
63495
+ })]
63496
+ }), workspace !== null && workspace !== void 0 && workspace.name ? /*#__PURE__*/jsx("span", {
63497
+ className: "text-sm truncate ".concat(muted),
63498
+ children: workspace.name
63499
+ }) : null]
63368
63500
  }), /*#__PURE__*/jsx("button", {
63369
63501
  type: "button",
63370
63502
  onClick: handleCancel,
63503
+ "aria-label": "Close",
63371
63504
  className: "opacity-50 hover:opacity-100 transition-opacity cursor-pointer",
63372
63505
  children: /*#__PURE__*/jsx(FontAwesomeIcon, {
63373
63506
  icon: "xmark",
63374
63507
  className: "h-5 w-5"
63375
63508
  })
63376
63509
  })]
63377
- }), /*#__PURE__*/jsx(Divider, {}), /*#__PURE__*/jsxs("div", {
63378
- className: "flex-shrink-0 flex flex-row items-center gap-2 px-4 pt-3",
63379
- children: [/*#__PURE__*/jsxs("button", {
63380
- type: "button",
63510
+ }), /*#__PURE__*/jsxs("div", {
63511
+ role: "tablist",
63512
+ className: "flex-shrink-0 flex flex-row gap-6 px-5 mt-3 border-b ".concat(hairline),
63513
+ children: [/*#__PURE__*/jsxs(ConfigTab, {
63514
+ active: activeTab === "providers",
63381
63515
  onClick: function onClick() {
63382
63516
  return setActiveTab("providers");
63383
63517
  },
63384
- className: "px-3 py-1.5 text-sm font-medium -mb-px border-b-2 ".concat(activeTab === "providers" ? "border-indigo-400" : "border-transparent opacity-60 hover:opacity-100"),
63385
63518
  children: ["Providers", unresolvedCount > 0 && /*#__PURE__*/jsx("span", {
63386
63519
  className: "ml-2 inline-block h-1.5 w-1.5 rounded-full bg-amber-400 align-middle"
63387
63520
  })]
63388
- }), /*#__PURE__*/jsx("button", {
63389
- type: "button",
63521
+ }), /*#__PURE__*/jsx(ConfigTab, {
63522
+ active: activeTab === "listeners",
63390
63523
  onClick: function onClick() {
63391
63524
  return setActiveTab("listeners");
63392
63525
  },
63393
- className: "px-3 py-1.5 text-sm font-medium -mb-px border-b-2 ".concat(activeTab === "listeners" ? "border-indigo-400" : "border-transparent opacity-60 hover:opacity-100"),
63394
63526
  children: "Listeners"
63395
- }), /*#__PURE__*/jsx("button", {
63396
- type: "button",
63527
+ }), /*#__PURE__*/jsx(ConfigTab, {
63528
+ active: activeTab === "notifications",
63397
63529
  onClick: function onClick() {
63398
63530
  return setActiveTab("notifications");
63399
63531
  },
63400
- className: "px-3 py-1.5 text-sm font-medium -mb-px border-b-2 ".concat(activeTab === "notifications" ? "border-indigo-400" : "border-transparent opacity-60 hover:opacity-100"),
63401
63532
  children: "Notifications"
63402
- }), /*#__PURE__*/jsx("button", {
63403
- type: "button",
63533
+ }), /*#__PURE__*/jsx(ConfigTab, {
63534
+ active: activeTab === "widgets",
63404
63535
  onClick: function onClick() {
63405
63536
  return setActiveTab("widgets");
63406
63537
  },
63407
- className: "px-3 py-1.5 text-sm font-medium -mb-px border-b-2 ".concat(activeTab === "widgets" ? "border-indigo-400" : "border-transparent opacity-60 hover:opacity-100"),
63408
63538
  children: "Widgets"
63409
- }), /*#__PURE__*/jsx("button", {
63410
- type: "button",
63539
+ }), /*#__PURE__*/jsx(ConfigTab, {
63540
+ active: activeTab === "permissions",
63411
63541
  onClick: function onClick() {
63412
63542
  return setActiveTab("permissions");
63413
63543
  },
63414
- className: "px-3 py-1.5 text-sm font-medium -mb-px border-b-2 ".concat(activeTab === "permissions" ? "border-indigo-400" : "border-transparent opacity-60 hover:opacity-100"),
63415
63544
  children: "Permissions"
63416
- }), /*#__PURE__*/jsx("button", {
63417
- type: "button",
63545
+ }), /*#__PURE__*/jsx(ConfigTab, {
63546
+ active: activeTab === "bots",
63418
63547
  onClick: function onClick() {
63419
63548
  return setActiveTab("bots");
63420
63549
  },
63421
- className: "px-3 py-1.5 text-sm font-medium -mb-px border-b-2 ".concat(activeTab === "bots" ? "border-indigo-400" : "border-transparent opacity-60 hover:opacity-100"),
63422
63550
  children: "Bots"
63423
- }), /*#__PURE__*/jsxs("button", {
63424
- type: "button",
63551
+ }), /*#__PURE__*/jsxs(ConfigTab, {
63552
+ active: activeTab === "dependencies",
63425
63553
  onClick: function onClick() {
63426
63554
  return setActiveTab("dependencies");
63427
63555
  },
63428
- className: "px-3 py-1.5 text-sm font-medium -mb-px border-b-2 ".concat(activeTab === "dependencies" ? "border-indigo-400" : "border-transparent opacity-60 hover:opacity-100"),
63429
63556
  children: ["Dependencies", dependencyCount > 0 && /*#__PURE__*/jsxs(Caption2, {
63430
63557
  className: "ml-2",
63431
63558
  children: ["(", dependencyCount, ")"]
@@ -63433,7 +63560,7 @@ var DashboardConfigModal = function DashboardConfigModal(_ref) {
63433
63560
  className: "ml-1 inline-block h-1.5 w-1.5 rounded-full bg-amber-400 align-middle"
63434
63561
  })]
63435
63562
  })]
63436
- }), /*#__PURE__*/jsx(Divider, {}), /*#__PURE__*/jsxs("div", {
63563
+ }), /*#__PURE__*/jsxs("div", {
63437
63564
  className: "flex-1 min-h-0 ".concat(activeTab === "widgets" ? "" : "p-5"),
63438
63565
  children: [activeTab === "listeners" && /*#__PURE__*/jsx(ListenersTab, {
63439
63566
  emitters: emitters,
@@ -63493,8 +63620,8 @@ var DashboardConfigModal = function DashboardConfigModal(_ref) {
63493
63620
  * write fails the user can re-toggle. No staging — the bulk modal
63494
63621
  * doesn't gate the user behind a Save button for boolean prefs.
63495
63622
  */
63496
- function NotificationsTab(_ref4) {
63497
- var workspace = _ref4.workspace;
63623
+ function NotificationsTab(_ref5) {
63624
+ var workspace = _ref5.workspace;
63498
63625
  var _useState9 = useState(""),
63499
63626
  _useState0 = _slicedToArray(_useState9, 2),
63500
63627
  searchQuery = _useState0[0],
@@ -63736,12 +63863,16 @@ function NotificationsTab(_ref4) {
63736
63863
  * dot per-type when any widget of that type is unresolved). Column 2
63737
63864
  * shows the selected type's bulk dropdown + per-widget dropdowns.
63738
63865
  */
63739
- function ProvidersTab(_ref5) {
63866
+ function ProvidersTab(_ref6) {
63740
63867
  var _typeEntries$, _selectedRows$;
63741
- var grouped = _ref5.grouped,
63742
- providersByType = _ref5.providersByType,
63743
- onBulk = _ref5.onBulk,
63744
- onPerWidget = _ref5.onPerWidget;
63868
+ var grouped = _ref6.grouped,
63869
+ providersByType = _ref6.providersByType,
63870
+ onBulk = _ref6.onBulk,
63871
+ onPerWidget = _ref6.onPerWidget;
63872
+ var _useConfigTokens3 = useConfigTokens(),
63873
+ muted = _useConfigTokens3.muted,
63874
+ hairline = _useConfigTokens3.hairline,
63875
+ fieldBg = _useConfigTokens3.fieldBg;
63745
63876
  var typeEntries = useMemo(function () {
63746
63877
  return Array.from(grouped.entries());
63747
63878
  }, [grouped]);
@@ -63772,73 +63903,66 @@ function ProvidersTab(_ref5) {
63772
63903
  return /*#__PURE__*/jsxs("div", {
63773
63904
  className: "flex flex-row gap-3 h-full min-h-0",
63774
63905
  children: [/*#__PURE__*/jsxs("div", {
63775
- className: "w-56 flex-shrink-0 overflow-hidden flex flex-col border-r border-white/10",
63776
- children: [/*#__PURE__*/jsx("div", {
63777
- className: "px-3 py-2 text-xs font-semibold opacity-50 uppercase tracking-wider",
63906
+ className: "w-56 flex-shrink-0 overflow-hidden flex flex-col",
63907
+ children: [/*#__PURE__*/jsx(SectionLabel, {
63908
+ className: "px-3 mb-2",
63778
63909
  children: "Provider Types"
63779
- }), /*#__PURE__*/jsx(Divider, {}), /*#__PURE__*/jsx("div", {
63780
- className: "overflow-y-auto flex-1",
63781
- children: typeEntries.map(function (_ref6) {
63782
- var _ref7 = _slicedToArray(_ref6, 2),
63783
- providerType = _ref7[0],
63784
- rows = _ref7[1];
63785
- var isActive = selectedType === providerType;
63910
+ }), /*#__PURE__*/jsx("div", {
63911
+ className: "overflow-y-auto flex-1 flex flex-col gap-1",
63912
+ children: typeEntries.map(function (_ref7) {
63913
+ var _ref8 = _slicedToArray(_ref7, 2),
63914
+ providerType = _ref8[0],
63915
+ rows = _ref8[1];
63786
63916
  var unresolvedHere = rows.filter(function (r) {
63787
63917
  return r.required && !r.resolvedProviderName;
63788
63918
  }).length;
63789
- return /*#__PURE__*/jsxs("button", {
63790
- type: "button",
63919
+ return /*#__PURE__*/jsx(ConfigListRow, {
63920
+ title: providerType,
63921
+ active: selectedType === providerType,
63791
63922
  onClick: function onClick() {
63792
63923
  return setSelectedType(providerType);
63793
63924
  },
63794
- className: "w-full text-left px-3 py-2 border-l-2 ".concat(isActive ? "bg-indigo-900/30 border-indigo-400" : "border-transparent hover:bg-white/5"),
63795
- children: [/*#__PURE__*/jsxs("div", {
63796
- className: "flex items-center gap-2",
63925
+ meta: "".concat(rows.length, " widget").concat(rows.length === 1 ? "" : "s"),
63926
+ badge: unresolvedHere > 0 ? /*#__PURE__*/jsxs("span", {
63927
+ className: "flex flex-row items-center gap-1.5 text-xs text-amber-400 flex-shrink-0",
63797
63928
  children: [/*#__PURE__*/jsx("span", {
63798
- className: "text-sm font-medium truncate",
63799
- children: providerType
63800
- }), unresolvedHere > 0 && /*#__PURE__*/jsxs("span", {
63801
- className: "text-[10px] text-amber-300 flex items-center gap-1",
63802
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
63803
- icon: "triangle-exclamation",
63804
- className: "h-2.5 w-2.5"
63805
- }), unresolvedHere]
63806
- })]
63807
- }), /*#__PURE__*/jsxs("div", {
63808
- className: "text-xs opacity-50 mt-0.5",
63809
- children: [rows.length, " widget", rows.length === 1 ? "" : "s"]
63810
- })]
63929
+ className: "inline-block h-1.5 w-1.5 rounded-full bg-amber-400"
63930
+ }), unresolvedHere]
63931
+ }) : null
63811
63932
  }, providerType);
63812
63933
  })
63813
63934
  })]
63935
+ }), /*#__PURE__*/jsx("div", {
63936
+ "aria-hidden": true,
63937
+ className: "flex-shrink-0 border-r ".concat(hairline)
63814
63938
  }), /*#__PURE__*/jsx("div", {
63815
63939
  className: "flex-1 min-w-0 overflow-hidden flex flex-col",
63816
63940
  children: selectedType ? /*#__PURE__*/jsxs(Fragment, {
63817
63941
  children: [/*#__PURE__*/jsxs("div", {
63818
- className: "px-4 py-3 flex-shrink-0",
63942
+ className: "px-4 pb-3 flex-shrink-0 border-b ".concat(hairline),
63819
63943
  children: [/*#__PURE__*/jsxs("div", {
63820
63944
  className: "text-sm font-semibold",
63821
63945
  children: [selectedType, " ", /*#__PURE__*/jsx("span", {
63822
- className: "opacity-60 font-normal",
63946
+ className: "font-normal ".concat(muted),
63823
63947
  children: "provider"
63824
63948
  })]
63825
63949
  }), /*#__PURE__*/jsx("div", {
63826
- className: "text-xs opacity-60 mt-1",
63950
+ className: "text-xs mt-1 ".concat(muted),
63827
63951
  children: "Apply one provider to every widget of this type, or adjust per-widget below."
63828
63952
  })]
63829
- }), /*#__PURE__*/jsx(Divider, {}), /*#__PURE__*/jsxs("div", {
63953
+ }), /*#__PURE__*/jsxs("div", {
63830
63954
  className: "flex-1 overflow-y-auto p-4 space-y-4",
63831
63955
  children: [/*#__PURE__*/jsxs("div", {
63832
63956
  className: "flex items-center gap-3",
63833
63957
  children: [/*#__PURE__*/jsx("span", {
63834
- className: "text-xs opacity-60 flex-shrink-0 w-20",
63958
+ className: "text-xs flex-shrink-0 w-20 ".concat(muted),
63835
63959
  children: "Bulk assign"
63836
63960
  }), /*#__PURE__*/jsxs("select", {
63837
63961
  value: topValue,
63838
63962
  onChange: function onChange(e) {
63839
63963
  return onBulk(selectedType, e.target.value);
63840
63964
  },
63841
- className: "flex-1 bg-gray-800 border border-white/10 rounded px-3 py-1.5 text-sm",
63965
+ className: "flex-1 rounded-lg border px-3 py-1.5 text-sm ".concat(fieldBg, " ").concat(hairline),
63842
63966
  children: [/*#__PURE__*/jsx("option", {
63843
63967
  value: "",
63844
63968
  children: "\u2014 Select provider \u2014"
@@ -63850,10 +63974,11 @@ function ProvidersTab(_ref5) {
63850
63974
  })]
63851
63975
  })]
63852
63976
  }), /*#__PURE__*/jsxs("div", {
63853
- children: [/*#__PURE__*/jsx("div", {
63854
- className: "text-xs font-semibold opacity-50 uppercase tracking-wider mb-2",
63977
+ className: "flex flex-col gap-2",
63978
+ children: [/*#__PURE__*/jsx(SectionLabel, {
63855
63979
  children: "Per-widget"
63856
63980
  }), /*#__PURE__*/jsx("div", {
63981
+ className: "flex flex-col gap-2",
63857
63982
  children: selectedRows.map(function (row) {
63858
63983
  var _row$layoutItem;
63859
63984
  var hasExplicitOverride = !!((_row$layoutItem = row.layoutItem) !== null && _row$layoutItem !== void 0 && (_row$layoutItem = _row$layoutItem.selectedProviders) !== null && _row$layoutItem !== void 0 && _row$layoutItem[selectedType]);
@@ -63861,35 +63986,29 @@ function ProvidersTab(_ref5) {
63861
63986
  var isMissing = !row.resolvedProviderName;
63862
63987
  var needsAttention = isRequired && isMissing;
63863
63988
  return /*#__PURE__*/jsxs("div", {
63864
- className: "flex flex-row items-center gap-3 py-2 px-2 rounded border-l-2 transition-colors ".concat(needsAttention ? "bg-red-900 border-red-500" : "border-transparent hover:bg-gray-800"),
63989
+ "data-testid": "provider-row",
63990
+ className: "flex flex-row items-center gap-3 rounded-lg border px-3 py-2 ".concat(hairline),
63865
63991
  children: [/*#__PURE__*/jsxs("div", {
63866
63992
  className: "flex-1 min-w-0",
63867
- children: [/*#__PURE__*/jsxs("div", {
63868
- className: "text-sm truncate flex items-center gap-1.5 ".concat(needsAttention ? "font-semibold text-red-100" : "font-medium"),
63869
- children: [/*#__PURE__*/jsx("span", {
63870
- className: "truncate",
63871
- children: row.label || row.component || "widget"
63872
- }), isRequired && /*#__PURE__*/jsx("span", {
63873
- className: needsAttention ? "text-red-300" : "text-indigo-300",
63874
- title: "Required provider",
63875
- "aria-label": "required",
63876
- children: "*"
63877
- })]
63878
- }), (row.widgetRef || row.component) && /*#__PURE__*/jsx(Caption, {
63879
- block: true,
63880
- className: "font-mono truncate mt-0.5",
63993
+ children: [/*#__PURE__*/jsx("div", {
63994
+ className: "text-sm font-medium truncate",
63995
+ children: row.label || row.component || "widget"
63996
+ }), (row.widgetRef || row.component) && /*#__PURE__*/jsx("div", {
63997
+ className: "text-xs font-mono truncate mt-0.5 ".concat(muted),
63881
63998
  title: row.widgetRef || row.component,
63882
63999
  children: row.widgetRef || row.component
63883
64000
  }), /*#__PURE__*/jsxs("div", {
63884
- className: "flex items-center gap-1.5 mt-1 text-xs",
63885
- children: [/*#__PURE__*/jsx("span", {
63886
- className: "uppercase tracking-wide px-1.5 py-0.5 rounded font-semibold ".concat(needsAttention ? "bg-red-600 text-white" : isRequired ? "bg-indigo-800 text-indigo-100" : "bg-gray-700 text-gray-300"),
63887
- children: isRequired ? "required" : "optional"
64001
+ className: "flex flex-row items-center gap-3 mt-1 text-xs",
64002
+ children: [/*#__PURE__*/jsxs("span", {
64003
+ className: "flex flex-row items-center gap-1.5 uppercase tracking-wider font-semibold ".concat(needsAttention ? "text-amber-400" : muted),
64004
+ children: [needsAttention && /*#__PURE__*/jsx("span", {
64005
+ className: "inline-block h-1.5 w-1.5 rounded-full bg-amber-400"
64006
+ }), isRequired ? "Required" : "Optional"]
63888
64007
  }), hasExplicitOverride && /*#__PURE__*/jsx("span", {
63889
- className: "uppercase tracking-wide px-1.5 py-0.5 rounded font-semibold bg-indigo-900 text-indigo-200",
63890
- children: "override"
64008
+ className: "uppercase tracking-wider font-semibold ".concat(muted),
64009
+ children: "Override"
63891
64010
  }), /*#__PURE__*/jsx("span", {
63892
- className: "opacity-40 truncate ml-1",
64011
+ className: "font-mono truncate ".concat(muted),
63893
64012
  children: (row.widgetId || "").slice(0, 8)
63894
64013
  })]
63895
64014
  })]
@@ -63898,7 +64017,7 @@ function ProvidersTab(_ref5) {
63898
64017
  onChange: function onChange(e) {
63899
64018
  return onPerWidget(row.widgetId, selectedType, e.target.value);
63900
64019
  },
63901
- className: "bg-gray-800 border rounded px-2 py-1 text-xs min-w-[12rem] ".concat(needsAttention ? "border-red-400" : "border-gray-700"),
64020
+ className: "w-48 flex-shrink-0 rounded-lg border px-2 py-1 text-xs ".concat(fieldBg, " ").concat(needsAttention ? "border-amber-400" : hairline),
63902
64021
  children: [/*#__PURE__*/jsx("option", {
63903
64022
  value: "",
63904
64023
  children: "\u2014 none \u2014"
@@ -63915,7 +64034,7 @@ function ProvidersTab(_ref5) {
63915
64034
  })]
63916
64035
  })]
63917
64036
  }) : /*#__PURE__*/jsx("div", {
63918
- className: "flex-1 flex items-center justify-center text-sm opacity-60",
64037
+ className: "flex-1 flex items-center justify-center text-sm ".concat(muted),
63919
64038
  children: "Pick a provider type to bulk-assign or adjust per widget."
63920
64039
  })
63921
64040
  })]
@@ -63936,8 +64055,8 @@ function ProvidersTab(_ref5) {
63936
64055
  * package (no `config.id` / `config.package` / item.workspace hint).
63937
64056
  * Usually this is a stale layout item whose widget got uninstalled.
63938
64057
  */
63939
- function DependenciesTab(_ref9) {
63940
- var dependencies = _ref9.dependencies;
64058
+ function DependenciesTab(_ref0) {
64059
+ var dependencies = _ref0.dependencies;
63941
64060
  if (!dependencies || dependencies.length === 0) {
63942
64061
  return /*#__PURE__*/jsx("div", {
63943
64062
  className: "flex items-center justify-center h-full text-sm opacity-60 text-center",
@@ -64010,13 +64129,16 @@ function sameWiringEntry(a, b) {
64010
64129
  * adjusts wiring per handler from a single dropdown of all emitters'
64011
64130
  * (widget × event) pairs.
64012
64131
  */
64013
- function ListenersTab(_ref0) {
64132
+ function ListenersTab(_ref1) {
64014
64133
  var _receivers$;
64015
- var emitters = _ref0.emitters,
64016
- receivers = _ref0.receivers,
64017
- wiring = _ref0.wiring,
64018
- onAdd = _ref0.onAdd,
64019
- onRemove = _ref0.onRemove;
64134
+ var emitters = _ref1.emitters,
64135
+ receivers = _ref1.receivers,
64136
+ wiring = _ref1.wiring,
64137
+ onAdd = _ref1.onAdd,
64138
+ onRemove = _ref1.onRemove;
64139
+ var _useConfigTokens4 = useConfigTokens(),
64140
+ muted = _useConfigTokens4.muted,
64141
+ hairline = _useConfigTokens4.hairline;
64020
64142
  var _useState17 = useState(((_receivers$ = receivers[0]) === null || _receivers$ === void 0 ? void 0 : _receivers$.key) || null),
64021
64143
  _useState18 = _slicedToArray(_useState17, 2),
64022
64144
  selectedReceiverKey = _useState18[0],
@@ -64072,31 +64194,25 @@ function ListenersTab(_ref0) {
64072
64194
  className: "flex flex-row gap-3 flex-1 min-h-0",
64073
64195
  children: [/*#__PURE__*/jsxs("div", {
64074
64196
  className: "w-56 flex-shrink-0 overflow-hidden flex flex-col",
64075
- children: [/*#__PURE__*/jsx("div", {
64076
- className: "px-3 py-2 text-xs font-semibold opacity-50 uppercase tracking-wider",
64197
+ children: [/*#__PURE__*/jsx(SectionLabel, {
64198
+ className: "px-3 mb-2",
64077
64199
  children: "Widgets"
64078
- }), /*#__PURE__*/jsx(Divider, {}), /*#__PURE__*/jsx("div", {
64079
- className: "overflow-y-auto flex-1",
64200
+ }), /*#__PURE__*/jsx("div", {
64201
+ className: "overflow-y-auto flex-1 flex flex-col gap-1",
64080
64202
  children: receivers.map(function (r) {
64081
- var isActive = r.key === selectedReceiverKey;
64082
- return /*#__PURE__*/jsxs("button", {
64083
- type: "button",
64203
+ return /*#__PURE__*/jsx(ConfigListRow, {
64204
+ title: r.label,
64205
+ subtitle: r.widgetRef || null,
64206
+ active: r.key === selectedReceiverKey,
64084
64207
  onClick: function onClick() {
64085
64208
  return setSelectedReceiverKey(r.key);
64086
- },
64087
- className: "w-full text-left px-3 py-2 border-l-2 ".concat(isActive ? "bg-indigo-900/30 border-indigo-400" : "border-transparent hover:bg-white/5"),
64088
- children: [/*#__PURE__*/jsx("div", {
64089
- className: "text-sm font-medium truncate",
64090
- children: r.label
64091
- }), r.widgetRef && /*#__PURE__*/jsx(Caption, {
64092
- block: true,
64093
- className: "font-mono truncate mt-0.5",
64094
- title: r.widgetRef,
64095
- children: r.widgetRef
64096
- })]
64209
+ }
64097
64210
  }, r.key);
64098
64211
  })
64099
64212
  })]
64213
+ }), /*#__PURE__*/jsx("div", {
64214
+ "aria-hidden": true,
64215
+ className: "flex-shrink-0 border-r ".concat(hairline)
64100
64216
  }), selectedReceiver ? /*#__PURE__*/jsxs(Fragment, {
64101
64217
  children: [/*#__PURE__*/jsx(HandlersColumn, {
64102
64218
  receiver: selectedReceiver,
@@ -64116,7 +64232,7 @@ function ListenersTab(_ref0) {
64116
64232
  onRemove: onRemove
64117
64233
  })]
64118
64234
  }) : /*#__PURE__*/jsx("div", {
64119
- className: "flex-1 min-w-0 flex items-center justify-center text-sm opacity-60",
64235
+ className: "flex-1 min-w-0 flex items-center justify-center text-sm ".concat(muted),
64120
64236
  children: "Pick a widget on the left to wire its handlers."
64121
64237
  })]
64122
64238
  })
@@ -64129,11 +64245,11 @@ function ListenersTab(_ref0) {
64129
64245
  * third column. Matches the left-column look from
64130
64246
  * PanelEditItemHandlers.
64131
64247
  */
64132
- function HandlersColumn(_ref10) {
64133
- var receiver = _ref10.receiver,
64134
- myWiring = _ref10.myWiring,
64135
- selectedHandler = _ref10.selectedHandler,
64136
- onSelectHandler = _ref10.onSelectHandler;
64248
+ function HandlersColumn(_ref11) {
64249
+ var receiver = _ref11.receiver,
64250
+ myWiring = _ref11.myWiring,
64251
+ selectedHandler = _ref11.selectedHandler,
64252
+ onSelectHandler = _ref11.onSelectHandler;
64137
64253
  var countsByHandler = useMemo(function () {
64138
64254
  var m = new Map();
64139
64255
  var _iterator9 = _createForOfIteratorHelper$9(myWiring),
@@ -64150,44 +64266,43 @@ function HandlersColumn(_ref10) {
64150
64266
  }
64151
64267
  return m;
64152
64268
  }, [myWiring]);
64269
+ var _useConfigTokens5 = useConfigTokens(),
64270
+ muted = _useConfigTokens5.muted,
64271
+ hairline = _useConfigTokens5.hairline;
64153
64272
  return (
64154
64273
  /*#__PURE__*/
64155
64274
  // Plain <div> wrapper — Card2 reads as washed-out against the
64156
64275
  // modal's dark chrome. See ListenersTab + ProvidersTab fix.
64157
- jsxs("div", {
64158
- className: "w-56 flex-shrink-0 overflow-hidden flex flex-col",
64159
- children: [/*#__PURE__*/jsx("div", {
64160
- className: "px-3 py-2 text-xs font-semibold opacity-50 uppercase tracking-wider",
64161
- children: "Event Handlers"
64162
- }), /*#__PURE__*/jsx(Divider, {}), /*#__PURE__*/jsx("div", {
64163
- className: "overflow-y-auto flex-1",
64164
- children: receiver.eventHandlers.length === 0 ? /*#__PURE__*/jsx("div", {
64165
- className: "text-xs opacity-50 text-center py-6 px-3",
64166
- children: "This widget declares no event handlers."
64167
- }) : receiver.eventHandlers.map(function (h) {
64168
- var isActive = h === selectedHandler;
64169
- var count = countsByHandler.get(h) || 0;
64170
- return /*#__PURE__*/jsxs("button", {
64171
- type: "button",
64172
- onClick: function onClick() {
64173
- return onSelectHandler(h);
64174
- },
64175
- className: "w-full text-left px-3 py-2 text-sm flex items-center justify-between gap-2 border-l-2 ".concat(isActive ? "bg-indigo-900/30 border-indigo-400" : "border-transparent hover:bg-white/5"),
64176
- children: [/*#__PURE__*/jsxs("span", {
64177
- className: "flex items-center gap-2 min-w-0",
64178
- children: [/*#__PURE__*/jsx(FontAwesomeIcon, {
64179
- icon: "bolt",
64180
- className: "h-3 w-3 opacity-60 flex-shrink-0"
64181
- }), /*#__PURE__*/jsx("code", {
64182
- className: "truncate",
64183
- children: h
64184
- })]
64185
- }), /*#__PURE__*/jsx("span", {
64186
- className: "text-xs opacity-60 flex-shrink-0",
64187
- children: count
64188
- })]
64189
- }, h);
64190
- })
64276
+ jsxs(Fragment, {
64277
+ children: [/*#__PURE__*/jsxs("div", {
64278
+ className: "w-56 flex-shrink-0 overflow-hidden flex flex-col",
64279
+ children: [/*#__PURE__*/jsx(SectionLabel, {
64280
+ className: "px-3 mb-2",
64281
+ children: "Event Handlers"
64282
+ }), /*#__PURE__*/jsx("div", {
64283
+ className: "overflow-y-auto flex-1 flex flex-col gap-1",
64284
+ children: receiver.eventHandlers.length === 0 ? /*#__PURE__*/jsx("div", {
64285
+ className: "text-xs text-center py-6 px-3 ".concat(muted),
64286
+ children: "This widget declares no event handlers."
64287
+ }) : receiver.eventHandlers.map(function (h) {
64288
+ var count = countsByHandler.get(h) || 0;
64289
+ return /*#__PURE__*/jsx(ConfigListRow, {
64290
+ title: h,
64291
+ mono: true,
64292
+ active: h === selectedHandler,
64293
+ onClick: function onClick() {
64294
+ return onSelectHandler(h);
64295
+ },
64296
+ badge: /*#__PURE__*/jsx("span", {
64297
+ className: "text-xs flex-shrink-0 ".concat(muted),
64298
+ children: count
64299
+ })
64300
+ }, h);
64301
+ })
64302
+ })]
64303
+ }), /*#__PURE__*/jsx("div", {
64304
+ "aria-hidden": true,
64305
+ className: "flex-shrink-0 border-r ".concat(hairline)
64191
64306
  })]
64192
64307
  })
64193
64308
  );
@@ -64199,13 +64314,16 @@ function HandlersColumn(_ref10) {
64199
64314
  * Checked = wired; toggling commits an add/remove. Mirrors the
64200
64315
  * right-column UX of PanelEditItemHandlers.
64201
64316
  */
64202
- function EventsColumn(_ref11) {
64203
- var receiver = _ref11.receiver,
64204
- handlerName = _ref11.handlerName,
64205
- myWiring = _ref11.myWiring,
64206
- emitters = _ref11.emitters,
64207
- onAdd = _ref11.onAdd,
64208
- onRemove = _ref11.onRemove;
64317
+ function EventsColumn(_ref12) {
64318
+ var receiver = _ref12.receiver,
64319
+ handlerName = _ref12.handlerName,
64320
+ myWiring = _ref12.myWiring,
64321
+ emitters = _ref12.emitters,
64322
+ onAdd = _ref12.onAdd,
64323
+ onRemove = _ref12.onRemove;
64324
+ var _useConfigTokens6 = useConfigTokens(),
64325
+ muted = _useConfigTokens6.muted,
64326
+ hairline = _useConfigTokens6.hairline;
64209
64327
  // Wired-for-this-handler: dedupe defensively (legacy workspaces
64210
64328
  // occasionally contain duplicate entries under the same handler).
64211
64329
  var wiredHere = useMemo(function () {
@@ -64242,7 +64360,7 @@ function EventsColumn(_ref11) {
64242
64360
  });
64243
64361
  if (!handlerName) {
64244
64362
  return /*#__PURE__*/jsx("div", {
64245
- className: "flex-1 min-w-0 flex items-center justify-center text-sm opacity-60",
64363
+ className: "flex-1 min-w-0 flex items-center justify-center text-sm ".concat(muted),
64246
64364
  children: "Select a handler to view available events."
64247
64365
  });
64248
64366
  }
@@ -64276,7 +64394,7 @@ function EventsColumn(_ref11) {
64276
64394
  jsxs("div", {
64277
64395
  className: "flex-1 min-w-0 overflow-hidden flex flex-col",
64278
64396
  children: [/*#__PURE__*/jsxs("div", {
64279
- className: "flex-shrink-0 px-4 py-2 text-xs opacity-60",
64397
+ className: "flex-shrink-0 px-4 pb-3 text-xs border-b ".concat(muted, " ").concat(hairline),
64280
64398
  children: ["Check an event to fire ", /*#__PURE__*/jsx("code", {
64281
64399
  className: "text-xs",
64282
64400
  children: handlerName
@@ -64284,22 +64402,21 @@ function EventsColumn(_ref11) {
64284
64402
  className: "font-medium",
64285
64403
  children: receiver.label
64286
64404
  }), "."]
64287
- }), /*#__PURE__*/jsx(Divider, {}), /*#__PURE__*/jsx("div", {
64288
- className: "flex-1 overflow-y-auto p-4 space-y-5",
64405
+ }), /*#__PURE__*/jsx("div", {
64406
+ className: "flex-1 overflow-y-auto p-4 flex flex-col gap-3",
64289
64407
  children: emittersForList.length === 0 ? /*#__PURE__*/jsx("div", {
64290
- className: "text-sm opacity-60",
64408
+ className: "text-sm ".concat(muted),
64291
64409
  children: "No other widgets in this dashboard emit events."
64292
64410
  }) : emittersForList.map(function (e) {
64293
64411
  return /*#__PURE__*/jsxs("div", {
64294
- className: "space-y-1",
64412
+ className: "rounded-lg border px-3 py-2 flex flex-col gap-1 ".concat(hairline),
64295
64413
  children: [/*#__PURE__*/jsxs("div", {
64296
64414
  className: "flex flex-col gap-0.5 mb-1",
64297
64415
  children: [/*#__PURE__*/jsx("div", {
64298
64416
  className: "text-sm font-semibold",
64299
64417
  children: e.label
64300
- }), (e.widgetRef || e.component) && /*#__PURE__*/jsx(Caption, {
64301
- block: true,
64302
- className: "font-mono truncate",
64418
+ }), (e.widgetRef || e.component) && /*#__PURE__*/jsx("div", {
64419
+ className: "text-xs font-mono truncate ".concat(muted),
64303
64420
  children: (e.widgetRef || e.component) + (e.itemId != null ? "[".concat(e.itemId, "]") : "")
64304
64421
  })]
64305
64422
  }), e.events.map(function (eventName) {