@parallelworks/ui 0.45.0 → 0.47.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 (85) hide show
  1. package/README.md +16 -5
  2. package/dist/ai/agent/permissions.d.ts +1 -1
  3. package/dist/ai/agent/permissions.js +1 -1
  4. package/dist/ai/ai.css +4 -4
  5. package/dist/ai/components/ChatInput.js +1 -1
  6. package/dist/ai/components/ChatStage.d.ts +1 -1
  7. package/dist/ai/components/ChatStage.js +1 -1
  8. package/dist/ai/core/pasteLanguage.d.ts +1 -1
  9. package/dist/ai/core/pasteLanguage.js +1 -1
  10. package/dist/brandIcons.js +1 -1
  11. package/dist/components/ColorInput.d.ts +36 -0
  12. package/dist/components/ColorInput.js +82 -0
  13. package/dist/components/Combobox.d.ts +5 -2
  14. package/dist/components/Combobox.js +12 -11
  15. package/dist/components/CreateModal.js +2 -2
  16. package/dist/components/DatePicker.d.ts +5 -1
  17. package/dist/components/DatePicker.js +7 -7
  18. package/dist/components/Field.d.ts +19 -5
  19. package/dist/components/Field.js +21 -4
  20. package/dist/components/Input.d.ts +11 -1
  21. package/dist/components/Input.js +9 -6
  22. package/dist/components/Loader.d.ts +1 -1
  23. package/dist/components/MenuEntries.js +1 -1
  24. package/dist/components/NumberInput.d.ts +1 -0
  25. package/dist/components/OneTimeCodeInput.d.ts +23 -0
  26. package/dist/components/OneTimeCodeInput.js +39 -0
  27. package/dist/components/Provider.d.ts +15 -6
  28. package/dist/components/Provider.js +17 -5
  29. package/dist/components/SearchInput.d.ts +1 -0
  30. package/dist/components/Section.d.ts +7 -2
  31. package/dist/components/Section.js +58 -39
  32. package/dist/components/SegmentedControl.d.ts +4 -2
  33. package/dist/components/SegmentedControl.js +4 -2
  34. package/dist/components/Select.d.ts +2 -1
  35. package/dist/components/Select.js +1 -1
  36. package/dist/components/StatusBadge.d.ts +2 -2
  37. package/dist/components/StatusBadge.js +1 -1
  38. package/dist/components/Tabs.js +1 -0
  39. package/dist/components/ThemeEditor.js +15 -52
  40. package/dist/components/Toast.js +1 -1
  41. package/dist/components/ToggleGroup.d.ts +42 -0
  42. package/dist/components/ToggleGroup.js +69 -0
  43. package/dist/components/comboboxItems.d.ts +1 -1
  44. package/dist/components/fieldBox.js +1 -1
  45. package/dist/components/tone.d.ts +1 -1
  46. package/dist/editing.d.ts +1 -1
  47. package/dist/file-explorer/FileExplorerContext.js +11 -11
  48. package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +4 -4
  49. package/dist/file-explorer/FilePreview/useObjectText.js +4 -4
  50. package/dist/file-explorer/FilePreview/usePresignedUrl.js +4 -4
  51. package/dist/file-explorer/lib/types.d.ts +2 -2
  52. package/dist/file-explorer/toasts.js +9 -9
  53. package/dist/form/Fields/BooleanField.js +1 -1
  54. package/dist/form/Fields/ColorField.js +6 -10
  55. package/dist/form/Fields/DropdownField.js +1 -1
  56. package/dist/form/Fields/DurationField.js +1 -1
  57. package/dist/form/Fields/MultiDropdownField.js +1 -1
  58. package/dist/form/Fields/StringField.js +1 -1
  59. package/dist/form/Fields/TextAreaField.js +1 -1
  60. package/dist/form/Form.js +1 -1
  61. package/dist/form/utils/fieldItems.d.ts +1 -1
  62. package/dist/graph/GraphEditorDialogs.js +1 -1
  63. package/dist/graph/InputDialog.js +2 -2
  64. package/dist/graph/SuggestionInput.d.ts +1 -1
  65. package/dist/graph/SuggestionInput.js +1 -1
  66. package/dist/graph/WorkflowSettingsDialog.js +1 -1
  67. package/dist/graph/editorFields.js +2 -2
  68. package/dist/graph/editorPrimitives.d.ts +2 -2
  69. package/dist/graph/editorPrimitives.js +1 -1
  70. package/dist/graph/editorStrings.d.ts +2 -2
  71. package/dist/graph/editorStrings.js +4 -4
  72. package/dist/graph/inputRefs.js +2 -2
  73. package/dist/graph/stepWith.js +1 -1
  74. package/dist/icons.js +1 -1
  75. package/dist/index.d.ts +5 -1
  76. package/dist/index.js +14 -10
  77. package/dist/list/ListViewControls.js +1 -1
  78. package/dist/list/listSearch.js +1 -1
  79. package/dist/logviewer/segments.d.ts +1 -1
  80. package/dist/logviewer/segments.js +1 -1
  81. package/dist/styles/theme.css +1 -1
  82. package/dist/styles.css +1 -1
  83. package/dist/theme/derive.d.ts +3 -0
  84. package/dist/theme/derive.js +11 -7
  85. package/package.json +1 -1
