@parallelworks/ui 0.41.0 → 0.42.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 (280) hide show
  1. package/README.md +25 -0
  2. package/dist/ai/components/AllocationSelector.d.ts +3 -4
  3. package/dist/ai/components/AllocationSelector.js +37 -33
  4. package/dist/ai/components/AttachmentManager.js +7 -7
  5. package/dist/ai/components/AttachmentUpload.js +5 -5
  6. package/dist/ai/components/BranchNavigator.js +1 -1
  7. package/dist/ai/components/ChatEmptyState.js +2 -2
  8. package/dist/ai/components/ChatInput.js +10 -8
  9. package/dist/ai/components/ChatLayout.js +4 -5
  10. package/dist/ai/components/ChatMessage.js +12 -12
  11. package/dist/ai/components/ChatMessageList.js +9 -9
  12. package/dist/ai/components/ChatSidebar.js +8 -9
  13. package/dist/ai/components/ChatThread.js +4 -4
  14. package/dist/ai/components/ComposerChrome.d.ts +2 -2
  15. package/dist/ai/components/ComposerChrome.js +3 -6
  16. package/dist/ai/components/DragOverlay.js +2 -2
  17. package/dist/ai/components/ModelSelector.d.ts +5 -3
  18. package/dist/ai/components/ModelSelector.js +102 -339
  19. package/dist/ai/components/PastedText.js +11 -11
  20. package/dist/ai/components/ProviderIssueBanner.d.ts +2 -0
  21. package/dist/ai/components/ProviderIssueBanner.js +34 -16
  22. package/dist/ai/components/Reasoning.js +4 -4
  23. package/dist/ai/components/ShareDialog.js +43 -35
  24. package/dist/ai/components/SlashMenu.d.ts +12 -2
  25. package/dist/ai/components/SlashMenu.js +29 -13
  26. package/dist/ai/components/agent/ActivityLine.js +3 -3
  27. package/dist/ai/components/agent/AgentMessageParts.js +20 -20
  28. package/dist/ai/components/agent/PermissionPicker.js +13 -11
  29. package/dist/ai/components/conversationActions.d.ts +4 -6
  30. package/dist/ai/components/conversationActions.js +9 -13
  31. package/dist/ai/core/ChatProvider.js +1 -1
  32. package/dist/ai/core/config.js +1 -1
  33. package/dist/ai/core/providerIssues.d.ts +7 -0
  34. package/dist/ai/core/providerIssues.js +9 -1
  35. package/dist/ai/core/useKeyboardShortcuts.d.ts +4 -0
  36. package/dist/ai/core/useKeyboardShortcuts.js +8 -2
  37. package/dist/ai/index.d.ts +0 -1
  38. package/dist/ai/index.js +1 -2
  39. package/dist/ai/strings.d.ts +19 -0
  40. package/dist/ai/strings.js +18 -1
  41. package/dist/ai/ui/Avatar.js +5 -5
  42. package/dist/ai/ui/ConversationSidebar.d.ts +0 -1
  43. package/dist/ai/ui/ConversationSidebar.js +6 -7
  44. package/dist/ai/ui/Markdown.js +3 -3
  45. package/dist/ai/ui/Notice.js +6 -6
  46. package/dist/ai/ui/chip.d.ts +4 -0
  47. package/dist/ai/ui/chip.js +8 -0
  48. package/dist/ai/ui/sidebar.d.ts +6 -5
  49. package/dist/ai/ui/sidebar.js +39 -43
  50. package/dist/components/ActionMenu.d.ts +13 -0
  51. package/dist/components/ActionMenu.js +30 -0
  52. package/dist/components/Avatar.js +6 -6
  53. package/dist/components/Breadcrumbs.js +1 -1
  54. package/dist/components/Button.js +10 -10
  55. package/dist/components/Callout.js +2 -2
  56. package/dist/components/Card.js +3 -3
  57. package/dist/components/Combobox.d.ts +66 -0
  58. package/dist/components/Combobox.js +393 -0
  59. package/dist/components/ConfirmModal.js +11 -11
  60. package/dist/components/ContextMenu.d.ts +23 -0
  61. package/dist/components/ContextMenu.js +89 -0
  62. package/dist/components/CopyToClipboard.js +2 -2
  63. package/dist/components/CreateModal.d.ts +17 -36
  64. package/dist/components/CreateModal.js +97 -259
  65. package/dist/components/DescriptionList.js +8 -8
  66. package/dist/components/Filter.js +2 -2
  67. package/dist/components/FilterPill.js +2 -2
  68. package/dist/components/HoverCard.d.ts +14 -0
  69. package/dist/components/HoverCard.js +33 -0
  70. package/dist/components/IconButton.d.ts +5 -5
  71. package/dist/components/IconButton.js +18 -22
  72. package/dist/components/InfoTip.d.ts +15 -0
  73. package/dist/components/InfoTip.js +60 -0
  74. package/dist/components/Input.js +5 -5
  75. package/dist/components/LetterBadge.js +2 -2
  76. package/dist/components/Loader.js +3 -3
  77. package/dist/components/Markdown.js +1 -1
  78. package/dist/components/MarkdownImpl.js +2 -2
  79. package/dist/components/Menu.d.ts +33 -0
  80. package/dist/components/Menu.js +86 -0
  81. package/dist/components/MenuEntries.d.ts +56 -0
  82. package/dist/components/MenuEntries.js +123 -0
  83. package/dist/components/Modal.d.ts +29 -0
  84. package/dist/components/Modal.js +47 -0
  85. package/dist/components/Overview.js +11 -10
  86. package/dist/components/PageHeader.d.ts +10 -16
  87. package/dist/components/PageHeader.js +69 -95
  88. package/dist/components/Pagination.js +5 -5
  89. package/dist/components/Provider.d.ts +5 -11
  90. package/dist/components/Provider.js +11 -14
  91. package/dist/components/Radio.d.ts +8 -0
  92. package/dist/components/Radio.js +16 -0
  93. package/dist/components/SectionHeader.js +2 -2
  94. package/dist/components/SegmentedControl.d.ts +6 -5
  95. package/dist/components/SegmentedControl.js +34 -30
  96. package/dist/components/Select.d.ts +27 -0
  97. package/dist/components/Select.js +78 -0
  98. package/dist/components/SettingModeOption.d.ts +5 -8
  99. package/dist/components/SettingModeOption.js +10 -12
  100. package/dist/components/SettingRow.js +4 -4
  101. package/dist/components/SettingsCard.js +4 -4
  102. package/dist/components/SettingsGroup.js +2 -2
  103. package/dist/components/Sort.js +1 -1
  104. package/dist/components/StatusBadge.js +7 -7
  105. package/dist/components/StatusIcons.js +4 -4
  106. package/dist/components/Switch.d.ts +22 -0
  107. package/dist/components/Switch.js +28 -0
  108. package/dist/components/Table.js +11 -11
  109. package/dist/components/Tooltip.d.ts +24 -20
  110. package/dist/components/Tooltip.js +58 -76
  111. package/dist/components/floating.d.ts +14 -0
  112. package/dist/components/floating.js +21 -0
  113. package/dist/components/search.d.ts +2 -0
  114. package/dist/components/search.js +14 -0
  115. package/dist/editor/Editor.js +1 -1
  116. package/dist/editor/EditorField.js +16 -21
  117. package/dist/editor/FormCodePanel.js +19 -19
  118. package/dist/editor/Monaco.js +3 -3
  119. package/dist/file-explorer/FileExplorer.js +77 -81
  120. package/dist/file-explorer/FileExplorerContext.js +2 -2
  121. package/dist/file-explorer/FilePreview/CodePreviewEditor.js +1 -1
  122. package/dist/file-explorer/FilePreview/Inline.js +1 -1
  123. package/dist/file-explorer/FilePreview/StreamedBadge.js +5 -6
  124. package/dist/file-explorer/FilePreview/Viewer.js +8 -8
  125. package/dist/file-explorer/FilePreview/index.d.ts +1 -1
  126. package/dist/file-explorer/FilePreview/index.js +49 -83
  127. package/dist/file-explorer/FileRow.d.ts +4 -3
  128. package/dist/file-explorer/FileRow.js +32 -38
  129. package/dist/file-explorer/FileRowsWindow.d.ts +3 -2
  130. package/dist/file-explorer/FileRowsWindow.js +4 -4
  131. package/dist/file-explorer/FileTable.d.ts +3 -2
  132. package/dist/file-explorer/FileTable.js +3 -3
  133. package/dist/file-explorer/LoadMoreRow.js +1 -1
  134. package/dist/file-explorer/TreeView.js +11 -16
  135. package/dist/file-explorer/helpers.js +11 -12
  136. package/dist/file-explorer/toasts.js +11 -11
  137. package/dist/form/FieldGroup.d.ts +11 -0
  138. package/dist/form/FieldGroup.js +36 -0
  139. package/dist/form/FieldWrapper.js +4 -4
  140. package/dist/form/Fields/BooleanField.js +23 -33
  141. package/dist/form/Fields/CheckboxGroupField.d.ts +1 -1
  142. package/dist/form/Fields/CheckboxGroupField.js +9 -13
  143. package/dist/form/Fields/ColorField.d.ts +1 -2
  144. package/dist/form/Fields/ColorField.js +6 -11
  145. package/dist/form/Fields/DropdownField.d.ts +3 -13
  146. package/dist/form/Fields/DropdownField.js +40 -27
  147. package/dist/form/Fields/DurationField.d.ts +1 -2
  148. package/dist/form/Fields/DurationField.js +25 -32
  149. package/dist/form/Fields/LabelField.js +2 -2
  150. package/dist/form/Fields/MultiDropdownField.d.ts +6 -12
  151. package/dist/form/Fields/MultiDropdownField.js +31 -22
  152. package/dist/form/Fields/NumberField.d.ts +1 -1
  153. package/dist/form/Fields/NumberField.js +65 -35
  154. package/dist/form/Fields/ObjectField.d.ts +1 -1
  155. package/dist/form/Fields/ObjectField.js +12 -43
  156. package/dist/form/Fields/RadioField.d.ts +1 -1
  157. package/dist/form/Fields/RadioField.js +30 -41
  158. package/dist/form/Fields/RangeField.d.ts +1 -2
  159. package/dist/form/Fields/RangeField.js +23 -16
  160. package/dist/form/Fields/StringField.d.ts +1 -2
  161. package/dist/form/Fields/StringField.js +58 -26
  162. package/dist/form/Fields/TextAreaField.js +12 -10
  163. package/dist/form/Form.d.ts +30 -48
  164. package/dist/form/Form.js +306 -412
  165. package/dist/form/FormLayout.js +9 -9
  166. package/dist/form/Wizard/WizardContainer.d.ts +1 -4
  167. package/dist/form/Wizard/WizardContainer.js +40 -56
  168. package/dist/form/Wizard/WizardNavigation.js +1 -1
  169. package/dist/form/Wizard/WizardStepContent.d.ts +1 -5
  170. package/dist/form/Wizard/WizardStepContent.js +11 -16
  171. package/dist/form/Wizard/WizardStepIndicator.js +6 -6
  172. package/dist/form/Wizard/types.d.ts +0 -14
  173. package/dist/form/fieldRegistry.d.ts +1 -1
  174. package/dist/form/fieldRegistry.js +6 -6
  175. package/dist/form/formEditing.js +1 -1
  176. package/dist/form/index.d.ts +5 -4
  177. package/dist/form/index.js +6 -7
  178. package/dist/form/types/fieldComponentTypes.d.ts +8 -10
  179. package/dist/form/useChoiceField.d.ts +20 -0
  180. package/dist/form/useChoiceField.js +49 -0
  181. package/dist/form/useFieldValue.d.ts +7 -0
  182. package/dist/form/useFieldValue.js +20 -0
  183. package/dist/form/useParsedOpts.d.ts +3 -1
  184. package/dist/form/useParsedOpts.js +12 -17
  185. package/dist/form/utils/dependentOptions.d.ts +8 -4
  186. package/dist/form/utils/dependentOptions.js +25 -17
  187. package/dist/form/utils/fieldItems.d.ts +10 -0
  188. package/dist/form/utils/fieldItems.js +11 -0
  189. package/dist/form/utils/fieldPath.d.ts +10 -0
  190. package/dist/form/utils/fieldPath.js +20 -0
  191. package/dist/form/utils/shareEqual.d.ts +6 -0
  192. package/dist/form/utils/shareEqual.js +38 -0
  193. package/dist/graph/AnnotationBanner.js +8 -8
  194. package/dist/graph/Collapse.d.ts +1 -0
  195. package/dist/graph/Collapse.js +6 -27
  196. package/dist/graph/Connectors.js +5 -5
  197. package/dist/graph/DependencyGraph.js +20 -19
  198. package/dist/graph/GraphEditor.js +30 -41
  199. package/dist/graph/GraphEditorDialogs.js +17 -17
  200. package/dist/graph/GraphNode.js +1 -1
  201. package/dist/graph/InputDialog.js +19 -22
  202. package/dist/graph/InputsEditor.js +58 -66
  203. package/dist/graph/JobSummary.js +42 -39
  204. package/dist/graph/MatrixGroup.js +1 -1
  205. package/dist/graph/ProblemsButton.js +18 -19
  206. package/dist/graph/Reveal.js +1 -1
  207. package/dist/graph/ShortcutsButton.js +15 -18
  208. package/dist/graph/SuggestionInput.d.ts +5 -10
  209. package/dist/graph/SuggestionInput.js +14 -18
  210. package/dist/graph/ToolbarPopover.d.ts +11 -6
  211. package/dist/graph/ToolbarPopover.js +35 -67
  212. package/dist/graph/TreeView.js +24 -37
  213. package/dist/graph/WorkflowSettingsDialog.js +4 -4
  214. package/dist/graph/editorChrome.js +13 -12
  215. package/dist/graph/editorFields.js +29 -29
  216. package/dist/graph/editorPrimitives.d.ts +1 -1
  217. package/dist/graph/editorPrimitives.js +10 -7
  218. package/dist/graph/editorRows.js +103 -97
  219. package/dist/graph/fieldProblems.js +2 -2
  220. package/dist/graph/graphEditorState.d.ts +4 -3
  221. package/dist/graph/inputRefs.js +9 -9
  222. package/dist/graph/settingsViews.js +6 -7
  223. package/dist/graph/stepWith.js +6 -6
  224. package/dist/index.d.ts +14 -15
  225. package/dist/index.js +15 -14
  226. package/dist/list/ActionToolbar.d.ts +6 -14
  227. package/dist/list/ActionToolbar.js +48 -96
  228. package/dist/list/ListPage.d.ts +6 -12
  229. package/dist/list/ListPage.js +46 -29
  230. package/dist/list/ListPager.js +4 -4
  231. package/dist/list/ListTable.js +5 -5
  232. package/dist/list/ListViewControls.d.ts +5 -4
  233. package/dist/list/ListViewControls.js +177 -267
  234. package/dist/list/UserHoverCard.d.ts +3 -17
  235. package/dist/list/UserHoverCard.js +21 -45
  236. package/dist/list/index.d.ts +3 -4
  237. package/dist/list/index.js +3 -4
  238. package/dist/list/listSearch.js +12 -11
  239. package/dist/list/rowMenu.d.ts +63 -0
  240. package/dist/list/rowMenu.js +134 -0
  241. package/dist/logviewer/LogViewer.js +26 -26
  242. package/dist/styles.css +1 -1
  243. package/package.json +7 -13
  244. package/dist/ai/ui/Dropdown.d.ts +0 -31
  245. package/dist/ai/ui/Dropdown.js +0 -110
  246. package/dist/components/AddMenu.d.ts +0 -18
  247. package/dist/components/AddMenu.js +0 -46
  248. package/dist/components/BareModal.d.ts +0 -17
  249. package/dist/components/BareModal.js +0 -77
  250. package/dist/components/CollapsiblePanel.d.ts +0 -27
  251. package/dist/components/CollapsiblePanel.js +0 -77
  252. package/dist/components/Dropdown.d.ts +0 -28
  253. package/dist/components/Dropdown.js +0 -355
  254. package/dist/components/Listbox.d.ts +0 -21
  255. package/dist/components/Listbox.js +0 -119
  256. package/dist/components/MultiSelect.d.ts +0 -22
  257. package/dist/components/MultiSelect.js +0 -168
  258. package/dist/components/SwitchToggle.d.ts +0 -15
  259. package/dist/components/SwitchToggle.js +0 -57
  260. package/dist/components/SwitchToggleSmall.d.ts +0 -6
  261. package/dist/components/SwitchToggleSmall.js +0 -14
  262. package/dist/components/Toggle.d.ts +0 -6
  263. package/dist/components/Toggle.js +0 -20
  264. package/dist/components/dropdownUtils.d.ts +0 -37
  265. package/dist/components/dropdownUtils.js +0 -99
  266. package/dist/form/SpecialTypes/DropdownWrapper.d.ts +0 -25
  267. package/dist/form/SpecialTypes/DropdownWrapper.js +0 -28
  268. package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +0 -51
  269. package/dist/form/SpecialTypes/FormikCustomDropdown.js +0 -119
  270. package/dist/form/SpecialTypes/FormikCustomInput.d.ts +0 -19
  271. package/dist/form/SpecialTypes/FormikCustomInput.js +0 -121
  272. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +0 -13
  273. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +0 -31
  274. package/dist/form/SpecialTypes/FormikNumericInput.d.ts +0 -9
  275. package/dist/form/SpecialTypes/FormikNumericInput.js +0 -60
  276. package/dist/form/SpecialTypes/index.d.ts +0 -3
  277. package/dist/list/HoverCard.d.ts +0 -24
  278. package/dist/list/HoverCard.js +0 -73
  279. package/dist/list/RowContextMenu.d.ts +0 -127
  280. package/dist/list/RowContextMenu.js +0 -515
