@burdenoff/fluidgrids-fe-sdk 2026.1101.4 → 2026.1102.2

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.
Files changed (49) hide show
  1. package/dist/{ExecutionDetailPage-JQCJR5XD.js → ExecutionDetailPage-XHII23QR.js} +11 -11
  2. package/dist/{ExecutionsListPage-UDDASCDL.js → ExecutionsListPage-GTCSYSC6.js} +7 -7
  3. package/dist/{WorkflowBuilder-P52OTD2Y.js → WorkflowBuilder-ZIXEU7DQ.js} +12 -11
  4. package/dist/{WorkflowsList-QMN25IG4.js → WorkflowsList-NYSQEZWU.js} +7 -7
  5. package/dist/{agentTools-F2USMIDU.js → agentTools-PA62A53S.js} +4 -4
  6. package/dist/{chunk-V4TI5JMD.js → chunk-23LYGZ27.js} +1 -1
  7. package/dist/{chunk-QBYLI3HK.js → chunk-37BKVPO7.js} +12 -40
  8. package/dist/{chunk-D56WJCK6.js → chunk-3Y4266JL.js} +3 -3
  9. package/dist/{chunk-7MGYG6DR.js → chunk-4FDMLKLL.js} +2 -2
  10. package/dist/{chunk-6JJKKWVD.js → chunk-6VODFT2Q.js} +5 -5
  11. package/dist/{chunk-EZRX2PZT.js → chunk-7JLLH4YE.js} +4 -4
  12. package/dist/{chunk-LIVFWFT4.js → chunk-7SY2SL5Y.js} +6 -6
  13. package/dist/{chunk-IQZ3DD7U.js → chunk-A4XNCGWT.js} +2 -2
  14. package/dist/{chunk-FV77SZWB.js → chunk-A7QPQ6MO.js} +1 -1
  15. package/dist/{chunk-UN6NUIBV.js → chunk-B2DNUVKW.js} +4 -4
  16. package/dist/{chunk-ITLNDVAU.js → chunk-BDBSRN2O.js} +4 -4
  17. package/dist/{chunk-FLYFZJUC.js → chunk-CXNJKM4D.js} +1 -1
  18. package/dist/{chunk-XGMGCOTR.js → chunk-DLKGWGRN.js} +1 -1
  19. package/dist/{chunk-BUWFUPN2.js → chunk-EFOJEQDS.js} +2 -2
  20. package/dist/{chunk-6EE4PRD6.js → chunk-JCHE4V55.js} +1 -1
  21. package/dist/{chunk-DO554TUK.js → chunk-JTQFBZTV.js} +3 -1
  22. package/dist/{chunk-KEPQLNP6.js → chunk-MY752OLT.js} +67 -195
  23. package/dist/{chunk-6XVGLGJ4.js → chunk-OR7KZZ2D.js} +1 -1
  24. package/dist/{chunk-AVZ4SXUG.js → chunk-OUYEMZT6.js} +1 -1
  25. package/dist/{chunk-O4RZZXVP.js → chunk-OZCJHPMH.js} +3 -3
  26. package/dist/{chunk-7FYXSA76.js → chunk-P6IRD5SA.js} +10 -10
  27. package/dist/chunk-PBCBDSVA.js +1480 -0
  28. package/dist/{chunk-UWCGAXYV.js → chunk-PC3CICOW.js} +1 -1
  29. package/dist/{chunk-LFCF5KTH.js → chunk-QAXP5HON.js} +2 -2
  30. package/dist/{chunk-WKNYQ4M6.js → chunk-TJ2PFY7I.js} +2 -2
  31. package/dist/{chunk-QUIZ5IP4.js → chunk-UETHT3KG.js} +2 -2
  32. package/dist/{chunk-K5TN3BKD.js → chunk-VFLHURFM.js} +1 -1
  33. package/dist/{chunk-LGMSYVMT.js → chunk-W74MXVFX.js} +1 -1
  34. package/dist/{chunk-PC66C2AA.js → chunk-XNVYPEBO.js} +129 -21
  35. package/dist/{chunk-QRECENSK.js → chunk-YVOHCC7J.js} +4 -4
  36. package/dist/{chunk-WN4FBSFD.js → chunk-ZTJX5ONT.js} +4 -4
  37. package/dist/executions.js +12 -12
  38. package/dist/history.js +5 -4
  39. package/dist/index.d.ts +29 -1
  40. package/dist/index.js +43 -42
  41. package/dist/{node-detail-view-NTWGYZMB.js → node-detail-view-KET5DNEH.js} +427 -9
  42. package/dist/nodes.js +2 -2
  43. package/dist/observability.js +5 -5
  44. package/dist/{quick-config-panel-ZMCB6VXB.js → quick-config-panel-L6CTZQUG.js} +5 -5
  45. package/dist/settings.js +6 -6
  46. package/dist/templates.js +11 -10
  47. package/dist/workflow-builder.js +13 -12
  48. package/dist/workflows-list.js +7 -7
  49. package/package.json +1 -1