@@ -135,7 +135,7 @@ function ToastViewport() {
135
135
  return /* @__PURE__ */ jsx(Toast.Portal, { children: /* @__PURE__ */ jsx(Toast.Viewport, {
136
136
  "data-toast-viewport": "",
137
137
  "aria-label": common.notifications,
138
- className: "fixed inset-x-0 top-3 z-(--layer-toast) mx-auto w-[calc(100vw-2rem)] outline-none sm:w-96",
138
+ className: "fixed top-[calc(var(--app-inset-top,0px)+0.75rem)] right-0 left-(--app-inset-start,0px) z-(--layer-toast) mx-auto w-[calc(100vw-var(--app-inset-start,0px)-2rem)] outline-none sm:w-96",
139
139
  children: /* @__PURE__ */ jsx(ToastList, {})
140
140
  }) });
141
141
  }
@@ -0,0 +1,42 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface ToggleGroupOption<T extends string> {
3
+ value: T;
4
+ label: string;
5
+ /** Before the label, such as a `StatusDot` in the status's tone or a provider's logo. */
6
+ icon?: ReactNode;
7
+ /** How many items the option matches, after the label. */
8
+ count?: number | undefined;
9
+ disabled?: boolean | undefined;
10
+ testId?: string;
11
+ }
12
+ export interface ToggleGroupProps<T extends string> {
13
+ /** Names the group for assistive technology. Leave it out inside a
14
+ * `Field group`, whose legend names it. */
15
+ label?: string | undefined;
16
+ options: readonly ToggleGroupOption<T>[];
17
+ /** The pressed options. Empty filters nothing out. */
18
+ value: readonly T[];
19
+ /** Called with the pressed options in the order `options` lists them. */
20
+ onValueChange: (value: T[]) => void;
21
+ /** Several options may be pressed at once; `false` allows one or none. */
22
+ multiple?: boolean | undefined;
23
+ /** Leads with an "All" option, pressed while nothing else is, that clears
24
+ * the others. `{ count }` shows the total beside it. */
25
+ all?: boolean | {
26
+ count?: number | undefined;
27
+ } | undefined;
28
+ size?: 'sm' | 'md' | undefined;
29
+ disabled?: boolean | undefined;
30
+ testId?: string;
31
+ }
32
+ /** Options that narrow a list, such as run statuses or job states, as a row of
33
+ * toggle buttons that wraps on a narrow screen. Pressing one adds it to the
34
+ * filter and pressing it again takes it out, so an empty filter shows
35
+ * everything; with `multiple={false}` pressing one replaces the last. Each
36
+ * option may carry an icon, such as a status dot, and a count.
37
+ *
38
+ * Use `SegmentedControl` instead for a setting that always has exactly one
39
+ * value, such as a time range, what to group by, or which view of the same
40
+ * data to show. A filter that may be off, or takes several values, is a
41
+ * `ToggleGroup`. */
42
+ export declare function ToggleGroup<T extends string>({ label, options, value, onValueChange, multiple, all, size, disabled, testId, }: ToggleGroupProps<T>): import("react").JSX.Element;
@@ -0,0 +1,69 @@
1
+ import { cx } from "../cx.js";
2
+ import { buttonClasses } from "./buttonClasses.js";
3
+ import { useStrings } from "./Provider.js";
4
+ import { formatCount } from "../format.js";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { Toggle } from "@base-ui/react/toggle";
7
+ import { ToggleGroup } from "@base-ui/react/toggle-group";
8
+ //#region src/components/ToggleGroup.tsx
9
+ var ALL = "\0all";
10
+ /** Options that narrow a list, such as run statuses or job states, as a row of
11
+ * toggle buttons that wraps on a narrow screen. Pressing one adds it to the
12
+ * filter and pressing it again takes it out, so an empty filter shows
13
+ * everything; with `multiple={false}` pressing one replaces the last. Each
14
+ * option may carry an icon, such as a status dot, and a count.
15
+ *
16
+ * Use `SegmentedControl` instead for a setting that always has exactly one
17
+ * value, such as a time range, what to group by, or which view of the same
18
+ * data to show. A filter that may be off, or takes several values, is a
19
+ * `ToggleGroup`. */
20
+ function ToggleGroup$1({ label, options, value, onValueChange, multiple = true, all = false, size = "sm", disabled = false, testId }) {
21
+ const strings = useStrings();
22
+ const allCount = typeof all === "object" ? all.count : void 0;
23
+ const pressed = all && value.length === 0 ? [ALL] : value;
24
+ return /* @__PURE__ */ jsxs(ToggleGroup, {
25
+ "aria-label": label,
26
+ "data-testid": testId,
27
+ className: "flex flex-wrap items-center gap-1",
28
+ multiple,
29
+ disabled,
30
+ value: pressed,
31
+ onValueChange: (next) => {
32
+ if (next.includes(ALL) && !pressed.includes(ALL)) {
33
+ onValueChange([]);
34
+ return;
35
+ }
36
+ onValueChange(options.filter((option) => next.includes(option.value)).map((option) => option.value));
37
+ },
38
+ children: [all && /* @__PURE__ */ jsx(Chip, {
39
+ value: ALL,
40
+ label: strings.common.all,
41
+ count: allCount,
42
+ size
43
+ }), options.map((option) => /* @__PURE__ */ jsx(Chip, {
44
+ ...option,
45
+ size
46
+ }, option.value))]
47
+ });
48
+ }
49
+ function Chip({ value, label, icon, count, disabled, testId, size }) {
50
+ return /* @__PURE__ */ jsxs(Toggle, {
51
+ value,
52
+ disabled,
53
+ "data-testid": testId,
54
+ className: cx("group aria-pressed:bg-(--theme-accent-subtle)", buttonClasses({
55
+ variant: "outline",
56
+ size
57
+ })),
58
+ children: [
59
+ icon,
60
+ label,
61
+ count !== void 0 && /* @__PURE__ */ jsx("span", {
62
+ className: "tabular-nums text-(--theme-muted-text-color) group-aria-pressed:text-(--theme-app)",
63
+ children: formatCount(count)
64
+ })
65
+ ]
66
+ });
67
+ }
68
+ //#endregion
69
+ export { ToggleGroup$1 as ToggleGroup };
@@ -15,7 +15,7 @@ export interface ComboboxGroup<Value = string> {
15
15
  /** Empty for a group that only reports a status; a search finds it by its heading. */
16
16
  items: readonly ComboboxLeaf<Value>[];
17
17
  }
