@flytedan/flytebot-design-system 0.12.11 → 0.12.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +230 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -9
- package/dist/index.d.ts +57 -9
- package/dist/index.js +226 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components.css +216 -3
- package/styles/tokens.css +22 -6
package/dist/index.cjs
CHANGED
|
@@ -73,6 +73,8 @@ __export(index_exports, {
|
|
|
73
73
|
EmptyState: () => EmptyState,
|
|
74
74
|
EntityRow: () => EntityRow,
|
|
75
75
|
EntityRowMetrics: () => EntityRowMetrics,
|
|
76
|
+
FILE_VIEWER_CSV_ROW_LIMIT: () => FILE_VIEWER_CSV_ROW_LIMIT,
|
|
77
|
+
FILE_VIEWER_TEXT_LIMIT: () => FILE_VIEWER_TEXT_LIMIT,
|
|
76
78
|
FeatureGate: () => FeatureGate,
|
|
77
79
|
FileChip: () => FileChip,
|
|
78
80
|
FileGrid: () => FileGrid,
|
|
@@ -80,6 +82,7 @@ __export(index_exports, {
|
|
|
80
82
|
FilePickButton: () => FilePickButton,
|
|
81
83
|
FileStrip: () => FileStrip,
|
|
82
84
|
FileTile: () => FileTile,
|
|
85
|
+
FileViewer: () => FileViewer,
|
|
83
86
|
FilterBar: () => FilterBar,
|
|
84
87
|
Flag: () => Flag,
|
|
85
88
|
FlytedeskBrand: () => FlytedeskBrand,
|
|
@@ -184,6 +187,7 @@ __export(index_exports, {
|
|
|
184
187
|
markdownToText: () => markdownToText,
|
|
185
188
|
meterFormats: () => meterFormats,
|
|
186
189
|
modifierLabel: () => modifierLabel,
|
|
190
|
+
parseDelimited: () => parseDelimited,
|
|
187
191
|
pastedTextName: () => pastedTextName,
|
|
188
192
|
pluralizeUnit: () => pluralizeUnit,
|
|
189
193
|
preferenceScore: () => preferenceScore,
|
|
@@ -4672,7 +4676,7 @@ function useStagedFiles(upload, opts) {
|
|
|
4672
4676
|
patch(att.id, { progress: 0, error: void 0 });
|
|
4673
4677
|
Promise.resolve().then(() => upload(att.file, (p) => patch(att.id, { progress: Math.max(0, Math.min(99, p)) }), ac ? ac.signal : void 0)).then((res) => {
|
|
4674
4678
|
const r = res || {};
|
|
4675
|
-
patch(att.id, {
|
|
4679
|
+
patch(att.id, Object.assign({}, r, { id: r.id || att.id, progress: 100, error: void 0 }));
|
|
4676
4680
|
o.onUploaded && o.onUploaded(att);
|
|
4677
4681
|
}).catch((err) => {
|
|
4678
4682
|
if (ac && ac.signal.aborted) return;
|
|
@@ -9668,7 +9672,9 @@ function ChatComposer({
|
|
|
9668
9672
|
const submit = () => {
|
|
9669
9673
|
if (!canSend) return;
|
|
9670
9674
|
onSubmit(text.trim(), staged.items.map((f) => {
|
|
9671
|
-
const { file
|
|
9675
|
+
const { file, blobUrl, ...rest } = f;
|
|
9676
|
+
void file;
|
|
9677
|
+
void blobUrl;
|
|
9672
9678
|
return rest;
|
|
9673
9679
|
}));
|
|
9674
9680
|
change("");
|
|
@@ -10363,8 +10369,219 @@ function AgentChatPanel({
|
|
|
10363
10369
|
);
|
|
10364
10370
|
}
|
|
10365
10371
|
|
|
10366
|
-
// src/
|
|
10372
|
+
// src/components/files/FileViewer.tsx
|
|
10367
10373
|
var React47 = __toESM(require("react"), 1);
|
|
10374
|
+
var import_jsx_runtime78 = require("react/jsx-runtime");
|
|
10375
|
+
function previewKindOf(file) {
|
|
10376
|
+
const mime = (file.mime || "").toLowerCase();
|
|
10377
|
+
const ext = extensionOf(file.name || "");
|
|
10378
|
+
if (isImage(mime, file.name)) return "image";
|
|
10379
|
+
if (mime === "application/pdf" || ext === "pdf") return "pdf";
|
|
10380
|
+
if (mime === "text/markdown" || ext === "md" || ext === "markdown") return "markdown";
|
|
10381
|
+
if (mime === "application/json" || ext === "json") return "json";
|
|
10382
|
+
if (mime === "text/csv" || mime === "text/tab-separated-values" || ext === "csv" || ext === "tsv") return "csv";
|
|
10383
|
+
if (mime.startsWith("text/") || ext === "txt" || ext === "log") return "text";
|
|
10384
|
+
return "none";
|
|
10385
|
+
}
|
|
10386
|
+
var FILE_VIEWER_TEXT_LIMIT = 5e5;
|
|
10387
|
+
var FILE_VIEWER_CSV_ROW_LIMIT = 500;
|
|
10388
|
+
function parseDelimited(text, delimiter) {
|
|
10389
|
+
const rows = [];
|
|
10390
|
+
let row = [];
|
|
10391
|
+
let field = "";
|
|
10392
|
+
let inQuotes = false;
|
|
10393
|
+
for (let i = 0; i < text.length; i++) {
|
|
10394
|
+
const c = text[i];
|
|
10395
|
+
if (inQuotes) {
|
|
10396
|
+
if (c === '"') {
|
|
10397
|
+
if (text[i + 1] === '"') {
|
|
10398
|
+
field += '"';
|
|
10399
|
+
i++;
|
|
10400
|
+
} else inQuotes = false;
|
|
10401
|
+
} else field += c;
|
|
10402
|
+
continue;
|
|
10403
|
+
}
|
|
10404
|
+
if (c === '"') {
|
|
10405
|
+
inQuotes = true;
|
|
10406
|
+
continue;
|
|
10407
|
+
}
|
|
10408
|
+
if (c === delimiter) {
|
|
10409
|
+
row.push(field);
|
|
10410
|
+
field = "";
|
|
10411
|
+
continue;
|
|
10412
|
+
}
|
|
10413
|
+
if (c === "\n") {
|
|
10414
|
+
row.push(field);
|
|
10415
|
+
rows.push(row);
|
|
10416
|
+
row = [];
|
|
10417
|
+
field = "";
|
|
10418
|
+
continue;
|
|
10419
|
+
}
|
|
10420
|
+
if (c === "\r") continue;
|
|
10421
|
+
field += c;
|
|
10422
|
+
}
|
|
10423
|
+
if (field.length || row.length) {
|
|
10424
|
+
row.push(field);
|
|
10425
|
+
rows.push(row);
|
|
10426
|
+
}
|
|
10427
|
+
return rows;
|
|
10428
|
+
}
|
|
10429
|
+
function usePreview(file, kind, resolveUrl) {
|
|
10430
|
+
const [state, setState] = React47.useState({ status: "loading" });
|
|
10431
|
+
const [attempt, setAttempt] = React47.useState(0);
|
|
10432
|
+
const resolveRef = React47.useRef(resolveUrl);
|
|
10433
|
+
React47.useEffect(() => {
|
|
10434
|
+
resolveRef.current = resolveUrl;
|
|
10435
|
+
}, [resolveUrl]);
|
|
10436
|
+
React47.useEffect(() => {
|
|
10437
|
+
if (kind === "none") {
|
|
10438
|
+
setState({ status: "ready" });
|
|
10439
|
+
return;
|
|
10440
|
+
}
|
|
10441
|
+
let dead = false;
|
|
10442
|
+
const ac = typeof AbortController !== "undefined" ? new AbortController() : void 0;
|
|
10443
|
+
setState({ status: "loading" });
|
|
10444
|
+
resolveRef.current("inline").then((url) => {
|
|
10445
|
+
if (dead) return void 0;
|
|
10446
|
+
if (kind === "image" || kind === "pdf") {
|
|
10447
|
+
setState({ status: "ready", url });
|
|
10448
|
+
return void 0;
|
|
10449
|
+
}
|
|
10450
|
+
return fetch(url, ac ? { signal: ac.signal } : void 0).then((res) => {
|
|
10451
|
+
if (!res.ok) throw new Error("The preview didn't load (" + res.status + ").");
|
|
10452
|
+
return res.text();
|
|
10453
|
+
}).then((body) => {
|
|
10454
|
+
if (dead) return;
|
|
10455
|
+
setState({ status: "ready", url, text: body.length > FILE_VIEWER_TEXT_LIMIT ? body.slice(0, FILE_VIEWER_TEXT_LIMIT) : body });
|
|
10456
|
+
});
|
|
10457
|
+
}).catch((err) => {
|
|
10458
|
+
if (dead || ac && ac.signal.aborted) return;
|
|
10459
|
+
setState({ status: "error", error: err && err.message || "The preview didn't load." });
|
|
10460
|
+
});
|
|
10461
|
+
return () => {
|
|
10462
|
+
dead = true;
|
|
10463
|
+
if (ac) ac.abort();
|
|
10464
|
+
};
|
|
10465
|
+
}, [file.id, kind, attempt]);
|
|
10466
|
+
return { ...state, retry: React47.useCallback(() => setAttempt((a) => a + 1), []) };
|
|
10467
|
+
}
|
|
10468
|
+
function PreviewBody({ file, kind, state }) {
|
|
10469
|
+
if (kind === "image") return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("img", { className: "fd-fv-image", src: state.url, alt: file.name || "Preview" });
|
|
10470
|
+
if (kind === "pdf") return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("iframe", { className: "fd-fv-pdf", src: state.url, title: file.name || "PDF preview" });
|
|
10471
|
+
if (kind === "markdown") return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Markdown, { className: "fd-fv-markdown", source: state.text || "" });
|
|
10472
|
+
if (kind === "json") {
|
|
10473
|
+
let pretty = state.text || "";
|
|
10474
|
+
try {
|
|
10475
|
+
pretty = JSON.stringify(JSON.parse(pretty), null, 2);
|
|
10476
|
+
} catch {
|
|
10477
|
+
}
|
|
10478
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CodeBlock, { code: pretty, language: "json" });
|
|
10479
|
+
}
|
|
10480
|
+
if (kind === "csv") {
|
|
10481
|
+
const tsv = extensionOf(file.name || "") === "tsv" || (file.mime || "").toLowerCase().includes("tab-separated");
|
|
10482
|
+
const rows = parseDelimited(state.text || "", tsv ? " " : ",").filter((r) => r.length > 1 || r[0] !== "");
|
|
10483
|
+
const head = rows[0] || [];
|
|
10484
|
+
const dataRows = rows.slice(1);
|
|
10485
|
+
const shown = dataRows.slice(0, FILE_VIEWER_CSV_ROW_LIMIT);
|
|
10486
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-fv-csv", children: [
|
|
10487
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("table", { className: "fd-fv-csv-table", children: [
|
|
10488
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("tr", { children: head.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("th", { children: c }, i)) }) }),
|
|
10489
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("tbody", { children: shown.map((r, ri) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("tr", { children: head.map((_, ci) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("td", { children: r[ci] ?? "" }, ci)) }, ri)) })
|
|
10490
|
+
] }),
|
|
10491
|
+
dataRows.length > FILE_VIEWER_CSV_ROW_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("p", { className: "fd-fv-csv-note fd-body-sm fd-muted", children: [
|
|
10492
|
+
"Showing the first ",
|
|
10493
|
+
FILE_VIEWER_CSV_ROW_LIMIT.toLocaleString(),
|
|
10494
|
+
" of ",
|
|
10495
|
+
dataRows.length.toLocaleString(),
|
|
10496
|
+
" rows."
|
|
10497
|
+
] }) : null
|
|
10498
|
+
] });
|
|
10499
|
+
}
|
|
10500
|
+
if (kind === "text") return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(CodeBlock, { code: state.text || "", language: extensionOf(file.name || "") || void 0 });
|
|
10501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-fv-fallback", children: [
|
|
10502
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-fv-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
10503
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-fv-fallback-title", children: "No preview available" }),
|
|
10504
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-fv-fallback-meta", children: [
|
|
10505
|
+
file.mime || "Unknown type",
|
|
10506
|
+
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
10507
|
+
] })
|
|
10508
|
+
] });
|
|
10509
|
+
}
|
|
10510
|
+
function FileViewer({ file, resolveUrl, sidePanel, sidePanelLabel = "Details", onClose, actions, className = "" }) {
|
|
10511
|
+
const kind = React47.useMemo(() => previewKindOf(file), [file]);
|
|
10512
|
+
const preview = usePreview(file, kind, resolveUrl);
|
|
10513
|
+
const [tab, setTab] = React47.useState("preview");
|
|
10514
|
+
const [downloading, setDownloading] = React47.useState(false);
|
|
10515
|
+
const [downloadError, setDownloadError] = React47.useState(null);
|
|
10516
|
+
const hasSide = sidePanel != null;
|
|
10517
|
+
React47.useEffect(() => {
|
|
10518
|
+
setTab("preview");
|
|
10519
|
+
}, [file.id]);
|
|
10520
|
+
const download = () => {
|
|
10521
|
+
setDownloading(true);
|
|
10522
|
+
setDownloadError(null);
|
|
10523
|
+
resolveUrl("attachment").then((url) => {
|
|
10524
|
+
const a = document.createElement("a");
|
|
10525
|
+
a.href = url;
|
|
10526
|
+
a.rel = "noopener";
|
|
10527
|
+
a.download = file.name || "";
|
|
10528
|
+
document.body.appendChild(a);
|
|
10529
|
+
a.click();
|
|
10530
|
+
a.remove();
|
|
10531
|
+
}).catch((err) => setDownloadError(err && err.message || "Download failed.")).finally(() => setDownloading(false));
|
|
10532
|
+
};
|
|
10533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)(
|
|
10534
|
+
"section",
|
|
10535
|
+
{
|
|
10536
|
+
className: ["fd-fv", hasSide && tab === "side" ? "is-tab-side" : "is-tab-preview", className].filter(Boolean).join(" "),
|
|
10537
|
+
"aria-label": file.name || "File",
|
|
10538
|
+
children: [
|
|
10539
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("header", { className: "fd-fv-head", children: [
|
|
10540
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-fv-head-icon", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("i", { className: "ph ph-" + iconForMime(file.mime, file.name) }) }),
|
|
10541
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-fv-head-titles", children: [
|
|
10542
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "fd-fv-head-title", title: file.name, children: file.name }),
|
|
10543
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-fv-head-meta", children: [
|
|
10544
|
+
file.mime || "Unknown type",
|
|
10545
|
+
file.size ? " \xB7 " + formatBytes(file.size) : ""
|
|
10546
|
+
] })
|
|
10547
|
+
] }),
|
|
10548
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { className: "fd-fv-head-actions", children: [
|
|
10549
|
+
actions,
|
|
10550
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Button, { variant: "secondary", size: "sm", icon: "download-simple", loading: downloading, onClick: download, children: "Download" }),
|
|
10551
|
+
onClose ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(IconButton, { icon: "x", label: "Close", onClick: onClose }) : null
|
|
10552
|
+
] })
|
|
10553
|
+
] }),
|
|
10554
|
+
downloadError ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-fv-download-error", role: "alert", children: downloadError }) : null,
|
|
10555
|
+
hasSide ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
10556
|
+
Tabs,
|
|
10557
|
+
{
|
|
10558
|
+
className: "fd-fv-tabs",
|
|
10559
|
+
tabs: [{ value: "preview", label: "Preview" }, { value: "side", label: sidePanelLabel }],
|
|
10560
|
+
value: tab,
|
|
10561
|
+
onChange: (v) => setTab(v)
|
|
10562
|
+
}
|
|
10563
|
+
) : null,
|
|
10564
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "fd-fv-body", children: [
|
|
10565
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-fv-preview", role: "region", "aria-label": "Preview of " + (file.name || "file"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
10566
|
+
LoadingRegion,
|
|
10567
|
+
{
|
|
10568
|
+
state: preview.status === "loading" ? "loading" : preview.status === "error" ? "error" : "ready",
|
|
10569
|
+
error: preview.error,
|
|
10570
|
+
label: "Loading preview of " + (file.name || "file"),
|
|
10571
|
+
onRetry: preview.status === "error" ? preview.retry : void 0,
|
|
10572
|
+
skeleton: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(Skeleton, { shape: "card", h: 220 }),
|
|
10573
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(PreviewBody, { file, kind, state: preview })
|
|
10574
|
+
}
|
|
10575
|
+
) }),
|
|
10576
|
+
hasSide ? /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "fd-fv-side", role: "region", "aria-label": sidePanelLabel, children: sidePanel }) : null
|
|
10577
|
+
] })
|
|
10578
|
+
]
|
|
10579
|
+
}
|
|
10580
|
+
);
|
|
10581
|
+
}
|
|
10582
|
+
|
|
10583
|
+
// src/kits/query.ts
|
|
10584
|
+
var React48 = __toESM(require("react"), 1);
|
|
10368
10585
|
function eqFilter(get2) {
|
|
10369
10586
|
return (row, value) => Array.isArray(value) ? value.includes(get2(row)) : get2(row) === value;
|
|
10370
10587
|
}
|
|
@@ -10396,22 +10613,22 @@ function compare(a, b, dir) {
|
|
|
10396
10613
|
var API = null;
|
|
10397
10614
|
var PREFS = null;
|
|
10398
10615
|
function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
10399
|
-
const [query, setQuery] =
|
|
10616
|
+
const [query, setQuery] = React48.useState(() => {
|
|
10400
10617
|
const store = PREFS || window.PlannerPrefs;
|
|
10401
10618
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
10402
10619
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
10403
10620
|
});
|
|
10404
|
-
const savePref =
|
|
10621
|
+
const savePref = React48.useCallback((patch2) => {
|
|
10405
10622
|
const store = PREFS || window.PlannerPrefs;
|
|
10406
10623
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
10407
10624
|
}, [prefsKey]);
|
|
10408
|
-
const [res, setRes] =
|
|
10409
|
-
const [loading, setLoading] =
|
|
10410
|
-
const seq2 =
|
|
10625
|
+
const [res, setRes] = React48.useState(null);
|
|
10626
|
+
const [loading, setLoading] = React48.useState(true);
|
|
10627
|
+
const seq2 = React48.useRef(0);
|
|
10411
10628
|
const depKey = (deps || []).join("|");
|
|
10412
10629
|
const paramKey = JSON.stringify(params || {});
|
|
10413
10630
|
const queryKey = JSON.stringify(query);
|
|
10414
|
-
|
|
10631
|
+
React48.useEffect(() => {
|
|
10415
10632
|
const id = ++seq2.current;
|
|
10416
10633
|
setLoading(true);
|
|
10417
10634
|
const t = setTimeout(() => {
|
|
@@ -10753,6 +10970,8 @@ function createVersionStore(initialState, options) {
|
|
|
10753
10970
|
EmptyState,
|
|
10754
10971
|
EntityRow,
|
|
10755
10972
|
EntityRowMetrics,
|
|
10973
|
+
FILE_VIEWER_CSV_ROW_LIMIT,
|
|
10974
|
+
FILE_VIEWER_TEXT_LIMIT,
|
|
10756
10975
|
FeatureGate,
|
|
10757
10976
|
FileChip,
|
|
10758
10977
|
FileGrid,
|
|
@@ -10760,6 +10979,7 @@ function createVersionStore(initialState, options) {
|
|
|
10760
10979
|
FilePickButton,
|
|
10761
10980
|
FileStrip,
|
|
10762
10981
|
FileTile,
|
|
10982
|
+
FileViewer,
|
|
10763
10983
|
FilterBar,
|
|
10764
10984
|
Flag,
|
|
10765
10985
|
FlytedeskBrand,
|
|
@@ -10864,6 +11084,7 @@ function createVersionStore(initialState, options) {
|
|
|
10864
11084
|
markdownToText,
|
|
10865
11085
|
meterFormats,
|
|
10866
11086
|
modifierLabel,
|
|
11087
|
+
parseDelimited,
|
|
10867
11088
|
pastedTextName,
|
|
10868
11089
|
pluralizeUnit,
|
|
10869
11090
|
preferenceScore,
|