@parallelworks/ui 0.50.0 → 0.52.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 (240) hide show
  1. package/README.md +204 -18
  2. package/dist/ai/agent/toolStrings.d.ts +2 -0
  3. package/dist/ai/agent/toolStrings.js +20 -18
  4. package/dist/ai/ai.css +12 -0
  5. package/dist/ai/components/AllocationSelector.js +5 -1
  6. package/dist/ai/components/AttachmentManager.js +51 -42
  7. package/dist/ai/components/AttachmentUpload.d.ts +4 -2
  8. package/dist/ai/components/AttachmentUpload.js +9 -9
  9. package/dist/ai/components/BlockedGroupBanner.js +8 -14
  10. package/dist/ai/components/BranchNavigator.js +11 -12
  11. package/dist/ai/components/ChatEmptyState.js +12 -19
  12. package/dist/ai/components/ChatInput.d.ts +4 -3
  13. package/dist/ai/components/ChatInput.js +27 -13
  14. package/dist/ai/components/ChatMessage.js +45 -121
  15. package/dist/ai/components/ChatMessageList.d.ts +5 -2
  16. package/dist/ai/components/ChatMessageList.js +89 -51
  17. package/dist/ai/components/ChatSidebar.js +11 -7
  18. package/dist/ai/components/ChatThread.js +1 -13
  19. package/dist/ai/components/DragOverlay.js +3 -3
  20. package/dist/ai/components/MessageAttachments.d.ts +10 -0
  21. package/dist/ai/components/MessageAttachments.js +78 -0
  22. package/dist/ai/components/ModelSelector.js +4 -4
  23. package/dist/ai/components/PastedText.js +2 -2
  24. package/dist/ai/components/ProviderIssueBanner.js +19 -23
  25. package/dist/ai/components/ShareDialog.js +2 -2
  26. package/dist/ai/components/agent/ActivityLine.d.ts +0 -2
  27. package/dist/ai/components/agent/ActivityLine.js +8 -51
  28. package/dist/ai/components/agent/AgentMessageParts.js +117 -56
  29. package/dist/ai/core/ChatProvider.d.ts +16 -5
  30. package/dist/ai/core/ChatProvider.js +41 -8
  31. package/dist/ai/core/config.js +4 -3
  32. package/dist/ai/index.d.ts +1 -1
  33. package/dist/ai/index.js +3 -3
  34. package/dist/ai/strings.d.ts +29 -3
  35. package/dist/ai/strings.js +81 -26
  36. package/dist/ai/types.d.ts +4 -0
  37. package/dist/ai/ui/Notice.d.ts +2 -2
  38. package/dist/ai/ui/Notice.js +29 -62
  39. package/dist/ai/ui/sidebar.d.ts +5 -3
  40. package/dist/ai/ui/sidebar.js +21 -9
  41. package/dist/components/ActionMenu.d.ts +1 -0
  42. package/dist/components/ActionMenu.js +6 -1
  43. package/dist/components/AppLink.d.ts +26 -0
  44. package/dist/components/AppLink.js +51 -0
  45. package/dist/components/Avatar.d.ts +2 -1
  46. package/dist/components/Avatar.js +4 -2
  47. package/dist/components/Button.d.ts +15 -5
  48. package/dist/components/Button.js +47 -40
  49. package/dist/components/Callout.d.ts +31 -7
  50. package/dist/components/Callout.js +51 -24
  51. package/dist/components/Card.d.ts +11 -6
  52. package/dist/components/Card.js +14 -8
  53. package/dist/components/Checkbox.js +2 -1
  54. package/dist/components/ColorInput.js +5 -3
  55. package/dist/components/Combobox.js +49 -19
  56. package/dist/components/ConfirmModal.d.ts +19 -8
  57. package/dist/components/ConfirmModal.js +31 -53
  58. package/dist/components/CopyButton.d.ts +38 -0
  59. package/dist/components/CopyButton.js +68 -0
  60. package/dist/components/CreateModal.js +118 -111
  61. package/dist/components/DatePicker.js +12 -8
  62. package/dist/components/DescriptionList.d.ts +51 -17
  63. package/dist/components/DescriptionList.js +117 -31
  64. package/dist/components/Disclosure.js +1 -1
  65. package/dist/components/Drawer.js +10 -16
  66. package/dist/components/Field.d.ts +15 -5
  67. package/dist/components/Field.js +41 -9
  68. package/dist/components/IconButton.d.ts +14 -5
  69. package/dist/components/IconButton.js +25 -14
  70. package/dist/components/InfoTip.d.ts +4 -1
  71. package/dist/components/InfoTip.js +2 -1
  72. package/dist/components/Input.d.ts +14 -8
  73. package/dist/components/Input.js +46 -31
  74. package/dist/components/Loader.js +1 -1
  75. package/dist/components/MenuEntries.d.ts +43 -12
  76. package/dist/components/MenuEntries.js +34 -19
  77. package/dist/components/Meter.js +5 -4
  78. package/dist/components/Modal.d.ts +28 -4
  79. package/dist/components/Modal.js +37 -14
  80. package/dist/components/Overview.d.ts +20 -12
  81. package/dist/components/Overview.js +14 -9
  82. package/dist/components/PageHeader.d.ts +47 -65
  83. package/dist/components/PageHeader.js +275 -153
  84. package/dist/components/PageHeaderAction.d.ts +67 -0
  85. package/dist/components/PageHeaderAction.js +107 -0
  86. package/dist/components/Pagination.js +6 -16
  87. package/dist/components/Popover.js +3 -2
  88. package/dist/components/Provider.d.ts +79 -19
  89. package/dist/components/Provider.js +140 -130
  90. package/dist/components/Radio.js +2 -1
  91. package/dist/components/RefreshButton.js +7 -8
  92. package/dist/components/RequiredMark.js +1 -1
  93. package/dist/components/RunStatusIcon.js +2 -2
  94. package/dist/components/Section.js +1 -1
  95. package/dist/components/Select.d.ts +4 -9
  96. package/dist/components/Select.js +24 -11
  97. package/dist/components/SettingModeOption.d.ts +1 -1
  98. package/dist/components/SettingModeOption.js +7 -1
  99. package/dist/components/SettingsCard.d.ts +5 -3
  100. package/dist/components/SettingsCard.js +27 -20
  101. package/dist/components/Slider.js +1 -1
  102. package/dist/components/StatusBadge.js +2 -2
  103. package/dist/components/StatusIcons.js +2 -2
  104. package/dist/components/Switch.js +5 -4
  105. package/dist/components/Table.d.ts +30 -20
  106. package/dist/components/Table.js +50 -73
  107. package/dist/components/Tabs.d.ts +3 -7
  108. package/dist/components/Tabs.js +6 -10
  109. package/dist/components/ThemeEditor.js +24 -14
  110. package/dist/components/Toast.d.ts +11 -3
  111. package/dist/components/Toast.js +47 -22
  112. package/dist/components/buttonClasses.js +2 -2
  113. package/dist/components/comboboxItems.d.ts +4 -0
  114. package/dist/components/comboboxItems.js +6 -1
  115. package/dist/components/dismiss.d.ts +12 -0
  116. package/dist/components/dismiss.js +19 -0
  117. package/dist/components/fieldBox.d.ts +4 -0
  118. package/dist/components/fieldBox.js +7 -3
  119. package/dist/components/floating.d.ts +3 -3
  120. package/dist/components/floating.js +1 -1
  121. package/dist/components/markdownCodeBreaks.js +3 -4
  122. package/dist/components/pageHeaderStore.d.ts +41 -0
  123. package/dist/components/pageHeaderStore.js +67 -0
  124. package/dist/components/pathBreaks.d.ts +8 -0
  125. package/dist/components/pathBreaks.js +28 -0
  126. package/dist/components/segmented.js +1 -1
  127. package/dist/components/shortcutKey.d.ts +2 -1
  128. package/dist/components/shortcutKey.js +19 -2
  129. package/dist/components/splitter.js +1 -1
  130. package/dist/components/tone.d.ts +5 -2
  131. package/dist/components/tone.js +15 -6
  132. package/dist/components/useCssIsDark.js +40 -18
  133. package/dist/components/useTheme.js +9 -10
  134. package/dist/dev.d.ts +9 -0
  135. package/dist/dev.js +14 -0
  136. package/dist/editor/Editor.d.ts +3 -2
  137. package/dist/editor/Editor.js +11 -2
  138. package/dist/editor/EditorField.d.ts +2 -1
  139. package/dist/editor/EditorField.js +11 -29
  140. package/dist/editor/FormCodePanel.d.ts +7 -3
  141. package/dist/editor/FormCodePanel.js +14 -7
  142. package/dist/editor/Monaco.d.ts +14 -5
  143. package/dist/editor/Monaco.js +163 -112
  144. package/dist/editor/index.d.ts +5 -5
  145. package/dist/editor/index.js +3 -3
  146. package/dist/editor/themes.d.ts +8 -5
  147. package/dist/editor/themes.js +58 -30
  148. package/dist/editor/yaml.d.ts +6 -2
  149. package/dist/editor/yaml.js +11 -2
  150. package/dist/file-explorer/FileExplorer.js +143 -124
  151. package/dist/file-explorer/FileExplorerContext.js +1 -1
  152. package/dist/file-explorer/FilePreview/StreamedBadge.js +3 -1
  153. package/dist/file-explorer/FilePreview/Viewer.js +2 -2
  154. package/dist/file-explorer/FilePreview/index.js +4 -4
  155. package/dist/file-explorer/FileRow.js +1 -1
  156. package/dist/file-explorer/FileRowsWindow.js +34 -3
  157. package/dist/file-explorer/FileTable.js +3 -1
  158. package/dist/file-explorer/TreeView.js +37 -14
  159. package/dist/file-explorer/helpers.d.ts +2 -1
  160. package/dist/file-explorer/helpers.js +21 -20
  161. package/dist/file-explorer/toasts.js +27 -19
  162. package/dist/file-explorer/treeRows.d.ts +6 -0
  163. package/dist/file-explorer/treeRows.js +19 -1
  164. package/dist/file-explorer/useNearEnd.js +3 -6
  165. package/dist/form/Fields/CheckboxGroupField.js +12 -5
  166. package/dist/form/Fields/DurationField.js +1 -1
  167. package/dist/form/Fields/LabelField.js +1 -1
  168. package/dist/form/Fields/ObjectField.d.ts +1 -1
  169. package/dist/form/Fields/ObjectField.js +3 -2
  170. package/dist/form/Fields/StringField.js +16 -29
  171. package/dist/form/Fields/TextAreaField.js +3 -4
  172. package/dist/form/Form.js +3 -8
  173. package/dist/form/Wizard/WizardNavigation.js +1 -4
  174. package/dist/form/Wizard/WizardStepIndicator.js +1 -1
  175. package/dist/form/Wizard/utils.js +1 -1
  176. package/dist/form/fieldFrame.d.ts +1 -1
  177. package/dist/form/fieldFrame.js +2 -2
  178. package/dist/form/types/fieldComponentTypes.d.ts +2 -1
  179. package/dist/graph/AnnotationBanner.d.ts +1 -2
  180. package/dist/graph/AnnotationBanner.js +30 -32
  181. package/dist/graph/Connectors.js +4 -1
  182. package/dist/graph/DependencyGraph.js +2 -2
  183. package/dist/graph/GraphEditor.js +12 -10
  184. package/dist/graph/GraphEditorDialogs.js +2 -2
  185. package/dist/graph/GraphNode.js +7 -4
  186. package/dist/graph/InputDialog.js +1 -1
  187. package/dist/graph/InputsEditor.js +14 -11
  188. package/dist/graph/MatrixGroup.js +9 -3
  189. package/dist/graph/ProblemsButton.js +2 -2
  190. package/dist/graph/Reveal.js +18 -10
  191. package/dist/graph/ShortcutsButton.d.ts +11 -2
  192. package/dist/graph/ShortcutsButton.js +15 -4
  193. package/dist/graph/TreeView.js +35 -18
  194. package/dist/graph/WorkflowSettingsDialog.js +1 -1
  195. package/dist/graph/editorChrome.js +1 -1
  196. package/dist/graph/editorFields.js +1 -1
  197. package/dist/graph/editorRows.js +16 -10
  198. package/dist/graph/editorStrings.d.ts +7 -0
  199. package/dist/graph/editorStrings.js +8 -1
  200. package/dist/graph/fieldProblems.js +1 -1
  201. package/dist/graph/inputRefs.js +1 -1
  202. package/dist/graph/settingsViews.js +11 -18
  203. package/dist/graph/stepWith.js +2 -2
  204. package/dist/icons.d.ts +2 -0
  205. package/dist/icons.js +4 -2
  206. package/dist/index.d.ts +12 -12
  207. package/dist/index.js +16 -16
  208. package/dist/list/ActionToolbar.d.ts +44 -8
  209. package/dist/list/ActionToolbar.js +301 -102
  210. package/dist/list/ListPage.d.ts +15 -23
  211. package/dist/list/ListPage.js +46 -45
  212. package/dist/list/ListTable.d.ts +32 -7
  213. package/dist/list/ListTable.js +48 -12
  214. package/dist/list/ListViewControls.js +2 -2
  215. package/dist/list/UserHoverCard.js +7 -15
  216. package/dist/list/index.d.ts +2 -2
  217. package/dist/list/index.js +2 -2
  218. package/dist/list/listSearch.js +12 -10
  219. package/dist/list/listView.d.ts +10 -1
  220. package/dist/list/listView.js +15 -1
  221. package/dist/list/rowMenu.d.ts +2 -2
  222. package/dist/logviewer/LogViewer.d.ts +4 -2
  223. package/dist/logviewer/LogViewer.js +88 -70
  224. package/dist/logviewer/logviewer.css +3 -2
  225. package/dist/reducedMotion.d.ts +5 -0
  226. package/dist/reducedMotion.js +20 -0
  227. package/dist/safeUrl.d.ts +1 -1
  228. package/dist/safeUrl.js +4 -2
  229. package/dist/styles/theme.css +24 -10
  230. package/dist/styles.css +1 -1
  231. package/dist/theme/derive.d.ts +1 -1
  232. package/dist/theme/derive.js +46 -21
  233. package/dist/theme/fit.js +10 -4
  234. package/package.json +1 -1
  235. package/dist/components/Breadcrumbs.d.ts +0 -37
  236. package/dist/components/Breadcrumbs.js +0 -90
  237. package/dist/components/CopyToClipboard.d.ts +0 -17
  238. package/dist/components/CopyToClipboard.js +0 -66
  239. package/dist/components/Sort.d.ts +0 -9
  240. package/dist/components/Sort.js +0 -42
