@parallelworks/ui 0.12.0 → 0.13.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.
Files changed (84) hide show
  1. package/dist/chunks/{BareModal-DBa84JZO.js → BareModal-BqroLbZ5.js} +1 -0
  2. package/dist/chunks/{CodePreviewEditor-hwjZof0M.js → CodePreviewEditor-67A_SKgE.js} +1 -1
  3. package/dist/chunks/{CreateModal-g6c-9-6N.js → CreateModal-k_e1dI8c.js} +31 -10
  4. package/dist/chunks/{Monaco-DCwRDrPm.js → Monaco-H56KyEdb.js} +22 -12
  5. package/dist/chunks/{PageHeader-dyoL44ue.js → PageHeader-FhtphHGc.js} +44 -10
  6. package/dist/chunks/{Provider-CfFV-vc5.js → Provider-CbFVFB7O.js} +8 -2
  7. package/dist/chunks/RequiredMark-DfLdYbYZ.js +11 -0
  8. package/dist/chunks/{StatusBadge-P6C2tv7Z.js → StatusBadge-RRUI78iS.js} +4 -4
  9. package/dist/chunks/{SwitchToggle-DcPCXkqL.js → SwitchToggle-DbW0Q__L.js} +49 -32
  10. package/dist/chunks/{Table-ByziK93x.js → Table-CutP1bRt.js} +22 -6
  11. package/dist/chunks/{Tooltip-WgbiC_nd.js → Tooltip-n9w7Tkt1.js} +28 -3
  12. package/dist/chunks/{editor-BH81U5-C.js → editor-BZ9Buwi4.js} +34 -23
  13. package/dist/chunks/lib-DyJvmbzj.js +256 -0
  14. package/dist/chunks/{list-CWVR3dfZ.js → list-3jZW8rmM.js} +33 -13
  15. package/dist/components/Breadcrumbs.d.ts +9 -0
  16. package/dist/components/CollapsiblePanel.d.ts +4 -4
  17. package/dist/components/CreateModal.d.ts +8 -8
  18. package/dist/components/Dropdown.d.ts +5 -3
  19. package/dist/components/Input.d.ts +1 -1
  20. package/dist/components/Listbox.d.ts +7 -4
  21. package/dist/components/Loader.d.ts +1 -1
  22. package/dist/components/MultiSelect.d.ts +8 -5
  23. package/dist/components/PageHeader.d.ts +3 -3
  24. package/dist/components/Pagination.d.ts +2 -2
  25. package/dist/components/Provider.d.ts +9 -3
  26. package/dist/components/RequiredMark.d.ts +1 -0
  27. package/dist/components/SettingRow.d.ts +1 -1
  28. package/dist/components/SwitchToggle.d.ts +3 -2
  29. package/dist/components/Table.d.ts +5 -3
  30. package/dist/components/Tooltip.d.ts +7 -1
  31. package/dist/components/dropdownUtils.d.ts +6 -6
  32. package/dist/editor/FormCodePanel.d.ts +3 -3
  33. package/dist/editor/Monaco.d.ts +2 -2
  34. package/dist/editor/index.js +1 -1
  35. package/dist/file-explorer/FileExplorer.d.ts +2 -2
  36. package/dist/file-explorer/helpers.d.ts +2 -2
  37. package/dist/file-explorer/index.d.ts +1 -1
  38. package/dist/file-explorer/index.js +54 -23
  39. package/dist/file-explorer/lib/fileExplorer.d.ts +4 -2
  40. package/dist/file-explorer/lib/types.d.ts +21 -21
  41. package/dist/file-explorer/lib/utils.d.ts +1 -0
  42. package/dist/form/FieldWrapper.d.ts +6 -1
  43. package/dist/form/Fields/ResourceOptionIcon.d.ts +1 -1
  44. package/dist/form/Fields/StepField.d.ts +1 -1
  45. package/dist/form/Form.d.ts +28 -27
  46. package/dist/form/SpecialTypes/DropdownWrapper.d.ts +16 -3
  47. package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +11 -11
  48. package/dist/form/SpecialTypes/FormikCustomInput.d.ts +12 -10
  49. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +1 -1
  50. package/dist/form/SpecialTypes/FormikNumericInput.d.ts +2 -2
  51. package/dist/form/Wizard/WizardContainer.d.ts +1 -1
  52. package/dist/form/Wizard/WizardStepContent.d.ts +2 -2
  53. package/dist/form/Wizard/types.d.ts +21 -14
  54. package/dist/form/Wizard/utils.d.ts +1 -1
  55. package/dist/form/fieldContext.d.ts +19 -0
  56. package/dist/form/index.d.ts +2 -1
  57. package/dist/form/index.js +191 -106
  58. package/dist/form/lib.d.ts +3 -3
  59. package/dist/form/types/fieldComponentTypes.d.ts +2 -2
  60. package/dist/form/useParsedOpts.d.ts +1 -1
  61. package/dist/form/utils/getParentValue.d.ts +3 -1
  62. package/dist/form/utils/getValueUsingPath.d.ts +1 -1
  63. package/dist/form/utils/pwResolver.d.ts +4 -4
  64. package/dist/icons.d.ts +5 -5
  65. package/dist/index.d.ts +3 -2
  66. package/dist/index.js +51 -21
  67. package/dist/list/ActionToolbar.d.ts +4 -4
  68. package/dist/list/ListPage.d.ts +3 -3
  69. package/dist/list/ListTable.d.ts +1 -1
  70. package/dist/list/RowContextMenu.d.ts +20 -20
  71. package/dist/list/index.js +2 -2
  72. package/dist/logviewer/index.js +24 -7
  73. package/dist/styles/theme.css +6 -6
  74. package/dist/styles.css +1 -1
  75. package/dist/theme/index.js +4 -3
  76. package/dist/workflow/AnnotationBanner.d.ts +2 -1
  77. package/dist/workflow/DependencyGraph.d.ts +15 -3
  78. package/dist/workflow/JobSummary.d.ts +2 -25
  79. package/dist/workflow/MatrixGroup.d.ts +3 -2
  80. package/dist/workflow/TreeView.d.ts +1 -32
  81. package/dist/workflow/index.js +235 -138
  82. package/dist/workflow/types.d.ts +48 -0
  83. package/package.json +2 -6
  84. package/dist/chunks/lib-DTgL8klR.js +0 -191
