@parallelworks/ui 0.2.0 → 0.3.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 (61) hide show
  1. package/dist/chunks/CodePreviewEditor-CSPRILMp.js +61 -0
  2. package/dist/chunks/Indicator-hBSIxOPK.js +39 -0
  3. package/dist/chunks/Markdown-C5Re2ezs.js +101 -0
  4. package/dist/chunks/{Indicator-fF8AVbjQ.js → Modal-sOUEwebV.js} +1 -38
  5. package/dist/chunks/{Monaco-CP_cL9gp.js → Monaco-CC4ak1JG.js} +3 -31
  6. package/dist/chunks/Provider-DvVvScTQ.js +391 -0
  7. package/dist/chunks/StatusBadge-DXp4zkSd.js +46 -0
  8. package/dist/chunks/{Table-DWuRINhu.js → SwitchToggle-2uRw8ZeJ.js} +2 -132
  9. package/dist/chunks/Table-C5z6qWjM.js +91 -0
  10. package/dist/chunks/editor-D55tumuZ.js +372 -0
  11. package/dist/chunks/list-7PyDF1tz.js +465 -0
  12. package/dist/components/Provider.d.ts +293 -0
  13. package/dist/editor/index.d.ts +1 -0
  14. package/dist/editor/index.js +2 -219
  15. package/dist/editor/useCssIsDark.d.ts +6 -0
  16. package/dist/file-explorer/FileExplorer.d.ts +23 -0
  17. package/dist/file-explorer/FileExplorerContext.d.ts +17 -0
  18. package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +6 -0
  19. package/dist/file-explorer/FilePreview/Inline.d.ts +13 -0
  20. package/dist/file-explorer/FilePreview/StreamedBadge.d.ts +1 -0
  21. package/dist/file-explorer/FilePreview/Viewer.d.ts +15 -0
  22. package/dist/file-explorer/FilePreview/index.d.ts +15 -0
  23. package/dist/file-explorer/FilePreview/parse.d.ts +24 -0
  24. package/dist/file-explorer/FilePreview/previewCache.d.ts +26 -0
  25. package/dist/file-explorer/FilePreview/previewType.d.ts +21 -0
  26. package/dist/file-explorer/FilePreview/readCappedBytes.d.ts +37 -0
  27. package/dist/file-explorer/FilePreview/useObjectBlobUrl.d.ts +16 -0
  28. package/dist/file-explorer/FilePreview/useObjectText.d.ts +23 -0
  29. package/dist/file-explorer/FilePreview/usePresignedUrl.d.ts +12 -0
  30. package/dist/file-explorer/FileRow.d.ts +35 -0
  31. package/dist/file-explorer/FileRowsWindow.d.ts +43 -0
  32. package/dist/file-explorer/FileTable.d.ts +26 -0
  33. package/dist/file-explorer/FileTableHeaders.d.ts +13 -0
  34. package/dist/file-explorer/LoadMoreRow.d.ts +15 -0
  35. package/dist/file-explorer/TreeView.d.ts +28 -0
  36. package/dist/file-explorer/helpers.d.ts +47 -0
  37. package/dist/file-explorer/index.d.ts +10 -0
  38. package/dist/file-explorer/index.js +5646 -0
  39. package/dist/file-explorer/lib/batch.d.ts +3 -0
  40. package/dist/file-explorer/lib/errors.d.ts +3 -0
  41. package/dist/file-explorer/lib/fileExplorer.d.ts +32 -0
  42. package/dist/file-explorer/lib/paging.d.ts +93 -0
  43. package/dist/file-explorer/lib/types.d.ts +92 -0
  44. package/dist/file-explorer/lib/utils.d.ts +37 -0
  45. package/dist/file-explorer/toasts.d.ts +9 -0
  46. package/dist/file-explorer/treeRows.d.ts +35 -0
  47. package/dist/file-explorer/useNearEnd.d.ts +7 -0
  48. package/dist/form/index.js +4 -2
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.js +9 -101
  51. package/dist/list/ListTable.d.ts +63 -0
  52. package/dist/list/RowContextMenu.d.ts +113 -0
  53. package/dist/list/index.d.ts +2 -0
  54. package/dist/list/index.js +2 -0
  55. package/dist/logviewer/index.js +1 -1
  56. package/dist/styles/theme.css +30 -0
  57. package/dist/styles.css +1 -1
  58. package/dist/workflow/index.js +3 -2
  59. package/package.json +12 -1
  60. package/dist/chunks/Provider-C2VtPnh5.js +0 -151
  61. package/dist/chunks/workers-Cjfjb8E7.js +0 -119