@@ -1,5 +1,7 @@
1
1
  import type { WorkflowVariables } from '../engine.js';
2
2
  /**
3
- * useMemo won't work here — Formik values changes on every keystroke, so this hook extracts which inputs.* keys the schema references and re-parses only when those change. Defaults `userVars`/`secretKeys` to empty — callers in React scope should pass them from `useUserVars()` so the parser leaves `${{ var.SECRET }}` literal during template eval (otherwise the recursive substitution turns `"https://${{ var.PAT }}@host/"` into `"https://@host/"`).
3
+ * Parses a schema against the form's values, again only when an input it reads changes: a keystroke
4
+ * elsewhere in the form gets the last parse back. A parse keeps each part of the last one it equals, so
5
+ * a field whose schema the change left alone keeps its identity. Defaults `userVars`/`secretKeys` to empty — callers in React scope should pass them from `useUserVars()` so the parser leaves `${{ var.SECRET }}` literal during template eval (otherwise the recursive substitution turns `"https://${{ var.PAT }}@host/"` into `"https://@host/"`).
4
6
  */
5
7
  export declare function useParsedOpts<T extends object = Record<string, unknown>>(rawOptions: T, values: Record<string, unknown>, organizationVariables: WorkflowVariables | undefined, userVars?: Record<string, string>, secretKeys?: string[], remoteVars?: Record<string, string | undefined>): T;