@@ -3,15 +3,26 @@ import { useLocalPersistedState } from "./persistedState.js";
3
3
  import { Toaster } from "./Toast.js";
4
4
  import { TooltipProvider } from "./Tooltip.js";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
- import { createContext, use, useCallback, useContext, useEffect, useMemo, useState } from "react";
6
+ import { createContext, use, useCallback, useContext, useEffect, useRef, useState } from "react";
7
+ import { dequal } from "dequal";
7
8
  //#region src/components/Provider.tsx
9
+ var isGroup = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
10
+ function mergeStrings(defaults, overrides) {
11
+ if (!isGroup(overrides) || !isGroup(defaults)) return defaults;
12
+ const merged = { ...defaults };
13
+ for (const [key, value] of Object.entries(overrides)) {
14
+ if (value === void 0) continue;
15
+ merged[key] = isGroup(value) && isGroup(merged[key]) ? mergeStrings(merged[key], value) : value;
16
+ }
17
+ return merged;
18
+ }
8
19
  var DefaultLink = ({ href, ...rest }) => /* @__PURE__ */ jsx("a", {
9
20
  href: safeUrl(href),
10
21
  ...rest
11
22
  });
12
23
  /** The provider's link slot, with a plain anchor fallback. */
13
24
  function useLink() {
14
- return useContext(UIContext).slots.link ?? DefaultLink;
25
+ return useContext(SlotsContext).link ?? DefaultLink;
15
26
  }