18
- /** One item: an option, or a bare string labelled by its value. */
18
+ /** One item: an option, or a bare string labeled by its value. */
19
19
  export type ComboboxLeaf<Value = string> = ComboboxItem<Value> | (Value & string);
20
20
  /** Items, groups under headings, or both: items between groups list where they sit, without a heading. */
21
21
  export type ComboboxItems<Value = string> = readonly (ComboboxLeaf<Value> | ComboboxGroup<Value>)[];
@@ -16,7 +16,7 @@ var sizes = {
16
16
  text: "text-sm"
17
17
  }
18
18
  };
19
- var base = "w-full min-w-0 rounded-md border border-(--theme-border) bg-(--theme-input-bg) text-(--theme-app) outline-none transition-colors placeholder:text-(--theme-muted-text-color)";
19
+ var base = "w-full min-w-0 rounded-md border border-(--theme-border) bg-(--theme-input-bg) text-(--theme-app) outline-none transition-colors placeholder:text-(--theme-placeholder)";
20
20
  var own = cx("focus-visible:border-(--theme-accent) focus-visible:ring-1 focus-visible:ring-(--theme-accent)", "aria-invalid:border-(--theme-error) aria-invalid:focus-visible:ring-(--theme-error)", "disabled:cursor-not-allowed disabled:bg-(--theme-input-disabled-bg) disabled:text-(--theme-placeholder)", "data-disabled:cursor-not-allowed data-disabled:bg-(--theme-input-disabled-bg) data-disabled:text-(--theme-placeholder)");
21
21
  var inside = cx("has-[:focus-visible]:border-(--theme-accent) has-[:focus-visible]:ring-1 has-[:focus-visible]:ring-(--theme-accent)", "has-[[aria-invalid=true]]:border-(--theme-error) has-[[aria-invalid=true]:focus-visible]:ring-(--theme-error)", "has-[input:disabled]:cursor-not-allowed has-[input:disabled]:bg-(--theme-input-disabled-bg) has-[input:disabled]:text-(--theme-placeholder)", "data-disabled:cursor-not-allowed data-disabled:bg-(--theme-input-disabled-bg) data-disabled:text-(--theme-placeholder)");
22
22
  /** The box every input-like control draws: text inputs, textareas, and the triggers of
@@ -1,4 +1,4 @@
1
- /** How a status reads: its colours come from the theme's tone tokens, so every
1
+ /** How a status reads: its colors come from the theme's tone tokens, so every
2
2
  * theme, dark ones included, sets them once. */
3
3
  export type Tone = 'default' | 'success' | 'warning' | 'error' | 'info' | 'muted';
4
4
  /** Text in the tone, for a status line beside a dot or icon. */