@@ -1,21 +1,21 @@
1
- import { NDV_Z_INDEX, NodeExecutionActions, ReadOnlyFieldset, NodeParamsForm } from './chunk-ITLNDVAU.js';
1
+ import { NDV_Z_INDEX, NodeExecutionActions, ReadOnlyFieldset, NodeParamsForm } from './chunk-BDBSRN2O.js';
2
2
  import { CodeEditorField } from './chunk-AASHQI77.js';
3
- import { useNodeConfig, latestNodeLog, nodeTitle, nodeSubtitle, FieldTree } from './chunk-WKNYQ4M6.js';
4
- import { RunOnSection } from './chunk-6XVGLGJ4.js';
3
+ import { useNodeConfig, latestNodeLog, nodeTitle, nodeSubtitle, FieldTree } from './chunk-TJ2PFY7I.js';
4
+ import { RunOnSection } from './chunk-OR7KZZ2D.js';
5
5
  import './chunk-GTEBQQ7J.js';
6
- import { useRunHistory, RunHistoryView, SignalRunDialog } from './chunk-QUIZ5IP4.js';
7
- import './chunk-FV77SZWB.js';
8
- import { TableView, JsonView } from './chunk-LGMSYVMT.js';
6
+ import { useRunHistory, RunHistoryView, SignalRunDialog } from './chunk-UETHT3KG.js';
7
+ import './chunk-A7QPQ6MO.js';
8
+ import { TableView, JsonView } from './chunk-W74MXVFX.js';
9
9
  import './chunk-JDLQ6QIB.js';
10
10
  import './chunk-AOLY5INN.js';
11
- import { useFlowStore, useDurableFunctionNodesEnabled, CODE_WORKFLOW_NODE_TYPE, fieldsFromValue, useNodeExecution, getNodeDetail, readCodeWorkflowState, useCodeWorkflowInterface, clearCodeWorkflowDefinitionCache, diagnosticsByPath, interfaceHandlers, declaredSignals, throwIfResultError, childRunIdOf, defaultSourcePath, describeOperationError, projectLanguage, changedSourceFiles, isEditableSourcePath, sourceLanguageOf, interfaceFields } from './chunk-V4TI5JMD.js';
11
+ import { useFlowStore, useDurableFunctionNodesEnabled, CODE_WORKFLOW_NODE_TYPE, fieldsFromValue, useNodeExecution, getNodeDetail, readCodeWorkflowState, useCodeWorkflowInterface, clearCodeWorkflowDefinitionCache, diagnosticsByPath, interfaceHandlers, declaredSignals, throwIfResultError, childRunIdOf, defaultSourcePath, describeOperationError, projectLanguage, changedSourceFiles, isEditableSourcePath, sourceLanguageOf, interfaceFields } from './chunk-23LYGZ27.js';
12
12
  import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS } from './chunk-ZUVFD5KV.js';
13
13
  import './chunk-JL7CASN5.js';
14
14
  import './chunk-OCJTTHTS.js';
15
15
  import './chunk-PXIFUMLA.js';
16
16
  import './chunk-6AMNEX2Y.js';
17
17
  import './chunk-G77IGC3Y.js';
18
- import { useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, NodeStatesDocument, WorkflowCodeSourceDocument, WorkflowEditLeaseStatusDocument, BuildWorkflowCodeDocument } from './chunk-DO554TUK.js';
18
+ import { useWorkflowPinnedDataQuery, usePinNodeDataMutation, useUnpinNodeDataMutation, NodeStatesDocument, FileDownloadUrlDocument, WorkflowCodeSourceDocument, WorkflowEditLeaseStatusDocument, BuildWorkflowCodeDocument } from './chunk-JTQFBZTV.js';
19
19
  import { useTr } from './chunk-UULVIT25.js';
20
20
  import { getFluidGridsClientSafe, getFluidGridsClient } from './chunk-NTWG3CJX.js';
21
21
  import * as React from 'react';
@@ -24,6 +24,7 @@ import { Icon } from '@iconify/react';
24
24
  import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Skeleton } from '@burdenoff/fe-libs/ui';
25
25
  import { cn } from '@burdenoff/fe-libs/utils';
26
26
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
27
+ import { FileCode, FileSpreadsheet, FileText, FileImage, File, Download } from 'lucide-react';
27
28
  import { useNavigate } from 'react-router';
28
29
  import { Button } from '@burdenoff/fe-libs/button';
29
30
 
@@ -449,6 +450,420 @@ function Field({
449
450
  children
450
451
  ] });
451
452
  }