16
27
  var defaultUseRunFile = () => ({
17
28
  data: void 0,
@@ -68,6 +79,7 @@ var DEFAULTS = {
68
79
  copyThing: (label) => `Copy ${label}`,
69
80
  copiedThing: (label) => `Copied ${label}`,
70
81
  copyThingFailed: (label) => `Couldn't copy ${label}`,
82
+ noValue: "None",
71
83
  invalidName: "Use letters, numbers, dashes, and underscores.",
72
84
  invalidNumber: "Use a number.",
73
85
  copy: "Copy",
@@ -83,6 +95,13 @@ var DEFAULTS = {
83
95
  remove: "Remove",
84
96
  sort: "Sort",
85
97
  userAvatar: "User avatar",
98
+ presence: {
99
+ online: "online",
100
+ offline: "offline",
101
+ busy: "busy",
102
+ away: "away"
103
+ },
104
+ withPresence: (name, presence) => `${name}, ${presence}`,
86
105
  moreInfo: "More information",
87
106
  actions: "Actions",
88
107
  edit: "Edit",
@@ -91,9 +110,12 @@ var DEFAULTS = {
91
110
  clearSearch: "Clear search",
92
111
  filterPlaceholder: "Filter…",
93
112
  breadcrumb: "Breadcrumb",
113
+ showFullPath: "Show full path",
94
114
  yes: "Yes",
95
115
  no: "No",
96
116
  opensInNewTab: "(opens in a new tab)",
117
+ codeEditor: "Code editor",
118
+ readOnlyText: "This text is read-only.",
97
119
  resizePanel: "Resize panel",
98
120
  panelWidth: (px) => `${px} pixels wide`,
99
121
  refresh: "Refresh",
@@ -105,7 +127,8 @@ var DEFAULTS = {
105
127
  noOptionsFound: "No options found",
106
128
  showOptions: "Show options",
107
129
  add: (text) => `Add “${text}”`,
108
- limitReached: (max) => `Up to ${max}`
130
+ limitReached: (max) => `Up to ${max}`,
131
+ removeValue: (label) => `Remove ${label}`
109
132
  },
110
133
  datePicker: {
111
134
  pickDate: "Pick a date",
@@ -175,9 +198,9 @@ var DEFAULTS = {
175
198
  top: "Top",
176
199
  clearSelection: "Clear selection",
177
200
  copyLines: (count) => count === 1 ? "Copy 1 line" : `Copy ${count} lines`,
178
- copyAll: "Copy All",
179
- hideDebug: "Hide Debug",
180
- showDebug: "Show Debug",
201
+ copyAll: "Copy all",
202
+ hideDebug: "Hide debug",
203
+ showDebug: "Show debug",
181
204
  filterLogs: "Filter logs",
182
205
  beginningOfLog: "Beginning of log",
183
206
  loadingOlderEntries: "Loading older entries…",
@@ -194,7 +217,8 @@ var DEFAULTS = {
194
217
  endBeforeStart: "End time must be after the start time.",
195
218
  endInFuture: "End time cannot be in the future.",
196
219
  follow: "Follow",
197
- following: "Following"
220
+ following: "Following",
221
+ selectLine: (line) => `Select line ${line}`
198
222
  },
199
223
  dag: {
200
224
  workflow: "Workflow",
@@ -202,7 +226,7 @@ var DEFAULTS = {
202
226
  status: "Status",
203
227
  runtime: "Runtime",
204
228
  submitted: "Submitted",
205
- resetView: "Reset View",
229
+ resetView: "Reset view",
206
230
  previousGraph: "Back to the previous graph",
207
231
  nextGraph: "Forward to the next graph",
208
232
  matrixOf: (name) => `Matrix: ${name}`,
@@ -226,6 +250,23 @@ var DEFAULTS = {
226
250
  warning: "Warning",
227
251
  notice: "Notice"
228
252
  },
253
+ annotationsLabel: ({ error, warning, notice }) => `Annotations: ${[
254
+ [
255
+ error,
256
+ "error",
257
+ "errors"
258
+ ],
259
+ [
260
+ warning,
261
+ "warning",
262
+ "warnings"
263
+ ],
264
+ [
265
+ notice,
266
+ "notice",
267
+ "notices"
268
+ ]
269
+ ].filter(([count]) => count).map(([count, one, many]) => `${count} ${count === 1 ? one : many}`).join(", ")}`,
229
270
  annotationSource: (job, step) => `in ${job} → ${step}`,
230
271
  stepNumber: (index) => `step ${index}`
231
272
  },
@@ -249,7 +290,7 @@ var DEFAULTS = {
249
290
  preview: "Preview",
250
291
  openFullPreview: "Open full preview",
251
292
  previewLayout: "Preview layout",
252
- quickLook: "Quick Look",
293
+ compact: "Compact",
253
294
  fullWindow: "Full window",
254
295
  streamed: "Streamed",
255
296
  streamedTooltip: "Streamed securely to your browser over a short-lived signed URL — never written to disk.",
@@ -297,12 +338,12 @@ var DEFAULTS = {
297
338
  uri: "URI",
298
339
  cors: {
299
340
  explanation: {
300
- title: "CORS Configuration Required",
341
+ title: "CORS configuration required",
301
342
  description: "This storage location cannot be accessed from the browser because it is missing Cross-Origin Resource Sharing (CORS) rules.",
302
343
  action: "You can automatically configure these rules to allow access from this domain.",
303
344
  note: "Note: Changes may take up to 30 seconds to propagate."
304
345
  },
305
- actions: { addRules: "Add CORS Rules" },
346
+ actions: { addRules: "Add CORS rules" },
306
347
  propagating: {
307
348
  title: "Propagating CORS rules",
308
349
  description: "The storage provider is rolling out the new rules to its endpoints. This usually completes within a minute.",
@@ -340,7 +381,7 @@ var DEFAULTS = {
340
381
  noItemsForDeletion: "No items selected for deletion.",
341
382
  deleting: "Deleting item(s) from storage...",
342
383
  deleteSomeFailed: "Failed to delete one or more items. Please try again.",
343
- deleteSuccess: "Deleted item(s) from storage successfully!",
384
+ deleteSuccess: "Deleted from storage.",
344
385
  deleteFailed: (message) => `Failed to delete item(s): ${message}`,
345
386
  noFilesToUpload: "No files to upload or target path not selected.",
346
387
  invalidUploadTarget: "This target path is not valid for upload.",
@@ -350,14 +391,16 @@ var DEFAULTS = {
350
391
  corsNoStorage: "No storage selected",
351
392
  corsAdded: "CORS rules added successfully",
352
393
  corsPropagating: "CORS rules were added, but are still propagating. Try again in a moment.",
353
- previewUnsupported: "Preview is not supported for this storage."
394
+ previewUnsupported: "Preview is not supported for this storage.",
395
+ loadFailed: (name, message) => `Failed to load contents for ${name}: ${message}`,
396
+ unknownError: "Unknown error"
354
397
  },
355
398
  chrome: {
356
399
  explorer: "Explorer",
357
400
  upload: "Upload",
358
401
  downloadFromBrowser: "From browser",
359
402
  access: "Access",
360
- manageAccess: "Manage Access",
403
+ manageAccess: "Manage access",
361
404
  selectAll: "Select all",
362
405
  name: "Name",
363
406
  size: "Size",
@@ -372,21 +415,25 @@ var DEFAULTS = {
372
415
  storageClass: "Storage class",
373
416
  details: "Details",
374
417
  selectFiles: "Select files",
375
- selectFolder: "Select folder"
418
+ selectFolder: "Select folder",
419
+ files: "Files",
420
+ folders: "Folders",
421
+ location: "Location",
422
+ shareHelp: "This will generate a pre-signed URL for this file. Anyone with this link can temporarily access and download the file, even if they don't have an account. The link will automatically expire after 12 hours."
376
423
  },
377
424
  confirmUpload: {
378
- title: "Confirm Upload",
425
+ title: "Confirm upload",
379
426
  text: (path) => `Please confirm the following objects you want to upload to ${path}.`,
380
427
  defaultPath: "the selected path",
381
428
  noPath: "No path selected",
382
429
  confirm: "Confirm",
383
430
  target: "Target:",
384
- sizeLimitTitle: "Upload Size Limit Exceeded",
431
+ sizeLimitTitle: "Upload size limit exceeded",
385
432
  sizeLimitBody: (total, max) => `The total upload size (${total}) exceeds the maximum allowed limit of ${max}.`,
386
433
  sizeLimitHint: "Please reduce the number of files or upload them in smaller batches."
387
434
  },
388
435
  confirmDelete: {
389
- title: "Confirm Delete",
436
+ title: "Confirm delete",
390
437
  text: "Are you sure you want to delete the following item(s)? Folders are deleted with everything inside them. This action cannot be undone."
391
438
  },
392
439
  empty: {
@@ -399,14 +446,14 @@ var DEFAULTS = {
399
446
  shareThisFile: "Share this file"
400
447
  },
401
448
  upload: {
402
- inQueue: (position, total) => `In Queue (#${position} of ${total})`,
449
+ inQueue: (position, total) => `In queue (#${position} of ${total})`,
403
450
  queuedShort: (position, total) => `Queued #${position} / ${total}`,
404
451
  destination: "Destination:",
405
452
  eta: "ETA:",
406
453
  uploading: "Uploading...",
407
- completeTitle: "Upload Complete!",
408
- failedTitle: "Upload Failed",
409
- unknownTitle: "Unknown Status",
454
+ completeTitle: "Upload complete",
455
+ failedTitle: "Upload failed",
456
+ unknownTitle: "Unknown status",
410
457
  unknownShort: "Unknown",
411
458
  canceled: "Canceled",
412
459
  completed: "Completed",
@@ -419,14 +466,14 @@ var DEFAULTS = {
419
466
  minimizeDetails: "Minimize details",
420
467
  sessionNotQueued: (id, status) => `Upload session with ID ${id} is not queued, current status is ${status}`,
421
468
  allCanceled: (count) => `All ${count} file(s) were canceled by user.`,
422
- someUploaded: (count) => `${count} file(s) uploaded successfully!`,
469
+ someUploaded: (count) => `${count} file(s) uploaded.`,
423
470
  someCanceled: (count) => `${count} file(s) canceled by user.`,
424
- allUploaded: "Upload file(s) successfully!",
471
+ allUploaded: "Uploaded the file(s).",
425
472
  failedSummary: (failed, total) => `${failed}/${total} files failed to upload:`,
426
473
  failReasonGeneric: "The file(s) may be too large or the connection may have been interrupted.",
427
474
  refreshFailed: (name, message) => `Failed to refresh storage data for ${name}. ${message}. Please try again.`,
428
475
  unknownError: "Unknown error",
429
- overallProgress: "Overall Progress",
476
+ overallProgress: "Overall progress",
430
477
  cancelFile: (name) => `Cancel ${name}`,
431
478
  confirmCancelFile: "Cancel?",
432
479
  confirmCancelAll: "Cancel all uploading files?",
@@ -450,8 +497,6 @@ var DEFAULTS = {
450
497
  allSteps: "All steps",
451
498
  stepDone: "Done",
452
499
  stepNeedsAttention: "Needs a fix",
453
- previousStep: "Go to previous step",
454
- nextStep: "Go to next step",
455
500
  runWizard: "Execute",
456
501
  fixErrorsToContinue: "Please fix errors before proceeding",
457
502
  stepFailed: "An error occurred",
@@ -473,6 +518,9 @@ var DEFAULTS = {
473
518
  labelId: "ID",
474
519
  labelUrl: "URL",
475
520
  couldNotLoad: (noun) => `Couldn't load ${noun}`,
521
+ data: "data",
522
+ count: (count, noun) => `${count} ${noun}`,
523
+ matchCount: (matches, total, nounPlural) => `${matches} of ${total} ${nounPlural}`,
476
524
  displayOptions: "Display options",
477
525
  grouping: "Grouping",
478
526
  ordering: "Ordering",
@@ -482,6 +530,7 @@ var DEFAULTS = {
482
530
  descending: "Descending",
483
531
  columnHeaders: "Column headers",
484
532
  showColumnHeaders: "Show column headers",
533
+ selectAll: "Select all",
485
534
  showActions: "Show actions",
486
535
  showRowActions: "Show row actions",
487
536
  alwaysShowActions: "Always show actions",
@@ -519,28 +568,32 @@ var DEFAULTS = {
519
568
  },
520
569
  slots: {}
521
570
  };
522
- var UIContext = createContext(DEFAULTS);
571
+ var StringsContext = createContext(DEFAULTS.strings);
572
+ var NavigationContext = createContext(DEFAULTS.navigation);
573
+ var DataContext = createContext(DEFAULTS.data);
574
+ var SlotsContext = createContext(DEFAULTS.slots);
575
+ var EngineContext = createContext(void 0);
523
576
  function useStrings() {
524
- return useContext(UIContext).strings;
577
+ return useContext(StringsContext);
525
578
  }
526
579
  function useNavigation() {
527
- return useContext(UIContext).navigation;
580
+ return useContext(NavigationContext);
528
581
  }
529
582
  function useWorkflowJsonResolver() {
530
- return useContext(UIContext).data.resolveWorkflowJson;
583
+ return useContext(DataContext).resolveWorkflowJson;
531
584
  }
532
585
  function useRepoSuggestions() {
533
- return useContext(UIContext).data.repoSuggestions;
586
+ return useContext(DataContext).repoSuggestions;
534
587
  }
535
588
  var NO_ACTIONS = {};
536
589
  function useWorkflowActions() {
537
- return useContext(UIContext).data.workflowActions ?? NO_ACTIONS;
590
+ return useContext(DataContext).workflowActions ?? NO_ACTIONS;
538
591
  }
539
592
  function useSecretVariablesResolver() {
540
- return useContext(UIContext).data.resolveSecretVariables;
593
+ return useContext(DataContext).resolveSecretVariables;
541
594
  }
542
595
  function useSlots() {
543
- return useContext(UIContext).slots;
596
+ return useContext(SlotsContext);
544
597
  }
545
598
  var loadedEngines = /* @__PURE__ */ new WeakMap();
546
599
  function loadEngine(load) {
@@ -562,18 +615,18 @@ function resolveEngine(source) {
562
615
  }
563
616
  /** The engine when one is provided and `enabled`; suspends while a loader resolves. */
564
617
  function useOptionalWorkflowEngine(enabled = true) {
565
- const source = useContext(UIContext).engine;
618
+ const source = useContext(EngineContext);
566
619
  if (!enabled || !source) return;
567
620
  return resolveEngine(source);
568
621
  }
569
622
  function useWorkflowEngine() {
570
- const source = useContext(UIContext).engine;
623
+ const source = useContext(EngineContext);
571
624
  if (!source) throw new Error("Workflow forms and graphs need a UIProvider with an engine.");
572
625
  return resolveEngine(source);
573
626
  }
574
627
  /** The engine once it has loaded, without suspending; renders again when a loader resolves. */
575
628
  function useLoadedWorkflowEngine() {
576
- const source = useContext(UIContext).engine;
629
+ const source = useContext(EngineContext);
577
630
  const [, setLoaded] = useState(0);
578
631
  const entry = typeof source === "function" ? loadEngine(source) : void 0;
579
632
  const engine = typeof source === "function" ? entry?.engine : source;
@@ -597,114 +650,71 @@ function useWorkflowEditing() {
597
650
  }
598
651
  /** Resolves the engine without suspending, for async callers such as editor completions. */
599
652
  function useWorkflowEngineLoader() {
600
- const source = useContext(UIContext).engine;
653
+ const source = useContext(EngineContext);
601
654
  return useCallback(async () => {
602
655
  if (!source) return;
603
656
  return typeof source === "function" ? loadEngine(source).promise : source;
604
657
  }, [source]);
605
658
  }
606
659
  function useProvisionCorsRules() {
607
- return useContext(UIContext).data.provisionCorsRules;
660
+ return useContext(DataContext).provisionCorsRules;
608
661
  }
609
662
  function useRunFile(slug, path, options) {
610
- const { useRunFile: boundUseRunFile } = useContext(UIContext).data;
663
+ const { useRunFile: boundUseRunFile } = useContext(DataContext);
611
664
  return boundUseRunFile(slug, path, options);
612
665
  }
613
666
  function usePersistedState(key, defaultValue) {
614
- const { usePersistedState: boundUsePersistedState } = useContext(UIContext).data;
667
+ const { usePersistedState: boundUsePersistedState } = useContext(DataContext);
615
668
  return boundUsePersistedState(key, defaultValue);
616
669
  }
617
- function UIProvider({ strings, navigation, data, slots, engine, children }) {
670
+ function useByValue(value) {
671
+ const ref = useRef(value);
672
+ if (ref.current !== value && !dequal(ref.current, value)) ref.current = value;
673
+ return ref.current;
674
+ }
675
+ function useMerged(compute, input) {
676
+ const stableInput = useByValue(input);
677
+ const ref = useRef(null);
678
+ if (!ref.current || ref.current.input !== stableInput) ref.current = {
679
+ input: stableInput,
680
+ value: compute()
681
+ };
682
+ return ref.current.value;
683
+ }
684
+ function UIProvider({ strings, navigation, data, slots, engine: engineProp, children }) {
685
+ const [firstLoader] = useState(() => typeof engineProp === "function" ? engineProp : void 0);
686
+ const engine = typeof engineProp === "function" ? firstLoader ?? engineProp : engineProp;
618
687
  useEffect(() => {
619
688
  if (typeof engine === "function") loadEngine(engine);
620
689
  }, [engine]);
621
- const value = useMemo(() => ({
622
- strings: {
623
- modal: {
624
- ...DEFAULTS.strings.modal,
625
- ...strings?.modal
626
- },
627
- common: {
628
- ...DEFAULTS.strings.common,
629
- ...strings?.common
630
- },
631
- dropdown: {
632
- ...DEFAULTS.strings.dropdown,
633
- ...strings?.dropdown
634
- },
635
- datePicker: {
636
- ...DEFAULTS.strings.datePicker,
637
- ...strings?.datePicker
638
- },
639
- colorInput: {
640
- ...DEFAULTS.strings.colorInput,
641
- ...strings?.colorInput
642
- },
643
- oneTimeCode: {
644
- ...DEFAULTS.strings.oneTimeCode,
645
- ...strings?.oneTimeCode
646
- },
647
- theme: {
648
- ...DEFAULTS.strings.theme,
649
- ...strings?.theme
650
- },
651
- logviewer: {
652
- ...DEFAULTS.strings.logviewer,
653
- ...strings?.logviewer
654
- },
655
- dag: {
656
- ...DEFAULTS.strings.dag,
657
- ...strings?.dag
658
- },
659
- jobActions: {
660
- ...DEFAULTS.strings.jobActions,
661
- ...strings?.jobActions
662
- },
663
- graphEditor: {
664
- ...DEFAULTS.strings.graphEditor,
665
- ...strings?.graphEditor
666
- },
667
- inputsEditor: {
668
- ...DEFAULTS.strings.inputsEditor,
669
- ...strings?.inputsEditor
670
- },
671
- fileExplorer: {
672
- ...DEFAULTS.strings.fileExplorer,
673
- ...strings?.fileExplorer
674
- },
675
- form: {
676
- ...DEFAULTS.strings.form,
677
- ...strings?.form
678
- },
679
- time: {
680
- ...DEFAULTS.strings.time,
681
- ...strings?.time
682
- },
683
- list: {
684
- ...DEFAULTS.strings.list,
685
- ...strings?.list
686
- }
687
- },
688
- navigation: {
689
- ...DEFAULTS.navigation,
690
- ...navigation
691
- },
692
- data: {
693
- ...DEFAULTS.data,
694
- ...data
695
- },
696
- slots: slots ?? DEFAULTS.slots,
697
- engine
698
- }), [
699
- strings,
700
- navigation,
701
- data,
702
- slots,
703
- engine
704
- ]);
705
- return /* @__PURE__ */ jsxs(UIContext.Provider, {
706
- value,
707
- children: [/* @__PURE__ */ jsx(TooltipProvider, { children }), /* @__PURE__ */ jsx(Toaster, {})]
690
+ const mergedStrings = useMerged(() => mergeStrings(DEFAULTS.strings, strings), strings);
691
+ const mergedData = useMerged(() => ({
692
+ ...DEFAULTS.data,
693
+ ...data
694
+ }), data);
695
+ const stableSlots = useByValue(slots ?? DEFAULTS.slots);
696
+ const navigationRef = useRef(navigation);
697
+ navigationRef.current = navigation;
698
+ const [stableNavigation] = useState(() => ({
699
+ goTo: (to) => (navigationRef.current?.goTo ?? DEFAULTS.navigation.goTo)(to),
700
+ openStepSource: (uses, sourceUrl) => (navigationRef.current?.openStepSource ?? DEFAULTS.navigation.openStepSource)(uses, sourceUrl),
701
+ openExternal: (href) => (navigationRef.current?.openExternal ?? DEFAULTS.navigation.openExternal)(href)
702
+ }));
703
+ return /* @__PURE__ */ jsx(StringsContext, {
704
+ value: mergedStrings,
705
+ children: /* @__PURE__ */ jsx(NavigationContext, {
706
+ value: stableNavigation,
707
+ children: /* @__PURE__ */ jsx(DataContext, {
708
+ value: mergedData,
709
+ children: /* @__PURE__ */ jsx(SlotsContext, {
710
+ value: stableSlots,
711
+ children: /* @__PURE__ */ jsxs(EngineContext, {
712
+ value: engine,
713
+ children: [/* @__PURE__ */ jsx(TooltipProvider, { children }), /* @__PURE__ */ jsx(Toaster, {})]
714
+ })
715
+ })
716
+ })
717
+ })
708
718
  });
709
719
  }
710
720
  //#endregion
@@ -1,4 +1,5 @@
1
1
  import { cx } from "../cx.js";
2
+ import { focusOutline } from "./fieldBox.js";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  import { Radio } from "@base-ui/react/radio";
4
5
  import { RadioGroup } from "@base-ui/react/radio-group";
@@ -8,7 +9,7 @@ import { RadioGroup } from "@base-ui/react/radio-group";
8
9
  function Radio$1({ className, ...props }) {
9
10
  return /* @__PURE__ */ jsx(Radio.Root, {
10
11
  ...props,
11
- className: cx("flex size-4 shrink-0 items-center justify-center rounded-full border border-(--theme-border) bg-(--theme-input-bg) cursor-pointer outline-none transition-colors", "data-checked:border-(--theme-accent) data-checked:bg-(--theme-accent)", "focus-visible:ring-2 focus-visible:ring-(--theme-focus-ring) aria-invalid:border-(--theme-error)", "data-disabled:cursor-not-allowed data-disabled:opacity-50", className),
12
+ className: cx("flex size-4 shrink-0 items-center justify-center rounded-full border border-(--theme-border-strong) bg-(--theme-input-bg) cursor-pointer transition-colors motion-reduce:transition-none", focusOutline, "data-checked:border-(--theme-accent) data-checked:bg-(--theme-accent)", "aria-invalid:border-(--theme-error)", "data-disabled:cursor-not-allowed data-disabled:opacity-50", className),
12
13
  children: /* @__PURE__ */ jsx(Radio.Indicator, { className: "size-1.5 rounded-full bg-(--theme-accent-text)" })
13
14
  });
14
15
  }
@@ -1,20 +1,16 @@
1
1
  import { cx } from "../cx.js";
2
- import { RefreshIcon } from "../icons.js";
3
2
  import { buttonClasses } from "./buttonClasses.js";
3
+ import { RefreshIcon } from "../icons.js";
4
4
  import { Tooltip } from "./Tooltip.js";
5
5
  import { useStrings } from "./Provider.js";
6
6
  import { useRelativeTime } from "./relativeTime.js";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
- import { useEffect, useRef, useState } from "react";
8
+ import { useState } from "react";
9
9
  //#region src/components/RefreshButton.tsx
10
10
  /** Fetches again on demand, and says so while it does, out loud too. */
11
11
  function RefreshButton({ onRefresh, refreshing = false, updatedAt, size = "md", iconOnly = false }) {
12
12
  const { common: t } = useStrings();
13
13
  const [pending, setPending] = useState(false);
14
- const mounted = useRef(true);
15
- useEffect(() => () => {
16
- mounted.current = false;
17
- }, []);
18
14
  const busy = refreshing || pending;
19
15
  const ago = useRelativeTime(updatedAt);
20
16
  const refresh = () => {
@@ -22,7 +18,7 @@ function RefreshButton({ onRefresh, refreshing = false, updatedAt, size = "md",
22
18
  const result = onRefresh();
23
19
  if (result instanceof Promise) {
24
20
  setPending(true);
25
- result.finally(() => mounted.current && setPending(false));
21
+ result.finally(() => setPending(false));
26
22
  }
27
23
  };
28
24
  const button = /* @__PURE__ */ jsxs("button", {
@@ -38,7 +34,10 @@ function RefreshButton({ onRefresh, refreshing = false, updatedAt, size = "md",
38
34
  children: [/* @__PURE__ */ jsx(RefreshIcon, {
39
35
  "aria-hidden": "true",
40
36
  className: cx("shrink-0 motion-reduce:animate-none motion-reduce:transition-none", busy ? "animate-spin" : "transition-transform duration-300 group-hover:rotate-180")
41
- }), !iconOnly && (ago ? t.updated(ago) : t.refresh)]
37
+ }), !iconOnly && (ago ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
38
+ className: "sr-only",
39
+ children: [t.refresh, ". "]
40
+ }), t.updated(ago)] }) : t.refresh)]
42
41
  });
43
42
  return /* @__PURE__ */ jsxs(Fragment, { children: [iconOnly ? /* @__PURE__ */ jsx(Tooltip, {
44
43
  content: t.refresh,
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
3
3
  function RequiredMark() {
4
4
  return /* @__PURE__ */ jsx("span", {
5
5
  "aria-hidden": "true",
6
- className: "text-red-500 ml-0.5",
6
+ className: "ml-0.5 text-(--theme-error-text)",
7
7
  children: "*"
8
8
  });
9
9
  }
@@ -1,6 +1,6 @@
1
1
  import { cx } from "../cx.js";
2
2
  import { CancelIcon, FailIcon, NotRunningIcon, RunningIcon, SkipIcon, SuccessIcon } from "../icons.js";
3
- import { toneText } from "./tone.js";
3
+ import { toneIcon } from "./tone.js";
4
4
  import { useStrings } from "./Provider.js";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region src/components/RunStatusIcon.tsx
@@ -73,7 +73,7 @@ function RunStatusIcon({ status, className }) {
73
73
  "aria-label": label
74
74
  } : { "aria-hidden": true },
75
75
  "data-status": status || "not-run",
76
- className: cx("flex h-2 items-center", toneText[look.tone], className),
76
+ className: cx("flex h-2 items-center", toneIcon[look.tone], className),
77
77
  children: /* @__PURE__ */ jsx(Icon, {
78
78
  "aria-hidden": "true",
79
79
  className: cx(look.spin && "animate-spin rounded-full")
@@ -75,7 +75,7 @@ function Section({ title, description, beside, actions, variant = "plain", colla
75
75
  children: /* @__PURE__ */ jsxs(Collapsible.Trigger, {
76
76
  ...titleProps,
77
77
  "aria-describedby": describedBy,
78
- className: cx("group flex min-w-0 cursor-pointer items-center gap-1 text-left", fill && "w-full", titleClasses[variant], foldedTitleClasses[variant]),
78
+ className: cx("group flex min-w-0 cursor-pointer items-center gap-1 rounded-sm text-left focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--theme-focus)", fill && "w-full", titleClasses[variant], foldedTitleClasses[variant]),
79
79
  children: [/* @__PURE__ */ jsx(ChevronRightIcon, {
80
80
  "aria-hidden": "true",
81
81
  className: cx("shrink-0 transition-transform group-data-panel-open:rotate-90 motion-reduce:transition-none", "px-1 text-[1.25rem]")
@@ -1,14 +1,9 @@
1
1
  import { Select as BaseSelect } from '@base-ui/react/select';
2
- import type { ReactElement, ReactNode } from 'react';
2
+ import { type ReactElement, type ReactNode } from 'react';
3
+ import { type ComboboxItem } from './comboboxItems.js';
3
4
  import { type FieldBoxSize } from './fieldBox.js';
4
- export interface SelectItem<Value> {
5
- value: Value;
6
- label: string;
7
- /** A second line under the label, such as what an option does. */
8
- description?: string | undefined;
9
- icon?: ReactNode;
10
- disabled?: boolean | undefined;
11
- }
5
+ /** An option of a Select: the same shape as a Combobox's, so a list moves between them as is. */
6
+ export type SelectItem<Value> = ComboboxItem<Value>;
12
7
  export type SelectProps<Value, Multiple extends boolean | undefined = false> = Omit<BaseSelect.Root.Props<Value, Multiple>, 'items' | 'children'> & {
13
8
  items: readonly SelectItem<Value>[];
14
9
  placeholder?: string | undefined;