@@ -0,0 +1,61 @@
1
+ import { i as getThemeName, n as setupMonacoWorkers, r as defineEditorThemes, t as useCssIsDark } from "./editor-D55tumuZ.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useRef } from "react";
4
+ import * as monaco from "monaco-editor";
5
+ //#region src/file-explorer/FilePreview/CodePreviewEditor.tsx
6
+ var OPTIONS = {
7
+ readOnly: true,
8
+ domReadOnly: true,
9
+ automaticLayout: true,
10
+ minimap: { enabled: false },
11
+ scrollBeyondLastLine: false,
12
+ renderLineHighlight: "none",
13
+ overviewRulerLanes: 0,
14
+ hideCursorInOverviewRuler: true,
15
+ lineNumbers: "on",
16
+ wordWrap: "off",
17
+ fontSize: 12,
18
+ scrollbar: { alwaysConsumeMouseWheel: false }
19
+ };
20
+ setupMonacoWorkers();
21
+ function CodePreviewEditor({ value, language }) {
22
+ const isDark = useCssIsDark();
23
+ const editorRef = useRef(null);
24
+ useEffect(() => {
25
+ return () => {
26
+ editorRef.current?.getModel()?.dispose();
27
+ editorRef.current?.dispose();
28
+ editorRef.current = null;
29
+ };
30
+ }, []);
31
+ useEffect(() => {
32
+ const model = editorRef.current?.getModel();
33
+ if (model && model.getValue() !== value) model.setValue(value);
34
+ }, [value]);
35
+ useEffect(() => {
36
+ const model = editorRef.current?.getModel();
37
+ if (model) monaco.editor.setModelLanguage(model, language);
38
+ }, [language]);
39
+ useEffect(() => {
40
+ if (editorRef.current) {
41
+ defineEditorThemes(monaco.editor);
42
+ monaco.editor.setTheme(getThemeName(isDark));
43
+ }
44
+ }, [isDark]);
45
+ return /* @__PURE__ */ jsx("div", {
46
+ className: "h-full w-full",
47
+ ref: (container) => {
48
+ if (container && !editorRef.current) {
49
+ defineEditorThemes(monaco.editor);
50
+ const model = monaco.editor.createModel(value, language);
51
+ editorRef.current = monaco.editor.create(container, {
52
+ ...OPTIONS,
53
+ model
54
+ });
55
+ monaco.editor.setTheme(getThemeName(isDark));
56
+ }
57
+ }
58
+ });
59
+ }
60
+ //#endregion
61
+ export { CodePreviewEditor as default };
@@ -0,0 +1,39 @@
1
+ import { CancelIcon, FailIcon, NotRunningIcon, RunningIcon, SkipIcon, SuccessIcon } from "../icons.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/Indicator.tsx
4
+ function Indicator({ status }) {
5
+ return /* @__PURE__ */ jsx("div", {
6
+ className: "h-2 flex items-center text-(--theme-panel-bg)",
7
+ children: status === "started" || status === "running" ? /* @__PURE__ */ jsx(RunningIcon, {
8
+ className: "rounded-full text-[#FFCF00] animate-spin",
9
+ "data-testid": "running-indicator"
10
+ }) : status === "completed" ? /* @__PURE__ */ jsx(SuccessIcon, {
11
+ className: "text-[#6FBF5A]",
12
+ style: { transform: "scale(1.25)" },
13
+ "data-testid": "completed-indicator"
14
+ }) : status === "failed" || status === "error" ? /* @__PURE__ */ jsx(FailIcon, {
15
+ className: "text-red-500",
16
+ style: { transform: "scale(1.25)" },
17
+ "data-testid": "failed-indicator"
18
+ }) : status === "skipped" || status === "skipped-failed" ? /* @__PURE__ */ jsx(SkipIcon, {
19
+ className: "text-gray-400",
20
+ style: { transform: "scale(1.25)" },
21
+ "data-testid": "skipped-indicator"
22
+ }) : status === "canceled" ? /* @__PURE__ */ jsx(CancelIcon, {
23
+ className: "text-[#3B82F6]",
24
+ style: { transform: "scale(1.5)" },
25
+ "data-testid": "canceled-indicator"
26
+ }) : status === "faulted" ? /* @__PURE__ */ jsx(RunningIcon, {
27
+ className: "rounded-full text-[#EF4444] animate-spin",
28
+ "data-testid": "faulted-indicator"
29
+ }) : status === "canceling" ? /* @__PURE__ */ jsx(RunningIcon, {
30
+ className: "rounded-full text-[#3B82F6] animate-spin",
31
+ "data-testid": "canceling-indicator"
32
+ }) : /* @__PURE__ */ jsx(NotRunningIcon, {
33
+ className: "rounded-full text-[#AAAAAA]",
34
+ "data-testid": "not-running-indicator"
35
+ })
36
+ });
37
+ }
38
+ //#endregion
39
+ export { Indicator as t };
@@ -0,0 +1,101 @@
1
+ import { AlertIcon, CheckIcon, ClipboardIcon, CopyIcon, HiddenFalseIcon, HiddenTrueIcon, InfoIcon } from "../icons.js";
2
+ import { i as useNotify } from "./Provider-DvVvScTQ.js";
3
+ import cx from "classnames";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Suspense, lazy, useState } from "react";
6
+ //#region src/components/Callout.tsx
7
+ function CalloutIcon({ type }) {
8
+ if (type === "warning" || type === "error") return /* @__PURE__ */ jsx(AlertIcon, { className: "h-6 w-6 mr-4 text-lg" });
9
+ else return /* @__PURE__ */ jsx(InfoIcon, { className: "h-6 w-6 mr-4 text-lg" });
10
+ }
11
+ function Callout({ type, className = "", children }) {
12
+ return /* @__PURE__ */ jsx("div", {
13
+ className: cx(className, type === "warning" && "bg-orange-100 border-orange-500 text-orange-700", type === "error" && "bg-red-100 border-red-500 text-red-700", type === "info" && "bg-blue-100 border-blue-500 text-blue-700", "border-t-4 rounded-b px-4 py-3 shadow-md my-4"),
14
+ role: "alert",
15
+ children: /* @__PURE__ */ jsxs("div", {
16
+ className: "flex",
17
+ children: [/* @__PURE__ */ jsx("div", {
18
+ className: "py-1",
19
+ children: /* @__PURE__ */ jsx(CalloutIcon, { type })
20
+ }), /* @__PURE__ */ jsx("div", { children })]
21
+ })
22
+ });
23
+ }
24
+ //#endregion
25
+ //#region src/components/CopyToClipboard.tsx
26
+ function CopyToClipboard({ as = "div", text, className, children, showIcon = true }) {
27
+ const notify = useNotify();
28
+ const handleCopy = async () => {
29
+ try {
30
+ await navigator.clipboard.writeText(text);
31
+ notify.info("Copied to clipboard");
32
+ } catch {
33
+ notify.error("Failed to copy to clipboard");
34
+ }
35
+ };
36
+ return /* @__PURE__ */ jsxs(as, {
37
+ className,
38
+ onClick: handleCopy,
39
+ ...as === "button" ? { type: "button" } : {},
40
+ children: [showIcon && /* @__PURE__ */ jsx(ClipboardIcon, {}), children]
41
+ });
42
+ }
43
+ function CopyCodeBlock({ textToCopy, children, secret = false, isRevealed = false, onRevealToggle }) {
44
+ const notify = useNotify();
45
+ const [copied, setCopied] = useState(false);
46
+ const handleCopy = async () => {
47
+ if (copied) return;
48
+ try {
49
+ await navigator.clipboard.writeText(textToCopy);
50
+ setCopied(true);
51
+ notify.info("Copied to clipboard");
52
+ setTimeout(() => setCopied(false), 2e3);
53
+ } catch {
54
+ notify.error("Failed to copy to clipboard");
55
+ }
56
+ };
57
+ return /* @__PURE__ */ jsxs("div", {
58
+ className: "group relative",
59
+ onClick: handleCopy,
60
+ children: [/* @__PURE__ */ jsx("pre", {
61
+ className: `p-4 theme-hover border rounded-lg text-left font-mono text-sm overflow-x-auto ${secret ? "pr-24" : "pr-12"}`,
62
+ children
63
+ }), /* @__PURE__ */ jsxs("div", {
64
+ className: "absolute top-0 right-0 bottom-0 flex items-center gap-1 pl-8 pr-2 bg-gradient-to-l from-[var(--color-panel)] from-70% to-transparent rounded-r-lg",
65
+ children: [secret && /* @__PURE__ */ jsx("button", {
66
+ type: "button",
67
+ onClick: (e) => {
68
+ e.stopPropagation();
69
+ onRevealToggle?.();
70
+ },
71
+ className: "p-2 rounded-md opacity-0 group-hover:opacity-100 transition-all duration-150",
72
+ "aria-label": isRevealed ? "Hide secret" : "Reveal secret",
73
+ title: isRevealed ? "Hide secret" : "Reveal secret",
74
+ children: isRevealed ? /* @__PURE__ */ jsx(HiddenFalseIcon, {}) : /* @__PURE__ */ jsx(HiddenTrueIcon, {})
75
+ }), /* @__PURE__ */ jsx("button", {
76
+ type: "button",
77
+ onClick: (e) => {
78
+ e.stopPropagation();
79
+ handleCopy();
80
+ },
81
+ className: "p-2 rounded-md opacity-0 group-hover:opacity-100 transition-all duration-150",
82
+ "aria-label": copied ? "Copied" : "Copy to clipboard",
83
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-green-400" }) : /* @__PURE__ */ jsx(CopyIcon, {})
84
+ })]
85
+ })]
86
+ });
87
+ }
88
+ //#endregion
89
+ //#region src/components/Markdown.tsx
90
+ var MarkdownImpl = lazy(() => import("./MarkdownImpl-Bq4QhrtA.js"));
91
+ function Markdown(props) {
92
+ return /* @__PURE__ */ jsx(Suspense, {
93
+ fallback: /* @__PURE__ */ jsx("div", {
94
+ className: "markdown whitespace-pre-wrap text-start w-full",
95
+ children: props.children
96
+ }),
97
+ children: /* @__PURE__ */ jsx(MarkdownImpl, { ...props })
98
+ });
99
+ }
100
+ //#endregion
101
+ export { Callout as i, CopyCodeBlock as n, CopyToClipboard as r, Markdown as t };
@@ -1,4 +1,3 @@
1
- import { CancelIcon, FailIcon, NotRunningIcon, RunningIcon, SkipIcon, SuccessIcon } from "../icons.js";
2
1
  import cx from "classnames";
