@flytedan/flytebot-design-system 0.40.0 → 0.42.0

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
@@ -102,6 +102,7 @@ __export(index_exports, {
102
102
  FormatEta: () => FormatEta,
103
103
  FunnelChart: () => FunnelChart,
104
104
  Gate: () => Gate,
105
+ GatePending: () => GatePending,
105
106
  IMPORTANCE_LEVELS: () => IMPORTANCE_LEVELS,
106
107
  IconButton: () => IconButton,
107
108
  ImportanceTag: () => ImportanceTag,
@@ -1012,54 +1013,17 @@ function Collapsible({
1012
1013
  }
1013
1014
 
1014
1015
  // src/components/surfaces/Drawer.tsx
1015
- var React5 = __toESM(require("react"), 1);
1016
+ var React6 = __toESM(require("react"), 1);
1016
1017
  var import_react_dom3 = require("react-dom");
1017
- var import_jsx_runtime8 = require("react/jsx-runtime");
1018
- function Drawer({ open = true, title, onClose, footer, children, className = "", ...rest }) {
1019
- const zIndex = useOverlayLayer(open);
1020
- const [closing, setClosing] = React5.useState(false);
1021
- const close = React5.useCallback(() => {
1022
- if (!onClose) return;
1023
- setClosing(true);
1024
- setTimeout(onClose, 210);
1025
- }, [onClose]);
1026
- React5.useEffect(() => {
1027
- if (!open || !onClose) return;
1028
- const h = (e) => {
1029
- if (e.key === "Escape") close();
1030
- };
1031
- document.addEventListener("keydown", h);
1032
- return () => document.removeEventListener("keydown", h);
1033
- }, [open, onClose, close]);
1034
- if (!open) return null;
1035
- return (0, import_react_dom3.createPortal)(
1036
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(LayerProvider, { zIndex, children: [
1037
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close }),
1038
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("aside", { className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, style: { zIndex }, children: [
1039
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "fd-card-head", style: { flex: "none" }, children: [
1040
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
1041
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("i", { className: "ph ph-x" }) }) : null
1042
- ] }),
1043
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children }),
1044
- footer ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "fd-card-foot", style: { flex: "none" }, children: typeof footer === "function" ? footer(close) : footer }) : null
1045
- ] })
1046
- ] }),
1047
- document.body
1048
- );
1049
- }
1050
-
1051
- // src/components/surfaces/Modal.tsx
1052
- var React7 = __toESM(require("react"), 1);
1053
- var import_react_dom4 = require("react-dom");
1054
1018
 
1055
1019
  // src/kits/useFocusTrap.ts
1056
- var React6 = __toESM(require("react"), 1);
1020
+ var React5 = __toESM(require("react"), 1);
1057
1021
  var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
1058
1022
  function getFocusable(container) {
1059
1023
  return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR));
1060
1024
  }
1061
1025
  function useFocusTrap(containerRef, active) {
1062
- React6.useEffect(() => {
1026
+ React5.useEffect(() => {
1063
1027
  if (!active) return;
1064
1028
  const container = containerRef.current;
1065
1029
  if (!container) return;
@@ -1095,7 +1059,46 @@ function useFocusTrap(containerRef, active) {
1095
1059
  }, [active, containerRef]);
1096
1060
  }
1097
1061
 
1062
+ // src/components/surfaces/Drawer.tsx
1063
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1064
+ function Drawer({ open = true, title, onClose, footer, children, className = "", ...rest }) {
1065
+ const zIndex = useOverlayLayer(open);
1066
+ const asideRef = React6.useRef(null);
1067
+ useFocusTrap(asideRef, !!open);
1068
+ const [closing, setClosing] = React6.useState(false);
1069
+ const close = React6.useCallback(() => {
1070
+ if (!onClose) return;
1071
+ setClosing(true);
1072
+ setTimeout(onClose, 210);
1073
+ }, [onClose]);
1074
+ React6.useEffect(() => {
1075
+ if (!open || !onClose) return;
1076
+ const h = (e) => {
1077
+ if (e.key === "Escape") close();
1078
+ };
1079
+ document.addEventListener("keydown", h);
1080
+ return () => document.removeEventListener("keydown", h);
1081
+ }, [open, onClose, close]);
1082
+ if (!open) return null;
1083
+ return (0, import_react_dom3.createPortal)(
1084
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(LayerProvider, { zIndex, children: [
1085
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close }),
1086
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("aside", { ref: asideRef, className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, style: { zIndex }, children: [
1087
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "fd-card-head", style: { flex: "none" }, children: [
1088
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
1089
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("i", { className: "ph ph-x" }) }) : null
1090
+ ] }),
1091
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children }),
1092
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "fd-card-foot", style: { flex: "none" }, children: typeof footer === "function" ? footer(close) : footer }) : null
1093
+ ] })
1094
+ ] }),
1095
+ document.body
1096
+ );
1097
+ }
1098
+
1098
1099
  // src/components/surfaces/Modal.tsx
