@flytedan/flytebot-design-system 0.12.12 → 0.12.14

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.cjs CHANGED
@@ -405,14 +405,48 @@ var portal = (node) => {
405
405
  };
406
406
  var ROOT_LAYER = 0;
407
407
  var LAYER_STEP = 10;
408
+ var ROOT_STEP = 100;
409
+ var OVERLAY_CEILING = 1e4;
408
410
  var LayerContext = React2.createContext(ROOT_LAYER);
411
+ var openRootIds = [];
412
+ var rootListeners = /* @__PURE__ */ new Set();
413
+ var notifyRootListeners = () => {
414
+ rootListeners.forEach((listener) => listener());
415
+ };
416
+ var subscribeRootOverlays = (listener) => {
417
+ rootListeners.add(listener);
418
+ return () => {
419
+ rootListeners.delete(listener);
420
+ };
421
+ };
422
+ var getRootOverlaysSnapshot = () => openRootIds;
423
+ var registerRootOverlay = (id) => {
424
+ if (openRootIds.includes(id)) return;
425
+ openRootIds = [...openRootIds, id];
426
+ notifyRootListeners();
427
+ };
428
+ var unregisterRootOverlay = (id) => {
429
+ if (!openRootIds.includes(id)) return;
430
+ openRootIds = openRootIds.filter((existing) => existing !== id);
431
+ notifyRootListeners();
432
+ };
409
433
  var useLayer = () => React2.useContext(LayerContext);