@@ -1,11 +1,13 @@
1
1
  import { useWorkflowEngine } from "../components/Provider.js";
2
+ import { shareEqual } from "./utils/shareEqual.js";
2
3
  import { useRef } from "react";
3
- import deepEqual from "fast-deep-equal";
4
4
  //#region src/form/useParsedOpts.ts
5
5
  var EMPTY_VARS = {};
6
6
  var EMPTY_KEYS = [];
7
7
  /**
8
- * useMemo won't work here — Formik values changes on every keystroke, so this hook extracts which inputs.* keys the schema references and re-parses only when those change. Defaults `userVars`/`secretKeys` to empty — callers in React scope should pass them from `useUserVars()` so the parser leaves `${{ var.SECRET }}` literal during template eval (otherwise the recursive substitution turns `"https://${{ var.PAT }}@host/"` into `"https://@host/"`).
8
+ * Parses a schema against the form's values, again only when an input it reads changes: a keystroke
9
+ * elsewhere in the form gets the last parse back. A parse keeps each part of the last one it equals, so
10
+ * a field whose schema the change left alone keeps its identity. Defaults `userVars`/`secretKeys` to empty — callers in React scope should pass them from `useUserVars()` so the parser leaves `${{ var.SECRET }}` literal during template eval (otherwise the recursive substitution turns `"https://${{ var.PAT }}@host/"` into `"https://@host/"`).
9
11
  */