1100
+ var React7 = __toESM(require("react"), 1);
1101
+ var import_react_dom4 = require("react-dom");
1099
1102
  var import_jsx_runtime9 = require("react/jsx-runtime");
1100
1103
  function Modal({ open = true, title, description, onClose, footer, wide = false, children, className = "", ...rest }) {
1101
1104
  const [closing, setClosing] = React7.useState(false);
@@ -7300,14 +7303,14 @@ function AccountMenu({
7300
7303
  className = "",
7301
7304
  ...rest
7302
7305
  }) {
7303
- const { user, roles, can: can2, signOut: ctxSignOut, demo } = useSessionContext();
7306
+ const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
7304
7307
  const [open, setOpen] = React43.useState(false);
7305
7308
  const [switching, setSwitching] = React43.useState(false);
7306
7309
  const [signingOut, setSigningOut] = React43.useState(false);
7307
7310
  const [signOutError, setSignOutError] = React43.useState(null);
7308
7311
  const ref = React43.useRef(null);
7309
- const visibleLinks = links.filter((l) => !l.perm || can2(l.perm));
7310
- const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || can2(l.perm)) })).filter((g) => g.links.length);
7312
+ const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
7313
+ const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
7311
7314
  const closeMenu = () => {
7312
7315
  setOpen(false);
7313
7316
  setSignOutError(null);
@@ -10614,8 +10617,39 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
10614
10617
  }
10615
10618
  );
10616
10619
  }
10617
- function Gate({ perm, anyOf, role, silent = false, fallback, compact: compact3 = false, children }) {
10618
- const { can: can2, canAny: canAny2, hasRole: hasRole2 } = useSessionContext();
10620
+ function GatePending({ compact: compact3 = false, className = "" }) {
10621
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
10622
+ "div",
10623
+ {
10624
+ className: ["fd-stack", className].filter(Boolean).join(" "),
10625
+ role: "status",
10626
+ style: {
10627
+ gap: 10,
10628
+ alignItems: "flex-start",
10629
+ padding: compact3 ? "14px 16px" : "28px 24px",
10630
+ borderRadius: 10,
10631
+ border: "1px dashed var(--border-strong)",
10632
+ background: "var(--surface-2)",
10633
+ maxWidth: 560,
10634
+ textAlign: "left"
10635
+ },
10636
+ children: [
10637
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-row", style: { gap: 8 }, children: [
10638
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
10639
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
10640
+ ] }),
10641
+ /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: "Your access can't be verified right now. This will resolve on its own once the connection is back." })
10642
+ ]
10643
+ }
10644
+ );
10645
+ }
10646
+ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, compact: compact3 = false, children }) {
10647
+ const { can: can2, canAny: canAny2, hasRole: hasRole2, pending } = useSessionContext();
10648
+ if (pending) {
10649
+ if (pendingFallback !== void 0) return pendingFallback;
10650
+ if (silent) return null;
10651
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(GatePending, { compact: compact3 });
10652
+ }
10619
10653
  let ok = true;
10620
10654
  if (perm) ok = ok && can2(perm);
10621
10655
  if (anyOf) ok = ok && canAny2(anyOf);
@@ -10638,14 +10672,14 @@ function FeatureGate({
10638
10672
  bypassPerm = "flags.manage"
10639
10673
  }) {
10640
10674
  SessionKit.useSession();
10641
- const { can: can2 } = useSessionContext();
10675
+ const { can: can2, pending } = useSessionContext();
10642
10676
  const rt = useFeatureStatus(flag);
10643
10677
  if (!SessionKit.isEnabled(flag)) return fallback;
10644
10678
  if (rt.complete || rt.mode === "test") return children;
10645
10679
  if (!preview) return fallback;
10646
10680
  const f = SessionKit.findFlag(flag) || {};
10647
10681
  const missing = rt.missing || [];
10648
- const canBypass = bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
10682
+ const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
10649
10683
  return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
10650
10684
  ComingSoon,
10651
10685
  {
@@ -10665,7 +10699,10 @@ function FeatureGate({
10665
10699
  );
10666
10700
  }
10667
10701
  function PermissionHint({ perm, children }) {
10668
- const { can: can2 } = useSessionContext();
10702
+ const { can: can2, pending } = useSessionContext();
10703
+ if (pending) {
10704
+ return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { style: { pointerEvents: "none" }, children }) });
10705
+ }
10669
10706
  if (can2(perm)) return children;
10670
10707
  return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
10671
10708
  "span",
@@ -14107,6 +14144,7 @@ function useDocumentTitle(routeTitle, appName) {
14107
14144
  FormatEta,
14108
14145
  FunnelChart,
14109
14146
  Gate,
14147
+ GatePending,
14110
14148
  IMPORTANCE_LEVELS,
14111
14149
  IconButton,
14112
14150
  ImportanceTag,