410
- var useOverlayLayer = (base) => {
434
+ var useOverlayLayer = (isOpen) => {
411
435
  const parent = useLayer();
412
- return parent === ROOT_LAYER ? base : parent + LAYER_STEP;
436
+ const isRoot = parent === ROOT_LAYER;
437
+ const id = React2.useId();
438
+ const openIds = React2.useSyncExternalStore(subscribeRootOverlays, getRootOverlaysSnapshot, getRootOverlaysSnapshot);
439
+ React2.useLayoutEffect(() => {
440
+ if (!isRoot || !isOpen) return;
441
+ registerRootOverlay(id);
442
+ return () => unregisterRootOverlay(id);
443
+ }, [isRoot, isOpen, id]);
444
+ if (!isRoot) return parent + LAYER_STEP;
445
+ if (!isOpen) return ROOT_LAYER;
446
+ const index = openIds.indexOf(id);
447
+ return index === -1 ? ROOT_LAYER : (index + 1) * ROOT_STEP;
413
448
  };
414
449
  var LayerProvider = ({ zIndex, children }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LayerContext.Provider, { value: zIndex, children });
415
- var POPOVER_BASE = 140;
416
450
  function Popover({
417
451
  open,
418
452
  anchorRef,
@@ -449,7 +483,7 @@ function Popover({
449
483
  layerRef: ref
450
484
  });
451
485
  const restore = React2.useRef(null);
452
- const zIndex = useOverlayLayer(POPOVER_BASE);
486
+ const zIndex = useOverlayLayer(!!open);
453
487
  React2.useEffect(() => {
454
488
  if (!open) return;
455
489
  restore.current = typeof document !== "undefined" ? document.activeElement : null;
@@ -776,6 +810,13 @@ function SegmentedControl({ options = [], value, onChange, className = "", ...re
776
810
  }) });
777
811
  }
778
812
 
813
+ // src/components/textExposure.ts
814
+ function truncationTitle(content) {
815
+ if (typeof content !== "string" && typeof content !== "number") return void 0;
816
+ const text = String(content);
817
+ return text === "" ? void 0 : text;
818
+ }
819
+
779
820
  // src/components/surfaces/Card.tsx
780
821
  var import_jsx_runtime5 = require("react/jsx-runtime");
781
822
  function Card({
@@ -797,7 +838,7 @@ function Card({
797
838
  ].filter(Boolean).join(" ");
798
839
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: cls, ...rest, children: [
799
840
  title ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "fd-card-head", children: [
800
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fd-card-head-title", children: title }),
841
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
801
842
  action
802
843
  ] }) : null,
803
844
  padded ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "fd-card-body", children }) : children,
@@ -850,9 +891,8 @@ function Collapsible({
850
891
  var React4 = __toESM(require("react"), 1);
851
892
  var import_react_dom2 = require("react-dom");
852
893
  var import_jsx_runtime7 = require("react/jsx-runtime");
853
- var DRAWER_BASE = 90;
854
894
  function Drawer({ open = true, title, onClose, footer, children, className = "", ...rest }) {
855
- const zIndex = useOverlayLayer(DRAWER_BASE);
895
+ const zIndex = useOverlayLayer(open);
856
896
  const [closing, setClosing] = React4.useState(false);
857
897
  const close = React4.useCallback(() => {
858
898
  if (!onClose) return;
@@ -873,7 +913,7 @@ function Drawer({ open = true, title, onClose, footer, children, className = "",
873
913
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close }),
874
914
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("aside", { className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, style: { zIndex }, children: [
875
915
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "fd-card-head", style: { flex: "none" }, children: [
876
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fd-card-head-title", children: title }),
916
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
877
917
  onClose ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("i", { className: "ph ph-x" }) }) : null
878
918
  ] }),
879
919
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children }),
@@ -890,6 +930,7 @@ var import_react_dom3 = require("react-dom");
890
930
  var import_jsx_runtime8 = require("react/jsx-runtime");
891
931
  function Modal({ open = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
892
932
  const [closing, setClosing] = React5.useState(false);
933
+ const zIndex = useOverlayLayer(!!open);
893
934
  const close = React5.useCallback(() => {
894
935
  if (!onClose) return;
895
936
  setClosing(true);
@@ -905,10 +946,11 @@ function Modal({ open = true, title, description, onClose, footer, wide = false,
905
946
  }, [open, onClose, close]);
906
947
  if (!open) return null;
907
948
  return (0, import_react_dom3.createPortal)(
908
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
949
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LayerProvider, { zIndex, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
909
950
  "div",
910
951
  {
911
952
  className: "fd-scrim" + (closing ? " is-closing" : ""),
953
+ style: { zIndex: zIndex - LAYER_STEP },
912
954
  onClick: onClose ? (e) => {
913
955
  if (e.target === e.currentTarget) close();
914
956
  } : void 0,
@@ -934,7 +976,7 @@ function Modal({ open = true, title, description, onClose, footer, wide = false,
934
976
  }
935
977
  )
936
978
  }
937
- ),
979
+ ) }),
938
980
  document.body
939
981
  );
940
982
  }
@@ -1069,7 +1111,7 @@ function SidebarNav({ brand, groups = [], current: current2, onNavigate, footer,
1069
1111
  onClick: onNavigate ? () => onNavigate(it.value) : void 0,
1070
1112
  children: [
1071
1113
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-side-item-icon", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) }),
1072
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: it.label }),
1114
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: truncationTitle(it.label), children: it.label }),
1073
1115
  it.preview ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tip, { label: "Designed, backend not wired yet", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-traffic-cone", style: { fontSize: 13, color: "var(--warn-solid)", flex: "none" } }) }) : null,
1074
1116
  it.locked ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Tip, { label: "You do not have permission for this", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("i", { className: "ph ph-lock-simple", style: { fontSize: 13, color: "var(--text-muted)", flex: "none" } }) }) : null,
1075
1117
  it.count !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "fd-side-item-count", children: it.count }) : null,
@@ -1155,7 +1197,12 @@ function Topbar({
1155
1197
  onMenu ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Menu", onClick: onMenu, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-list" }) }) : null,