10
12
  function useParsedOpts(rawOptions, values, organizationVariables, userVars = EMPTY_VARS, secretKeys = EMPTY_KEYS, remoteVars = EMPTY_VARS) {
11
13
  const engine = useWorkflowEngine();
@@ -18,8 +20,9 @@ function useParsedOpts(rawOptions, values, organizationVariables, userVars = EMP
18
20
  converted: {},
19
21
  inputDeps: /* @__PURE__ */ new Set(),
20
22
  hasExpressions: false,
21
- relevantSnapshot: {},
22
- result: null
23
+ relevant: "",
24
+ result: null,
25
+ shared: null
23
26
  }).current;
24
27
  if (rawOptions !== c.rawOptions) {
25
28
  c.rawOptions = rawOptions;
@@ -36,15 +39,8 @@ function useParsedOpts(rawOptions, values, organizationVariables, userVars = EMP
36
39
  c.remoteVars = remoteVars;
37
40
  c.result = null;
38
41
  }
39
- if (c.result !== null) {
40
- if (c.inputDeps.size === 0) return c.result;
41
- let inputsChanged = false;
42
- for (const key of c.inputDeps) if (!deepEqual(values[key], c.relevantSnapshot[key])) {
43
- inputsChanged = true;
44
- break;
45
- }
46
- if (!inputsChanged) return c.result;
47
- }
42
+ const relevant = JSON.stringify([...c.inputDeps].map((key) => values[key]));
43
+ if (c.result !== null && relevant === c.relevant) return c.result;
48
44
  const parsed = engine.evaluate({
49
45
  inputs: values,
50
46
  obj: c.converted,
@@ -53,10 +49,9 @@ function useParsedOpts(rawOptions, values, organizationVariables, userVars = EMP
53
49
  secretKeys,
54
50
  remoteVars
55
51
  });
56
- c.result = parsed;
57
- c.relevantSnapshot = {};
58
- for (const key of c.inputDeps) c.relevantSnapshot[key] = values[key];
59
- return parsed;
52
+ c.result = c.shared = shareEqual(c.shared, parsed);
53
+ c.relevant = relevant;
54
+ return c.result;
60
55
  }
61
56
  //#endregion
62
57
  export { useParsedOpts };
@@ -1,6 +1,10 @@
1
- /** Options for a field whose list is keyed by another field's value: with
2
- * depends_on, the list follows whatever is currently chosen at that path. */
3
- export declare function dependentOptions<T>(options: T[] | Record<string, T[]>, dependsOn: string | undefined, values: Record<string, unknown>): {
4
- options: T[];
1
+ /** Options for a field whose list is keyed by another field's value: the list follows whatever is
2
+ * chosen there. A plain list is its own options; a keyed one offers nothing until that field is set. */
3
+ export declare function dependentOptions<T>(options: readonly T[] | Record<string, T[]>, parentValue: unknown): readonly T[];
4
+ /** The value of the field at `path`, rendering again only when it changes; undefined without a path. */
5
+ export declare function useFieldAt(path: string | undefined): unknown;
6
+ /** A field's options and the value of the field its `depends_on` names, which keys them. */
7
+ export declare function useDependentOptions<T>(options: readonly T[] | Record<string, T[]>, dependsOn: string | undefined): {
8
+ options: readonly T[];
5
9
  parentValue: unknown;
6
10
  };
@@ -1,21 +1,29 @@
1
- import { getValueUsingPath } from "./getValueUsingPath.js";
1
+ import { useMemo } from "react";
2
+ import { useFormContext, useWatch } from "react-hook-form";
2
3
  //#region src/form/utils/dependentOptions.ts
3
- /** Options for a field whose list is keyed by another field's value: with
4
- * depends_on, the list follows whatever is currently chosen at that path. */
5
- function dependentOptions(options, dependsOn, values) {
6
- if (Array.isArray(options)) return {
7
- options,
8
- parentValue: void 0
9
- };
10
- const parentValue = dependsOn ? getValueUsingPath(values, dependsOn) : void 0;
11
- if (parentValue === void 0 || parentValue === null) return {
12
- options: [],
13
- parentValue
14
- };
15
- return {
16
- options: options[String(parentValue)] ?? [],
4
+ /** Options for a field whose list is keyed by another field's value: the list follows whatever is
5
+ * chosen there. A plain list is its own options; a keyed one offers nothing until that field is set. */
6
+ function dependentOptions(options, parentValue) {
7
+ if (Array.isArray(options)) return options;
8
+ if (parentValue === void 0 || parentValue === null) return [];
9
+ return options[String(parentValue)] ?? [];
10
+ }
11
+ /** The value of the field at `path`, rendering again only when it changes; undefined without a path. */
12
+ function useFieldAt(path) {
13
+ const { control } = useFormContext();
14
+ return useWatch({
15
+ control,
16
+ name: path ?? "",
17
+ disabled: !path
18
+ });
19
+ }
20
+ /** A field's options and the value of the field its `depends_on` names, which keys them. */
21
+ function useDependentOptions(options, dependsOn) {
22
+ const parentValue = useFieldAt(dependsOn);
23
+ return useMemo(() => ({
24
+ options: dependentOptions(options, parentValue),
17
25
  parentValue
18
- };
26
+ }), [options, parentValue]);
19
27
  }
20
28
  //#endregion
21
- export { dependentOptions };
29
+ export { dependentOptions, useDependentOptions, useFieldAt };
@@ -0,0 +1,10 @@
1
+ import type { ComboboxItem } from '../../components/Combobox.js';
2
+ /** A dropdown option as workflow YAML writes it. */
3
+ export type FieldOption<Value = string> = string | {
4
+ label: string;
5
+ value: Value;
6
+ description?: string;
7
+ secondaryLabel?: string;
8
+ };
9
+ /** YAML options as picker items. secondaryLabel is the older key for description. */
10
+ export declare function toFieldItems<Value>(options: readonly FieldOption<Value>[]): (ComboboxItem<Value> | string)[];
@@ -0,0 +1,11 @@
1
+ //#region src/form/utils/fieldItems.ts
2
+ /** YAML options as picker items. secondaryLabel is the older key for description. */
3
+ function toFieldItems(options) {
4
+ return options.map((option) => typeof option === "string" ? option : {
5
+ label: option.label,
6
+ value: option.value,
7
+ description: option.description ?? option.secondaryLabel
8
+ });
9
+ }
10
+ //#endregion
11
+ export { toFieldItems };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * A field's path as the form store names it: `hosts[0].cpus` becomes `hosts.0.cpus`. A workflow writes
3
+ * rows with brackets, but the store tells a field of a change by a path it starts, so a row's fields
4
+ * hear a change to their list only when both name it with dots.
5
+ */
6
+ export declare function fieldPath(path: string): string;
7
+ /** The index of the innermost row a path is in, or undefined outside every list. */
8
+ export declare function rowIndexOf(path: string): number | undefined;
9
+ /** A list's `[index]` placeholder in a path, filled with the row a field is in. */
10
+ export declare function atIndex(path: string, index: number | undefined): string;
@@ -0,0 +1,20 @@
1
+ //#region src/form/utils/fieldPath.ts
2
+ /**
3
+ * A field's path as the form store names it: `hosts[0].cpus` becomes `hosts.0.cpus`. A workflow writes
4
+ * rows with brackets, but the store tells a field of a change by a path it starts, so a row's fields
5
+ * hear a change to their list only when both name it with dots.
6
+ */
7
+ function fieldPath(path) {
8
+ return path.replace(/\[(\d+)\]/g, ".$1");
9
+ }
10
+ /** The index of the innermost row a path is in, or undefined outside every list. */
11
+ function rowIndexOf(path) {
12
+ const index = fieldPath(path).split(".").findLast((segment) => /^\d+$/.test(segment));
13
+ return index === void 0 ? void 0 : Number(index);
14
+ }
15
+ /** A list's `[index]` placeholder in a path, filled with the row a field is in. */
16
+ function atIndex(path, index) {
17
+ return index === void 0 ? path : path.replace("[index]", `[${index}]`);
18
+ }
19
+ //#endregion
20
+ export { atIndex, fieldPath, rowIndexOf };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `next`, reusing every part of `prev` it equals, so whatever didn't change keeps its identity: a
3
+ * schema parsed again because one input changed hands each field that input left alone back as it
4
+ * was, and a field that renders from it can skip the render.
5
+ */
6
+ export declare function shareEqual<T>(prev: unknown, next: T): T;
@@ -0,0 +1,38 @@
1
+ //#region src/form/utils/shareEqual.ts
2
+ function isPlain(value) {
3
+ if (value === null || typeof value !== "object") return false;
4
+ const proto = Object.getPrototypeOf(value);
5
+ return proto === Object.prototype || proto === null;
6
+ }
7
+ /**
8
+ * `next`, reusing every part of `prev` it equals, so whatever didn't change keeps its identity: a
9
+ * schema parsed again because one input changed hands each field that input left alone back as it
10
+ * was, and a field that renders from it can skip the render.
11
+ */
12
+ function shareEqual(prev, next) {
13
+ if (Object.is(prev, next)) return prev;
14
+ if (Array.isArray(prev) && Array.isArray(next)) {
15
+ let same = prev.length === next.length;
16
+ const shared = next.map((item, i) => {
17
+ const kept = shareEqual(prev[i], item);
18
+ same &&= kept === prev[i];
19
+ return kept;
20
+ });
21
+ return same ? prev : shared;
22
+ }
23
+ if (isPlain(prev) && isPlain(next)) {
24
+ const keys = Object.keys(next);
25
+ const before = Object.keys(prev);
26
+ let same = keys.length === before.length;
27
+ const shared = {};
28
+ keys.forEach((key, i) => {
29
+ const kept = shareEqual(prev[key], next[key]);
30
+ same &&= before[i] === key && kept === prev[key];
31
+ shared[key] = kept;
32
+ });
33
+ return same ? prev : shared;
34
+ }
35
+ return next;
36
+ }
37
+ //#endregion
38
+ export { shareEqual };
@@ -4,9 +4,9 @@ import { FaInfoCircle } from "../icons/fa/FaInfoCircle.js";
4
4
  import { IoWarningOutline } from "../icons/io5/IoWarningOutline.js";
5
5
  import { LuChevronRight } from "../icons/lu/LuChevronRight.js";
6
6
  import { keyedByContent } from "../components/keys.js";
7
- import cx from "classnames";
8
- import { useState } from "react";
7
+ import { clsx } from "clsx";
9
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { useState } from "react";
10
10
  //#region src/graph/AnnotationBanner.tsx
11
11
  var typeOrder = {
12
12
  error: 0,
@@ -77,11 +77,11 @@ function AnnotationBanner({ executedJobs }) {
77
77
  for (const a of annotations) counts[a.type]++;
78
78
  const ChevronIcon = expanded ? FaChevronDown : LuChevronRight;
79
79
  return /* @__PURE__ */ jsxs("div", {
80
- className: cx("rounded-lg border border-[var(--theme-border)] overflow-hidden", "bg-[var(--theme-panel-bg)]"),
80
+ className: clsx("rounded-lg border border-[var(--theme-border)] overflow-hidden", "bg-[var(--theme-panel-bg)]"),
81
81
  children: [/* @__PURE__ */ jsxs("button", {
82
82
  type: "button",
83
83
  onClick: () => setExpanded((prev) => !prev),
84
- className: cx("w-full flex items-center gap-3 px-4 py-2.5 text-left", "hover:bg-[var(--theme-hover)] transition-colors", expanded && "border-b border-[var(--theme-border)]"),
84
+ className: clsx("w-full flex items-center gap-3 px-4 py-2.5 text-left", "hover:bg-[var(--theme-hover)] transition-colors", expanded && "border-b border-[var(--theme-border)]"),
85
85
  children: [
86
86
  /* @__PURE__ */ jsx(ChevronIcon, { className: "w-3.5 h-3.5 text-[var(--theme-muted-text-color)] shrink-0" }),
87
87
  /* @__PURE__ */ jsx("span", {
@@ -99,7 +99,7 @@ function AnnotationBanner({ executedJobs }) {
99
99
  const config = typeConfig[type];
100
100
  const Icon = config.icon;
101
101
  return /* @__PURE__ */ jsxs("span", {
102
- className: cx("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium", config.countBg),
102
+ className: clsx("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium", config.countBg),
103
103
  children: [/* @__PURE__ */ jsx(Icon, { className: "w-3 h-3" }), counts[type]]
104
104
  }, type);
105
105
  })
@@ -111,12 +111,12 @@ function AnnotationBanner({ executedJobs }) {
111
111
  const config = typeConfig[annotation.type] || typeConfig.notice;
112
112
  const Icon = config.icon;
113
113
  return /* @__PURE__ */ jsxs("div", {
114
- className: cx("flex items-start gap-2.5 px-4 py-2 text-sm", config.bgClass),
115
- children: [/* @__PURE__ */ jsx(Icon, { className: cx("w-4 h-4 mt-0.5 shrink-0", config.accentClass) }), /* @__PURE__ */ jsxs("div", {
114
+ className: clsx("flex items-start gap-2.5 px-4 py-2 text-sm", config.bgClass),
115
+ children: [/* @__PURE__ */ jsx(Icon, { className: clsx("w-4 h-4 mt-0.5 shrink-0", config.accentClass) }), /* @__PURE__ */ jsxs("div", {
116
116
  className: "flex-1 min-w-0",
117
117
  children: [
118
118
  /* @__PURE__ */ jsxs("span", {
119
- className: cx("font-medium", config.accentClass),
119
+ className: clsx("font-medium", config.accentClass),
120
120
  children: [annotation.title || config.label, ":"]
121
121
  }),
122
122
  " ",
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from 'react';
2
2
  export declare function Collapse({ expanded, id, children, }: {
3
3
  expanded: boolean;
4
+ /** The external toggle's aria-controls target. */
4
5
  id?: string;
5
6
  children: ReactNode;
6
7
  }): import("react").JSX.Element;
@@ -1,35 +1,14 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { AnimatePresence, motion } from "framer-motion";
2
+ import { Collapsible } from "@base-ui/react/collapsible";
3
3
  //#region src/graph/Collapse.tsx
4
4
  function Collapse({ expanded, id, children }) {
5
- return /* @__PURE__ */ jsx(AnimatePresence, {
6
- initial: false,
7
- children: expanded && /* @__PURE__ */ jsx(motion.div, {
5
+ return /* @__PURE__ */ jsx(Collapsible.Root, {
6
+ open: expanded,
7
+ children: /* @__PURE__ */ jsx(Collapsible.Panel, {
8
8
  id,
9
- initial: {
10
- height: 0,
11
- opacity: 0
12
- },
13
- animate: {
14
- height: "auto",
15
- opacity: 1
16
- },
17
- exit: {
18
- height: 0,
19
- opacity: 0
20
- },
21
- transition: {
22
- duration: .2,
23
- ease: [
24
- .25,
25
- .1,
26
- .25,
27
- 1
28
- ]
29
- },
30
- className: "overflow-hidden",
9
+ className: "h-(--collapsible-panel-height) overflow-hidden transition-[height,opacity] duration-200 ease-[cubic-bezier(0.25,0.1,0.25,1)] data-starting-style:h-0 data-starting-style:opacity-0 data-ending-style:h-0 data-ending-style:opacity-0",
31
10
  children
32
- }, "collapse")
11
+ })
33
12
  });
34
13
  }
35
14
  //#endregion
@@ -1,7 +1,7 @@
1
1
  import { highlightOf, useLineage, useLineageStore } from "./lineage.js";
2
2
  import { dimClasses } from "./GraphNode.js";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
4
  import { memo, useMemo } from "react";
4
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/graph/Connectors.tsx
6
6
  var CONNECTOR_COLOR = "var(--theme-border)";
7
7
  var HIGHLIGHT_COLOR = "var(--theme-element)";
@@ -57,7 +57,7 @@ function LitEdges({ edges }) {
57
57
  }, `${from}→${to}`));
58
58
  }
59
59
  }
60
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [lines.length > 0 && /* @__PURE__ */ jsx("path", {
60
+ return /* @__PURE__ */ jsxs(Fragment, { children: [lines.length > 0 && /* @__PURE__ */ jsx("path", {
61
61
  d: lines.join(" "),
62
62
  stroke: CONNECTOR_COLOR,
63
63
  strokeWidth: STROKE,
@@ -82,7 +82,7 @@ function LitDots({ ports }) {
82
82
  }, key));
83
83
  }
84
84
  }
85
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [at.length > 0 && /* @__PURE__ */ jsx("path", {
85
+ return /* @__PURE__ */ jsxs(Fragment, { children: [at.length > 0 && /* @__PURE__ */ jsx("path", {
86
86
  d: squaresAt(at),
87
87
  fill: PANEL_COLOR
88
88
  }), lit] });
@@ -130,7 +130,7 @@ var ConnectorLayers = memo(function ConnectorLayers({ edges, zBase }) {
130
130
  style: { zIndex: z + zBase },
131
131
  children
132
132
  });
133
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
133
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
134
134
  keyframes,
135
135
  layer(-1, /* @__PURE__ */ jsx("path", {
136
136
  d: lines,
@@ -140,7 +140,7 @@ var ConnectorLayers = memo(function ConnectorLayers({ edges, zBase }) {
140
140
  className: fade
141
141
  })),
142
142
  layer(20, /* @__PURE__ */ jsx(LitEdges, { edges })),
143
- layer(30, /* @__PURE__ */ jsxs(Fragment$1, { children: [
143
+ layer(30, /* @__PURE__ */ jsxs(Fragment, { children: [
144
144
  /* @__PURE__ */ jsx("path", {
145
145
  d: squares,
146
146
  fill: PANEL_COLOR
@@ -1,4 +1,3 @@
1
- import { useRunFile, useSlots, useStrings, useWorkflowEngine } from "../components/Provider.js";
2
1
  import { FaArrowLeft } from "../icons/fa/FaArrowLeft.js";
3
2
  import { FaArrowRight } from "../icons/fa/FaArrowRight.js";
4
3
  import { IoDocumentTextOutline } from "../icons/io5/IoDocumentTextOutline.js";
@@ -6,8 +5,9 @@ import { LuChevronLeft } from "../icons/lu/LuChevronLeft.js";
6
5
  import { LuChevronRight } from "../icons/lu/LuChevronRight.js";
7
6
  import { LuZoomIn } from "../icons/lu/LuZoomIn.js";
8
7
  import { LuZoomOut } from "../icons/lu/LuZoomOut.js";
9
- import { TooltipInfo } from "../components/Tooltip.js";
10
- import { BareModal, modalPanelClasses } from "../components/BareModal.js";
8
+ import { useRunFile, useSlots, useStrings, useWorkflowEngine } from "../components/Provider.js";
9
+ import { Modal } from "../components/Modal.js";
10
+ import { InfoTip } from "../components/InfoTip.js";
11
11
  import { IconButton } from "../components/IconButton.js";
12
12
  import { Indicator } from "../components/Indicator.js";
13
13
  import Loader from "../components/Loader.js";
@@ -32,9 +32,9 @@ import { computeGraphLayout, displayJobsOf, hopDistances, positionsOf } from "./
32
32
  import { MatrixGroupNode, MatrixGroupSummaryItem } from "./MatrixGroup.js";
33
33
  import TreeView from "./TreeView.js";
34
34
  import { FIT_MAX_SCALE, MIN_SCALE, ZOOM_STEP, fitMargin, fitView, intoView, wheelFactor, zoomAround, zoomLimit } from "./viewport.js";
35
- import cx from "classnames";
36
- import { Fragment, Suspense, createContext, lazy, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
37
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
35
+ import { clsx } from "clsx";
36
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
37
+ import { Fragment as Fragment$1, Suspense, createContext, lazy, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
38
38
  import { flushSync } from "react-dom";
39
39
  import { DateTime } from "luxon";
40
40
  import { TransformComponent, TransformWrapper } from "react-zoom-pan-pinch";
@@ -45,12 +45,12 @@ function ViewToggle({ viewMode, setViewMode }) {
45
45
  children: [/* @__PURE__ */ jsx("button", {
46
46
  type: "button",
47
47
  onClick: () => setViewMode("dag"),
48
- className: cx("px-3 py-1.5 text-xs font-mono transition-colors", viewMode === "dag" ? "bg-[var(--theme-element)] text-[var(--theme-element-text)]" : "text-[var(--theme-muted-text-color)] hover:text-[var(--theme-app)] hover:bg-[var(--theme-hover)]"),
48
+ className: clsx("px-3 py-1.5 text-xs font-mono transition-colors", viewMode === "dag" ? "bg-[var(--theme-element)] text-[var(--theme-element-text)]" : "text-[var(--theme-muted-text-color)] hover:text-[var(--theme-app)] hover:bg-[var(--theme-hover)]"),
49
49
  children: "DAG"
50
50
  }), /* @__PURE__ */ jsx("button", {
51
51
  type: "button",
52
52
  onClick: () => setViewMode("tree"),
53
- className: cx("px-3 py-1.5 text-xs font-mono transition-colors", viewMode === "tree" ? "bg-[var(--theme-element)] text-[var(--theme-element-text)]" : "text-[var(--theme-muted-text-color)] hover:text-[var(--theme-app)] hover:bg-[var(--theme-hover)]"),
53
+ className: clsx("px-3 py-1.5 text-xs font-mono transition-colors", viewMode === "tree" ? "bg-[var(--theme-element)] text-[var(--theme-element-text)]" : "text-[var(--theme-muted-text-color)] hover:text-[var(--theme-app)] hover:bg-[var(--theme-hover)]"),
54
54
  children: "Tree"
55
55
  })]
56
56
  });
@@ -63,7 +63,7 @@ function GraphViewControls({ history, expand, onReset, onZoom, zoomedAll }) {
63
63
  return /* @__PURE__ */ jsxs("div", {
64
64
  className: VIEW_BAR,
65
65
  children: [
66
- history && /* @__PURE__ */ jsxs(Fragment$1, { children: [
66
+ history && /* @__PURE__ */ jsxs(Fragment, { children: [
67
67
  /* @__PURE__ */ jsx(IconButton, {
68
68
  icon: /* @__PURE__ */ jsx(LuChevronLeft, { className: "h-4 w-4" }),
69
69
  label: dag.previousGraph,
@@ -531,7 +531,7 @@ function EditorEdges({ edges, cols, boxes, selected, zBase, size }) {
531
531
  const wiredIn = new Set(edges.map((edge) => edge.to));
532
532
  const wiredOut = new Set(edges.map((edge) => edge.from));
533
533
  const chosen = new Set(selected.map((edge) => `${edge.from}→${edge.to}`));
534
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
534
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
535
535
  cols.flatMap((col) => col.map((jobNames) => {
536
536
  const [head] = jobNames;
537
537
  const box = head === void 0 ? void 0 : boxes.get(head);
@@ -568,7 +568,7 @@ function EditorEdges({ edges, cols, boxes, selected, zBase, size }) {
568
568
  width: size?.width,
569
569
  height: size?.height,
570
570
  style: { zIndex: 1 + zBase },
571
- children: edges.map(({ from, to, path }) => /* @__PURE__ */ jsxs(Fragment, { children: [chosen.has(`${from}→${to}`) && /* @__PURE__ */ jsx("path", {
571
+ children: edges.map(({ from, to, path }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [chosen.has(`${from}→${to}`) && /* @__PURE__ */ jsx("path", {
572
572
  d: path.d,
573
573
  stroke: "var(--theme-element)",
574
574
  strokeWidth: "10",
@@ -625,7 +625,7 @@ function SidebarJobs({ jobs, pathPrefix, preview, stepsOpen, toggleSteps, expand
625
625
  seenMatrixGroups.add(originaljob);
626
626
  return [originaljob];
627
627
  });
628
- return /* @__PURE__ */ jsx(Fragment$1, { children: orderedKeys.map((jobName) => {
628
+ return /* @__PURE__ */ jsx(Fragment, { children: orderedKeys.map((jobName) => {
629
629
  const mg = displayJobs[jobName]?._matrixGroup;
630
630
  if (mg) return /* @__PURE__ */ jsx(MatrixGroupSummaryItem, {
631
631
  matrixGroup: mg,
@@ -1142,7 +1142,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
1142
1142
  })
1143
1143
  }) : void 0;
1144
1144
  const startDt = run.createdAt ? DateTime.fromISO(run.createdAt) : shownAt;
1145
- const additionalBottomLeftBarComponents = sublogIsStep ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
1145
+ const additionalBottomLeftBarComponents = sublogIsStep ? /* @__PURE__ */ jsxs(Fragment, { children: [
1146
1146
  /* @__PURE__ */ jsxs("button", {
1147
1147
  type: "button",
1148
1148
  className: "btn btn-neutral",
@@ -1203,7 +1203,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
1203
1203
  ]
1204
1204
  }),
1205
1205
  /* @__PURE__ */ jsxs("div", {
1206
- className: cx(preview ? "w-full" : "flex-1 min-w-0 mt-2", "h-full flex flex-col gap-y-2"),
1206
+ className: clsx(preview ? "w-full" : "flex-1 min-w-0 mt-2", "h-full flex flex-col gap-y-2"),
1207
1207
  children: [
1208
1208
  !preview && /* @__PURE__ */ jsxs("div", {
1209
1209
  className: "panel w-full border rounded-lg px-4 py-2 flex flex-wrap items-center gap-x-16 gap-y-2",
@@ -1235,7 +1235,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
1235
1235
  children: dagStrings.status
1236
1236
  }), /* @__PURE__ */ jsx("div", {
1237
1237
  className: "text-sm font-semibold flex items-center gap-x-1",
1238
- children: /* @__PURE__ */ jsxs(TooltipInfo, {
1238
+ children: /* @__PURE__ */ jsxs(InfoTip, {
1239
1239
  className: "flex items-center gap-x-1",
1240
1240
  text: dagStrings.statusReason(run.statusReason) ?? "",
1241
1241
  children: [/* @__PURE__ */ jsx(Indicator, { status: runStatus }), dagStrings.statusLabel(runStatus)]
@@ -1291,7 +1291,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
1291
1291
  }) : /* @__PURE__ */ jsxs("div", {
1292
1292
  ref: setContainerElement,
1293
1293
  tabIndex: editor ? -1 : void 0,
1294
- className: cx("panel w-full overflow-hidden relative", removeBorder ? "border-none" : "border", editor && "outline-none"),
1294
+ className: clsx("panel w-full overflow-hidden relative", removeBorder ? "border-none" : "border", editor && "outline-none"),
1295
1295
  style: {
1296
1296
  height: fixedHeight ?? (containerHeight !== null ? `${containerHeight}px` : previewHeight !== null ? `${Math.min(previewHeight, windowSize.h * .62)}px` : "62vh"),
1297
1297
  minHeight: previewHeight !== null && !fixedHeight ? 0 : 160
@@ -1311,7 +1311,7 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
1311
1311
  onPanning: moved,
1312
1312
  onPinch: moved,
1313
1313
  onTransform,
1314
- children: () => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
1314
+ children: () => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
1315
1315
  className: "absolute z-10 top-2 right-2 flex max-w-[calc(100%-1rem)] flex-col items-end gap-y-1",
1316
1316
  children: /* @__PURE__ */ jsx(GraphViewControls, {
1317
1317
  history: executedJobsPath.length > 1 ? {
@@ -1365,11 +1365,12 @@ function DependencyGraph({ run, preview = false, removeBorder, viewMode = "dag",
1365
1365
  })
1366
1366
  ]
1367
1367
  }),
1368
- /* @__PURE__ */ jsx(BareModal, {
1368
+ /* @__PURE__ */ jsx(Modal, {
1369
1369
  open: sublogOpen !== "",
1370
1370
  onClose: () => setSublogOpen(""),
1371
+ "aria-label": logName.replace(/\s+/g, " ") || sublogOpen.slice(sublogFileStart),
1371
1372
  align: "center",
1372
- className: cx(modalPanelClasses, "max-h-full overflow-y-auto p-4 sm:p-6"),
1373
+ className: "max-h-full overflow-y-auto p-4 sm:p-6",
1373
1374
  children: /* @__PURE__ */ jsx("div", {
1374
1375
  className: "flex w-full",
1375
1376
  children: sublogsLoading && (!sublogs || !runNumber) ? /* @__PURE__ */ jsx(Loader, {