453
+
454
+ // src/builder/lib/output-files.ts
455
+ var FILE_REFERENCE_KIND = "burdenoff.file";
456
+ var MAX_OUTPUT_FILES = 20;
457
+ var MAX_DEPTH = 8;
458
+ var TEXT_PREVIEW_MAX_BYTES = 512 * 1024;
459
+ var CSV_PREVIEW_ROWS = 50;
460
+ var CSV_PREVIEW_COLUMNS = 20;
461
+ function isRecord(value) {
462
+ return typeof value === "object" && value !== null && !Array.isArray(value);
463
+ }
464
+ function isOutputFileReference(value) {
465
+ if (!isRecord(value)) return false;
466
+ const { kind, fileId, name, mimeType, size } = value;
467
+ return kind === FILE_REFERENCE_KIND && typeof fileId === "string" && fileId.length > 0 && typeof name === "string" && typeof mimeType === "string" && typeof size === "number" && Number.isSafeInteger(size) && size >= 0;
468
+ }
469
+ function childPath(parent, key) {
470
+ if (typeof key === "number") return `${parent}[${key}]`;
471
+ return parent ? `${parent}.${key}` : key;
472
+ }
473
+ function collectOutputFiles(output) {
474
+ const files = [];
475
+ const seen = /* @__PURE__ */ new Set();
476
+ const visit = (value, path, depth) => {
477
+ if (files.length >= MAX_OUTPUT_FILES || depth > MAX_DEPTH) return;
478
+ if (isOutputFileReference(value)) {
479
+ if (!seen.has(value.fileId)) {
480
+ seen.add(value.fileId);
481
+ files.push({ path, file: value });
482
+ }
483
+ return;
484
+ }
485
+ if (Array.isArray(value)) {
486
+ value.forEach(
487
+ (entry, index) => visit(entry, childPath(path, index), depth + 1)
488
+ );
489
+ } else if (isRecord(value)) {
490
+ for (const [key, entry] of Object.entries(value)) {
491
+ visit(entry, childPath(path, key), depth + 1);
492
+ }
493
+ }
494
+ };
495
+ visit(output, "", 0);
496
+ return files;
497
+ }
498
+ var IMAGE_TYPES = /* @__PURE__ */ new Set([
499
+ "image/png",
500
+ "image/jpeg",
501
+ "image/gif",
502
+ "image/webp",
503
+ "image/avif",
504
+ "image/bmp"
505
+ ]);
506
+ var TEXT_TYPES = /* @__PURE__ */ new Set([
507
+ "application/json",
508
+ "application/xml",
509
+ "application/x-ndjson",
510
+ "application/yaml",
511
+ "application/x-yaml"
512
+ ]);
513
+ function filePreviewKind(file) {
514
+ const mimeType = file.mimeType.split(";")[0]?.trim().toLowerCase() ?? "";
515
+ const name = file.name.toLowerCase();
516
+ if (IMAGE_TYPES.has(mimeType)) return "image";
517
+ if (mimeType === "application/pdf") return "pdf";
518
+ const csv = mimeType === "text/csv" || name.endsWith(".csv");
519
+ const text = csv || mimeType.startsWith("text/") && mimeType !== "text/html" || TEXT_TYPES.has(mimeType) || /\.(txt|json|md|log|xml|ya?ml|tsv)$/.test(name);
520
+ if (!text) return null;
521
+ if (file.size > TEXT_PREVIEW_MAX_BYTES) return null;
522
+ return csv ? "csv" : "text";
523
+ }
524
+ function formatFileSize(size) {
525
+ if (size < 1024) return `${size} B`;
526
+ const units = ["KB", "MB", "GB", "TB"];
527
+ let value = size / 1024;
528
+ let unit = 0;
529
+ while (value >= 1024 && unit < units.length - 1) {
530
+ value /= 1024;
531
+ unit += 1;
532
+ }
533
+ return `${value >= 10 ? Math.round(value) : Math.round(value * 10) / 10} ${units[unit]}`;
534
+ }
535
+ function csvPreviewRows(text) {
536
+ const rows = [];
537
+ let row = [];
538
+ let cell = "";
539
+ let quoted = false;
540
+ const endCell = () => {
541
+ if (row.length < CSV_PREVIEW_COLUMNS) row.push(cell);
542
+ cell = "";
543
+ };
544
+ const endRow = () => {
545
+ endCell();
546
+ if (row.length > 1 || row[0] !== "") rows.push(row);
547
+ row = [];
548
+ };
549
+ const source = text.startsWith("\uFEFF") ? text.slice(1) : text;
550
+ for (let index = 0; index < source.length; index++) {
551
+ if (rows.length >= CSV_PREVIEW_ROWS) return rows;
552
+ const char = source[index];
553
+ if (quoted) {
554
+ if (char === '"' && source[index + 1] === '"') {
555
+ cell += '"';
556
+ index += 1;
557
+ } else if (char === '"') {
558
+ quoted = false;
559
+ } else {
560
+ cell += char;
561
+ }
562
+ } else if (char === '"' && cell === "") {
563
+ quoted = true;
564
+ } else if (char === ",") {
565
+ endCell();
566
+ } else if (char === "\n" || char === "\r") {
567
+ if (char === "\r" && source[index + 1] === "\n") index += 1;
568
+ endRow();
569
+ } else {
570
+ cell += char;
571
+ }
572
+ }
573
+ if (cell !== "" || row.length > 0) endRow();
574
+ return rows.slice(0, CSV_PREVIEW_ROWS);
575
+ }
576
+ var DOWNLOAD_URL_LIFETIME_SECONDS = 3600;
577
+ async function readTextUpTo(response, maxBytes) {
578
+ const declared = Number(response.headers.get("content-length"));
579
+ if (Number.isFinite(declared) && declared > maxBytes) {
580
+ await response.body?.cancel();
581
+ return null;
582
+ }
583
+ if (!response.body) return "";
584
+ const reader = response.body.getReader();
585
+ const chunks = [];
586
+ let total = 0;
587
+ for (; ; ) {
588
+ const { done, value } = await reader.read();
589
+ if (done) break;
590
+ total += value.byteLength;
591
+ if (total > maxBytes) {
592
+ await reader.cancel();
593
+ return null;
594
+ }
595
+ chunks.push(value);
596
+ }
597
+ const bytes = new Uint8Array(total);
598
+ let offset = 0;
599
+ for (const chunk of chunks) {
600
+ bytes.set(chunk, offset);
601
+ offset += chunk.byteLength;
602
+ }
603
+ return new TextDecoder().decode(bytes);
604
+ }
605
+ async function fetchFileDownloadUrl(fileId, expiresIn = DOWNLOAD_URL_LIFETIME_SECONDS) {
606
+ const result = await getFluidGridsClient().query({
607
+ query: FileDownloadUrlDocument,
608
+ variables: { id: fileId, expiresIn },
609
+ fetchPolicy: "network-only"
610
+ });
611
+ throwIfResultError(result);
612
+ const url = result.data?.getFileDownloadUrl;
613
+ if (!url) throw new Error("No download link for this file.");
614
+ return url;
615
+ }
616
+ var LINK_RENEWAL_MARGIN_MS = 5 * 60 * 1e3;
617
+ var LINK_RETRY_MS = 30 * 1e3;
618
+ var KIND_ICONS = {
619
+ image: FileImage,
620
+ pdf: FileText,
621
+ csv: FileSpreadsheet,
622
+ text: FileCode
623
+ };
624
+ function OutputFiles({ output }) {
625
+ const tr = useTr();
626
+ const files = useMemo(() => collectOutputFiles(output), [output]);
627
+ if (files.length === 0) return null;
628
+ return /* @__PURE__ */ jsxs(
629
+ "section",
630
+ {
631
+ className: "mx-2 mb-2 rounded-md border border-border bg-muted/30",
632
+ "data-testid": "ndv-output-files",
633
+ children: [
634
+ /* @__PURE__ */ jsx("h4", { className: "px-3 pt-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: tr("fluidgrids.builder.outputFiles.title", "Files") }),
635
+ /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border", children: files.map((entry) => /* @__PURE__ */ jsx(OutputFileRow, { entry }, entry.file.fileId)) })
636
+ ]
637
+ }
638
+ );
639
+ }
640
+ function OutputFileRow({ entry }) {
641
+ const tr = useTr();
642
+ const { file, path } = entry;
643
+ const kind = filePreviewKind(file);
644
+ const [link, setLink] = useState({ status: "loading" });
645
+ const [previewOpen, setPreviewOpen] = useState(false);
646
+ const [linkGeneration, setLinkGeneration] = useState(0);
647
+ const linkExpiresAt = useRef(0);
648
+ const KindIcon = kind ? KIND_ICONS[kind] : File;
649
+ useEffect(() => {
650
+ let active = true;
651
+ let renewal;
652
+ const renewIn = (ms) => {
653
+ renewal = setTimeout(
654
+ () => setLinkGeneration((generation) => generation + 1),
655
+ ms
656
+ );
657
+ };
658
+ fetchFileDownloadUrl(file.fileId).then(
659
+ (url) => {
660
+ if (!active) return;
661
+ linkExpiresAt.current = Date.now() + DOWNLOAD_URL_LIFETIME_SECONDS * 1e3;
662
+ setLink({ status: "ready", url });
663
+ renewIn(DOWNLOAD_URL_LIFETIME_SECONDS * 1e3 - LINK_RENEWAL_MARGIN_MS);
664
+ },
665
+ () => {
666
+ if (!active) return;
667
+ if (Date.now() + LINK_RETRY_MS < linkExpiresAt.current) {
668
+ renewIn(LINK_RETRY_MS);
669
+ } else {
670
+ setLink({ status: "error" });
671
+ }
672
+ }
673
+ );
674
+ return () => {
675
+ active = false;
676
+ clearTimeout(renewal);
677
+ };
678
+ }, [file.fileId, linkGeneration]);
679
+ return /* @__PURE__ */ jsxs("li", { className: "px-3 py-2", "data-testid": "ndv-output-file", children: [
680
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
681
+ /* @__PURE__ */ jsx(
682
+ KindIcon,
683
+ {
684
+ className: "size-4 shrink-0 text-muted-foreground",
685
+ "aria-hidden": true
686
+ }
687
+ ),
688
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
689
+ /* @__PURE__ */ jsx(
690
+ "p",
691
+ {
692
+ className: "truncate text-xs font-medium text-foreground",
693
+ title: file.name,
694
+ children: file.name || file.fileId
695
+ }
696
+ ),
697
+ /* @__PURE__ */ jsx("p", { className: "truncate text-[10px] text-muted-foreground", children: [formatFileSize(file.size), file.mimeType, path].filter(Boolean).join(" \xB7 ") })
698
+ ] }),
699
+ kind && link.status === "ready" && /* @__PURE__ */ jsx(
700
+ "button",
701
+ {
702
+ type: "button",
703
+ onClick: () => setPreviewOpen((open) => !open),
704
+ "aria-expanded": previewOpen,
705
+ className: cn(
706
+ "rounded px-1.5 py-0.5 text-[11px] font-medium transition-colors",
707
+ previewOpen ? "bg-primary/10 text-primary" : "text-muted-foreground hover:text-foreground"
708
+ ),
709
+ "data-testid": "ndv-output-file-preview-toggle",
710
+ children: previewOpen ? tr("fluidgrids.builder.outputFiles.hidePreview", "Hide preview") : tr("fluidgrids.builder.outputFiles.preview", "Preview")
711
+ }
712
+ ),
713
+ link.status === "ready" ? /* @__PURE__ */ jsxs(
714
+ "a",
715
+ {
716
+ href: link.url,
717
+ target: "_blank",
718
+ rel: "noopener noreferrer",
719
+ download: file.name || void 0,
720
+ className: "inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[11px] font-medium text-primary hover:bg-primary/10",
721
+ "data-testid": "ndv-output-file-download",
722
+ children: [
723
+ /* @__PURE__ */ jsx(Download, { className: "size-3.5", "aria-hidden": true }),
724
+ tr("fluidgrids.builder.outputFiles.download", "Download")
725
+ ]
726
+ }
727
+ ) : /* @__PURE__ */ jsx(
728
+ "span",
729
+ {
730
+ className: cn(
731
+ "text-[11px]",
732
+ link.status === "error" ? "text-destructive" : "text-muted-foreground"
733
+ ),
734
+ "data-testid": "ndv-output-file-link-status",
735
+ children: link.status === "error" ? tr(
736
+ "fluidgrids.builder.outputFiles.linkFailed",
737
+ "Could not get a download link"
738
+ ) : tr("fluidgrids.builder.outputFiles.loading", "Loading\u2026")
739
+ }
740
+ )
741
+ ] }),
742
+ previewOpen && kind && link.status === "ready" && /* @__PURE__ */ jsx(FilePreview, { kind, url: link.url, file })
743
+ ] });
744
+ }
745
+ function FilePreview({
746
+ kind,
747
+ url,
748
+ file
749
+ }) {
750
+ const tr = useTr();
751
+ if (kind === "image") {
752
+ return /* @__PURE__ */ jsx(
753
+ "img",
754
+ {
755
+ src: url,
756
+ alt: file.name,
757
+ loading: "lazy",
758
+ className: "mt-2 max-h-80 max-w-full rounded border border-border object-contain",
759
+ "data-testid": "ndv-output-file-image"
760
+ }
761
+ );
762
+ }
763
+ if (kind === "pdf") {
764
+ return /* @__PURE__ */ jsx(
765
+ "object",
766
+ {
767
+ data: url,
768
+ type: "application/pdf",
769
+ "aria-label": file.name,
770
+ className: "mt-2 h-96 w-full rounded border border-border",
771
+ "data-testid": "ndv-output-file-pdf",
772
+ children: /* @__PURE__ */ jsx("p", { className: "p-3 text-xs text-muted-foreground", children: tr(
773
+ "fluidgrids.builder.outputFiles.pdfUnavailable",
774
+ "This browser cannot show the PDF here; download it instead."
775
+ ) })
776
+ }
777
+ );
778
+ }
779
+ return /* @__PURE__ */ jsx(TextPreview, { url, csv: kind === "csv" });
780
+ }
781
+ function TextPreview({ url, csv }) {
782
+ const tr = useTr();
783
+ const [state, setState] = useState({ status: "loading" });
784
+ useEffect(() => {
785
+ const controller = new AbortController();
786
+ setState({ status: "loading" });
787
+ fetch(url, { signal: controller.signal }).then((response) => {
788
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
789
+ return readTextUpTo(response, TEXT_PREVIEW_MAX_BYTES);
790
+ }).then(
791
+ (text) => setState(
792
+ text === null ? { status: "tooLarge" } : { status: "ready", text }
793
+ ),
794
+ () => {
795
+ if (!controller.signal.aborted) setState({ status: "error" });
796
+ }
797
+ );
798
+ return () => controller.abort();
799
+ }, [url]);
800
+ if (state.status === "loading") {
801
+ return /* @__PURE__ */ jsx("p", { className: "mt-2 text-[11px] text-muted-foreground", children: tr("fluidgrids.builder.outputFiles.loading", "Loading\u2026") });
802
+ }
803
+ if (state.status === "tooLarge") {
804
+ return /* @__PURE__ */ jsx(
805
+ "p",
806
+ {
807
+ className: "mt-2 text-[11px] text-muted-foreground",
808
+ "data-testid": "ndv-output-file-preview-too-large",
809
+ children: tr(
810
+ "fluidgrids.builder.outputFiles.previewTooLarge",
811
+ "Too large to preview here; download it instead."
812
+ )
813
+ }
814
+ );
815
+ }
816
+ if (state.status === "error") {
817
+ return /* @__PURE__ */ jsx(
818
+ "p",
819
+ {
820
+ className: "mt-2 text-[11px] text-destructive",
821
+ "data-testid": "ndv-output-file-preview-error",
822
+ children: tr(
823
+ "fluidgrids.builder.outputFiles.previewFailed",
824
+ "Could not load the preview"
825
+ )
826
+ }
827
+ );
828
+ }
829
+ if (csv) {
830
+ const rows = csvPreviewRows(state.text);
831
+ const [header = [], ...body] = rows;
832
+ return /* @__PURE__ */ jsx("div", { className: "mt-2 max-h-80 overflow-auto rounded border border-border", children: /* @__PURE__ */ jsxs(
833
+ "table",
834
+ {
835
+ className: "w-full border-collapse text-[11px]",
836
+ "data-testid": "ndv-output-file-csv",
837
+ children: [
838
+ /* @__PURE__ */ jsx("thead", { className: "sticky top-0 bg-muted", children: /* @__PURE__ */ jsx("tr", { children: header.map((cell, index) => /* @__PURE__ */ jsx(
839
+ "th",
840
+ {
841
+ className: "border-b border-border px-2 py-1 text-left font-semibold text-foreground",
842
+ children: cell
843
+ },
844
+ index
845
+ )) }) }),
846
+ /* @__PURE__ */ jsx("tbody", { children: body.map((row, rowIndex) => /* @__PURE__ */ jsx("tr", { className: "odd:bg-muted/20", children: row.map((cell, index) => /* @__PURE__ */ jsx(
847
+ "td",
848
+ {
849
+ className: "max-w-[16rem] truncate border-b border-border px-2 py-1 text-muted-foreground",
850
+ children: cell
851
+ },
852
+ index
853
+ )) }, rowIndex)) })
854
+ ]
855
+ }
856
+ ) });
857
+ }
858
+ return /* @__PURE__ */ jsx(
859
+ "pre",
860
+ {
861
+ className: "mt-2 max-h-80 overflow-auto whitespace-pre-wrap break-words rounded border border-border bg-background p-2 text-[11px] leading-relaxed text-foreground",
862
+ "data-testid": "ndv-output-file-text",
863
+ children: state.text
864
+ }
865
+ );
866
+ }
452
867
  function useMediaQuery(query) {
453
868
  const [matches, setMatches] = React.useState(false);
454
869
  React.useEffect(() => {
@@ -1800,7 +2215,10 @@ function NodeDetailView() {
1800
2215
  {
1801
2216
  className: "min-h-0 flex-1 overflow-auto px-2 pb-3",
1802
2217
  "data-testid": "ndv-output-tree",
1803
- children: hasRealOutput ? outputView === "schema" ? /* @__PURE__ */ jsx(FieldTree, { fields: realOutputFields, draggable: true }) : outputView === "table" ? /* @__PURE__ */ jsx(TableView, { data: nodeLog.output }) : /* @__PURE__ */ jsx(JsonView, { data: nodeLog.output }) : outputFields.length === 0 ? /* @__PURE__ */ jsx(
2218
+ children: hasRealOutput ? /* @__PURE__ */ jsxs(Fragment, { children: [
2219
+ /* @__PURE__ */ jsx(OutputFiles, { output: nodeLog.output }),
2220
+ outputView === "schema" ? /* @__PURE__ */ jsx(FieldTree, { fields: realOutputFields, draggable: true }) : outputView === "table" ? /* @__PURE__ */ jsx(TableView, { data: nodeLog.output }) : /* @__PURE__ */ jsx(JsonView, { data: nodeLog.output })
2221
+ ] }) : outputFields.length === 0 ? /* @__PURE__ */ jsx(
1804
2222
  EmptyState,
1805
2223
  {
1806
2224
  icon: "mdi:tray-arrow-up",
package/dist/nodes.js CHANGED
@@ -1,4 +1,4 @@
1
- export { NodesPage } from './chunk-K5TN3BKD.js';
2
- import './chunk-DO554TUK.js';
1
+ export { NodesPage } from './chunk-VFLHURFM.js';
2
+ import './chunk-JTQFBZTV.js';
3
3
  import './chunk-UULVIT25.js';
4
4
  import './chunk-NTWG3CJX.js';
@@ -1,16 +1,16 @@
1
- export { DataSinkDashboardPage, ErrorAnalyticsPage, InsightsPage } from './chunk-EZRX2PZT.js';
2
- import './chunk-IQZ3DD7U.js';
3
- import './chunk-FLYFZJUC.js';
1
+ export { DataSinkDashboardPage, ErrorAnalyticsPage, InsightsPage } from './chunk-7JLLH4YE.js';
2
+ import './chunk-A4XNCGWT.js';
3
+ import './chunk-CXNJKM4D.js';
4
4
  import './chunk-5ERAJC2I.js';
5
5
  import './chunk-GLYINMOR.js';
6
6
  import './chunk-AOLY5INN.js';
7
- import './chunk-V4TI5JMD.js';
7
+ import './chunk-23LYGZ27.js';
8
8
  import './chunk-ZUVFD5KV.js';
9
9
  import './chunk-JL7CASN5.js';
10
10
  import './chunk-OCJTTHTS.js';
11
11
  import './chunk-PXIFUMLA.js';
12
12
  import './chunk-6AMNEX2Y.js';
13
13
  import './chunk-G77IGC3Y.js';
14
- import './chunk-DO554TUK.js';
14
+ import './chunk-JTQFBZTV.js';
15
15
  import './chunk-UULVIT25.js';
16
16
  import './chunk-NTWG3CJX.js';
@@ -1,18 +1,18 @@
1
- import { ReadOnlyFieldset, NodeParamsForm, NodeExecutionActions } from './chunk-ITLNDVAU.js';
1
+ import { ReadOnlyFieldset, NodeParamsForm, NodeExecutionActions } from './chunk-BDBSRN2O.js';
2
2
  import './chunk-AASHQI77.js';
3
- import { useNodeConfig, nodeSubtitle, nodeTitle, FieldTree } from './chunk-WKNYQ4M6.js';
3
+ import { useNodeConfig, nodeSubtitle, nodeTitle, FieldTree } from './chunk-TJ2PFY7I.js';
4
4
  import './chunk-GTEBQQ7J.js';
5
- import './chunk-FV77SZWB.js';
5
+ import './chunk-A7QPQ6MO.js';
6
6
  import './chunk-JDLQ6QIB.js';
7
7
  import './chunk-AOLY5INN.js';
8
- import { useFlowStore, useNodeExecution, getNodeDetail, nodeAccent, NodeTypeIcon } from './chunk-V4TI5JMD.js';
8
+ import { useFlowStore, useNodeExecution, getNodeDetail, nodeAccent, NodeTypeIcon } from './chunk-23LYGZ27.js';
9
9
  import './chunk-ZUVFD5KV.js';
10
10
  import './chunk-JL7CASN5.js';
11
11
  import './chunk-OCJTTHTS.js';
12
12
  import './chunk-PXIFUMLA.js';
13
13
  import './chunk-6AMNEX2Y.js';
14
14
  import './chunk-G77IGC3Y.js';
15
- import './chunk-DO554TUK.js';
15
+ import './chunk-JTQFBZTV.js';
16
16
  import { useTr } from './chunk-UULVIT25.js';
17
17
  import './chunk-NTWG3CJX.js';
18
18
  import { useState, useRef, useLayoutEffect, useMemo, useEffect } from 'react';
package/dist/settings.js CHANGED
@@ -1,16 +1,16 @@
1
- export { SettingsPage } from './chunk-6JJKKWVD.js';
2
- import './chunk-FV77SZWB.js';
3
- import './chunk-XGMGCOTR.js';
4
- import './chunk-FLYFZJUC.js';
1
+ export { SettingsPage } from './chunk-6VODFT2Q.js';
2
+ import './chunk-A7QPQ6MO.js';
3
+ import './chunk-DLKGWGRN.js';
4
+ import './chunk-CXNJKM4D.js';
5
5
  import './chunk-5ERAJC2I.js';
6
6
  import './chunk-4VJ3MDOV.js';
7
- import './chunk-V4TI5JMD.js';
7
+ import './chunk-23LYGZ27.js';
8
8
  import './chunk-ZUVFD5KV.js';
9
9
  import './chunk-JL7CASN5.js';
10
10
  import './chunk-OCJTTHTS.js';
11
11
  import './chunk-PXIFUMLA.js';
12
12
  import './chunk-6AMNEX2Y.js';
13
13
  import './chunk-G77IGC3Y.js';
14
- import './chunk-DO554TUK.js';
14
+ import './chunk-JTQFBZTV.js';
15
15
  import './chunk-UULVIT25.js';
16
16
  import './chunk-NTWG3CJX.js';
package/dist/templates.js CHANGED
@@ -1,30 +1,31 @@
1
- export { TemplatePreview, TemplatesPage } from './chunk-QRECENSK.js';
2
- import './chunk-KEPQLNP6.js';
1
+ export { TemplatePreview, TemplatesPage } from './chunk-YVOHCC7J.js';
2
+ import './chunk-MY752OLT.js';
3
3
  import './chunk-GEMNVFPK.js';
4
4
  import './chunk-B6CCE2RW.js';
5
5
  import './chunk-IEVSFCFS.js';
6
6
  import './chunk-YXMFRQYV.js';
7
7
  import './chunk-BQXVT32O.js';
8
- import './chunk-LGMSYVMT.js';
9
- import './chunk-AVZ4SXUG.js';
10
- import './chunk-7MGYG6DR.js';
11
- import './chunk-D56WJCK6.js';
8
+ import './chunk-W74MXVFX.js';
9
+ import './chunk-OUYEMZT6.js';
10
+ import './chunk-4FDMLKLL.js';
11
+ import './chunk-3Y4266JL.js';
12
12
  import './chunk-JDLQ6QIB.js';
13
- import './chunk-UWCGAXYV.js';
13
+ import './chunk-PC3CICOW.js';
14
14
  import './chunk-Y53CVZVV.js';
15
+ import './chunk-PBCBDSVA.js';
15
16
  import './chunk-FNZZ5JJL.js';
16
- import './chunk-BUWFUPN2.js';
17
+ import './chunk-EFOJEQDS.js';
17
18
  import './chunk-PJAWNFJV.js';
18
19
  import './chunk-GLYINMOR.js';
19
20
  import './chunk-AOLY5INN.js';
20
21
  import './chunk-4VJ3MDOV.js';
21
- import './chunk-V4TI5JMD.js';
22
+ import './chunk-23LYGZ27.js';
22
23
  import './chunk-ZUVFD5KV.js';
23
24
  import './chunk-JL7CASN5.js';
24
25
  import './chunk-OCJTTHTS.js';
25
26
  import './chunk-PXIFUMLA.js';
26
27
  import './chunk-6AMNEX2Y.js';
27
28
  import './chunk-G77IGC3Y.js';
28
- import './chunk-DO554TUK.js';
29
+ import './chunk-JTQFBZTV.js';
29
30
  import './chunk-UULVIT25.js';
30
31
  import './chunk-NTWG3CJX.js';
@@ -1,31 +1,32 @@
1
- export { WorkflowBuilder, WorkflowBuilderCore, WorkflowSearchRedirect } from './chunk-O4RZZXVP.js';
2
- export { WorkflowBuilder as WorkflowBuilderPage } from './chunk-QBYLI3HK.js';
3
- import './chunk-6EE4PRD6.js';
1
+ export { WorkflowBuilder, WorkflowBuilderCore, WorkflowSearchRedirect } from './chunk-OZCJHPMH.js';
2
+ export { WorkflowBuilder as WorkflowBuilderPage } from './chunk-37BKVPO7.js';
3
+ import './chunk-JCHE4V55.js';
4
4
  import './chunk-PIKYQE7P.js';
5
- import './chunk-KEPQLNP6.js';
5
+ import './chunk-MY752OLT.js';
6
6
  import './chunk-GEMNVFPK.js';
7
7
  import './chunk-B6CCE2RW.js';
8
8
  import './chunk-IEVSFCFS.js';
9
9
  import './chunk-YXMFRQYV.js';
10
10
  import './chunk-BQXVT32O.js';
11
- import './chunk-LGMSYVMT.js';
12
- import './chunk-AVZ4SXUG.js';
13
- import './chunk-7MGYG6DR.js';
14
- import './chunk-D56WJCK6.js';
11
+ import './chunk-W74MXVFX.js';
12
+ import './chunk-OUYEMZT6.js';
13
+ import './chunk-4FDMLKLL.js';
14
+ import './chunk-3Y4266JL.js';
15
15
  import './chunk-JDLQ6QIB.js';
16
- import './chunk-UWCGAXYV.js';
16
+ import './chunk-PC3CICOW.js';
17
17
  import './chunk-Y53CVZVV.js';
18
- import './chunk-BUWFUPN2.js';
18
+ import './chunk-PBCBDSVA.js';
19
+ import './chunk-EFOJEQDS.js';
19
20
  import './chunk-GLYINMOR.js';
20
21
  import './chunk-AOLY5INN.js';
21
22
  import './chunk-4VJ3MDOV.js';
22
- export { refetchStoreNodes, useFlowStore } from './chunk-V4TI5JMD.js';
23
+ export { refetchStoreNodes, useFlowStore } from './chunk-23LYGZ27.js';
23
24
  import './chunk-ZUVFD5KV.js';
24
25
  import './chunk-JL7CASN5.js';
25
26
  import './chunk-OCJTTHTS.js';
26
27
  import './chunk-PXIFUMLA.js';
27
28
  import './chunk-6AMNEX2Y.js';
28
29
  import './chunk-G77IGC3Y.js';
29
- import './chunk-DO554TUK.js';
30
+ import './chunk-JTQFBZTV.js';
30
31
  import './chunk-UULVIT25.js';
31
32
  import './chunk-NTWG3CJX.js';
@@ -1,20 +1,20 @@
1
- export { WorkflowsList } from './chunk-LIVFWFT4.js';
2
- import './chunk-6EE4PRD6.js';
3
- import './chunk-LFCF5KTH.js';
1
+ export { WorkflowsList } from './chunk-7SY2SL5Y.js';
2
+ import './chunk-JCHE4V55.js';
3
+ import './chunk-QAXP5HON.js';
4
4
  import './chunk-5ERAJC2I.js';
5
- import './chunk-7MGYG6DR.js';
5
+ import './chunk-4FDMLKLL.js';
6
6
  import './chunk-FNZZ5JJL.js';
7
- import './chunk-BUWFUPN2.js';
7
+ import './chunk-EFOJEQDS.js';
8
8
  import './chunk-PJAWNFJV.js';
9
9
  import './chunk-AOLY5INN.js';
10
10
  import './chunk-4VJ3MDOV.js';
11
- import './chunk-V4TI5JMD.js';
11
+ import './chunk-23LYGZ27.js';
12
12
  import './chunk-ZUVFD5KV.js';
13
13
  import './chunk-JL7CASN5.js';
14
14
  import './chunk-OCJTTHTS.js';
15
15
  import './chunk-PXIFUMLA.js';
16
16
  import './chunk-6AMNEX2Y.js';
17
17
  import './chunk-G77IGC3Y.js';
18
- import './chunk-DO554TUK.js';
18
+ import './chunk-JTQFBZTV.js';
19
19
  import './chunk-UULVIT25.js';
20
20
  import './chunk-NTWG3CJX.js';