@@ -1,12 +1,12 @@
1
1
  import { AccessIcon, AlertIcon, AngleDownIcon, AngleRightIcon, AngleUpIcon, ChevronLeftIcon, ChevronRightIcon, ClipboardIcon, CloseIcon, CloudUploadIcon, CollapseIcon, CustomizeIcon, DiskIcon, DocumentIcon, DownloadFileIcon, ExpandIcon, ExpandVerticalIcon, EyeIcon, FileIcon, FileTextIcon, FolderIcon, FolderOpenIcon, ImageIcon, LinkIcon, LockIcon, MinimizeIcon, MusicIcon, PdfIcon, RefreshIcon, ShareIcon, SpreadsheetIcon, SuccessIcon, TrashIcon, UploadIcon, UserIcon, VideoIcon, ZipIcon, ZoomInIcon, ZoomOutIcon } from "../icons.js";
2
- import { c as ConfirmModal, f as Markdown, h as Callout, m as CopyToClipboard, n as CreateModal, p as CopyCodeBlock } from "../chunks/CreateModal-g6c-9-6N.js";
3
- import { a as useProvisionCorsRules, c as useStrings, i as useNotify, s as useSlots } from "../chunks/Provider-CfFV-vc5.js";
4
- import { n as TOOLTIP_ID, r as TooltipInfo } from "../chunks/Tooltip-WgbiC_nd.js";
5
- import { t as StatusBadge } from "../chunks/StatusBadge-P6C2tv7Z.js";
2
+ import { c as ConfirmModal, f as Markdown, h as Callout, m as CopyToClipboard, n as CreateModal, p as CopyCodeBlock } from "../chunks/CreateModal-k_e1dI8c.js";
3
+ import { a as useProvisionCorsRules, c as useStrings, i as useNotify, s as useSlots } from "../chunks/Provider-CbFVFB7O.js";
4
+ import { n as TOOLTIP_ID, r as TooltipInfo } from "../chunks/Tooltip-n9w7Tkt1.js";
5
+ import { t as StatusBadge } from "../chunks/StatusBadge-RRUI78iS.js";
6
6
  import { t as Loader } from "../chunks/Loader-BXoXTZGc.js";
7
- import { d as copySubmenu, g as useRowMenuActive, h as useRowMenu, l as MoreButton, u as assembleRowMenu } from "../chunks/PageHeader-dyoL44ue.js";
8
- import { n as Table } from "../chunks/Table-ByziK93x.js";
9
- import { C as ListSkeleton, E as RowSelectCheckbox, O as listTableFixedProps, k as listTableProps, x as ListActionsHeader } from "../chunks/list-CWVR3dfZ.js";
7
+ import { d as copySubmenu, g as useRowMenuActive, h as useRowMenu, l as MoreButton, u as assembleRowMenu } from "../chunks/PageHeader-FhtphHGc.js";
8
+ import { n as Table } from "../chunks/Table-CutP1bRt.js";
9
+ import { C as ListSkeleton, E as RowSelectCheckbox, O as listTableFixedProps, k as listTableProps, x as ListActionsHeader } from "../chunks/list-3jZW8rmM.js";
10
10
  import cx from "classnames";
11
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
12
  import { Suspense, createContext, lazy, memo, use, useCallback, useEffect, useEffectEvent, useId, useLayoutEffect, useMemo, useRef, useState, useTransition } from "react";
@@ -36,7 +36,7 @@ function getFileExtension(filename) {
36
36
  }
37
37
  function getNodeName(node) {
38
38
  const parts = removeTrailingSlash(node.path || "").split("/");
39
- return parts[parts.length - 1];
39
+ return parts[parts.length - 1] ?? "";
40
40
  }