package/dist/editing.d.ts CHANGED
@@ -320,7 +320,7 @@ export type SettingsYamlProblem = {
320
320
  /** A key or list index on the way down to a YAML node. */
321
321
  export type YamlSegment = string | number;
322
322
  type UnknownRecord = Record<string, unknown>;
323
- /** One input a built-in action takes in its step's `with`, labelled in the reader's language. */
323
+ /** One input a built-in action takes in its step's `with`, labeled in the reader's language. */
324
324
  export interface WorkflowActionInput {
325
325
  key: string;
326
326
  kind: 'text' | 'textarea' | 'number' | 'any' | 'list' | 'bool' | 'choice' | 'flags' | 'target';
@@ -107,7 +107,7 @@ function FileExplorerProvider({ children }) {
107
107
  const fileProgress = session.progress.allFiles.get(relativePath);
108
108
  if (fileProgress?.abortController && (fileProgress.status === "pending" || fileProgress.status === "uploading")) {
109
109
  fileProgress.abortController.abort();
110
- updateFileProgressInUploadSession(session, relativePath, { status: "cancelled" });
110
+ updateFileProgressInUploadSession(session, relativePath, { status: "canceled" });
111
111
  }
112
112
  };
113
113
  const handleSessionCancel = (session) => {
@@ -116,12 +116,12 @@ function FileExplorerProvider({ children }) {
116
116
  fileProgress.abortController.abort();
117
117
  session.progress?.allFiles?.set(relativePath, {
118
118
  ...fileProgress,
119
- status: "cancelled"
119
+ status: "canceled"
120
120
  });
121
121
  }
122
122
  });
123
123
  session.abortController?.abort();
124
- session.status = "cancelled";
124
+ session.status = "canceled";
125
125
  };