3
2
  import { jsx, jsxs } from "react/jsx-runtime";
4
3
  import { useCallback, useEffect, useId, useRef, useState } from "react";
@@ -119,40 +118,4 @@ function Modal({ isOpen, close, cancelAction = noop, children, title = "", text
119
118
  }), document.body);
120
119
  }
121
120
  //#endregion
122
- //#region src/components/Indicator.tsx
123
- function Indicator({ status }) {
124
- return /* @__PURE__ */ jsx("div", {
125
- className: "h-2 flex items-center text-(--theme-panel-bg)",
126
- children: status === "started" || status === "running" ? /* @__PURE__ */ jsx(RunningIcon, {
127
- className: "rounded-full text-[#FFCF00] animate-spin",
128
- "data-testid": "running-indicator"
129
- }) : status === "completed" ? /* @__PURE__ */ jsx(SuccessIcon, {
130
- className: "text-[#6FBF5A]",
131
- style: { transform: "scale(1.25)" },
132
- "data-testid": "completed-indicator"
133
- }) : status === "failed" || status === "error" ? /* @__PURE__ */ jsx(FailIcon, {
134
- className: "text-red-500",
135
- style: { transform: "scale(1.25)" },
136
- "data-testid": "failed-indicator"
137
- }) : status === "skipped" || status === "skipped-failed" ? /* @__PURE__ */ jsx(SkipIcon, {
138
- className: "text-gray-400",
139
- style: { transform: "scale(1.25)" },
140
- "data-testid": "skipped-indicator"
141
- }) : status === "canceled" ? /* @__PURE__ */ jsx(CancelIcon, {
142
- className: "text-[#3B82F6]",
143
- style: { transform: "scale(1.5)" },
144
- "data-testid": "canceled-indicator"
145
- }) : status === "faulted" ? /* @__PURE__ */ jsx(RunningIcon, {
146
- className: "rounded-full text-[#EF4444] animate-spin",
147
- "data-testid": "faulted-indicator"
148
- }) : status === "canceling" ? /* @__PURE__ */ jsx(RunningIcon, {
149
- className: "rounded-full text-[#3B82F6] animate-spin",
150
- "data-testid": "canceling-indicator"
151
- }) : /* @__PURE__ */ jsx(NotRunningIcon, {
152
- className: "rounded-full text-[#AAAAAA]",
153
- "data-testid": "not-running-indicator"
154
- })
155
- });
156
- }
157
- //#endregion
158
- export { Modal as n, Indicator as t };
121
+ export { Modal as t };
@@ -1,8 +1,8 @@
1
- import { s as useWorkflowJsonResolver } from "./Provider-C2VtPnh5.js";
2
- import { n as defineEditorThemes, r as getThemeName, t as setupMonacoWorkers } from "./workers-Cjfjb8E7.js";
1
+ import { l as useWorkflowJsonResolver } from "./Provider-DvVvScTQ.js";
2
+ import { i as getThemeName, n as setupMonacoWorkers, r as defineEditorThemes, t as useCssIsDark } from "./editor-D55tumuZ.js";
3
3
  import cx from "classnames";