41
41
  function buildTreeFromStorage(storage, unsortedParents) {
42
42
  if (!storage) return {
@@ -134,7 +134,7 @@ function buildTreeFromUserStorages(storages, options) {
134
134
  displayName: username
135
135
  };
136
136
  parentToChildrenMap[userPath] = [];
137
- for (const storage of userGroups[username]) {
137
+ for (const storage of userGroups[username] ?? []) {
138
138
  const cspBucketName = storage.bucketName || storage.name;
139
139
  const storageFullPath = ensureTrailingSlash(`${userPath}${removeLeadingAndTrailingSlashes(storage.name)}`);
140
140
  treeMap[storageFullPath] = {
@@ -222,7 +222,7 @@ async function getUploadNodesFromDataTransferItems(items) {
222
222
  }
223
223
  const entries = [];
224
224
  for (let i = 0; i < items.length; i++) {
225
- const entry = items[i].webkitGetAsEntry?.();
225
+ const entry = items[i]?.webkitGetAsEntry?.();
226
226
  if (entry) entries.push(entry);
227
227
  }
228
228
  for (const entry of entries) await traverse(entry);
@@ -239,6 +239,9 @@ function calculateUploadNodesTotalSize(uploadNodes) {
239
239
  function getObjectKeyFromNode(node) {
240
240
  return node.relativePath || node.path.split("/").filter(Boolean).slice(1).join("/");
241
241
  }
242
+ function attachmentDisposition(filename) {
243
+ return `attachment; filename="${filename.replace(/[^\x20-\x7e]|["\\]/g, "_")}"; filename*=UTF-8''${encodeURIComponent(filename).replace(/['()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`)}`;
244
+ }
242
245
  function getDirectoryPrefixFromNode(node) {
243
246
  const key = getObjectKeyFromNode(node);
244
247
  if (!key) throw new Error(`Cannot resolve an object prefix for ${node.path}`);
@@ -436,6 +439,7 @@ function FileProgressBar({ fileProgress, fileName, progressBarColorScheme, onCan
436
439
  className: "flex items-center gap-1",
437
440
  children: [
438
441
  /* @__PURE__ */ jsx("div", {
442
+ role: "none",
439
443
  className: "relative flex-1",
440
444
  onMouseEnter: () => setIsHovered(true),
441
445
  onMouseLeave: () => setIsHovered(false),
@@ -470,6 +474,8 @@ function FileProgressBar({ fileProgress, fileName, progressBarColorScheme, onCan
470
474
  })
471
475
  }),
472
476
  !showCancelConfirm && canCancel && /* @__PURE__ */ jsx("button", {
477
+ type: "button",
478
+ "aria-label": `Cancel ${fileName}`,
473
479
  className: "p-1 rounded-full hover:bg-red-100 relative cursor-pointer",
474
480
  onClick: handleCancelClick,
475
481
  title: `Cancel ${fileName}`,
@@ -483,11 +489,13 @@ function FileProgressBar({ fileProgress, fileName, progressBarColorScheme, onCan
483
489
  children: "Cancel?"
484
490
  }),
485
491
  /* @__PURE__ */ jsx("button", {
492
+ type: "button",
486
493
  className: "px-1.5 py-0.5 text-xs bg-(--theme-border) theme-muted-text rounded hover:theme-hover",
487
494
  onClick: handleKeepUploading,
488
495
  children: "No"
489
496
  }),
490
497
  /* @__PURE__ */ jsx("button", {
498
+ type: "button",
491
499
  className: "!px-1.5 !py-0.5 text-xs btn btn-destructive cursor-pointer",
492
500
  onClick: handleConfirmCancel,
493
501
  children: "Yes"
@@ -562,6 +570,7 @@ function UploadSessionToast({ session, queueLength, onCancel, onCancelFile }) {
562
570
  className: cx("w-10 h-10 rounded-full flex items-center justify-center", statusInfo.bgColor),
563
571
  children: statusInfo.icon
564
572
  }), /* @__PURE__ */ jsxs("div", {
573
+ role: "none",
565
574
  className: "flex-1 cursor-pointer",
566
575
  onClick: handleExpandClick,
567
576
  children: [
@@ -576,6 +585,8 @@ function UploadSessionToast({ session, queueLength, onCancel, onCancelFile }) {
576
585
  className: "text-xs theme-muted-text ml-2",
577
586
  children: [totalProgress.toFixed(1), "%"]
578
587
  }), /* @__PURE__ */ jsx("button", {
588
+ type: "button",
589
+ "aria-label": strings.expandDetails,
579
590
  className: "flex items-center justify-between text-xs theme-muted-text hover:theme-text cursor-pointer",
580
591
  onClick: handleExpandClick,
581
592
  title: strings.expandDetails,
@@ -635,6 +646,8 @@ function UploadSessionToast({ session, queueLength, onCancel, onCancelFile }) {
635
646
  ]
636
647
  })] })]
637
648
  }), /* @__PURE__ */ jsx("button", {
649
+ type: "button",
650
+ "aria-label": strings.minimizeDetails,
638
651
  className: "flex items-center justify-between text-xs theme-muted-text hover:theme-text cursor-pointer mr-2",
639
652
  onClick: handleExpandClick,
640
653
  title: strings.minimizeDetails,
@@ -690,6 +703,7 @@ function UploadSessionToast({ session, queueLength, onCancel, onCancelFile }) {
690
703
  session.uploadNodes.length > 1 && /* @__PURE__ */ jsxs("div", {
691
704
  className: "flex flex-col bg-(--theme-muted-panel-bg) rounded py-2 px-3 space-y-2 transition-all duration-300",
692
705
  children: [/* @__PURE__ */ jsxs("button", {
706
+ type: "button",
693
707
  className: "flex items-center justify-between text-xs theme-muted-text hover:theme-text cursor-pointer",
694
708
  onClick: () => setIsExpanded(!isFileListExpanded),
695
709
  children: [/* @__PURE__ */ jsxs("span", { children: [session.uploadNodes.length, " files"] }), isFileListExpanded ? /* @__PURE__ */ jsx(AngleUpIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx(AngleDownIcon, { className: "w-4 h-4" })]
@@ -716,6 +730,7 @@ function UploadSessionToast({ session, queueLength, onCancel, onCancelFile }) {
716
730
  /* @__PURE__ */ jsxs("div", {
717
731
  className: "flex items-center justify-end",
718
732
  children: [shouldShowSessionCancelButton && /* @__PURE__ */ jsx("button", {
733
+ type: "button",
719
734
  className: "!px-2 !py-1 text-xs btn btn-destructive cursor-pointer transition-colors",
720
735
  onClick: handleCancelClick,
721
736
  children: "Cancel"
@@ -727,11 +742,13 @@ function UploadSessionToast({ session, queueLength, onCancel, onCancelFile }) {
727
742
  children: "Cancel all uploading files?"
728
743
  }),
729
744
  /* @__PURE__ */ jsx("button", {
745
+ type: "button",
730
746
  className: "!px-2 !py-1 text-xs bg-(--theme-border) theme-muted-text rounded hover:theme-hover",
731
747
  onClick: handleKeepUploading,
732
748
  children: "No"
733
749
  }),
734
750
  /* @__PURE__ */ jsx("button", {
751
+ type: "button",
735
752
  className: "!px-2 !py-1 text-xs btn btn-destructive cursor-pointer",
736
753
  onClick: handleConfirmCancel,
737
754
  children: "Yes"
@@ -1339,10 +1356,12 @@ function CorsIssuePreview({ selectedStorage, onRefresh }) {
1339
1356
  }), /* @__PURE__ */ jsxs("div", {
1340
1357
  className: "flex gap-3 justify-center",
1341
1358
  children: [/* @__PURE__ */ jsxs("button", {
1359
+ type: "button",
1342
1360
  className: "btn btn-info cursor-pointer flex items-center",
1343
1361
  onClick: onRefresh ? () => onRefresh() : void 0,
1344
1362
  children: [/* @__PURE__ */ jsx(RefreshIcon, { className: "h-4 w-4 mr-2" }), t.actions.retry]
1345
1363
  }), provisionCorsRules && /* @__PURE__ */ jsxs("button", {
1364
+ type: "button",
1346
1365
  className: "btn btn-info cursor-pointer flex items-center",
1347
1366
  onClick: handleAddCorsRules,
1348
1367
  children: [/* @__PURE__ */ jsx(CustomizeIcon, { className: "h-4 w-4 mr-2" }), /* @__PURE__ */ jsx("span", { children: t.actions.addRules })]
@@ -1529,6 +1548,7 @@ function NoDataAvailablePreview({ selectedStorage, error, onRefresh, connectionI
1529
1548
  children: connectionIssueMessage
1530
1549
  }),
1531
1550
  /* @__PURE__ */ jsxs("button", {
1551
+ type: "button",
1532
1552
  className: "btn btn-info cursor-pointer flex items-center gap-2",
1533
1553
  onClick: onRefresh ? () => onRefresh() : void 0,
1534
1554
  children: [/* @__PURE__ */ jsx(RefreshIcon, { className: "h-4 w-4" }), t.empty.tryAgain]
@@ -1566,6 +1586,7 @@ function SkeletonPreview() {
1566
1586
  function DragDropZone({ onDropFiles, children, className = "" }) {
1567
1587
  const [isDragging, setIsDragging] = useState(false);
1568
1588
  return /* @__PURE__ */ jsx("div", {
1589
+ role: "none",
1569
1590
  className: cx("transition-[box-shadow,background-color] duration-150", className, isDragging && "ring-1 ring-(--theme-link) ring-inset bg-(--theme-link)/5"),
1570
1591
  onDragOver: (e) => {
1571
1592
  e.preventDefault();
@@ -1585,6 +1606,7 @@ function ShareFileButton({ node, onShare }) {
1585
1606
  const t = useStrings().fileExplorer;
1586
1607
  const [isPending, startTransition] = useTransition();
1587
1608
  return /* @__PURE__ */ jsxs("button", {
1609
+ type: "button",
1588
1610
  "aria-label": t.preview.shareFile,
1589
1611
  className: "btn btn-info cursor-pointer flex items-center justify-between",
1590
1612
  onClick: () => {
@@ -2515,7 +2537,7 @@ function useObjectText(url, { enabled, maxBytes, maxLines, knownSize, cacheKey,
2515
2537
  }
2516
2538
  //#endregion
2517
2539
  //#region src/file-explorer/FilePreview/Viewer.tsx
2518
- var CodePreviewEditor = lazy(() => import("../chunks/CodePreviewEditor-hwjZof0M.js"));
2540
+ var CodePreviewEditor = lazy(() => import("../chunks/CodePreviewEditor-67A_SKgE.js"));
2519
2541
  var PREVIEW_MARKDOWN_CONTROLS = {
2520
2542
  table: { fullscreen: false },
2521
2543
  mermaid: { fullscreen: false }
@@ -3195,13 +3217,16 @@ function FilePreview({ open, node, siblings, storage, getPresignedUrl, onNavigat
3195
3217
  }, node.path)
3196
3218
  });
3197
3219
  return createPortal(/* @__PURE__ */ jsxs("div", {
3220
+ role: "none",
3198
3221
  className: "fixed inset-0 z-9995 flex items-center justify-center",
3199
3222
  style: {
3200
3223
  backgroundColor: isOverlay ? "rgba(1,4,9,.94)" : "rgba(1,4,9,.62)",
3201
3224
  backdropFilter: isOverlay ? void 0 : "blur(3px)",
3202
3225
  WebkitBackdropFilter: isOverlay ? void 0 : "blur(3px)"
3203
3226
  },
3204
- onClick: onClose,
3227
+ onClick: (e) => {
3228
+ if (e.target === e.currentTarget) onClose();
3229
+ },
3205
3230
  children: [isOverlay && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(EdgeButton, {
3206
3231
  side: "left",
3207
3232
  label: t.preview.previousFile,
@@ -3221,7 +3246,6 @@ function FilePreview({ open, node, siblings, storage, getPresignedUrl, onNavigat
3221
3246
  width: "min(1120px, 94vw)",
3222
3247
  height: "min(780px, 90vh)"
3223
3248
  },
3224
- onClick: (e) => e.stopPropagation(),
3225
3249
  children: [
3226
3250
  topBar,
3227
3251
  stage,
@@ -3581,7 +3605,7 @@ function FileRowsWindow({ items, padTop, padBottom, nodes, checkedItems, activeI
3581
3605
  ] });
3582
3606
  }
3583
3607
  function Spacer({ height }) {
3584
- return /* @__PURE__ */ jsx("tr", {
3608
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("tr", {
3585
3609
  "aria-hidden": "true",
3586
3610
  className: "border-0",
3587
3611
  children: /* @__PURE__ */ jsx("td", {
@@ -3591,7 +3615,7 @@ function Spacer({ height }) {
3591
3615
  padding: 0
3592
3616
  }
3593
3617
  })
3594
- });
3618
+ }) });
3595
3619
  }
3596
3620
  /** A nested overflow container stealing the scroll leaves the virtualizer at
3597
3621
  * scrollTop 0 forever, rendering only the first window. */
@@ -4627,7 +4651,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
4627
4651
  };
4628
4652
  const handleDownload = async () => {
4629
4653
  let filesToDownload = [];
4630
- if (checkedItems.size > 0) filesToDownload = Array.from(checkedItems).map((path) => treeMap[path]).filter((node) => node && node.type === "file");
4654
+ if (checkedItems.size > 0) filesToDownload = Array.from(checkedItems).map((path) => treeMap[path]).filter((node) => !!node && node.type === "file");
4631
4655
  else if (selectedNode && selectedNode.type === "file") filesToDownload = [selectedNode];
4632
4656
  if (filesToDownload.length === 0) {
4633
4657
  notify.error(t.messages.noFilesForDownload);
@@ -4641,7 +4665,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
4641
4665
  return;
4642
4666
  }
4643
4667
  for (const [index, node] of filesToDownload.entries()) {
4644
- const input = provider.getFileInput(node.storageName ?? "", node);
4668
+ const input = provider.getFileInput(node.storageName ?? "", node, void 0, node.name);
4645
4669
  const [presignedUrl, error] = await client.getFile(input);
4646
4670
  if (error || !presignedUrl) {
4647
4671
  notify.error(error?.message ?? t.messages.downloadLinkFailed);
@@ -4679,12 +4703,12 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
4679
4703
  document.body.removeChild(a);
4680
4704
  }, 300);
4681
4705
  };
4682
- const getPresignedUrl = async (node) => {
4706
+ const getPresignedUrl = async (node, downloadFilename) => {
4683
4707
  const factory = await getStorageProviderAndClient(node.storageId);
4684
4708
  if (!factory) return [null, /* @__PURE__ */ new Error("Failed to connect to storage provider.")];
4685
4709
  const { provider, client } = factory;
4686
4710
  if (!provider?.getFileInput) return [null, /* @__PURE__ */ new Error("Preview is not supported for this storage.")];
4687
- const input = provider.getFileInput(node.storageName ?? "", node, PREVIEW_URL_EXPIRES_IN);
4711
+ const input = provider.getFileInput(node.storageName ?? "", node, PREVIEW_URL_EXPIRES_IN, downloadFilename);
4688
4712
  return client.getFile(input);
4689
4713
  };
4690
4714
  const previewSiblings = useMemo(() => previewNode ? getNodeChildren(parentToChildrenMap, getParentPath(previewNode.path)).filter((n) => n.type === "file") : [], [previewNode, parentToChildrenMap]);
@@ -4723,7 +4747,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
4723
4747
  }
4724
4748
  };
4725
4749
  const downloadNode = async (node) => {
4726
- const [presignedUrl, error] = await getPresignedUrl(node);
4750
+ const [presignedUrl, error] = await getPresignedUrl(node, node.name);
4727
4751
  if (error || !presignedUrl) {
4728
4752
  notify.error(error?.message ?? t.messages.downloadLinkFailed);
4729
4753
  return;
@@ -4851,7 +4875,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
4851
4875
  };
4852
4876
  const generateDownloadCommand = () => {
4853
4877
  let filesToDownload = [];
4854
- if (checkedItems.size > 0) filesToDownload = Array.from(checkedItems).map((path) => treeMap[path]).filter((node) => node && node.type === "file");
4878
+ if (checkedItems.size > 0) filesToDownload = Array.from(checkedItems).map((path) => treeMap[path]).filter((node) => !!node && node.type === "file");
4855
4879
  else if (selectedNode && selectedNode.type === "file") filesToDownload = [selectedNode];
4856
4880
  if (filesToDownload.length === 0) return "";
4857
4881
  const commands = filesToDownload.map((node) => {
@@ -4868,7 +4892,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
4868
4892
  return;
4869
4893
  }
4870
4894
  let nodesToDelete = [];
4871
- if (checkedItems.size > 0) nodesToDelete = Array.from(checkedItems).map((path) => treeMap[path]).filter(Boolean);
4895
+ if (checkedItems.size > 0) nodesToDelete = Array.from(checkedItems).map((path) => treeMap[path]).filter((node) => Boolean(node));
4872
4896
  else if (selectedNode) nodesToDelete = [selectedNode];
4873
4897
  setPendingDelete(pruneNodesInsideSelectedDirectories(nodesToDelete));
4874
4898
  setDeleteModalOpen(true);
@@ -5089,6 +5113,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
5089
5113
  children: /* @__PURE__ */ jsxs("div", {
5090
5114
  className: "flex gap-x-0.5",
5091
5115
  children: [/* @__PURE__ */ jsx("button", {
5116
+ type: "button",
5092
5117
  "aria-label": t.chrome.refresh,
5093
5118
  "data-tooltip-id": TOOLTIP_ID,
5094
5119
  "data-tooltip-content": "Refresh",
@@ -5097,6 +5122,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
5097
5122
  onClick: () => handleRefresh(),
5098
5123
  children: /* @__PURE__ */ jsx(RefreshIcon, { className: "h-3.5 w-3.5" })
5099
5124
  }), /* @__PURE__ */ jsx("button", {
5125
+ type: "button",
5100
5126
  "aria-label": t.chrome.collapse,
5101
5127
  "data-tooltip-id": TOOLTIP_ID,
5102
5128
  "data-tooltip-content": "Collapse All",
@@ -5236,10 +5262,12 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
5236
5262
  anchor: "bottom end",
5237
5263
  className: "theme-panel w-36 rounded-md border p-1 mt-1 shadow-lg z-50 origin-top-right transition duration-100\n ease-out data-closed:scale-95 data-closed:opacity-0 focus:outline-none",
5238
5264
  children: [/* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsx("button", {
5265
+ type: "button",
5239
5266
  className: "text-sm rounded-sm hover:theme-hover cursor-pointer w-full items-center px-2 py-1.5",
5240
5267
  onClick: () => fileInputRef.current?.click(),
5241
5268
  children: "Select Files"
5242
5269
  }) }), /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsx("button", {
5270
+ type: "button",
5243
5271
  className: "text-sm rounded-sm hover:theme-hover cursor-pointer w-full items-center px-2 py-1.5",
5244
5272
  onClick: () => folderInputRef.current?.click(),
5245
5273
  children: "Select Folder"
@@ -5258,6 +5286,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
5258
5286
  anchor: "bottom end",
5259
5287
  className: "theme-panel w-72 rounded-md border p-1 mt-1 shadow-lg z-50 origin-top-right transition duration-100 \n ease-out data-closed:scale-95 data-closed:opacity-0 focus:outline-none",
5260
5288
  children: [/* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsx("button", {
5289
+ type: "button",
5261
5290
  className: "text-sm rounded-sm hover:theme-hover cursor-pointer w-full items-center px-2 py-1.5",
5262
5291
  onClick: handleDownload,
5263
5292
  children: "From browser"
@@ -5279,6 +5308,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
5279
5308
  })()] }) })] })]
5280
5309
  })] }),
5281
5310
  /* @__PURE__ */ jsxs("button", {
5311
+ type: "button",
5282
5312
  "aria-label": t.chrome.access,
5283
5313
  className: "btn btn-info cursor-pointer flex items-center justify-center",
5284
5314
  disabled: !selectedNode.storageId,
@@ -5290,6 +5320,7 @@ function FileExplorer({ storages, onRefresh, showUserHierarchy = false, groups =
5290
5320
  })]
5291
5321
  }),
5292
5322
  selectedNodeCanWrite && /* @__PURE__ */ jsxs("button", {
5323
+ type: "button",
5293
5324
  "aria-label": t.chrome.delete,
5294
5325
  className: "btn btn-destructive cursor-pointer flex items-center justify-center",
5295
5326
  disabled: checkedItems.size === 0 && selectedNode.type !== "file" || !selectedNode.storageId,
@@ -5641,4 +5672,4 @@ async function mapWithConcurrency(items, limit, worker) {
5641
5672
  return results;
5642
5673
  }
5643
5674
  //#endregion
5644
- export { CorsError, FileExplorer, FileExplorerProvider, LIST_PAGE_SIZE, NoDataAvailablePreview, SkeletonPreview, chunk, collectObjectKeysToDelete, getObjectKeyFromNode, isClientValid, mapWithConcurrency, paginate, removeLeadingAndTrailingSlashes, useFileExplorer };
5675
+ export { CorsError, FileExplorer, FileExplorerProvider, LIST_PAGE_SIZE, NoDataAvailablePreview, SkeletonPreview, attachmentDisposition, chunk, collectObjectKeysToDelete, getObjectKeyFromNode, isClientValid, mapWithConcurrency, paginate, removeLeadingAndTrailingSlashes, useFileExplorer };
@@ -5,7 +5,7 @@ export type FileExplorerGetFileResult = [string | null, Error | null];
5
5
  /** The UI only checks Errors?.length; each provider's richer error entries
6
6
  * satisfy this structurally. */
7
7
  export interface FileExplorerDeleteFilesResult {
8
- Errors?: unknown[];
8
+ Errors?: unknown[] | undefined;
9
9
  }
10
10
  export interface IFileExplorerClient {
11
11
  getStorageName(): string;
@@ -26,7 +26,9 @@ export interface IFileExplorerProvider {
26
26
  * the same bivariance reason as the two above. */
27
27
  nextPageCursor?(data: unknown): string | undefined;
28
28
  listDirectoryInput?: ((storage: TStorage, dir_path?: string, page?: TListPageRequest) => unknown) | null;
29
- getFileInput?: ((storageName: string, node: TreeNode, presignedUrlExpiresIn?: number) => unknown) | null;
29
+ /** `downloadFilename` asks for a URL that saves under that name. Omit it for a
30
+ * link the user keeps, or for a read the app parses itself. */
31
+ getFileInput?: ((storageName: string, node: TreeNode, presignedUrlExpiresIn?: number, downloadFilename?: string) => unknown) | null;
30
32
  deleteFilesInput?: ((storageName: string, nodes: TreeNode[]) => unknown) | null;
31
33
  uploadFileInput?: ((storageName: string, objectPath: string, file: File | Blob) => unknown) | null;
32
34
  }
@@ -22,31 +22,31 @@ export type TStorageObject = {
22
22
  path: string;
23
23
  type: 'file' | 'directory';
24
24
  key?: string;
25
- size?: number;
26
- created?: string;
27
- modified?: string;
28
- contentType?: string;
29
- hash?: string;
30
- storageClass?: string;
25
+ size?: number | undefined;
26
+ created?: string | undefined;
27
+ modified?: string | undefined;
28
+ contentType?: string | undefined;
29
+ hash?: string | undefined;
30
+ storageClass?: string | undefined;
31
31
  };
32
32
  export type TreeNode = {
33
33
  name: string;
34
- displayName?: string;
34
+ displayName?: string | undefined;
35
35
  path: string;
36
- relativePath?: string;
36
+ relativePath?: string | undefined;
37
37
  type: 'file' | 'directory';
38
- size?: number;
39
- created?: string;
40
- modified?: string;
41
- contentType?: string;
42
- hash?: string;
43
- storageClass?: string;
44
- storageId?: string;
45
- storageName?: string;
46
- storageNodeIcon?: string;
47
- storageImageUrl?: string;
48
- storageType?: string;
49
- root?: boolean;
38
+ size?: number | undefined;
39
+ created?: string | undefined;
40
+ modified?: string | undefined;
41
+ contentType?: string | undefined;
42
+ hash?: string | undefined;
43
+ storageClass?: string | undefined;
44
+ storageId?: string | undefined;
45
+ storageName?: string | undefined;
46
+ storageNodeIcon?: string | undefined;
47
+ storageImageUrl?: string | undefined;
48
+ storageType?: string | undefined;
49
+ root?: boolean | undefined;
50
50
  };
51
51
  export type TreeMap = {
52
52
  [path: string]: TreeNode;
@@ -83,7 +83,7 @@ export interface UploadSession {
83
83
  totalLoadedBytes?: number;
84
84
  lastProgressTime?: number;
85
85
  lastProgressBytes?: number;
86
- estimatedSecondsLeft?: number;
86
+ estimatedSecondsLeft?: number | undefined;
87
87
  };
88
88
  toastId: string;
89
89
  abortController?: AbortController;
@@ -20,6 +20,7 @@ export declare function getUploadNodesFromDataTransferItems(items: DataTransferI
20
20
  }>;
21
21
  export declare function calculateUploadNodesTotalSize(uploadNodes: UploadNode[]): number;
22
22
  export declare function getObjectKeyFromNode(node: TreeNode): string;
23
+ export declare function attachmentDisposition(filename: string): string;
23
24
  export declare function getDirectoryPrefixFromNode(node: TreeNode): string;
24
25
  export declare function pruneNodesInsideSelectedDirectories(nodes: TreeNode[]): TreeNode[];
25
26
  export declare function collectObjectKeysToDelete(nodes: TreeNode[], listKeysUnderPrefix: (prefix: string) => Promise<string[]>): Promise<string[]>;
@@ -1,4 +1,9 @@
1
1
  import type React from 'react';
2
+ export interface FieldLabelBinding {
3
+ id: string;
4
+ labelId: string;
5
+ describedBy: string | undefined;
6
+ }
2
7
  export declare function FieldWrapper({ label, tooltipComponent, description, labelPosition, spaceCompact, optional, children, }: {
3
8
  label: string;
4
9
  tooltipComponent?: React.ReactNode;
@@ -6,5 +11,5 @@ export declare function FieldWrapper({ label, tooltipComponent, description, lab
6
11
  labelPosition?: 'left' | 'top' | undefined;
7
12
  spaceCompact?: boolean | undefined;
8
13
  optional?: boolean | undefined;
9
- children: React.ReactNode;
14
+ children: React.ReactNode | ((binding: FieldLabelBinding) => React.ReactNode);
10
15
  }): React.JSX.Element;
@@ -1,7 +1,7 @@
1
1
  import { StatusDot } from '../../components/StatusBadge.js';
2
2
  import type { ComponentProps } from 'react';
3
3
  interface ResourceOptionIconProps {
4
- imageUrl?: string;
4
+ imageUrl?: string | undefined;
5
5
  fallbackIcon: string;
6
6
  alt: string;
7
7
  variant?: ComponentProps<typeof StatusDot>['variant'];
@@ -1,3 +1,3 @@
1
1
  /** Not directly rendered — wizard container handles step fields; this stub satisfies the registry. */
2
2
  import type { FieldComponentProps } from '../types/fieldComponentTypes.js';
3
- export default function StepField(_props: FieldComponentProps<any>): null;
3
+ export default function StepField(_props: FieldComponentProps): null;
@@ -2,23 +2,24 @@ import { type FormikProps, type FormikValues } from 'formik';
2
2
  import { type WorkflowVariables } from '@parallelworks/workflow-parser';
3
3
  import React, { type SetStateAction } from 'react';
4
4
  import { type FieldComponent } from './fieldRegistry.js';
5
+ interface FormMeta {
6
+ labelPosition?: 'left' | 'top' | undefined;
7
+ spaceCompact?: boolean | undefined;
8
+ }
5
9
  /** Applies `$meta` overrides for `labelPosition` / `spaceCompact`. */
6
10
  export declare function resolveMetaOverrides(options: {
7
- $meta?: {
8
- labelPosition?: 'left' | 'top';
9
- spaceCompact?: boolean;
10
- };
11
- } | undefined, labelPosition: 'left' | 'top' | undefined, spaceCompact: boolean): {
11
+ $meta?: FormMeta;
12
+ } | Record<string, unknown> | undefined, labelPosition: 'left' | 'top' | undefined, spaceCompact: boolean): {
12
13
  labelPosition: "left" | "top" | undefined;
13
14
  spaceCompact: boolean;
14
15
  };
15
16
  /** Collects every field with a `default` for the form-level sync to track. */
16
- export declare function collectFieldsWithDefaults(options: Record<string, any>, values?: Record<string, any>, prefix?: string): Array<{
17
+ export declare function collectFieldsWithDefaults(options: Record<string, unknown>, values?: Record<string, unknown>, prefix?: string): Array<{
17
18
  name: string;
18
- defaultValue: any;
19
+ defaultValue: unknown;
19
20
  }>;
20
21
  export declare function defaultReferencesField(defaultValue: unknown, fieldPath: string): boolean;
21
- export declare function findSelfReferencingFieldNames(schema: Record<string, any>, values?: Record<string, any>): string[];
22
+ export declare function findSelfReferencingFieldNames(schema: Record<string, unknown>, values?: Record<string, unknown>): string[];
22
23
  /**
23
24
  * Re-syncs each field's value when its resolved default changes between
24
25
  * renders, unless `meta.touched` (this session) or a synth-touched marker
@@ -26,7 +27,7 @@ export declare function findSelfReferencingFieldNames(schema: Record<string, any
26
27
  * remounted via `key` when the run/config context changes.
27
28
  */
28
29
  export declare function DynamicDefaultsSync({ options, }: {
29
- options: Record<string, any>;
30
+ options: Record<string, unknown>;
30
31
  }): null;
31
32
  export declare function GroupHeader({ children, open, setOpen, title, }: {
32
33
  children?: React.ReactNode;
@@ -59,48 +60,48 @@ export declare function MultiSelectionDropdown({ name, label, invalid, options:
59
60
  options?: {
60
61
  label: string;
61
62
  secondaryLabel?: string;
62
- value: any;
63
+ value: string;
63
64
  selected: boolean;
64
65
  }[];
65
66
  setFormDirty: TSetFormDirty;
66
- onChange?: (val: any) => void;
67
- parentValue?: any;
67
+ onChange?: ((val: unknown) => void) | undefined;
68
+ parentValue?: unknown;
68
69
  className?: string;
69
- secondaryField?: string;
70
+ secondaryField?: string | undefined;
70
71
  }): React.JSX.Element;
71
72
  export declare function FieldsFromOptions({ options, values, setFormDirty, setFieldValue, setFieldTouched, parentInfo, labelPosition, missingFields, spaceCompact, workflowForm, }: {
72
- options: Record<string, any>;
73
- values: Record<string, any>;
73
+ options: Record<string, unknown>;
74
+ values: Record<string, unknown>;
74
75
  setFormDirty: TSetFormDirty;
75
- setFieldValue: (field: string, value: any, shouldValidate?: boolean) => void;
76
+ setFieldValue: (field: string, value: unknown, shouldValidate?: boolean) => void;
76
77
  setFieldTouched: (field: string, touched?: boolean, shouldValidate?: boolean) => void;
77
78
  /** If fields are part of other field, this is the info needed*/
78
79
  parentInfo?: {
79
- computeOn?: boolean;
80
+ computeOn?: boolean | undefined;
80
81
  parentName: string;
81
82
  fieldNamePrefix: string;
82
- arrayIndex?: number;
83
+ arrayIndex?: number | undefined;
83
84
  onChange?: (fieldName: string, index: number, changeOtherValuesTo?: string | boolean, keepOneValueOf?: string | boolean, currentValue?: string | boolean) => void;
84
- };
85
- labelPosition?: 'left' | 'top';
85
+ } | undefined;
86
+ labelPosition?: 'left' | 'top' | undefined;
86
87
  missingFields?: string[];
87
88
  spaceCompact?: boolean;
88
89
  /** Prevents deletion of hidden+ignored field values (workflow forms filter at submit time) */
89
- workflowForm?: boolean;
90
+ workflowForm?: boolean | undefined;
90
91
  }): React.JSX.Element[];
91
92
  export interface DynamicFormProps {
92
- formJSONs: Record<string, any>;
93
+ formJSONs: Record<string, unknown>;
93
94
  reinitialize?: boolean;
94
95
  setFormDirty?: (dirty: boolean) => void;
95
- initialValues: Record<string, any>;
96
- setValues?: (values: Record<string, any>) => void;
96
+ initialValues: object;
97
+ setValues?: (values: Record<string, unknown>) => void;
97
98
  formikRef?: React.RefObject<FormikProps<FormikValues> | null>;
98
99
  labelPosition?: 'left' | 'top';
99
- missingFields?: string[];
100
+ missingFields?: string[] | undefined;
100
101
  spaceCompact?: boolean;
101
- organizationVariables?: WorkflowVariables;
102
+ organizationVariables?: WorkflowVariables | undefined;
102
103
  needsOrganizationVariables?: boolean;
103
- onSubmit?: (values: Record<string, any>) => void;
104
+ onSubmit?: ((values: Record<string, unknown>) => void) | undefined;
104
105
  submitLabel?: string;
105
106
  className?: string;
106
107
  /** Prevents deletion of hidden+ignored field values (workflow forms filter at submit time).
@@ -1,12 +1,25 @@
1
1
  import FormikCustomDropdown from './FormikCustomDropdown.js';
2
2
  export default function DropdownWrapper({ options, onChange, fieldObj, setFormDirty, invalid, loading, disabled, allowCustomValue, currentValue, setFieldValue, setFieldTouched, }: {
3
3
  options: React.ComponentProps<typeof FormikCustomDropdown>['options'];
4
- onChange?: (val: string) => void;
5
- fieldObj: any;
4
+ onChange?: ((val: string) => void) | undefined;
5
+ fieldObj: {
6
+ name?: string | undefined;
7
+ label?: string | undefined;
8
+ disabled?: boolean | string | undefined;
9
+ placeholder?: string | undefined;
10
+ default?: unknown;
11
+ parentValue?: unknown;
12
+ secondaryField?: string | string[] | undefined;
13
+ resetOnChange?: string | boolean | undefined;
14
+ value?: string | undefined;
15
+ autoselect?: boolean | string | Record<string, unknown> | undefined;
16
+ allowCustomValue?: boolean | undefined;
17
+ customValueLabel?: string | undefined;
18
+ };
6
19
  setFormDirty: React.ComponentProps<typeof FormikCustomDropdown>['setFormDirty'];
7
20
  invalid?: boolean;
8
21
  loading?: boolean;
9
- disabled?: boolean;
22
+ disabled?: boolean | undefined;
10
23
  allowCustomValue?: boolean;
11
24
  currentValue: unknown;
12
25
  setFieldValue: React.ComponentProps<typeof FormikCustomDropdown>['setFieldValue'];
@@ -17,8 +17,8 @@ declare function toComparableOptions(options: React.ComponentProps<typeof Dropdo
17
17
  value: unknown;
18
18
  disabled: boolean | undefined;
19
19
  } | {
20
- category?: undefined;
21
- options?: undefined;
20
+ category?: never;
21
+ options?: never;
22
22
  label: string;
23
23
  value: unknown;
24
24
  disabled: boolean | undefined;
@@ -26,21 +26,21 @@ declare function toComparableOptions(options: React.ComponentProps<typeof Dropdo
26
26
  })[] | undefined;
27
27
  type FormikCustomDropdownProps = {
28
28
  name: string;
29
- ariaLabel?: string;
29
+ ariaLabel?: string | undefined;
30
30
  options: React.ComponentProps<typeof Dropdown>['options'];
31
31
  setFormDirty: TSetFormDirty;
32
- onChange?: (val: string) => void;
33
- parentValue?: any;
32
+ onChange?: ((val: string) => void) | undefined;
33
+ parentValue?: unknown;
34
34
  className?: string;
35
- secondaryField?: string | string[];
35
+ secondaryField?: string | string[] | undefined;
36
36
  disabled?: boolean;
37
- resetOnChange?: string;
37
+ resetOnChange?: string | boolean | undefined;
38
38
  loading?: boolean;
39
39
  invalid?: boolean;
40
- autoselect?: boolean;
41
- value?: string;
42
- allowCustomValue?: boolean;
43
- customValueLabel?: string;
40
+ autoselect?: boolean | undefined;
41
+ value?: string | undefined;
42
+ allowCustomValue?: boolean | undefined;
43
+ customValueLabel?: string | undefined;
44
44
  placeholder?: string;
45
45
  currentValue: unknown;
46
46
  setFieldValue: (field: string, value: unknown, shouldValidate?: boolean) => void;