1156
1198
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("nav", { className: "fd-crumb", "aria-label": "Breadcrumb", children: crumbs.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(React6.Fragment, { children: [
1157
1199
  i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("i", { className: "ph ph-caret-right", style: { fontSize: 11, opacity: 0.6 }, "aria-hidden": "true" }) : null,
1158
- i === crumbs.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fd-crumb-current", children: c.label }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1200
+ i === crumbs.length - 1 ? (
1201
+ // MP-141: the current crumb mixes a static route label with (usually) a
1202
+ // user-entered campaign name and is single-line by design — exposure,
1203
+ // not wrapping, is the fix here, same rule as every other identifier.
1204
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "fd-crumb-current", title: truncationTitle(c.label), children: c.label })
1205
+ ) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1159
1206
  "a",
1160
1207
  {
1161
1208
  href: c.href || "#",
@@ -1360,7 +1407,6 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
1360
1407
  // src/components/feedback/Tooltip.tsx
1361
1408
  var React7 = __toESM(require("react"), 1);
1362
1409
  var import_jsx_runtime24 = require("react/jsx-runtime");
1363
- var TOOLTIP_BASE = 150;
1364
1410
  var CLOSE_DELAY_MS = 120;
1365
1411
  function Tooltip({ label, placement = "top", children, className = "" }) {
1366
1412
  const anchorRef = React7.useRef(null);
@@ -1404,7 +1450,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1404
1450
  layerRef: bubbleRef,
1405
1451
  onDetach: hide
1406
1452
  });
1407
- const zIndex = useOverlayLayer(TOOLTIP_BASE);
1453
+ const zIndex = useOverlayLayer(open);
1408
1454
  React7.useEffect(() => {
1409
1455
  if (!open) return;
1410
1456
  const key = (e) => {
@@ -1647,11 +1693,10 @@ function DataTable({
1647
1693
  // src/components/data/FilterBar.tsx
1648
1694
  var React9 = __toESM(require("react"), 1);
1649
1695
  var import_jsx_runtime28 = require("react/jsx-runtime");
1650
- var FILTER_BAR_BASE = 120;
1651
1696
  var isSet = (v) => !(v == null || v === "" || v === false);
1652
1697
  function FilterBar({ fields = [], filters, onFilterChange, onFilterRemove, align = "left", className = "", ...rest }) {
1653
1698
  const [panel, setPanel] = React9.useState(null);
1654
- const zIndex = useOverlayLayer(FILTER_BAR_BASE);
1699
+ const zIndex = useOverlayLayer(!!panel);
1655
1700
  const rootRef = React9.useRef(null);
1656
1701
  const textInputRef = React9.useRef(null);
1657
1702
  const optionsRef = React9.useRef(null);
@@ -2750,12 +2795,12 @@ function SegmentedMeter({
2750
2795
  legend ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("ul", { className: "fd-segmeter-legend", children: [
2751
2796
  items.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("li", { children: [
2752
2797
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fd-segmeter-dot", style: { background: fill(s, i) }, "aria-hidden": "true" }),
2753
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fd-segmeter-key", children: s.label }),
2798
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fd-segmeter-key", title: truncationTitle(s.label), children: s.label }),
2754
2799
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fd-segmeter-val fd-tabular", children: format(s.value) })
2755
2800
  ] }, s.id || s.label || i)),
2756
2801
  safeTotal && used < safeTotal ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("li", { className: "is-remainder", children: [
2757
2802
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fd-segmeter-dot is-empty", "aria-hidden": "true" }),
2758
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fd-segmeter-key", children: remainderLabel }),
2803
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fd-segmeter-key", title: truncationTitle(remainderLabel), children: remainderLabel }),
2759
2804
  /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "fd-segmeter-val fd-tabular", children: format(safeTotal - used) })
2760
2805
  ] }) : null
2761
2806
  ] }) : null
@@ -2847,10 +2892,9 @@ function ScoreMeter({
2847
2892
  // src/components/data/SortMenu.tsx
2848
2893
  var React15 = __toESM(require("react"), 1);
2849
2894
  var import_jsx_runtime37 = require("react/jsx-runtime");
2850
- var SORT_MENU_BASE = 120;
2851
2895
  function SortMenu({ fields = [], sort, onSort, align = "right", size = "md", className = "", ...rest }) {
2852
2896
  const [open, setOpen] = React15.useState(false);
2853
- const zIndex = useOverlayLayer(SORT_MENU_BASE);
2897
+ const zIndex = useOverlayLayer(open);
2854
2898
  const ref = React15.useRef(null);
2855
2899
  React15.useEffect(() => {
2856
2900
  if (!open) return;
@@ -2944,7 +2988,7 @@ function StepList({
2944
2988
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: ["fd-steps", dense ? "is-dense" : "", open ? "is-open" : "", className].filter(Boolean).join(" "), children: [
2945
2989
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("button", { type: "button", className: "fd-steps-head", onClick: toggle, "aria-expanded": open, children: [
2946
2990
  running ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-steps-spin", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("i", { className: "ph ph-" + (failed ? "warning-circle" : "check-circle"), "aria-hidden": "true" }),
2947
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-steps-title", children: summary }),
2991
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-steps-title", title: truncationTitle(summary), children: summary }),
2948
2992
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "fd-steps-count fd-tabular", children: [
2949
2993
  steps.length,
2950
2994
  " step",
@@ -2972,11 +3016,11 @@ function StepList({
2972
3016
  "aria-expanded": isOpen,
2973
3017
  onClick: () => setExpanded((m) => Object.assign({}, m, { [id]: !isOpen })),
2974
3018
  children: [
2975
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: s.label }),
3019
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { title: truncationTitle(s.label), children: s.label }),
2976
3020
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("i", { className: "ph ph-caret-" + (isOpen ? "up" : "down"), "aria-hidden": "true" })
2977
3021
  ]
2978
3022
  }
2979
- ) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-step-label is-static", children: s.label }),
3023
+ ) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-step-label is-static", title: truncationTitle(s.label), children: s.label }),
2980
3024
  s.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-step-badge is-error", children: "failed" }) : null,
2981
3025
  showDurations && s.durationMs ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "fd-step-dur fd-tabular", children: formatDuration(s.durationMs) }) : null
2982
3026
  ] }),
@@ -3197,8 +3241,12 @@ function EntityRow({
3197
3241
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-title fd-body-sm", children: title })
3198
3242
  ]
3199
3243
  }
3200
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-title fd-body-sm", children: title }),
3201
- meta ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-meta", children: meta }) : null
3244
+ ) }) : (
3245
+ // MP-141: dense-row identifier, no Tooltip wrapper in this branch — a native
3246
+ // `title` is the exposure mechanism, same rule as every other identifier.
3247
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-title fd-body-sm", title: truncationTitle(title), children: title })
3248
+ ),
3249
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "fd-erow-meta", title: truncationTitle(meta), children: meta }) : null
3202
3250
  ] }),
3203
3251
  hasStrip ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "fd-erow-strip", children: [
3204
3252
  metrics && metrics.length ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(EntityRowMetrics, { metrics }) : null,
@@ -3534,7 +3582,7 @@ function TransferList({
3534
3582
  height: drag.height,
3535
3583
  transform: `translate(${drag.x - drag.offsetX}px, ${drag.y - drag.offsetY}px) rotate(-3deg)`,
3536
3584
  pointerEvents: "none",
3537
- zIndex: 1e3
3585
+ zIndex: OVERLAY_CEILING
3538
3586
  },
3539
3587
  children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(EntityRow, { ...renderRow(drag.item), draggable: true, className: "fd-erow-dragging" })
3540
3588
  }
@@ -3879,7 +3927,7 @@ function Select({
3879
3927
  style: { all: "unset", flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: 8, cursor: "inherit", overflow: "hidden" },
3880
3928
  children: [
3881
3929
  selected && selected.icon ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("i", { className: "ph ph-" + selected.icon, style: { flex: "none", color: "var(--text-2)" } }) : null,
3882
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
3930
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { title: truncationTitle(boxText), style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: (multiple ? chosen.length : selected) ? "var(--text)" : "var(--text-muted)" }, children: boxText }),
3883
3931
  multiple && chosen.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "fd-mono", style: { flex: "none", fontSize: 11, fontWeight: 700, padding: "1px 6px", borderRadius: 99, background: "var(--brand)", color: "#fff" }, children: chosen.length }) : null
3884
3932
  ]
3885
3933
  }
@@ -4151,6 +4199,7 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
4151
4199
  type: "button",
4152
4200
  id: fieldId,
4153
4201
  "aria-labelledby": ariaLabelledBy,
4202
+ title: truncationTitle(display),
4154
4203
  disabled,
4155
4204
  onKeyDown: (e) => {
4156
4205
  if (e.key === "Enter" || e.key === " ") {
@@ -6975,7 +7024,7 @@ function AccountMenu({
6975
7024
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Avatar, { name: user.name }),
6976
7025
  /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
6977
7026
  /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
6978
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", children: user.email })
7027
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
6979
7028
  ] })
6980
7029
  ] }),
