@flytedan/flytebot-design-system 0.72.0 → 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.js CHANGED
@@ -940,7 +940,7 @@ function Collapsible({
940
940
  import * as React6 from "react";
941
941
  import { createPortal as createPortal2 } from "react-dom";
942
942
  import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
943
- function Drawer({ open: open2 = true, title, onClose, footer, bare = false, children, className = "", ...rest }) {
943
+ function Drawer({ open: open2 = true, title, label, onClose, footer, bare = false, children, className = "", ...rest }) {
944
944
  const asideRef = React6.useRef(null);
945
945
  const [closing, setClosing] = React6.useState(false);
946
946
  const close2 = React6.useCallback(() => {
@@ -950,13 +950,19 @@ function Drawer({ open: open2 = true, title, onClose, footer, bare = false, chil
950
950
  }, [onClose]);
951
951
  const layer = useStackedLayer({ active: !!open2, containerRef: asideRef, trap: true, onEscape: onClose ? close2 : void 0 });
952
952
  const zIndex = useLayerZIndex(layer);
953
+ const titleId = React6.useId();
954
+ const accessibleName = bare ? label ?? (typeof title === "string" ? title : void 0) : label;
955
+ const unnamed = !!open2 && bare && !accessibleName;
956
+ React6.useEffect(() => {
957
+ 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.");
958
+ }, [unnamed]);
953
959
  if (!open2) return null;
954
960
  return createPortal2(
955
961
  /* @__PURE__ */ jsxs6(StackedLayerProvider, { layer, children: [
956
962
  /* @__PURE__ */ jsx9("div", { className: "fd-scrim" + (closing ? " is-closing" : ""), style: { display: "block", zIndex: zIndex - LAYER_STEP }, onClick: close2 }),
957
- /* @__PURE__ */ jsxs6("aside", { ref: asideRef, className: ["fd-drawer", bare ? "is-bare" : "", closing ? "is-closing" : "", className].filter(Boolean).join(" "), role: "dialog", "aria-modal": "true", "aria-label": bare && typeof title === "string" ? title : void 0, ...rest, style: { zIndex }, children: [
963
+ /* @__PURE__ */ jsxs6("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: [
958
964
  bare ? null : /* @__PURE__ */ jsxs6("div", { className: "fd-card-head", style: { flex: "none" }, children: [
959
- /* @__PURE__ */ jsx9("span", { className: "fd-card-head-title", title: truncationTitle(title), children: title }),
965
+ /* @__PURE__ */ jsx9("span", { id: titleId, className: "fd-card-head-title", title: truncationTitle(title), children: title }),
960
966
  onClose ? /* @__PURE__ */ jsx9("button", { type: "button", className: "fd-btn-icon", "aria-label": "Close", onClick: close2, children: /* @__PURE__ */ jsx9("i", { className: "ph ph-x" }) }) : null
961
967
  ] }),
962
968
  /* @__PURE__ */ jsx9("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 }),
@@ -1529,8 +1535,16 @@ function Topbar({
1529
1535
 
1530
1536
  // src/kits/useResponsiveRail.ts
1531
1537
  import * as React15 from "react";
1538
+
1539
+ // src/kits/overlayLayout.ts
1540
+ var OVERLAY_BREAKPOINT = 1024;
1541
+ function useOverlayLayout() {
1542
+ return useIsNarrow(OVERLAY_BREAKPOINT);
1543
+ }
1544
+
1545
+ // src/kits/useResponsiveRail.ts
1532
1546
  function useResponsiveRail(options = {}) {
1533
- const { breakpoint = 1024, initialOpen = true, onPersist } = options;
1547
+ const { breakpoint = OVERLAY_BREAKPOINT, initialOpen = true, onPersist } = options;
1534
1548
  const navRef = React15.useRef(null);
1535
1549
  const overlay = useIsNarrow(breakpoint);
1536
1550
  const [open2, setOpenRaw] = React15.useState(() => overlay ? false : initialOpen);
@@ -1571,7 +1585,7 @@ function AppShell({
1571
1585
  navFooter,
1572
1586
  initialNavOpen = true,
1573
1587
  onNavOpenChange,
1574
- railBreakpoint = 1024,
1588
+ railBreakpoint = OVERLAY_BREAKPOINT,
1575
1589
  crumbs,
1576
1590
  loading,
1577
1591
  actions,
@@ -3891,7 +3905,7 @@ import { jsx as jsx50, jsxs as jsxs41 } from "react/jsx-runtime";
3891
3905
  var TAIL_CHARS = 12;
3892
3906
  var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
3893
3907
  function splitForMiddleEllipsis(text) {
3894
- const chars = Array.from(graphemes.segment(text), (part) => part.segment);
3908
+ const chars = Array.from(graphemes.segment(text), (part2) => part2.segment);
3895
3909
  if (chars.length <= TAIL_CHARS) return { head: text, tail: "" };
3896
3910
  return { head: chars.slice(0, -TAIL_CHARS).join(""), tail: chars.slice(-TAIL_CHARS).join("") };
3897
3911
  }
@@ -12388,17 +12402,13 @@ function PreferenceMeter({
12388
12402
  }
12389
12403
 
12390
12404
  // src/components/chat/AgentChatPanel.tsx
12391
- import * as React75 from "react";
12405
+ import * as React76 from "react";
12392
12406
 
12393
12407
  // src/components/chat/chatEngine.ts
12408
+ import * as React71 from "react";
12409
+
12410
+ // src/components/chat/chatStore.ts
12394
12411
  import * as React70 from "react";
12395
- var CHAT_UNAVAILABLE = "chat_unavailable";
12396
- var JOB_PENDING = ["queued", "running"];
12397
- var JOB_SUCCESS = ["completed", "recovered"];
12398
- var STORAGE_PREFIX = "fdchat:job:";
12399
- var seq = 0;
12400
- var uid = (p) => p + "_" + ++seq + "_" + Date.now().toString(36);
12401
- var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
12402
12412
  var safeStore = {
12403
12413
  get(k) {
12404
12414
  try {
@@ -12420,6 +12430,38 @@ var safeStore = {
12420
12430
  }
12421
12431
  }
12422
12432
  };
12433
+ var part = (v) => encodeURIComponent(v);
12434
+ var jobKey = (threadId) => "fdchat:job:" + part(threadId);
12435
+ var draftKey = (owner, contextType, contextId) => "fdchat:draft:" + [owner, contextType, contextId].map(part).join(":");
12436
+ function useChatDraft(owner, contextType, contextId, store = safeStore) {
12437
+ if (owner === "") throw new Error("useChatDraft: draftOwner is an empty string; pass the signed-in user's id, or null for no owner.");
12438
+ const key = owner === null ? null : draftKey(owner, contextType, contextId);
12439
+ const read2 = (k) => k ? store.get(k) || "" : "";
12440
+ const [state, setState] = React70.useState(() => ({ key, text: read2(key) }));
12441
+ let current2 = state;
12442
+ if (state.key !== key) {
12443
+ current2 = { key, text: read2(key) };
12444
+ setState(current2);
12445
+ }
12446
+ const setText = React70.useCallback((text) => {
12447
+ if (key) {
12448
+ if (text) {
12449
+ store.set(key, text);
12450
+ if (store.get(key) !== text) store.del(key);
12451
+ } else store.del(key);
12452
+ }
12453
+ setState({ key, text });
12454
+ }, [key, store]);
12455
+ return [current2.text, setText];
12456
+ }
12457
+
12458
+ // src/components/chat/chatEngine.ts
12459
+ var CHAT_UNAVAILABLE = "chat_unavailable";
12460
+ var JOB_PENDING = ["queued", "running"];
12461
+ var JOB_SUCCESS = ["completed", "recovered"];
12462
+ var seq = 0;
12463
+ var uid = (p) => p + "_" + ++seq + "_" + Date.now().toString(36);
12464
+ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
12423
12465
  var isSystemMessage = (m) => !!m && (m.role === "system" || m.metadata != null && m.metadata.type === "system");
12424
12466
  var visibleMessages = (list) => (list || []).filter((m) => !isSystemMessage(m));
12425
12467
  function jobBucket(status) {
@@ -12460,33 +12502,33 @@ function useChatEngine(opts) {
12460
12502
  onClear,
12461
12503
  onFeedback
12462
12504
  } = opts || {};
12463
- const [status, setStatus] = React70.useState("idle");
12464
- const [threadId, setThreadId] = React70.useState(null);
12465
- const [messages, setMessages] = React70.useState([]);
12466
- const [queue, setQueue] = React70.useState([]);
12467
- const [fatal, setFatal] = React70.useState(null);
12468
- const [busy, setBusy] = React70.useState(false);
12469
- const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
12470
- const listRef = React70.useRef([]);
12471
- const queueRef = React70.useRef([]);
12472
- const busyRef = React70.useRef(false);
12473
- const loadedRef = React70.useRef(false);
12474
- const stoppedRef = React70.useRef(false);
12475
- const abortRef = React70.useRef(null);
12476
- const serverCount = React70.useRef(0);
12477
- const serverIds = React70.useRef(/* @__PURE__ */ new Set());
12478
- const liveTurn = React70.useRef(null);
12479
- const lastTurnOwn = React70.useRef(/* @__PURE__ */ new Set());
12480
- const retired = React70.useRef(/* @__PURE__ */ new Set());
12481
- const threadRef = React70.useRef(null);
12482
- const mounted = React70.useRef(true);
12483
- React70.useEffect(() => {
12505
+ const [status, setStatus] = React71.useState("idle");
12506
+ const [threadId, setThreadId] = React71.useState(null);
12507
+ const [messages, setMessages] = React71.useState([]);
12508
+ const [queue, setQueue] = React71.useState([]);
12509
+ const [fatal, setFatal] = React71.useState(null);
12510
+ const [busy, setBusy] = React71.useState(false);
12511
+ const [turnStartedAt, setTurnStartedAt] = React71.useState(null);
12512
+ const listRef = React71.useRef([]);
12513
+ const queueRef = React71.useRef([]);
12514
+ const busyRef = React71.useRef(false);
12515
+ const loadedRef = React71.useRef(false);
12516
+ const stoppedRef = React71.useRef(false);
12517
+ const abortRef = React71.useRef(null);
12518
+ const serverCount = React71.useRef(0);
12519
+ const serverIds = React71.useRef(/* @__PURE__ */ new Set());
12520
+ const liveTurn = React71.useRef(null);
12521
+ const lastTurnOwn = React71.useRef(/* @__PURE__ */ new Set());
12522
+ const retired = React71.useRef(/* @__PURE__ */ new Set());
12523
+ const threadRef = React71.useRef(null);
12524
+ const mounted = React71.useRef(true);
12525
+ React71.useEffect(() => {
12484
12526
  mounted.current = true;
12485
12527
  return () => {
12486
12528
  mounted.current = false;
12487
12529
  };
12488
12530
  }, []);
12489
- const describeWaitingRef = React70.useRef(describeWaiting);
12531
+ const describeWaitingRef = React71.useRef(describeWaiting);
12490
12532
  describeWaitingRef.current = describeWaiting;
12491
12533
  const commit = (next) => {
12492
12534
  const derived = withWaiting(next, (pending) => describeWaitingRef.current(pending));
@@ -12505,7 +12547,7 @@ function useChatEngine(opts) {
12505
12547
  }
12506
12548
  return false;
12507
12549
  };
12508
- const loadThread = React70.useCallback(async (id) => {
12550
+ const loadThread = React71.useCallback(async (id) => {
12509
12551
  const data = await apiAdapter.getThread(id);
12510
12552
  const list = [...data && data.messages || []];
12511
12553
  serverCount.current = list.length;
@@ -12545,7 +12587,7 @@ function useChatEngine(opts) {
12545
12587
  packet: progress.packet ?? holder.packet
12546
12588
  });
12547
12589
  }
12548
- React70.useEffect(() => {
12590
+ React71.useEffect(() => {
12549
12591
  if (!apiAdapter) {
12550
12592
  setStatus("idle");
12551
12593
  setFatal(null);
@@ -12592,7 +12634,7 @@ function useChatEngine(opts) {
12592
12634
  setStatus("ready");
12593
12635
  loadedRef.current = true;
12594
12636
  onThreadReady && onThreadReady(id);
12595
- const stored = store.get(STORAGE_PREFIX + id);
12637
+ const stored = store.get(jobKey(id));
12596
12638
  const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
12597
12639
  if (stored) resumeJob(stored);
12598
12640
  else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
@@ -12611,7 +12653,7 @@ function useChatEngine(opts) {
12611
12653
  };
12612
12654
  }, [apiAdapter, contextType, contextId, threadIdProp]);
12613
12655
  async function pollJob(jobId, placeholderId) {
12614
- store.set(STORAGE_PREFIX + threadRef.current, jobId);
12656
+ store.set(jobKey(threadRef.current), jobId);
12615
12657
  const deadline = Date.now() + pendingTimeoutMs;
12616
12658
  while (true) {
12617
12659
  if (stoppedRef.current) break;
@@ -12659,7 +12701,7 @@ function useChatEngine(opts) {
12659
12701
  }
12660
12702
  }
12661
12703
  async function finishJob(_jobId, _job) {
12662
- store.del(STORAGE_PREFIX + threadRef.current);
12704
+ store.del(jobKey(threadRef.current));
12663
12705
  try {
12664
12706
  const list = await loadThread(threadRef.current);
12665
12707
  const withPacket = [...list].reverse().find((m) => m && m.packet);
@@ -12669,7 +12711,7 @@ function useChatEngine(opts) {
12669
12711
  }
12670
12712
  }
12671
12713
  function recordFailure(placeholderId, code, retryable, job) {
12672
- store.del(STORAGE_PREFIX + threadRef.current);
12714
+ store.del(jobKey(threadRef.current));
12673
12715
  if (!listRef.current.some((m) => m.id === placeholderId)) {
12674
12716
  push({ id: placeholderId, role: "assistant", text: null });
12675
12717
  }
@@ -12777,7 +12819,7 @@ function useChatEngine(opts) {
12777
12819
  await dispatchTurn(turn);
12778
12820
  }
12779
12821
  }
12780
- const send = React70.useCallback((text, attachments) => {
12822
+ const send = React71.useCallback((text, attachments) => {
12781
12823
  const body = (text || "").trim();
12782
12824
  if (!body && !(attachments && attachments.length)) return;
12783
12825
  if (status === "disconnected") return;
@@ -12787,7 +12829,7 @@ function useChatEngine(opts) {
12787
12829
  stoppedRef.current = false;
12788
12830
  drain();
12789
12831
  }, [status]);
12790
- const stop = React70.useCallback(() => {
12832
+ const stop = React71.useCallback(() => {
12791
12833
  stoppedRef.current = true;
12792
12834
  const ac = abortRef.current;
12793
12835
  if (ac) {
@@ -12803,14 +12845,14 @@ function useChatEngine(opts) {
12803
12845
  Promise.resolve(apiAdapter.cancelJob(holder.jobId)).catch(() => {
12804
12846
  });
12805
12847
  }
12806
- store.del(STORAGE_PREFIX + threadRef.current);
12848
+ store.del(jobKey(threadRef.current));
12807
12849
  }
12808
12850
  }, [apiAdapter]);
12809
- const removeQueued = React70.useCallback((id) => {
12851
+ const removeQueued = React71.useCallback((id) => {
12810
12852
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12811
12853
  setQueue(queueRef.current.slice());
12812
12854
  }, []);
12813
- const retry = React70.useCallback(() => {
12855
+ const retry = React71.useCallback(() => {
12814
12856
  const list = listRef.current;
12815
12857
  let at = -1;
12816
12858
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12827,19 +12869,19 @@ function useChatEngine(opts) {
12827
12869
  setQueue(queueRef.current.slice());
12828
12870
  drain();
12829
12871
  }, []);
12830
- const clear = React70.useCallback(() => {
12872
+ const clear = React71.useCallback(() => {
12831
12873
  commit([]);
12832
12874
  serverCount.current = 0;
12833
12875
  queueRef.current = [];
12834
12876
  setQueue([]);
12835
12877
  onClear && onClear();
12836
12878
  }, [onClear]);
12837
- const setFeedback = React70.useCallback((id, value) => {
12879
+ const setFeedback = React71.useCallback((id, value) => {
12838
12880
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12839
12881
  const msg = listRef.current.find((m) => m.id === id);
12840
12882
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12841
12883
  }, [onFeedback]);
12842
- const reload = React70.useCallback(async () => {
12884
+ const reload = React71.useCallback(async () => {
12843
12885
  if (!threadRef.current) return;
12844
12886
  setStatus("loading");
12845
12887
  try {
@@ -12877,10 +12919,10 @@ var ChatKit = {
12877
12919
  };
12878
12920
 
12879
12921
  // src/components/chat/ChatTranscript.tsx
12880
- import * as React72 from "react";
12922
+ import * as React73 from "react";
12881
12923
 
12882
12924
  // src/components/chat/ChatTurn.tsx
12883
- import * as React71 from "react";
12925
+ import * as React72 from "react";
12884
12926
  import { jsx as jsx101, jsxs as jsxs88 } from "react/jsx-runtime";
12885
12927
  function JsonView({ value }) {
12886
12928
  let text;
@@ -12917,7 +12959,7 @@ function PacketCard({ packet, schema, render, onApply, applied }) {
12917
12959
  ] });
12918
12960
  }
12919
12961
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12920
- const [open2, setOpen] = React71.useState(defaultOpen);
12962
+ const [open2, setOpen] = React72.useState(defaultOpen);
12921
12963
  if (!text) return null;
12922
12964
  return /* @__PURE__ */ jsxs88("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12923
12965
  /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -12934,7 +12976,7 @@ function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12934
12976
  ] });
12935
12977
  }
12936
12978
  function Citations({ items = [], onOpen }) {
12937
- const [open2, setOpen] = React71.useState(false);
12979
+ const [open2, setOpen] = React72.useState(false);
12938
12980
  if (!items.length) return null;
12939
12981
  return /* @__PURE__ */ jsxs88("div", { className: "fdc-cites", children: [
12940
12982
  /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
@@ -12960,7 +13002,7 @@ function clampText(text, max) {
12960
13002
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
12961
13003
  }
12962
13004
  function MessageBody({ message: m, ctx }) {
12963
- const [expanded, setExpanded] = React71.useState(false);
13005
+ const [expanded, setExpanded] = React72.useState(false);
12964
13006
  const isUser = m.role === "user";
12965
13007
  const raw = m.text || "";
12966
13008
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
@@ -13039,7 +13081,7 @@ function RunActions({ group, ctx }) {
13039
13081
  ] }),
13040
13082
  isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx101("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
13041
13083
  group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx101("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
13042
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs88(React71.Fragment, { children: [
13084
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs88(React72.Fragment, { children: [
13043
13085
  /* @__PURE__ */ jsx101("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__ */ jsx101("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
13044
13086
  /* @__PURE__ */ jsx101("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__ */ jsx101("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
13045
13087
  ] }) : null,
@@ -13134,10 +13176,10 @@ function ChatTranscript({
13134
13176
  renderEmpty,
13135
13177
  className = ""
13136
13178
  }) {
13137
- const scroller = React72.useRef(null);
13138
- const stick = React72.useRef(true);
13139
- const [pill, setPill] = React72.useState(0);
13140
- const seen = React72.useRef(0);
13179
+ const scroller = React73.useRef(null);
13180
+ const stick = React73.useRef(true);
13181
+ const [pill, setPill] = React73.useState(0);
13182
+ const seen = React73.useRef(0);
13141
13183
  const toBottom = (smooth) => {
13142
13184
  const el = scroller.current;
13143
13185
  if (!el) return;
@@ -13156,7 +13198,7 @@ function ChatTranscript({
13156
13198
  seen.current = messages.length;
13157
13199
  }
13158
13200
  };
13159
- React72.useLayoutEffect(() => {
13201
+ React73.useLayoutEffect(() => {
13160
13202
  const el = scroller.current;
13161
13203
  if (!el) return;
13162
13204
  if (stick.current) {
@@ -13164,7 +13206,7 @@ function ChatTranscript({
13164
13206
  seen.current = messages.length;
13165
13207
  } else setPill(Math.max(0, messages.length - seen.current));
13166
13208
  }, [messages]);
13167
- React72.useEffect(() => {
13209
+ React73.useEffect(() => {
13168
13210
  const el = scroller.current;
13169
13211
  const inner = el && el.firstChild;
13170
13212
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -13174,7 +13216,7 @@ function ChatTranscript({
13174
13216
  ro.observe(inner);
13175
13217
  return () => ro.disconnect();
13176
13218
  }, []);
13177
- const groups = React72.useMemo(() => groupMessages(messages), [messages]);
13219
+ const groups = React73.useMemo(() => groupMessages(messages), [messages]);
13178
13220
  const empty = !messages.length && status === "ready";
13179
13221
  return /* @__PURE__ */ jsxs89("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
13180
13222
  /* @__PURE__ */ jsxs89("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
@@ -13198,7 +13240,7 @@ function ChatTranscript({
13198
13240
  const prev = groups[i - 1];
13199
13241
  const k = dayKey(g.messages[0].timestamp);
13200
13242
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
13201
- return /* @__PURE__ */ jsxs89(React72.Fragment, { children: [
13243
+ return /* @__PURE__ */ jsxs89(React73.Fragment, { children: [
13202
13244
  showDay ? /* @__PURE__ */ jsx102("div", { className: "fdc-day", children: /* @__PURE__ */ jsx102("span", { children: dayLabel(k) }) }) : null,
13203
13245
  /* @__PURE__ */ jsx102(ChatTurn, { group: g, ctx })
13204
13246
  ] }, g.key || i);
@@ -13215,7 +13257,7 @@ function ChatTranscript({
13215
13257
  var TranscriptKit = { groupMessages };
13216
13258
 
13217
13259
  // src/components/chat/ChatComposer.tsx
13218
- import * as React73 from "react";
13260
+ import * as React74 from "react";
13219
13261
  import { jsx as jsx103, jsxs as jsxs90 } from "react/jsx-runtime";
13220
13262
  function ChatComposer({
13221
13263
  onSubmit,
@@ -13243,17 +13285,17 @@ function ChatComposer({
13243
13285
  onReject,
13244
13286
  onOpenAttachment
13245
13287
  }) {
13246
- const [text, setText] = React73.useState(draft || "");
13247
- const [trigger, setTrigger] = React73.useState(null);
13248
- const [mentionItems, setMentionItems] = React73.useState([]);
13249
- const [listening, setListening] = React73.useState(false);
13250
- const [notice, setNotice] = React73.useState(null);
13251
- const editor = React73.useRef(null);
13252
- const wrap = React73.useRef(null);
13253
- const stopVoice = React73.useRef(null);
13288
+ const [text, setText] = React74.useState(draft || "");
13289
+ const [trigger, setTrigger] = React74.useState(null);
13290
+ const [mentionItems, setMentionItems] = React74.useState([]);
13291
+ const [listening, setListening] = React74.useState(false);
13292
+ const [notice, setNotice] = React74.useState(null);
13293
+ const editor = React74.useRef(null);
13294
+ const wrap = React74.useRef(null);
13295
+ const stopVoice = React74.useRef(null);
13254
13296
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
13255
13297
  } });
13256
- React73.useEffect(() => {
13298
+ React74.useEffect(() => {
13257
13299
  if (draft != null && draft !== text) setText(draft);
13258
13300
  }, [draft]);
13259
13301
  const change = (v) => {
@@ -13289,7 +13331,7 @@ function ChatComposer({
13289
13331
  e.preventDefault();
13290
13332
  staged.add(found.files);
13291
13333
  };
13292
- React73.useEffect(() => {
13334
+ React74.useEffect(() => {
13293
13335
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
13294
13336
  setMentionItems([]);
13295
13337
  return;
@@ -13307,7 +13349,7 @@ function ChatComposer({
13307
13349
  const q = (trigger.query || "").toLowerCase();
13308
13350
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
13309
13351
  }, [trigger, mentionSources]);
13310
- const slashItems = React73.useMemo(() => {
13352
+ const slashItems = React74.useMemo(() => {
13311
13353
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
13312
13354
  const q = (trigger.query || "").toLowerCase();
13313
13355
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -13477,12 +13519,12 @@ function ChatComposer({
13477
13519
  }
13478
13520
 
13479
13521
  // src/components/chat/ChatSessionBar.tsx
13480
- import * as React74 from "react";
13522
+ import * as React75 from "react";
13481
13523
  import { jsx as jsx104, jsxs as jsxs91 } from "react/jsx-runtime";
13482
13524
  var compact2 = meterFormats.compact;
13483
13525
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
13484
- const [open2, setOpen] = React74.useState(false);
13485
- const anchor = React74.useRef(null);
13526
+ const [open2, setOpen] = React75.useState(false);
13527
+ const anchor = React75.useRef(null);
13486
13528
  const stats = sessionStats || null;
13487
13529
  const cu = contextUsage || null;
13488
13530
  const limits = usageLimits || null;
@@ -13497,7 +13539,7 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13497
13539
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
13498
13540
  if (cu) bits.push(pct + "% context");
13499
13541
  const expandable = !!(cu || limits);
13500
- return /* @__PURE__ */ jsxs91(React74.Fragment, { children: [
13542
+ return /* @__PURE__ */ jsxs91(React75.Fragment, { children: [
13501
13543
  /* @__PURE__ */ jsxs91("div", { className: "fdc-bar", children: [
13502
13544
  /* @__PURE__ */ jsxs91(
13503
13545
  "button",
@@ -13638,7 +13680,7 @@ function ModelControls({
13638
13680
  ] })
13639
13681
  });
13640
13682
  }
13641
- return /* @__PURE__ */ jsxs91(React74.Fragment, { children: [
13683
+ return /* @__PURE__ */ jsxs91(React75.Fragment, { children: [
13642
13684
  /* @__PURE__ */ jsx104(
13643
13685
  MenuButton,
13644
13686
  {
@@ -13677,6 +13719,7 @@ function AgentChatPanel({
13677
13719
  /* required */
13678
13720
  contextType,
13679
13721
  contextId,
13722
+ draftOwner,
13680
13723
  apiAdapter,
13681
13724
  threadId,
13682
13725
  /* identity + chrome */
@@ -13757,11 +13800,11 @@ function AgentChatPanel({
13757
13800
  onFeedback,
13758
13801
  onEditMessage
13759
13802
  }) {
13760
- const [panelWidth, setPanelWidth] = React75.useState(width);
13761
- const [applied, setApplied] = React75.useState({});
13762
- const [draft, setDraft] = React75.useState("");
13763
- const dragging = React75.useRef(null);
13764
- React75.useEffect(() => setPanelWidth(width), [width]);
13803
+ const [panelWidth, setPanelWidth] = React76.useState(width);
13804
+ const [applied, setApplied] = React76.useState({});
13805
+ const [draft, setDraft] = useChatDraft(draftOwner, contextType, contextId);
13806
+ const dragging = React76.useRef(null);
13807
+ React76.useEffect(() => setPanelWidth(width), [width]);
13765
13808
  const engine = useChatEngine({
13766
13809
  contextType,
13767
13810
  contextId,
@@ -13967,7 +14010,7 @@ function AgentChatPanel({
13967
14010
  }
13968
14011
 
13969
14012
  // src/components/files/FileViewer.tsx
13970
- import * as React76 from "react";
14013
+ import * as React77 from "react";
13971
14014
  import { jsx as jsx106, jsxs as jsxs93 } from "react/jsx-runtime";
13972
14015
  function previewKindOf(file) {
13973
14016
  const mime = (file.mime || "").toLowerCase();
@@ -14024,13 +14067,13 @@ function parseDelimited(text, delimiter) {
14024
14067
  return rows;
14025
14068
  }
14026
14069
  function usePreview(file, kind, resolveUrl) {
14027
- const [state, setState] = React76.useState({ status: "loading" });
14028
- const [attempt, setAttempt] = React76.useState(0);
14029
- const resolveRef = React76.useRef(resolveUrl);
14030
- React76.useEffect(() => {
14070
+ const [state, setState] = React77.useState({ status: "loading" });
14071
+ const [attempt, setAttempt] = React77.useState(0);
14072
+ const resolveRef = React77.useRef(resolveUrl);
14073
+ React77.useEffect(() => {
14031
14074
  resolveRef.current = resolveUrl;
14032
14075
  }, [resolveUrl]);
14033
- React76.useEffect(() => {
14076
+ React77.useEffect(() => {
14034
14077
  if (kind === "none") {
14035
14078
  setState({ status: "ready" });
14036
14079
  return;
@@ -14060,7 +14103,7 @@ function usePreview(file, kind, resolveUrl) {
14060
14103
  if (ac) ac.abort();
14061
14104
  };
14062
14105
  }, [file.id, kind, attempt]);
14063
- return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
14106
+ return { ...state, retry: React77.useCallback(() => setAttempt((a) => a + 1), []) };
14064
14107
  }
14065
14108
  function PreviewBody({ file, kind, state }) {
14066
14109
  if (kind === "image") return /* @__PURE__ */ jsx106("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
@@ -14105,13 +14148,13 @@ function PreviewBody({ file, kind, state }) {
14105
14148
  ] });
14106
14149
  }
14107
14150
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
14108
- const kind = React76.useMemo(() => previewKindOf(file), [file]);
14151
+ const kind = React77.useMemo(() => previewKindOf(file), [file]);
14109
14152
  const preview = usePreview(file, kind, resolveUrl);
14110
- const [tab, setTab] = React76.useState("preview");
14111
- const [downloading, setDownloading] = React76.useState(false);
14112
- const [downloadError, setDownloadError] = React76.useState(null);
14153
+ const [tab, setTab] = React77.useState("preview");
14154
+ const [downloading, setDownloading] = React77.useState(false);
14155
+ const [downloadError, setDownloadError] = React77.useState(null);
14113
14156
  const hasSide = sidePanel != null;
14114
- React76.useEffect(() => {
14157
+ React77.useEffect(() => {
14115
14158
  setTab("preview");
14116
14159
  }, [file.id]);
14117
14160
  const download = () => {
@@ -14178,7 +14221,7 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
14178
14221
  }
14179
14222
 
14180
14223
  // src/components/files/FileBrowser.tsx
14181
- import * as React77 from "react";
14224
+ import * as React78 from "react";
14182
14225
  import { Fragment as Fragment31, jsx as jsx107, jsxs as jsxs94 } from "react/jsx-runtime";
14183
14226
  function childrenOf(folders, parentId) {
14184
14227
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
@@ -14288,8 +14331,8 @@ function FolderPickerMenu({
14288
14331
  ] });
14289
14332
  }
14290
14333
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
14291
- const [over, setOver] = React77.useState(false);
14292
- const dragCounter = React77.useRef(0);
14334
+ const [over, setOver] = React78.useState(false);
14335
+ const dragCounter = React78.useRef(0);
14293
14336
  const dropHandlers = isDropTarget ? {
14294
14337
  onDragEnter: (e) => {
14295
14338
  if (!hasInternalPayload(e)) return;
@@ -14337,8 +14380,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
14337
14380
  }
14338
14381
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
14339
14382
  const kids = childrenOf(folders, folder.id);
14340
- const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14341
- React77.useEffect(() => {
14383
+ const [expanded, setExpanded] = React78.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14384
+ React78.useEffect(() => {
14342
14385
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
14343
14386
  }, [currentFolderId, folder.id, folders]);
14344
14387
  const isCurrent = folder.id === currentFolderId;
@@ -14404,15 +14447,15 @@ function FileBrowser({
14404
14447
  const canUpload = perm.canUpload !== false && !!onUpload;
14405
14448
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
14406
14449
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
14407
- const [createOpen, setCreateOpen] = React77.useState(false);
14408
- const [createName, setCreateName] = React77.useState("");
14409
- const [renameTarget, setRenameTarget] = React77.useState(null);
14410
- const [renameValue, setRenameValue] = React77.useState("");
14411
- const [deleteTarget, setDeleteTarget] = React77.useState(null);
14412
- const uploadInputRef = React77.useRef(null);
14413
- const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14414
- const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14415
- const currentFiles = React77.useMemo(
14450
+ const [createOpen, setCreateOpen] = React78.useState(false);
14451
+ const [createName, setCreateName] = React78.useState("");
14452
+ const [renameTarget, setRenameTarget] = React78.useState(null);
14453
+ const [renameValue, setRenameValue] = React78.useState("");
14454
+ const [deleteTarget, setDeleteTarget] = React78.useState(null);
14455
+ const uploadInputRef = React78.useRef(null);
14456
+ const crumbFolders = React78.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14457
+ const subfolders = React78.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14458
+ const currentFiles = React78.useMemo(
14416
14459
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
14417
14460
  [files, currentFolderId]
14418
14461
  );
@@ -14644,8 +14687,8 @@ function BreadcrumbCrumb({
14644
14687
  isDropTarget,
14645
14688
  onDropPayload
14646
14689
  }) {
14647
- const [over, setOver] = React77.useState(false);
14648
- const dragCounter = React77.useRef(0);
14690
+ const [over, setOver] = React78.useState(false);
14691
+ const dragCounter = React78.useRef(0);
14649
14692
  const dropHandlers = isDropTarget ? {
14650
14693
  onDragEnter: (e) => {
14651
14694
  if (!hasInternalPayload(e)) return;
@@ -14674,7 +14717,7 @@ function BreadcrumbCrumb({
14674
14717
  }
14675
14718
 
14676
14719
  // src/kits/query.ts
14677
- import * as React78 from "react";
14720
+ import * as React79 from "react";
14678
14721
 
14679
14722
  // src/kits/queryUrl.ts
14680
14723
  var historyUrlAdapter = {
@@ -14812,38 +14855,38 @@ function requestFor(params, query, paging, after) {
14812
14855
  }
14813
14856
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
14814
14857
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
14815
- const [base] = React78.useState(() => {
14858
+ const [base] = React79.useState(() => {
14816
14859
  const store = PREFS || window.PlannerPrefs;
14817
14860
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
14818
14861
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
14819
14862
  });
14820
- const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14821
- const address = React78.useRef(mountParams);
14822
- const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14823
- const savePref = React78.useCallback((patch2) => {
14863
+ const [mountParams] = React79.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14864
+ const address = React79.useRef(mountParams);
14865
+ const [query, setQuery] = React79.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14866
+ const savePref = React79.useCallback((patch2) => {
14824
14867
  const store = PREFS || window.PlannerPrefs;
14825
14868
  if (prefsKey && store) store.setTable(prefsKey, patch2);
14826
14869
  }, [prefsKey]);
14827
- const [res, setRes] = React78.useState(null);
14828
- const [loading, setLoading] = React78.useState(true);
14829
- const [loadingMore, setLoadingMore] = React78.useState(false);
14830
- const [failure, setFailure] = React78.useState(null);
14831
- const [reloadToken, setReloadToken] = React78.useState(0);
14832
- const moreController = React78.useRef(null);
14870
+ const [res, setRes] = React79.useState(null);
14871
+ const [loading, setLoading] = React79.useState(true);
14872
+ const [loadingMore, setLoadingMore] = React79.useState(false);
14873
+ const [failure, setFailure] = React79.useState(null);
14874
+ const [reloadToken, setReloadToken] = React79.useState(0);
14875
+ const moreController = React79.useRef(null);
14833
14876
  const depKey = (deps || []).join("|");
14834
14877
  const paramKey = JSON.stringify(params || {});
14835
14878
  const queryKey = JSON.stringify(query);
14836
- const lifetime = React78.useRef(null);
14837
- React78.useEffect(() => {
14879
+ const lifetime = React79.useRef(null);
14880
+ React79.useEffect(() => {
14838
14881
  const controller = new AbortController();
14839
14882
  lifetime.current = controller;
14840
14883
  return () => controller.abort();
14841
14884
  }, []);
14842
- const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
14843
- React78.useLayoutEffect(() => {
14885
+ const latest = React79.useRef({ res, loading, query, params, endpoint, url, base });
14886
+ React79.useLayoutEffect(() => {
14844
14887
  latest.current = { res, loading, query, params, endpoint, url, base };
14845
14888
  });
14846
- React78.useEffect(() => {
14889
+ React79.useEffect(() => {
14847
14890
  const controller = new AbortController();
14848
14891
  const { signal } = controller;
14849
14892
  setLoading(true);
@@ -14879,7 +14922,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
14879
14922
  };
14880
14923
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
14881
14924
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
14882
- React78.useEffect(() => {
14925
+ React79.useEffect(() => {
14883
14926
  if (!adapter) return;
14884
14927
  return adapter.subscribe((params2) => {
14885
14928
  const { url: u, base: b } = latest.current;
@@ -15229,12 +15272,12 @@ function createVersionStore(initialState, options) {
15229
15272
  }
15230
15273
 
15231
15274
  // src/kits/documentTitle.ts
15232
- import * as React79 from "react";
15275
+ import * as React80 from "react";
15233
15276
  function formatDocumentTitle(routeTitle, appName) {
15234
- return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
15277
+ return [routeTitle, appName, "Flytedesk"].filter((part2) => !!part2 && part2.length > 0).join(" \xB7 ");
15235
15278
  }
15236
15279
  function useDocumentTitle(routeTitle, appName) {
15237
- React79.useEffect(() => {
15280
+ React80.useEffect(() => {
15238
15281
  if (typeof document === "undefined") return;
15239
15282
  document.title = formatDocumentTitle(routeTitle, appName);
15240
15283
  }, [routeTitle, appName]);
@@ -15344,6 +15387,7 @@ export {
15344
15387
  ModeSwitch,
15345
15388
  ModelControls,
15346
15389
  NumberInput,
15390
+ OVERLAY_BREAKPOINT,
15347
15391
  OVERLAY_CEILING,
15348
15392
  POPOVER_BODY_MIN,
15349
15393
  PacketCard,
@@ -15468,6 +15512,7 @@ export {
15468
15512
  useDocumentTitle,
15469
15513
  useFeatureStatus,
15470
15514
  useLayerZIndex,
15515
+ useOverlayLayout,
15471
15516
  usePopoverPosition,
15472
15517
  useResponsiveRail,
15473
15518
  useRuntimeMode,