4
4
  import { jsx } from "react/jsx-runtime";
5
- import { useEffect, useRef, useState } from "react";
5
+ import { useEffect, useRef } from "react";
6
6
  import { dumpYaml } from "@parallelworks/workflow-parser";
7
7
  import yaml from "js-yaml";
8
8
  import * as monaco from "monaco-editor";
@@ -10,34 +10,6 @@ import { configureMonacoYaml } from "monaco-yaml";
10
10
  //#region src/editor/Monaco.tsx
11
11
  setupMonacoWorkers();
12
12
  var activeWorkflowJsonResolver;
13
- function readIsDark() {
14
- const scheme = getComputedStyle(document.documentElement).colorScheme;
15
- const dark = scheme.includes("dark");
16
- if (dark !== scheme.includes("light")) return dark;
17
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
18
- }
19
- function useCssIsDark() {
20
- const [isDark, setIsDark] = useState(readIsDark);
21
- useEffect(() => {
22
- const update = () => setIsDark(readIsDark());
23
- const media = window.matchMedia("(prefers-color-scheme: dark)");
24
- media.addEventListener("change", update);
25
- const observer = new MutationObserver(update);
26
- observer.observe(document.documentElement, {
27
- attributes: true,
28
- attributeFilter: [
29
- "style",
30
- "class",
31
- "data-theme"
32
- ]
33
- });
34
- return () => {
35
- media.removeEventListener("change", update);
36
- observer.disconnect();
37
- };
38
- }, []);
39
- return isDark;
40
- }
41
13
  var monacoWithWorkerBridge = {
42
14
  ...monaco,
43
15
  editor: {
@@ -0,0 +1,391 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext, useMemo } from "react";
3
+ //#region src/components/Provider.tsx
4
+ var DefaultLink = ({ to, onClick, className, children }) => /* @__PURE__ */ jsx("a", {
5
+ href: to,
6
+ onClick,
7
+ className,
8
+ children
9
+ });
10
+ /** The provider's link slot, with a plain anchor fallback. */
11
+ function useLink() {
12
+ return useContext(UIContext).slots.link ?? DefaultLink;
13
+ }
14
+ var defaultUseRunFile = () => ({
15
+ data: void 0,
16
+ isLoading: false,
17
+ error: void 0
18
+ });
19
+ var DEFAULTS = {
20
+ notify: {
21
+ info: () => {},
22
+ success: () => {},
23
+ warning: () => {},
24
+ error: () => {},
25
+ loading: () => "toast",
26
+ update: () => {},
27
+ dismiss: () => {}
28
+ },
29
+ strings: {
30
+ loading: "Loading…",
31
+ common: {
32
+ copy: "Copy",
33
+ copied: "Copied!",
34
+ copyFailed: "Failed to copy text to clipboard",
35
+ showHiddenFields: "Show hidden fields",
36
+ showHiddenFieldsHint: "Includes fields hidden by default because they're specific to each resource, such as name and group.",
37
+ jsonHasErrors: "JSON has errors, please fix before saving"
38
+ },
39
+ dropdown: {
40
+ select: (type) => `Select ${type}`,
41
+ noOptionsFound: "No options found"
42
+ },
43
+ logviewer: {
44
+ error: "Error:",
45
+ warning: "Warning:",
46
+ notice: "Notice:",
47
+ top: "Top",
48
+ clearSelection: "Clear selection",
49
+ copyLines: (count) => count === 1 ? "Copy 1 line" : `Copy ${count} lines`,
50
+ copyAll: "Copy All",
51
+ hideDebug: "Hide Debug",
52
+ showDebug: "Show Debug",
53
+ filterLogs: "Filter logs",
54
+ download: "Download"
55
+ },
56
+ dag: {
57
+ workflow: "Workflow",
58
+ run: "Run",
59
+ status: "Status",
60
+ runtime: "Runtime",
61
+ submitted: "Submitted",
62
+ expandAll: "Expand all",
63
+ collapseAll: "Collapse all",
64
+ statusLabel: (status) => status,
65
+ statusReason: () => void 0
66
+ },
67
+ jobActions: {
68
+ openSubworkflowLogs: "Open subworkflow logs",
69
+ openOriginalWorkflow: "Open original workflow",
70
+ openInNewGraph: "Open in new graph"
71
+ },
72
+ fileExplorer: {
73
+ preview: {
74
+ shareFile: "Share file",
75
+ open: "Open",
76
+ userType: "User",
77
+ select: (name) => `Select ${name}`,
78
+ viewDetails: "View details",
79
+ openFolder: "Open folder",
80
+ delete: "Delete",
81
+ detailsTab: "Details",
82
+ previewTab: "Preview",
83
+ preview: "Preview",
84
+ openFullPreview: "Open full preview",
85
+ quickLook: "Quick Look",
86
+ fullWindow: "Full window",
87
+ streamed: "Streamed",
88
+ streamedTooltip: "Streamed securely to your browser over a short-lived signed URL — never written to disk.",
89
+ loading: "Loading preview…",
90
+ linkError: "Couldn't generate a preview link for this file.",
91
+ errorTitle: "Couldn't load preview",
92
+ previewError: "This file couldn't be previewed in your browser.",
93
+ tooLarge: "This file is too large to preview in the browser.",
94
+ downloadInstead: "Download instead",
95
+ archiveTitle: "Can't preview archives",
96
+ archiveMessage: "Archive files can't be previewed in the browser. Download the file to view its contents.",
97
+ unsupportedTitle: "Preview not available",
98
+ unsupportedMessage: "This file type can't be previewed in the browser. Download the file to view it.",
99
+ notebookParseError: "This notebook couldn't be parsed.",
100
+ copyUri: "Copy URI",
101
+ download: "Download",
102
+ close: "Close",
103
+ zoomIn: "Zoom in",
104
+ zoomOut: "Zoom out",
105
+ previousFile: "Previous file",
106
+ nextFile: "Next file",
107
+ csvRows: (count, columns) => `${count} rows · ${columns} columns`,
108
+ csvFirstRows: (count, columns) => `First ${count} rows · ${columns} columns`,
109
+ head: "Head",
110
+ tail: "Tail",
111
+ firstLines: (count) => `First ${count} lines`,
112
+ lastLines: (count) => `Last ${count} lines`,
113
+ notebookOutput: "Notebook output"
114
+ },
115
+ createFolder: {
116
+ action: "New folder",
117
+ submit: "Create folder",
118
+ creating: "Creating folder…",
119
+ folder: "Folder",
120
+ namePlaceholder: "Folder name",
121
+ success: (name) => `Created ${name}.`,
122
+ error: (message) => `Couldn't create folder: ${message}`,
123
+ invalidTarget: "Select a folder before creating a new folder.",
124
+ noWriteAccess: "You do not have write access to this storage.",
125
+ unsupported: "Folder creation is not supported for this storage.",
126
+ validation: {
127
+ reserved: "The folder name cannot be . or ..",
128
+ separator: "Folder names cannot include / or \\.",
129
+ exists: "An item with this name already exists."
130
+ }
131
+ },
132
+ readOnly: "Read-only",
133
+ cors: {
134
+ explanation: {
135
+ title: "CORS Configuration Required",
136
+ description: "This storage location cannot be accessed from the browser because it is missing Cross-Origin Resource Sharing (CORS) rules.",
137
+ action: "You can automatically configure these rules to allow access from this domain.",
138
+ note: "Note: Changes may take up to 30 seconds to propagate."
139
+ },
140
+ actions: {
141
+ retry: "Retry Connection",
142
+ addRules: "Add CORS Rules"
143
+ },
144
+ propagating: {
145
+ title: "Propagating CORS rules",
146
+ description: "Azure is rolling out the new rules to its storage endpoints. This usually completes within a minute.",
147
+ stages: {
148
+ submitted: "Submitted",
149
+ propagating: "Propagating",
150
+ verified: "Verified"
151
+ },
152
+ telemetry: { probing: "probing every 3s" }
153
+ }
154
+ },
155
+ selectedCount: (count) => `${count} selected`,
156
+ loadingMore: "Loading more items…",
157
+ loadMore: "Load more",
158
+ retry: "Retry",
159
+ partialCount: (count) => `${count.toLocaleString()}+ items`,
160
+ notFound: {
161
+ title: (name) => `Couldn't find ${name}`,
162
+ description: "It may have been moved or deleted, or it may sit further into a folder than we have listed.",
163
+ retry: "Try again"
164
+ },
165
+ treeMoreCount: (count) => `${count.toLocaleString()} more`,
166
+ treeMoreCountPartial: (count) => `${count.toLocaleString()}+ more`,
167
+ messages: {
168
+ noWriteAccess: "You do not have write access to this storage.",
169
+ uploadsUnsupported: "Uploads are not supported for this storage.",
170
+ noFilesForDownload: "No files selected for download.",
171
+ downloadLinkFailed: "Failed to generate download link",
172
+ fileLinkFailed: "Failed to generate file link",
173
+ fileLinkCopied: "File link copied to clipboard",
174
+ noUri: "No URI available for this file.",
175
+ uriCopied: "URI copied to clipboard",
176
+ uriCopyFailed: "Failed to copy URI",
177
+ storageUnavailable: "This storage is not available at the moment. Please try again later.",
178
+ waitForCurrentUpload: "Please wait for the current upload to finish before starting a new one.",
179
+ waitForUpload: "Please wait for the upload to finish.",
180
+ downloadUnsupported: "Download is not supported for this storage at the moment. Please check back later.",
181
+ sharingUnsupported: "Sharing is not supported for this storage at the moment. Please check back later.",
182
+ deleteUnsupported: "Delete is not supported for this storage at the moment. Please check back later.",
183
+ uploadUnsupported: "Upload is not supported for this storage at the moment. Please check back later.",
184
+ noItemsForDeletion: "No items selected for deletion.",
185
+ deleting: "Deleting item(s) from storage...",
186
+ deleteSomeFailed: "Failed to delete one or more items. Please try again.",
187
+ deleteSuccess: "Deleted item(s) from storage successfully!",
188
+ deleteFailed: (message) => `Failed to delete item(s): ${message}`,
189
+ noFilesToUpload: "No files to upload or target path not selected.",
190
+ invalidUploadTarget: "This target path is not valid for upload.",
191
+ uploadInitFailed: "Failed to initialize upload session. Please try again.",
192
+ uploadQueuedInfo: "Another upload is in progress. This upload will be added to the queue and handled once the previous upload finishes.",
193
+ connectFailed: "Failed to connect to storage provider. Please check your storage settings and try again.",
194
+ corsNoStorage: "No storage selected",
195
+ corsAdded: "CORS rules added successfully",
196
+ corsPropagating: "CORS rules were added, but are still propagating. Try again in a moment."
197
+ },
198
+ chrome: {
199
+ explorer: "Explorer",
200
+ refresh: "Refresh",
201
+ collapse: "Collapse",
202
+ upload: "Upload",
203
+ download: "Download",
204
+ access: "Access",
205
+ manageAccess: "Manage Access",
206
+ delete: "Delete",
207
+ copyToClipboard: "Copy to clipboard",
208
+ selectAll: "Select all",
209
+ name: "Name",
210
+ size: "Size",
211
+ created: "Created",
212
+ hash: "Hash",
213
+ storageIconAlt: "An icon for the storage"
214
+ },
215
+ confirmUpload: {
216
+ title: "Confirm Upload",
217
+ text: (path) => `Please confirm the following objects you want to upload to ${path}.`,
218
+ defaultPath: "the selected path",
219
+ noPath: "No path selected",
220
+ confirm: "Confirm",
221
+ target: "Target:",
222
+ totalSize: "Total Size:",
223
+ sizeLimitTitle: "Upload Size Limit Exceeded",
224
+ sizeLimitBody: (total, max) => `The total upload size (${total}) exceeds the maximum allowed limit of ${max}.`,
225
+ sizeLimitHint: "Please reduce the number of files or upload them in smaller batches."
226
+ },
227
+ confirmDelete: {
228
+ title: "Confirm Delete",
229
+ text: "Are you sure you want to delete the following item(s)? Folders are deleted with everything inside them. This action cannot be undone.",
230
+ action: "Delete"
231
+ },
232
+ empty: {
233
+ nothingSelected: "Nothing selected",
234
+ nothingSelectedHint: "Pick a folder or file from the tree to see its contents.",
235
+ folderEmpty: "This folder is empty",
236
+ dropHint: "Drag files or a folder here to upload.",
237
+ readOnlyHint: "You have read-only access to this storage.",
238
+ connectionIssue: "Connection issue",
239
+ tryAgain: "Try again",
240
+ shareThisFile: "Share this file"
241
+ },
242
+ upload: {
243
+ inQueue: (position, total) => `In Queue (#${position} of ${total})`,
244
+ queuedShort: (position, total) => `Queued #${position} / ${total}`,
245
+ destination: "Destination:",
246
+ eta: "ETA:",
247
+ uploading: "Uploading...",
248
+ completeTitle: "Upload Complete!",
249
+ completeShort: "Completed",
250
+ failedTitle: "Upload Failed",
251
+ failedShort: "Failed",
252
+ unknownTitle: "Unknown Status",
253
+ unknownShort: "Unknown",
254
+ cancelled: "Cancelled",
255
+ completed: "Completed",
256
+ failed: "Failed",
257
+ totalSize: "Total size:",
258
+ size: "Size:",
259
+ calculating: "Calculating...",
260
+ expandDetails: "Expand details",
261
+ minimizeDetails: "Minimize details",
262
+ sessionNotQueued: (id, status) => `Upload session with ID ${id} is not queued, current status is ${status}`,
263
+ allCancelled: (count) => `All ${count} file(s) were cancelled by user.`,
264
+ someUploaded: (count) => `${count} file(s) uploaded successfully!`,
265
+ someCancelled: (count) => `${count} file(s) cancelled by user.`,
266
+ allUploaded: "Upload file(s) successfully!",
267
+ failedSummary: (failed, total) => `${failed}/${total} files failed to upload:`,
268
+ failReasonGeneric: "The file(s) may be too large or the connection may have been interrupted.",
269
+ refreshFailed: (name, message) => `Failed to refresh storage data for ${name}. ${message}. Please try again.`,
270
+ unknownError: "Unknown error",
271
+ overallProgress: "Overall Progress"
272
+ }
273
+ },
274
+ form: {
275
+ invalidDuration: "Enter a duration as DD-HH:MM:SS or HH:MM:SS.",
276
+ durationOutOfRange: (min, max) => `Must be between ${min} and ${max}.`,
277
+ durationBelowMin: (min) => `Must be at least ${min}.`,
278
+ readOnly: "Read-only",
279
+ readWrite: "Read-write",
280
+ readOnlyDescription: "Read-only mounts can list and download objects, but cannot upload, modify, or delete them.",
281
+ readOnlyForced: "Your access to this bucket is read-only, so this mount cannot be writable."
282
+ },
283
+ list: {
284
+ copy: (label) => `Copy ${label}`,
285
+ copied: (label) => `Copied ${label}`,
286
+ couldntCopy: (label) => `Couldn't copy ${label}`,
287
+ moreActions: "More actions",
288
+ labelName: "name",
289
+ labelEmail: "email",
290
+ labelUsername: "username",
291
+ labelUid: "UID",
292
+ labelId: "ID",
293
+ labelUrl: "URL",
294
+ couldNotLoad: (noun) => `Couldn't load ${noun}`
295
+ }
296
+ },
297
+ navigation: {
298
+ toWorkflow: () => {},
299
+ toMarketItem: () => {},
300
+ openExternal: (href) => window.open(href, "_blank")
301
+ },
302
+ data: { useRunFile: defaultUseRunFile },
303
+ slots: {}
304
+ };
305
+ var UIContext = createContext(DEFAULTS);
306
+ function useNotify() {
307
+ return useContext(UIContext).notify;
308
+ }
309
+ function useStrings() {
310
+ return useContext(UIContext).strings;
311
+ }
312
+ function useNavigation() {
313
+ return useContext(UIContext).navigation;
314
+ }
315
+ function useSlots() {
316
+ return useContext(UIContext).slots;
317
+ }
318
+ function useWorkflowJsonResolver() {
319
+ return useContext(UIContext).data.resolveWorkflowJson;
320
+ }
321
+ function useProvisionCorsRules() {
322
+ return useContext(UIContext).data.provisionCorsRules;
323
+ }
324
+ function useRunFile(slug, path, options) {
325
+ const { useRunFile: boundUseRunFile } = useContext(UIContext).data;
326
+ return boundUseRunFile(slug, path, options);
327
+ }
328
+ function UIProvider({ notify, strings, navigation, data, slots, children }) {
329
+ const value = useMemo(() => ({
330
+ notify: {
331
+ ...DEFAULTS.notify,
332
+ ...notify
333
+ },
334
+ strings: {
335
+ loading: strings?.loading ?? DEFAULTS.strings.loading,
336
+ common: {
337
+ ...DEFAULTS.strings.common,
338
+ ...strings?.common
339
+ },
340
+ dropdown: {
341
+ ...DEFAULTS.strings.dropdown,
342
+ ...strings?.dropdown
343
+ },
344
+ logviewer: {
345
+ ...DEFAULTS.strings.logviewer,
346
+ ...strings?.logviewer
347
+ },
348
+ dag: {
349
+ ...DEFAULTS.strings.dag,
350
+ ...strings?.dag
351
+ },
352
+ jobActions: {
353
+ ...DEFAULTS.strings.jobActions,
354
+ ...strings?.jobActions
355
+ },
356
+ fileExplorer: {
357
+ ...DEFAULTS.strings.fileExplorer,
358
+ ...strings?.fileExplorer
359
+ },
360
+ form: {
361
+ ...DEFAULTS.strings.form,
362
+ ...strings?.form
363
+ },
364
+ list: {
365
+ ...DEFAULTS.strings.list,
366
+ ...strings?.list
367
+ }
368
+ },
369
+ navigation: {
370
+ ...DEFAULTS.navigation,
371
+ ...navigation
372
+ },
373
+ data: {
374
+ ...DEFAULTS.data,
375
+ ...data
376
+ },
377
+ slots: slots ?? DEFAULTS.slots
378
+ }), [
379
+ notify,
380
+ strings,
381
+ navigation,
382
+ data,
383
+ slots
384
+ ]);
385
+ return /* @__PURE__ */ jsx(UIContext.Provider, {
386
+ value,
387
+ children
388
+ });
389
+ }
390
+ //#endregion
391
+ export { useProvisionCorsRules as a, useStrings as c, useNotify as i, useWorkflowJsonResolver as l, useLink as n, useRunFile as o, useNavigation as r, useSlots as s, UIProvider as t };