126
126
  const startUploadSession = async (sessionId) => {
127
127
  const session = getUploadSessionById(sessionId);
@@ -157,7 +157,7 @@ function FileExplorerProvider({ children }) {
157
157
  const results = await mapWithConcurrency(session.uploadNodes, UPLOAD_CONCURRENCY, async (node) => {
158
158
  const fileProgress = session.progress?.allFiles?.get(node.relativePath);
159
159
  if (!fileProgress) return;
160
- if (fileProgress.status === "cancelled") throw new Error("Upload cancelled by user");
160
+ if (fileProgress.status === "canceled") throw new Error("Upload canceled by user");
161
161
  updateFileProgressInUploadSession(session, node.relativePath, {
162
162
  status: "uploading",
163
163
  loadedBytes: 0,
@@ -172,11 +172,11 @@ function FileExplorerProvider({ children }) {
172
172
  }
173
173
  const input = uploadFileInput(session.storageName, objectPath, node.file);
174
174
  const onProgress = (progress) => {
175
- if (session.status === "cancelled" || !session.progress?.allFiles) return;
175
+ if (session.status === "canceled" || !session.progress?.allFiles) return;
176
176
  const currentFileProgress = session.progress.allFiles.get(node.relativePath);
177
177
  if (!currentFileProgress || [
178
178
  "failed",
179
- "cancelled",
179
+ "canceled",
180
180
  "completed"
181
181
  ].includes(currentFileProgress.status ?? "")) return;
182
182
  updateFileProgressInUploadSession(session, node.relativePath, {
@@ -205,8 +205,8 @@ function FileExplorerProvider({ children }) {
205
205
  updateFileProgressInUploadSession(session, node.relativePath, { status: "completed" });
206
206
  } catch (error) {
207
207
  const errorMessage = error instanceof Error ? error.message : String(error ?? "");
208
- const isCancelled = errorMessage.toLowerCase().includes("abort") || errorMessage.toLowerCase().includes("cancel");
209
- updateFileProgressInUploadSession(session, node.relativePath, { status: isCancelled ? "cancelled" : "failed" });
208
+ const isCanceled = errorMessage.toLowerCase().includes("abort") || errorMessage.toLowerCase().includes("cancel");
209
+ updateFileProgressInUploadSession(session, node.relativePath, { status: isCanceled ? "canceled" : "failed" });
210
210
  toast.update(sessionId, {
211
211
  message: progressToast({
212
212
  ...session,
@@ -218,7 +218,7 @@ function FileExplorerProvider({ children }) {
218
218
  }
219
219
  }),
220
220
  icon: false,
221
- dismissible: session.status === "failed" || session.status === "cancelled",
221
+ dismissible: session.status === "failed" || session.status === "canceled",
222
222
  timeout: false
223
223
  });
224
224
  throw error;
@@ -267,12 +267,12 @@ function FileExplorerProvider({ children }) {
267
267
  else if (abortedCount > 0 && successfulCount > 0) toast.update(sessionId, {
268
268
  message: /* @__PURE__ */ jsxs("div", {
269
269
  className: "w-full flex flex-col gap-1",
270
- children: [/* @__PURE__ */ jsx("div", { children: t.upload.someUploaded(successfulCount) }), /* @__PURE__ */ jsx("div", { children: t.upload.someCancelled(abortedCount) })]
270
+ children: [/* @__PURE__ */ jsx("div", { children: t.upload.someUploaded(successfulCount) }), /* @__PURE__ */ jsx("div", { children: t.upload.someCanceled(abortedCount) })]
271
271
  }),
272
272
  tone: "success"
273
273
  });
274
274
  else if (abortedCount > 0 && successfulCount === 0) toast.update(sessionId, {
275
- message: t.upload.allCancelled(abortedCount),
275
+ message: t.upload.allCanceled(abortedCount),
276
276
  tone: "info"
277
277
  });
278
278
  else toast.update(sessionId, {
@@ -34,7 +34,7 @@ function useObjectBlobUrl(url, { maxBytes, knownSize, mimeType, cacheKey }) {
34
34
  });
35
35
  return;
36
36
  }
37
- let cancelled = false;
37
+ let canceled = false;
38
38
  const record = loadPreviewContent(cacheKey, async (signal) => {
39
39
  const response = await fetchPreviewObject(cacheKey, url, signal);
40
40
  const { bytes, tooLarge: exceeded } = await readCappedBytes(response, maxBytes);
@@ -52,17 +52,17 @@ function useObjectBlobUrl(url, { maxBytes, knownSize, mimeType, cacheKey }) {
52
52
  loading: true
53
53
  });
54
54
  record.promise.then((result) => {
55
- if (!cancelled) setState(toState(result));
55
+ if (!canceled) setState(toState(result));
56
56
  }).catch((err) => {
57
57
  if (err instanceof DOMException && err.name === "AbortError") return;
58
- if (!cancelled) setState({
58
+ if (!canceled) setState({
59
59
  ...IDLE,
60
60
  error: err instanceof Error ? err.message : "Failed to load file",
61
61
  corsError: err instanceof CorsError
62
62
  });
63
63
  });
64
64
  return () => {
65
- cancelled = true;
65
+ canceled = true;
66
66
  };
67
67
  }, [
68
68
  url,
@@ -60,7 +60,7 @@ function useObjectText(url, { maxBytes, maxLines, knownSize, cacheKey, tail = fa
60
60
  });
61
61
  return;
62
62
  }
63
- let cancelled = false;
63
+ let canceled = false;
64
64
  const record = loadPreviewContent(key, (signal) => readObjectText(signal, {
65
65
  url,
66
66
  cacheKey,
@@ -74,17 +74,17 @@ function useObjectText(url, { maxBytes, maxLines, knownSize, cacheKey, tail = fa
74
74
  loading: true
75
75
  });
76
76
  record.promise.then((result) => {
77
- if (!cancelled) setState(toState(result));
77
+ if (!canceled) setState(toState(result));
78
78
  }).catch((err) => {
79
79
  if (err instanceof DOMException && err.name === "AbortError") return;
80
- if (!cancelled) setState({
80
+ if (!canceled) setState({
81
81
  ...IDLE,
82
82
  error: err instanceof Error ? err.message : "Failed to load file",
83
83
  corsError: err instanceof CorsError
84
84
  });
85
85
  });
86
86
  return () => {
87
- cancelled = true;
87
+ canceled = true;
88
88
  };
89
89
  }, [
90
90
  url,
@@ -46,7 +46,7 @@ function usePresignedUrl(node, getPresignedUrl, { enabled, linkErrorMessage }) {
46
46
  });
47
47
  return;
48
48
  }
49
- let cancelled = false;
49
+ let canceled = false;
50
50
  const record = loadPreviewUrl(path, () => getUrlRef.current(node));
51
51
  setState(record.value ? toState(record.value, linkErrorRef.current) : {
52
52
  url: null,
@@ -54,16 +54,16 @@ function usePresignedUrl(node, getPresignedUrl, { enabled, linkErrorMessage }) {
54
54
  error: null
55
55
  });
56
56
  record.promise.then((result) => {
57
- if (!cancelled) setState(toState(result, linkErrorRef.current));
57
+ if (!canceled) setState(toState(result, linkErrorRef.current));
58
58
  }).catch((err) => {
59
- if (!cancelled) setState({
59
+ if (!canceled) setState({
60
60
  url: null,
61
61
  loading: false,
62
62
  error: err instanceof Error ? err.message : linkErrorRef.current
63
63
  });
64
64
  });
65
65
  return () => {
66
- cancelled = true;
66
+ canceled = true;
67
67
  };
68
68
  }, [path]);
69
69
  const cached = path ? peekPreviewUrl(path) : void 0;
@@ -79,14 +79,14 @@ export interface UploadFileProgress {
79
79
  totalBytes?: number;
80
80
  percentage?: number;
81
81
  abortController?: AbortController;
82
- status?: 'pending' | 'uploading' | 'completed' | 'failed' | 'cancelled';
82
+ status?: 'pending' | 'uploading' | 'completed' | 'failed' | 'canceled';
83
83
  }
84
84
  export interface UploadSession {
85
85
  id: string;
86
86
  storageName: string;
87
87
  targetPath: string;
88
88
  uploadNodes: UploadNode[];
89
- status: 'queued' | 'uploading' | 'completed' | 'failed' | 'cancelled';
89
+ status: 'queued' | 'uploading' | 'completed' | 'failed' | 'canceled';
90
90
  queueIndex: number;
91
91
  client: IFileExplorerClient;
92
92
  provider: IFileExplorerProvider;
@@ -42,9 +42,9 @@ function getSessionStatusInfo(session, queueLength, strings) {
42
42
  };
43
43
  }
44
44
  }
45
- function barTone({ isCompleted, isCancelled, isFailed }) {
45
+ function barTone({ isCompleted, isCanceled, isFailed }) {
46
46
  if (isCompleted) return "success";
47
- if (isCancelled) return "muted";
47
+ if (isCanceled) return "muted";
48
48
  return isFailed ? "error" : "accent";
49
49
  }
50
50
  function FileProgressBar({ fileProgress, fileName, onCancelFile }) {
@@ -55,9 +55,9 @@ function FileProgressBar({ fileProgress, fileName, onCancelFile }) {
55
55
  const loadedBytes = fileProgress.loadedBytes || 0;
56
56
  const totalBytes = fileProgress.fileSizeBytes || fileProgress.totalBytes || 0;
57
57
  const isCompleted = percentage === 100 || fileProgress.status === "completed";
58
- const isCancelled = fileProgress.status === "cancelled";
58
+ const isCanceled = fileProgress.status === "canceled";
59
59
  const isFailed = fileProgress.status === "failed";
60
- const isSettled = isCompleted || isCancelled || isFailed;
60
+ const isSettled = isCompleted || isCanceled || isFailed;
61
61
  const canCancel = !!fileProgress.abortController && !isSettled;
62
62
  const stop = (e, then) => {
63
63
  e.stopPropagation();
@@ -71,11 +71,11 @@ function FileProgressBar({ fileProgress, fileName, onCancelFile }) {
71
71
  value: percentage,
72
72
  tone: barTone({
73
73
  isCompleted,
74
- isCancelled,
74
+ isCanceled,
75
75
  isFailed
76
76
  }),
77
77
  label: fileName,
78
- status: isCancelled ? strings.cancelled : isCompleted ? strings.completed : isFailed ? strings.failed : void 0,
78
+ status: isCanceled ? strings.canceled : isCompleted ? strings.completed : isFailed ? strings.failed : void 0,
79
79
  detail: !isSettled && totalBytes > 0 ? `${formatBytes(loadedBytes)} / ${formatBytes(totalBytes)}` : void 0
80
80
  }),
81
81
  !showCancelConfirm && canCancel && /* @__PURE__ */ jsx(IconButton, {
@@ -120,14 +120,14 @@ function UploadSessionToast({ session, queueLength, onCancel, onCancelFile }) {
120
120
  const statusInfo = getSessionStatusInfo(session, queueLength, strings);
121
121
  const targetPath = `${session.targetPath}/`;
122
122
  const isCompleted = session.status === "completed";
123
- const isCancelled = session.status === "cancelled";
123
+ const isCanceled = session.status === "canceled";
124
124
  const isFailed = session.status === "failed";
125
- const isUploading = !isCompleted && !isCancelled && !isFailed;
125
+ const isUploading = !isCompleted && !isCanceled && !isFailed;
126
126
  const totalProgress = session.progress?.overallProgress || 0;
127
127
  const totalSize = session.progress?.totalSizeBytes || 0;
128
128
  const sessionTone = barTone({
129
129
  isCompleted,
130
- isCancelled,
130
+ isCanceled,
131
131
  isFailed
132
132
  });
133
133
  const allFiles = session.progress?.allFiles ? Array.from(session.progress.allFiles.values()) : [];
@@ -1,6 +1,6 @@
1
1
  import { Tooltip } from "../../components/Tooltip.js";
2
- import { Switch } from "../../components/Switch.js";
3
2
  import { Field } from "../../components/Field.js";
3
+ import { Switch } from "../../components/Switch.js";
4
4
  import { fieldFrame } from "../fieldFrame.js";
5
5
  import { useFieldValue } from "../useFieldValue.js";
6
6
  import { jsx } from "react/jsx-runtime";
@@ -1,6 +1,5 @@
1
- import { cx } from "../../cx.js";
2
- import { fieldBox } from "../../components/fieldBox.js";
3
1
  import { Field } from "../../components/Field.js";
2
+ import { ColorInput } from "../../components/ColorInput.js";
4
3
  import { fieldFrame } from "../fieldFrame.js";
5
4
  import { useFieldValue } from "../useFieldValue.js";
6
5
  import { jsx } from "react/jsx-runtime";
@@ -8,20 +7,17 @@ import { jsx } from "react/jsx-runtime";
8
7
  function ColorField(props) {
9
8
  const { field, disabled, onChange } = props;
10
9
  const [value, change] = useFieldValue(field.name ?? "");
11
- const handleChange = (e) => {
12
- onChange?.(e.target.value);
13
- change(e.target.value);
14
- };
15
10
  return /* @__PURE__ */ jsx(Field, {
16
11
  ...fieldFrame(props),
17
- children: (control) => /* @__PURE__ */ jsx("input", {
12
+ children: (control) => /* @__PURE__ */ jsx(ColorInput, {
18
13
  ...control,
19
- className: cx(fieldBox(), "w-18 cursor-pointer p-1"),
20
14
  name: field.name,
21
15
  value: value || "#fbbf24",
22
- type: "color",
23
16
  disabled,
24
- onChange: handleChange
17
+ onValueChange: (color) => {
18
+ onChange?.(color);
19
+ change(color);
20
+ }
25
21
  })
26
22
  });
27
23
  }
@@ -1,5 +1,5 @@
1
- import { Autocomplete, Combobox } from "../../components/Combobox.js";
2
1
  import { Field } from "../../components/Field.js";
2
+ import { Autocomplete, Combobox } from "../../components/Combobox.js";
3
3
  import { toFieldItems } from "../utils/fieldItems.js";
4
4
  import { fieldFrame } from "../fieldFrame.js";
5
5
  import { useChoiceField } from "../useChoiceField.js";
@@ -1,7 +1,7 @@
1
1
  import { useStrings } from "../../components/Provider.js";
2
2
  import { Checkbox } from "../../components/Checkbox.js";
3
- import { fieldBox } from "../../components/fieldBox.js";
4
3
  import { Field, FieldOption } from "../../components/Field.js";
4
+ import { fieldBox } from "../../components/fieldBox.js";
5
5
  import { fieldFrame } from "../fieldFrame.js";
6
6
  import { useFieldValue } from "../useFieldValue.js";
7
7
  import { formatDurationText, parseDurationText } from "../utils/duration.js";
@@ -1,5 +1,5 @@
1
- import { Combobox } from "../../components/Combobox.js";
2
1
  import { Field } from "../../components/Field.js";
2
+ import { Combobox } from "../../components/Combobox.js";
3
3
  import { toFieldItems } from "../utils/fieldItems.js";
4
4
  import { fieldFrame } from "../fieldFrame.js";
5
5
  import { useFieldValue } from "../useFieldValue.js";
@@ -1,6 +1,6 @@
1
1
  import { cx } from "../../cx.js";
2
- import { fieldBox } from "../../components/fieldBox.js";
3
2
  import { Field, RevealToggle } from "../../components/Field.js";
3
+ import { fieldBox } from "../../components/fieldBox.js";
4
4
  import { fieldFrame } from "../fieldFrame.js";
5
5
  import { useFieldValue } from "../useFieldValue.js";
6
6
  import { getPlaceholder } from "../utils/getPlaceholder.js";
@@ -1,6 +1,6 @@
1
1
  import { cx } from "../../cx.js";
2
- import { fieldBox } from "../../components/fieldBox.js";
3
2
  import { Field } from "../../components/Field.js";
3
+ import { fieldBox } from "../../components/fieldBox.js";
4
4
  import { fieldFrame } from "../fieldFrame.js";
5
5
  import { useFieldValue } from "../useFieldValue.js";
6
6
  import { getPlaceholder } from "../utils/getPlaceholder.js";
package/dist/form/Form.js CHANGED
@@ -2,8 +2,8 @@ import { cx } from "../cx.js";
2
2
  import { Loader } from "../components/Loader.js";
3
3
  import { useStrings, useWorkflowEngine } from "../components/Provider.js";
4
4
  import { Button } from "../components/Button.js";
5
- import { InfoTip } from "../components/InfoTip.js";
6
5
  import { FieldRowContext } from "../components/Field.js";
6
+ import { InfoTip } from "../components/InfoTip.js";
7
7
  import { Section } from "../components/Section.js";
8
8
  import { parseWizardConfig } from "./Wizard/utils.js";
9
9
  import { inputWidth, resolvedFlag } from "./lib.js";
@@ -17,7 +17,7 @@ export interface FieldOptionGroup<Value = string> {
17
17
  category?: string | undefined;
18
18
  options: readonly (FieldOptionItem<Value> | string)[];
19
19
  }
20
- /** A dropdown option: a bare string is a choice labelled by its value. */
20
+ /** A dropdown option: a bare string is a choice labeled by its value. */
21
21
  export type FieldOption<Value = string> = string | FieldOptionItem<Value> | FieldOptionGroup<Value>;
22
22
  /** A picker item that also sets other fields when chosen, through `secondaryField`. */
23
23
  export type ChoiceItem<Value = unknown> = ComboboxItem<Value> & {
@@ -3,8 +3,8 @@ import { withPositionKeys } from "../components/keys.js";
3
3
  import { useWorkflowActions, useWorkflowEditing } from "../components/Provider.js";
4
4
  import { Checkbox } from "../components/Checkbox.js";
5
5
  import { ErrorText, FieldOption } from "../components/Field.js";
6
- import { IconButton } from "../components/IconButton.js";
7
6
  import { Input } from "../components/Input.js";
7
+ import { IconButton } from "../components/IconButton.js";
8
8
  import { Select } from "../components/Select.js";
9
9
  import { useGraphEditorStrings } from "./editorStrings.js";
10
10
  import { asRecord } from "./records.js";
@@ -3,10 +3,10 @@ import { ArrowDownIcon, ArrowUpIcon, EditIcon, RemoveIcon, TrashIcon } from "../
3
3
  import { withPositionKeys } from "../components/keys.js";
4
4
  import { useWorkflowEditing, useWorkflowEngine } from "../components/Provider.js";
5
5
  import { Checkbox, CheckboxGroup } from "../components/Checkbox.js";
6
- import { Combobox } from "../components/Combobox.js";
7
6
  import { ErrorText, Field, FieldOption } from "../components/Field.js";
8
- import { IconButton } from "../components/IconButton.js";
9
7
  import { Input, Textarea } from "../components/Input.js";
8
+ import { Combobox } from "../components/Combobox.js";
9
+ import { IconButton } from "../components/IconButton.js";
10
10
  import { useGraphEditorStrings, useInputsEditorStrings } from "./editorStrings.js";
11
11
  import { asRecord } from "./records.js";
12
12
  import { INPUT_YAML_PATH } from "../editor/settingsYaml.js";
@@ -4,7 +4,7 @@ export interface Suggestion {
4
4
  value: string;
5
5
  label?: string | undefined;
6
6
  }
7
- /** A labelled suggestion shows its meaning, with the value it writes beneath. */
7
+ /** A labeled suggestion shows its meaning, with the value it writes beneath. */
8
8
  export declare function suggestionItems(suggestions: Suggestion[]): ComboboxItem[];
9
9
  /** A field that takes any typed value, offering `suggestions` as it's typed. */
10
10
  export declare function SuggestionInput({ suggestions, ...props }: Omit<AutocompleteProps, 'items' | 'defaultValue'> & {
@@ -1,7 +1,7 @@
1
1
  import { Autocomplete } from "../components/Combobox.js";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  //#region src/graph/SuggestionInput.tsx
4
- /** A labelled suggestion shows its meaning, with the value it writes beneath. */
4
+ /** A labeled suggestion shows its meaning, with the value it writes beneath. */
5
5
  function suggestionItems(suggestions) {
6
6
  return suggestions.map(({ value, label }) => label ? {
7
7
  value,
@@ -1,8 +1,8 @@
1
1
  import { RemoveIcon } from "../icons.js";
2
2
  import { useWorkflowEditing } from "../components/Provider.js";
3
3
  import { ErrorText } from "../components/Field.js";
4
- import { IconButton } from "../components/IconButton.js";
5
4
  import { Input } from "../components/Input.js";
5
+ import { IconButton } from "../components/IconButton.js";
6
6
  import { useGraphEditorStrings, useInputsEditorStrings } from "./editorStrings.js";
7
7
  import { asRecord } from "./records.js";
8
8
  import { SETTINGS_YAML_PATH } from "../editor/settingsYaml.js";
@@ -3,11 +3,11 @@ import { withPositionKeys } from "../components/keys.js";
3
3
  import { Tooltip } from "../components/Tooltip.js";
4
4
  import { Button } from "../components/Button.js";
5
5
  import { Checkbox } from "../components/Checkbox.js";
6
+ import { ErrorText, Field } from "../components/Field.js";
7
+ import { Input, Textarea } from "../components/Input.js";
6
8
  import { Modal, ModalTitle } from "../components/Modal.js";
7
9
  import { Switch } from "../components/Switch.js";
8
- import { ErrorText, Field } from "../components/Field.js";
9
10
  import { IconButton } from "../components/IconButton.js";
10
- import { Input, Textarea } from "../components/Input.js";
11
11
  import { Section } from "../components/Section.js";
12
12
  import { SegmentedControl } from "../components/SegmentedControl.js";
13
13
  import { useGraphEditorStrings } from "./editorStrings.js";
@@ -33,7 +33,7 @@ interface DragOptions {
33
33
  onMove?: (client: Point) => void;
34
34
  /** The release; `dragged` tells a drag from a click. */
35
35
  onEnd?: (client: Point, dragged: boolean) => void;
36
- /** A cancelled pointer, or Escape when `escape` is on. */
36
+ /** A canceled pointer, or Escape when `escape` is on. */
37
37
  onCancel?: (dragged: boolean) => void;
38
38
  /** Escape cancels the press, and goes no further. */
39
39
  escape?: boolean;
@@ -42,7 +42,7 @@ interface DragOptions {
42
42
  /** The click after the release: swallowed always, only after a drag, or never. */
43
43
  swallowClick?: 'always' | 'drag' | 'never';
44
44
  }
45
- /** Follows a press from `start` until it's released or cancelled. */
45
+ /** Follows a press from `start` until it's released or canceled. */
46
46
  export declare function trackDrag(start: Point, { onMove, onEnd, onCancel, escape: cancelOnEscape, holdText, swallowClick, }: DragOptions): void;
47
47
  export declare function place(box: Box): {
48
48
  left: number;
@@ -69,7 +69,7 @@ function suppressNextClick() {
69
69
  window.addEventListener("click", swallow, true);
70
70
  setTimeout(() => window.removeEventListener("click", swallow, true), 0);
71
71
  }
72
- /** Follows a press from `start` until it's released or cancelled. */
72
+ /** Follows a press from `start` until it's released or canceled. */
73
73
  function trackDrag(start, { onMove, onEnd, onCancel, escape: cancelOnEscape = false, holdText, swallowClick = "never" }) {
74
74
  let dragged = false;
75
75
  const cleanup = () => {
@@ -203,14 +203,14 @@ export declare const GRAPH_EDITOR_STRINGS: {
203
203
  default: string;
204
204
  always: string;
205
205
  failure: string;
206
- cancelled: string;
206
+ canceled: string;
207
207
  success: string;
208
208
  };
209
209
  jobConditions: {
210
210
  default: string;
211
211
  always: string;
212
212
  failure: string;
213
- cancelled: string;
213
+ canceled: string;
214
214
  success: string;
215
215
  };
216
216
  modeFromInput: string;