@flytedan/flytebot-design-system 0.71.7 → 0.73.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
@@ -1013,6 +1013,7 @@ __export(index_exports, {
1013
1013
  ModeSwitch: () => ModeSwitch,
1014
1014
  ModelControls: () => ModelControls,
1015
1015
  NumberInput: () => NumberInput,
1016
+ OVERLAY_BREAKPOINT: () => OVERLAY_BREAKPOINT,
1016
1017
  OVERLAY_CEILING: () => OVERLAY_CEILING,
1017
1018
  POPOVER_BODY_MIN: () => POPOVER_BODY_MIN,
1018
1019
  PacketCard: () => PacketCard,
@@ -1137,6 +1138,7 @@ __export(index_exports, {
1137
1138
  useDocumentTitle: () => useDocumentTitle,
1138
1139
  useFeatureStatus: () => useFeatureStatus,
1139
1140
  useLayerZIndex: () => useLayerZIndex,
1141
+ useOverlayLayout: () => useOverlayLayout,
1140
1142
  usePopoverPosition: () => usePopoverPosition,
1141
1143
  useResponsiveRail: () => useResponsiveRail,
1142
1144
  useRuntimeMode: () => useRuntimeMode,
@@ -2083,7 +2085,7 @@ function Collapsible({
2083
2085
  var React6 = __toESM(require("react"), 1);
2084
2086
  var import_react_dom3 = require("react-dom");
2085
2087
  var import_jsx_runtime9 = require("react/jsx-runtime");
2086
- function Drawer({ open: open2 = true, title, onClose, footer, children, className = "", ...rest }) {
2088
+ function Drawer({ open: open2 = true, title, label, onClose, footer, bare = false, children, className = "", ...rest }) {
2087
2089
  const asideRef = React6.useRef(null);
2088
2090
  const [closing, setClosing] = React6.useState(false);
2089
2091
  const close2 = React6.useCallback(() => {
@@ -2093,16 +2095,22 @@ function Drawer({ open: open2 = true, title, onClose, footer, children, classNam
2093
2095
  }, [onClose]);
2094
2096
  const layer = useStackedLayer({ active: !!open2, containerRef: asideRef, trap: true, onEscape: onClose ? close2 : void 0 });
2095
2097
  const zIndex = useLayerZIndex(layer);
2098
+ const titleId = React6.useId();
2099
+ const accessibleName = bare ? label ?? (typeof title === "string" ? title : void 0) : label;
2100
+ const unnamed = !!open2 && bare && !accessibleName;
2101
+ React6.useEffect(() => {
2102
+ if (process.env.NODE_ENV !== "production" && unnamed) console.warn("Drawer: a bare Drawer has no header to name it. Pass `label`, or a string `title`, so the dialog has an accessible name.");
2103
+ }, [unnamed]);
2096
2104
  if (!open2) return null;
2097
2105
  return (0, import_react_dom3.createPortal)(
2098
2106
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(StackedLayerProvider, { layer, children: [
2099
2107
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close2 }),
2100
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("aside", { ref: asideRef, className: ["fd-drawer", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", ...rest, style: { zIndex }, children: [
2101
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "fd-card-head", style: { flex: "none" }, children: [
2102
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
2108
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("aside", { ref: asideRef, className: ["fd-drawer", bare ? "is-bare" : "", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", "aria-label": accessibleName, "aria-labelledby": bare || label ? void 0 : titleId, ...rest, style: { zIndex }, children: [
2109
+ bare ? null : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "fd-card-head", style: { flex: "none" }, children: [
2110
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { id: titleId, className: "fd-card-head-title", title: truncationTitle(title), children: title }),
2103
2111
  onClose ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close2, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("i", { className: "ph ph-x" }) }) : null
2104
2112
  ] }),
2105
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children }),
2113
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: bare ? { flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column" } : { flex: "1 1 auto", minHeight: 0, overflow: "auto", padding: 20 }, children: typeof children === "function" ? children(close2) : children }),
2106
2114
  footer ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "fd-card-foot", style: { flex: "none" }, children: typeof footer === "function" ? footer(close2) : footer }) : null
2107
2115
  ] })
2108
2116
  ] }),
@@ -2672,8 +2680,16 @@ function Topbar({
2672
2680
 
2673
2681
  // src/kits/useResponsiveRail.ts
2674
2682
  var React15 = __toESM(require("react"), 1);
2683
+
2684
+ // src/kits/overlayLayout.ts
2685
+ var OVERLAY_BREAKPOINT = 1024;
2686
+ function useOverlayLayout() {
2687
+ return useIsNarrow(OVERLAY_BREAKPOINT);
2688
+ }
2689
+
2690
+ // src/kits/useResponsiveRail.ts
2675
2691
  function useResponsiveRail(options = {}) {
2676
- const { breakpoint = 1024, initialOpen = true, onPersist } = options;
2692
+ const { breakpoint = OVERLAY_BREAKPOINT, initialOpen = true, onPersist } = options;
2677
2693
  const navRef = React15.useRef(null);
2678
2694
  const overlay = useIsNarrow(breakpoint);
2679
2695
  const [open2, setOpenRaw] = React15.useState(() => overlay ? false : initialOpen);
@@ -2714,7 +2730,7 @@ function AppShell({
2714
2730
  navFooter,
2715
2731
  initialNavOpen = true,
2716
2732
  onNavOpenChange,
2717
- railBreakpoint = 1024,
2733
+ railBreakpoint = OVERLAY_BREAKPOINT,
2718
2734
  crumbs,
2719
2735
  loading,
2720
2736
  actions,
@@ -5034,7 +5050,7 @@ var import_jsx_runtime50 = require("react/jsx-runtime");
5034
5050
  var TAIL_CHARS = 12;
5035
5051
  var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
5036
5052
  function splitForMiddleEllipsis(text) {
5037
- const chars = Array.from(graphemes.segment(text), (part) => part.segment);
5053
+ const chars = Array.from(graphemes.segment(text), (part2) => part2.segment);
5038
5054
  if (chars.length <= TAIL_CHARS) return { head: text, tail: "" };
5039
5055
  return { head: chars.slice(0, -TAIL_CHARS).join(""), tail: chars.slice(-TAIL_CHARS).join("") };
5040
5056
  }
@@ -7070,7 +7086,8 @@ function StepList({
7070
7086
  onToggle,
7071
7087
  showDurations = true,
7072
7088
  dense = false,
7073
- className = ""
7089
+ className = "",
7090
+ active = false
7074
7091
  }) {
7075
7092
  const [openState, setOpenState] = React39.useState(defaultOpen);
7076
7093
  const open2 = openProp == null ? openState : openProp;
@@ -7080,15 +7097,15 @@ function StepList({
7080
7097
  const failed = steps.filter((s) => s.status === "error").length;
7081
7098
  const total = steps.reduce((n, s) => n + (s.durationMs || 0), 0);
7082
7099
  const current2 = steps.filter((s) => s.status === "running").slice(-1)[0];
7083
- const summary = label || (running ? current2 ? current2.label : "Working" : total ? "Worked for " + formatDuration(total) : "Steps");
7100
+ const summary = label || (running ? current2 ? current2.label : "Working" : active ? "Steps so far" : total ? "Worked for " + formatDuration(total) : "Steps");
7084
7101
  const toggle = () => {
7085
7102
  const next = !open2;
7086
7103
  if (openProp == null) setOpenState(next);
7087
7104
  onToggle && onToggle(next);
7088
7105
  };
7089
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: ["fd-steps", dense ? "is-dense" : "", open2 ? "is-open" : "", className].filter(Boolean).join(" "), children: [
7106
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: ["fd-steps", dense ? "is-dense" : "", active ? "is-active" : "", open2 ? "is-open" : "", className].filter(Boolean).join(" "), children: [
7090
7107
  /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", className: "fd-steps-head", onClick: toggle, "aria-expanded": open2, children: [
7091
- running ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-steps-spin", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-" + (failed ? "warning-circle" : "check-circle"), "aria-hidden": "true" }),
7108
+ running ? /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-steps-spin", "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("i", { className: "ph ph-" + (failed ? "warning-circle" : active ? "list-checks" : "check-circle"), "aria-hidden": "true" }),
7092
7109
  /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "fd-steps-title", title: truncationTitle(summary), children: summary }),
7093
7110
  /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "fd-steps-count fd-tabular", children: [
7094
7111
  steps.length,
@@ -13565,17 +13582,13 @@ function PreferenceMeter({
13565
13582
  }
13566
13583
 
13567
13584
  // src/components/chat/AgentChatPanel.tsx
13568
- var React75 = __toESM(require("react"), 1);
13585
+ var React76 = __toESM(require("react"), 1);
13569
13586
 
13570
13587
  // src/components/chat/chatEngine.ts
13588
+ var React71 = __toESM(require("react"), 1);
13589
+
13590
+ // src/components/chat/chatStore.ts
13571
13591
  var React70 = __toESM(require("react"), 1);
13572
- var CHAT_UNAVAILABLE = "chat_unavailable";
13573
- var JOB_PENDING = ["queued", "running"];
13574
- var JOB_SUCCESS = ["completed", "recovered"];
13575
- var STORAGE_PREFIX = "fdchat:job:";
13576
- var seq = 0;
13577
- var uid = (p) => p + "_" + ++seq + "_" + Date.now().toString(36);
13578
- var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
13579
13592
  var safeStore = {
13580
13593
  get(k) {
13581
13594
  try {
@@ -13597,6 +13610,38 @@ var safeStore = {
13597
13610
  }
13598
13611
  }
13599
13612
  };
13613
+ var part = (v) => encodeURIComponent(v);
13614
+ var jobKey = (threadId) => "fdchat:job:" + part(threadId);
13615
+ var draftKey = (owner, contextType, contextId) => "fdchat:draft:" + [owner, contextType, contextId].map(part).join(":");
13616
+ function useChatDraft(owner, contextType, contextId, store = safeStore) {
13617
+ if (owner === "") throw new Error("useChatDraft: draftOwner is an empty string; pass the signed-in user's id, or null for no owner.");
13618
+ const key = owner === null ? null : draftKey(owner, contextType, contextId);
13619
+ const read2 = (k) => k ? store.get(k) || "" : "";
13620
+ const [state, setState] = React70.useState(() => ({ key, text: read2(key) }));
13621
+ let current2 = state;
13622
+ if (state.key !== key) {
13623
+ current2 = { key, text: read2(key) };
13624
+ setState(current2);
13625
+ }
13626
+ const setText = React70.useCallback((text) => {
13627
+ if (key) {
13628
+ if (text) {
13629
+ store.set(key, text);
13630
+ if (store.get(key) !== text) store.del(key);
13631
+ } else store.del(key);
13632
+ }
13633
+ setState({ key, text });
13634
+ }, [key, store]);
13635
+ return [current2.text, setText];
13636
+ }
13637
+
13638
+ // src/components/chat/chatEngine.ts
13639
+ var CHAT_UNAVAILABLE = "chat_unavailable";
13640
+ var JOB_PENDING = ["queued", "running"];
13641
+ var JOB_SUCCESS = ["completed", "recovered"];
13642
+ var seq = 0;
13643
+ var uid = (p) => p + "_" + ++seq + "_" + Date.now().toString(36);
13644
+ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
13600
13645
  var isSystemMessage = (m) => !!m && (m.role === "system" || m.metadata != null && m.metadata.type === "system");
13601
13646
  var visibleMessages = (list) => (list || []).filter((m) => !isSystemMessage(m));
13602
13647
  function jobBucket(status) {
@@ -13605,6 +13650,20 @@ function jobBucket(status) {
13605
13650
  if (JOB_SUCCESS.indexOf(s) !== -1) return "success";
13606
13651
  return "failure";
13607
13652
  }
13653
+ function defaultDescribeWaiting(pending) {
13654
+ return "Waiting on " + pending.length + " background " + (pending.length === 1 ? "task" : "tasks");
13655
+ }
13656
+ function withWaiting(list, describe) {
13657
+ const pending = list.filter((m) => m.taskPending);
13658
+ let turn = -1;
13659
+ list.forEach((m, i) => {
13660
+ if (m.working) turn = i;
13661
+ });
13662
+ return list.map((m, i) => {
13663
+ const want = i === turn && pending.length ? describe(pending) : void 0;
13664
+ return m.waitingFor === want ? m : Object.assign({}, m, { waitingFor: want });
13665
+ });
13666
+ }
13608
13667
  function useChatEngine(opts) {
13609
13668
  const {
13610
13669
  contextType,
@@ -13614,6 +13673,7 @@ function useChatEngine(opts) {
13614
13673
  threadId: threadIdProp,
13615
13674
  pollIntervalMs = 1500,
13616
13675
  pendingTimeoutMs = 18e4,
13676
+ describeWaiting = defaultDescribeWaiting,
13617
13677
  store = safeStore,
13618
13678
  onPacket,
13619
13679
  onThreadReady,
@@ -13622,35 +13682,38 @@ function useChatEngine(opts) {
13622
13682
  onClear,
13623
13683
  onFeedback
13624
13684
  } = opts || {};
13625
- const [status, setStatus] = React70.useState("idle");
13626
- const [threadId, setThreadId] = React70.useState(null);
13627
- const [messages, setMessages] = React70.useState([]);
13628
- const [queue, setQueue] = React70.useState([]);
13629
- const [fatal, setFatal] = React70.useState(null);
13630
- const [busy, setBusy] = React70.useState(false);
13631
- const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
13632
- const listRef = React70.useRef([]);
13633
- const queueRef = React70.useRef([]);
13634
- const busyRef = React70.useRef(false);
13635
- const loadedRef = React70.useRef(false);
13636
- const stoppedRef = React70.useRef(false);
13637
- const abortRef = React70.useRef(null);
13638
- const serverCount = React70.useRef(0);
13639
- const serverIds = React70.useRef(/* @__PURE__ */ new Set());
13640
- const liveTurn = React70.useRef(null);
13641
- const lastTurnOwn = React70.useRef(/* @__PURE__ */ new Set());
13642
- const retired = React70.useRef(/* @__PURE__ */ new Set());
13643
- const threadRef = React70.useRef(null);
13644
- const mounted = React70.useRef(true);
13645
- React70.useEffect(() => {
13685
+ const [status, setStatus] = React71.useState("idle");
13686
+ const [threadId, setThreadId] = React71.useState(null);
13687
+ const [messages, setMessages] = React71.useState([]);
13688
+ const [queue, setQueue] = React71.useState([]);
13689
+ const [fatal, setFatal] = React71.useState(null);
13690
+ const [busy, setBusy] = React71.useState(false);
13691
+ const [turnStartedAt, setTurnStartedAt] = React71.useState(null);
13692
+ const listRef = React71.useRef([]);
13693
+ const queueRef = React71.useRef([]);
13694
+ const busyRef = React71.useRef(false);
13695
+ const loadedRef = React71.useRef(false);
13696
+ const stoppedRef = React71.useRef(false);
13697
+ const abortRef = React71.useRef(null);
13698
+ const serverCount = React71.useRef(0);
13699
+ const serverIds = React71.useRef(/* @__PURE__ */ new Set());
13700
+ const liveTurn = React71.useRef(null);
13701
+ const lastTurnOwn = React71.useRef(/* @__PURE__ */ new Set());
13702
+ const retired = React71.useRef(/* @__PURE__ */ new Set());
13703
+ const threadRef = React71.useRef(null);
13704
+ const mounted = React71.useRef(true);
13705
+ React71.useEffect(() => {
13646
13706
  mounted.current = true;
13647
13707
  return () => {
13648
13708
  mounted.current = false;
13649
13709
  };
13650
13710
  }, []);
13711
+ const describeWaitingRef = React71.useRef(describeWaiting);
13712
+ describeWaitingRef.current = describeWaiting;
13651
13713
  const commit = (next) => {
13652
- listRef.current = next;
13653
- if (mounted.current) setMessages(next);
13714
+ const derived = withWaiting(next, (pending) => describeWaitingRef.current(pending));
13715
+ listRef.current = derived;
13716
+ if (mounted.current) setMessages(derived);
13654
13717
  };
13655
13718
  const patch = (id, p) => commit(listRef.current.map((m) => m.id === id ? Object.assign({}, m, typeof p === "function" ? p(m) : p) : m));
13656
13719
  const push = (...msgs) => commit(listRef.current.concat(msgs));
@@ -13664,7 +13727,7 @@ function useChatEngine(opts) {
13664
13727
  }
13665
13728
  return false;
13666
13729
  };
13667
- const loadThread = React70.useCallback(async (id) => {
13730
+ const loadThread = React71.useCallback(async (id) => {
13668
13731
  const data = await apiAdapter.getThread(id);
13669
13732
  const list = [...data && data.messages || []];
13670
13733
  serverCount.current = list.length;
@@ -13704,7 +13767,7 @@ function useChatEngine(opts) {
13704
13767
  packet: progress.packet ?? holder.packet
13705
13768
  });
13706
13769
  }
13707
- React70.useEffect(() => {
13770
+ React71.useEffect(() => {
13708
13771
  if (!apiAdapter) {
13709
13772
  setStatus("idle");
13710
13773
  setFatal(null);
@@ -13751,7 +13814,7 @@ function useChatEngine(opts) {
13751
13814
  setStatus("ready");
13752
13815
  loadedRef.current = true;
13753
13816
  onThreadReady && onThreadReady(id);
13754
- const stored = store.get(STORAGE_PREFIX + id);
13817
+ const stored = store.get(jobKey(id));
13755
13818
  const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
13756
13819
  if (stored) resumeJob(stored);
13757
13820
  else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
@@ -13770,7 +13833,7 @@ function useChatEngine(opts) {
13770
13833
  };
13771
13834
  }, [apiAdapter, contextType, contextId, threadIdProp]);
13772
13835
  async function pollJob(jobId, placeholderId) {
13773
- store.set(STORAGE_PREFIX + threadRef.current, jobId);
13836
+ store.set(jobKey(threadRef.current), jobId);
13774
13837
  const deadline = Date.now() + pendingTimeoutMs;
13775
13838
  while (true) {
13776
13839
  if (stoppedRef.current) break;
@@ -13818,7 +13881,7 @@ function useChatEngine(opts) {
13818
13881
  }
13819
13882
  }
13820
13883
  async function finishJob(_jobId, _job) {
13821
- store.del(STORAGE_PREFIX + threadRef.current);
13884
+ store.del(jobKey(threadRef.current));
13822
13885
  try {
13823
13886
  const list = await loadThread(threadRef.current);
13824
13887
  const withPacket = [...list].reverse().find((m) => m && m.packet);
@@ -13828,7 +13891,7 @@ function useChatEngine(opts) {
13828
13891
  }
13829
13892
  }
13830
13893
  function recordFailure(placeholderId, code, retryable, job) {
13831
- store.del(STORAGE_PREFIX + threadRef.current);
13894
+ store.del(jobKey(threadRef.current));
13832
13895
  if (!listRef.current.some((m) => m.id === placeholderId)) {
13833
13896
  push({ id: placeholderId, role: "assistant", text: null });
13834
13897
  }
@@ -13936,7 +13999,7 @@ function useChatEngine(opts) {
13936
13999
  await dispatchTurn(turn);
13937
14000
  }
13938
14001
  }
13939
- const send = React70.useCallback((text, attachments) => {
14002
+ const send = React71.useCallback((text, attachments) => {
13940
14003
  const body = (text || "").trim();
13941
14004
  if (!body && !(attachments && attachments.length)) return;
13942
14005
  if (status === "disconnected") return;
@@ -13946,7 +14009,7 @@ function useChatEngine(opts) {
13946
14009
  stoppedRef.current = false;
13947
14010
  drain();
13948
14011
  }, [status]);
13949
- const stop = React70.useCallback(() => {
14012
+ const stop = React71.useCallback(() => {
13950
14013
  stoppedRef.current = true;
13951
14014
  const ac = abortRef.current;
13952
14015
  if (ac) {
@@ -13962,14 +14025,14 @@ function useChatEngine(opts) {
13962
14025
  Promise.resolve(apiAdapter.cancelJob(holder.jobId)).catch(() => {
13963
14026
  });
13964
14027
  }
13965
- store.del(STORAGE_PREFIX + threadRef.current);
14028
+ store.del(jobKey(threadRef.current));
13966
14029
  }
13967
14030
  }, [apiAdapter]);
13968
- const removeQueued = React70.useCallback((id) => {
14031
+ const removeQueued = React71.useCallback((id) => {
13969
14032
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
13970
14033
  setQueue(queueRef.current.slice());
13971
14034
  }, []);
13972
- const retry = React70.useCallback(() => {
14035
+ const retry = React71.useCallback(() => {
13973
14036
  const list = listRef.current;
13974
14037
  let at = -1;
13975
14038
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -13986,19 +14049,19 @@ function useChatEngine(opts) {
13986
14049
  setQueue(queueRef.current.slice());
13987
14050
  drain();
13988
14051
  }, []);
13989
- const clear = React70.useCallback(() => {
14052
+ const clear = React71.useCallback(() => {
13990
14053
  commit([]);
13991
14054
  serverCount.current = 0;
13992
14055
  queueRef.current = [];
13993
14056
  setQueue([]);
13994
14057
  onClear && onClear();
13995
14058
  }, [onClear]);
13996
- const setFeedback = React70.useCallback((id, value) => {
14059
+ const setFeedback = React71.useCallback((id, value) => {
13997
14060
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
13998
14061
  const msg = listRef.current.find((m) => m.id === id);
13999
14062
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
14000
14063
  }, [onFeedback]);
14001
- const reload = React70.useCallback(async () => {
14064
+ const reload = React71.useCallback(async () => {
14002
14065
  if (!threadRef.current) return;
14003
14066
  setStatus("loading");
14004
14067
  try {
@@ -14036,10 +14099,10 @@ var ChatKit = {
14036
14099
  };
14037
14100
 
14038
14101
  // src/components/chat/ChatTranscript.tsx
14039
- var React72 = __toESM(require("react"), 1);
14102
+ var React73 = __toESM(require("react"), 1);
14040
14103
 
14041
14104
  // src/components/chat/ChatTurn.tsx
14042
- var React71 = __toESM(require("react"), 1);
14105
+ var React72 = __toESM(require("react"), 1);
14043
14106
  var import_jsx_runtime102 = require("react/jsx-runtime");
14044
14107
  function JsonView({ value }) {
14045
14108
  let text;
@@ -14076,7 +14139,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
14076
14139
  ] });
14077
14140
  }
14078
14141
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
14079
- const [open2, setOpen] = React71.useState(defaultOpen);
14142
+ const [open2, setOpen] = React72.useState(defaultOpen);
14080
14143
  if (!text) return null;
14081
14144
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
14082
14145
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -14093,7 +14156,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
14093
14156
  ] });
14094
14157
  }
14095
14158
  function Citations({ items = [], onOpen }) {
14096
- const [open2, setOpen] = React71.useState(false);
14159
+ const [open2, setOpen] = React72.useState(false);
14097
14160
  if (!items.length) return null;
14098
14161
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-cites", children: [
14099
14162
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -14119,7 +14182,7 @@ function clampText(text, max) {
14119
14182
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
14120
14183
  }
14121
14184
  function MessageBody({ message: m, ctx }) {
14122
- const [expanded, setExpanded] = React71.useState(false);
14185
+ const [expanded, setExpanded] = React72.useState(false);
14123
14186
  const isUser = m.role === "user";
14124
14187
  const raw = m.text || "";
14125
14188
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -14127,7 +14190,7 @@ function MessageBody({ message: m, ctx }) {
14127
14190
  const showMd = ctx.markdown && !isUser;
14128
14191
  return /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-body", children: [
14129
14192
  m.thinking && ctx.showThinking ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
14130
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
14193
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), active: !!m.working, dense: true }) : null,
14131
14194
  body ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
14132
14195
  showMd ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("div", { className: "fdc-plain", children: body }),
14133
14196
  m.streaming ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
@@ -14159,8 +14222,8 @@ function MessageBody({ message: m, ctx }) {
14159
14222
  /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", {})
14160
14223
  ] }),
14161
14224
  /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("span", { className: "fdc-working-label", children: [
14162
- m.resumed ? "Resuming" : "Working",
14163
- m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("span", { className: "fdc-working-job", children: [
14225
+ m.waitingFor || (m.resumed ? "Resuming" : "Working"),
14226
+ !m.waitingFor && m.job && m.job.status ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("span", { className: "fdc-working-job", children: [
14164
14227
  " \xB7 ",
14165
14228
  m.job.status
14166
14229
  ] }) : null,
@@ -14168,8 +14231,7 @@ function MessageBody({ message: m, ctx }) {
14168
14231
  " \xB7 ",
14169
14232
  m.job.detail
14170
14233
  ] }) : null
14171
- ] }),
14172
- m.jobId ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
14234
+ ] })
14173
14235
  ] }) : null,
14174
14236
  m.stopped ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)("div", { className: "fdc-stopped", children: [
14175
14237
  /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
@@ -14199,7 +14261,7 @@ function RunActions({ group, ctx }) {
14199
14261
  ] }),
14200
14262
  isAssistant && ctx.onRetry ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
14201
14263
  group.role === "user" && ctx.onEdit ? /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
14202
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React71.Fragment, { children: [
14264
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ (0, import_jsx_runtime102.jsxs)(React72.Fragment, { children: [
14203
14265
  /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("button", { type: "button", className: "fdc-act" + (fb === "up" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "up"), "aria-pressed": fb === "up", "aria-label": "Good response", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
14204
14266
  /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("button", { type: "button", className: "fdc-act" + (fb === "down" ? " is-on" : ""), onClick: () => ctx.onFeedback(last.id, "down"), "aria-pressed": fb === "down", "aria-label": "Bad response", children: /* @__PURE__ */ (0, import_jsx_runtime102.jsx)("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
14205
14267
  ] }) : null,
@@ -14294,10 +14356,10 @@ function ChatTranscript({
14294
14356
  renderEmpty,
14295
14357
  className = ""
14296
14358
  }) {
14297
- const scroller = React72.useRef(null);
14298
- const stick = React72.useRef(true);
14299
- const [pill, setPill] = React72.useState(0);
14300
- const seen = React72.useRef(0);
14359
+ const scroller = React73.useRef(null);
14360
+ const stick = React73.useRef(true);
14361
+ const [pill, setPill] = React73.useState(0);
14362
+ const seen = React73.useRef(0);
14301
14363
  const toBottom = (smooth) => {
14302
14364
  const el = scroller.current;
14303
14365
  if (!el) return;
@@ -14316,7 +14378,7 @@ function ChatTranscript({
14316
14378
  seen.current = messages.length;
14317
14379
  }
14318
14380
  };
14319
- React72.useLayoutEffect(() => {
14381
+ React73.useLayoutEffect(() => {
14320
14382
  const el = scroller.current;
14321
14383
  if (!el) return;
14322
14384
  if (stick.current) {
@@ -14324,7 +14386,7 @@ function ChatTranscript({
14324
14386
  seen.current = messages.length;
14325
14387
  } else setPill(Math.max(0, messages.length - seen.current));
14326
14388
  }, [messages]);
14327
- React72.useEffect(() => {
14389
+ React73.useEffect(() => {
14328
14390
  const el = scroller.current;
14329
14391
  const inner = el && el.firstChild;
14330
14392
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -14334,7 +14396,7 @@ function ChatTranscript({
14334
14396
  ro.observe(inner);
14335
14397
  return () => ro.disconnect();
14336
14398
  }, []);
14337
- const groups = React72.useMemo(() => groupMessages(messages), [messages]);
14399
+ const groups = React73.useMemo(() => groupMessages(messages), [messages]);
14338
14400
  const empty = !messages.length && status === "ready";
14339
14401
  return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
14340
14402
  /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -14358,7 +14420,7 @@ function ChatTranscript({
14358
14420
  const prev = groups[i - 1];
14359
14421
  const k = dayKey(g.messages[0].timestamp);
14360
14422
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
14361
- return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(React72.Fragment, { children: [
14423
+ return /* @__PURE__ */ (0, import_jsx_runtime103.jsxs)(React73.Fragment, { children: [
14362
14424
  showDay ? /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("div", { className: "fdc-day", children: /* @__PURE__ */ (0, import_jsx_runtime103.jsx)("span", { children: dayLabel(k) }) }) : null,
14363
14425
  /* @__PURE__ */ (0, import_jsx_runtime103.jsx)(ChatTurn, { group: g, ctx })
14364
14426
  ] }, g.key || i);
@@ -14375,7 +14437,7 @@ function ChatTranscript({
14375
14437
  var TranscriptKit = { groupMessages };
14376
14438
 
14377
14439
  // src/components/chat/ChatComposer.tsx
14378
- var React73 = __toESM(require("react"), 1);
14440
+ var React74 = __toESM(require("react"), 1);
14379
14441
  var import_jsx_runtime104 = require("react/jsx-runtime");
14380
14442
  function ChatComposer({
14381
14443
  onSubmit,
@@ -14403,17 +14465,17 @@ function ChatComposer({
14403
14465
  onReject,
14404
14466
  onOpenAttachment
14405
14467
  }) {
14406
- const [text, setText] = React73.useState(draft || "");
14407
- const [trigger, setTrigger] = React73.useState(null);
14408
- const [mentionItems, setMentionItems] = React73.useState([]);
14409
- const [listening, setListening] = React73.useState(false);
14410
- const [notice, setNotice] = React73.useState(null);
14411
- const editor = React73.useRef(null);
14412
- const wrap = React73.useRef(null);
14413
- const stopVoice = React73.useRef(null);
14468
+ const [text, setText] = React74.useState(draft || "");
14469
+ const [trigger, setTrigger] = React74.useState(null);
14470
+ const [mentionItems, setMentionItems] = React74.useState([]);
14471
+ const [listening, setListening] = React74.useState(false);
14472
+ const [notice, setNotice] = React74.useState(null);
14473
+ const editor = React74.useRef(null);
14474
+ const wrap = React74.useRef(null);
14475
+ const stopVoice = React74.useRef(null);
14414
14476
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
14415
14477
  } });
14416
- React73.useEffect(() => {
14478
+ React74.useEffect(() => {
14417
14479
  if (draft != null && draft !== text) setText(draft);
14418
14480
  }, [draft]);
14419
14481
  const change = (v) => {
@@ -14449,7 +14511,7 @@ function ChatComposer({
14449
14511
  e.preventDefault();
14450
14512
  staged.add(found.files);
14451
14513
  };
14452
- React73.useEffect(() => {
14514
+ React74.useEffect(() => {
14453
14515
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
14454
14516
  setMentionItems([]);
14455
14517
  return;
@@ -14467,7 +14529,7 @@ function ChatComposer({
14467
14529
  const q = (trigger.query || "").toLowerCase();
14468
14530
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
14469
14531
  }, [trigger, mentionSources]);
14470
- const slashItems = React73.useMemo(() => {
14532
+ const slashItems = React74.useMemo(() => {
14471
14533
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
14472
14534
  const q = (trigger.query || "").toLowerCase();
14473
14535
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -14637,12 +14699,12 @@ function ChatComposer({
14637
14699
  }
14638
14700
 
14639
14701
  // src/components/chat/ChatSessionBar.tsx
14640
- var React74 = __toESM(require("react"), 1);
14702
+ var React75 = __toESM(require("react"), 1);
14641
14703
  var import_jsx_runtime105 = require("react/jsx-runtime");
14642
14704
  var compact2 = meterFormats.compact;
14643
14705
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
14644
- const [open2, setOpen] = React74.useState(false);
14645
- const anchor = React74.useRef(null);
14706
+ const [open2, setOpen] = React75.useState(false);
14707
+ const anchor = React75.useRef(null);
14646
14708
  const stats = sessionStats || null;
14647
14709
  const cu = contextUsage || null;
14648
14710
  const limits = usageLimits || null;
@@ -14657,7 +14719,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
14657
14719
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
14658
14720
  if (cu) bits.push(pct + "% context");
14659
14721
  const expandable = !!(cu || limits);
14660
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React74.Fragment, { children: [
14722
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React75.Fragment, { children: [
14661
14723
  /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)("div", { className: "fdc-bar", children: [
14662
14724
  /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(
14663
14725
  "button",
@@ -14798,7 +14860,7 @@ function ModelControls({
14798
14860
  ] })
14799
14861
  });
14800
14862
  }
14801
- return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React74.Fragment, { children: [
14863
+ return /* @__PURE__ */ (0, import_jsx_runtime105.jsxs)(React75.Fragment, { children: [
14802
14864
  /* @__PURE__ */ (0, import_jsx_runtime105.jsx)(
14803
14865
  MenuButton,
14804
14866
  {
@@ -14837,6 +14899,7 @@ function AgentChatPanel({
14837
14899
  /* required */
14838
14900
  contextType,
14839
14901
  contextId,
14902
+ draftOwner,
14840
14903
  apiAdapter,
14841
14904
  threadId,
14842
14905
  /* identity + chrome */
@@ -14866,6 +14929,7 @@ function AgentChatPanel({
14866
14929
  packetRenderers,
14867
14930
  onApplyPacket,
14868
14931
  pendingTimeoutMs,
14932
+ describeWaiting,
14869
14933
  onOpenAttachment,
14870
14934
  errorCopy,
14871
14935
  /* composer */
@@ -14916,11 +14980,11 @@ function AgentChatPanel({
14916
14980
  onFeedback,
14917
14981
  onEditMessage
14918
14982
  }) {
14919
- const [panelWidth, setPanelWidth] = React75.useState(width);
14920
- const [applied, setApplied] = React75.useState({});
14921
- const [draft, setDraft] = React75.useState("");
14922
- const dragging = React75.useRef(null);
14923
- React75.useEffect(() => setPanelWidth(width), [width]);
14983
+ const [panelWidth, setPanelWidth] = React76.useState(width);
14984
+ const [applied, setApplied] = React76.useState({});
14985
+ const [draft, setDraft] = useChatDraft(draftOwner, contextType, contextId);
14986
+ const dragging = React76.useRef(null);
14987
+ React76.useEffect(() => setPanelWidth(width), [width]);
14924
14988
  const engine = useChatEngine({
14925
14989
  contextType,
14926
14990
  contextId,
@@ -14928,6 +14992,7 @@ function AgentChatPanel({
14928
14992
  initialMessage,
14929
14993
  threadId,
14930
14994
  pendingTimeoutMs,
14995
+ describeWaiting,
14931
14996
  onPacket,
14932
14997
  onThreadReady,
14933
14998
  onError,
@@ -15125,7 +15190,7 @@ function AgentChatPanel({
15125
15190
  }
15126
15191
 
15127
15192
  // src/components/files/FileViewer.tsx
15128
- var React76 = __toESM(require("react"), 1);
15193
+ var React77 = __toESM(require("react"), 1);
15129
15194
  var import_jsx_runtime107 = require("react/jsx-runtime");
15130
15195
  function previewKindOf(file) {
15131
15196
  const mime = (file.mime || "").toLowerCase();
@@ -15182,13 +15247,13 @@ function parseDelimited(text, delimiter) {
15182
15247
  return rows;
15183
15248
  }
15184
15249
  function usePreview(file, kind, resolveUrl) {
15185
- const [state, setState] = React76.useState({ status: "loading" });
15186
- const [attempt, setAttempt] = React76.useState(0);
15187
- const resolveRef = React76.useRef(resolveUrl);
15188
- React76.useEffect(() => {
15250
+ const [state, setState] = React77.useState({ status: "loading" });
15251
+ const [attempt, setAttempt] = React77.useState(0);
15252
+ const resolveRef = React77.useRef(resolveUrl);
15253
+ React77.useEffect(() => {
15189
15254
  resolveRef.current = resolveUrl;
15190
15255
  }, [resolveUrl]);
15191
- React76.useEffect(() => {
15256
+ React77.useEffect(() => {
15192
15257
  if (kind === "none") {
15193
15258
  setState({ status: "ready" });
15194
15259
  return;
@@ -15218,7 +15283,7 @@ function usePreview(file, kind, resolveUrl) {
15218
15283
  if (ac) ac.abort();
15219
15284
  };
15220
15285
  }, [file.id, kind, attempt]);
15221
- return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
15286
+ return { ...state, retry: React77.useCallback(() => setAttempt((a) => a + 1), []) };
15222
15287
  }
15223
15288
  function PreviewBody({ file, kind, state }) {
15224
15289
  if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime107.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
@@ -15263,13 +15328,13 @@ function PreviewBody({ file, kind, state }) {
15263
15328
  ] });
15264
15329
  }
15265
15330
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
15266
- const kind = React76.useMemo(() => previewKindOf(file), [file]);
15331
+ const kind = React77.useMemo(() => previewKindOf(file), [file]);
15267
15332
  const preview = usePreview(file, kind, resolveUrl);
15268
- const [tab, setTab] = React76.useState("preview");
15269
- const [downloading, setDownloading] = React76.useState(false);
15270
- const [downloadError, setDownloadError] = React76.useState(null);
15333
+ const [tab, setTab] = React77.useState("preview");
15334
+ const [downloading, setDownloading] = React77.useState(false);
15335
+ const [downloadError, setDownloadError] = React77.useState(null);
15271
15336
  const hasSide = sidePanel != null;
15272
- React76.useEffect(() => {
15337
+ React77.useEffect(() => {
15273
15338
  setTab("preview");
15274
15339
  }, [file.id]);
15275
15340
  const download = () => {
@@ -15336,7 +15401,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
15336
15401
  }
15337
15402
 
15338
15403
  // src/components/files/FileBrowser.tsx
15339
- var React77 = __toESM(require("react"), 1);
15404
+ var React78 = __toESM(require("react"), 1);
15340
15405
  var import_jsx_runtime108 = require("react/jsx-runtime");
15341
15406
  function childrenOf(folders, parentId) {
15342
15407
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
@@ -15446,8 +15511,8 @@ function FolderPickerMenu({
15446
15511
  ] });
15447
15512
  }
15448
15513
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
15449
- const [over, setOver] = React77.useState(false);
15450
- const dragCounter = React77.useRef(0);
15514
+ const [over, setOver] = React78.useState(false);
15515
+ const dragCounter = React78.useRef(0);
15451
15516
  const dropHandlers = isDropTarget ? {
15452
15517
  onDragEnter: (e) => {
15453
15518
  if (!hasInternalPayload(e)) return;
@@ -15495,8 +15560,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
15495
15560
  }
15496
15561
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
15497
15562
  const kids = childrenOf(folders, folder.id);
15498
- const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15499
- React77.useEffect(() => {
15563
+ const [expanded, setExpanded] = React78.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
15564
+ React78.useEffect(() => {
15500
15565
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
15501
15566
  }, [currentFolderId, folder.id, folders]);
15502
15567
  const isCurrent = folder.id === currentFolderId;
@@ -15562,15 +15627,15 @@ function FileBrowser({
15562
15627
  const canUpload = perm.canUpload !== false && !!onUpload;
15563
15628
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
15564
15629
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
15565
- const [createOpen, setCreateOpen] = React77.useState(false);
15566
- const [createName, setCreateName] = React77.useState("");
15567
- const [renameTarget, setRenameTarget] = React77.useState(null);
15568
- const [renameValue, setRenameValue] = React77.useState("");
15569
- const [deleteTarget, setDeleteTarget] = React77.useState(null);
15570
- const uploadInputRef = React77.useRef(null);
15571
- const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
15572
- const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
15573
- const currentFiles = React77.useMemo(
15630
+ const [createOpen, setCreateOpen] = React78.useState(false);
15631
+ const [createName, setCreateName] = React78.useState("");
15632
+ const [renameTarget, setRenameTarget] = React78.useState(null);
15633
+ const [renameValue, setRenameValue] = React78.useState("");
15634
+ const [deleteTarget, setDeleteTarget] = React78.useState(null);
15635
+ const uploadInputRef = React78.useRef(null);
15636
+ const crumbFolders = React78.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
15637
+ const subfolders = React78.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
15638
+ const currentFiles = React78.useMemo(
15574
15639
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
15575
15640
  [files, currentFolderId]
15576
15641
  );
@@ -15802,8 +15867,8 @@ function BreadcrumbCrumb({
15802
15867
  isDropTarget,
15803
15868
  onDropPayload
15804
15869
  }) {
15805
- const [over, setOver] = React77.useState(false);
15806
- const dragCounter = React77.useRef(0);
15870
+ const [over, setOver] = React78.useState(false);
15871
+ const dragCounter = React78.useRef(0);
15807
15872
  const dropHandlers = isDropTarget ? {
15808
15873
  onDragEnter: (e) => {
15809
15874
  if (!hasInternalPayload(e)) return;
@@ -15832,7 +15897,7 @@ function BreadcrumbCrumb({
15832
15897
  }
15833
15898
 
15834
15899
  // src/kits/query.ts
15835
- var React78 = __toESM(require("react"), 1);
15900
+ var React79 = __toESM(require("react"), 1);
15836
15901
 
15837
15902
  // src/kits/queryUrl.ts
15838
15903
  var historyUrlAdapter = {
@@ -15970,38 +16035,38 @@ function requestFor(params, query, paging, after) {
15970
16035
  }
15971
16036
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
15972
16037
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
15973
- const [base] = React78.useState(() => {
16038
+ const [base] = React79.useState(() => {
15974
16039
  const store = PREFS || window.PlannerPrefs;
15975
16040
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
15976
16041
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
15977
16042
  });
15978
- const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
15979
- const address = React78.useRef(mountParams);
15980
- const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
15981
- const savePref = React78.useCallback((patch2) => {
16043
+ const [mountParams] = React79.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
16044
+ const address = React79.useRef(mountParams);
16045
+ const [query, setQuery] = React79.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
16046
+ const savePref = React79.useCallback((patch2) => {
15982
16047
  const store = PREFS || window.PlannerPrefs;
15983
16048
  if (prefsKey && store) store.setTable(prefsKey, patch2);
15984
16049
  }, [prefsKey]);
15985
- const [res, setRes] = React78.useState(null);
15986
- const [loading, setLoading] = React78.useState(true);
15987
- const [loadingMore, setLoadingMore] = React78.useState(false);
15988
- const [failure, setFailure] = React78.useState(null);
15989
- const [reloadToken, setReloadToken] = React78.useState(0);
15990
- const moreController = React78.useRef(null);
16050
+ const [res, setRes] = React79.useState(null);
16051
+ const [loading, setLoading] = React79.useState(true);
16052
+ const [loadingMore, setLoadingMore] = React79.useState(false);
16053
+ const [failure, setFailure] = React79.useState(null);
16054
+ const [reloadToken, setReloadToken] = React79.useState(0);
16055
+ const moreController = React79.useRef(null);
15991
16056
  const depKey = (deps || []).join("|");
15992
16057
  const paramKey = JSON.stringify(params || {});
15993
16058
  const queryKey = JSON.stringify(query);
15994
- const lifetime = React78.useRef(null);
15995
- React78.useEffect(() => {
16059
+ const lifetime = React79.useRef(null);
16060
+ React79.useEffect(() => {
15996
16061
  const controller = new AbortController();
15997
16062
  lifetime.current = controller;
15998
16063
  return () => controller.abort();
15999
16064
  }, []);
16000
- const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
16001
- React78.useLayoutEffect(() => {
16065
+ const latest = React79.useRef({ res, loading, query, params, endpoint, url, base });
16066
+ React79.useLayoutEffect(() => {
16002
16067
  latest.current = { res, loading, query, params, endpoint, url, base };
16003
16068
  });
16004
- React78.useEffect(() => {
16069
+ React79.useEffect(() => {
16005
16070
  const controller = new AbortController();
16006
16071
  const { signal } = controller;
16007
16072
  setLoading(true);
@@ -16037,7 +16102,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
16037
16102
  };
16038
16103
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
16039
16104
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
16040
- React78.useEffect(() => {
16105
+ React79.useEffect(() => {
16041
16106
  if (!adapter) return;
16042
16107
  return adapter.subscribe((params2) => {
16043
16108
  const { url: u, base: b } = latest.current;
@@ -16387,12 +16452,12 @@ function createVersionStore(initialState, options) {
16387
16452
  }
16388
16453
 
16389
16454
  // src/kits/documentTitle.ts
16390
- var React79 = __toESM(require("react"), 1);
16455
+ var React80 = __toESM(require("react"), 1);
16391
16456
  function formatDocumentTitle(routeTitle, appName) {
16392
- return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
16457
+ return [routeTitle, appName, "Flytedesk"].filter((part2) => !!part2 && part2.length > 0).join(" \xB7 ");
16393
16458
  }
16394
16459
  function useDocumentTitle(routeTitle, appName) {
16395
- React79.useEffect(() => {
16460
+ React80.useEffect(() => {
16396
16461
  if (typeof document === "undefined") return;
16397
16462
  document.title = formatDocumentTitle(routeTitle, appName);
16398
16463
  }, [routeTitle, appName]);
@@ -16503,6 +16568,7 @@ function useDocumentTitle(routeTitle, appName) {
16503
16568
  ModeSwitch,
16504
16569
  ModelControls,
16505
16570
  NumberInput,
16571
+ OVERLAY_BREAKPOINT,
16506
16572
  OVERLAY_CEILING,
16507
16573
  POPOVER_BODY_MIN,
16508
16574
  PacketCard,
@@ -16627,6 +16693,7 @@ function useDocumentTitle(routeTitle, appName) {
16627
16693
  useDocumentTitle,
16628
16694
  useFeatureStatus,
16629
16695
  useLayerZIndex,
16696
+ useOverlayLayout,
16630
16697
  usePopoverPosition,
16631
16698
  useResponsiveRail,
16632
16699
  useRuntimeMode,