6981
7030
  showRoles && session.roles.length ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: session.roles.map((r) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
@@ -7790,7 +7839,6 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7790
7839
  var React36 = __toESM(require("react"), 1);
7791
7840
  var import_react_dom5 = require("react-dom");
7792
7841
  var import_jsx_runtime62 = require("react/jsx-runtime");
7793
- var SOON_HOVERCARD_BASE = 220;
7794
7842
  var BYPASS_STORE = "fd.soon.bypass.v1";
7795
7843
  function readBypassed() {
7796
7844
  try {
@@ -7985,7 +8033,7 @@ function ComingSoon({
7985
8033
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
7986
8034
  const [open, setOpen] = React36.useState(false);
7987
8035
  const [anchor, pos] = useHoverCard(open);
7988
- const zIndex = useOverlayLayer(SOON_HOVERCARD_BASE);
8036
+ const zIndex = useOverlayLayer(open);
7989
8037
  const close = React36.useRef(null);
7990
8038
  const show = () => {
7991
8039
  if (close.current) {
@@ -8174,11 +8222,10 @@ function PermissionHint({ perm, children }) {
8174
8222
  // src/components/platform/ModeSwitch.tsx
8175
8223
  var React37 = __toESM(require("react"), 1);
8176
8224
  var import_jsx_runtime64 = require("react/jsx-runtime");
8177
- var MODE_SWITCH_BASE = 140;
8178
8225
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
8179
8226
  const mode2 = useRuntimeMode();
8180
8227
  const [open, setOpen] = React37.useState(false);
8181
- const zIndex = useOverlayLayer(MODE_SWITCH_BASE);
8228
+ const zIndex = useOverlayLayer(open);
8182
8229
  const ref = React37.useRef(null);
8183
8230
  React37.useEffect(() => {
8184
8231
  if (!open) return;
@@ -9285,7 +9332,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
9285
9332
  return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
9286
9333
  /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("header", { className: "fdc-packet-head", children: [
9287
9334
  /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
9288
- /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-packet-title", children: title }),
9335
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
9289
9336
  packet.repaired ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
9290
9337
  invalid ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
9291
9338
  ] }),
@@ -9790,7 +9837,7 @@ function ChatComposer({
9790
9837
  return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
9791
9838
  queue.length ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "fdc-queue-row", children: [
9792
9839
  /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
9793
- /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fdc-queue-text", children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
9840
+ /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
9794
9841
  onRemoveQueued ? /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
9795
9842
  ] }, q.id)) }) : null,
9796
9843
  sessionBar,
@@ -9918,7 +9965,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
9918
9965
  "aria-label": expandable ? "Usage details" : void 0,
9919
9966
  children: [
9920
9967
  cu ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
9921
- /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fdc-bar-text", children: bits.join(" \xB7 ") }),
9968
+ /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
9922
9969
  expandable ? /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
9923
9970
  ]
9924
9971
  }
@@ -10312,8 +10359,8 @@ function AgentChatPanel({
10312
10359
  showHeader ? /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("header", { className: "fdc-head", children: [
10313
10360
  /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("i", { className: "ph ph-" + assistantIcon }) }),
10314
10361
  /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fdc-head-titles", children: [
10315
- /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fdc-head-title", children: title }),
10316
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fdc-head-sub", children: subtitle }) : null
10362
+ /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
10363
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
10317
10364
  ] }),
10318
10365
  /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("span", { className: "fdc-head-acts", children: [
10319
10366
  headerActions,