@flytedan/flytebot-design-system 0.67.4 → 0.70.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
@@ -1,3 +1,8 @@
1
+ import {
2
+ hideEscapes,
3
+ showEscapes,
4
+ showEscapesRaw
5
+ } from "./chunk-OVTWSE43.js";
1
6
  import {
2
7
  US_STATES,
3
8
  US_STATE_CODES,
@@ -3047,6 +3052,24 @@ function CsiHero({ band = "weak", crp, label, className = "" }) {
3047
3052
  // src/components/data/DataTable.tsx
3048
3053
  import { Fragment as Fragment7, jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
3049
3054
  var STACK_MAX_WIDTH = 640;
3055
+ function RowActionButton({ action, size }) {
3056
+ return /* @__PURE__ */ jsx44(
3057
+ IconButton,
3058
+ {
3059
+ icon: action.icon,
3060
+ label: action.label,
3061
+ size,
3062
+ disabled: action.disabled,
3063
+ onClick: (e) => {
3064
+ e.stopPropagation();
3065
+ action.onClick();
3066
+ }
3067
+ }
3068
+ );
3069
+ }
3070
+ function RowActionCell({ action }) {
3071
+ return /* @__PURE__ */ jsx44("td", { className: "fd-table-action", children: action ? /* @__PURE__ */ jsx44(RowActionButton, { action, size: "sm" }) : null });
3072
+ }
3050
3073
  var cellOf = (c, row) => c.render ? c.render(row) : row[c.key];
3051
3074
  function rowInteraction(row, onRowClick) {
3052
3075
  if (!onRowClick) return {};
@@ -3074,6 +3097,7 @@ function DataTable({
3074
3097
  selectedIds,
3075
3098
  rowTitle,
3076
3099
  onRowClick,
3100
+ rowAction,
3077
3101
  rowKey = "id",
3078
3102
  loading = false,
3079
3103
  refreshing = false,
@@ -3110,27 +3134,37 @@ function DataTable({
3110
3134
  onSort,
3111
3135
  rowTitle,
3112
3136
  onRowClick,
3137
+ rowAction,
3113
3138
  isSelected
3114
3139
  }
3115
3140
  ) : /* @__PURE__ */ jsxs35("table", { className: ["fd-table", compact3 ? "fd-table-compact" : ""].filter(Boolean).join(" "), children: [
3116
- /* @__PURE__ */ jsx44("thead", { children: /* @__PURE__ */ jsx44("tr", { children: columns.map((c) => /* @__PURE__ */ jsx44(
3117
- "th",
3118
- {
3119
- scope: "col",
3120
- style: { width: c.width },
3121
- className: [c.numeric ? "is-num" : "", sort && sort.key === c.key ? "is-sorted" : ""].filter(Boolean).join(" "),
3122
- "aria-sort": sort && sort.key === c.key ? sort.dir === "asc" ? "ascending" : "descending" : void 0,
3123
- children: c.sortable && onSort ? /* @__PURE__ */ jsx44(SortButton, { column: c, sort, onSort }) : c.label
3124
- },
3125
- c.key
3126
- )) }) }),
3127
- /* @__PURE__ */ jsx44("tbody", { className: stale ? "fd-stale" : void 0, children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsx44("tr", { children: columns.map((c) => /* @__PURE__ */ jsx44("td", { className: c.numeric ? "is-num" : "", children: /* @__PURE__ */ jsx44("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 13, width: c.numeric ? 52 : i % 3 === 0 ? "72%" : "88%" } }) }, c.key)) }, i)) : rows.map((r) => /* @__PURE__ */ jsx44(
3141
+ /* @__PURE__ */ jsx44("thead", { children: /* @__PURE__ */ jsxs35("tr", { children: [
3142
+ columns.map((c) => /* @__PURE__ */ jsx44(
3143
+ "th",
3144
+ {
3145
+ scope: "col",
3146
+ style: { width: c.width },
3147
+ className: [c.numeric ? "is-num" : "", sort && sort.key === c.key ? "is-sorted" : ""].filter(Boolean).join(" "),
3148
+ "aria-sort": sort && sort.key === c.key ? sort.dir === "asc" ? "ascending" : "descending" : void 0,
3149
+ children: c.sortable && onSort ? /* @__PURE__ */ jsx44(SortButton, { column: c, sort, onSort }) : c.label
3150
+ },
3151
+ c.key
3152
+ )),
3153
+ rowAction ? /* @__PURE__ */ jsx44("th", { scope: "col", className: "fd-table-action-head", children: /* @__PURE__ */ jsx44("span", { className: "fd-sr-only", children: "Actions" }) }) : null
3154
+ ] }) }),
3155
+ /* @__PURE__ */ jsx44("tbody", { className: stale ? "fd-stale" : void 0, children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsxs35("tr", { children: [
3156
+ columns.map((c) => /* @__PURE__ */ jsx44("td", { className: c.numeric ? "is-num" : "", children: /* @__PURE__ */ jsx44("span", { className: "fd-skel fd-skel-text", style: { display: "inline-block", height: 13, width: c.numeric ? 52 : i % 3 === 0 ? "72%" : "88%" } }) }, c.key)),
3157
+ rowAction ? /* @__PURE__ */ jsx44("td", { className: "fd-table-action" }) : null
3158
+ ] }, i)) : rows.map((r) => /* @__PURE__ */ jsxs35(
3128
3159
  "tr",
3129
3160
  {
3130
3161
  "aria-selected": isSelected(r) ? "true" : void 0,
3131
3162
  title: rowTitle ? rowTitle(r) : void 0,
3132
3163
  ...rowInteraction(r, onRowClick),
3133
- children: columns.map((c) => /* @__PURE__ */ jsx44("td", { className: c.numeric ? "is-num" : "", children: cellOf(c, r) }, c.key))
3164
+ children: [
3165
+ columns.map((c) => /* @__PURE__ */ jsx44("td", { className: c.numeric ? "is-num" : "", children: cellOf(c, r) }, c.key)),
3166
+ rowAction ? /* @__PURE__ */ jsx44(RowActionCell, { action: rowAction(r) }) : null
3167
+ ]
3134
3168
  },
3135
3169
  r[rowKey]
3136
3170
  )) })
@@ -3143,7 +3177,7 @@ function DataTable({
3143
3177
  ] }) }) : null
3144
3178
  ] });
3145
3179
  }
3146
- function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort, onSort, rowTitle, onRowClick, isSelected }) {
3180
+ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort, onSort, rowTitle, onRowClick, rowAction, isSelected }) {
3147
3181
  const sortable = onSort ? columns.filter((c) => c.sortable) : [];
3148
3182
  const primary = columns.filter((c) => c.phone === "primary");
3149
3183
  const secondary = columns.filter((c) => c.phone === "secondary");
@@ -3162,31 +3196,34 @@ function StackedRows({ columns, rows, rowKey, loading, stale, skeletonRows, sort
3162
3196
  c.key
3163
3197
  );
3164
3198
  }) }) : null,
3165
- /* @__PURE__ */ jsx44("div", { className: stale ? "fd-dt-cards fd-stale" : "fd-dt-cards", children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsxs35("div", { className: "fd-dt-card", children: [
3199
+ /* @__PURE__ */ jsx44("div", { className: stale ? "fd-dt-cards fd-stale" : "fd-dt-cards", children: loading ? Array.from({ length: skeletonRows }).map((_, i) => /* @__PURE__ */ jsx44("div", { className: "fd-dt-item", children: /* @__PURE__ */ jsxs35("div", { className: "fd-dt-card", children: [
3166
3200
  /* @__PURE__ */ jsx44("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: 14, width: i % 3 === 0 ? "55%" : "70%" } }),
3167
3201
  secondary.length ? /* @__PURE__ */ jsx44("span", { className: "fd-skel fd-skel-text", style: { display: "block", height: 12, width: "40%" } }) : null
3168
- ] }, i)) : rows.map((r) => {
3202
+ ] }) }, i)) : rows.map((r) => {
3169
3203
  const selected = isSelected(r);
3204
+ const action = rowAction ? rowAction(r) : null;
3170
3205
  const semantics = onRowClick ? { role: "button", "aria-pressed": selected } : { "aria-current": selected ? "true" : void 0 };
3171
- return /* @__PURE__ */ jsxs35(
3172
- "div",
3173
- {
3174
- className: "fd-dt-card",
3175
- title: rowTitle ? rowTitle(r) : void 0,
3176
- "data-selected": selected ? "true" : void 0,
3177
- ...semantics,
3178
- ...rowInteraction(r, onRowClick),
3179
- children: [
3180
- /* @__PURE__ */ jsx44("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ jsx44("span", { className: c.numeric ? "is-num" : void 0, children: cellOf(c, r) }, c.key)) }),
3181
- secondary.length ? /* @__PURE__ */ jsx44("div", { className: "fd-dt-card-meta", children: secondary.map((c) => /* @__PURE__ */ jsxs35("span", { className: c.numeric ? "is-num" : void 0, children: [
3182
- /* @__PURE__ */ jsx44("span", { className: "fd-dt-card-label", children: c.label }),
3183
- " ",
3184
- cellOf(c, r)
3185
- ] }, c.key)) }) : null
3186
- ]
3187
- },
3188
- r[rowKey]
3189
- );
3206
+ return /* @__PURE__ */ jsxs35("div", { className: "fd-dt-item", children: [
3207
+ /* @__PURE__ */ jsxs35(
3208
+ "div",
3209
+ {
3210
+ className: "fd-dt-card",
3211
+ title: rowTitle ? rowTitle(r) : void 0,
3212
+ "data-selected": selected ? "true" : void 0,
3213
+ ...semantics,
3214
+ ...rowInteraction(r, onRowClick),
3215
+ children: [
3216
+ /* @__PURE__ */ jsx44("div", { className: "fd-dt-card-title", children: primary.map((c) => /* @__PURE__ */ jsx44("span", { className: c.numeric ? "is-num" : void 0, children: cellOf(c, r) }, c.key)) }),
3217
+ secondary.length ? /* @__PURE__ */ jsx44("div", { className: "fd-dt-card-meta", children: secondary.map((c) => /* @__PURE__ */ jsxs35("span", { className: c.numeric ? "is-num" : void 0, children: [
3218
+ /* @__PURE__ */ jsx44("span", { className: "fd-dt-card-label", children: c.label }),
3219
+ " ",
3220
+ cellOf(c, r)
3221
+ ] }, c.key)) }) : null
3222
+ ]
3223
+ }
3224
+ ),
3225
+ action ? /* @__PURE__ */ jsx44("div", { className: "fd-dt-action", children: /* @__PURE__ */ jsx44(RowActionButton, { action, size: "md" }) }) : null
3226
+ ] }, r[rowKey]);
3190
3227
  }) })
3191
3228
  ] });
3192
3229
  }
@@ -5192,7 +5229,8 @@ var INLINE = [
5192
5229
  ];
5193
5230
  function inlineNodes(src, ctx, keyBase) {
5194
5231
  const out = [];
5195
- let rest = String(src == null ? "" : src), guard = 0;
5232
+ let rest = hideEscapes(String(src == null ? "" : src)), guard = 0;
5233
+ const d = showEscapes;
5196
5234
  const key = () => keyBase + "-" + out.length;
5197
5235
  while (rest && guard++ < 800) {
5198
5236
  let best = null;
@@ -5203,28 +5241,28 @@ function inlineNodes(src, ctx, keyBase) {
5203
5241
  }
5204
5242
  if (!best) break;
5205
5243
  const { kind, m } = best;
5206
- if (m.index > 0) out.push(rest.slice(0, m.index));
5244
+ if (m.index > 0) out.push(d(rest.slice(0, m.index)));
5207
5245
  const g = (i) => m[i];
5208
- if (kind === "code") out.push(/* @__PURE__ */ jsx54("code", { className: "fd-md-code", children: g(1) }, key()));
5246
+ if (kind === "code") out.push(/* @__PURE__ */ jsx54("code", { className: "fd-md-code", children: showEscapesRaw(g(1)) }, key()));
5209
5247
  else if (kind === "image") {
5210
- const src2 = safeHref(g(2));
5211
- out.push(ctx.allowImages && src2 ? /* @__PURE__ */ jsx54("img", { className: "fd-md-img", src: src2, alt: g(1) || "", title: g(3) || void 0, loading: "lazy" }, key()) : /* @__PURE__ */ jsx54("span", { className: "fd-md-imgalt", children: g(1) || "image" }, key()));
5248
+ const src2 = safeHref(d(g(2)));
5249
+ out.push(ctx.allowImages && src2 ? /* @__PURE__ */ jsx54("img", { className: "fd-md-img", src: src2, alt: d(g(1) || ""), title: g(3) ? d(g(3)) : void 0, loading: "lazy" }, key()) : /* @__PURE__ */ jsx54("span", { className: "fd-md-imgalt", children: d(g(1) || "image") }, key()));
5212
5250
  } else if (kind === "link") {
5213
- const href = safeHref(g(2));
5214
- out.push(href ? /* @__PURE__ */ jsx54("a", { href, title: g(3) || void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx54("span", { children: g(1) }, key()));
5251
+ const href = safeHref(d(g(2)));
5252
+ out.push(href ? /* @__PURE__ */ jsx54("a", { href, title: g(3) ? d(g(3)) : void 0, target: /^https?:/i.test(href) ? "_blank" : void 0, rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: inlineNodes(g(1), ctx, key()) }, key()) : /* @__PURE__ */ jsx54("span", { children: d(g(1)) }, key()));
5215
5253
  } else if (kind === "cite") {
5216
- out.push(ctx.renderCitation ? /* @__PURE__ */ jsx54(React35.Fragment, { children: ctx.renderCitation(g(1)) }, key()) : /* @__PURE__ */ jsx54("sup", { className: "fd-md-cite", children: g(1) }, key()));
5254
+ out.push(ctx.renderCitation ? /* @__PURE__ */ jsx54(React35.Fragment, { children: ctx.renderCitation(d(g(1))) }, key()) : /* @__PURE__ */ jsx54("sup", { className: "fd-md-cite", children: d(g(1)) }, key()));
5217
5255
  } else if (kind === "strongem") out.push(/* @__PURE__ */ jsx54("strong", { children: /* @__PURE__ */ jsx54("em", { children: inlineNodes(g(1), ctx, key()) }) }, key()));
5218
5256
  else if (kind === "strong") out.push(/* @__PURE__ */ jsx54("strong", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
5219
5257
  else if (kind === "em") out.push(/* @__PURE__ */ jsx54("em", { children: inlineNodes(g(1) || g(2), ctx, key()) }, key()));
5220
5258
  else if (kind === "del") out.push(/* @__PURE__ */ jsx54("del", { children: inlineNodes(g(1), ctx, key()) }, key()));
5221
5259
  else if (kind === "autolink" || kind === "bare") {
5222
- const href = safeHref(g(1));
5223
- out.push(href ? /* @__PURE__ */ jsx54("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: g(1).replace(/^mailto:/, "") }, key()) : g(1));
5260
+ const href = safeHref(d(g(1)));
5261
+ out.push(href ? /* @__PURE__ */ jsx54("a", { href, target: "_blank", rel: "noopener noreferrer", onClick: ctx.onLinkClick, children: d(g(1)).replace(/^mailto:/, "") }, key()) : d(g(1)));
5224
5262
  }
5225
5263
  rest = rest.slice(m.index + m[0].length);
5226
5264
  }
5227
- if (rest) out.push(rest);
5265
+ if (rest) out.push(d(rest));
5228
5266
  return out;
5229
5267
  }
5230
5268
  var RE = {
@@ -5236,7 +5274,26 @@ var RE = {
5236
5274
  task: /^\[([ xX])\]\s+(.*)$/,
5237
5275
  tableSep: /^\s*\|?[\s:|-]*-[\s:|-]*\|?\s*$/
5238
5276
  };
5239
- var splitRow = (line) => line.replace(/^\s*\|/, "").replace(/\|\s*$/, "").split("|").map((c) => c.trim());
5277
+ var splitRow = (line) => {
5278
+ const t = line.trim();
5279
+ const cells = [];
5280
+ let cur = "";
5281
+ for (let i = t.startsWith("|") ? 1 : 0; i < t.length; i++) {
5282
+ const c = t[i];
5283
+ if (c === "\\" && i + 1 < t.length) {
5284
+ cur += c + t[++i];
5285
+ continue;
5286
+ }
5287
+ if (c === "|") {
5288
+ cells.push(cur.trim());
5289
+ cur = "";
5290
+ continue;
5291
+ }
5292
+ cur += c;
5293
+ }
5294
+ if (cur.trim() || !t.endsWith("|")) cells.push(cur.trim());
5295
+ return cells;
5296
+ };
5240
5297
  function parseBlocks(src) {
5241
5298
  const lines = String(src == null ? "" : src).replace(/\r\n?/g, "\n").split("\n");
5242
5299
  const blocks = [];
@@ -5368,6 +5425,7 @@ function renderBlocks(blocks, ctx, path) {
5368
5425
  }
5369
5426
  });
5370
5427
  }
5428
+ var mdClass = (base, size, tone, className) => [base, size && `${base}--${size}`, tone === "muted" && `${base}--muted`, className].filter(Boolean).join(" ");
5371
5429
  function Markdown({
5372
5430
  source = "",
5373
5431
  className = "",
@@ -5375,14 +5433,16 @@ function Markdown({
5375
5433
  allowImages = true,
5376
5434
  headingOffset = 0,
5377
5435
  renderCitation,
5378
- onLinkClick
5436
+ onLinkClick,
5437
+ size = "body",
5438
+ tone = "default"
5379
5439
  }) {
5380
5440
  const ctx = { allowImages, headingOffset, renderCitation, onLinkClick, codeProps };
5381
5441
  const blocks = React35.useMemo(() => parseBlocks(source), [source]);
5382
- return /* @__PURE__ */ jsx54("div", { className: ["fd-md", className].filter(Boolean).join(" "), children: renderBlocks(blocks, ctx, "b") });
5442
+ return /* @__PURE__ */ jsx54("div", { className: mdClass("fd-md", size, tone, className), children: renderBlocks(blocks, ctx, "b") });
5383
5443
  }
5384
- function MarkdownInline({ source = "", className = "", onLinkClick }) {
5385
- return /* @__PURE__ */ jsx54("span", { className: ["fd-md-inline", className].filter(Boolean).join(" "), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
5444
+ function MarkdownInline({ source = "", className = "", onLinkClick, size, tone }) {
5445
+ return /* @__PURE__ */ jsx54("span", { className: mdClass("fd-md-inline", size, tone, className), children: inlineNodes(source, { allowImages: false, onLinkClick }, "i") });
5386
5446
  }
5387
5447
  function markdownToText(src) {
5388
5448
  return String(src == null ? "" : src).replace(/```[\w+#-]*\n?([\s\S]*?)```/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/\*\*\*([^*]+)\*\*\*|\*\*([^*]+)\*\*|__([^_]+)__/g, "$1$2$3").replace(/(^|\W)[*_]([^*_\n]+)[*_](\W|$)/g, "$1$2$3").replace(/~~([^~]+)~~/g, "$1").replace(/^\s*>\s?/gm, "").trim();
@@ -6646,14 +6706,17 @@ function Checkbox({ label, description, card = false, indeterminate = false, cla
6646
6706
 
6647
6707
  // src/components/forms/Radio.tsx
6648
6708
  import { jsx as jsx69, jsxs as jsxs58 } from "react/jsx-runtime";
6649
- function Radio({ label, description, card = false, className = "", ...rest }) {
6709
+ function Radio({ label, description, badge, card = false, className = "", ...rest }) {
6650
6710
  return /* @__PURE__ */ jsxs58("label", { className: ["fd-choice", card ? "fd-choice-card" : "", className].filter(Boolean).join(" "), children: [
6651
6711
  /* @__PURE__ */ jsxs58("span", { className: "fd-choice-input", children: [
6652
6712
  /* @__PURE__ */ jsx69("input", { type: "radio", ...rest }),
6653
6713
  /* @__PURE__ */ jsx69("span", { className: "fd-choice-box fd-choice-box-round", "aria-hidden": "true", children: /* @__PURE__ */ jsx69("span", { className: "fd-choice-dot" }) })
6654
6714
  ] }),
6655
6715
  /* @__PURE__ */ jsxs58("span", { className: "fd-choice-text", children: [
6656
- /* @__PURE__ */ jsx69("span", { className: "fd-choice-title", children: label }),
6716
+ /* @__PURE__ */ jsxs58("span", { className: "fd-choice-title", children: [
6717
+ label,
6718
+ badge ? /* @__PURE__ */ jsx69("span", { className: "fd-choice-badge", children: badge }) : null
6719
+ ] }),
6657
6720
  description ? /* @__PURE__ */ jsx69("span", { className: "fd-choice-desc", children: description }) : null
6658
6721
  ] })
6659
6722
  ] });
@@ -8245,17 +8308,49 @@ function CodeEditor({
8245
8308
  ] });
8246
8309
  }
8247
8310
 
8311
+ // src/components/forms/RadioGroup.tsx
8312
+ import * as React53 from "react";
8313
+ import { jsx as jsx79, jsxs as jsxs68 } from "react/jsx-runtime";
8314
+ function RadioGroup({ label, options, value, onChange, card = false, disabled = false, name, className = "" }) {
8315
+ const autoName = React53.useId();
8316
+ const labelId = React53.useId();
8317
+ return /* @__PURE__ */ jsxs68("div", { role: "radiogroup", "aria-labelledby": labelId, "aria-disabled": disabled || void 0, className: ["fd-radiogroup", className].filter(Boolean).join(" "), children: [
8318
+ /* @__PURE__ */ jsx79("span", { id: labelId, className: "fd-radiogroup-label", children: label }),
8319
+ options.map((o) => /* @__PURE__ */ jsx79(
8320
+ Radio,
8321
+ {
8322
+ card,
8323
+ name: name ?? autoName,
8324
+ value: o.value,
8325
+ label: o.label,
8326
+ description: o.description,
8327
+ badge: o.badge,
8328
+ checked: o.value === value,
8329
+ disabled: disabled || o.disabled,
8330
+ onChange: () => onChange(o.value)
8331
+ },
8332
+ o.value
8333
+ ))
8334
+ ] });
8335
+ }
8336
+
8337
+ // src/components/forms/Fieldset.tsx
8338
+ import { jsx as jsx80 } from "react/jsx-runtime";
8339
+ function Fieldset({ busy = false, className = "", ...rest }) {
8340
+ return /* @__PURE__ */ jsx80("fieldset", { disabled: busy, "aria-busy": busy || void 0, className: ["fd-fieldset", className].filter(Boolean).join(" "), ...rest });
8341
+ }
8342
+
8248
8343
  // src/components/platform/AccountMenu.tsx
8249
- import * as React54 from "react";
8344
+ import * as React55 from "react";
8250
8345
 
8251
8346
  // src/kits/sessionContext.tsx
8252
- import * as React53 from "react";
8253
- var SessionContext = React53.createContext(null);
8347
+ import * as React54 from "react";
8348
+ var SessionContext = React54.createContext(null);
8254
8349
  function SessionProvider({ value, children }) {
8255
- return React53.createElement(SessionContext.Provider, { value }, children);
8350
+ return React54.createElement(SessionContext.Provider, { value }, children);
8256
8351
  }
8257
8352
  function useSessionContext() {
8258
- const ctx = React53.useContext(SessionContext);
8353
+ const ctx = React54.useContext(SessionContext);
8259
8354
  if (!ctx) {
8260
8355
  throw new Error(
8261
8356
  "useSessionContext() was called outside a <SessionProvider>. Wrap your app root in <SessionProvider value={...}> with your real session, or \u2014 in the docs site or a demo \u2014 in <DemoSessionProvider>, before rendering AccountMenu, Gate, ProfilePage or AppSwitcher."
@@ -8265,11 +8360,11 @@ function useSessionContext() {
8265
8360
  }
8266
8361
 
8267
8362
  // src/components/platform/AccountMenu.tsx
8268
- import { Fragment as Fragment19, jsx as jsx79, jsxs as jsxs68 } from "react/jsx-runtime";
8363
+ import { Fragment as Fragment19, jsx as jsx81, jsxs as jsxs69 } from "react/jsx-runtime";
8269
8364
  var DEFAULT_LINKS = [];
8270
8365
  var DEFAULT_GROUPS = [];
8271
8366
  function Item({ item, onPick }) {
8272
- return /* @__PURE__ */ jsxs68(
8367
+ return /* @__PURE__ */ jsxs69(
8273
8368
  "button",
8274
8369
  {
8275
8370
  type: "button",
@@ -8277,9 +8372,9 @@ function Item({ item, onPick }) {
8277
8372
  className: "fd-acct-item",
8278
8373
  onClick: () => onPick(item),
8279
8374
  children: [
8280
- item.icon ? /* @__PURE__ */ jsx79("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
8281
- /* @__PURE__ */ jsx79("span", { style: { flex: 1 }, children: item.label }),
8282
- item.badge ? /* @__PURE__ */ jsx79(Badge, { tone: "neutral", children: item.badge }) : null
8375
+ item.icon ? /* @__PURE__ */ jsx81("i", { className: "ph ph-" + item.icon, "aria-hidden": "true" }) : null,
8376
+ /* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: item.label }),
8377
+ item.badge ? /* @__PURE__ */ jsx81(Badge, { tone: "neutral", children: item.badge }) : null
8283
8378
  ]
8284
8379
  }
8285
8380
  );
@@ -8295,11 +8390,11 @@ function AccountMenu({
8295
8390
  ...rest
8296
8391
  }) {
8297
8392
  const { user, roles, can: can2, signOut: ctxSignOut, demo, pending } = useSessionContext();
8298
- const [open2, setOpen] = React54.useState(false);
8299
- const [switching, setSwitching] = React54.useState(false);
8300
- const [signingOut, setSigningOut] = React54.useState(false);
8301
- const [signOutError, setSignOutError] = React54.useState(null);
8302
- const ref = React54.useRef(null);
8393
+ const [open2, setOpen] = React55.useState(false);
8394
+ const [switching, setSwitching] = React55.useState(false);
8395
+ const [signingOut, setSigningOut] = React55.useState(false);
8396
+ const [signOutError, setSignOutError] = React55.useState(null);
8397
+ const ref = React55.useRef(null);
8303
8398
  const visibleLinks = links.filter((l) => !l.perm || !pending && can2(l.perm));
8304
8399
  const visibleGroups = groups.map((g) => ({ label: g.label, links: g.links.filter((l) => !l.perm || !pending && can2(l.perm)) })).filter((g) => g.links.length);
8305
8400
  const closeMenu = () => {
@@ -8327,8 +8422,8 @@ function AccountMenu({
8327
8422
  }
8328
8423
  };
8329
8424
  const showSwitcher = allowUserSwitch && !!demo;
8330
- return /* @__PURE__ */ jsxs68(Fragment19, { children: [
8331
- /* @__PURE__ */ jsxs68(
8425
+ return /* @__PURE__ */ jsxs69(Fragment19, { children: [
8426
+ /* @__PURE__ */ jsxs69(
8332
8427
  "button",
8333
8428
  {
8334
8429
  type: "button",
@@ -8340,12 +8435,12 @@ function AccountMenu({
8340
8435
  onClick: () => open2 ? closeMenu() : setOpen(true),
8341
8436
  ...rest,
8342
8437
  children: [
8343
- /* @__PURE__ */ jsx79(Avatar, { name: user.name, size: "sm" }),
8344
- /* @__PURE__ */ jsx79("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
8438
+ /* @__PURE__ */ jsx81(Avatar, { name: user.name, size: "sm" }),
8439
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-caret-down", "aria-hidden": "true", style: { fontSize: 11, color: "var(--text-muted)" } })
8345
8440
  ]
8346
8441
  }
8347
8442
  ),
8348
- /* @__PURE__ */ jsx79(
8443
+ /* @__PURE__ */ jsx81(
8349
8444
  Popover,
8350
8445
  {
8351
8446
  open: open2,
@@ -8353,27 +8448,27 @@ function AccountMenu({
8353
8448
  onClose: closeMenu,
8354
8449
  placement: "bottom-end",
8355
8450
  width: 272,
8356
- children: /* @__PURE__ */ jsxs68("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
8357
- /* @__PURE__ */ jsxs68("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
8358
- /* @__PURE__ */ jsx79(Avatar, { name: user.name }),
8359
- /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
8360
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
8361
- /* @__PURE__ */ jsx79("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
8451
+ children: /* @__PURE__ */ jsxs69("div", { role: "menu", className: "fd-stack", style: { gap: 0 }, children: [
8452
+ /* @__PURE__ */ jsxs69("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
8453
+ /* @__PURE__ */ jsx81(Avatar, { name: user.name }),
8454
+ /* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 1, minWidth: 0, flex: 1 }, children: [
8455
+ /* @__PURE__ */ jsx81("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: user.name }),
8456
+ /* @__PURE__ */ jsx81("span", { className: "fd-body-sm fd-muted fd-table-trunc", title: truncationTitle(user.email), children: user.email })
8362
8457
  ] })
8363
8458
  ] }),
8364
- showRoles && roles.length ? /* @__PURE__ */ jsx79("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx79(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
8365
- visibleLinks.length ? /* @__PURE__ */ jsx79("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx79(Item, { item: l, onPick: pick }, l.id)) }) : null,
8366
- visibleGroups.map((g) => /* @__PURE__ */ jsxs68("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8367
- /* @__PURE__ */ jsx79("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
8368
- g.links.map((l) => /* @__PURE__ */ jsx79(Item, { item: l, onPick: pick }, l.id))
8459
+ showRoles && roles.length ? /* @__PURE__ */ jsx81("div", { className: "fd-row", style: { gap: 6, padding: "10px 14px", flexWrap: "wrap", borderBottom: "1px solid var(--border)" }, children: roles.map((r) => /* @__PURE__ */ jsx81(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)) }) : null,
8460
+ visibleLinks.length ? /* @__PURE__ */ jsx81("div", { className: "fd-acct-group", children: visibleLinks.map((l) => /* @__PURE__ */ jsx81(Item, { item: l, onPick: pick }, l.id)) }) : null,
8461
+ visibleGroups.map((g) => /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8462
+ /* @__PURE__ */ jsx81("span", { className: "fd-overline fd-muted", style: { padding: "8px 14px 4px", display: "block" }, children: g.label }),
8463
+ g.links.map((l) => /* @__PURE__ */ jsx81(Item, { item: l, onPick: pick }, l.id))
8369
8464
  ] }, g.label)),
8370
- showSwitcher && demo ? /* @__PURE__ */ jsxs68("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8371
- /* @__PURE__ */ jsxs68("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
8372
- /* @__PURE__ */ jsx79("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
8373
- /* @__PURE__ */ jsx79("span", { style: { flex: 1 }, children: "View as another member" }),
8374
- /* @__PURE__ */ jsx79("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
8465
+ showSwitcher && demo ? /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8466
+ /* @__PURE__ */ jsxs69("button", { type: "button", role: "menuitem", className: "fd-acct-item", onClick: () => setSwitching((s) => !s), children: [
8467
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-user-switch", "aria-hidden": "true" }),
8468
+ /* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: "View as another member" }),
8469
+ /* @__PURE__ */ jsx81("i", { className: "ph ph-caret-" + (switching ? "up" : "down"), "aria-hidden": "true", style: { fontSize: 11 } })
8375
8470
  ] }),
8376
- switching ? /* @__PURE__ */ jsx79("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs68(
8471
+ switching ? /* @__PURE__ */ jsx81("div", { className: "fd-stack", style: { gap: 0 }, children: demo.allUsers.map((u) => /* @__PURE__ */ jsxs69(
8377
8472
  "button",
8378
8473
  {
8379
8474
  type: "button",
@@ -8385,19 +8480,19 @@ function AccountMenu({
8385
8480
  setSwitching(false);
8386
8481
  },
8387
8482
  children: [
8388
- /* @__PURE__ */ jsx79(Avatar, { name: u.name, size: "sm" }),
8389
- /* @__PURE__ */ jsxs68("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
8390
- /* @__PURE__ */ jsx79("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
8391
- u.roles ? /* @__PURE__ */ jsx79("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
8483
+ /* @__PURE__ */ jsx81(Avatar, { name: u.name, size: "sm" }),
8484
+ /* @__PURE__ */ jsxs69("span", { className: "fd-stack", style: { gap: 0, flex: 1, minWidth: 0, alignItems: "flex-start" }, children: [
8485
+ /* @__PURE__ */ jsx81("span", { style: { fontWeight: u.id === user.id ? 700 : 500 }, children: u.name }),
8486
+ u.roles ? /* @__PURE__ */ jsx81("span", { className: "fd-muted", style: { fontSize: 11.5 }, children: u.roles.join(", ") }) : null
8392
8487
  ] }),
8393
- u.id === user.id ? /* @__PURE__ */ jsx79("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
8488
+ u.id === user.id ? /* @__PURE__ */ jsx81("i", { className: "ph ph-check", "aria-hidden": "true", style: { color: "var(--ok-text)" } }) : null
8394
8489
  ]
8395
8490
  },
8396
8491
  u.id
8397
8492
  )) }) : null
8398
8493
  ] }) : null,
8399
- /* @__PURE__ */ jsxs68("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8400
- /* @__PURE__ */ jsxs68(
8494
+ /* @__PURE__ */ jsxs69("div", { className: "fd-acct-group", style: { borderTop: "1px solid var(--border)" }, children: [
8495
+ /* @__PURE__ */ jsxs69(
8401
8496
  "button",
8402
8497
  {
8403
8498
  type: "button",
@@ -8407,14 +8502,14 @@ function AccountMenu({
8407
8502
  disabled: signingOut,
8408
8503
  onClick: signOut,
8409
8504
  children: [
8410
- signingOut ? /* @__PURE__ */ jsx79(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx79("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
8411
- /* @__PURE__ */ jsx79("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
8505
+ signingOut ? /* @__PURE__ */ jsx81(Spinner, { size: "sm" }) : /* @__PURE__ */ jsx81("i", { className: "ph ph-sign-out", "aria-hidden": "true" }),
8506
+ /* @__PURE__ */ jsx81("span", { style: { flex: 1 }, children: signingOut ? "Signing out\u2026" : "Sign out" })
8412
8507
  ]
8413
8508
  }
8414
8509
  ),
8415
- signOutError ? /* @__PURE__ */ jsxs68("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
8416
- /* @__PURE__ */ jsx79("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
8417
- /* @__PURE__ */ jsx79("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
8510
+ signOutError ? /* @__PURE__ */ jsxs69("div", { role: "alert", className: "fd-body-sm", style: { padding: "0 14px 12px" }, children: [
8511
+ /* @__PURE__ */ jsx81("span", { style: { display: "block", color: "var(--danger-text)", marginBottom: 6 }, children: signOutError }),
8512
+ /* @__PURE__ */ jsx81("button", { type: "button", className: "fd-soon-link", disabled: signingOut, onClick: signOut, children: "Retry" })
8418
8513
  ] }) : null
8419
8514
  ] })
8420
8515
  ] })
@@ -8424,13 +8519,13 @@ function AccountMenu({
8424
8519
  }
8425
8520
 
8426
8521
  // src/components/platform/AppSwitcher.tsx
8427
- import * as React55 from "react";
8428
- import { jsx as jsx80, jsxs as jsxs69 } from "react/jsx-runtime";
8522
+ import * as React56 from "react";
8523
+ import { jsx as jsx82, jsxs as jsxs70 } from "react/jsx-runtime";
8429
8524
  function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8430
8525
  const { apps: contextApps } = useSessionContext();
8431
8526
  const apps = appsProp ?? contextApps ?? [];
8432
- const [open2, setOpen] = React55.useState(false);
8433
- const anchorRef = React55.useRef(null);
8527
+ const [open2, setOpen] = React56.useState(false);
8528
+ const anchorRef = React56.useRef(null);
8434
8529
  if (!apps.length) return null;
8435
8530
  const items = apps.map((app) => ({
8436
8531
  id: app.key,
@@ -8444,8 +8539,8 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8444
8539
  window.location.href = app.url;
8445
8540
  }
8446
8541
  }));
8447
- return /* @__PURE__ */ jsxs69(React55.Fragment, { children: [
8448
- /* @__PURE__ */ jsx80("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx80(
8542
+ return /* @__PURE__ */ jsxs70(React56.Fragment, { children: [
8543
+ /* @__PURE__ */ jsx82("span", { ref: anchorRef, className: ["fd-appswitch-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx82(
8449
8544
  IconButton,
8450
8545
  {
8451
8546
  icon: "squares-four",
@@ -8455,7 +8550,7 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8455
8550
  onClick: () => setOpen((v) => !v)
8456
8551
  }
8457
8552
  ) }),
8458
- /* @__PURE__ */ jsx80(
8553
+ /* @__PURE__ */ jsx82(
8459
8554
  Popover,
8460
8555
  {
8461
8556
  open: open2,
@@ -8466,17 +8561,17 @@ function AppSwitcher({ apps: appsProp, onNavigate, className = "" }) {
8466
8561
  label: "All flytedesk apps",
8467
8562
  width: 240,
8468
8563
  maxHeight: 360,
8469
- children: /* @__PURE__ */ jsx80(Menu, { items, onClose: () => setOpen(false) })
8564
+ children: /* @__PURE__ */ jsx82(Menu, { items, onClose: () => setOpen(false) })
8470
8565
  }
8471
8566
  )
8472
8567
  ] });
8473
8568
  }
8474
8569
 
8475
8570
  // src/components/platform/AppearanceMenu.tsx
8476
- import * as React58 from "react";
8571
+ import * as React59 from "react";
8477
8572
 
8478
8573
  // src/kits/appearance.ts
8479
- import * as React56 from "react";
8574
+ import * as React57 from "react";
8480
8575
  var DEFAULT_STORAGE_KEY = "fd-appearance";
8481
8576
  var DEFAULT_PREFS = {
8482
8577
  theme: "system",
@@ -8588,8 +8683,8 @@ function watchAppearance(store, root = document.documentElement) {
8588
8683
  };
8589
8684
  }
8590
8685
  function useAppearancePrefs(store) {
8591
- const prefs = React56.useSyncExternalStore(store.subscribe, store.getSnapshot);
8592
- const update = React56.useCallback(
8686
+ const prefs = React57.useSyncExternalStore(store.subscribe, store.getSnapshot);
8687
+ const update = React57.useCallback(
8593
8688
  (patch) => {
8594
8689
  store.write({ ...store.getSnapshot(), ...patch });
8595
8690
  },
@@ -8599,21 +8694,21 @@ function useAppearancePrefs(store) {
8599
8694
  }
8600
8695
 
8601
8696
  // src/components/platform/AppearanceProvider.tsx
8602
- import * as React57 from "react";
8603
- import { jsx as jsx81 } from "react/jsx-runtime";
8604
- var AppearanceStoreContext = React57.createContext(null);
8697
+ import * as React58 from "react";
8698
+ import { jsx as jsx83 } from "react/jsx-runtime";
8699
+ var AppearanceStoreContext = React58.createContext(null);
8605
8700
  function AppearanceProvider({ store, children }) {
8606
- React57.useLayoutEffect(() => watchAppearance(store), [store]);
8607
- return /* @__PURE__ */ jsx81(AppearanceStoreContext.Provider, { value: store, children });
8701
+ React58.useLayoutEffect(() => watchAppearance(store), [store]);
8702
+ return /* @__PURE__ */ jsx83(AppearanceStoreContext.Provider, { value: store, children });
8608
8703
  }
8609
8704
  function useAppearanceStore() {
8610
- const store = React57.useContext(AppearanceStoreContext);
8705
+ const store = React58.useContext(AppearanceStoreContext);
8611
8706
  if (!store) throw new Error("AppearanceMenu and useAppearanceStore must be rendered inside an <AppearanceProvider>.");
8612
8707
  return store;
8613
8708
  }
8614
8709
 
8615
8710
  // src/components/platform/AppearanceMenu.tsx
8616
- import { jsx as jsx82, jsxs as jsxs70 } from "react/jsx-runtime";
8711
+ import { jsx as jsx84, jsxs as jsxs71 } from "react/jsx-runtime";
8617
8712
  var THEME_OPTIONS = [
8618
8713
  { value: "light", label: "Light" },
8619
8714
  { value: "dark", label: "Dark" },
@@ -8627,11 +8722,11 @@ var TEXT_SCALE_OPTIONS = [
8627
8722
  ];
8628
8723
  function AppearanceMenu({ className = "" }) {
8629
8724
  const [prefs, update] = useAppearancePrefs(useAppearanceStore());
8630
- const [open2, setOpen] = React58.useState(false);
8631
- const anchorRef = React58.useRef(null);
8725
+ const [open2, setOpen] = React59.useState(false);
8726
+ const anchorRef = React59.useRef(null);
8632
8727
  const patch = (p) => update(p);
8633
- return /* @__PURE__ */ jsxs70(React58.Fragment, { children: [
8634
- /* @__PURE__ */ jsx82("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx82(
8728
+ return /* @__PURE__ */ jsxs71(React59.Fragment, { children: [
8729
+ /* @__PURE__ */ jsx84("span", { ref: anchorRef, className: ["fd-appearance-anchor", className].filter(Boolean).join(" "), style: { display: "inline-flex" }, children: /* @__PURE__ */ jsx84(
8635
8730
  IconButton,
8636
8731
  {
8637
8732
  icon: "circle-half",
@@ -8639,7 +8734,7 @@ function AppearanceMenu({ className = "" }) {
8639
8734
  onClick: () => setOpen((v) => !v)
8640
8735
  }
8641
8736
  ) }),
8642
- /* @__PURE__ */ jsx82(
8737
+ /* @__PURE__ */ jsx84(
8643
8738
  Popover,
8644
8739
  {
8645
8740
  open: open2,
@@ -8649,10 +8744,10 @@ function AppearanceMenu({ className = "" }) {
8649
8744
  padded: true,
8650
8745
  width: 260,
8651
8746
  label: "Appearance settings",
8652
- children: /* @__PURE__ */ jsxs70("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
8653
- /* @__PURE__ */ jsxs70("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8654
- /* @__PURE__ */ jsx82("span", { className: "fd-field-label", children: "Theme" }),
8655
- /* @__PURE__ */ jsx82(
8747
+ children: /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
8748
+ /* @__PURE__ */ jsxs71("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8749
+ /* @__PURE__ */ jsx84("span", { className: "fd-field-label", children: "Theme" }),
8750
+ /* @__PURE__ */ jsx84(
8656
8751
  SegmentedControl,
8657
8752
  {
8658
8753
  options: THEME_OPTIONS,
@@ -8662,9 +8757,9 @@ function AppearanceMenu({ className = "" }) {
8662
8757
  }
8663
8758
  )
8664
8759
  ] }),
8665
- /* @__PURE__ */ jsxs70("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8666
- /* @__PURE__ */ jsx82("span", { className: "fd-field-label", children: "Text size" }),
8667
- /* @__PURE__ */ jsx82(
8760
+ /* @__PURE__ */ jsxs71("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: [
8761
+ /* @__PURE__ */ jsx84("span", { className: "fd-field-label", children: "Text size" }),
8762
+ /* @__PURE__ */ jsx84(
8668
8763
  SegmentedControl,
8669
8764
  {
8670
8765
  options: TEXT_SCALE_OPTIONS,
@@ -8674,7 +8769,7 @@ function AppearanceMenu({ className = "" }) {
8674
8769
  }
8675
8770
  )
8676
8771
  ] }),
8677
- /* @__PURE__ */ jsx82(
8772
+ /* @__PURE__ */ jsx84(
8678
8773
  Switch,
8679
8774
  {
8680
8775
  label: "High contrast",
@@ -8683,7 +8778,7 @@ function AppearanceMenu({ className = "" }) {
8683
8778
  onChange: (e) => patch({ highContrast: e.target.checked })
8684
8779
  }
8685
8780
  ),
8686
- /* @__PURE__ */ jsx82(
8781
+ /* @__PURE__ */ jsx84(
8687
8782
  Switch,
8688
8783
  {
8689
8784
  label: "Reduce motion",
@@ -8699,14 +8794,14 @@ function AppearanceMenu({ className = "" }) {
8699
8794
  }
8700
8795
 
8701
8796
  // src/components/platform/ApiSpecBrowser.tsx
8702
- import * as React59 from "react";
8703
- import { jsx as jsx83, jsxs as jsxs71 } from "react/jsx-runtime";
8797
+ import * as React60 from "react";
8798
+ import { jsx as jsx85, jsxs as jsxs72 } from "react/jsx-runtime";
8704
8799
  var METHOD_TONE = { GET: "success", POST: "info", PATCH: "warning", PUT: "warning", DELETE: "danger" };
8705
8800
  function Json({ obj }) {
8706
- return /* @__PURE__ */ jsx83("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8801
+ return /* @__PURE__ */ jsx85("pre", { className: "fd-json", children: JSON.stringify(obj, null, 2) });
8707
8802
  }
8708
8803
  function Endpoint({ s, onRequest }) {
8709
- const [tried, setTried] = React59.useState(null);
8804
+ const [tried, setTried] = React60.useState(null);
8710
8805
  const run = async () => {
8711
8806
  setTried("busy");
8712
8807
  const t0 = (window.performance || Date).now();
@@ -8717,50 +8812,50 @@ function Endpoint({ s, onRequest }) {
8717
8812
  setTried({ ms: Math.round((window.performance || Date).now() - t0), error: String(e && e.message || e) });
8718
8813
  }
8719
8814
  };
8720
- return /* @__PURE__ */ jsx83(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 0 }, children: [
8721
- /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
8722
- /* @__PURE__ */ jsx83(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8723
- /* @__PURE__ */ jsx83("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8724
- s.isList ? /* @__PURE__ */ jsx83(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8725
- /* @__PURE__ */ jsx83("span", { style: { flex: 1 } }),
8726
- /* @__PURE__ */ jsxs71("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8815
+ return /* @__PURE__ */ jsx85(Card, { elevation: "flat", padded: false, children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 0 }, children: [
8816
+ /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, padding: "14px 18px", flexWrap: "wrap" }, children: [
8817
+ /* @__PURE__ */ jsx85(Badge, { tone: METHOD_TONE[s.method] || "neutral", children: s.method }),
8818
+ /* @__PURE__ */ jsx85("code", { className: "fd-mono", style: { fontSize: 12.5, fontWeight: 600, color: "var(--text)", wordBreak: "break-all" }, children: s.path }),
8819
+ s.isList ? /* @__PURE__ */ jsx85(Badge, { tone: "neutral", icon: "rows", children: "Paged list" }) : null,
8820
+ /* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
8821
+ /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted fd-mono", children: [
8727
8822
  s.latency[0],
8728
8823
  "\u2013",
8729
8824
  s.latency[1],
8730
8825
  "ms"
8731
8826
  ] }),
8732
- /* @__PURE__ */ jsx83(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
8827
+ /* @__PURE__ */ jsx85(Button, { size: "sm", variant: "secondary", icon: "play", loading: tried === "busy", onClick: run, children: "Try it" })
8733
8828
  ] }),
8734
- /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
8735
- /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8736
- /* @__PURE__ */ jsx83("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8737
- /* @__PURE__ */ jsx83("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8738
- s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx83("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx83(Tag, { children: u }, u)) }) : null
8829
+ /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 14, padding: "0 18px 16px" }, children: [
8830
+ /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8831
+ /* @__PURE__ */ jsx85("span", { className: "fd-body-sm", style: { fontWeight: 700 }, children: s.title }),
8832
+ /* @__PURE__ */ jsx85("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: s.purpose }),
8833
+ s.usedBy && s.usedBy.length ? /* @__PURE__ */ jsx85("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: s.usedBy.map((u) => /* @__PURE__ */ jsx85(Tag, { children: u }, u)) }) : null
8739
8834
  ] }),
8740
- /* @__PURE__ */ jsxs71("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
8741
- s.request ? /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8742
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Request body" }),
8743
- /* @__PURE__ */ jsx83(Json, { obj: s.request })
8835
+ /* @__PURE__ */ jsxs72("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(280px,1fr))", gap: 12, alignItems: "start" }, children: [
8836
+ s.request ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8837
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Request body" }),
8838
+ /* @__PURE__ */ jsx85(Json, { obj: s.request })
8744
8839
  ] }) : null,
8745
- s.query ? /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8746
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Query" }),
8747
- /* @__PURE__ */ jsx83(Json, { obj: s.query })
8840
+ s.query ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8841
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Query" }),
8842
+ /* @__PURE__ */ jsx85(Json, { obj: s.query })
8748
8843
  ] }) : null,
8749
- /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8750
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8751
- /* @__PURE__ */ jsx83(Json, { obj: s.response })
8844
+ /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8845
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Response 200" }),
8846
+ /* @__PURE__ */ jsx85(Json, { obj: s.response })
8752
8847
  ] })
8753
8848
  ] }),
8754
- s.notes ? /* @__PURE__ */ jsx83(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
8755
- tried && tried !== "busy" ? /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 6 }, children: [
8756
- /* @__PURE__ */ jsxs71("span", { className: "fd-row", style: { gap: 8 }, children: [
8757
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8758
- /* @__PURE__ */ jsxs71(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
8849
+ s.notes ? /* @__PURE__ */ jsx85(Flag, { tone: "info", statement: "Implementation note", cost: s.notes, actions: null }) : null,
8850
+ tried && tried !== "busy" ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 6 }, children: [
8851
+ /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 8 }, children: [
8852
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Simulated response" }),
8853
+ /* @__PURE__ */ jsxs72(Badge, { tone: tried.error ? "danger" : "success", icon: "timer", children: [
8759
8854
  tried.ms,
8760
8855
  "ms"
8761
8856
  ] })
8762
8857
  ] }),
8763
- /* @__PURE__ */ jsx83(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8858
+ /* @__PURE__ */ jsx85(Json, { obj: tried.error ? { error: tried.error } : tried.data })
8764
8859
  ] }) : null
8765
8860
  ] })
8766
8861
  ] }) });
@@ -8779,58 +8874,58 @@ function ApiSpecBrowser({
8779
8874
  className = "",
8780
8875
  ...rest
8781
8876
  }) {
8782
- const [q, setQ] = React59.useState("");
8783
- const [method, setMethod] = React59.useState(null);
8784
- const [mod, setMod] = React59.useState(null);
8785
- const [listOnly, setListOnly] = React59.useState(false);
8877
+ const [q, setQ] = React60.useState("");
8878
+ const [method, setMethod] = React60.useState(null);
8879
+ const [mod, setMod] = React60.useState(null);
8880
+ const [listOnly, setListOnly] = React60.useState(false);
8786
8881
  const activeModule = modules && modules.find((m) => m.id === mod);
8787
8882
  const hits = spec.filter((s) => (!method || s.method === method) && (!listOnly || s.isList) && (!activeModule || activeModule.endpoints.indexOf(s.id) >= 0) && (!q || (s.path + " " + s.title + " " + s.purpose + " " + (s.usedBy || []).join(" ")).toLowerCase().includes(q.toLowerCase())));
8788
8883
  const effGroups = groups && groups.length ? groups : [["All endpoints", spec.map((s) => s.id)]];
8789
8884
  const methods = [...new Set(spec.map((s) => s.method))];
8790
8885
  const listCount = spec.filter((s) => s.isList).length;
8791
- return /* @__PURE__ */ jsxs71("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8792
- /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 10 }, children: [
8793
- kicker ? /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8794
- /* @__PURE__ */ jsx83("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8795
- lede ? /* @__PURE__ */ jsx83("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8886
+ return /* @__PURE__ */ jsxs72("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 1100 }, ...rest, children: [
8887
+ /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
8888
+ kicker ? /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: kicker }) : null,
8889
+ /* @__PURE__ */ jsx85("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
8890
+ lede ? /* @__PURE__ */ jsx85("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede }) : null
8796
8891
  ] }),
8797
- modules && modules.length ? /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 8 }, children: [
8798
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8799
- /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8800
- /* @__PURE__ */ jsxs71(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8892
+ modules && modules.length ? /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 8 }, children: [
8893
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", children: "Filter by screen \u2014 every endpoint that screen depends on" }),
8894
+ /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
8895
+ /* @__PURE__ */ jsxs72(Tag, { icon: "stack", selected: !mod, onClick: () => setMod(null), children: [
8801
8896
  "All screens ",
8802
- /* @__PURE__ */ jsx83("span", { className: "fd-mono", children: spec.length })
8897
+ /* @__PURE__ */ jsx85("span", { className: "fd-mono", children: spec.length })
8803
8898
  ] }),
8804
- modules.map((m) => /* @__PURE__ */ jsxs71(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8899
+ modules.map((m) => /* @__PURE__ */ jsxs72(Tag, { icon: m.icon, selected: mod === m.id, onClick: () => setMod(mod === m.id ? null : m.id), children: [
8805
8900
  m.label,
8806
8901
  " ",
8807
- /* @__PURE__ */ jsx83("span", { className: "fd-mono", children: m.endpoints.length })
8902
+ /* @__PURE__ */ jsx85("span", { className: "fd-mono", children: m.endpoints.length })
8808
8903
  ] }, m.id))
8809
8904
  ] }),
8810
- activeModule ? /* @__PURE__ */ jsx83(
8905
+ activeModule ? /* @__PURE__ */ jsx85(
8811
8906
  Flag,
8812
8907
  {
8813
8908
  tone: "info",
8814
8909
  statement: activeModule.label + " calls " + activeModule.endpoints.length + " endpoints.",
8815
8910
  cost: "Integration checklist for this screen: " + activeModule.endpoints.join(", ") + ". Wire these and the screen is done.",
8816
- actions: /* @__PURE__ */ jsx83(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8911
+ actions: /* @__PURE__ */ jsx85(Button, { size: "sm", variant: "ghost", icon: "x", onClick: () => setMod(null), children: "Show all screens" })
8817
8912
  }
8818
8913
  ) : null
8819
8914
  ] }) : null,
8820
- sourceNote ? /* @__PURE__ */ jsx83(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8821
- /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8822
- /* @__PURE__ */ jsx83(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8823
- methods.map((m) => /* @__PURE__ */ jsxs71(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8915
+ sourceNote ? /* @__PURE__ */ jsx85(Flag, { tone: "info", statement: "Design-first: this page is the spec.", cost: sourceNote, actions: null }) : null,
8916
+ /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
8917
+ /* @__PURE__ */ jsx85(Input, { icon: "magnifying-glass", placeholder: "Find an endpoint, screen, or behavior", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
8918
+ methods.map((m) => /* @__PURE__ */ jsxs72(Tag, { selected: method === m, onClick: () => setMethod(method === m ? null : m), children: [
8824
8919
  m,
8825
8920
  " ",
8826
- /* @__PURE__ */ jsx83("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8921
+ /* @__PURE__ */ jsx85("span", { className: "fd-mono", children: spec.filter((s) => s.method === m).length })
8827
8922
  ] }, m)),
8828
- listCount ? /* @__PURE__ */ jsxs71(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8923
+ listCount ? /* @__PURE__ */ jsxs72(Tag, { icon: "rows", selected: listOnly, onClick: () => setListOnly(!listOnly), children: [
8829
8924
  "Paged lists ",
8830
- /* @__PURE__ */ jsx83("span", { className: "fd-mono", children: listCount })
8925
+ /* @__PURE__ */ jsx85("span", { className: "fd-mono", children: listCount })
8831
8926
  ] }) : null,
8832
- /* @__PURE__ */ jsx83("span", { style: { flex: 1 } }),
8833
- /* @__PURE__ */ jsxs71("span", { className: "fd-body-sm fd-muted", children: [
8927
+ /* @__PURE__ */ jsx85("span", { style: { flex: 1 } }),
8928
+ /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
8834
8929
  hits.length,
8835
8930
  " of ",
8836
8931
  spec.length,
@@ -8838,31 +8933,31 @@ function ApiSpecBrowser({
8838
8933
  listCount ? " \xB7 " + listCount + " paged" : ""
8839
8934
  ] })
8840
8935
  ] }),
8841
- hits.length === 0 ? /* @__PURE__ */ jsx83(Card, { elevation: "flat", children: /* @__PURE__ */ jsx83("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8936
+ hits.length === 0 ? /* @__PURE__ */ jsx85(Card, { elevation: "flat", children: /* @__PURE__ */ jsx85("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No endpoint matches those filters." }) }) : effGroups.map(([g, ids]) => {
8842
8937
  const items = hits.filter((s) => ids.indexOf(s.id) >= 0);
8843
8938
  if (!items.length) return null;
8844
- return /* @__PURE__ */ jsxs71("div", { className: "fd-stack", style: { gap: 12 }, children: [
8845
- /* @__PURE__ */ jsx83("span", { className: "fd-label-lg", children: g }),
8846
- items.map((s) => /* @__PURE__ */ jsx83(Endpoint, { s, onRequest }, s.id))
8939
+ return /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 12 }, children: [
8940
+ /* @__PURE__ */ jsx85("span", { className: "fd-label-lg", children: g }),
8941
+ items.map((s) => /* @__PURE__ */ jsx85(Endpoint, { s, onRequest }, s.id))
8847
8942
  ] }, g);
8848
8943
  }),
8849
- conventions && conventions.length ? /* @__PURE__ */ jsx83(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx83("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8850
- /* @__PURE__ */ jsx83("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8851
- /* @__PURE__ */ jsx83("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8944
+ conventions && conventions.length ? /* @__PURE__ */ jsx85(Card, { title: "Cross-cutting conventions", elevation: "flat", children: /* @__PURE__ */ jsx85("div", { className: "fd-stack", style: { gap: 10 }, children: conventions.map(([k, v]) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, alignItems: "flex-start" }, children: [
8945
+ /* @__PURE__ */ jsx85("span", { className: "fd-overline fd-muted", style: { width: 110, flex: "none", paddingTop: 2 }, children: k }),
8946
+ /* @__PURE__ */ jsx85("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: v })
8852
8947
  ] }, k)) }) }) : null,
8853
- openQuestions && openQuestions.length ? /* @__PURE__ */ jsx83(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx83("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs71("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8854
- /* @__PURE__ */ jsx83(Badge, { tone: "danger", children: id }),
8855
- /* @__PURE__ */ jsxs71("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8856
- /* @__PURE__ */ jsx83("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8857
- /* @__PURE__ */ jsx83("span", { className: "fd-body-sm fd-muted", children: why })
8948
+ openQuestions && openQuestions.length ? /* @__PURE__ */ jsx85(Collapsible, { icon: "list-checks", title: "Open questions before implementation", subtitle: openQuestions.length + " unresolved", children: /* @__PURE__ */ jsx85("div", { className: "fd-stack", style: { gap: 8 }, children: openQuestions.map(([id, question, why]) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start", padding: "8px 0", borderTop: "1px solid var(--border)" }, children: [
8949
+ /* @__PURE__ */ jsx85(Badge, { tone: "danger", children: id }),
8950
+ /* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 2, flex: 1 }, children: [
8951
+ /* @__PURE__ */ jsx85("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: question }),
8952
+ /* @__PURE__ */ jsx85("span", { className: "fd-body-sm fd-muted", children: why })
8858
8953
  ] })
8859
8954
  ] }, id)) }) }) : null
8860
8955
  ] });
8861
8956
  }
8862
8957
 
8863
8958
  // src/components/platform/ProfilePage.tsx
8864
- import * as React60 from "react";
8865
- import { jsx as jsx84, jsxs as jsxs72 } from "react/jsx-runtime";
8959
+ import * as React61 from "react";
8960
+ import { jsx as jsx86, jsxs as jsxs73 } from "react/jsx-runtime";
8866
8961
  function fieldInitialValue(field, user) {
8867
8962
  if (field.value) return field.value(user);
8868
8963
  const raw = user[field.key];
@@ -8897,21 +8992,21 @@ function ProfilePage({
8897
8992
  }) {
8898
8993
  const { user: sessionUser, roles, permissions, saveProfile: saveProfile2 } = useSessionContext();
8899
8994
  const user = userProp || sessionUser;
8900
- const initialFieldValues = React60.useMemo(() => {
8995
+ const initialFieldValues = React61.useMemo(() => {
8901
8996
  const values2 = {};
8902
8997
  for (const field of fields) values2[field.key] = fieldInitialValue(field, user);
8903
8998
  return values2;
8904
8999
  }, [user.id, fields]);
8905
- const initialNotify = React60.useMemo(() => {
9000
+ const initialNotify = React61.useMemo(() => {
8906
9001
  const values2 = {};
8907
9002
  for (const n of notifications) values2[n.key] = !!user.notify?.[n.key];
8908
9003
  return values2;
8909
9004
  }, [user.id, notifications]);
8910
- const [values, setValues] = React60.useState(initialFieldValues);
8911
- const [notify, setNotify] = React60.useState(initialNotify);
8912
- const [saving, setSaving] = React60.useState(false);
8913
- const [saved, setSaved] = React60.useState(false);
8914
- const [prevUserId, setPrevUserId] = React60.useState(user.id);
9005
+ const [values, setValues] = React61.useState(initialFieldValues);
9006
+ const [notify, setNotify] = React61.useState(initialNotify);
9007
+ const [saving, setSaving] = React61.useState(false);
9008
+ const [saved, setSaved] = React61.useState(false);
9009
+ const [prevUserId, setPrevUserId] = React61.useState(user.id);
8915
9010
  if (user.id !== prevUserId) {
8916
9011
  setPrevUserId(user.id);
8917
9012
  setValues(initialFieldValues);
@@ -8948,37 +9043,37 @@ function ProfilePage({
8948
9043
  };
8949
9044
  const displayName = fields.some((f) => f.key === "name") ? values.name || user.name : user.name;
8950
9045
  const fieldGroups = groupFields(fields);
8951
- return /* @__PURE__ */ jsxs72("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
8952
- /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 10 }, children: [
8953
- /* @__PURE__ */ jsx84("span", { className: "fd-overline fd-muted", children: "Account" }),
8954
- /* @__PURE__ */ jsx84("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
8955
- /* @__PURE__ */ jsx84("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
9046
+ return /* @__PURE__ */ jsxs73("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 20, maxWidth: 860 }, children: [
9047
+ /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 10 }, children: [
9048
+ /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", children: "Account" }),
9049
+ /* @__PURE__ */ jsx86("h1", { className: "fd-h1", style: { margin: 0 }, children: "Your profile" }),
9050
+ /* @__PURE__ */ jsx86("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: "How you appear to colleagues and clients across every flytedesk app, and what we send you." })
8956
9051
  ] }),
8957
- /* @__PURE__ */ jsx84(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
8958
- /* @__PURE__ */ jsx84(Avatar, { name: displayName, size: "lg" }),
8959
- /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
8960
- /* @__PURE__ */ jsx84("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
8961
- /* @__PURE__ */ jsxs72("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
8962
- roles.map((r) => /* @__PURE__ */ jsx84(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
8963
- user.sso ? /* @__PURE__ */ jsx84(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
9052
+ /* @__PURE__ */ jsx86(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: { gap: 16, flexWrap: "wrap", alignItems: "flex-start" }, children: [
9053
+ /* @__PURE__ */ jsx86(Avatar, { name: displayName, size: "lg" }),
9054
+ /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 4, flex: 1, minWidth: 200 }, children: [
9055
+ /* @__PURE__ */ jsx86("span", { className: "fd-h3", style: { margin: 0 }, children: displayName }),
9056
+ /* @__PURE__ */ jsxs73("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 4 }, children: [
9057
+ roles.map((r) => /* @__PURE__ */ jsx86(Badge, { tone: r.id === "owner" ? "success" : "neutral", children: r.name }, r.id)),
9058
+ user.sso ? /* @__PURE__ */ jsx86(Badge, { tone: "info", icon: "shield-check", children: "SSO" }) : null
8964
9059
  ] })
8965
9060
  ] }),
8966
- onChangePhoto ? /* @__PURE__ */ jsx84(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
9061
+ onChangePhoto ? /* @__PURE__ */ jsx86(Button, { variant: "secondary", size: "sm", icon: "image", onClick: onChangePhoto, children: "Change photo" }) : null
8967
9062
  ] }) }),
8968
- fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx84(
9063
+ fieldGroups.map(({ group, description, fields: groupFieldDefs }) => /* @__PURE__ */ jsx86(
8969
9064
  Card,
8970
9065
  {
8971
- title: description ? /* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 2 }, children: [
8972
- /* @__PURE__ */ jsx84("span", { children: group }),
8973
- /* @__PURE__ */ jsx84("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
9066
+ title: description ? /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 2 }, children: [
9067
+ /* @__PURE__ */ jsx86("span", { children: group }),
9068
+ /* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: description })
8974
9069
  ] }) : group,
8975
9070
  elevation: "flat",
8976
- children: /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 14 }, children: [
8977
- /* @__PURE__ */ jsx84("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
9071
+ children: /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 14 }, children: [
9072
+ /* @__PURE__ */ jsx86("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(220px,1fr))", gap: 14 }, children: groupFieldDefs.filter((f) => f.type !== "textarea").map((field) => {
8978
9073
  const help = typeof field.help === "function" ? field.help(user) : field.help;
8979
9074
  const readOnly = field.readOnly || field.type === "readonly";
8980
9075
  if (field.type === "select") {
8981
- return /* @__PURE__ */ jsx84(
9076
+ return /* @__PURE__ */ jsx86(
8982
9077
  Select,
8983
9078
  {
8984
9079
  label: field.label,
@@ -8992,7 +9087,7 @@ function ProfilePage({
8992
9087
  field.key
8993
9088
  );
8994
9089
  }
8995
- return /* @__PURE__ */ jsx84(
9090
+ return /* @__PURE__ */ jsx86(
8996
9091
  Input,
8997
9092
  {
8998
9093
  label: field.label,
@@ -9008,7 +9103,7 @@ function ProfilePage({
9008
9103
  }) }),
9009
9104
  groupFieldDefs.filter((f) => f.type === "textarea").map((field) => {
9010
9105
  const help = typeof field.help === "function" ? field.help(user) : field.help;
9011
- return /* @__PURE__ */ jsx84(
9106
+ return /* @__PURE__ */ jsx86(
9012
9107
  Textarea,
9013
9108
  {
9014
9109
  label: field.label,
@@ -9028,16 +9123,16 @@ function ProfilePage({
9028
9123
  group
9029
9124
  )),
9030
9125
  extra,
9031
- notifications.length > 0 ? /* @__PURE__ */ jsx84(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx84("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx84(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
9032
- /* @__PURE__ */ jsxs72(
9126
+ notifications.length > 0 ? /* @__PURE__ */ jsx86(Card, { title: "Notifications", elevation: "flat", children: /* @__PURE__ */ jsx86("div", { className: "fd-stack", style: { gap: 14 }, children: notifications.map((n) => /* @__PURE__ */ jsx86(Switch, { checked: !!notify[n.key], onChange: () => toggleNotify(n.key), label: n.label, description: n.description }, n.key)) }) }) : null,
9127
+ /* @__PURE__ */ jsxs73(
9033
9128
  Card,
9034
9129
  {
9035
- title: /* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 2 }, children: [
9036
- /* @__PURE__ */ jsx84("span", { children: "Access" }),
9037
- /* @__PURE__ */ jsx84("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
9130
+ title: /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 2 }, children: [
9131
+ /* @__PURE__ */ jsx86("span", { children: "Access" }),
9132
+ /* @__PURE__ */ jsx86("span", { className: "fd-body-sm fd-muted", style: { fontWeight: 400 }, children: "What your roles grant you" })
9038
9133
  ] }),
9039
9134
  elevation: "flat",
9040
- action: /* @__PURE__ */ jsx84(
9135
+ action: /* @__PURE__ */ jsx86(
9041
9136
  Button,
9042
9137
  {
9043
9138
  size: "sm",
@@ -9048,39 +9143,39 @@ function ProfilePage({
9048
9143
  }
9049
9144
  ),
9050
9145
  children: [
9051
- /* @__PURE__ */ jsxs72("div", { className: "fd-stack", style: { gap: 0 }, children: [
9052
- /* @__PURE__ */ jsx84(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
9053
- /* @__PURE__ */ jsxs72(CardRow, { label: "Permissions", children: [
9146
+ /* @__PURE__ */ jsxs73("div", { className: "fd-stack", style: { gap: 0 }, children: [
9147
+ /* @__PURE__ */ jsx86(CardRow, { label: "Roles", children: roles.map((r) => r.name).join(", ") || "None" }),
9148
+ /* @__PURE__ */ jsxs73(CardRow, { label: "Permissions", children: [
9054
9149
  permissions.length,
9055
9150
  " granted"
9056
9151
  ] }),
9057
- /* @__PURE__ */ jsx84(CardRow, { label: "Member since", children: user.joined || "\u2014" })
9152
+ /* @__PURE__ */ jsx86(CardRow, { label: "Member since", children: user.joined || "\u2014" })
9058
9153
  ] }),
9059
- /* @__PURE__ */ jsx84("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
9154
+ /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-muted", style: { margin: "12px 0 0" }, children: "You cannot change your own roles \u2014 that is the point of them. An administrator manages roles from Admin \u2192 Users." })
9060
9155
  ]
9061
9156
  }
9062
9157
  ),
9063
- sessions ? /* @__PURE__ */ jsx84(
9158
+ sessions ? /* @__PURE__ */ jsx86(
9064
9159
  Card,
9065
9160
  {
9066
9161
  title: "Signed-in devices",
9067
9162
  elevation: "flat",
9068
- action: /* @__PURE__ */ jsx84(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
9069
- children: /* @__PURE__ */ jsx84("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx84("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
9070
- /* @__PURE__ */ jsx84("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
9071
- /* @__PURE__ */ jsxs72("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
9072
- /* @__PURE__ */ jsx84("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
9073
- /* @__PURE__ */ jsxs72("span", { className: "fd-body-sm fd-muted", children: [
9163
+ action: /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", icon: "sign-out", onClick: onSignOutEverywhere, children: "Sign out everywhere" }),
9164
+ children: /* @__PURE__ */ jsx86("div", { className: "fd-stack", style: { gap: 0 }, children: sessions.length === 0 ? /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: "No other signed-in devices." }) : sessions.map((s) => /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: { gap: 12, padding: "10px 0", borderTop: "1px solid var(--border)", flexWrap: "wrap" }, children: [
9165
+ /* @__PURE__ */ jsx86("i", { className: "ph ph-device-mobile", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
9166
+ /* @__PURE__ */ jsxs73("span", { className: "fd-stack", style: { gap: 1, flex: 1, minWidth: 160 }, children: [
9167
+ /* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { fontWeight: 600 }, children: s.device }),
9168
+ /* @__PURE__ */ jsxs73("span", { className: "fd-body-sm fd-muted", children: [
9074
9169
  s.where,
9075
9170
  " \xB7 ",
9076
9171
  s.when
9077
9172
  ] })
9078
9173
  ] }),
9079
- s.current ? /* @__PURE__ */ jsx84(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx84(Button, { size: "sm", variant: "ghost", children: "Revoke" })
9174
+ s.current ? /* @__PURE__ */ jsx86(Badge, { tone: "success", dot: true, children: "This device" }) : /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", children: "Revoke" })
9080
9175
  ] }, s.id)) })
9081
9176
  }
9082
9177
  ) : null,
9083
- /* @__PURE__ */ jsxs72("div", { className: "fd-row", style: {
9178
+ /* @__PURE__ */ jsxs73("div", { className: "fd-row", style: {
9084
9179
  gap: 10,
9085
9180
  flexWrap: "wrap",
9086
9181
  position: "sticky",
@@ -9091,16 +9186,16 @@ function ProfilePage({
9091
9186
  border: "1px solid var(--border)",
9092
9187
  boxShadow: "0 -4px 16px rgba(11,13,17,.06)"
9093
9188
  }, children: [
9094
- /* @__PURE__ */ jsx84("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
9095
- /* @__PURE__ */ jsx84(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
9096
- /* @__PURE__ */ jsx84(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
9189
+ /* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { fontWeight: 600, flex: 1 }, children: saved ? "Saved." : dirty ? "Unsaved changes" : "No pending changes" }),
9190
+ /* @__PURE__ */ jsx86(Button, { size: "sm", variant: "ghost", disabled: !dirty || saving, onClick: discard, children: "Discard" }),
9191
+ /* @__PURE__ */ jsx86(Button, { size: "sm", icon: "check", disabled: !dirty || !canSave, loading: saving, onClick: save, children: "Save changes" })
9097
9192
  ] })
9098
9193
  ] });
9099
9194
  }
9100
9195
 
9101
9196
  // src/components/platform/SessionScreen.tsx
9102
- import * as React61 from "react";
9103
- import { Fragment as Fragment22, jsx as jsx85, jsxs as jsxs73 } from "react/jsx-runtime";
9197
+ import * as React62 from "react";
9198
+ import { Fragment as Fragment22, jsx as jsx87, jsxs as jsxs74 } from "react/jsx-runtime";
9104
9199
  var COPY = {
9105
9200
  "signing-in": { busy: "Signing you in\u2026" },
9106
9201
  "session-expired": { busy: "Your session expired \u2014 signing you back in\u2026" },
@@ -9113,28 +9208,28 @@ function SessionScreen({ kind, error, onRetry, productName }) {
9113
9208
  const copy = COPY[kind];
9114
9209
  const busyMessage = "busy" in copy ? copy.busy : null;
9115
9210
  const failureTitle = "failure" in copy ? copy.failure : null;
9116
- const [announced, setAnnounced] = React61.useState("");
9117
- React61.useEffect(() => {
9211
+ const [announced, setAnnounced] = React62.useState("");
9212
+ React62.useEffect(() => {
9118
9213
  setAnnounced(busyMessage ?? "");
9119
9214
  }, [busyMessage]);
9120
- const titleRef = React61.useRef(null);
9215
+ const titleRef = React62.useRef(null);
9121
9216
  const failed = failureTitle !== null;
9122
- React61.useEffect(() => {
9217
+ React62.useEffect(() => {
9123
9218
  titleRef.current?.focus({ preventScroll: true });
9124
9219
  }, [failed]);
9125
- return /* @__PURE__ */ jsx85("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs73("div", { className: "fd-session-screen-inner", children: [
9126
- /* @__PURE__ */ jsx85("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx85(FlytedeskMark, { size: "lg" }) }),
9127
- /* @__PURE__ */ jsxs73("div", { className: "fd-session-screen-frame", children: [
9128
- /* @__PURE__ */ jsx85("div", { className: "fd-session-screen-stripe" }),
9129
- /* @__PURE__ */ jsx85(Card, { children: /* @__PURE__ */ jsxs73("div", { className: "fd-session-screen-body", children: [
9130
- /* @__PURE__ */ jsx85("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
9131
- /* @__PURE__ */ jsx85("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs73(Fragment22, { children: [
9132
- /* @__PURE__ */ jsx85("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
9133
- /* @__PURE__ */ jsx85("p", { className: "fd-body fd-session-screen-message", children: announced })
9220
+ return /* @__PURE__ */ jsx87("main", { className: "fd-session-screen", children: /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-inner", children: [
9221
+ /* @__PURE__ */ jsx87("div", { className: "fd-session-screen-mark", "data-theme": "dark", children: /* @__PURE__ */ jsx87(FlytedeskMark, { size: "lg" }) }),
9222
+ /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-frame", children: [
9223
+ /* @__PURE__ */ jsx87("div", { className: "fd-session-screen-stripe" }),
9224
+ /* @__PURE__ */ jsx87(Card, { children: /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-body", children: [
9225
+ /* @__PURE__ */ jsx87("h1", { ref: titleRef, tabIndex: -1, className: "fd-h3 fd-session-screen-title", children: productName }),
9226
+ /* @__PURE__ */ jsx87("div", { role: "status", "aria-live": "polite", className: "fd-session-screen-status", children: busyMessage !== null ? /* @__PURE__ */ jsxs74(Fragment22, { children: [
9227
+ /* @__PURE__ */ jsx87("span", { className: "fd-spinner fd-spinner-lg fd-session-screen-spinner", "aria-hidden": "true" }),
9228
+ /* @__PURE__ */ jsx87("p", { className: "fd-body fd-session-screen-message", children: announced })
9134
9229
  ] }) : null }),
9135
- failureTitle !== null ? /* @__PURE__ */ jsxs73("div", { className: "fd-session-screen-failure", children: [
9136
- /* @__PURE__ */ jsx85(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
9137
- onRetry !== null ? /* @__PURE__ */ jsx85(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
9230
+ failureTitle !== null ? /* @__PURE__ */ jsxs74("div", { className: "fd-session-screen-failure", children: [
9231
+ /* @__PURE__ */ jsx87(Banner, { tone: "danger", title: failureTitle, detail: error ?? void 0 }),
9232
+ onRetry !== null ? /* @__PURE__ */ jsx87(Button, { variant: "primary", block: true, onClick: onRetry, children: "Try again" }) : null
9138
9233
  ] }) : null
9139
9234
  ] }) })
9140
9235
  ] })
@@ -9142,10 +9237,10 @@ function SessionScreen({ kind, error, onRetry, productName }) {
9142
9237
  }
9143
9238
 
9144
9239
  // src/components/platform/RoadmapTimeline.tsx
9145
- import * as React64 from "react";
9240
+ import * as React65 from "react";
9146
9241
 
9147
9242
  // src/kits/session.ts
9148
- import * as React62 from "react";
9243
+ import * as React63 from "react";
9149
9244
  var PERMISSION_CATALOG = [
9150
9245
  { group: "Plans", items: [
9151
9246
  { key: "plan.view", label: "View plans", detail: "Read any plan in the workspace." },
@@ -10712,8 +10807,8 @@ function roadmap(overrides) {
10712
10807
  };
10713
10808
  }
10714
10809
  function useSession() {
10715
- const [s, setS] = React62.useState(getSession);
10716
- React62.useEffect(() => subscribe(setS), []);
10810
+ const [s, setS] = React63.useState(getSession);
10811
+ React63.useEffect(() => subscribe(setS), []);
10717
10812
  return s;
10718
10813
  }
10719
10814
  var SessionKit = {
@@ -10746,7 +10841,7 @@ var SessionKit = {
10746
10841
  };
10747
10842
  function DemoSessionProvider({ children }) {
10748
10843
  const session = useSession();
10749
- const value = React62.useMemo(
10844
+ const value = React63.useMemo(
10750
10845
  () => ({
10751
10846
  user: session.user,
10752
10847
  roles: session.roles,
@@ -10762,11 +10857,11 @@ function DemoSessionProvider({ children }) {
10762
10857
  }),
10763
10858
  [session]
10764
10859
  );
10765
- return React62.createElement(SessionProvider, { value }, children);
10860
+ return React63.createElement(SessionProvider, { value }, children);
10766
10861
  }
10767
10862
 
10768
10863
  // src/kits/runtime.ts
10769
- import * as React63 from "react";
10864
+ import * as React64 from "react";
10770
10865
  var WIRED_ENDPOINTS = [
10771
10866
  // Nothing yet. Every id below would come from a real service:
10772
10867
  // "plan.get", "placements.list", …
@@ -10937,8 +11032,8 @@ var RuntimeKit = {
10937
11032
  };
10938
11033
  RuntimeKit.declare(FEATURE_NEEDS);
10939
11034
  function useRuntimeMode() {
10940
- const [m, setM] = React63.useState(RuntimeKit.getMode());
10941
- React63.useEffect(() => RuntimeKit.subscribe(setM), []);
11035
+ const [m, setM] = React64.useState(RuntimeKit.getMode());
11036
+ React64.useEffect(() => RuntimeKit.subscribe(setM), []);
10942
11037
  return m;
10943
11038
  }
10944
11039
  function useFeatureStatus(key) {
@@ -10957,7 +11052,7 @@ var UseRuntimeMode = useRuntimeMode;
10957
11052
  var UseFeatureStatus = useFeatureStatus;
10958
11053
 
10959
11054
  // src/components/platform/RoadmapTimeline.tsx
10960
- import { jsx as jsx86, jsxs as jsxs74 } from "react/jsx-runtime";
11055
+ import { jsx as jsx88, jsxs as jsxs75 } from "react/jsx-runtime";
10961
11056
  var STATUS = {
10962
11057
  shipped: { tone: "success", icon: "check-circle", label: "Wired" },
10963
11058
  next: { tone: "warning", icon: "traffic-cone", label: "Not wired" },
@@ -10972,45 +11067,45 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
10972
11067
  const s = STATUS[item.status] || STATUS.planned;
10973
11068
  const deps = (item.dependsOn || []).map((k) => byKey[k]).filter(Boolean);
10974
11069
  const blocking = deps.filter((d) => !d.implemented);
10975
- return /* @__PURE__ */ jsx86(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs74("div", { className: "fd-stack", style: { gap: 10 }, children: [
10976
- /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
10977
- /* @__PURE__ */ jsx86("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
10978
- /* @__PURE__ */ jsx86(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
10979
- /* @__PURE__ */ jsx86(Badge, { tone: s.tone, icon: s.icon, children: s.label })
11070
+ return /* @__PURE__ */ jsx88(Card, { elevation: "flat", children: /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 10 }, children: [
11071
+ /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: [
11072
+ /* @__PURE__ */ jsx88("span", { className: "fd-body", style: { fontWeight: 700, flex: 1, minWidth: 140 }, children: item.label }),
11073
+ /* @__PURE__ */ jsx88(Badge, { tone: "neutral", icon: PROJECT_ICON[item.project] || "squares-four", children: item.project }),
11074
+ /* @__PURE__ */ jsx88(Badge, { tone: s.tone, icon: s.icon, children: s.label })
10980
11075
  ] }),
10981
- /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
10982
- item.backend ? /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
10983
- /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
10984
- /* @__PURE__ */ jsx86("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
11076
+ /* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: item.description }),
11077
+ item.backend ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, alignItems: "flex-start" }, children: [
11078
+ /* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", style: { width: 62, flex: "none", paddingTop: 2 }, children: "Backend" }),
11079
+ /* @__PURE__ */ jsx88("span", { className: "fd-body-sm", style: { flex: 1, textWrap: "pretty" }, children: item.backend })
10985
11080
  ] }) : null,
10986
- /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
10987
- item.effort ? /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm fd-muted", children: [
10988
- /* @__PURE__ */ jsx86("i", { className: "ph ph-hourglass-medium" }),
11081
+ /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
11082
+ item.effort ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", children: [
11083
+ /* @__PURE__ */ jsx88("i", { className: "ph ph-hourglass-medium" }),
10989
11084
  " ",
10990
11085
  item.effort
10991
11086
  ] }) : null,
10992
- /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm fd-muted", children: [
10993
- /* @__PURE__ */ jsx86("i", { className: "ph ph-user" }),
11087
+ /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm fd-muted", children: [
11088
+ /* @__PURE__ */ jsx88("i", { className: "ph ph-user" }),
10994
11089
  " ",
10995
11090
  item.owner
10996
11091
  ] }),
10997
- item.screen ? /* @__PURE__ */ jsx86(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
10998
- /* @__PURE__ */ jsx86("span", { style: { flex: 1 } }),
10999
- /* @__PURE__ */ jsx86(
11092
+ item.screen ? /* @__PURE__ */ jsx88(Badge, { tone: "neutral", icon: "browser", children: "screen" }) : null,
11093
+ /* @__PURE__ */ jsx88("span", { style: { flex: 1 } }),
11094
+ /* @__PURE__ */ jsx88(
11000
11095
  "button",
11001
11096
  {
11002
11097
  type: "button",
11003
11098
  onClick: () => onOpenFlag && onOpenFlag(item.key),
11004
11099
  style: { all: "unset", cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 5 },
11005
- children: /* @__PURE__ */ jsx86("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
11100
+ children: /* @__PURE__ */ jsx88("code", { className: "fd-mono", style: { fontSize: 11, color: "var(--brand)" }, children: item.key })
11006
11101
  }
11007
11102
  )
11008
11103
  ] }),
11009
- deps.length ? /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
11010
- /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
11011
- deps.map((d) => /* @__PURE__ */ jsx86(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
11104
+ deps.length ? /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 6, flexWrap: "wrap", paddingTop: 6, borderTop: "1px solid var(--border)" }, children: [
11105
+ /* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", style: { paddingTop: 3 }, children: "After" }),
11106
+ deps.map((d) => /* @__PURE__ */ jsx88(Tag, { icon: d.implemented ? "check" : "clock", children: d.label }, d.key))
11012
11107
  ] }) : null,
11013
- blocking.length && !item.implemented ? /* @__PURE__ */ jsxs74("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
11108
+ blocking.length && !item.implemented ? /* @__PURE__ */ jsxs75("span", { className: "fd-body-sm", style: { color: "var(--warn-text)" }, children: [
11014
11109
  "Blocked until ",
11015
11110
  blocking.map((d) => d.label).join(" and "),
11016
11111
  " ",
@@ -11021,12 +11116,12 @@ function RoadmapCard({ item, byKey, onOpenFlag }) {
11021
11116
  }
11022
11117
  function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11023
11118
  const session = SessionKit.useSession();
11024
- const [project, setProject] = React64.useState("");
11025
- const [q, setQ] = React64.useState("");
11026
- const scrollRef = React64.useRef(null);
11027
- const nowRef = React64.useRef(null);
11028
- const rm = React64.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
11029
- const byKey = React64.useMemo(() => {
11119
+ const [project, setProject] = React65.useState("");
11120
+ const [q, setQ] = React65.useState("");
11121
+ const scrollRef = React65.useRef(null);
11122
+ const nowRef = React65.useRef(null);
11123
+ const rm = React65.useMemo(() => SessionKit.roadmap({ isComplete: RuntimeKit.isComplete }), [session]);
11124
+ const byKey = React65.useMemo(() => {
11030
11125
  const m = {};
11031
11126
  rm.items.forEach((i) => {
11032
11127
  m[i.key] = i;
@@ -11035,7 +11130,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11035
11130
  }, [rm]);
11036
11131
  const items = rm.items.filter((i) => (!project || i.project === project) && (!q || (i.label + " " + i.description + " " + (i.backend || "") + " " + i.key).toLowerCase().includes(q.toLowerCase())));
11037
11132
  const projects = [...new Set(rm.items.map((i) => i.project))];
11038
- React64.useEffect(() => {
11133
+ React65.useEffect(() => {
11039
11134
  let raf1 = 0, raf2 = 0;
11040
11135
  const place = () => {
11041
11136
  const box = scrollRef.current, mark = nowRef.current;
@@ -11063,23 +11158,23 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11063
11158
  }, 0);
11064
11159
  const nextPhase = items.find((i) => !i.implemented);
11065
11160
  let lastPhase = null;
11066
- return /* @__PURE__ */ jsxs74("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
11067
- /* @__PURE__ */ jsxs74("div", { className: "fd-stack", style: { gap: 10 }, children: [
11068
- /* @__PURE__ */ jsx86("span", { className: "fd-overline fd-muted", children: "Architecture" }),
11069
- /* @__PURE__ */ jsx86("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
11070
- /* @__PURE__ */ jsx86("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
11161
+ return /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 16, maxWidth: 1e3 }, children: [
11162
+ /* @__PURE__ */ jsxs75("div", { className: "fd-stack", style: { gap: 10 }, children: [
11163
+ /* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", children: "Architecture" }),
11164
+ /* @__PURE__ */ jsx88("h1", { className: "fd-h1", style: { margin: 0 }, children: title }),
11165
+ /* @__PURE__ */ jsx88("p", { className: "fd-body fd-secondary fd-prose", style: { margin: 0 }, children: lede || "Every screen and feature in these tools is already designed and working against a simulated backend. This is the plan for connecting them to the real one \u2014 so the only work described here is server work." })
11071
11166
  ] }),
11072
- /* @__PURE__ */ jsxs74("div", { className: "fd-grid-stats is-thin", children: [
11073
- /* @__PURE__ */ jsx86(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
11074
- /* @__PURE__ */ jsx86(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
11075
- /* @__PURE__ */ jsx86(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
11076
- /* @__PURE__ */ jsx86(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
11167
+ /* @__PURE__ */ jsxs75("div", { className: "fd-grid-stats is-thin", children: [
11168
+ /* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Wired", value: String(rm.shipped), sub: "of " + rm.items.length + " features" }),
11169
+ /* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Remaining", value: String(rm.remaining), sub: "backend work" }),
11170
+ /* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Est. effort", value: days ? days + " days" : "\u2014", sub: "sum of estimates, not calendar" }),
11171
+ /* @__PURE__ */ jsx88(StatTile, { compact: true, label: "Up next", value: nextPhase ? "Phase " + nextPhase.phase : "\u2014", sub: nextPhase ? nextPhase.phaseName : "all wired" })
11077
11172
  ] }),
11078
- /* @__PURE__ */ jsxs74("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
11079
- /* @__PURE__ */ jsx86(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
11080
- /* @__PURE__ */ jsx86(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
11081
- /* @__PURE__ */ jsx86("span", { style: { flex: 1 } }),
11082
- /* @__PURE__ */ jsx86(
11173
+ /* @__PURE__ */ jsxs75("div", { className: "fd-row", style: { gap: 10, flexWrap: "wrap" }, children: [
11174
+ /* @__PURE__ */ jsx88(Input, { icon: "magnifying-glass", placeholder: "Find a feature or a piece of backend work", value: q, onChange: (e) => setQ(e.target.value), style: { width: 300 } }),
11175
+ /* @__PURE__ */ jsx88(Select, { placeholder: "All projects", value: project, onChange: (e) => setProject(e.target.value), options: projects, style: { width: 190 } }),
11176
+ /* @__PURE__ */ jsx88("span", { style: { flex: 1 } }),
11177
+ /* @__PURE__ */ jsx88(
11083
11178
  Button,
11084
11179
  {
11085
11180
  size: "sm",
@@ -11093,7 +11188,7 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11093
11188
  }
11094
11189
  )
11095
11190
  ] }),
11096
- /* @__PURE__ */ jsx86(
11191
+ /* @__PURE__ */ jsx88(
11097
11192
  Flag,
11098
11193
  {
11099
11194
  tone: "info",
@@ -11102,60 +11197,60 @@ function RoadmapTimeline({ onOpenFlag, title = "Roadmap", lede }) {
11102
11197
  actions: null
11103
11198
  }
11104
11199
  ),
11105
- /* @__PURE__ */ jsx86("div", { className: "fd-rm", children: /* @__PURE__ */ jsx86("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs74("div", { className: "fd-rm-track", children: [
11106
- /* @__PURE__ */ jsx86("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx86("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
11200
+ /* @__PURE__ */ jsx88("div", { className: "fd-rm", children: /* @__PURE__ */ jsx88("div", { className: "fd-rm-scroll", ref: scrollRef, children: /* @__PURE__ */ jsxs75("div", { className: "fd-rm-track", children: [
11201
+ /* @__PURE__ */ jsx88("span", { className: "fd-rm-spine", children: /* @__PURE__ */ jsx88("span", { className: "fd-rm-spine-done", style: { height: items.length ? 100 * shippedShown / items.length + "%" : "0%" } }) }),
11107
11202
  items.map((item, n) => {
11108
11203
  const showPhase = item.phase !== lastPhase;
11109
11204
  lastPhase = item.phase;
11110
11205
  const inPhase = items.filter((i) => i.phase === item.phase).length;
11111
11206
  const isBoundary = n === firstPending;
11112
- return /* @__PURE__ */ jsxs74(React64.Fragment, { children: [
11113
- showPhase ? /* @__PURE__ */ jsxs74("div", { className: "fd-rm-era", children: [
11114
- /* @__PURE__ */ jsxs74("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
11115
- /* @__PURE__ */ jsx86("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
11116
- item.phase === 0 ? null : /* @__PURE__ */ jsxs74("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
11207
+ return /* @__PURE__ */ jsxs75(React65.Fragment, { children: [
11208
+ showPhase ? /* @__PURE__ */ jsxs75("div", { className: "fd-rm-era", children: [
11209
+ /* @__PURE__ */ jsxs75("span", { className: "fd-row", style: { gap: 8, flexWrap: "wrap", alignItems: "baseline" }, children: [
11210
+ /* @__PURE__ */ jsx88("span", { style: { fontWeight: 700 }, children: item.phase === 0 ? "Shipped" : "Phase " + item.phase + " \u2014 " + item.phaseName }),
11211
+ item.phase === 0 ? null : /* @__PURE__ */ jsxs75("span", { className: "fd-mono", style: { opacity: 0.7, fontWeight: 400 }, children: [
11117
11212
  fmtDate(item.phaseStart),
11118
11213
  " \u2013 ",
11119
11214
  fmtDate(item.date)
11120
11215
  ] }),
11121
- /* @__PURE__ */ jsxs74("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
11216
+ /* @__PURE__ */ jsxs75("span", { style: { opacity: 0.7, fontWeight: 400 }, children: [
11122
11217
  "\xB7 ",
11123
11218
  inPhase,
11124
11219
  " feature",
11125
11220
  inPhase === 1 ? "" : "s"
11126
11221
  ] })
11127
11222
  ] }),
11128
- item.phaseWhy ? /* @__PURE__ */ jsx86("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
11223
+ item.phaseWhy ? /* @__PURE__ */ jsx88("p", { className: "fd-rm-era-why", children: item.phaseWhy }) : null
11129
11224
  ] }) : null,
11130
- isBoundary ? /* @__PURE__ */ jsx86("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs74("span", { className: "fd-rm-now-pill", children: [
11131
- /* @__PURE__ */ jsx86("i", { className: "ph ph-map-pin" }),
11225
+ isBoundary ? /* @__PURE__ */ jsx88("div", { className: "fd-rm-now", ref: nowRef, children: /* @__PURE__ */ jsxs75("span", { className: "fd-rm-now-pill", children: [
11226
+ /* @__PURE__ */ jsx88("i", { className: "ph ph-map-pin" }),
11132
11227
  " You are here \u2014 everything above is wired"
11133
11228
  ] }) }) : null,
11134
- /* @__PURE__ */ jsxs74("div", { className: "fd-rm-row", children: [
11135
- /* @__PURE__ */ jsx86("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
11136
- /* @__PURE__ */ jsxs74("div", { className: "fd-rm-date", children: [
11229
+ /* @__PURE__ */ jsxs75("div", { className: "fd-rm-row", children: [
11230
+ /* @__PURE__ */ jsx88("span", { className: "fd-rm-dot " + (item.implemented ? "is-shipped" : item.status === "next" ? "is-next" : "") }),
11231
+ /* @__PURE__ */ jsxs75("div", { className: "fd-rm-date", children: [
11137
11232
  fmtDate(item.date),
11138
- /* @__PURE__ */ jsx86("br", {}),
11139
- /* @__PURE__ */ jsx86("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
11233
+ /* @__PURE__ */ jsx88("br", {}),
11234
+ /* @__PURE__ */ jsx88("span", { style: { opacity: 0.75 }, children: item.implemented ? "shipped" : "phase " + item.phase })
11140
11235
  ] }),
11141
- /* @__PURE__ */ jsx86(RoadmapCard, { item, byKey, onOpenFlag })
11236
+ /* @__PURE__ */ jsx88(RoadmapCard, { item, byKey, onOpenFlag })
11142
11237
  ] })
11143
11238
  ] }, item.key);
11144
11239
  }),
11145
- !items.length ? /* @__PURE__ */ jsx86("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
11240
+ !items.length ? /* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-muted", children: "Nothing matches that filter." }) : null
11146
11241
  ] }) }) }),
11147
- /* @__PURE__ */ jsxs74("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
11242
+ /* @__PURE__ */ jsxs75("p", { className: "fd-body-sm fd-muted", style: { margin: 0 }, children: [
11148
11243
  "Derived from the feature-flag registry \u2014 each entry's status is its flag's ",
11149
- /* @__PURE__ */ jsx86("code", { className: "fd-mono", children: "implemented" }),
11244
+ /* @__PURE__ */ jsx88("code", { className: "fd-mono", children: "implemented" }),
11150
11245
  " field, so this page cannot drift from what the apps actually do."
11151
11246
  ] })
11152
11247
  ] });
11153
11248
  }
11154
11249
 
11155
11250
  // src/components/platform/ComingSoon.tsx
11156
- import * as React65 from "react";
11251
+ import * as React66 from "react";
11157
11252
  import { createPortal as createPortal6 } from "react-dom";
11158
- import { Fragment as Fragment24, jsx as jsx87, jsxs as jsxs75 } from "react/jsx-runtime";
11253
+ import { Fragment as Fragment24, jsx as jsx89, jsxs as jsxs76 } from "react/jsx-runtime";
11159
11254
  var BYPASS_STORE = "fd.soon.bypass.v1";
11160
11255
  function readBypassed() {
11161
11256
  try {
@@ -11171,8 +11266,8 @@ function writeBypassed(list) {
11171
11266
  }
11172
11267
  }
11173
11268
  function useBypass(key) {
11174
- const [on, setOn] = React65.useState(() => !!key && readBypassed().indexOf(key) >= 0);
11175
- React65.useEffect(() => {
11269
+ const [on, setOn] = React66.useState(() => !!key && readBypassed().indexOf(key) >= 0);
11270
+ React66.useEffect(() => {
11176
11271
  setOn(!!key && readBypassed().indexOf(key) >= 0);
11177
11272
  }, [key]);
11178
11273
  const set = (next) => {
@@ -11185,43 +11280,43 @@ function useBypass(key) {
11185
11280
  return [on, set];
11186
11281
  }
11187
11282
  function SoonCard({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass }) {
11188
- return /* @__PURE__ */ jsxs75(Fragment24, { children: [
11189
- /* @__PURE__ */ jsxs75("span", { className: "fd-soon-badge", children: [
11190
- /* @__PURE__ */ jsx87("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
11283
+ return /* @__PURE__ */ jsxs76(Fragment24, { children: [
11284
+ /* @__PURE__ */ jsxs76("span", { className: "fd-soon-badge", children: [
11285
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
11191
11286
  label
11192
11287
  ] }),
11193
- detail ? /* @__PURE__ */ jsx87("span", { className: "fd-soon-detail", children: detail }) : null,
11194
- backend ? /* @__PURE__ */ jsxs75("span", { className: "fd-soon-backend", children: [
11195
- /* @__PURE__ */ jsx87("span", { className: "fd-overline", children: "Needs" }),
11288
+ detail ? /* @__PURE__ */ jsx89("span", { className: "fd-soon-detail", children: detail }) : null,
11289
+ backend ? /* @__PURE__ */ jsxs76("span", { className: "fd-soon-backend", children: [
11290
+ /* @__PURE__ */ jsx89("span", { className: "fd-overline", children: "Needs" }),
11196
11291
  " ",
11197
11292
  backend
11198
11293
  ] }) : null,
11199
- eta || effort || onRoadmap ? /* @__PURE__ */ jsxs75("span", { className: "fd-soon-meta", children: [
11200
- eta ? /* @__PURE__ */ jsxs75("span", { children: [
11201
- /* @__PURE__ */ jsx87("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
11294
+ eta || effort || onRoadmap ? /* @__PURE__ */ jsxs76("span", { className: "fd-soon-meta", children: [
11295
+ eta ? /* @__PURE__ */ jsxs76("span", { children: [
11296
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-calendar-blank", "aria-hidden": "true" }),
11202
11297
  " ",
11203
11298
  eta
11204
11299
  ] }) : null,
11205
- effort ? /* @__PURE__ */ jsxs75("span", { children: [
11206
- /* @__PURE__ */ jsx87("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
11300
+ effort ? /* @__PURE__ */ jsxs76("span", { children: [
11301
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-hourglass-medium", "aria-hidden": "true" }),
11207
11302
  " ",
11208
11303
  effort
11209
11304
  ] }) : null,
11210
- onRoadmap ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
11305
+ onRoadmap ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
11211
11306
  "See the roadmap ",
11212
- /* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11307
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11213
11308
  ] }) : null
11214
11309
  ] }) : null,
11215
- allowed ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
11216
- /* @__PURE__ */ jsx87("i", { className: "ph ph-eye", "aria-hidden": "true" }),
11310
+ allowed ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-view", onClick: onBypass, children: [
11311
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-eye", "aria-hidden": "true" }),
11217
11312
  " View and use it anyway"
11218
11313
  ] }) : null
11219
11314
  ] });
11220
11315
  }
11221
11316
  function useHoverCard(open2) {
11222
- const anchor = React65.useRef(null);
11223
- const [pos, setPos] = React65.useState(null);
11224
- React65.useLayoutEffect(() => {
11317
+ const anchor = React66.useRef(null);
11318
+ const [pos, setPos] = React66.useState(null);
11319
+ React66.useLayoutEffect(() => {
11225
11320
  if (!open2 || !anchor.current) {
11226
11321
  setPos(null);
11227
11322
  return;
@@ -11273,9 +11368,9 @@ function ComingSoon({
11273
11368
  const tip = [label, detail, backend ? "Needs " + backend : null, eta ? "ETA " + eta : null, effort].filter(Boolean).join(" \xB7 ");
11274
11369
  if (inline) {
11275
11370
  if (allowed && bypassed) {
11276
- return /* @__PURE__ */ jsxs75("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
11371
+ return /* @__PURE__ */ jsxs76("span", { className: ["fd-soon-inline-on", className].filter(Boolean).join(" "), ...rest, children: [
11277
11372
  children,
11278
- /* @__PURE__ */ jsx87(
11373
+ /* @__PURE__ */ jsx89(
11279
11374
  "button",
11280
11375
  {
11281
11376
  type: "button",
@@ -11283,12 +11378,12 @@ function ComingSoon({
11283
11378
  title: "Unwired \u2014 writes go to the simulated backend. " + tip + " Click to re-blur.",
11284
11379
  onClick: () => setBypassed(false),
11285
11380
  "aria-label": "Re-blur this unwired feature",
11286
- children: /* @__PURE__ */ jsx87("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11381
+ children: /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11287
11382
  }
11288
11383
  )
11289
11384
  ] });
11290
11385
  }
11291
- return /* @__PURE__ */ jsx87(
11386
+ return /* @__PURE__ */ jsx89(
11292
11387
  InlineSoon,
11293
11388
  {
11294
11389
  label,
@@ -11308,20 +11403,20 @@ function ComingSoon({
11308
11403
  );
11309
11404
  }
11310
11405
  if (allowed && bypassed) {
11311
- return /* @__PURE__ */ jsxs75("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
11312
- /* @__PURE__ */ jsxs75("div", { className: "fd-soon-bar", role: "status", children: [
11313
- /* @__PURE__ */ jsxs75("span", { className: "fd-soon-badge", children: [
11314
- /* @__PURE__ */ jsx87("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
11406
+ return /* @__PURE__ */ jsxs76("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, ...rest, children: [
11407
+ /* @__PURE__ */ jsxs76("div", { className: "fd-soon-bar", role: "status", children: [
11408
+ /* @__PURE__ */ jsxs76("span", { className: "fd-soon-badge", children: [
11409
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" }),
11315
11410
  "Unwired feature \u2014 you are using it anyway"
11316
11411
  ] }),
11317
- /* @__PURE__ */ jsx87("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
11318
- /* @__PURE__ */ jsxs75("span", { className: "fd-soon-bar-actions", children: [
11319
- onRoadmap ? /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
11412
+ /* @__PURE__ */ jsx89("span", { className: "fd-soon-bar-detail", children: "Every action here writes to the simulated backend, so nothing you do persists beyond this session." }),
11413
+ /* @__PURE__ */ jsxs76("span", { className: "fd-soon-bar-actions", children: [
11414
+ onRoadmap ? /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: onRoadmap, children: [
11320
11415
  "Roadmap ",
11321
- /* @__PURE__ */ jsx87("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11416
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11322
11417
  ] }) : null,
11323
- /* @__PURE__ */ jsxs75("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
11324
- /* @__PURE__ */ jsx87("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
11418
+ /* @__PURE__ */ jsxs76("button", { type: "button", className: "fd-soon-link", onClick: () => setBypassed(false), children: [
11419
+ /* @__PURE__ */ jsx89("i", { className: "ph ph-eye-slash", "aria-hidden": "true" }),
11325
11420
  " Re-blur"
11326
11421
  ] })
11327
11422
  ] })
@@ -11329,10 +11424,10 @@ function ComingSoon({
11329
11424
  children
11330
11425
  ] });
11331
11426
  }
11332
- return /* @__PURE__ */ jsxs75("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
11333
- /* @__PURE__ */ jsx87("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11334
- /* @__PURE__ */ jsx87("div", { className: "fd-soon-veil" }),
11335
- /* @__PURE__ */ jsx87("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx87(
11427
+ return /* @__PURE__ */ jsxs76("div", { className: ["fd-soon", className].filter(Boolean).join(" "), style: minHeight ? { minHeight } : void 0, ...rest, children: [
11428
+ /* @__PURE__ */ jsx89("div", { className: "fd-soon-under", style: { filter: "blur(" + blur + "px) saturate(.62)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11429
+ /* @__PURE__ */ jsx89("div", { className: "fd-soon-veil" }),
11430
+ /* @__PURE__ */ jsx89("div", { className: "fd-soon-note", role: "note", children: /* @__PURE__ */ jsx89(
11336
11431
  SoonCard,
11337
11432
  {
11338
11433
  label,
@@ -11348,12 +11443,12 @@ function ComingSoon({
11348
11443
  ] });
11349
11444
  }
11350
11445
  function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, onBypass, blur, tip, className, rest, children }) {
11351
- const [open2, setOpen] = React65.useState(false);
11446
+ const [open2, setOpen] = React66.useState(false);
11352
11447
  const [anchor, pos] = useHoverCard(open2);
11353
- const hoverCardRef = React65.useRef(null);
11448
+ const hoverCardRef = React66.useRef(null);
11354
11449
  const hoverLayer = useStackedLayer({ active: open2, containerRef: hoverCardRef, returnFocus: false });
11355
11450
  const zIndex = useLayerZIndex(hoverLayer);
11356
- const close2 = React65.useRef(null);
11451
+ const close2 = React66.useRef(null);
11357
11452
  const show = () => {
11358
11453
  if (close2.current) {
11359
11454
  clearTimeout(close2.current);
@@ -11369,10 +11464,10 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11369
11464
  setOpen(false);
11370
11465
  }, 140);
11371
11466
  };
11372
- React65.useEffect(() => () => {
11467
+ React66.useEffect(() => () => {
11373
11468
  if (close2.current) clearTimeout(close2.current);
11374
11469
  }, []);
11375
- return /* @__PURE__ */ jsxs75(
11470
+ return /* @__PURE__ */ jsxs76(
11376
11471
  "span",
11377
11472
  {
11378
11473
  ref: anchor,
@@ -11383,8 +11478,8 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11383
11478
  onBlur: hide,
11384
11479
  ...rest,
11385
11480
  children: [
11386
- /* @__PURE__ */ jsx87("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11387
- /* @__PURE__ */ jsx87(
11481
+ /* @__PURE__ */ jsx89("span", { className: "fd-soon-under", style: { filter: "blur(" + Math.min(blur, 1.1) + "px) saturate(.66)" }, ...{ inert: "" }, "aria-hidden": "true", children }),
11482
+ /* @__PURE__ */ jsx89(
11388
11483
  "button",
11389
11484
  {
11390
11485
  type: "button",
@@ -11395,11 +11490,11 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11395
11490
  onFocus: show,
11396
11491
  onBlur: hide,
11397
11492
  onClick: () => open2 ? setOpen(false) : show(),
11398
- children: /* @__PURE__ */ jsx87("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11493
+ children: /* @__PURE__ */ jsx89("i", { className: "ph ph-traffic-cone", "aria-hidden": "true" })
11399
11494
  }
11400
11495
  ),
11401
11496
  open2 && pos ? createPortal6(
11402
- /* @__PURE__ */ jsx87(
11497
+ /* @__PURE__ */ jsx89(
11403
11498
  "div",
11404
11499
  {
11405
11500
  ref: hoverCardRef,
@@ -11408,7 +11503,7 @@ function InlineSoon({ label, detail, backend, eta, effort, onRoadmap, allowed, o
11408
11503
  style: { position: "fixed", left: pos.left, top: pos.top, bottom: pos.bottom, width: pos.width, zIndex },
11409
11504
  onMouseEnter: show,
11410
11505
  onMouseLeave: hide,
11411
- children: /* @__PURE__ */ jsx87(
11506
+ children: /* @__PURE__ */ jsx89(
11412
11507
  SoonCard,
11413
11508
  {
11414
11509
  label,
@@ -11438,10 +11533,10 @@ function formatEta(iso2) {
11438
11533
  var FormatEta = formatEta;
11439
11534
 
11440
11535
  // src/components/platform/Gate.tsx
11441
- import { jsx as jsx88, jsxs as jsxs76 } from "react/jsx-runtime";
11536
+ import { jsx as jsx90, jsxs as jsxs77 } from "react/jsx-runtime";
11442
11537
  function PermissionDenied({ permission, title, detail, compact: compact3 = false, className = "", ...rest }) {
11443
11538
  const need = Array.isArray(permission) ? permission : [permission].filter(Boolean);
11444
- return /* @__PURE__ */ jsxs76(
11539
+ return /* @__PURE__ */ jsxs77(
11445
11540
  "div",
11446
11541
  {
11447
11542
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -11457,14 +11552,14 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
11457
11552
  },
11458
11553
  ...rest,
11459
11554
  children: [
11460
- /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 8 }, children: [
11461
- /* @__PURE__ */ jsx88("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11462
- /* @__PURE__ */ jsx88("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
11555
+ /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8 }, children: [
11556
+ /* @__PURE__ */ jsx90("i", { className: "ph ph-lock-simple", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11557
+ /* @__PURE__ */ jsx90("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: title || "You do not have access to this" })
11463
11558
  ] }),
11464
- /* @__PURE__ */ jsx88("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
11465
- need.length ? /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
11466
- /* @__PURE__ */ jsx88("span", { className: "fd-overline fd-muted", children: "Requires" }),
11467
- need.map((p) => /* @__PURE__ */ jsx88("code", { className: "fd-mono", style: {
11559
+ /* @__PURE__ */ jsx90("p", { className: "fd-body-sm fd-secondary", style: { margin: 0, textWrap: "pretty" }, children: detail || "Your roles do not grant this. An administrator can change that from Admin \u2192 Users." }),
11560
+ need.length ? /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 6, flexWrap: "wrap" }, children: [
11561
+ /* @__PURE__ */ jsx90("span", { className: "fd-overline fd-muted", children: "Requires" }),
11562
+ need.map((p) => /* @__PURE__ */ jsx90("code", { className: "fd-mono", style: {
11468
11563
  fontSize: 11.5,
11469
11564
  padding: "2px 7px",
11470
11565
  borderRadius: 5,
@@ -11477,7 +11572,7 @@ function PermissionDenied({ permission, title, detail, compact: compact3 = false
11477
11572
  );
11478
11573
  }
11479
11574
  function GatePending({ compact: compact3 = false, className = "" }) {
11480
- return /* @__PURE__ */ jsxs76(
11575
+ return /* @__PURE__ */ jsxs77(
11481
11576
  "div",
11482
11577
  {
11483
11578
  className: ["fd-stack", className].filter(Boolean).join(" "),
@@ -11493,11 +11588,11 @@ function GatePending({ compact: compact3 = false, className = "" }) {
11493
11588
  textAlign: "left"
11494
11589
  },
11495
11590
  children: [
11496
- /* @__PURE__ */ jsxs76("span", { className: "fd-row", style: { gap: 8 }, children: [
11497
- /* @__PURE__ */ jsx88("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11498
- /* @__PURE__ */ jsx88("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
11591
+ /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8 }, children: [
11592
+ /* @__PURE__ */ jsx90("i", { className: "ph ph-arrows-clockwise", style: { fontSize: 16, color: "var(--text-muted)" }, "aria-hidden": "true" }),
11593
+ /* @__PURE__ */ jsx90("span", { className: compact3 ? "fd-label-lg" : "fd-h3", children: "Reconnecting\u2026" })
11499
11594
  ] }),
11500
- /* @__PURE__ */ jsx88("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." })
11595
+ /* @__PURE__ */ jsx90("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." })
11501
11596
  ]
11502
11597
  }
11503
11598
  );
@@ -11507,7 +11602,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
11507
11602
  if (pending) {
11508
11603
  if (pendingFallback !== void 0) return pendingFallback;
11509
11604
  if (silent) return null;
11510
- return /* @__PURE__ */ jsx88(GatePending, { compact: compact3 });
11605
+ return /* @__PURE__ */ jsx90(GatePending, { compact: compact3 });
11511
11606
  }
11512
11607
  let ok = true;
11513
11608
  if (perm) ok = ok && can2(perm);
@@ -11516,7 +11611,7 @@ function Gate({ perm, anyOf, role, silent = false, fallback, pendingFallback, co
11516
11611
  if (ok) return children;
11517
11612
  if (fallback !== void 0) return fallback;
11518
11613
  if (silent) return null;
11519
- return /* @__PURE__ */ jsx88(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11614
+ return /* @__PURE__ */ jsx90(PermissionDenied, { permission: perm || anyOf, compact: compact3 });
11520
11615
  }
11521
11616
  function FeatureGate({
11522
11617
  flag,
@@ -11539,7 +11634,7 @@ function FeatureGate({
11539
11634
  const f = SessionKit.findFlag(flag) || {};
11540
11635
  const missing = rt.missing || [];
11541
11636
  const canBypass = pending ? false : bypassPerm === null ? false : !bypassPerm || can2(bypassPerm);
11542
- return /* @__PURE__ */ jsx88(
11637
+ return /* @__PURE__ */ jsx90(
11543
11638
  ComingSoon,
11544
11639
  {
11545
11640
  label: label || (variant === "inline" ? f.label || "Not wired yet" : "Designed \u2014 backend not wired yet"),
@@ -11560,22 +11655,22 @@ function FeatureGate({
11560
11655
  function PermissionHint({ perm, children }) {
11561
11656
  const { can: can2, pending } = useSessionContext();
11562
11657
  if (pending) {
11563
- return /* @__PURE__ */ jsx88("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx88("span", { style: { pointerEvents: "none" }, children }) });
11658
+ return /* @__PURE__ */ jsx90("span", { title: "Access can't be verified right now", style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" }, "aria-disabled": "true", children: /* @__PURE__ */ jsx90("span", { style: { pointerEvents: "none" }, children }) });
11564
11659
  }
11565
11660
  if (can2(perm)) return children;
11566
- return /* @__PURE__ */ jsx88(
11661
+ return /* @__PURE__ */ jsx90(
11567
11662
  "span",
11568
11663
  {
11569
11664
  title: "Requires " + (Array.isArray(perm) ? perm.join(", ") : perm),
11570
11665
  style: { display: "inline-flex", opacity: 0.45, cursor: "not-allowed" },
11571
11666
  "aria-disabled": "true",
11572
- children: /* @__PURE__ */ jsx88("span", { style: { pointerEvents: "none" }, children })
11667
+ children: /* @__PURE__ */ jsx90("span", { style: { pointerEvents: "none" }, children })
11573
11668
  }
11574
11669
  );
11575
11670
  }
11576
11671
 
11577
11672
  // src/components/platform/ModeSwitch.tsx
11578
- import { Fragment as Fragment25, jsx as jsx89, jsxs as jsxs77 } from "react/jsx-runtime";
11673
+ import { Fragment as Fragment25, jsx as jsx91, jsxs as jsxs78 } from "react/jsx-runtime";
11579
11674
  function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog, onOpenSpec, summary }) {
11580
11675
  const mode2 = useRuntimeMode();
11581
11676
  const panel = useInlinePanel();
@@ -11587,8 +11682,8 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11587
11682
  RuntimeKit.setMode(next);
11588
11683
  setOpen(false);
11589
11684
  };
11590
- return /* @__PURE__ */ jsxs77("span", { style: { display: "inline-flex" }, ref, children: [
11591
- /* @__PURE__ */ jsxs77(
11685
+ return /* @__PURE__ */ jsxs78("span", { style: { display: "inline-flex" }, ref, children: [
11686
+ /* @__PURE__ */ jsxs78(
11592
11687
  "button",
11593
11688
  {
11594
11689
  type: "button",
@@ -11598,29 +11693,29 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11598
11693
  title: test ? "Test mode \u2014 every response is simulated. Click to inspect requests or return to live mode." : "Live mode \u2014 incomplete features are shown under construction. Click for test mode.",
11599
11694
  className: "fd-mode-btn" + (test ? " is-test" : "") + (open2 ? " is-open" : ""),
11600
11695
  children: [
11601
- /* @__PURE__ */ jsx89("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11602
- test && requestCount ? /* @__PURE__ */ jsx89("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
11696
+ /* @__PURE__ */ jsx91("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), style: { fontSize: 17 } }),
11697
+ test && requestCount ? /* @__PURE__ */ jsx91("span", { className: "fd-mono fd-mode-count", children: requestCount > 99 ? "99+" : requestCount }, requestCount) : null
11603
11698
  ]
11604
11699
  }
11605
11700
  ),
11606
- /* @__PURE__ */ jsxs77(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
11607
- /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11608
- /* @__PURE__ */ jsxs77("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
11609
- /* @__PURE__ */ jsx89("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
11701
+ /* @__PURE__ */ jsxs78(InlinePanelSurface, { panel, align: "right", offset: 8, width: 400, className: "fd-mode-pop", label: test ? "Test mode" : "Live mode", children: [
11702
+ /* @__PURE__ */ jsxs78("span", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11703
+ /* @__PURE__ */ jsxs78("span", { className: "fd-badge " + (test ? "fd-badge-warning" : "fd-badge-neutral"), children: [
11704
+ /* @__PURE__ */ jsx91("i", { className: "ph " + (test ? "ph-flask" : "ph-lightning"), "aria-hidden": "true" }),
11610
11705
  test ? "Test mode" : "Live mode"
11611
11706
  ] }),
11612
- test ? /* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11707
+ test ? /* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11613
11708
  requestCount,
11614
11709
  " simulated request",
11615
11710
  requestCount === 1 ? "" : "s"
11616
11711
  ] }) : null,
11617
- /* @__PURE__ */ jsx89("span", { style: { flex: 1 } }),
11618
- test && onClearLog ? /* @__PURE__ */ jsx89("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11712
+ /* @__PURE__ */ jsx91("span", { style: { flex: 1 } }),
11713
+ test && onClearLog ? /* @__PURE__ */ jsx91("button", { type: "button", className: "fd-soon-link", onClick: onClearLog, children: "Clear" }) : null
11619
11714
  ] }),
11620
- /* @__PURE__ */ jsxs77("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11621
- /* @__PURE__ */ jsx89("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
11622
- /* @__PURE__ */ jsxs77("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11623
- /* @__PURE__ */ jsxs77("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11715
+ /* @__PURE__ */ jsxs78("span", { style: { display: "block", padding: "12px 14px", borderBottom: "1px solid var(--border)" }, children: [
11716
+ /* @__PURE__ */ jsx91("span", { className: "fd-body-sm fd-secondary", style: { display: "block", textWrap: "pretty" }, children: test ? "Every feature is usable and nothing is obstructed, but no response comes from a real service \u2014 nothing you do here persists. Use this to review and demo the design." : "This is what a user would see today. " + s.incomplete + " of " + s.total + " features depend on backend work that is not wired yet, so they render under construction." }),
11717
+ /* @__PURE__ */ jsxs78("span", { className: "fd-row", style: { gap: 8, marginTop: 10, flexWrap: "wrap" }, children: [
11718
+ /* @__PURE__ */ jsxs78("span", { className: "fd-body-sm fd-muted fd-mono", children: [
11624
11719
  s.endpointsWired,
11625
11720
  " endpoint",
11626
11721
  s.endpointsWired === 1 ? "" : "s",
@@ -11630,58 +11725,58 @@ function ModeSwitch({ canToggle = false, requestCount = 0, onClearLog, renderLog
11630
11725
  s.total,
11631
11726
  " features complete"
11632
11727
  ] }),
11633
- onOpenSpec ? /* @__PURE__ */ jsxs77(Fragment25, { children: [
11634
- /* @__PURE__ */ jsx89("span", { style: { flex: 1 } }),
11635
- /* @__PURE__ */ jsxs77("button", { type: "button", className: "fd-soon-link", onClick: () => {
11728
+ onOpenSpec ? /* @__PURE__ */ jsxs78(Fragment25, { children: [
11729
+ /* @__PURE__ */ jsx91("span", { style: { flex: 1 } }),
11730
+ /* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-soon-link", onClick: () => {
11636
11731
  setOpen(false);
11637
11732
  onOpenSpec();
11638
11733
  }, children: [
11639
11734
  "API spec ",
11640
- /* @__PURE__ */ jsx89("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11735
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-arrow-right", "aria-hidden": "true" })
11641
11736
  ] })
11642
11737
  ] }) : null
11643
11738
  ] })
11644
11739
  ] }),
11645
- /* @__PURE__ */ jsxs77("span", { className: "fd-mode-choice", children: [
11646
- /* @__PURE__ */ jsxs77("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11647
- /* @__PURE__ */ jsx89("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11648
- /* @__PURE__ */ jsxs77("span", { className: "fd-mode-opt-text", children: [
11649
- /* @__PURE__ */ jsx89("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11650
- /* @__PURE__ */ jsx89("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11740
+ /* @__PURE__ */ jsxs78("span", { className: "fd-mode-choice", children: [
11741
+ /* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-mode-opt" + (!test ? " is-on" : ""), onClick: () => go("live"), children: [
11742
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11743
+ /* @__PURE__ */ jsxs78("span", { className: "fd-mode-opt-text", children: [
11744
+ /* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-title", children: "Live mode" }),
11745
+ /* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-desc", children: "Incomplete features under construction" })
11651
11746
  ] }),
11652
- !test ? /* @__PURE__ */ jsx89("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11747
+ !test ? /* @__PURE__ */ jsx91("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11653
11748
  ] }),
11654
- /* @__PURE__ */ jsxs77("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11655
- /* @__PURE__ */ jsx89("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11656
- /* @__PURE__ */ jsxs77("span", { className: "fd-mode-opt-text", children: [
11657
- /* @__PURE__ */ jsx89("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11658
- /* @__PURE__ */ jsx89("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11749
+ /* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-mode-opt" + (test ? " is-on" : ""), onClick: () => go("test"), children: [
11750
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11751
+ /* @__PURE__ */ jsxs78("span", { className: "fd-mode-opt-text", children: [
11752
+ /* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-title", children: "Test mode" }),
11753
+ /* @__PURE__ */ jsx91("span", { className: "fd-mode-opt-desc", children: "Everything usable, all data simulated" })
11659
11754
  ] }),
11660
- test ? /* @__PURE__ */ jsx89("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11755
+ test ? /* @__PURE__ */ jsx91("i", { className: "ph ph-check", "aria-hidden": "true" }) : null
11661
11756
  ] })
11662
11757
  ] }),
11663
- test && renderLog ? /* @__PURE__ */ jsx89("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11758
+ test && renderLog ? /* @__PURE__ */ jsx91("span", { style: { display: "block", maxHeight: 340, overflowY: "auto", borderTop: "1px solid var(--border)" }, children: renderLog() }) : null
11664
11759
  ] })
11665
11760
  ] });
11666
11761
  }
11667
11762
  function TestModeBar({ onExit }) {
11668
11763
  const mode2 = useRuntimeMode();
11669
11764
  if (mode2 !== "test") return null;
11670
- return /* @__PURE__ */ jsxs77("div", { className: "fd-testbar", role: "status", children: [
11671
- /* @__PURE__ */ jsxs77("span", { className: "fd-badge fd-badge-warning", children: [
11672
- /* @__PURE__ */ jsx89("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11765
+ return /* @__PURE__ */ jsxs78("div", { className: "fd-testbar", role: "status", children: [
11766
+ /* @__PURE__ */ jsxs78("span", { className: "fd-badge fd-badge-warning", children: [
11767
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-flask", "aria-hidden": "true" }),
11673
11768
  "Test mode"
11674
11769
  ] }),
11675
- /* @__PURE__ */ jsx89("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11676
- /* @__PURE__ */ jsxs77("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11677
- /* @__PURE__ */ jsx89("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11770
+ /* @__PURE__ */ jsx91("span", { className: "fd-testbar-detail", children: "Every feature is unlocked and every response is simulated \u2014 nothing here persists." }),
11771
+ /* @__PURE__ */ jsxs78("button", { type: "button", className: "fd-soon-link", onClick: () => onExit ? onExit() : RuntimeKit.setMode("live"), children: [
11772
+ /* @__PURE__ */ jsx91("i", { className: "ph ph-lightning", "aria-hidden": "true" }),
11678
11773
  " Back to live mode"
11679
11774
  ] })
11680
11775
  ] });
11681
11776
  }
11682
11777
 
11683
11778
  // src/components/planner/ChannelMeta.tsx
11684
- import { jsx as jsx90, jsxs as jsxs78 } from "react/jsx-runtime";
11779
+ import { jsx as jsx92, jsxs as jsxs79 } from "react/jsx-runtime";
11685
11780
  var CHANNEL_WEIGHTS = {
11686
11781
  "OOH": 50,
11687
11782
  "DOOH": 50,
@@ -11734,9 +11829,9 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11734
11829
  const m = ChannelMeta(channel);
11735
11830
  const wt = channelWeightOf(channel || "");
11736
11831
  if (dot) {
11737
- return /* @__PURE__ */ jsx90("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11832
+ return /* @__PURE__ */ jsx92("span", { className: ["fd-chan-dot", className].filter(Boolean).join(" "), title: m.name, style: { background: m.color }, ...rest });
11738
11833
  }
11739
- return /* @__PURE__ */ jsxs78(
11834
+ return /* @__PURE__ */ jsxs79(
11740
11835
  "span",
11741
11836
  {
11742
11837
  className: ["fd-chan", size === "sm" ? "fd-chan-sm" : "", className].filter(Boolean).join(" "),
@@ -11744,16 +11839,16 @@ function ChannelTag({ channel, size = "md", showLabel = true, dot = false, weigh
11744
11839
  style: { "--chan": m.color },
11745
11840
  ...rest,
11746
11841
  children: [
11747
- /* @__PURE__ */ jsx90("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11748
- showLabel ? /* @__PURE__ */ jsx90("span", { className: "fd-chan-label", children: m.label }) : null,
11749
- weight ? /* @__PURE__ */ jsx90("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11842
+ /* @__PURE__ */ jsx92("i", { className: "ph ph-" + m.icon, "aria-hidden": "true" }),
11843
+ showLabel ? /* @__PURE__ */ jsx92("span", { className: "fd-chan-label", children: m.label }) : null,
11844
+ weight ? /* @__PURE__ */ jsx92("span", { className: "fd-chan-weight", children: wt || 0 }) : null
11750
11845
  ]
11751
11846
  }
11752
11847
  );
11753
11848
  }
11754
11849
 
11755
11850
  // src/components/planner/SaturationDistribution.tsx
11756
- import { jsx as jsx91, jsxs as jsxs79 } from "react/jsx-runtime";
11851
+ import { jsx as jsx93, jsxs as jsxs80 } from "react/jsx-runtime";
11757
11852
  var BANDS2 = [
11758
11853
  { key: "weak", label: "Weak", n: 1, range: "< 50" },
11759
11854
  { key: "adequate", label: "Adequate", n: 2, range: "50\u2013100" },
@@ -11764,24 +11859,24 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11764
11859
  const grouped = BANDS2.map((b) => ({ ...b, items: campuses.filter((c) => c.band === b.key) }));
11765
11860
  const tallest = Math.max(1, ...grouped.map((g) => g.items.length));
11766
11861
  const floor = BANDS2.find((b) => b.key === floorBand) || BANDS2[0];
11767
- return /* @__PURE__ */ jsxs79("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11768
- /* @__PURE__ */ jsx91("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11862
+ return /* @__PURE__ */ jsxs80("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11863
+ /* @__PURE__ */ jsx93("div", { style: { display: "grid", gridTemplateColumns: "repeat(4,minmax(0,1fr))", gap: 12, alignItems: "end" }, children: grouped.map((g) => {
11769
11864
  const mark = "var(--csi-" + g.n + "-mark)";
11770
11865
  const active = selectedBand === g.key;
11771
- return /* @__PURE__ */ jsxs79(
11866
+ return /* @__PURE__ */ jsxs80(
11772
11867
  "button",
11773
11868
  {
11774
11869
  type: "button",
11775
11870
  onClick: onSelectBand ? () => onSelectBand(active ? null : g.key) : void 0,
11776
11871
  style: { display: "flex", flexDirection: "column", justifyContent: "flex-end", gap: 10, padding: 12, border: "1px solid " + (active ? "var(--border-strong)" : "var(--border)"), borderRadius: "var(--r-lg)", background: active ? "var(--surface-2)" : "var(--surface)", cursor: onSelectBand ? "pointer" : "default", textAlign: "left", minHeight: 190, minWidth: 0, transition: "background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)" },
11777
11872
  children: [
11778
- /* @__PURE__ */ jsx91("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx91("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11873
+ /* @__PURE__ */ jsx93("span", { style: { display: "flex", flexDirection: "column-reverse", gap: 4, minHeight: tallest * 24, minWidth: 0 }, children: loading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx93("span", { className: "fd-skel", style: { height: 16, borderRadius: 4 } }, i)) : g.items.map((c) => (
11779
11874
  // `overflow: hidden` + `white-space: nowrap` only clips once the span
11780
11875
  // actually HAS a bounded width to clip against (see the grid/flex
11781
11876
  // `minWidth: 0` chain above) — `textOverflow: ellipsis` then makes
11782
11877
  // that clip readable instead of a hard cut mid-letter; the full name
11783
11878
  // is still one hover away via `title`.
11784
- /* @__PURE__ */ jsx91(
11879
+ /* @__PURE__ */ jsx93(
11785
11880
  "span",
11786
11881
  {
11787
11882
  title: c.name + " \xB7 " + c.crp,
@@ -11791,13 +11886,13 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11791
11886
  c.name
11792
11887
  )
11793
11888
  )) }),
11794
- /* @__PURE__ */ jsxs79("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11795
- /* @__PURE__ */ jsx91("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11796
- /* @__PURE__ */ jsx91("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx91("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11889
+ /* @__PURE__ */ jsxs80("span", { className: "fd-row", style: { gap: 8, alignItems: "baseline" }, children: [
11890
+ /* @__PURE__ */ jsx93("span", { className: "fd-num-hero", style: { fontSize: 30, color: g.items.length ? "var(--text)" : "var(--text-disabled)" }, children: loading ? "\u2013" : g.items.length }),
11891
+ /* @__PURE__ */ jsx93("span", { className: "fd-meter", style: { gap: 2, color: mark }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx93("span", { className: "fd-meter-seg" + (i <= g.n ? " is-on" : ""), style: { width: 4, height: 9 } }, i)) })
11797
11892
  ] }),
11798
- /* @__PURE__ */ jsxs79("span", { className: "fd-stack", style: { gap: 1 }, children: [
11799
- /* @__PURE__ */ jsx91("span", { className: "fd-label-lg", children: g.label }),
11800
- /* @__PURE__ */ jsxs79("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11893
+ /* @__PURE__ */ jsxs80("span", { className: "fd-stack", style: { gap: 1 }, children: [
11894
+ /* @__PURE__ */ jsx93("span", { className: "fd-label-lg", children: g.label }),
11895
+ /* @__PURE__ */ jsxs80("span", { className: "fd-body-sm fd-muted", style: { fontSize: 11.5 }, children: [
11801
11896
  "CRP ",
11802
11897
  g.range
11803
11898
  ] })
@@ -11807,10 +11902,10 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11807
11902
  g.key
11808
11903
  );
11809
11904
  }) }),
11810
- floorBand ? /* @__PURE__ */ jsxs79("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
11811
- /* @__PURE__ */ jsx91("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx91("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11812
- /* @__PURE__ */ jsxs79("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11813
- /* @__PURE__ */ jsxs79("strong", { style: { color: "var(--text)" }, children: [
11905
+ floorBand ? /* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 10, padding: "12px 14px", borderRadius: "var(--r-md)", background: "var(--surface-2)", border: "1px solid var(--border)", flexWrap: "wrap" }, children: [
11906
+ /* @__PURE__ */ jsx93("span", { className: "fd-meter", style: { gap: 2, color: "var(--csi-" + floor.n + "-mark)" }, "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx93("span", { className: "fd-meter-seg" + (i <= floor.n ? " is-on" : ""), style: { width: 5, height: 12 } }, i)) }),
11907
+ /* @__PURE__ */ jsxs80("span", { className: "fd-body-sm fd-secondary", style: { flex: 1, minWidth: 240 }, children: [
11908
+ /* @__PURE__ */ jsxs80("strong", { style: { color: "var(--text)" }, children: [
11814
11909
  "Plan floor ",
11815
11910
  floorScore
11816
11911
  ] }),
@@ -11821,8 +11916,8 @@ function SaturationDistribution({ campuses = [], floorBand, floorScore, onSelect
11821
11916
  }
11822
11917
 
11823
11918
  // src/components/planner/MixGap.tsx
11824
- import * as React66 from "react";
11825
- import { Fragment as Fragment26, jsx as jsx92, jsxs as jsxs80 } from "react/jsx-runtime";
11919
+ import * as React67 from "react";
11920
+ import { Fragment as Fragment26, jsx as jsx94, jsxs as jsxs81 } from "react/jsx-runtime";
11826
11921
  var MIX_GAP_LAYOUT = {
11827
11922
  trackHeight: 30,
11828
11923
  barHeight: 20,
@@ -11836,19 +11931,19 @@ function mixGapOffset(value, max) {
11836
11931
  }
11837
11932
  function MixGap({ rows = [], loading = false, className = "" }) {
11838
11933
  const max = Math.max(1, ...rows.flatMap((r) => [r.target, r.realized]));
11839
- const [hover, setHover] = React66.useState(null);
11934
+ const [hover, setHover] = React67.useState(null);
11840
11935
  const toneOf = (gap) => gap >= -1 ? "ok" : gap >= -4 ? "warn" : "danger";
11841
11936
  const TONE = { ok: "var(--ok-solid)", warn: "var(--warn-solid)", danger: "var(--danger-solid)" };
11842
11937
  const { trackHeight, barHeight, targetWidth, labelGap } = MIX_GAP_LAYOUT;
11843
11938
  const barTop = (trackHeight - barHeight) / 2;
11844
- return /* @__PURE__ */ jsxs80("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11845
- /* @__PURE__ */ jsxs80("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11846
- [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs80("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11847
- /* @__PURE__ */ jsx92("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11939
+ return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 4 }, children: [
11940
+ /* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { gap: 16, justifyContent: "flex-end", paddingBottom: 6, flexWrap: "wrap" }, children: [
11941
+ [["On target", TONE.ok], ["Close", TONE.warn], ["Short", TONE.danger]].map(([l, c]) => /* @__PURE__ */ jsxs81("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11942
+ /* @__PURE__ */ jsx94("span", { style: { width: 14, height: 9, borderRadius: 2, background: c } }),
11848
11943
  l
11849
11944
  ] }, l)),
11850
- /* @__PURE__ */ jsxs80("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11851
- /* @__PURE__ */ jsx92("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11945
+ /* @__PURE__ */ jsxs81("span", { className: "fd-row fd-body-sm fd-muted", style: { gap: 6 }, children: [
11946
+ /* @__PURE__ */ jsx94("span", { "data-mixgap-legend-target": "", style: { width: targetWidth, height: 16, borderRadius: 1, background: MIX_GAP_TARGET_STRIPE } }),
11852
11947
  "Target"
11853
11948
  ] })
11854
11949
  ] }),
@@ -11857,7 +11952,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11857
11952
  const tone = toneOf(gap);
11858
11953
  const tip = "Realized " + r.realized + "% vs " + r.target + "% target" + (gap < -1 ? " \xB7 " + Math.abs(gap).toFixed(0) + " pts short" : gap > 1 ? " \xB7 " + gap.toFixed(0) + " pts over" : " \xB7 on target") + (r.note ? " \u2014 " + r.note : "");
11859
11954
  const labelLeft = r.realized > r.target ? `calc(${mixGapOffset(r.realized, max)} + ${labelGap}px)` : `calc(${mixGapOffset(r.target, max)} + ${targetWidth / 2 + labelGap}px)`;
11860
- return /* @__PURE__ */ jsxs80(
11955
+ return /* @__PURE__ */ jsxs81(
11861
11956
  "div",
11862
11957
  {
11863
11958
  className: "fd-row",
@@ -11865,15 +11960,15 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11865
11960
  onMouseEnter: () => setHover(r.channel),
11866
11961
  onMouseLeave: () => setHover(null),
11867
11962
  children: [
11868
- /* @__PURE__ */ jsx92("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx92(ChannelTag, { channel: r.channel, size: "sm" }) }),
11869
- /* @__PURE__ */ jsx92("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx92("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs80(Fragment26, { children: [
11870
- /* @__PURE__ */ jsx92("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
11871
- /* @__PURE__ */ jsx92("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
11872
- /* @__PURE__ */ jsxs80("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
11963
+ /* @__PURE__ */ jsx94("span", { style: { width: 128, flex: "none" }, children: /* @__PURE__ */ jsx94(ChannelTag, { channel: r.channel, size: "sm" }) }),
11964
+ /* @__PURE__ */ jsx94("span", { style: { position: "relative", flex: 1, height: trackHeight, minWidth: 120 }, children: loading ? /* @__PURE__ */ jsx94("span", { className: "fd-skel", style: { position: "absolute", left: 0, right: 0, top: barTop, height: barHeight, borderRadius: 3 } }) : /* @__PURE__ */ jsxs81(Fragment26, { children: [
11965
+ /* @__PURE__ */ jsx94("span", { "data-mixgap-bar": "", style: { position: "absolute", left: 0, top: barTop, height: barHeight, width: mixGapOffset(r.realized, max), background: TONE[tone], borderRadius: "2px 3px 3px 2px", transition: "width var(--dur-slow) var(--ease), background var(--dur-base) var(--ease)" } }),
11966
+ /* @__PURE__ */ jsx94("span", { "data-mixgap-target": "", style: { position: "absolute", left: `calc(${mixGapOffset(r.target, max)} - ${targetWidth / 2}px)`, top: 0, width: targetWidth, height: trackHeight, background: MIX_GAP_TARGET_STRIPE, borderRadius: 1 } }),
11967
+ /* @__PURE__ */ jsxs81("span", { "data-mixgap-label": "", className: "fd-num", style: { position: "absolute", left: labelLeft, top: "50%", transform: "translateY(-50%)", fontSize: 12, color: "var(--text-muted)", whiteSpace: "nowrap" }, children: [
11873
11968
  r.realized,
11874
11969
  "%"
11875
11970
  ] }),
11876
- hover === r.channel ? /* @__PURE__ */ jsx92("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
11971
+ hover === r.channel ? /* @__PURE__ */ jsx94("span", { className: "fd-tooltip", role: "tooltip", style: { position: "absolute", left: 0, right: "auto", bottom: trackHeight + 4, maxWidth: "min(340px, 100%)", whiteSpace: "normal", textAlign: "left", width: "max-content" }, children: tip }) : null
11877
11972
  ] }) })
11878
11973
  ]
11879
11974
  },
@@ -11884,7 +11979,7 @@ function MixGap({ rows = [], loading = false, className = "" }) {
11884
11979
  }
11885
11980
 
11886
11981
  // src/components/planner/ChannelContribution.tsx
11887
- import { jsx as jsx93, jsxs as jsxs81 } from "react/jsx-runtime";
11982
+ import { jsx as jsx95, jsxs as jsxs82 } from "react/jsx-runtime";
11888
11983
  var money = (n) => "$" + Math.round(n).toLocaleString();
11889
11984
  function ChannelContribution({
11890
11985
  channels = [],
@@ -11900,9 +11995,9 @@ function ChannelContribution({
11900
11995
  const grand = total !== void 0 ? total : base + bonus;
11901
11996
  const pct = (v) => grand ? v / grand * 100 : 0;
11902
11997
  const spendTotal = channels.reduce((s, c) => s + Number(String(c.spend || 0).replace(/[^0-9.]/g, "")), 0);
11903
- return /* @__PURE__ */ jsxs81("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11904
- loading ? /* @__PURE__ */ jsx93("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs81("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
11905
- channels.map((c) => /* @__PURE__ */ jsx93(
11998
+ return /* @__PURE__ */ jsxs82("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 16 }, children: [
11999
+ loading ? /* @__PURE__ */ jsx95("span", { className: "fd-skel", style: { height: 34, borderRadius: "var(--r-sm)" } }) : /* @__PURE__ */ jsxs82("div", { className: "fd-row", style: { height: 34, borderRadius: "var(--r-sm)", overflow: "hidden", gap: 2, background: "var(--surface-3)" }, children: [
12000
+ channels.map((c) => /* @__PURE__ */ jsx95(
11906
12001
  "span",
11907
12002
  {
11908
12003
  title: c.name + " \xB7 " + c.crp.toFixed(1) + " CRP",
@@ -11911,7 +12006,7 @@ function ChannelContribution({
11911
12006
  },
11912
12007
  c.name
11913
12008
  )),
11914
- bonus > 0 ? /* @__PURE__ */ jsx93(
12009
+ bonus > 0 ? /* @__PURE__ */ jsx95(
11915
12010
  "span",
11916
12011
  {
11917
12012
  title: "Surround-sound bonus +" + bonusPct + "%",
@@ -11920,18 +12015,18 @@ function ChannelContribution({
11920
12015
  }
11921
12016
  ) : null
11922
12017
  ] }),
11923
- showTable ? /* @__PURE__ */ jsxs81("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
11924
- /* @__PURE__ */ jsx93("thead", { children: /* @__PURE__ */ jsxs81("tr", { children: [
11925
- /* @__PURE__ */ jsx93("th", { style: { width: "34%" }, children: "Channel" }),
11926
- /* @__PURE__ */ jsx93("th", { style: { width: "16%" }, children: "Weight" }),
11927
- /* @__PURE__ */ jsx93("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
11928
- /* @__PURE__ */ jsx93("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
11929
- /* @__PURE__ */ jsx93("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
12018
+ showTable ? /* @__PURE__ */ jsxs82("table", { className: "fd-table", style: { fontSize: "var(--body-sm-size)" }, children: [
12019
+ /* @__PURE__ */ jsx95("thead", { children: /* @__PURE__ */ jsxs82("tr", { children: [
12020
+ /* @__PURE__ */ jsx95("th", { style: { width: "34%" }, children: "Channel" }),
12021
+ /* @__PURE__ */ jsx95("th", { style: { width: "16%" }, children: "Weight" }),
12022
+ /* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "16%" }, children: "Spend" }),
12023
+ /* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "17%" }, children: "CRP" }),
12024
+ /* @__PURE__ */ jsx95("th", { className: "is-num", style: { width: "17%" }, children: "Share" })
11930
12025
  ] }) }),
11931
- /* @__PURE__ */ jsxs81("tbody", { children: [
11932
- channels.map((c) => /* @__PURE__ */ jsxs81("tr", { children: [
11933
- /* @__PURE__ */ jsx93("td", { children: /* @__PURE__ */ jsx93(ChannelTag, { channel: c.name, size: "sm" }) }),
11934
- /* @__PURE__ */ jsx93("td", { children: /* @__PURE__ */ jsx93(
12026
+ /* @__PURE__ */ jsxs82("tbody", { children: [
12027
+ channels.map((c) => /* @__PURE__ */ jsxs82("tr", { children: [
12028
+ /* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsx95(ChannelTag, { channel: c.name, size: "sm" }) }),
12029
+ /* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsx95(
11935
12030
  "span",
11936
12031
  {
11937
12032
  className: "fd-badge fd-badge-neutral",
@@ -11940,38 +12035,38 @@ function ChannelContribution({
11940
12035
  children: "weight " + (channelWeightOf(c.name) || 0)
11941
12036
  }
11942
12037
  ) }),
11943
- /* @__PURE__ */ jsx93("td", { className: "is-num", children: c.spend }),
11944
- /* @__PURE__ */ jsx93("td", { className: "is-num", children: c.crp.toFixed(1) }),
11945
- /* @__PURE__ */ jsxs81("td", { className: "is-num", children: [
12038
+ /* @__PURE__ */ jsx95("td", { className: "is-num", children: c.spend }),
12039
+ /* @__PURE__ */ jsx95("td", { className: "is-num", children: c.crp.toFixed(1) }),
12040
+ /* @__PURE__ */ jsxs82("td", { className: "is-num", children: [
11946
12041
  pct(c.crp).toFixed(0),
11947
12042
  "%"
11948
12043
  ] })
11949
12044
  ] }, c.name)),
11950
- bonus > 0 ? /* @__PURE__ */ jsxs81("tr", { children: [
11951
- /* @__PURE__ */ jsx93("td", { children: /* @__PURE__ */ jsxs81("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
11952
- /* @__PURE__ */ jsx93("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
12045
+ bonus > 0 ? /* @__PURE__ */ jsxs82("tr", { children: [
12046
+ /* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsxs82("span", { className: "fd-row", style: { gap: 9, fontWeight: 600 }, children: [
12047
+ /* @__PURE__ */ jsx95("span", { style: { width: 9, height: 9, borderRadius: 2, background: "repeating-linear-gradient(135deg,var(--csi-3-mark) 0 3px,var(--csi-2-mark) 3px 6px)", flex: "none" } }),
11953
12048
  "Surround-sound bonus"
11954
12049
  ] }) }),
11955
- /* @__PURE__ */ jsx93("td", { children: /* @__PURE__ */ jsxs81("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
12050
+ /* @__PURE__ */ jsx95("td", { children: /* @__PURE__ */ jsxs82("span", { className: "fd-badge fd-badge-success", style: { height: 20, fontSize: 11 }, children: [
11956
12051
  "+",
11957
12052
  bonusPct,
11958
12053
  "% of +",
11959
12054
  bonusMax,
11960
12055
  "%"
11961
12056
  ] }) }),
11962
- /* @__PURE__ */ jsx93("td", { className: "is-num fd-muted", children: "\u2014" }),
11963
- /* @__PURE__ */ jsx93("td", { className: "is-num", children: bonus.toFixed(1) }),
11964
- /* @__PURE__ */ jsxs81("td", { className: "is-num", children: [
12057
+ /* @__PURE__ */ jsx95("td", { className: "is-num fd-muted", children: "\u2014" }),
12058
+ /* @__PURE__ */ jsx95("td", { className: "is-num", children: bonus.toFixed(1) }),
12059
+ /* @__PURE__ */ jsxs82("td", { className: "is-num", children: [
11965
12060
  pct(bonus).toFixed(0),
11966
12061
  "%"
11967
12062
  ] })
11968
12063
  ] }) : null,
11969
- /* @__PURE__ */ jsxs81("tr", { style: { background: "var(--surface-2)" }, children: [
11970
- /* @__PURE__ */ jsx93("td", { style: { fontWeight: 700 }, children: "Campus total" }),
11971
- /* @__PURE__ */ jsx93("td", {}),
11972
- /* @__PURE__ */ jsx93("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
11973
- /* @__PURE__ */ jsx93("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
11974
- /* @__PURE__ */ jsx93("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
12064
+ /* @__PURE__ */ jsxs82("tr", { style: { background: "var(--surface-2)" }, children: [
12065
+ /* @__PURE__ */ jsx95("td", { style: { fontWeight: 700 }, children: "Campus total" }),
12066
+ /* @__PURE__ */ jsx95("td", {}),
12067
+ /* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: money(spendTotal) }),
12068
+ /* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: grand.toFixed(1) }),
12069
+ /* @__PURE__ */ jsx95("td", { className: "is-num", style: { fontWeight: 700 }, children: "100%" })
11975
12070
  ] })
11976
12071
  ] })
11977
12072
  ] }) : null
@@ -11979,8 +12074,8 @@ function ChannelContribution({
11979
12074
  }
11980
12075
 
11981
12076
  // src/components/planner/BudgetReallocator.tsx
11982
- import * as React67 from "react";
11983
- import { Fragment as Fragment27, jsx as jsx94, jsxs as jsxs82 } from "react/jsx-runtime";
12077
+ import * as React68 from "react";
12078
+ import { Fragment as Fragment27, jsx as jsx96, jsxs as jsxs83 } from "react/jsx-runtime";
11984
12079
  var bandFor = (crp) => crp >= 200 ? "dominant" : crp >= 100 ? "strong" : crp >= 50 ? "adequate" : "weak";
11985
12080
  function BudgetReallocator({
11986
12081
  campus,
@@ -11995,8 +12090,8 @@ function BudgetReallocator({
11995
12090
  onCancel,
11996
12091
  className = ""
11997
12092
  }) {
11998
- const [draft, setDraft] = React67.useState(spend);
11999
- React67.useEffect(() => setDraft(spend), [spend]);
12093
+ const [draft, setDraft] = React68.useState(spend);
12094
+ React68.useEffect(() => setDraft(spend), [spend]);
12000
12095
  const dirty = draft !== spend;
12001
12096
  const nextCrp = scoreFor ? scoreFor(draft) : crp;
12002
12097
  const nextBand = bandFor(nextCrp);
@@ -12011,10 +12106,10 @@ function BudgetReallocator({
12011
12106
  setDraft(spend);
12012
12107
  if (onCancel) onCancel();
12013
12108
  };
12014
- const trackRef = React67.useRef(null);
12015
- const chipRef = React67.useRef(null);
12016
- const [chipLeft, setChipLeft] = React67.useState(null);
12017
- React67.useLayoutEffect(() => {
12109
+ const trackRef = React68.useRef(null);
12110
+ const chipRef = React68.useRef(null);
12111
+ const [chipLeft, setChipLeft] = React68.useState(null);
12112
+ React68.useLayoutEffect(() => {
12018
12113
  const track = trackRef.current;
12019
12114
  if (!dirty || !track) {
12020
12115
  setChipLeft(null);
@@ -12035,23 +12130,23 @@ function BudgetReallocator({
12035
12130
  ro.observe(track);
12036
12131
  return () => ro.disconnect();
12037
12132
  }, [dirty, pct]);
12038
- return /* @__PURE__ */ jsxs82(
12133
+ return /* @__PURE__ */ jsxs83(
12039
12134
  "div",
12040
12135
  {
12041
12136
  className: ["fd-stack", className].filter(Boolean).join(" "),
12042
12137
  style: { gap: 14, padding: 18, border: "1px solid " + (dirty ? "var(--border-brand)" : "var(--border)"), borderRadius: "var(--r-lg)", background: dirty ? "var(--surface-brand)" : "var(--surface)", color: "var(--text)", transition: "background var(--dur-base) var(--ease),border-color var(--dur-base) var(--ease)" },
12043
12138
  children: [
12044
- /* @__PURE__ */ jsxs82("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12045
- /* @__PURE__ */ jsx94("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
12046
- /* @__PURE__ */ jsx94(CsiBadge, { band: nowBand, crp, size: "medium" }),
12047
- dirty ? /* @__PURE__ */ jsxs82(Fragment27, { children: [
12048
- /* @__PURE__ */ jsx94("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
12049
- /* @__PURE__ */ jsx94(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
12139
+ /* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12140
+ /* @__PURE__ */ jsx96("span", { className: "fd-h4", style: { flex: 1, minWidth: 140 }, children: campus }),
12141
+ /* @__PURE__ */ jsx96(CsiBadge, { band: nowBand, crp, size: "medium" }),
12142
+ dirty ? /* @__PURE__ */ jsxs83(Fragment27, { children: [
12143
+ /* @__PURE__ */ jsx96("i", { className: "ph ph-arrow-right fd-muted", "aria-hidden": "true" }),
12144
+ /* @__PURE__ */ jsx96(CsiBadge, { band: nextBand, crp: nextCrp, size: "medium", preview: true })
12050
12145
  ] }) : null
12051
12146
  ] }),
12052
- /* @__PURE__ */ jsxs82("div", { className: "fd-slider", ref: trackRef, children: [
12053
- /* @__PURE__ */ jsx94("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
12054
- dirty ? /* @__PURE__ */ jsx94(
12147
+ /* @__PURE__ */ jsxs83("div", { className: "fd-slider", ref: trackRef, children: [
12148
+ /* @__PURE__ */ jsx96("span", { className: "fd-slider-fill", style: { width: pct + "%" } }),
12149
+ dirty ? /* @__PURE__ */ jsx96(
12055
12150
  "span",
12056
12151
  {
12057
12152
  ref: chipRef,
@@ -12063,7 +12158,7 @@ function BudgetReallocator({
12063
12158
  children: (delta < 0 ? "\u2212$" : "+$") + Math.abs(delta).toLocaleString()
12064
12159
  }
12065
12160
  ) : null,
12066
- /* @__PURE__ */ jsx94(
12161
+ /* @__PURE__ */ jsx96(
12067
12162
  "input",
12068
12163
  {
12069
12164
  type: "range",
@@ -12079,13 +12174,13 @@ function BudgetReallocator({
12079
12174
  }
12080
12175
  )
12081
12176
  ] }),
12082
- /* @__PURE__ */ jsxs82("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12083
- /* @__PURE__ */ jsxs82("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
12084
- /* @__PURE__ */ jsx94("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
12085
- /* @__PURE__ */ jsx94("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
12177
+ /* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { gap: 12, flexWrap: "wrap" }, children: [
12178
+ /* @__PURE__ */ jsxs83("span", { className: "fd-stack", style: { gap: 2, flex: 1, minWidth: 150 }, children: [
12179
+ /* @__PURE__ */ jsx96("span", { className: "fd-num", style: { fontSize: 19, fontWeight: 700 }, children: "$" + draft.toLocaleString() }),
12180
+ /* @__PURE__ */ jsx96("span", { className: "fd-body-sm fd-muted", children: "Arrow keys step $100, shift+arrow $1,000. Escape reverts." })
12086
12181
  ] }),
12087
- /* @__PURE__ */ jsx94("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
12088
- /* @__PURE__ */ jsx94(
12182
+ /* @__PURE__ */ jsx96("button", { type: "button", className: "fd-btn fd-btn-ghost", disabled: !dirty, onClick: revert, children: "Cancel" }),
12183
+ /* @__PURE__ */ jsx96(
12089
12184
  "button",
12090
12185
  {
12091
12186
  type: "button",
@@ -12104,7 +12199,7 @@ function BudgetReallocator({
12104
12199
  }
12105
12200
 
12106
12201
  // src/components/planner/SurroundSound.tsx
12107
- import { jsx as jsx95, jsxs as jsxs83 } from "react/jsx-runtime";
12202
+ import { jsx as jsx97, jsxs as jsxs84 } from "react/jsx-runtime";
12108
12203
  var CATEGORIES = [
12109
12204
  { key: "ooh", label: "OOH", icon: "flag-banner", color: "var(--ch-ooh)" },
12110
12205
  { key: "transit", label: "Transit", icon: "bus", color: "var(--ch-transit)" },
@@ -12116,26 +12211,26 @@ var CATEGORIES = [
12116
12211
  function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost, className = "" }) {
12117
12212
  const earned = Math.max(0, Math.min(1, bonusPct / bonusMax));
12118
12213
  const single = present.length <= 2;
12119
- return /* @__PURE__ */ jsxs83("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
12120
- /* @__PURE__ */ jsx95("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
12214
+ return /* @__PURE__ */ jsxs84("div", { className: ["fd-stack", className].filter(Boolean).join(" "), style: { gap: 14 }, children: [
12215
+ /* @__PURE__ */ jsx97("div", { className: "fd-row", style: { gap: 8, flexWrap: "wrap" }, children: CATEGORIES.map((c) => {
12121
12216
  const on = present.includes(c.key);
12122
- return /* @__PURE__ */ jsxs83(
12217
+ return /* @__PURE__ */ jsxs84(
12123
12218
  "span",
12124
12219
  {
12125
12220
  title: c.label + (on ? " \u2014 present" : " \u2014 not bought"),
12126
12221
  style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 5, width: 62, padding: "10px 0", borderRadius: "var(--r-md)", border: "1px solid " + (on ? "var(--csi-2-edge)" : "var(--border)"), background: on ? "var(--csi-2-fill)" : "var(--surface-2)", color: on ? "var(--csi-2-text)" : "var(--text-disabled)" },
12127
12222
  children: [
12128
- /* @__PURE__ */ jsx95("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
12129
- /* @__PURE__ */ jsx95("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
12223
+ /* @__PURE__ */ jsx97("i", { className: "ph ph-" + c.icon, style: { fontSize: 19, color: on ? c.color : "var(--text-muted)" }, "aria-hidden": "true" }),
12224
+ /* @__PURE__ */ jsx97("span", { style: { fontSize: 10.5, fontWeight: 700 }, children: c.label })
12130
12225
  ]
12131
12226
  },
12132
12227
  c.key
12133
12228
  );
12134
12229
  }) }),
12135
- /* @__PURE__ */ jsxs83("div", { className: "fd-stack", style: { gap: 8 }, children: [
12136
- /* @__PURE__ */ jsxs83("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
12137
- /* @__PURE__ */ jsx95("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
12138
- /* @__PURE__ */ jsxs83("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
12230
+ /* @__PURE__ */ jsxs84("div", { className: "fd-stack", style: { gap: 8 }, children: [
12231
+ /* @__PURE__ */ jsxs84("div", { className: "fd-row", style: { justifyContent: "space-between", gap: 12 }, children: [
12232
+ /* @__PURE__ */ jsx97("span", { className: "fd-label-lg", children: "Surround-sound bonus earned" }),
12233
+ /* @__PURE__ */ jsxs84("span", { className: "fd-num", style: { color: single ? "var(--warn-text)" : "var(--csi-3-mark)", fontWeight: 700 }, children: [
12139
12234
  "+",
12140
12235
  bonusPct,
12141
12236
  "% of +",
@@ -12143,8 +12238,8 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
12143
12238
  "%"
12144
12239
  ] })
12145
12240
  ] }),
12146
- /* @__PURE__ */ jsx95("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx95("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
12147
- /* @__PURE__ */ jsxs83("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
12241
+ /* @__PURE__ */ jsx97("div", { style: { height: 8, borderRadius: "var(--r-xs)", background: "var(--surface-3)", overflow: "hidden" }, children: /* @__PURE__ */ jsx97("div", { style: { height: "100%", width: earned * 100 + "%", background: "var(--csi-3-mark)", borderRadius: "inherit", transition: "width var(--dur-slow) var(--ease)" } }) }),
12242
+ /* @__PURE__ */ jsxs84("span", { className: "fd-body-sm fd-secondary", style: { textWrap: "pretty" }, children: [
12148
12243
  present.length,
12149
12244
  " of 6 channel categories present.",
12150
12245
  " ",
@@ -12156,7 +12251,7 @@ function SurroundSound({ present = [], bonusPct = 0, bonusMax = 40, missedCost,
12156
12251
  }
12157
12252
 
12158
12253
  // src/components/planner/Importance.tsx
12159
- import { jsx as jsx96, jsxs as jsxs84 } from "react/jsx-runtime";
12254
+ import { jsx as jsx98, jsxs as jsxs85 } from "react/jsx-runtime";
12160
12255
  var IMPORTANCE_LEVELS = [
12161
12256
  { id: "nudge", rank: 1, label: "Nudge", icon: "feather", description: "Breaks a tie, nothing more." },
12162
12257
  { id: "lean", rank: 2, label: "Lean", icon: "arrow-bend-up-right", description: "A mild preference between otherwise equal options." },
@@ -12186,7 +12281,7 @@ function importanceTokens(id) {
12186
12281
  function ImportanceTag({ level, showLabel = true, size = "sm", className = "", disabled = false }) {
12187
12282
  const lvl = importanceLevel(level);
12188
12283
  const t = importanceTokens(level);
12189
- return /* @__PURE__ */ jsxs84(
12284
+ return /* @__PURE__ */ jsxs85(
12190
12285
  "span",
12191
12286
  {
12192
12287
  className: ["fd-imp-tag", size === "md" ? "is-md" : "", disabled ? "is-disabled" : "", className].filter(Boolean).join(" "),
@@ -12194,16 +12289,16 @@ function ImportanceTag({ level, showLabel = true, size = "sm", className = "", d
12194
12289
  title: lvl.label + " \u2014 " + lvl.description,
12195
12290
  "aria-disabled": disabled ? "true" : void 0,
12196
12291
  children: [
12197
- /* @__PURE__ */ jsx96("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
12198
- showLabel ? lvl.label : /* @__PURE__ */ jsx96("span", { className: "fd-sr", children: lvl.label })
12292
+ /* @__PURE__ */ jsx98("i", { className: "ph ph-" + lvl.icon, "aria-hidden": "true" }),
12293
+ showLabel ? lvl.label : /* @__PURE__ */ jsx98("span", { className: "fd-sr", children: lvl.label })
12199
12294
  ]
12200
12295
  }
12201
12296
  );
12202
12297
  }
12203
12298
 
12204
12299
  // src/components/planner/PreferenceMeter.tsx
12205
- import * as React68 from "react";
12206
- import { jsx as jsx97, jsxs as jsxs85 } from "react/jsx-runtime";
12300
+ import * as React69 from "react";
12301
+ import { jsx as jsx99, jsxs as jsxs86 } from "react/jsx-runtime";
12207
12302
  function preferenceScore(criteria) {
12208
12303
  const earned = criteria.reduce((n, c) => n + (Number(c.earned) || 0), 0);
12209
12304
  const weight = criteria.reduce((n, c) => n + (Number(c.weight) || 0), 0);
@@ -12232,8 +12327,8 @@ function PreferenceMeter({
12232
12327
  className = ""
12233
12328
  }) {
12234
12329
  const value = score == null ? preferenceScore(criteria) : score;
12235
- const segments = React68.useMemo(() => preferenceSegments(criteria), [criteria]);
12236
- return /* @__PURE__ */ jsx97(
12330
+ const segments = React69.useMemo(() => preferenceSegments(criteria), [criteria]);
12331
+ return /* @__PURE__ */ jsx99(
12237
12332
  ScoreMeter,
12238
12333
  {
12239
12334
  score: value,
@@ -12245,22 +12340,22 @@ function PreferenceMeter({
12245
12340
  placement,
12246
12341
  className,
12247
12342
  breakdownLabel: breakdownTitle,
12248
- breakdown: /* @__PURE__ */ jsxs85("div", { className: "fd-prefbreak", children: [
12249
- /* @__PURE__ */ jsxs85("div", { className: "fd-prefbreak-head", children: [
12250
- /* @__PURE__ */ jsx97("span", { className: "fd-label-lg", children: breakdownTitle }),
12251
- /* @__PURE__ */ jsx97("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
12343
+ breakdown: /* @__PURE__ */ jsxs86("div", { className: "fd-prefbreak", children: [
12344
+ /* @__PURE__ */ jsxs86("div", { className: "fd-prefbreak-head", children: [
12345
+ /* @__PURE__ */ jsx99("span", { className: "fd-label-lg", children: breakdownTitle }),
12346
+ /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-score fd-tabular", children: Math.round(value) })
12252
12347
  ] }),
12253
- /* @__PURE__ */ jsx97("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
12348
+ /* @__PURE__ */ jsx99("ul", { className: "fd-prefbreak-list", children: criteria.map((c) => {
12254
12349
  const pct = c.weight > 0 ? Math.round((Number(c.earned) || 0) / c.weight * 100) : 0;
12255
- return /* @__PURE__ */ jsxs85("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
12256
- /* @__PURE__ */ jsx97(ImportanceTag, { level: c.importance }),
12257
- /* @__PURE__ */ jsxs85("span", { className: "fd-prefbreak-text", children: [
12258
- /* @__PURE__ */ jsx97("span", { className: "fd-prefbreak-label", children: c.label }),
12259
- c.note ? /* @__PURE__ */ jsx97("span", { className: "fd-prefbreak-note", children: c.note }) : null
12350
+ return /* @__PURE__ */ jsxs86("li", { className: pct === 0 ? "fd-prefbreak-item is-unmet" : "fd-prefbreak-item", children: [
12351
+ /* @__PURE__ */ jsx99(ImportanceTag, { level: c.importance }),
12352
+ /* @__PURE__ */ jsxs86("span", { className: "fd-prefbreak-text", children: [
12353
+ /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-label", children: c.label }),
12354
+ c.note ? /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-note", children: c.note }) : null
12260
12355
  ] }),
12261
- /* @__PURE__ */ jsxs85("span", { className: "fd-prefbreak-val fd-tabular", children: [
12356
+ /* @__PURE__ */ jsxs86("span", { className: "fd-prefbreak-val fd-tabular", children: [
12262
12357
  Math.round(Number(c.earned) || 0),
12263
- /* @__PURE__ */ jsx97("span", { className: "fd-prefbreak-sep", children: "/" }),
12358
+ /* @__PURE__ */ jsx99("span", { className: "fd-prefbreak-sep", children: "/" }),
12264
12359
  Math.round(c.weight)
12265
12360
  ] })
12266
12361
  ] }, c.id);
@@ -12271,10 +12366,10 @@ function PreferenceMeter({
12271
12366
  }
12272
12367
 
12273
12368
  // src/components/chat/AgentChatPanel.tsx
12274
- import * as React74 from "react";
12369
+ import * as React75 from "react";
12275
12370
 
12276
12371
  // src/components/chat/chatEngine.ts
12277
- import * as React69 from "react";
12372
+ import * as React70 from "react";
12278
12373
  var CHAT_UNAVAILABLE = "chat_unavailable";
12279
12374
  var JOB_PENDING = ["queued", "running"];
12280
12375
  var JOB_SUCCESS = ["completed", "recovered"];
@@ -12319,7 +12414,7 @@ function useChatEngine(opts) {
12319
12414
  initialMessage,
12320
12415
  threadId: threadIdProp,
12321
12416
  pollIntervalMs = 1500,
12322
- pollMaxAttempts = 120,
12417
+ pendingTimeoutMs = 18e4,
12323
12418
  store = safeStore,
12324
12419
  onPacket,
12325
12420
  onThreadReady,
@@ -12328,22 +12423,22 @@ function useChatEngine(opts) {
12328
12423
  onClear,
12329
12424
  onFeedback
12330
12425
  } = opts || {};
12331
- const [status, setStatus] = React69.useState("idle");
12332
- const [threadId, setThreadId] = React69.useState(null);
12333
- const [messages, setMessages] = React69.useState([]);
12334
- const [queue, setQueue] = React69.useState([]);
12335
- const [fatal, setFatal] = React69.useState(null);
12336
- const [busy, setBusy] = React69.useState(false);
12337
- const [turnStartedAt, setTurnStartedAt] = React69.useState(null);
12338
- const listRef = React69.useRef([]);
12339
- const queueRef = React69.useRef([]);
12340
- const busyRef = React69.useRef(false);
12341
- const stoppedRef = React69.useRef(false);
12342
- const abortRef = React69.useRef(null);
12343
- const serverCount = React69.useRef(0);
12344
- const threadRef = React69.useRef(null);
12345
- const mounted = React69.useRef(true);
12346
- React69.useEffect(() => {
12426
+ const [status, setStatus] = React70.useState("idle");
12427
+ const [threadId, setThreadId] = React70.useState(null);
12428
+ const [messages, setMessages] = React70.useState([]);
12429
+ const [queue, setQueue] = React70.useState([]);
12430
+ const [fatal, setFatal] = React70.useState(null);
12431
+ const [busy, setBusy] = React70.useState(false);
12432
+ const [turnStartedAt, setTurnStartedAt] = React70.useState(null);
12433
+ const listRef = React70.useRef([]);
12434
+ const queueRef = React70.useRef([]);
12435
+ const busyRef = React70.useRef(false);
12436
+ const stoppedRef = React70.useRef(false);
12437
+ const abortRef = React70.useRef(null);
12438
+ const serverCount = React70.useRef(0);
12439
+ const threadRef = React70.useRef(null);
12440
+ const mounted = React70.useRef(true);
12441
+ React70.useEffect(() => {
12347
12442
  mounted.current = true;
12348
12443
  return () => {
12349
12444
  mounted.current = false;
@@ -12365,14 +12460,21 @@ function useChatEngine(opts) {
12365
12460
  }
12366
12461
  return false;
12367
12462
  };
12368
- const loadThread = React69.useCallback(async (id) => {
12463
+ const loadThread = React70.useCallback(async (id) => {
12369
12464
  const data = await apiAdapter.getThread(id);
12370
12465
  const list = [...data && data.messages || []];
12371
12466
  serverCount.current = list.length;
12372
12467
  commit(list);
12373
12468
  return list;
12374
12469
  }, [apiAdapter]);
12375
- React69.useEffect(() => {
12470
+ async function mergeThread() {
12471
+ const data = await apiAdapter.getThread(threadRef.current);
12472
+ const server = data && data.messages || [];
12473
+ const ids = new Set(server.map((m) => m.id));
12474
+ serverCount.current = server.length;
12475
+ commit([...server, ...listRef.current.filter((m) => !ids.has(m.id))]);
12476
+ }
12477
+ React70.useEffect(() => {
12376
12478
  if (!apiAdapter) {
12377
12479
  setStatus("idle");
12378
12480
  setFatal(null);
@@ -12418,7 +12520,9 @@ function useChatEngine(opts) {
12418
12520
  setStatus("ready");
12419
12521
  onThreadReady && onThreadReady(id);
12420
12522
  const stored = store.get(STORAGE_PREFIX + id);
12523
+ const last = [...visibleMessages(listRef.current)].reverse().find((m) => m.role === "assistant");
12421
12524
  if (stored) resumeJob(stored);
12525
+ else if (last && last.working && last.jobId) resumeJob(last.jobId, last.id);
12422
12526
  else if (initialMessage) send(initialMessage);
12423
12527
  } catch (err) {
12424
12528
  if (dead) return;
@@ -12434,8 +12538,8 @@ function useChatEngine(opts) {
12434
12538
  }, [apiAdapter, contextType, contextId, threadIdProp]);
12435
12539
  async function pollJob(jobId, placeholderId) {
12436
12540
  store.set(STORAGE_PREFIX + threadRef.current, jobId);
12437
- let attempts = 0;
12438
- while (attempts++ < pollMaxAttempts) {
12541
+ const deadline = Date.now() + pendingTimeoutMs;
12542
+ while (true) {
12439
12543
  if (stoppedRef.current) break;
12440
12544
  await sleep(pollIntervalMs);
12441
12545
  if (!mounted.current) return;
@@ -12453,7 +12557,15 @@ function useChatEngine(opts) {
12453
12557
  }
12454
12558
  patch(placeholderId, { job });
12455
12559
  const bucket2 = jobBucket(job && job.status);
12456
- if (bucket2 === "pending") continue;
12560
+ if (bucket2 === "pending") {
12561
+ try {
12562
+ await mergeThread();
12563
+ } catch (err) {
12564
+ fail(err);
12565
+ }
12566
+ if (Date.now() >= deadline) break;
12567
+ continue;
12568
+ }
12457
12569
  if (bucket2 === "success") {
12458
12570
  finishJob(jobId, job);
12459
12571
  return;
@@ -12490,9 +12602,10 @@ function useChatEngine(opts) {
12490
12602
  patch(placeholderId, { working: false, streaming: false, error: code, retryable: !!retryable, job: job || void 0 });
12491
12603
  onError && onError(new Error(code));
12492
12604
  }
12493
- function resumeJob(jobId) {
12494
- const id = uid("a");
12495
- push({ id, role: "assistant", working: true, jobId, resumed: true });
12605
+ function resumeJob(jobId, existingId) {
12606
+ const id = existingId || uid("a");
12607
+ if (existingId) patch(id, { working: true, resumed: true });
12608
+ else push({ id, role: "assistant", working: true, jobId, resumed: true });
12496
12609
  setBusy(true);
12497
12610
  busyRef.current = true;
12498
12611
  setTurnStartedAt(Date.now());
@@ -12585,7 +12698,7 @@ function useChatEngine(opts) {
12585
12698
  await dispatchTurn(turn);
12586
12699
  }
12587
12700
  }
12588
- const send = React69.useCallback((text, attachments) => {
12701
+ const send = React70.useCallback((text, attachments) => {
12589
12702
  const body = (text || "").trim();
12590
12703
  if (!body && !(attachments && attachments.length)) return;
12591
12704
  if (status === "disconnected") return;
@@ -12595,7 +12708,7 @@ function useChatEngine(opts) {
12595
12708
  stoppedRef.current = false;
12596
12709
  drain();
12597
12710
  }, [status]);
12598
- const stop = React69.useCallback(() => {
12711
+ const stop = React70.useCallback(() => {
12599
12712
  stoppedRef.current = true;
12600
12713
  const ac = abortRef.current;
12601
12714
  if (ac) {
@@ -12614,11 +12727,11 @@ function useChatEngine(opts) {
12614
12727
  store.del(STORAGE_PREFIX + threadRef.current);
12615
12728
  }
12616
12729
  }, [apiAdapter]);
12617
- const removeQueued = React69.useCallback((id) => {
12730
+ const removeQueued = React70.useCallback((id) => {
12618
12731
  queueRef.current = queueRef.current.filter((t) => t.id !== id);
12619
12732
  setQueue(queueRef.current.slice());
12620
12733
  }, []);
12621
- const retry = React69.useCallback(() => {
12734
+ const retry = React70.useCallback(() => {
12622
12735
  const list = listRef.current;
12623
12736
  let at = -1;
12624
12737
  for (let i = list.length - 1; i >= 0; i--) if (list[i].role === "user") {
@@ -12634,19 +12747,19 @@ function useChatEngine(opts) {
12634
12747
  setQueue(queueRef.current.slice());
12635
12748
  drain();
12636
12749
  }, []);
12637
- const clear = React69.useCallback(() => {
12750
+ const clear = React70.useCallback(() => {
12638
12751
  commit([]);
12639
12752
  serverCount.current = 0;
12640
12753
  queueRef.current = [];
12641
12754
  setQueue([]);
12642
12755
  onClear && onClear();
12643
12756
  }, [onClear]);
12644
- const setFeedback = React69.useCallback((id, value) => {
12757
+ const setFeedback = React70.useCallback((id, value) => {
12645
12758
  patch(id, (m) => ({ feedback: m.feedback === value ? null : value }));
12646
12759
  const msg = listRef.current.find((m) => m.id === id);
12647
12760
  onFeedback && onFeedback({ message: msg, feedback: msg ? msg.feedback : value });
12648
12761
  }, [onFeedback]);
12649
- const reload = React69.useCallback(async () => {
12762
+ const reload = React70.useCallback(async () => {
12650
12763
  if (!threadRef.current) return;
12651
12764
  setStatus("loading");
12652
12765
  try {
@@ -12684,11 +12797,11 @@ var ChatKit = {
12684
12797
  };
12685
12798
 
12686
12799
  // src/components/chat/ChatTranscript.tsx
12687
- import * as React71 from "react";
12800
+ import * as React72 from "react";
12688
12801
 
12689
12802
  // src/components/chat/ChatTurn.tsx
12690
- import * as React70 from "react";
12691
- import { jsx as jsx98, jsxs as jsxs86 } from "react/jsx-runtime";
12803
+ import * as React71 from "react";
12804
+ import { jsx as jsx100, jsxs as jsxs87 } from "react/jsx-runtime";
12692
12805
  function JsonView({ value }) {
12693
12806
  let text;
12694
12807
  try {
@@ -12696,67 +12809,67 @@ function JsonView({ value }) {
12696
12809
  } catch (e) {
12697
12810
  text = String(value);
12698
12811
  }
12699
- return /* @__PURE__ */ jsx98(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12812
+ return /* @__PURE__ */ jsx100(CodeBlock, { code: text, language: "json", collapseAfter: 18 });
12700
12813
  }
12701
12814
  function PacketCard({ packet, schema, render, onApply, applied }) {
12702
12815
  if (!packet) return null;
12703
12816
  const s = schema || {};
12704
12817
  const invalid = packet.valid === false;
12705
12818
  const title = s.heading || packet.type;
12706
- return /* @__PURE__ */ jsxs86("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12707
- /* @__PURE__ */ jsxs86("header", { className: "fdc-packet-head", children: [
12708
- /* @__PURE__ */ jsx98("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12709
- /* @__PURE__ */ jsx98("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12710
- packet.repaired ? /* @__PURE__ */ jsx98("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12711
- invalid ? /* @__PURE__ */ jsx98("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12819
+ return /* @__PURE__ */ jsxs87("section", { className: "fdc-packet" + (invalid ? " is-invalid" : ""), "aria-label": title, children: [
12820
+ /* @__PURE__ */ jsxs87("header", { className: "fdc-packet-head", children: [
12821
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (s.icon || "package"), "aria-hidden": "true" }),
12822
+ /* @__PURE__ */ jsx100("span", { className: "fdc-packet-title", title: truncationTitle(title), children: title }),
12823
+ packet.repaired ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-badge", children: "Repaired" }) : null,
12824
+ invalid ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-badge is-danger", children: "Invalid" }) : null
12712
12825
  ] }),
12713
- invalid ? /* @__PURE__ */ jsxs86("div", { className: "fdc-packet-alert", role: "alert", children: [
12714
- /* @__PURE__ */ jsx98("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12715
- /* @__PURE__ */ jsx98("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12716
- ] }) : /* @__PURE__ */ jsx98("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx98(JsonView, { value: packet.payload }) }),
12717
- !invalid && onApply ? /* @__PURE__ */ jsxs86("footer", { className: "fdc-packet-foot", children: [
12718
- packet.repaired ? /* @__PURE__ */ jsx98("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx98("span", {}),
12719
- /* @__PURE__ */ jsxs86("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12720
- /* @__PURE__ */ jsx98("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12826
+ invalid ? /* @__PURE__ */ jsxs87("div", { className: "fdc-packet-alert", role: "alert", children: [
12827
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12828
+ /* @__PURE__ */ jsx100("span", { children: packet.error || "This result failed validation and can\u2019t be applied." })
12829
+ ] }) : /* @__PURE__ */ jsx100("div", { className: "fdc-packet-body", children: render ? render(packet) : /* @__PURE__ */ jsx100(JsonView, { value: packet.payload }) }),
12830
+ !invalid && onApply && s.apply !== false ? /* @__PURE__ */ jsxs87("footer", { className: "fdc-packet-foot", children: [
12831
+ packet.repaired ? /* @__PURE__ */ jsx100("span", { className: "fdc-packet-note", children: "Corrected by the backend after a first attempt." }) : /* @__PURE__ */ jsx100("span", {}),
12832
+ /* @__PURE__ */ jsxs87("button", { type: "button", className: "fd-btn fd-btn-primary fd-btn-sm", disabled: applied, onClick: () => onApply(packet), children: [
12833
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (applied ? "check" : "arrow-square-in"), "aria-hidden": "true" }),
12721
12834
  applied ? "Applied" : s.applyLabel || "Apply"
12722
12835
  ] })
12723
12836
  ] }) : null
12724
12837
  ] });
12725
12838
  }
12726
12839
  function ThinkingBlock({ text, durationMs, streaming, defaultOpen = false }) {
12727
- const [open2, setOpen] = React70.useState(defaultOpen);
12840
+ const [open2, setOpen] = React71.useState(defaultOpen);
12728
12841
  if (!text) return null;
12729
- return /* @__PURE__ */ jsxs86("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12730
- /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12731
- /* @__PURE__ */ jsx98("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12732
- /* @__PURE__ */ jsx98("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12733
- streaming ? /* @__PURE__ */ jsxs86("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12734
- /* @__PURE__ */ jsx98("span", {}),
12735
- /* @__PURE__ */ jsx98("span", {}),
12736
- /* @__PURE__ */ jsx98("span", {})
12842
+ return /* @__PURE__ */ jsxs87("div", { className: "fdc-think" + (open2 ? " is-open" : ""), children: [
12843
+ /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-think-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12844
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-brain", "aria-hidden": "true" }),
12845
+ /* @__PURE__ */ jsx100("span", { children: streaming ? "Thinking" : durationMs ? "Thought for " + formatDuration(durationMs) : "Thought process" }),
12846
+ streaming ? /* @__PURE__ */ jsxs87("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12847
+ /* @__PURE__ */ jsx100("span", {}),
12848
+ /* @__PURE__ */ jsx100("span", {}),
12849
+ /* @__PURE__ */ jsx100("span", {})
12737
12850
  ] }) : null,
12738
- /* @__PURE__ */ jsx98("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12851
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12739
12852
  ] }),
12740
- open2 ? /* @__PURE__ */ jsx98("div", { className: "fdc-think-body", children: text }) : null
12853
+ open2 ? /* @__PURE__ */ jsx100("div", { className: "fdc-think-body", children: text }) : null
12741
12854
  ] });
12742
12855
  }
12743
12856
  function Citations({ items = [], onOpen }) {
12744
- const [open2, setOpen] = React70.useState(false);
12857
+ const [open2, setOpen] = React71.useState(false);
12745
12858
  if (!items.length) return null;
12746
- return /* @__PURE__ */ jsxs86("div", { className: "fdc-cites", children: [
12747
- /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12748
- /* @__PURE__ */ jsx98("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12749
- /* @__PURE__ */ jsxs86("span", { children: [
12859
+ return /* @__PURE__ */ jsxs87("div", { className: "fdc-cites", children: [
12860
+ /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-cites-head", onClick: () => setOpen((v) => !v), "aria-expanded": open2, children: [
12861
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-quotes", "aria-hidden": "true" }),
12862
+ /* @__PURE__ */ jsxs87("span", { children: [
12750
12863
  items.length,
12751
12864
  " source",
12752
12865
  items.length === 1 ? "" : "s"
12753
12866
  ] }),
12754
- /* @__PURE__ */ jsx98("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12867
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-caret-" + (open2 ? "up" : "down"), "aria-hidden": "true" })
12755
12868
  ] }),
12756
- open2 ? /* @__PURE__ */ jsx98("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs86("li", { children: [
12757
- /* @__PURE__ */ jsx98("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12758
- c.url ? /* @__PURE__ */ jsx98("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx98("span", { children: c.title || "Source" }),
12759
- c.detail ? /* @__PURE__ */ jsx98("span", { className: "fdc-cite-detail", children: c.detail }) : null
12869
+ open2 ? /* @__PURE__ */ jsx100("ol", { className: "fdc-cites-list", children: items.map((c, i) => /* @__PURE__ */ jsxs87("li", { children: [
12870
+ /* @__PURE__ */ jsx100("span", { className: "fdc-cite-n fd-tabular", children: c.marker || i + 1 }),
12871
+ c.url ? /* @__PURE__ */ jsx100("a", { href: c.url, target: "_blank", rel: "noopener noreferrer", onClick: onOpen ? (e) => onOpen(c, e) : void 0, children: c.title || c.url }) : /* @__PURE__ */ jsx100("span", { children: c.title || "Source" }),
12872
+ c.detail ? /* @__PURE__ */ jsx100("span", { className: "fdc-cite-detail", children: c.detail }) : null
12760
12873
  ] }, c.id || i)) }) : null
12761
12874
  ] });
12762
12875
  }
@@ -12767,29 +12880,29 @@ function clampText(text, max) {
12767
12880
  return (at > max * 0.6 ? cut.slice(0, at) : cut).trimEnd() + "\u2026";
12768
12881
  }
12769
12882
  function MessageBody({ message: m, ctx }) {
12770
- const [expanded, setExpanded] = React70.useState(false);
12883
+ const [expanded, setExpanded] = React71.useState(false);
12771
12884
  const isUser = m.role === "user";
12772
12885
  const raw = m.text || "";
12773
12886
  const clamped = !expanded && !m.streaming ? clampText(raw, ctx.maxVisibleChars) : null;
12774
12887
  const body = clamped != null ? clamped : raw;
12775
12888
  const showMd = ctx.markdown && !isUser;
12776
- return /* @__PURE__ */ jsxs86("div", { className: "fdc-body", children: [
12777
- m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx98(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12778
- m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx98(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12779
- body ? /* @__PURE__ */ jsxs86("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12780
- showMd ? /* @__PURE__ */ jsx98(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx98("div", { className: "fdc-plain", children: body }),
12781
- m.streaming ? /* @__PURE__ */ jsx98("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12889
+ return /* @__PURE__ */ jsxs87("div", { className: "fdc-body", children: [
12890
+ m.thinking && ctx.showThinking ? /* @__PURE__ */ jsx100(ThinkingBlock, { text: m.thinking, durationMs: m.thinkingMs, streaming: m.streaming && !m.text }) : null,
12891
+ m.steps && m.steps.length && ctx.showSteps ? /* @__PURE__ */ jsx100(StepList, { steps: m.steps, defaultOpen: m.steps.some((s) => s.status === "running"), dense: true }) : null,
12892
+ body ? /* @__PURE__ */ jsxs87("div", { className: "fdc-text" + (isUser ? " is-user" : ""), children: [
12893
+ showMd ? /* @__PURE__ */ jsx100(Markdown, { source: body, headingOffset: 2, codeProps: { collapseAfter: 22 }, renderCitation: ctx.renderCitation }) : /* @__PURE__ */ jsx100("div", { className: "fdc-plain", children: body }),
12894
+ m.streaming ? /* @__PURE__ */ jsx100("span", { className: "fdc-caret", "aria-hidden": "true" }) : null
12782
12895
  ] }) : null,
12783
- clamped != null ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12784
- /* @__PURE__ */ jsx98("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12896
+ clamped != null ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(true), children: [
12897
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-caret-down", "aria-hidden": "true" }),
12785
12898
  "Show more",
12786
- /* @__PURE__ */ jsx98("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12787
- ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12788
- /* @__PURE__ */ jsx98("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12899
+ /* @__PURE__ */ jsx100("span", { className: "fdc-more-len fd-tabular", children: raw.length < 2e3 ? raw.length.toLocaleString() + " characters" : Math.round(raw.length / 100) / 10 + "k characters" })
12900
+ ] }) : expanded && ctx.maxVisibleChars && raw.length > ctx.maxVisibleChars ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-more", onClick: () => setExpanded(false), children: [
12901
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-caret-up", "aria-hidden": "true" }),
12789
12902
  "Show less"
12790
12903
  ] }) : null,
12791
- m.attachments && m.attachments.length ? /* @__PURE__ */ jsx98(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12792
- m.packet ? /* @__PURE__ */ jsx98(
12904
+ m.attachments && m.attachments.length ? /* @__PURE__ */ jsx100(FileGrid, { files: m.attachments, onOpen: ctx.onOpenAttachment, tiles: true, maxHeight: ctx.attachmentHeight || 220, compact: ctx.narrow }) : null,
12905
+ m.packet ? /* @__PURE__ */ jsx100(
12793
12906
  PacketCard,
12794
12907
  {
12795
12908
  packet: m.packet,
@@ -12799,35 +12912,35 @@ function MessageBody({ message: m, ctx }) {
12799
12912
  applied: ctx.appliedPackets && ctx.appliedPackets[m.id]
12800
12913
  }
12801
12914
  ) : null,
12802
- m.citations && m.citations.length ? /* @__PURE__ */ jsx98(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12803
- m.working ? /* @__PURE__ */ jsxs86("div", { className: "fdc-working", role: "status", children: [
12804
- /* @__PURE__ */ jsxs86("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12805
- /* @__PURE__ */ jsx98("span", {}),
12806
- /* @__PURE__ */ jsx98("span", {}),
12807
- /* @__PURE__ */ jsx98("span", {})
12915
+ m.citations && m.citations.length ? /* @__PURE__ */ jsx100(Citations, { items: m.citations, onOpen: ctx.onOpenCitation }) : null,
12916
+ m.working ? /* @__PURE__ */ jsxs87("div", { className: "fdc-working", role: "status", children: [
12917
+ /* @__PURE__ */ jsxs87("span", { className: "fdc-dots", "aria-hidden": "true", children: [
12918
+ /* @__PURE__ */ jsx100("span", {}),
12919
+ /* @__PURE__ */ jsx100("span", {}),
12920
+ /* @__PURE__ */ jsx100("span", {})
12808
12921
  ] }),
12809
- /* @__PURE__ */ jsxs86("span", { className: "fdc-working-label", children: [
12922
+ /* @__PURE__ */ jsxs87("span", { className: "fdc-working-label", children: [
12810
12923
  m.resumed ? "Resuming" : "Working",
12811
- m.job && m.job.status ? /* @__PURE__ */ jsxs86("span", { className: "fdc-working-job", children: [
12924
+ m.job && m.job.status ? /* @__PURE__ */ jsxs87("span", { className: "fdc-working-job", children: [
12812
12925
  " \xB7 ",
12813
12926
  m.job.status
12814
12927
  ] }) : null,
12815
- m.job && m.job.detail ? /* @__PURE__ */ jsxs86("span", { className: "fdc-working-job", children: [
12928
+ m.job && m.job.detail ? /* @__PURE__ */ jsxs87("span", { className: "fdc-working-job", children: [
12816
12929
  " \xB7 ",
12817
12930
  m.job.detail
12818
12931
  ] }) : null
12819
12932
  ] }),
12820
- m.jobId ? /* @__PURE__ */ jsx98("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12933
+ m.jobId ? /* @__PURE__ */ jsx100("span", { className: "fdc-working-id fd-mono", children: String(m.jobId).slice(0, 12) }) : null
12821
12934
  ] }) : null,
12822
- m.stopped ? /* @__PURE__ */ jsxs86("div", { className: "fdc-stopped", children: [
12823
- /* @__PURE__ */ jsx98("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12935
+ m.stopped ? /* @__PURE__ */ jsxs87("div", { className: "fdc-stopped", children: [
12936
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
12824
12937
  "Stopped"
12825
12938
  ] }) : null,
12826
- m.error ? /* @__PURE__ */ jsxs86("div", { className: "fdc-error", role: "alert", children: [
12827
- /* @__PURE__ */ jsx98("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12828
- /* @__PURE__ */ jsx98("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12829
- m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12830
- /* @__PURE__ */ jsx98("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12939
+ m.error ? /* @__PURE__ */ jsxs87("div", { className: "fdc-error", role: "alert", children: [
12940
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
12941
+ /* @__PURE__ */ jsx100("span", { className: "fdc-error-text", children: ctx.errorCopy ? ctx.errorCopy(m.error) : m.error }),
12942
+ m.retryable && ctx.onRetry ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-error-retry", onClick: ctx.onRetry, children: [
12943
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12831
12944
  "Retry"
12832
12945
  ] }) : null
12833
12946
  ] }) : null
@@ -12840,16 +12953,16 @@ function RunActions({ group, ctx }) {
12840
12953
  const isAssistant = group.role === "assistant";
12841
12954
  const fb = last.feedback;
12842
12955
  if (!ctx.messageActions) return null;
12843
- return /* @__PURE__ */ jsxs86("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12844
- /* @__PURE__ */ jsxs86("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12845
- /* @__PURE__ */ jsx98("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12846
- /* @__PURE__ */ jsx98("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12956
+ return /* @__PURE__ */ jsxs87("div", { className: "fdc-actions", role: "group", "aria-label": "Message actions", children: [
12957
+ /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-act" + (copied ? " is-done" : ""), onClick: () => copy(markdownToText(text)), "aria-label": "Copy message", children: [
12958
+ /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (copied ? "check" : "copy"), "aria-hidden": "true" }),
12959
+ /* @__PURE__ */ jsx100("span", { className: "fdc-act-label", children: copied ? "Copied" : "Copy" })
12847
12960
  ] }),
12848
- isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx98("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12849
- group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx98("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx98("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12850
- isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs86(React70.Fragment, { children: [
12851
- /* @__PURE__ */ jsx98("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__ */ jsx98("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12852
- /* @__PURE__ */ jsx98("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__ */ jsx98("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12961
+ isAssistant && ctx.onRetry ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act", onClick: ctx.onRetry, "aria-label": "Retry this turn", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }) }) : null,
12962
+ group.role === "user" && ctx.onEdit ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-act", onClick: () => ctx.onEdit(last), "aria-label": "Edit and resend", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-pencil-simple", "aria-hidden": "true" }) }) : null,
12963
+ isAssistant && ctx.onFeedback ? /* @__PURE__ */ jsxs87(React71.Fragment, { children: [
12964
+ /* @__PURE__ */ jsx100("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__ */ jsx100("i", { className: "ph ph-thumbs-up", "aria-hidden": "true" }) }),
12965
+ /* @__PURE__ */ jsx100("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__ */ jsx100("i", { className: "ph ph-thumbs-down", "aria-hidden": "true" }) })
12853
12966
  ] }) : null,
12854
12967
  ctx.extraActions ? ctx.extraActions(group) : null
12855
12968
  ] });
@@ -12859,22 +12972,22 @@ function ChatTurn({ group, ctx }) {
12859
12972
  const name = isUser ? ctx.userName : group.author || ctx.assistantName;
12860
12973
  const avatar = isUser ? ctx.userAvatar : ctx.assistantAvatar;
12861
12974
  const stamp = group.messages[0].timestamp;
12862
- return /* @__PURE__ */ jsxs86("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12863
- /* @__PURE__ */ jsxs86("div", { className: "fdc-turn-head", children: [
12864
- ctx.showAvatars ? /* @__PURE__ */ jsx98("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx98("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx98("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx98("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12865
- /* @__PURE__ */ jsx98("span", { className: "fdc-who", children: name }),
12866
- stamp ? /* @__PURE__ */ jsx98(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12867
- group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx98("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12975
+ return /* @__PURE__ */ jsxs87("article", { className: "fdc-turn is-" + group.role, "aria-label": String(name) + (stamp ? " at " + formatClock(stamp) : ""), children: [
12976
+ /* @__PURE__ */ jsxs87("div", { className: "fdc-turn-head", children: [
12977
+ ctx.showAvatars ? /* @__PURE__ */ jsx100("span", { className: "fdc-avatar is-" + group.role, "aria-hidden": "true", children: avatar ? /* @__PURE__ */ jsx100("img", { src: avatar, alt: "" }) : isUser ? /* @__PURE__ */ jsx100("span", { className: "fdc-avatar-txt", children: (name || "You").slice(0, 1).toUpperCase() }) : /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (ctx.assistantIcon || "sparkle") }) }) : null,
12978
+ /* @__PURE__ */ jsx100("span", { className: "fdc-who", children: name }),
12979
+ stamp ? /* @__PURE__ */ jsx100(RelativeTime, { className: "fdc-when", value: stamp }) : null,
12980
+ group.messages.some((m) => m.model) ? /* @__PURE__ */ jsx100("span", { className: "fdc-turn-model", children: group.messages.find((m) => m.model).model }) : null
12868
12981
  ] }),
12869
- /* @__PURE__ */ jsxs86("div", { className: "fdc-turn-body", children: [
12870
- group.messages.map((m) => /* @__PURE__ */ jsx98("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx98(MessageBody, { message: m, ctx }) }, m.id)),
12871
- /* @__PURE__ */ jsx98(RunActions, { group, ctx })
12982
+ /* @__PURE__ */ jsxs87("div", { className: "fdc-turn-body", children: [
12983
+ group.messages.map((m) => /* @__PURE__ */ jsx100("div", { className: "fdc-msg" + (m.pending ? " is-pending" : ""), children: /* @__PURE__ */ jsx100(MessageBody, { message: m, ctx }) }, m.id)),
12984
+ /* @__PURE__ */ jsx100(RunActions, { group, ctx })
12872
12985
  ] })
12873
12986
  ] });
12874
12987
  }
12875
12988
 
12876
12989
  // src/components/chat/ChatTranscript.tsx
12877
- import { jsx as jsx99, jsxs as jsxs87 } from "react/jsx-runtime";
12990
+ import { jsx as jsx101, jsxs as jsxs88 } from "react/jsx-runtime";
12878
12991
  var GROUP_WINDOW = 6e4;
12879
12992
  var STICK_PX = 100;
12880
12993
  function groupMessages(list) {
@@ -12907,25 +13020,25 @@ function dayLabel(key) {
12907
13020
  }
12908
13021
  function Suggestions({ items = [], onPick }) {
12909
13022
  if (!items.length) return null;
12910
- return /* @__PURE__ */ jsx99("div", { className: "fdc-suggest", children: items.map((s, i) => {
13023
+ return /* @__PURE__ */ jsx101("div", { className: "fdc-suggest", children: items.map((s, i) => {
12911
13024
  const it = typeof s === "string" ? { label: s, text: s } : s;
12912
- return /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
12913
- it.icon ? /* @__PURE__ */ jsx99("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
12914
- /* @__PURE__ */ jsxs87("span", { className: "fdc-suggest-text", children: [
12915
- /* @__PURE__ */ jsx99("span", { className: "fdc-suggest-label", children: it.label }),
12916
- it.description ? /* @__PURE__ */ jsx99("span", { className: "fdc-suggest-desc", children: it.description }) : null
13025
+ return /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-suggest-item", onClick: () => onPick && onPick(it.text || it.label), children: [
13026
+ it.icon ? /* @__PURE__ */ jsx101("i", { className: "ph ph-" + it.icon, "aria-hidden": "true" }) : null,
13027
+ /* @__PURE__ */ jsxs88("span", { className: "fdc-suggest-text", children: [
13028
+ /* @__PURE__ */ jsx101("span", { className: "fdc-suggest-label", children: it.label }),
13029
+ it.description ? /* @__PURE__ */ jsx101("span", { className: "fdc-suggest-desc", children: it.description }) : null
12917
13030
  ] }),
12918
- /* @__PURE__ */ jsx99("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
13031
+ /* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-up-right fdc-suggest-go", "aria-hidden": "true" })
12919
13032
  ] }, it.id || i);
12920
13033
  }) });
12921
13034
  }
12922
13035
  function LoadingTurns() {
12923
- return /* @__PURE__ */ jsx99("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs87("div", { className: "fdc-skel-turn", children: [
12924
- /* @__PURE__ */ jsx99("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
12925
- /* @__PURE__ */ jsxs87("div", { className: "fdc-skel-lines", children: [
12926
- /* @__PURE__ */ jsx99("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
12927
- /* @__PURE__ */ jsx99("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
12928
- /* @__PURE__ */ jsx99("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
13036
+ return /* @__PURE__ */ jsx101("div", { className: "fdc-skel", "aria-hidden": "true", children: [0, 1].map((i) => /* @__PURE__ */ jsxs88("div", { className: "fdc-skel-turn", children: [
13037
+ /* @__PURE__ */ jsx101("div", { className: "fd-skel fd-skel-circle", style: { width: 22, height: 22 } }),
13038
+ /* @__PURE__ */ jsxs88("div", { className: "fdc-skel-lines", children: [
13039
+ /* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "62%" : "44%", height: 11 } }),
13040
+ /* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "94%" : "78%", height: 11 } }),
13041
+ /* @__PURE__ */ jsx101("div", { className: "fd-skel", style: { width: i ? "71%" : "56%", height: 11 } })
12929
13042
  ] })
12930
13043
  ] }, i)) });
12931
13044
  }
@@ -12942,10 +13055,10 @@ function ChatTranscript({
12942
13055
  renderEmpty,
12943
13056
  className = ""
12944
13057
  }) {
12945
- const scroller = React71.useRef(null);
12946
- const stick = React71.useRef(true);
12947
- const [pill, setPill] = React71.useState(0);
12948
- const seen = React71.useRef(0);
13058
+ const scroller = React72.useRef(null);
13059
+ const stick = React72.useRef(true);
13060
+ const [pill, setPill] = React72.useState(0);
13061
+ const seen = React72.useRef(0);
12949
13062
  const toBottom = (smooth) => {
12950
13063
  const el = scroller.current;
12951
13064
  if (!el) return;
@@ -12964,7 +13077,7 @@ function ChatTranscript({
12964
13077
  seen.current = messages.length;
12965
13078
  }
12966
13079
  };
12967
- React71.useLayoutEffect(() => {
13080
+ React72.useLayoutEffect(() => {
12968
13081
  const el = scroller.current;
12969
13082
  if (!el) return;
12970
13083
  if (stick.current) {
@@ -12972,7 +13085,7 @@ function ChatTranscript({
12972
13085
  seen.current = messages.length;
12973
13086
  } else setPill(Math.max(0, messages.length - seen.current));
12974
13087
  }, [messages]);
12975
- React71.useEffect(() => {
13088
+ React72.useEffect(() => {
12976
13089
  const el = scroller.current;
12977
13090
  const inner = el && el.firstChild;
12978
13091
  if (!el || !inner || typeof ResizeObserver === "undefined") return;
@@ -12982,38 +13095,38 @@ function ChatTranscript({
12982
13095
  ro.observe(inner);
12983
13096
  return () => ro.disconnect();
12984
13097
  }, []);
12985
- const groups = React71.useMemo(() => groupMessages(messages), [messages]);
13098
+ const groups = React72.useMemo(() => groupMessages(messages), [messages]);
12986
13099
  const empty = !messages.length && status === "ready";
12987
- return /* @__PURE__ */ jsxs87("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
12988
- /* @__PURE__ */ jsxs87("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
12989
- status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx99(LoadingTurns, {}) : null,
12990
- status === "disconnected" ? /* @__PURE__ */ jsxs87("div", { className: "fdc-dead", children: [
12991
- /* @__PURE__ */ jsx99("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
12992
- /* @__PURE__ */ jsx99("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
12993
- /* @__PURE__ */ jsx99("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
12994
- ctx.onReconnect ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
12995
- /* @__PURE__ */ jsx99("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
13100
+ return /* @__PURE__ */ jsxs88("div", { className: ["fdc-scroll", className].filter(Boolean).join(" "), ref: scroller, onScroll, children: [
13101
+ /* @__PURE__ */ jsxs88("div", { className: "fdc-log", role: "log", "aria-label": "Conversation", children: [
13102
+ status === "loading" || status === "resolving" ? /* @__PURE__ */ jsx101(LoadingTurns, {}) : null,
13103
+ status === "disconnected" ? /* @__PURE__ */ jsxs88("div", { className: "fdc-dead", children: [
13104
+ /* @__PURE__ */ jsx101("span", { className: "fdc-dead-icon", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-plugs", "aria-hidden": "true" }) }),
13105
+ /* @__PURE__ */ jsx101("h3", { className: "fdc-dead-title", children: ctx.deadTitle || "The assistant isn\u2019t reachable" }),
13106
+ /* @__PURE__ */ jsx101("p", { className: "fdc-dead-body", children: fatal === "chat_unavailable" ? "The service reported chat_unavailable. Nothing you type will be lost \u2014 reopen the panel once it\u2019s back." : "The thread couldn\u2019t be resolved" + (fatal ? " (" + fatal + ")" : "") + ". The composer stays disabled until it resolves." }),
13107
+ ctx.onReconnect ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fd-btn fd-btn-secondary fd-btn-sm", onClick: ctx.onReconnect, children: [
13108
+ /* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-clockwise", "aria-hidden": "true" }),
12996
13109
  "Try again"
12997
13110
  ] }) : null
12998
13111
  ] }) : null,
12999
- empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs87("div", { className: "fdc-empty", children: [
13000
- /* @__PURE__ */ jsx99("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx99("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
13001
- /* @__PURE__ */ jsx99("h3", { className: "fdc-empty-title", children: emptyTitle }),
13002
- emptyDescription ? /* @__PURE__ */ jsx99("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
13003
- /* @__PURE__ */ jsx99(Suggestions, { items: suggestions, onPick })
13112
+ empty ? renderEmpty ? renderEmpty() : /* @__PURE__ */ jsxs88("div", { className: "fdc-empty", children: [
13113
+ /* @__PURE__ */ jsx101("span", { className: "fdc-empty-icon", children: /* @__PURE__ */ jsx101("i", { className: "ph ph-" + emptyIcon, "aria-hidden": "true" }) }),
13114
+ /* @__PURE__ */ jsx101("h3", { className: "fdc-empty-title", children: emptyTitle }),
13115
+ emptyDescription ? /* @__PURE__ */ jsx101("p", { className: "fdc-empty-body", children: emptyDescription }) : null,
13116
+ /* @__PURE__ */ jsx101(Suggestions, { items: suggestions, onPick })
13004
13117
  ] }) : null,
13005
13118
  groups.map((g, i) => {
13006
13119
  const prev = groups[i - 1];
13007
13120
  const k = dayKey(g.messages[0].timestamp);
13008
13121
  const showDay = !!k && (!prev || dayKey(prev.messages[0].timestamp) !== k);
13009
- return /* @__PURE__ */ jsxs87(React71.Fragment, { children: [
13010
- showDay ? /* @__PURE__ */ jsx99("div", { className: "fdc-day", children: /* @__PURE__ */ jsx99("span", { children: dayLabel(k) }) }) : null,
13011
- /* @__PURE__ */ jsx99(ChatTurn, { group: g, ctx })
13122
+ return /* @__PURE__ */ jsxs88(React72.Fragment, { children: [
13123
+ showDay ? /* @__PURE__ */ jsx101("div", { className: "fdc-day", children: /* @__PURE__ */ jsx101("span", { children: dayLabel(k) }) }) : null,
13124
+ /* @__PURE__ */ jsx101(ChatTurn, { group: g, ctx })
13012
13125
  ] }, g.key || i);
13013
13126
  })
13014
13127
  ] }),
13015
- pill ? /* @__PURE__ */ jsxs87("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
13016
- /* @__PURE__ */ jsx99("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
13128
+ pill ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-pill", onClick: () => toBottom(true), children: [
13129
+ /* @__PURE__ */ jsx101("i", { className: "ph ph-arrow-down", "aria-hidden": "true" }),
13017
13130
  pill,
13018
13131
  " new message",
13019
13132
  pill === 1 ? "" : "s"
@@ -13023,8 +13136,8 @@ function ChatTranscript({
13023
13136
  var TranscriptKit = { groupMessages };
13024
13137
 
13025
13138
  // src/components/chat/ChatComposer.tsx
13026
- import * as React72 from "react";
13027
- import { jsx as jsx100, jsxs as jsxs88 } from "react/jsx-runtime";
13139
+ import * as React73 from "react";
13140
+ import { jsx as jsx102, jsxs as jsxs89 } from "react/jsx-runtime";
13028
13141
  function ChatComposer({
13029
13142
  onSubmit,
13030
13143
  onStop,
@@ -13051,17 +13164,17 @@ function ChatComposer({
13051
13164
  onReject,
13052
13165
  onOpenAttachment
13053
13166
  }) {
13054
- const [text, setText] = React72.useState(draft || "");
13055
- const [trigger, setTrigger] = React72.useState(null);
13056
- const [mentionItems, setMentionItems] = React72.useState([]);
13057
- const [listening, setListening] = React72.useState(false);
13058
- const [notice, setNotice] = React72.useState(null);
13059
- const editor = React72.useRef(null);
13060
- const wrap = React72.useRef(null);
13061
- const stopVoice = React72.useRef(null);
13167
+ const [text, setText] = React73.useState(draft || "");
13168
+ const [trigger, setTrigger] = React73.useState(null);
13169
+ const [mentionItems, setMentionItems] = React73.useState([]);
13170
+ const [listening, setListening] = React73.useState(false);
13171
+ const [notice, setNotice] = React73.useState(null);
13172
+ const editor = React73.useRef(null);
13173
+ const wrap = React73.useRef(null);
13174
+ const stopVoice = React73.useRef(null);
13062
13175
  const staged = useStagedFiles(fileUploadHandler, { onError: () => {
13063
13176
  } });
13064
- React72.useEffect(() => {
13177
+ React73.useEffect(() => {
13065
13178
  if (draft != null && draft !== text) setText(draft);
13066
13179
  }, [draft]);
13067
13180
  const change = (v) => {
@@ -13097,7 +13210,7 @@ function ChatComposer({
13097
13210
  e.preventDefault();
13098
13211
  staged.add(found.files);
13099
13212
  };
13100
- React72.useEffect(() => {
13213
+ React73.useEffect(() => {
13101
13214
  if (!trigger || trigger.type !== "mention" || !mentionSources) {
13102
13215
  setMentionItems([]);
13103
13216
  return;
@@ -13115,7 +13228,7 @@ function ChatComposer({
13115
13228
  const q = (trigger.query || "").toLowerCase();
13116
13229
  setMentionItems(mentionSources.filter((m) => !q || (m.label + " " + (m.description || "")).toLowerCase().includes(q)));
13117
13230
  }, [trigger, mentionSources]);
13118
- const slashItems = React72.useMemo(() => {
13231
+ const slashItems = React73.useMemo(() => {
13119
13232
  if (!trigger || trigger.type !== "slash" || !slashCommands) return [];
13120
13233
  const q = (trigger.query || "").toLowerCase();
13121
13234
  return slashCommands.filter((c) => !q || (c.id + " " + c.label + " " + (c.description || "")).toLowerCase().includes(q));
@@ -13129,7 +13242,7 @@ function ChatComposer({
13129
13242
  description: it.description,
13130
13243
  icon: it.icon,
13131
13244
  meta: mention.meta,
13132
- shortcut: slash.shortcut ? /* @__PURE__ */ jsx100(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
13245
+ shortcut: slash.shortcut ? /* @__PURE__ */ jsx102(KeyHint, { keys: slash.shortcut, size: "sm" }) : void 0,
13133
13246
  onSelect: () => {
13134
13247
  const insert = trigger.type === "slash" ? slash.immediate ? "/" + slash.id : "/" + slash.id + " " : "@" + (mention.value || mention.label) + " ";
13135
13248
  editor.current && editor.current.replaceRange(trigger.from, trigger.to, insert);
@@ -13188,14 +13301,14 @@ function ChatComposer({
13188
13301
  stopVoice.current = typeof res === "function" ? res : () => {
13189
13302
  };
13190
13303
  };
13191
- return /* @__PURE__ */ jsxs88("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
13192
- queue.length ? /* @__PURE__ */ jsx100("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs88("div", { className: "fdc-queue-row", children: [
13193
- /* @__PURE__ */ jsx100("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
13194
- /* @__PURE__ */ jsx100("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
13195
- onRemoveQueued ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13304
+ return /* @__PURE__ */ jsxs89("div", { className: "fdc-composer" + (disabled ? " is-disabled" : "") + (narrow ? " is-narrow" : ""), children: [
13305
+ queue.length ? /* @__PURE__ */ jsx102("div", { className: "fdc-queue", "aria-label": "Queued messages", children: queue.map((q) => /* @__PURE__ */ jsxs89("div", { className: "fdc-queue-row", children: [
13306
+ /* @__PURE__ */ jsx102("i", { className: "ph ph-clock-countdown", "aria-hidden": "true" }),
13307
+ /* @__PURE__ */ jsx102("span", { className: "fdc-queue-text", title: truncationTitle(q.text || (q.attachments ? q.attachments.length + " file(s)" : "")), children: q.text || (q.attachments ? q.attachments.length + " file(s)" : "") }),
13308
+ onRemoveQueued ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fdc-queue-x", onClick: () => onRemoveQueued(q.id), "aria-label": "Remove queued message", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13196
13309
  ] }, q.id)) }) : null,
13197
13310
  sessionBar,
13198
- /* @__PURE__ */ jsx100(
13311
+ /* @__PURE__ */ jsx102(
13199
13312
  Dropzone,
13200
13313
  {
13201
13314
  className: "fdc-field",
@@ -13209,9 +13322,9 @@ function ChatComposer({
13209
13322
  disabled: !fileUploadHandler || disabled,
13210
13323
  label: "Drop to attach",
13211
13324
  hint: acceptFiles ? acceptFiles.replace(/,/g, " \xB7 ") : void 0,
13212
- children: /* @__PURE__ */ jsxs88("div", { ref: wrap, className: "fdc-field-inner", children: [
13213
- staged.items.length ? /* @__PURE__ */ jsx100("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx100(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
13214
- /* @__PURE__ */ jsx100(
13325
+ children: /* @__PURE__ */ jsxs89("div", { ref: wrap, className: "fdc-field-inner", children: [
13326
+ staged.items.length ? /* @__PURE__ */ jsx102("div", { className: "fdc-staged", children: /* @__PURE__ */ jsx102(FileStrip, { files: staged.items, size: narrow ? 60 : 68, onRemove: staged.remove, onRetry: staged.retry, onOpen: onOpenAttachment }) }) : null,
13327
+ /* @__PURE__ */ jsx102(
13215
13328
  MarkdownEditor,
13216
13329
  {
13217
13330
  ref: editor,
@@ -13230,33 +13343,33 @@ function ChatComposer({
13230
13343
  ariaLabel: "Message"
13231
13344
  }
13232
13345
  ),
13233
- /* @__PURE__ */ jsxs88("div", { className: "fdc-tools", children: [
13234
- fileUploadHandler ? /* @__PURE__ */ jsx100(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
13235
- voiceHandler ? /* @__PURE__ */ jsx100("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx100("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
13346
+ /* @__PURE__ */ jsxs89("div", { className: "fdc-tools", children: [
13347
+ fileUploadHandler ? /* @__PURE__ */ jsx102(FilePickButton, { onFiles: staged.add, onReject: (r) => flash(r[0].message), accept: acceptFiles, maxFileSize, label: "Attach files", icon: "plus" }) : null,
13348
+ voiceHandler ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fd-attachbtn" + (listening ? " is-live" : ""), onClick: voice, "aria-pressed": listening, "aria-label": listening ? "Stop dictation" : "Dictate", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-" + (listening ? "waveform" : "microphone"), "aria-hidden": "true" }) }) : null,
13236
13349
  toolbarExtras,
13237
- /* @__PURE__ */ jsx100("span", { className: "fdc-tools-gap" }),
13238
- maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs88("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
13350
+ /* @__PURE__ */ jsx102("span", { className: "fdc-tools-gap" }),
13351
+ maxLength && text.length > maxLength * 0.6 ? /* @__PURE__ */ jsxs89("span", { className: "fdc-count fd-tabular" + (text.length > maxLength * 0.95 ? " is-hot" : ""), children: [
13239
13352
  text.length,
13240
13353
  "/",
13241
13354
  maxLength
13242
13355
  ] }) : null,
13243
- busy ? /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
13244
- /* @__PURE__ */ jsx100("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
13245
- /* @__PURE__ */ jsx100("span", { children: "Stop" })
13246
- ] }) : /* @__PURE__ */ jsxs88("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
13247
- /* @__PURE__ */ jsx100("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
13248
- /* @__PURE__ */ jsx100("span", { className: "fdc-send-label", children: "Send" })
13356
+ busy ? /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-stop", onClick: onStop, "aria-label": "Stop generating", children: [
13357
+ /* @__PURE__ */ jsx102("i", { className: "ph ph-stop-circle", "aria-hidden": "true" }),
13358
+ /* @__PURE__ */ jsx102("span", { children: "Stop" })
13359
+ ] }) : /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-send", onClick: submit, disabled: !canSend, "aria-label": "Send message", children: [
13360
+ /* @__PURE__ */ jsx102("i", { className: "ph ph-paper-plane-right", "aria-hidden": "true" }),
13361
+ /* @__PURE__ */ jsx102("span", { className: "fdc-send-label", children: "Send" })
13249
13362
  ] })
13250
13363
  ] })
13251
13364
  ] })
13252
13365
  }
13253
13366
  ),
13254
- notice ? /* @__PURE__ */ jsxs88("div", { className: "fdc-notice", role: "status", children: [
13255
- /* @__PURE__ */ jsx100("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
13367
+ notice ? /* @__PURE__ */ jsxs89("div", { className: "fdc-notice", role: "status", children: [
13368
+ /* @__PURE__ */ jsx102("i", { className: "ph ph-warning-circle", "aria-hidden": "true" }),
13256
13369
  notice
13257
13370
  ] }) : null,
13258
- hint && !notice ? /* @__PURE__ */ jsx100("div", { className: "fdc-hint", children: hint }) : null,
13259
- /* @__PURE__ */ jsx100(
13371
+ hint && !notice ? /* @__PURE__ */ jsx102("div", { className: "fdc-hint", children: hint }) : null,
13372
+ /* @__PURE__ */ jsx102(
13260
13373
  Popover,
13261
13374
  {
13262
13375
  open: menuOpen,
@@ -13270,12 +13383,12 @@ function ChatComposer({
13270
13383
  returnFocus: false,
13271
13384
  closeOnOutside: true,
13272
13385
  label: trigger && trigger.type === "slash" ? "Commands" : "Mentions",
13273
- children: /* @__PURE__ */ jsx100(
13386
+ children: /* @__PURE__ */ jsx102(
13274
13387
  Menu,
13275
13388
  {
13276
13389
  items: menuItems,
13277
13390
  autoFocus: false,
13278
- header: /* @__PURE__ */ jsx100("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
13391
+ header: /* @__PURE__ */ jsx102("div", { className: "fd-pop-group", children: trigger && trigger.type === "slash" ? "Commands" : "Attach context" }),
13279
13392
  onClose: () => setTrigger(null)
13280
13393
  }
13281
13394
  )
@@ -13285,12 +13398,12 @@ function ChatComposer({
13285
13398
  }
13286
13399
 
13287
13400
  // src/components/chat/ChatSessionBar.tsx
13288
- import * as React73 from "react";
13289
- import { jsx as jsx101, jsxs as jsxs89 } from "react/jsx-runtime";
13401
+ import * as React74 from "react";
13402
+ import { jsx as jsx103, jsxs as jsxs90 } from "react/jsx-runtime";
13290
13403
  var compact2 = meterFormats.compact;
13291
13404
  function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extras }) {
13292
- const [open2, setOpen] = React73.useState(false);
13293
- const anchor = React73.useRef(null);
13405
+ const [open2, setOpen] = React74.useState(false);
13406
+ const anchor = React74.useRef(null);
13294
13407
  const stats = sessionStats || null;
13295
13408
  const cu = contextUsage || null;
13296
13409
  const limits = usageLimits || null;
@@ -13305,9 +13418,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13305
13418
  if (stats && stats.runningTasks) bits.push(stats.runningTasks + " running task" + (stats.runningTasks === 1 ? "" : "s"));
13306
13419
  if (cu) bits.push(pct + "% context");
13307
13420
  const expandable = !!(cu || limits);
13308
- return /* @__PURE__ */ jsxs89(React73.Fragment, { children: [
13309
- /* @__PURE__ */ jsxs89("div", { className: "fdc-bar", children: [
13310
- /* @__PURE__ */ jsxs89(
13421
+ return /* @__PURE__ */ jsxs90(React74.Fragment, { children: [
13422
+ /* @__PURE__ */ jsxs90("div", { className: "fdc-bar", children: [
13423
+ /* @__PURE__ */ jsxs90(
13311
13424
  "button",
13312
13425
  {
13313
13426
  type: "button",
@@ -13318,15 +13431,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13318
13431
  "aria-expanded": expandable ? open2 : void 0,
13319
13432
  "aria-label": expandable ? "Usage details" : void 0,
13320
13433
  children: [
13321
- cu ? /* @__PURE__ */ jsx101("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx101(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
13322
- /* @__PURE__ */ jsx101("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
13323
- expandable ? /* @__PURE__ */ jsx101("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
13434
+ cu ? /* @__PURE__ */ jsx103("span", { className: "fdc-bar-mini", "aria-hidden": "true", children: /* @__PURE__ */ jsx103(SegmentedMeter, { total, segments: cu.segments, height: 4, showTotal: false }) }) : null,
13435
+ /* @__PURE__ */ jsx103("span", { className: "fdc-bar-text", title: truncationTitle(bits.join(" \xB7 ")), children: bits.join(" \xB7 ") }),
13436
+ expandable ? /* @__PURE__ */ jsx103("i", { className: "ph ph-caret-right fdc-bar-caret", "aria-hidden": "true" }) : null
13324
13437
  ]
13325
13438
  }
13326
13439
  ),
13327
13440
  extras
13328
13441
  ] }),
13329
- /* @__PURE__ */ jsx101(
13442
+ /* @__PURE__ */ jsx103(
13330
13443
  Popover,
13331
13444
  {
13332
13445
  open: open2,
@@ -13337,15 +13450,15 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13337
13450
  maxHeight: 460,
13338
13451
  padded: true,
13339
13452
  label: "Usage",
13340
- footer: onClear ? /* @__PURE__ */ jsxs89("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
13453
+ footer: onClear ? /* @__PURE__ */ jsxs90("button", { type: "button", className: "fdc-usage-clear", onClick: () => {
13341
13454
  setOpen(false);
13342
13455
  onClear();
13343
13456
  }, children: [
13344
- /* @__PURE__ */ jsx101("i", { className: "ph ph-trash", "aria-hidden": "true" }),
13457
+ /* @__PURE__ */ jsx103("i", { className: "ph ph-trash", "aria-hidden": "true" }),
13345
13458
  "Clear conversation"
13346
13459
  ] }) : void 0,
13347
- children: /* @__PURE__ */ jsxs89("div", { className: "fdc-usage", children: [
13348
- cu ? /* @__PURE__ */ jsx101("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx101(
13460
+ children: /* @__PURE__ */ jsxs90("div", { className: "fdc-usage", children: [
13461
+ cu ? /* @__PURE__ */ jsx103("section", { className: "fdc-usage-sec", children: /* @__PURE__ */ jsx103(
13349
13462
  SegmentedMeter,
13350
13463
  {
13351
13464
  total,
@@ -13357,9 +13470,9 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13357
13470
  remainderLabel: "Free"
13358
13471
  }
13359
13472
  ) }) : null,
13360
- limits && limits.length ? /* @__PURE__ */ jsxs89("section", { className: "fdc-usage-sec", children: [
13361
- /* @__PURE__ */ jsx101("h4", { className: "fdc-usage-h", children: "Usage limits" }),
13362
- /* @__PURE__ */ jsx101("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx101(
13473
+ limits && limits.length ? /* @__PURE__ */ jsxs90("section", { className: "fdc-usage-sec", children: [
13474
+ /* @__PURE__ */ jsx103("h4", { className: "fdc-usage-h", children: "Usage limits" }),
13475
+ /* @__PURE__ */ jsx103("div", { className: "fdc-usage-rows", children: limits.map((l) => /* @__PURE__ */ jsx103(
13363
13476
  QuotaRow,
13364
13477
  {
13365
13478
  label: l.label,
@@ -13369,25 +13482,25 @@ function ChatSessionBar({ sessionStats, contextUsage, usageLimits, onClear, extr
13369
13482
  l.id
13370
13483
  )) })
13371
13484
  ] }) : null,
13372
- stats ? /* @__PURE__ */ jsxs89("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
13373
- stats.elapsedMs ? /* @__PURE__ */ jsxs89("div", { children: [
13374
- /* @__PURE__ */ jsx101("span", { children: "Session" }),
13375
- /* @__PURE__ */ jsx101("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
13485
+ stats ? /* @__PURE__ */ jsxs90("section", { className: "fdc-usage-sec fdc-usage-stats", children: [
13486
+ stats.elapsedMs ? /* @__PURE__ */ jsxs90("div", { children: [
13487
+ /* @__PURE__ */ jsx103("span", { children: "Session" }),
13488
+ /* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: formatDuration(stats.elapsedMs) })
13376
13489
  ] }) : null,
13377
- stats.tokens ? /* @__PURE__ */ jsxs89("div", { children: [
13378
- /* @__PURE__ */ jsx101("span", { children: "Tokens" }),
13379
- /* @__PURE__ */ jsx101("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
13490
+ stats.tokens ? /* @__PURE__ */ jsxs90("div", { children: [
13491
+ /* @__PURE__ */ jsx103("span", { children: "Tokens" }),
13492
+ /* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: stats.tokens.toLocaleString() })
13380
13493
  ] }) : null,
13381
- stats.costUsd != null ? /* @__PURE__ */ jsxs89("div", { children: [
13382
- /* @__PURE__ */ jsx101("span", { children: "Cost" }),
13383
- /* @__PURE__ */ jsxs89("b", { className: "fd-tabular", children: [
13494
+ stats.costUsd != null ? /* @__PURE__ */ jsxs90("div", { children: [
13495
+ /* @__PURE__ */ jsx103("span", { children: "Cost" }),
13496
+ /* @__PURE__ */ jsxs90("b", { className: "fd-tabular", children: [
13384
13497
  "$",
13385
13498
  Number(stats.costUsd).toFixed(3)
13386
13499
  ] })
13387
13500
  ] }) : null,
13388
- stats.turns ? /* @__PURE__ */ jsxs89("div", { children: [
13389
- /* @__PURE__ */ jsx101("span", { children: "Turns" }),
13390
- /* @__PURE__ */ jsx101("b", { className: "fd-tabular", children: stats.turns })
13501
+ stats.turns ? /* @__PURE__ */ jsxs90("div", { children: [
13502
+ /* @__PURE__ */ jsx103("span", { children: "Turns" }),
13503
+ /* @__PURE__ */ jsx103("b", { className: "fd-tabular", children: stats.turns })
13391
13504
  ] }) : null
13392
13505
  ] }) : null
13393
13506
  ] })
@@ -13426,7 +13539,7 @@ function ModelControls({
13426
13539
  disabled: m.disabled,
13427
13540
  checked: m.id === (current2 && current2.id),
13428
13541
  meta: m.meta,
13429
- shortcut: m.shortcut ? /* @__PURE__ */ jsx101(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
13542
+ shortcut: m.shortcut ? /* @__PURE__ */ jsx103(KeyHint, { keys: m.shortcut, size: "sm" }) : void 0,
13430
13543
  onSelect: () => onModelChange && onModelChange(m.id)
13431
13544
  });
13432
13545
  const items = [{ kind: "section", label: "Models" }].concat(flat.map(item));
@@ -13439,15 +13552,15 @@ function ModelControls({
13439
13552
  items.push({ kind: "section", label: "Fast mode" });
13440
13553
  items.push({
13441
13554
  kind: "custom",
13442
- render: () => /* @__PURE__ */ jsxs89("label", { className: "fdc-switchrow", children: [
13443
- /* @__PURE__ */ jsx101("span", { children: fastModeLabel }),
13444
- /* @__PURE__ */ jsx101("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13445
- /* @__PURE__ */ jsx101("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx101("span", { className: "fd-switch-thumb" }) })
13555
+ render: () => /* @__PURE__ */ jsxs90("label", { className: "fdc-switchrow", children: [
13556
+ /* @__PURE__ */ jsx103("span", { children: fastModeLabel }),
13557
+ /* @__PURE__ */ jsx103("input", { type: "checkbox", className: "fd-sr", checked: !!fastMode, onChange: (e) => onFastModeChange(e.target.checked) }),
13558
+ /* @__PURE__ */ jsx103("span", { className: "fd-switch-track" + (fastMode ? " is-on" : ""), "aria-hidden": "true", children: /* @__PURE__ */ jsx103("span", { className: "fd-switch-thumb" }) })
13446
13559
  ] })
13447
13560
  });
13448
13561
  }
13449
- return /* @__PURE__ */ jsxs89(React73.Fragment, { children: [
13450
- /* @__PURE__ */ jsx101(
13562
+ return /* @__PURE__ */ jsxs90(React74.Fragment, { children: [
13563
+ /* @__PURE__ */ jsx103(
13451
13564
  MenuButton,
13452
13565
  {
13453
13566
  items,
@@ -13458,7 +13571,7 @@ function ModelControls({
13458
13571
  title: "Choose a model"
13459
13572
  }
13460
13573
  ),
13461
- effortLevels && effortLevels.length ? /* @__PURE__ */ jsx101(
13574
+ effortLevels && effortLevels.length ? /* @__PURE__ */ jsx103(
13462
13575
  MenuButton,
13463
13576
  {
13464
13577
  placement: "top-end",
@@ -13479,7 +13592,7 @@ function ModelControls({
13479
13592
  }
13480
13593
 
13481
13594
  // src/components/chat/AgentChatPanel.tsx
13482
- import { jsx as jsx102, jsxs as jsxs90 } from "react/jsx-runtime";
13595
+ import { jsx as jsx104, jsxs as jsxs91 } from "react/jsx-runtime";
13483
13596
  var SURFACES = { sidebar: "is-sidebar", inline: "is-inline", page: "is-page", modal: "is-modal", sheet: "is-sheet" };
13484
13597
  function AgentChatPanel({
13485
13598
  /* required */
@@ -13513,6 +13626,7 @@ function AgentChatPanel({
13513
13626
  packetSchemas,
13514
13627
  packetRenderers,
13515
13628
  onApplyPacket,
13629
+ pendingTimeoutMs,
13516
13630
  onOpenAttachment,
13517
13631
  errorCopy,
13518
13632
  /* composer */
@@ -13563,17 +13677,18 @@ function AgentChatPanel({
13563
13677
  onFeedback,
13564
13678
  onEditMessage
13565
13679
  }) {
13566
- const [panelWidth, setPanelWidth] = React74.useState(width);
13567
- const [applied, setApplied] = React74.useState({});
13568
- const [draft, setDraft] = React74.useState("");
13569
- const dragging = React74.useRef(null);
13570
- React74.useEffect(() => setPanelWidth(width), [width]);
13680
+ const [panelWidth, setPanelWidth] = React75.useState(width);
13681
+ const [applied, setApplied] = React75.useState({});
13682
+ const [draft, setDraft] = React75.useState("");
13683
+ const dragging = React75.useRef(null);
13684
+ React75.useEffect(() => setPanelWidth(width), [width]);
13571
13685
  const engine = useChatEngine({
13572
13686
  contextType,
13573
13687
  contextId,
13574
13688
  apiAdapter,
13575
13689
  initialMessage,
13576
13690
  threadId,
13691
+ pendingTimeoutMs,
13577
13692
  onPacket,
13578
13693
  onThreadReady,
13579
13694
  onError,
@@ -13633,7 +13748,7 @@ function AgentChatPanel({
13633
13748
  onReconnect: engine.reload,
13634
13749
  deadTitle: "The assistant isn\u2019t reachable"
13635
13750
  };
13636
- const sessionBar = /* @__PURE__ */ jsx102(
13751
+ const sessionBar = /* @__PURE__ */ jsx104(
13637
13752
  ChatSessionBar,
13638
13753
  {
13639
13754
  sessionStats,
@@ -13642,7 +13757,7 @@ function AgentChatPanel({
13642
13757
  onClear: engine.visible.length ? engine.clear : void 0
13643
13758
  }
13644
13759
  );
13645
- const modelControls = /* @__PURE__ */ jsx102(
13760
+ const modelControls = /* @__PURE__ */ jsx104(
13646
13761
  ModelControls,
13647
13762
  {
13648
13763
  models,
@@ -13657,7 +13772,7 @@ function AgentChatPanel({
13657
13772
  narrow
13658
13773
  }
13659
13774
  );
13660
- const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx102(
13775
+ const threadMenu = threads && threads.length ? /* @__PURE__ */ jsx104(
13661
13776
  MenuButton,
13662
13777
  {
13663
13778
  variant: "ghost",
@@ -13684,7 +13799,7 @@ function AgentChatPanel({
13684
13799
  })))
13685
13800
  }
13686
13801
  ) : null;
13687
- return /* @__PURE__ */ jsxs90(
13802
+ return /* @__PURE__ */ jsxs91(
13688
13803
  "aside",
13689
13804
  {
13690
13805
  className: ["fdc-panel", SURFACES[surface] || SURFACES.sidebar, narrow ? "is-narrow" : "", className].filter(Boolean).join(" "),
@@ -13695,7 +13810,7 @@ function AgentChatPanel({
13695
13810
  },
13696
13811
  "aria-label": title,
13697
13812
  children: [
13698
- surface === "sidebar" && resizable ? /* @__PURE__ */ jsx102(
13813
+ surface === "sidebar" && resizable ? /* @__PURE__ */ jsx104(
13699
13814
  "div",
13700
13815
  {
13701
13816
  className: "fdc-grip",
@@ -13710,20 +13825,20 @@ function AgentChatPanel({
13710
13825
  }
13711
13826
  }
13712
13827
  ) : null,
13713
- showHeader ? /* @__PURE__ */ jsxs90("header", { className: "fdc-head", children: [
13714
- /* @__PURE__ */ jsx102("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-" + assistantIcon }) }),
13715
- /* @__PURE__ */ jsxs90("span", { className: "fdc-head-titles", children: [
13716
- /* @__PURE__ */ jsx102("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13717
- subtitle ? /* @__PURE__ */ jsx102("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13828
+ showHeader ? /* @__PURE__ */ jsxs91("header", { className: "fdc-head", children: [
13829
+ /* @__PURE__ */ jsx104("span", { className: "fdc-head-mark", "aria-hidden": "true", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-" + assistantIcon }) }),
13830
+ /* @__PURE__ */ jsxs91("span", { className: "fdc-head-titles", children: [
13831
+ /* @__PURE__ */ jsx104("span", { className: "fdc-head-title", title: truncationTitle(title), children: title }),
13832
+ subtitle ? /* @__PURE__ */ jsx104("span", { className: "fdc-head-sub", title: truncationTitle(subtitle), children: subtitle }) : null
13718
13833
  ] }),
13719
- /* @__PURE__ */ jsxs90("span", { className: "fdc-head-acts", children: [
13834
+ /* @__PURE__ */ jsxs91("span", { className: "fdc-head-acts", children: [
13720
13835
  headerActions,
13721
13836
  threadMenu,
13722
- onNewThread ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13723
- onClose ? /* @__PURE__ */ jsx102("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx102("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13837
+ onNewThread ? /* @__PURE__ */ jsx104("button", { type: "button", className: "fdc-iconbtn", onClick: onNewThread, "aria-label": "New conversation", title: "New conversation", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-plus", "aria-hidden": "true" }) }) : null,
13838
+ onClose ? /* @__PURE__ */ jsx104("button", { type: "button", className: "fdc-iconbtn", onClick: onClose, "aria-label": "Close panel", title: "Close", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-x", "aria-hidden": "true" }) }) : null
13724
13839
  ] })
13725
13840
  ] }) : null,
13726
- /* @__PURE__ */ jsx102(
13841
+ /* @__PURE__ */ jsx104(
13727
13842
  ChatTranscript,
13728
13843
  {
13729
13844
  messages: engine.visible,
@@ -13738,7 +13853,7 @@ function AgentChatPanel({
13738
13853
  renderEmpty
13739
13854
  }
13740
13855
  ),
13741
- /* @__PURE__ */ jsx102(
13856
+ /* @__PURE__ */ jsx104(
13742
13857
  ChatComposer,
13743
13858
  {
13744
13859
  onSubmit: (text, atts) => engine.send(text, atts),
@@ -13771,8 +13886,8 @@ function AgentChatPanel({
13771
13886
  }
13772
13887
 
13773
13888
  // src/components/files/FileViewer.tsx
13774
- import * as React75 from "react";
13775
- import { jsx as jsx103, jsxs as jsxs91 } from "react/jsx-runtime";
13889
+ import * as React76 from "react";
13890
+ import { jsx as jsx105, jsxs as jsxs92 } from "react/jsx-runtime";
13776
13891
  function previewKindOf(file) {
13777
13892
  const mime = (file.mime || "").toLowerCase();
13778
13893
  const ext = extensionOf(file.name || "");
@@ -13828,13 +13943,13 @@ function parseDelimited(text, delimiter) {
13828
13943
  return rows;
13829
13944
  }
13830
13945
  function usePreview(file, kind, resolveUrl) {
13831
- const [state, setState] = React75.useState({ status: "loading" });
13832
- const [attempt, setAttempt] = React75.useState(0);
13833
- const resolveRef = React75.useRef(resolveUrl);
13834
- React75.useEffect(() => {
13946
+ const [state, setState] = React76.useState({ status: "loading" });
13947
+ const [attempt, setAttempt] = React76.useState(0);
13948
+ const resolveRef = React76.useRef(resolveUrl);
13949
+ React76.useEffect(() => {
13835
13950
  resolveRef.current = resolveUrl;
13836
13951
  }, [resolveUrl]);
13837
- React75.useEffect(() => {
13952
+ React76.useEffect(() => {
13838
13953
  if (kind === "none") {
13839
13954
  setState({ status: "ready" });
13840
13955
  return;
@@ -13864,19 +13979,19 @@ function usePreview(file, kind, resolveUrl) {
13864
13979
  if (ac) ac.abort();
13865
13980
  };
13866
13981
  }, [file.id, kind, attempt]);
13867
- return { ...state, retry: React75.useCallback(() => setAttempt((a) => a + 1), []) };
13982
+ return { ...state, retry: React76.useCallback(() => setAttempt((a) => a + 1), []) };
13868
13983
  }
13869
13984
  function PreviewBody({ file, kind, state }) {
13870
- if (kind === "image") return /* @__PURE__ */ jsx103("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13871
- if (kind === "pdf") return /* @__PURE__ */ jsx103("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13872
- if (kind === "markdown") return /* @__PURE__ */ jsx103(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13985
+ if (kind === "image") return /* @__PURE__ */ jsx105("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
13986
+ if (kind === "pdf") return /* @__PURE__ */ jsx105("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
13987
+ if (kind === "markdown") return /* @__PURE__ */ jsx105(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
13873
13988
  if (kind === "json") {
13874
13989
  let pretty = state.text || "";
13875
13990
  try {
13876
13991
  pretty = JSON.stringify(JSON.parse(pretty), null, 2);
13877
13992
  } catch {
13878
13993
  }
13879
- return /* @__PURE__ */ jsx103(CodeBlock, { code: pretty, language: "json" });
13994
+ return /* @__PURE__ */ jsx105(CodeBlock, { code: pretty, language: "json" });
13880
13995
  }
13881
13996
  if (kind === "csv") {
13882
13997
  const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
@@ -13884,12 +13999,12 @@ function PreviewBody({ file, kind, state }) {
13884
13999
  const head = rows[0] || [];
13885
14000
  const dataRows = rows.slice(1);
13886
14001
  const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
13887
- return /* @__PURE__ */ jsxs91("div", { className: "fd-fv-csv", children: [
13888
- /* @__PURE__ */ jsxs91("table", { className: "fd-fv-csv-table", children: [
13889
- /* @__PURE__ */ jsx103("thead", { children: /* @__PURE__ */ jsx103("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx103("th", { children: c }, i)) }) }),
13890
- /* @__PURE__ */ jsx103("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx103("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx103("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
14002
+ return /* @__PURE__ */ jsxs92("div", { className: "fd-fv-csv", children: [
14003
+ /* @__PURE__ */ jsxs92("table", { className: "fd-fv-csv-table", children: [
14004
+ /* @__PURE__ */ jsx105("thead", { children: /* @__PURE__ */ jsx105("tr", { children: head.map((c, i) => /* @__PURE__ */ jsx105("th", { children: c }, i)) }) }),
14005
+ /* @__PURE__ */ jsx105("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ jsx105("tr", { children: head.map((_, ci) => /* @__PURE__ */ jsx105("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
13891
14006
  ] }),
13892
- dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs91("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
14007
+ dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ jsxs92("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
13893
14008
  "Showing the first ",
13894
14009
  FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
13895
14010
  " of ",
@@ -13898,24 +14013,24 @@ function PreviewBody({ file, kind, state }) {
13898
14013
  ] }) : null
13899
14014
  ] });
13900
14015
  }
13901
- if (kind === "text") return /* @__PURE__ */ jsx103(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
13902
- return /* @__PURE__ */ jsxs91("div", { className: "fd-fv-fallback", children: [
13903
- /* @__PURE__ */ jsx103("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx103("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13904
- /* @__PURE__ */ jsx103("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
13905
- /* @__PURE__ */ jsxs91("span", { className: "fd-fv-fallback-meta", children: [
14016
+ if (kind === "text") return /* @__PURE__ */ jsx105(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
14017
+ return /* @__PURE__ */ jsxs92("div", { className: "fd-fv-fallback", children: [
14018
+ /* @__PURE__ */ jsx105("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx105("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
14019
+ /* @__PURE__ */ jsx105("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
14020
+ /* @__PURE__ */ jsxs92("span", { className: "fd-fv-fallback-meta", children: [
13906
14021
  file.mime || "Unknown type",
13907
14022
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13908
14023
  ] })
13909
14024
  ] });
13910
14025
  }
13911
14026
  function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
13912
- const kind = React75.useMemo(() => previewKindOf(file), [file]);
14027
+ const kind = React76.useMemo(() => previewKindOf(file), [file]);
13913
14028
  const preview = usePreview(file, kind, resolveUrl);
13914
- const [tab, setTab] = React75.useState("preview");
13915
- const [downloading, setDownloading] = React75.useState(false);
13916
- const [downloadError, setDownloadError] = React75.useState(null);
14029
+ const [tab, setTab] = React76.useState("preview");
14030
+ const [downloading, setDownloading] = React76.useState(false);
14031
+ const [downloadError, setDownloadError] = React76.useState(null);
13917
14032
  const hasSide = sidePanel != null;
13918
- React75.useEffect(() => {
14033
+ React76.useEffect(() => {
13919
14034
  setTab("preview");
13920
14035
  }, [file.id]);
13921
14036
  const download = () => {
@@ -13931,29 +14046,29 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13931
14046
  a.remove();
13932
14047
  }).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
13933
14048
  };
13934
- return /* @__PURE__ */ jsxs91(
14049
+ return /* @__PURE__ */ jsxs92(
13935
14050
  "section",
13936
14051
  {
13937
14052
  className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
13938
14053
  "aria-label": file.name || "File",
13939
14054
  children: [
13940
- /* @__PURE__ */ jsxs91("header", { className: "fd-fv-head", children: [
13941
- /* @__PURE__ */ jsx103("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx103("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
13942
- /* @__PURE__ */ jsxs91("span", { className: "fd-fv-head-titles", children: [
13943
- /* @__PURE__ */ jsx103("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
13944
- /* @__PURE__ */ jsxs91("span", { className: "fd-fv-head-meta", children: [
14055
+ /* @__PURE__ */ jsxs92("header", { className: "fd-fv-head", children: [
14056
+ /* @__PURE__ */ jsx105("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx105("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
14057
+ /* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-titles", children: [
14058
+ /* @__PURE__ */ jsx105("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
14059
+ /* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-meta", children: [
13945
14060
  file.mime || "Unknown type",
13946
14061
  file.size ? " \xB7 " + formatBytes(file.size) : ""
13947
14062
  ] })
13948
14063
  ] }),
13949
- /* @__PURE__ */ jsxs91("span", { className: "fd-fv-head-actions", children: [
14064
+ /* @__PURE__ */ jsxs92("span", { className: "fd-fv-head-actions", children: [
13950
14065
  actions,
13951
- /* @__PURE__ */ jsx103(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
13952
- onClose ? /* @__PURE__ */ jsx103(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
14066
+ /* @__PURE__ */ jsx105(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
14067
+ onClose ? /* @__PURE__ */ jsx105(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
13953
14068
  ] })
13954
14069
  ] }),
13955
- downloadError ? /* @__PURE__ */ jsx103("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
13956
- hasSide ? /* @__PURE__ */ jsx103(
14070
+ downloadError ? /* @__PURE__ */ jsx105("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
14071
+ hasSide ? /* @__PURE__ */ jsx105(
13957
14072
  Tabs,
13958
14073
  {
13959
14074
  className: "fd-fv-tabs",
@@ -13962,19 +14077,19 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13962
14077
  onChange: (v) => setTab(v)
13963
14078
  }
13964
14079
  ) : null,
13965
- /* @__PURE__ */ jsxs91("div", { className: "fd-fv-body", children: [
13966
- /* @__PURE__ */ jsx103("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx103(
14080
+ /* @__PURE__ */ jsxs92("div", { className: "fd-fv-body", children: [
14081
+ /* @__PURE__ */ jsx105("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ jsx105(
13967
14082
  LoadingRegion,
13968
14083
  {
13969
14084
  state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
13970
14085
  error: preview.error,
13971
14086
  label: "Loading preview of " + (file.name || "file"),
13972
14087
  onRetry: preview.status === "error" ? preview.retry : void 0,
13973
- skeleton: /* @__PURE__ */ jsx103(Skeleton, { shape: "card", h: 220 }),
13974
- children: /* @__PURE__ */ jsx103(PreviewBody, { file, kind, state: preview })
14088
+ skeleton: /* @__PURE__ */ jsx105(Skeleton, { shape: "card", h: 220 }),
14089
+ children: /* @__PURE__ */ jsx105(PreviewBody, { file, kind, state: preview })
13975
14090
  }
13976
14091
  ) }),
13977
- hasSide ? /* @__PURE__ */ jsx103("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
14092
+ hasSide ? /* @__PURE__ */ jsx105("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
13978
14093
  ] })
13979
14094
  ]
13980
14095
  }
@@ -13982,8 +14097,8 @@ function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", o
13982
14097
  }
13983
14098
 
13984
14099
  // src/components/files/FileBrowser.tsx
13985
- import * as React76 from "react";
13986
- import { Fragment as Fragment31, jsx as jsx104, jsxs as jsxs92 } from "react/jsx-runtime";
14100
+ import * as React77 from "react";
14101
+ import { Fragment as Fragment31, jsx as jsx106, jsxs as jsxs93 } from "react/jsx-runtime";
13987
14102
  function childrenOf(folders, parentId) {
13988
14103
  return folders.filter((f) => f.parentId === parentId).sort((a, b) => a.name.localeCompare(b.name));
13989
14104
  }
@@ -14055,8 +14170,8 @@ function FolderPickerMenu({
14055
14170
  }) {
14056
14171
  const panel = useInlinePanel();
14057
14172
  const { open: open2, setOpen, ref } = panel;
14058
- return /* @__PURE__ */ jsxs92("span", { className: "fd-fb-menu-anchor", ref, children: [
14059
- /* @__PURE__ */ jsx104(
14173
+ return /* @__PURE__ */ jsxs93("span", { className: "fd-fb-menu-anchor", ref, children: [
14174
+ /* @__PURE__ */ jsx106(
14060
14175
  IconButton,
14061
14176
  {
14062
14177
  icon: "arrows-out-cardinal",
@@ -14068,9 +14183,9 @@ function FolderPickerMenu({
14068
14183
  onClick: () => setOpen((v) => !v)
14069
14184
  }
14070
14185
  ),
14071
- /* @__PURE__ */ jsx104(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs92("div", { className: "fd-fb-menu", children: [
14072
- /* @__PURE__ */ jsx104("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
14073
- destinations.map((d) => /* @__PURE__ */ jsxs92(
14186
+ /* @__PURE__ */ jsx106(InlinePanelSurface, { panel, align: "right", offset: 4, width: 220, maxHeight: 280, role: "menu", label, children: /* @__PURE__ */ jsxs93("div", { className: "fd-fb-menu", children: [
14187
+ /* @__PURE__ */ jsx106("span", { className: "fd-overline fd-muted fd-fb-menu-title", children: "Move to\u2026" }),
14188
+ destinations.map((d) => /* @__PURE__ */ jsxs93(
14074
14189
  "button",
14075
14190
  {
14076
14191
  type: "button",
@@ -14082,7 +14197,7 @@ function FolderPickerMenu({
14082
14197
  setOpen(false);
14083
14198
  },
14084
14199
  children: [
14085
- /* @__PURE__ */ jsx104("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
14200
+ /* @__PURE__ */ jsx106("i", { className: "ph ph-" + (d.id == null ? "house-simple" : "folder-simple"), "aria-hidden": "true" }),
14086
14201
  d.name
14087
14202
  ]
14088
14203
  },
@@ -14092,8 +14207,8 @@ function FolderPickerMenu({
14092
14207
  ] });
14093
14208
  }
14094
14209
  function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropPayload, actions, className = "" }) {
14095
- const [over, setOver] = React76.useState(false);
14096
- const dragCounter = React76.useRef(0);
14210
+ const [over, setOver] = React77.useState(false);
14211
+ const dragCounter = React77.useRef(0);
14097
14212
  const dropHandlers = isDropTarget ? {
14098
14213
  onDragEnter: (e) => {
14099
14214
  if (!hasInternalPayload(e)) return;
@@ -14118,8 +14233,8 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
14118
14233
  if (payload && onDropPayload) onDropPayload(payload);
14119
14234
  }
14120
14235
  } : {};
14121
- return /* @__PURE__ */ jsxs92("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
14122
- /* @__PURE__ */ jsxs92(
14236
+ return /* @__PURE__ */ jsxs93("div", { className: ["fd-fb-row", over ? "is-drop-target" : "", className].filter(Boolean).join(" "), ...dropHandlers, children: [
14237
+ /* @__PURE__ */ jsxs93(
14123
14238
  "button",
14124
14239
  {
14125
14240
  type: "button",
@@ -14128,26 +14243,26 @@ function RowShell({ icon, name, meta, onOpen, draggableId, isDropTarget, onDropP
14128
14243
  draggable: !!draggableId,
14129
14244
  onDragStart: draggableId ? (e) => writeDragPayload(e, draggableId) : void 0,
14130
14245
  children: [
14131
- /* @__PURE__ */ jsx104("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx104("i", { className: "ph ph-" + icon }) }),
14132
- /* @__PURE__ */ jsxs92("span", { className: "fd-fb-row-text", children: [
14133
- /* @__PURE__ */ jsx104("span", { className: "fd-fb-row-name", title: name, children: name }),
14134
- meta ? /* @__PURE__ */ jsx104("span", { className: "fd-fb-row-meta", children: meta }) : null
14246
+ /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx106("i", { className: "ph ph-" + icon }) }),
14247
+ /* @__PURE__ */ jsxs93("span", { className: "fd-fb-row-text", children: [
14248
+ /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-name", title: name, children: name }),
14249
+ meta ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-meta", children: meta }) : null
14135
14250
  ] })
14136
14251
  ]
14137
14252
  }
14138
14253
  ),
14139
- actions ? /* @__PURE__ */ jsx104("span", { className: "fd-fb-row-actions", children: actions }) : null
14254
+ actions ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-row-actions", children: actions }) : null
14140
14255
  ] });
14141
14256
  }
14142
14257
  function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveInto, canMove }) {
14143
14258
  const kids = childrenOf(folders, folder.id);
14144
- const [expanded, setExpanded] = React76.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14145
- React76.useEffect(() => {
14259
+ const [expanded, setExpanded] = React77.useState(() => currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId));
14260
+ React77.useEffect(() => {
14146
14261
  if (currentFolderId != null && isSelfOrDescendant(folders, folder.id, currentFolderId)) setExpanded(true);
14147
14262
  }, [currentFolderId, folder.id, folders]);
14148
14263
  const isCurrent = folder.id === currentFolderId;
14149
- return /* @__PURE__ */ jsxs92("div", { className: "fd-fb-tree-node", children: [
14150
- /* @__PURE__ */ jsx104(
14264
+ return /* @__PURE__ */ jsxs93("div", { className: "fd-fb-tree-node", children: [
14265
+ /* @__PURE__ */ jsx106(
14151
14266
  RowShell,
14152
14267
  {
14153
14268
  icon: folder.id === currentFolderId ? "folder-open" : "folder-simple",
@@ -14157,7 +14272,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
14157
14272
  isDropTarget: canMove,
14158
14273
  onDropPayload: (payload) => onMoveInto(payload, folder.id),
14159
14274
  className: ["fd-fb-tree-row", isCurrent ? "is-current" : ""].filter(Boolean).join(" "),
14160
- actions: kids.length ? /* @__PURE__ */ jsx104(
14275
+ actions: kids.length ? /* @__PURE__ */ jsx106(
14161
14276
  IconButton,
14162
14277
  {
14163
14278
  icon: expanded ? "caret-down" : "caret-right",
@@ -14169,7 +14284,7 @@ function TreeNode({ folder, depth, folders, currentFolderId, onNavigate, onMoveI
14169
14284
  ) : void 0
14170
14285
  }
14171
14286
  ),
14172
- expanded && kids.length ? /* @__PURE__ */ jsx104("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx104(
14287
+ expanded && kids.length ? /* @__PURE__ */ jsx106("div", { className: "fd-fb-tree-children", style: { paddingLeft: 14 }, children: kids.map((k) => /* @__PURE__ */ jsx106(
14173
14288
  TreeNode,
14174
14289
  {
14175
14290
  folder: k,
@@ -14208,15 +14323,15 @@ function FileBrowser({
14208
14323
  const canUpload = perm.canUpload !== false && !!onUpload;
14209
14324
  const canRemoveFile = perm.canRemoveFile !== false && !!onRemoveFile;
14210
14325
  const canDeleteFolder = perm.canDeleteFolder !== false && !!onDeleteFolder;
14211
- const [createOpen, setCreateOpen] = React76.useState(false);
14212
- const [createName, setCreateName] = React76.useState("");
14213
- const [renameTarget, setRenameTarget] = React76.useState(null);
14214
- const [renameValue, setRenameValue] = React76.useState("");
14215
- const [deleteTarget, setDeleteTarget] = React76.useState(null);
14216
- const uploadInputRef = React76.useRef(null);
14217
- const crumbFolders = React76.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14218
- const subfolders = React76.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14219
- const currentFiles = React76.useMemo(
14326
+ const [createOpen, setCreateOpen] = React77.useState(false);
14327
+ const [createName, setCreateName] = React77.useState("");
14328
+ const [renameTarget, setRenameTarget] = React77.useState(null);
14329
+ const [renameValue, setRenameValue] = React77.useState("");
14330
+ const [deleteTarget, setDeleteTarget] = React77.useState(null);
14331
+ const uploadInputRef = React77.useRef(null);
14332
+ const crumbFolders = React77.useMemo(() => ancestorsOf(folders, currentFolderId), [folders, currentFolderId]);
14333
+ const subfolders = React77.useMemo(() => childrenOf(folders, currentFolderId), [folders, currentFolderId]);
14334
+ const currentFiles = React77.useMemo(
14220
14335
  () => files.filter((f) => f.folderId === currentFolderId).sort((a, b) => a.name.localeCompare(b.name)),
14221
14336
  [files, currentFolderId]
14222
14337
  );
@@ -14255,10 +14370,10 @@ function FileBrowser({
14255
14370
  if (deleteTarget && onDeleteFolder) onDeleteFolder(deleteTarget);
14256
14371
  setDeleteTarget(null);
14257
14372
  };
14258
- const content = /* @__PURE__ */ jsxs92("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
14259
- /* @__PURE__ */ jsxs92("div", { className: "fd-fb-head", children: [
14260
- /* @__PURE__ */ jsxs92("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
14261
- /* @__PURE__ */ jsx104(
14373
+ const content = /* @__PURE__ */ jsxs93("div", { className: ["fd-fb", className].filter(Boolean).join(" "), children: [
14374
+ /* @__PURE__ */ jsxs93("div", { className: "fd-fb-head", children: [
14375
+ /* @__PURE__ */ jsxs93("nav", { className: "fd-fb-crumbs", "aria-label": "Folder path", children: [
14376
+ /* @__PURE__ */ jsx106(
14262
14377
  BreadcrumbCrumb,
14263
14378
  {
14264
14379
  label: "Home",
@@ -14268,7 +14383,7 @@ function FileBrowser({
14268
14383
  onDropPayload: (p) => moveIntoFolder(p, null)
14269
14384
  }
14270
14385
  ),
14271
- crumbFolders.map((f, i) => /* @__PURE__ */ jsx104(
14386
+ crumbFolders.map((f, i) => /* @__PURE__ */ jsx106(
14272
14387
  BreadcrumbCrumb,
14273
14388
  {
14274
14389
  label: f.name,
@@ -14280,11 +14395,11 @@ function FileBrowser({
14280
14395
  f.id
14281
14396
  ))
14282
14397
  ] }),
14283
- /* @__PURE__ */ jsxs92("span", { className: "fd-fb-actions", children: [
14284
- canCreateFolder ? /* @__PURE__ */ jsx104(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
14285
- canUpload ? /* @__PURE__ */ jsxs92(Fragment31, { children: [
14286
- /* @__PURE__ */ jsx104(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
14287
- /* @__PURE__ */ jsx104(
14398
+ /* @__PURE__ */ jsxs93("span", { className: "fd-fb-actions", children: [
14399
+ canCreateFolder ? /* @__PURE__ */ jsx106(Button, { variant: "secondary", size: "sm", icon: "folder-simple-plus", onClick: openCreate, children: "New folder" }) : null,
14400
+ canUpload ? /* @__PURE__ */ jsxs93(Fragment31, { children: [
14401
+ /* @__PURE__ */ jsx106(Button, { variant: "secondary", size: "sm", icon: "upload-simple", onClick: () => uploadInputRef.current && uploadInputRef.current.click(), children: "Upload" }),
14402
+ /* @__PURE__ */ jsx106(
14288
14403
  "input",
14289
14404
  {
14290
14405
  ref: uploadInputRef,
@@ -14302,9 +14417,9 @@ function FileBrowser({
14302
14417
  ] }) : null
14303
14418
  ] })
14304
14419
  ] }),
14305
- /* @__PURE__ */ jsxs92("div", { className: "fd-fb-body", children: [
14306
- /* @__PURE__ */ jsxs92("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
14307
- /* @__PURE__ */ jsx104(
14420
+ /* @__PURE__ */ jsxs93("div", { className: "fd-fb-body", children: [
14421
+ /* @__PURE__ */ jsxs93("div", { className: "fd-fb-tree", role: "region", "aria-label": "Folder tree", children: [
14422
+ /* @__PURE__ */ jsx106(
14308
14423
  RowShell,
14309
14424
  {
14310
14425
  icon: "house-simple",
@@ -14315,7 +14430,7 @@ function FileBrowser({
14315
14430
  className: ["fd-fb-tree-row", currentFolderId == null ? "is-current" : ""].filter(Boolean).join(" ")
14316
14431
  }
14317
14432
  ),
14318
- childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx104(
14433
+ childrenOf(folders, null).map((f) => /* @__PURE__ */ jsx106(
14319
14434
  TreeNode,
14320
14435
  {
14321
14436
  folder: f,
@@ -14329,18 +14444,18 @@ function FileBrowser({
14329
14444
  f.id
14330
14445
  ))
14331
14446
  ] }),
14332
- /* @__PURE__ */ jsx104("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx104(
14447
+ /* @__PURE__ */ jsx106("div", { className: "fd-fb-main", role: "region", "aria-label": "Folder contents", children: /* @__PURE__ */ jsx106(
14333
14448
  LoadingRegion,
14334
14449
  {
14335
14450
  state: loading ? "loading" : "ready",
14336
14451
  label: "Loading folder contents",
14337
- skeleton: /* @__PURE__ */ jsxs92("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
14338
- /* @__PURE__ */ jsx104(Skeleton, { h: 44, radius: "10px" }),
14339
- /* @__PURE__ */ jsx104(Skeleton, { h: 44, radius: "10px" }),
14340
- /* @__PURE__ */ jsx104(Skeleton, { h: 44, radius: "10px" })
14452
+ skeleton: /* @__PURE__ */ jsxs93("div", { className: "fd-stack", style: { gap: 8, padding: 12 }, children: [
14453
+ /* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" }),
14454
+ /* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" }),
14455
+ /* @__PURE__ */ jsx106(Skeleton, { h: 44, radius: "10px" })
14341
14456
  ] }),
14342
- children: isEmpty ? /* @__PURE__ */ jsx104(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ jsxs92("div", { className: "fd-fb-list", children: [
14343
- subfolders.map((f) => /* @__PURE__ */ jsx104(
14457
+ children: isEmpty ? /* @__PURE__ */ jsx106(EmptyState, { icon: "folder-open", title: "This folder is empty", children: canUpload ? "Drop files here, or use Upload above." : "Nothing has been filed here yet." }) : /* @__PURE__ */ jsxs93("div", { className: "fd-fb-list", children: [
14458
+ subfolders.map((f) => /* @__PURE__ */ jsx106(
14344
14459
  RowShell,
14345
14460
  {
14346
14461
  icon: "folder-simple",
@@ -14349,9 +14464,9 @@ function FileBrowser({
14349
14464
  draggableId: canMove ? { kind: "folder", id: f.id } : void 0,
14350
14465
  isDropTarget: canMove,
14351
14466
  onDropPayload: (p) => moveIntoFolder(p, f.id),
14352
- actions: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14353
- canRenameFolder ? /* @__PURE__ */ jsx104(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
14354
- canMove ? /* @__PURE__ */ jsx104(
14467
+ actions: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14468
+ canRenameFolder ? /* @__PURE__ */ jsx106(IconButton, { icon: "pencil-simple", label: "Rename " + f.name, size: "sm", variant: "ghost", onClick: () => openRename(f) }) : null,
14469
+ canMove ? /* @__PURE__ */ jsx106(
14355
14470
  FolderPickerMenu,
14356
14471
  {
14357
14472
  label: "Move " + f.name,
@@ -14359,12 +14474,12 @@ function FileBrowser({
14359
14474
  onPick: (target) => moveIntoFolder({ kind: "folder", id: f.id }, target)
14360
14475
  }
14361
14476
  ) : null,
14362
- canDeleteFolder ? /* @__PURE__ */ jsx104(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
14477
+ canDeleteFolder ? /* @__PURE__ */ jsx106(IconButton, { icon: "trash-simple", label: "Delete " + f.name, size: "sm", variant: "ghost", onClick: () => openDelete(f) }) : null
14363
14478
  ] })
14364
14479
  },
14365
14480
  f.id
14366
14481
  )),
14367
- currentFiles.map((file) => /* @__PURE__ */ jsx104(
14482
+ currentFiles.map((file) => /* @__PURE__ */ jsx106(
14368
14483
  RowShell,
14369
14484
  {
14370
14485
  icon: iconForMime(file.mime, file.name),
@@ -14372,8 +14487,8 @@ function FileBrowser({
14372
14487
  meta: file.size ? formatBytes(file.size) : void 0,
14373
14488
  onOpen: onOpenFile ? () => onOpenFile(file) : void 0,
14374
14489
  draggableId: canMove ? { kind: "file", id: file.id } : void 0,
14375
- actions: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14376
- canMove ? /* @__PURE__ */ jsx104(
14490
+ actions: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14491
+ canMove ? /* @__PURE__ */ jsx106(
14377
14492
  FolderPickerMenu,
14378
14493
  {
14379
14494
  label: "Move " + file.name,
@@ -14381,7 +14496,7 @@ function FileBrowser({
14381
14496
  onPick: (target) => onMoveFile && onMoveFile(file.id, target)
14382
14497
  }
14383
14498
  ) : null,
14384
- canRemoveFile ? /* @__PURE__ */ jsx104(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
14499
+ canRemoveFile ? /* @__PURE__ */ jsx106(IconButton, { icon: "trash-simple", label: "Remove " + file.name, size: "sm", variant: "ghost", onClick: () => onRemoveFile && onRemoveFile(file) }) : null
14385
14500
  ] })
14386
14501
  },
14387
14502
  file.id
@@ -14390,10 +14505,10 @@ function FileBrowser({
14390
14505
  }
14391
14506
  ) })
14392
14507
  ] }),
14393
- /* @__PURE__ */ jsx104(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14394
- /* @__PURE__ */ jsx104(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
14395
- /* @__PURE__ */ jsx104(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
14396
- ] }), children: /* @__PURE__ */ jsx104(
14508
+ /* @__PURE__ */ jsx106(Modal, { open: createOpen, title: "New folder", onClose: () => setCreateOpen(false), footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14509
+ /* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setCreateOpen(false), children: "Cancel" }),
14510
+ /* @__PURE__ */ jsx106(Button, { onClick: submitCreate, disabled: !createName.trim(), children: "Create" })
14511
+ ] }), children: /* @__PURE__ */ jsx106(
14397
14512
  "input",
14398
14513
  {
14399
14514
  className: "fd-fb-input",
@@ -14407,10 +14522,10 @@ function FileBrowser({
14407
14522
  autoFocus: true
14408
14523
  }
14409
14524
  ) }),
14410
- /* @__PURE__ */ jsx104(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14411
- /* @__PURE__ */ jsx104(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
14412
- /* @__PURE__ */ jsx104(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
14413
- ] }), children: /* @__PURE__ */ jsx104(
14525
+ /* @__PURE__ */ jsx106(Modal, { open: renameTarget != null, title: "Rename folder", onClose: () => setRenameTarget(null), footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14526
+ /* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setRenameTarget(null), children: "Cancel" }),
14527
+ /* @__PURE__ */ jsx106(Button, { onClick: submitRename, disabled: !renameValue.trim(), children: "Save" })
14528
+ ] }), children: /* @__PURE__ */ jsx106(
14414
14529
  "input",
14415
14530
  {
14416
14531
  className: "fd-fb-input",
@@ -14424,22 +14539,22 @@ function FileBrowser({
14424
14539
  autoFocus: true
14425
14540
  }
14426
14541
  ) }),
14427
- /* @__PURE__ */ jsx104(
14542
+ /* @__PURE__ */ jsx106(
14428
14543
  Modal,
14429
14544
  {
14430
14545
  open: deleteTarget != null,
14431
14546
  title: deleteTarget ? "Delete \u201C" + deleteTarget.name + "\u201D?" : "Delete folder?",
14432
14547
  description: "This can't be undone. The folder must be empty.",
14433
14548
  onClose: () => setDeleteTarget(null),
14434
- footer: /* @__PURE__ */ jsxs92(Fragment31, { children: [
14435
- /* @__PURE__ */ jsx104(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
14436
- /* @__PURE__ */ jsx104(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
14549
+ footer: /* @__PURE__ */ jsxs93(Fragment31, { children: [
14550
+ /* @__PURE__ */ jsx106(Button, { variant: "secondary", onClick: () => setDeleteTarget(null), children: "Cancel" }),
14551
+ /* @__PURE__ */ jsx106(Button, { variant: "danger", onClick: confirmDelete, children: "Delete" })
14437
14552
  ] })
14438
14553
  }
14439
14554
  )
14440
14555
  ] });
14441
14556
  if (!canUpload) return content;
14442
- return /* @__PURE__ */ jsx104(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
14557
+ return /* @__PURE__ */ jsx106(Dropzone, { className: "fd-fb-dropzone", onFiles: (picked) => onUpload && onUpload(picked, currentFolderId), label: "Drop files to upload", children: content });
14443
14558
  }
14444
14559
  function BreadcrumbCrumb({
14445
14560
  label,
@@ -14448,8 +14563,8 @@ function BreadcrumbCrumb({
14448
14563
  isDropTarget,
14449
14564
  onDropPayload
14450
14565
  }) {
14451
- const [over, setOver] = React76.useState(false);
14452
- const dragCounter = React76.useRef(0);
14566
+ const [over, setOver] = React77.useState(false);
14567
+ const dragCounter = React77.useRef(0);
14453
14568
  const dropHandlers = isDropTarget ? {
14454
14569
  onDragEnter: (e) => {
14455
14570
  if (!hasInternalPayload(e)) return;
@@ -14474,11 +14589,11 @@ function BreadcrumbCrumb({
14474
14589
  if (payload && onDropPayload) onDropPayload(payload);
14475
14590
  }
14476
14591
  } : {};
14477
- return /* @__PURE__ */ jsx104("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx104("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx104("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
14592
+ return /* @__PURE__ */ jsx106("span", { className: ["fd-fb-crumb", over ? "is-drop-target" : ""].filter(Boolean).join(" "), ...dropHandlers, children: isCurrent ? /* @__PURE__ */ jsx106("span", { className: "fd-fb-crumb-current", "aria-current": "page", children: label }) : /* @__PURE__ */ jsx106("button", { type: "button", className: "fd-fb-crumb-link", onClick, children: label }) });
14478
14593
  }
14479
14594
 
14480
14595
  // src/kits/query.ts
14481
- import * as React77 from "react";
14596
+ import * as React78 from "react";
14482
14597
 
14483
14598
  // src/kits/queryUrl.ts
14484
14599
  var historyUrlAdapter = {
@@ -14616,38 +14731,38 @@ function requestFor(params, query, paging, after) {
14616
14731
  }
14617
14732
  var toError = (e) => e instanceof Error ? e : new Error(String(e));
14618
14733
  function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
14619
- const [base] = React77.useState(() => {
14734
+ const [base] = React78.useState(() => {
14620
14735
  const store = PREFS || window.PlannerPrefs;
14621
14736
  const saved = prefsKey && store ? store.getTable(prefsKey) : {};
14622
14737
  return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
14623
14738
  });
14624
- const [mountParams] = React77.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14625
- const address = React77.useRef(mountParams);
14626
- const [query, setQuery] = React77.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14627
- const savePref = React77.useCallback((patch2) => {
14739
+ const [mountParams] = React78.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
14740
+ const address = React78.useRef(mountParams);
14741
+ const [query, setQuery] = React78.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
14742
+ const savePref = React78.useCallback((patch2) => {
14628
14743
  const store = PREFS || window.PlannerPrefs;
14629
14744
  if (prefsKey && store) store.setTable(prefsKey, patch2);
14630
14745
  }, [prefsKey]);
14631
- const [res, setRes] = React77.useState(null);
14632
- const [loading, setLoading] = React77.useState(true);
14633
- const [loadingMore, setLoadingMore] = React77.useState(false);
14634
- const [failure, setFailure] = React77.useState(null);
14635
- const [reloadToken, setReloadToken] = React77.useState(0);
14636
- const moreController = React77.useRef(null);
14746
+ const [res, setRes] = React78.useState(null);
14747
+ const [loading, setLoading] = React78.useState(true);
14748
+ const [loadingMore, setLoadingMore] = React78.useState(false);
14749
+ const [failure, setFailure] = React78.useState(null);
14750
+ const [reloadToken, setReloadToken] = React78.useState(0);
14751
+ const moreController = React78.useRef(null);
14637
14752
  const depKey = (deps || []).join("|");
14638
14753
  const paramKey = JSON.stringify(params || {});
14639
14754
  const queryKey = JSON.stringify(query);
14640
- const lifetime = React77.useRef(null);
14641
- React77.useEffect(() => {
14755
+ const lifetime = React78.useRef(null);
14756
+ React78.useEffect(() => {
14642
14757
  const controller = new AbortController();
14643
14758
  lifetime.current = controller;
14644
14759
  return () => controller.abort();
14645
14760
  }, []);
14646
- const latest = React77.useRef({ res, loading, query, params, endpoint, url, base });
14647
- React77.useEffect(() => {
14761
+ const latest = React78.useRef({ res, loading, query, params, endpoint, url, base });
14762
+ React78.useLayoutEffect(() => {
14648
14763
  latest.current = { res, loading, query, params, endpoint, url, base };
14649
14764
  });
14650
- React77.useEffect(() => {
14765
+ React78.useEffect(() => {
14651
14766
  const controller = new AbortController();
14652
14767
  const { signal } = controller;
14653
14768
  setLoading(true);
@@ -14683,7 +14798,7 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "
14683
14798
  };
14684
14799
  }, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
14685
14800
  const adapter = url ? url.adapter ?? historyUrlAdapter : null;
14686
- React77.useEffect(() => {
14801
+ React78.useEffect(() => {
14687
14802
  if (!adapter) return;
14688
14803
  return adapter.subscribe((params2) => {
14689
14804
  const { url: u, base: b } = latest.current;
@@ -15033,12 +15148,12 @@ function createVersionStore(initialState, options) {
15033
15148
  }
15034
15149
 
15035
15150
  // src/kits/documentTitle.ts
15036
- import * as React78 from "react";
15151
+ import * as React79 from "react";
15037
15152
  function formatDocumentTitle(routeTitle, appName) {
15038
15153
  return [routeTitle, appName, "Flytedesk"].filter((part) => !!part && part.length > 0).join(" \xB7 ");
15039
15154
  }
15040
15155
  function useDocumentTitle(routeTitle, appName) {
15041
- React78.useEffect(() => {
15156
+ React79.useEffect(() => {
15042
15157
  if (typeof document === "undefined") return;
15043
15158
  document.title = formatDocumentTitle(routeTitle, appName);
15044
15159
  }, [routeTitle, appName]);
@@ -15109,6 +15224,7 @@ export {
15109
15224
  FILE_VIEWER_TEXT_LIMIT,
15110
15225
  FactList,
15111
15226
  FeatureGate,
15227
+ Fieldset,
15112
15228
  FileBrowser,
15113
15229
  FileChip,
15114
15230
  FileGrid,
@@ -15162,6 +15278,7 @@ export {
15162
15278
  QuotaRow,
15163
15279
  ROOT_STEP,
15164
15280
  Radio,
15281
+ RadioGroup,
15165
15282
  RangeSlider,
15166
15283
  RelativeTime,
15167
15284
  RoadmapTimeline,