@flytedan/flytebot-design-system 0.12.0 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -185,6 +185,16 @@ var portal = (node) => {
185
185
  if (typeof document !== "undefined") return createPortal(node, document.body);
186
186
  return node;
187
187
  };
188
+ var ROOT_LAYER = 0;
189
+ var LAYER_STEP = 10;
190
+ var LayerContext = React.createContext(ROOT_LAYER);
191
+ var useLayer = () => React.useContext(LayerContext);
192
+ var useOverlayLayer = (base) => {
193
+ const parent = useLayer();
194
+ return parent === ROOT_LAYER ? base : parent + LAYER_STEP;
195
+ };
196
+ var LayerProvider = ({ zIndex, children }) => /* @__PURE__ */ jsx3(LayerContext.Provider, { value: zIndex, children });
197
+ var POPOVER_BASE = 140;
188
198
  function Popover({
189
199
  open,
190
200
  anchorRef,
@@ -221,6 +231,7 @@ function Popover({
221
231
  layerRef: ref
222
232
  });
223
233
  const restore = React.useRef(null);
234
+ const zIndex = useOverlayLayer(POPOVER_BASE);
224
235
  React.useEffect(() => {
225
236
  if (!open) return;
226
237
  restore.current = typeof document !== "undefined" ? document.activeElement : null;
@@ -259,7 +270,7 @@ function Popover({
259
270
  }, [open, closeOnOutside, closeOnEscape, onClose, anchorRef, triggerRef]);
260
271
  if (!open || !pos) return null;
261
272
  return portal(
262
- /* @__PURE__ */ jsxs2(
273
+ /* @__PURE__ */ jsx3(LayerProvider, { zIndex, children: /* @__PURE__ */ jsxs2(
263
274
  "div",
264
275
  {
265
276
  ref,
@@ -289,8 +300,12 @@ function Popover({
289
300
  // ordinary content that simply happens to be taller than some fixed number.
290
301
  maxHeight: maxHeight != null ? Math.min(maxHeight, pos.maxH) : pos.maxH,
291
302
  transformOrigin: pos.side === "top" ? "bottom center" : "top center",
292
- zIndex: 140,
293
- ...style
303
+ // Last, and always: a caller's `style` (Select, DatePicker, TimePicker all pass
304
+ // one) must never be able to clobber the computed layer — that silent override
305
+ // via object-spread order is exactly how the Select listbox (130) ended up
306
+ // fixed below the Popover (140) it opens from. zIndex is never a caller concern.
307
+ ...style,
308
+ zIndex
294
309
  },
295
310
  children: [
296
311
  header != null ? /* @__PURE__ */ jsx3("div", { className: "fd-pop-header", children: header }) : null,
@@ -298,7 +313,7 @@ function Popover({
298
313
  footer != null ? /* @__PURE__ */ jsx3("div", { className: "fd-pop-footer", children: footer }) : null
299
314
  ]
300
315
  }
301
- )
316
+ ) })
302
317
  );
303
318
  }
304
319
  var isItem = (it) => !!it && it.kind !== "separator" && it.kind !== "section" && it.kind !== "custom" && !it.disabled;
@@ -616,8 +631,10 @@ function Collapsible({
616
631
  // src/components/surfaces/Drawer.tsx
617
632
  import * as React3 from "react";
618
633
  import { createPortal as createPortal2 } from "react-dom";
619
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
634
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
635
+ var DRAWER_BASE = 90;
620
636
  function Drawer({ open = true, title, onClose, footer, children, className = "", ...rest }) {
637
+ const zIndex = useOverlayLayer(DRAWER_BASE);
621
638
  const [closing, setClosing] = React3.useState(false);
622
639
  const close = React3.useCallback(() => {
623
640
  if (!onClose) return;
@@ -634,9 +651,9 @@ function Drawer({ open = true, title, onClose, footer, children, className = "",
634
651
  }, [open, onClose, close]);
635
652
  if (!open) return null;
636
653
  return createPortal2(
637
- /* @__PURE__ */ jsxs5(Fragment2, { children: [
638
- /* @__PURE__ */ jsx7("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block" }, onClick: close }),
639
- /* @__PURE__ */ jsxs5("aside", { className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, children: [
654
+ /* @__PURE__ */ jsxs5(LayerProvider, { zIndex, children: [
655
+ /* @__PURE__ */ jsx7("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close }),
656
+ /* @__PURE__ */ jsxs5("aside", { className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, style: { zIndex }, children: [
640
657
  /* @__PURE__ */ jsxs5("div", { className: "fd-card-head", style: { flex: "none" }, children: [
641
658
  /* @__PURE__ */ jsx7("span", { className: "fd-card-head-title", children: title }),
642
659
  onClose ? /* @__PURE__ */ jsx7("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close, children: /* @__PURE__ */ jsx7("i", { className: "ph ph-x" }) }) : null
@@ -888,7 +905,7 @@ function Tabs({ tabs = [], value, onChange, className = "", ...rest }) {
888
905
 
889
906
  // src/components/navigation/Topbar.tsx
890
907
  import * as React5 from "react";
891
- import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
908
+ import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
892
909
  function useIsNarrow(breakpoint) {
893
910
  const [narrow, setNarrow] = React5.useState(
894
911
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(`(max-width: ${breakpoint}px)`).matches
@@ -933,7 +950,7 @@ function Topbar({
933
950
  )
934
951
  ] }, i)) }),
935
952
  /* @__PURE__ */ jsx16("span", { style: { flex: 1 } }),
936
- overflowActions != null ? narrow ? /* @__PURE__ */ jsxs12(Fragment4, { children: [
953
+ overflowActions != null ? narrow ? /* @__PURE__ */ jsxs12(Fragment3, { children: [
937
954
  /* @__PURE__ */ jsx16(
938
955
  "button",
939
956
  {
@@ -1012,12 +1029,12 @@ function EmptyState({ icon = "tray", title, children, action, className = "", ..
1012
1029
  }
1013
1030
 
1014
1031
  // src/components/feedback/Flag.tsx
1015
- import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
1032
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
1016
1033
  function Flag({ statement, cost, actions, tone = "warning", className = "", ...rest }) {
1017
1034
  return /* @__PURE__ */ jsxs16("div", { className: ["fd-flag", "fd-flag-" + tone, className].filter(Boolean).join(" "), role: "status", ...rest, children: [
1018
1035
  /* @__PURE__ */ jsxs16("span", { className: "fd-flag-text", children: [
1019
1036
  statement,
1020
- cost ? /* @__PURE__ */ jsxs16(Fragment5, { children: [
1037
+ cost ? /* @__PURE__ */ jsxs16(Fragment4, { children: [
1021
1038
  " ",
1022
1039
  /* @__PURE__ */ jsx20("span", { className: "fd-flag-cost", children: cost })
1023
1040
  ] }) : null
@@ -1125,6 +1142,7 @@ function Toast({ title, children, tone = "success", onUndo, onDismiss, className
1125
1142
  // src/components/feedback/Tooltip.tsx
1126
1143
  import * as React6 from "react";
1127
1144
  import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
1145
+ var TOOLTIP_BASE = 150;
1128
1146
  var CLOSE_DELAY_MS = 120;
1129
1147
  function Tooltip({ label, placement = "top", children, className = "" }) {
1130
1148
  const anchorRef = React6.useRef(null);
@@ -1168,6 +1186,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1168
1186
  layerRef: bubbleRef,
1169
1187
  onDetach: hide
1170
1188
  });
1189
+ const zIndex = useOverlayLayer(TOOLTIP_BASE);
1171
1190
  React6.useEffect(() => {
1172
1191
  if (!open) return;
1173
1192
  const key = (e) => {
@@ -1231,7 +1250,7 @@ function Tooltip({ label, placement = "top", children, className = "" }) {
1231
1250
  ref: bubbleRef,
1232
1251
  role: "tooltip",
1233
1252
  className: ["fd-tooltip", pos.side === "bottom" ? "is-below" : "", className].filter(Boolean).join(" "),
1234
- style: { left: pos.left, top: pos.top == null ? "auto" : pos.top, bottom: pos.bottom == null ? "auto" : pos.bottom },
1253
+ style: { left: pos.left, top: pos.top == null ? "auto" : pos.top, bottom: pos.bottom == null ? "auto" : pos.bottom, zIndex },
1235
1254
  onPointerEnter: (e) => {
1236
1255
  if (isMouse(e)) cancelClose();
1237
1256
  },
@@ -1600,7 +1619,7 @@ function StatTile({ label, value, sub, delta, loading = false, compact: compact3
1600
1619
 
1601
1620
  // src/components/data/CodeBlock.tsx
1602
1621
  import * as React9 from "react";
1603
- import { Fragment as Fragment6, jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
1622
+ import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
1604
1623
  var JS_KW = /^(?:const|let|var|function|return|if|else|for|while|do|new|class|extends|import|from|export|default|await|async|try|catch|finally|throw|typeof|instanceof|of|in|switch|case|break|continue|delete|void|yield|static|get|set|this|super|interface|type|enum|implements|public|private|protected|readonly|abstract|as|satisfies|declare|namespace)$/;
1605
1624
  var RULES = {
1606
1625
  js: [
@@ -1756,7 +1775,7 @@ function tokenize(src, lang) {
1756
1775
  }
1757
1776
  function Highlighted({ code, lang }) {
1758
1777
  const toks = React9.useMemo(() => tokenize(code, lang), [code, lang]);
1759
- return /* @__PURE__ */ jsx30(Fragment6, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ jsx30("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
1778
+ return /* @__PURE__ */ jsx30(Fragment5, { children: toks.map((tk, i) => tk.c ? /* @__PURE__ */ jsx30("span", { className: "tok-" + tk.c, children: tk.t }, i) : tk.t) });
1760
1779
  }
1761
1780
  function useCopy() {
1762
1781
  const [done, setDone] = React9.useState(false);
@@ -2120,7 +2139,7 @@ function Meter({ segments = [], unallocated = 0, height = 8, label, legend = fal
2120
2139
  }
2121
2140
 
2122
2141
  // src/components/data/Pagination.tsx
2123
- import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
2142
+ import { Fragment as Fragment7, jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
2124
2143
  function Pagination({
2125
2144
  page = 1,
2126
2145
  pageSize = 25,
@@ -2146,10 +2165,10 @@ function Pagination({
2146
2165
  else if (nums[nums.length - 1] !== "\u2026") nums.push("\u2026");
2147
2166
  }
2148
2167
  return /* @__PURE__ */ jsxs28("div", { className: ["fd-pag", className].filter(Boolean).join(" "), ...rest, children: [
2149
- /* @__PURE__ */ jsx33("span", { className: "fd-pag-count", children: loading ? /* @__PURE__ */ jsx33("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 12, width: 108 } }) : total === 0 ? /* @__PURE__ */ jsxs28(Fragment8, { children: [
2168
+ /* @__PURE__ */ jsx33("span", { className: "fd-pag-count", children: loading ? /* @__PURE__ */ jsx33("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 12, width: 108 } }) : total === 0 ? /* @__PURE__ */ jsxs28(Fragment7, { children: [
2150
2169
  "No ",
2151
2170
  unit
2152
- ] }) : /* @__PURE__ */ jsxs28(Fragment8, { children: [
2171
+ ] }) : /* @__PURE__ */ jsxs28(Fragment7, { children: [
2153
2172
  /* @__PURE__ */ jsxs28("strong", { children: [
2154
2173
  from.toLocaleString(),
2155
2174
  "\u2013",
@@ -3644,7 +3663,7 @@ function Select({
3644
3663
  matchWidth: "min",
3645
3664
  minWidth: 260,
3646
3665
  role: "presentation",
3647
- style: { maxWidth: 380, zIndex: 130 },
3666
+ style: { maxWidth: 380 },
3648
3667
  header: hasSearch ? /* @__PURE__ */ jsxs44("div", { className: "fd-pop-search", children: [
3649
3668
  /* @__PURE__ */ jsx49("i", { className: "ph ph-magnifying-glass", style: { color: "var(--text-muted)", fontSize: 14 } }),
3650
3669
  /* @__PURE__ */ jsx49(
@@ -3908,7 +3927,7 @@ function DatePicker({ label, help, error, required = false, disabled = false, ra
3908
3927
  placement: "bottom-start",
3909
3928
  offset: 6,
3910
3929
  role: "presentation",
3911
- style: { width: "max-content", zIndex: 130 },
3930
+ style: { width: "max-content" },
3912
3931
  children: /* @__PURE__ */ jsx50(
3913
3932
  Calendar,
3914
3933
  {
@@ -4060,7 +4079,6 @@ function TimePicker({ label, help, error, required = false, disabled = false, va
4060
4079
  offset: 6,
4061
4080
  width: 262,
4062
4081
  role: "presentation",
4063
- style: { zIndex: 130 },
4064
4082
  footer: /* @__PURE__ */ jsxs46(React24.Fragment, { children: [
4065
4083
  /* @__PURE__ */ jsx51(
4066
4084
  "button",
@@ -6633,7 +6651,7 @@ var SessionKit = {
6633
6651
  };
6634
6652
 
6635
6653
  // src/components/platform/AccountMenu.tsx
6636
- import { Fragment as Fragment15, jsx as jsx57, jsxs as jsxs52 } from "react/jsx-runtime";
6654
+ import { Fragment as Fragment14, jsx as jsx57, jsxs as jsxs52 } from "react/jsx-runtime";
6637
6655
  var DEFAULT_LINKS = [
6638
6656
  { id: "profile", label: "Your profile", icon: "user-circle", href: "../admin/index.html#profile" },
6639
6657
  { id: "preferences", label: "Preferences", icon: "sliders-horizontal", href: "../admin/index.html#preferences" }
@@ -6686,7 +6704,7 @@ function AccountMenu({
6686
6704
  if (onSignOut) return onSignOut();
6687
6705
  window.alert("Signed out. (Simulated \u2014 no auth provider is wired up.)");
6688
6706
  };
6689
- return /* @__PURE__ */ jsxs52(Fragment15, { children: [
6707
+ return /* @__PURE__ */ jsxs52(Fragment14, { children: [
6690
6708
  /* @__PURE__ */ jsxs52(
6691
6709
  "button",
6692
6710
  {
@@ -7523,7 +7541,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
7523
7541
  // src/components/platform/ComingSoon.tsx
7524
7542
  import * as React35 from "react";
7525
7543
  import { createPortal as createPortal5 } from "react-dom";
7526
- import { Fragment as Fragment17, jsx as jsx61, jsxs as jsxs56 } from "react/jsx-runtime";
7544
+ import { Fragment as Fragment16, jsx as jsx61, jsxs as jsxs56 } from "react/jsx-runtime";
7527
7545
  var BYPASS_STORE = "fd.soon.bypass.v1";
7528
7546
  function readBypassed() {
7529
7547
  try {
@@ -7553,7 +7571,7 @@ function useBypass(key) {
7553
7571
  return [on, set];
7554
7572
  }
7555
7573
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
7556
- return /* @__PURE__ */ jsxs56(Fragment17, { children: [
7574
+ return /* @__PURE__ */ jsxs56(Fragment16, { children: [
7557
7575
  /* @__PURE__ */ jsxs56("span", { className: "fd-soon-badge", children: [
7558
7576
  /* @__PURE__ */ jsx61("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
7559
7577
  label
@@ -7904,7 +7922,7 @@ function PermissionHint({ perm, children }) {
7904
7922
 
7905
7923
  // src/components/platform/ModeSwitch.tsx
7906
7924
  import * as React36 from "react";
7907
- import { Fragment as Fragment18, jsx as jsx63, jsxs as jsxs58 } from "react/jsx-runtime";
7925
+ import { Fragment as Fragment17, jsx as jsx63, jsxs as jsxs58 } from "react/jsx-runtime";
7908
7926
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
7909
7927
  const mode2 = useRuntimeMode();
7910
7928
  const [open, setOpen] = React36.useState(false);
@@ -7974,7 +7992,7 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
7974
7992
  s.total,
7975
7993
  " features complete"
7976
7994
  ] }),
7977
- onOpenSpec ? /* @__PURE__ */ jsxs58(Fragment18, { children: [
7995
+ onOpenSpec ? /* @__PURE__ */ jsxs58(Fragment17, { children: [
7978
7996
  /* @__PURE__ */ jsx63("span", { style: { flex: 1 } }),
7979
7997
  /* @__PURE__ */ jsxs58("button", { type: "button", className: "fd-soon-link", onClick: () => {
7980
7998
  setOpen(false);
@@ -8159,7 +8177,7 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
8159
8177
 
8160
8178
  // src/components/planner/MixGap.tsx
8161
8179
  import * as React37 from "react";
8162
- import { Fragment as Fragment19, jsx as jsx66, jsxs as jsxs61 } from "react/jsx-runtime";
8180
+ import { Fragment as Fragment18, jsx as jsx66, jsxs as jsxs61 } from "react/jsx-runtime";
8163
8181
  var MIX_GAP_LAYOUT = {
8164
8182
  trackHeight: 30,
8165
8183
  barHeight: 20,
@@ -8203,7 +8221,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
8203
8221
  onMouseLeave: () => setHover(null),
8204
8222
  children: [
8205
8223
  /* @__PURE__ */ jsx66("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx66(ChannelTag, { channel: r.channel, size: "sm" }) }),
8206
- /* @__PURE__ */ jsx66("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx66("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs61(Fragment19, { children: [
8224
+ /* @__PURE__ */ jsx66("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx66("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs61(Fragment18, { children: [
8207
8225
  /* @__PURE__ */ jsx66("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
8208
8226
  /* @__PURE__ */ jsx66("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
8209
8227
  /* @__PURE__ */ jsxs61("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
@@ -8317,7 +8335,7 @@ function ChannelContribution({
8317
8335
 
8318
8336
  // src/components/planner/BudgetReallocator.tsx
8319
8337
  import * as React38 from "react";
8320
- import { Fragment as Fragment20, jsx as jsx68, jsxs as jsxs63 } from "react/jsx-runtime";
8338
+ import { Fragment as Fragment19, jsx as jsx68, jsxs as jsxs63 } from "react/jsx-runtime";
8321
8339
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
8322
8340
  function BudgetReallocator({
8323
8341
  campus,
@@ -8357,7 +8375,7 @@ function BudgetReallocator({
8357
8375
  /* @__PURE__ */ jsxs63("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
8358
8376
  /* @__PURE__ */ jsx68("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
8359
8377
  /* @__PURE__ */ jsx68(CsiBadge, { band: nowBand, crp, size: "medium" }),
8360
- dirty ? /* @__PURE__ */ jsxs63(Fragment20, { children: [
8378
+ dirty ? /* @__PURE__ */ jsxs63(Fragment19, { children: [
8361
8379
  /* @__PURE__ */ jsx68("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
8362
8380
  /* @__PURE__ */ jsx68(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
8363
8381
  ] }) : null