@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
package/dist/form/Form.js CHANGED
@@ -3,7 +3,6 @@ import { Loader } from "../components/Loader.js";
3
3
  import { useStrings, useWorkflowEngine } from "../components/Provider.js";
4
4
  import { Button } from "../components/Button.js";
5
5
  import { FieldRowContext } from "../components/Field.js";
6
- import { InfoTip } from "../components/InfoTip.js";
7
6
  import { Section } from "../components/Section.js";
8
7
  import { parseWizardConfig } from "./Wizard/utils.js";
9
8
  import { inputWidth, resolvedFlag } from "./lib.js";
@@ -322,10 +321,7 @@ var FormField = memo(function FormField({ fieldName, optionsField, nested, field
322
321
  setValue
323
322
  ]);
324
323
  const tooltip = field?.tooltip;
325
- const tooltipComponent = useMemo(() => tooltip ? /* @__PURE__ */ jsx(InfoTip, {
326
- className: "pr-2",
327
- text: typeof tooltip === "string" ? tooltip.replace(/\r/g, "") : tooltip.filter(Boolean).join("\n")
328
- }) : null, [tooltip]);
324
+ const help = (typeof tooltip === "string" ? tooltip.replace(/\r/g, "") : tooltip?.filter(Boolean).join("\n")) || void 0;
329
325
  const path = editing ? [...editing.parent, fieldName] : null;
330
326
  if (field === null || fieldName === "v3") return null;
331
327
  if (reads.hidden) return editing && path && fieldName !== "$meta" ? /* @__PURE__ */ jsx(editing.Row, {
@@ -408,7 +404,7 @@ var FormField = memo(function FormField({ fieldName, optionsField, nested, field
408
404
  disabled: Boolean(fieldObj.disabled),
409
405
  computeOn: computeOn || fieldObj.computeOn,
410
406
  spaceCompact,
411
- tooltipComponent
407
+ help
412
408
  })
413
409
  })
414
410
  });
@@ -625,8 +621,7 @@ function DynamicFormBody({ form, formJSONs: options = {}, reinitialize = false,
625
621
  parsed
626
622
  ]);
627
623
  const report = useEffectEvent((values) => {
628
- const { editorKeyPostfix: _, ...rest } = values;
629
- onValuesChange?.(rest);
624
+ onValuesChange?.(values);
630
625
  });
631
626
  useEffect(() => form.subscribe({
632
627
  formState: { values: true },
@@ -33,7 +33,7 @@ function WizardNavigation({ isLastStep, canGoBack, isCurrentStepValid, nextLabel
33
33
  };
34
34
  return /* @__PURE__ */ jsxs("div", { children: [error && /* @__PURE__ */ jsxs("p", {
35
35
  role: "alert",
36
- className: "mb-3 flex items-center gap-1.5 text-sm text-(--theme-error)",
36
+ className: "mb-3 flex items-center gap-1.5 text-sm text-(--theme-error-text)",
37
37
  children: [/* @__PURE__ */ jsx(WarningIcon, {
38
38
  "aria-hidden": "true",
39
39
  className: "size-4 shrink-0"
@@ -44,20 +44,17 @@ function WizardNavigation({ isLastStep, canGoBack, isCurrentStepValid, nextLabel
44
44
  variant: "secondary",
45
45
  onClick: onPrevious,
46
46
  disabled: !canGoBack || isLoading,
47
- "aria-label": t.previousStep,
48
47
  children: prevLabel || common.previous
49
48
  }), isLastStep && !onSubmit ? null : isLastStep ? /* @__PURE__ */ jsx(Button, {
50
49
  variant: "primary",
51
50
  onClick: handleSubmit,
52
51
  disabled: !isCurrentStepValid,
53
52
  loading: isLoading,
54
- "aria-label": submitLabel,
55
53
  children: submitLabel
56
54
  }) : /* @__PURE__ */ jsx(Button, {
57
55
  variant: "primary",
58
56
  onClick: handleNext,
59
57
  loading: isLoading,
60
- "aria-label": t.nextStep,
61
58
  children: nextLabel || common.next
62
59
  })]
63
60
  })] });
@@ -80,7 +80,7 @@ function StepItem({ number, title, description, status, onJump }) {
80
80
  children: strings.stepDone
81
81
  }),
82
82
  status === "invalid" && /* @__PURE__ */ jsx("span", {
83
- className: "text-xs text-(--theme-error)",
83
+ className: "text-xs text-(--theme-error-text)",
84
84
  children: strings.stepNeedsAttention
85
85
  }),
86
86
  description && /* @__PURE__ */ jsx("span", {
@@ -16,7 +16,7 @@ function parseWizardConfig(options) {
16
16
  stepOrder.push(key);
17
17
  }
18
18
  if (stepOrder.length === 0) {
19
- console.warn("Wizard mode enabled but no steps found");
19
+ if (process.env.NODE_ENV !== "production") console.warn("Wizard mode enabled but no steps found");
20
20
  return null;
21
21
  }
22
22
  return {
@@ -2,6 +2,6 @@ import type { FieldProps } from '../components/Field.js';
2
2
  import type { FieldComponentProps } from './types/fieldComponentTypes.js';
3
3
  /** How a form field's props frame it: its label, help, description, required mark and error,
4
4
  * laid out as the form lays out its fields. Spread on `Field`. */
5
- export declare function fieldFrame({ field, label, labelPosition, error, disabled, spaceCompact, tooltipComponent, }: FieldComponentProps, { group }?: {
5
+ export declare function fieldFrame({ field, label, labelPosition, error, disabled, spaceCompact, help }: FieldComponentProps, { group }?: {
6
6
  group?: boolean;
7
7
  }): Omit<FieldProps, 'children'>;
@@ -2,10 +2,10 @@ import { resolvedFlag } from "./lib.js";
2
2
  //#region src/form/fieldFrame.ts
3
3
  /** How a form field's props frame it: its label, help, description, required mark and error,
4
4
  * laid out as the form lays out its fields. Spread on `Field`. */
5
- function fieldFrame({ field, label, labelPosition, error, disabled, spaceCompact, tooltipComponent }, { group = false } = {}) {
5
+ function fieldFrame({ field, label, labelPosition, error, disabled, spaceCompact, help }, { group = false } = {}) {
6
6
  return {
7
7
  label,
8
- hint: tooltipComponent,
8
+ help,
9
9
  description: field.description,
10
10
  group,
11
11
  required: !resolvedFlag(field.optional),
@@ -27,7 +27,8 @@ export interface FieldComponentProps<TField extends FieldBase = FieldBase> {
27
27
  disabled: boolean;
28
28
  computeOn?: boolean | undefined;
29
29
  spaceCompact?: boolean;
30
- tooltipComponent?: React.ReactNode;
30
+ /** The field's help text, from its `tooltip`: `fieldFrame` puts it behind a ? beside the label. */
31
+ help?: string | undefined;
31
32
  }
32
33
  /** Props for a field component, given the field definition it renders. */
33
34
  export type FieldProps<TField extends FieldBase = BaseField> = FieldComponentProps<TField & RuntimeFieldExtensions>;
@@ -1,6 +1,5 @@
1
1
  import type { WorkflowJob } from './types.js';
2
- interface AnnotationBannerProps {
2
+ export interface AnnotationBannerProps {
3
3
  executedJobs: Record<string, WorkflowJob>;
4
4
  }
5
5
  export declare function AnnotationBanner({ executedJobs }: AnnotationBannerProps): import("react").JSX.Element | null;
6
- export {};
@@ -1,9 +1,10 @@
1
1
  import { cx } from "../cx.js";
2
- import { ChevronDownIcon, ChevronRightIcon, ErrorIcon, InfoIcon, WarningIcon } from "../icons.js";
2
+ import { ChevronRightIcon, ErrorIcon, InfoIcon, WarningIcon } from "../icons.js";
3
+ import { toneIcon, toneSurface, toneText } from "../components/tone.js";
3
4
  import { keyedByContent } from "../components/keys.js";
4
5
  import { useStrings } from "../components/Provider.js";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
- import { useState } from "react";
7
+ import { useId, useState } from "react";
7
8
  //#region src/graph/AnnotationBanner.tsx
8
9
  var typeOrder = {
9
10
  error: 0,
@@ -13,21 +14,15 @@ var typeOrder = {
13
14
  var typeConfig = {
14
15
  error: {
15
16
  icon: ErrorIcon,
16
- accentClass: "text-red-500",
17
- bgClass: "bg-red-500/5 dark:bg-red-500/10",
18
- countBg: "bg-red-500/15 text-red-700 dark:text-red-400"
17
+ tone: "error"
19
18
  },
20
19
  warning: {
21
20
  icon: WarningIcon,
22
- accentClass: "text-yellow-500",
23
- bgClass: "bg-yellow-500/5 dark:bg-yellow-500/10",
24
- countBg: "bg-yellow-500/15 text-yellow-700 dark:text-yellow-400"
21
+ tone: "warning"
25
22
  },
26
23
  notice: {
27
24
  icon: InfoIcon,
28
- accentClass: "text-blue-500",
29
- bgClass: "bg-blue-500/5 dark:bg-blue-500/10",
30
- countBg: "bg-blue-500/15 text-blue-700 dark:text-blue-400"
25
+ tone: "info"
31
26
  }
32
27
  };
33
28
  function collectAnnotations(executedJobs, parentPath) {
@@ -62,6 +57,7 @@ function collectAnnotations(executedJobs, parentPath) {
62
57
  function AnnotationBanner({ executedJobs }) {
63
58
  const [expanded, setExpanded] = useState(false);
64
59
  const { dag: t } = useStrings();
60
+ const listId = useId();
65
61
  const annotations = collectAnnotations(executedJobs);
66
62
  if (annotations.length === 0) return null;
67
63
  const counts = {
@@ -70,20 +66,23 @@ function AnnotationBanner({ executedJobs }) {
70
66
  notice: 0
71
67
  };
72
68
  for (const a of annotations) counts[a.type]++;
73
- const ChevronIcon = expanded ? ChevronDownIcon : ChevronRightIcon;
74
69
  return /* @__PURE__ */ jsxs("div", {
75
- className: cx("rounded-lg border border-[var(--theme-border)] overflow-hidden", "bg-[var(--theme-panel-bg)]"),
70
+ className: "overflow-hidden rounded-lg border border-(--theme-border) bg-(--theme-panel-bg)",
76
71
  children: [/* @__PURE__ */ jsxs("button", {
77
72
  type: "button",
73
+ "aria-expanded": expanded,
74
+ "aria-controls": listId,
75
+ "aria-label": t.annotationsLabel(counts),
78
76
  onClick: () => setExpanded((prev) => !prev),
79
- 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)]"),
77
+ className: cx("flex w-full items-center gap-3 px-4 py-2.5 text-left", "transition-colors hover:bg-(--theme-hover) motion-reduce:transition-none", "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--theme-link)", expanded && "border-b border-(--theme-border)"),
80
78
  children: [
81
- /* @__PURE__ */ jsx(ChevronIcon, { className: "w-3.5 h-3.5 text-[var(--theme-muted-text-color)] shrink-0" }),
79
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: cx("size-3.5 shrink-0 text-(--theme-muted-text-color) transition-transform motion-reduce:transition-none", expanded && "rotate-90") }),
82
80
  /* @__PURE__ */ jsx("span", {
83
- className: "text-sm font-medium text-[var(--theme-app)]",
81
+ className: "text-sm font-medium text-(--theme-app)",
84
82
  children: t.annotations
85
83
  }),
86
- /* @__PURE__ */ jsx("div", {
84
+ /* @__PURE__ */ jsx("span", {
85
+ "aria-hidden": true,
87
86
  className: "flex items-center gap-1.5",
88
87
  children: [
89
88
  "error",
@@ -91,36 +90,35 @@ function AnnotationBanner({ executedJobs }) {
91
90
  "notice"
92
91
  ].map((type) => {
93
92
  if (!counts[type]) return null;
94
- const config = typeConfig[type];
95
- const Icon = config.icon;
93
+ const { icon: Icon, tone } = typeConfig[type];
96
94
  return /* @__PURE__ */ jsxs("span", {
97
- className: cx("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium", config.countBg),
98
- children: [/* @__PURE__ */ jsx(Icon, { className: "w-3 h-3" }), counts[type]]
95
+ className: cx("inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium tabular-nums", toneSurface[tone]),
96
+ children: [/* @__PURE__ */ jsx(Icon, { className: cx("size-3", toneIcon[tone]) }), counts[type]]
99
97
  }, type);
100
98
  })
101
99
  })
102
100
  ]
103
- }), expanded && /* @__PURE__ */ jsx("div", {
104
- className: "divide-y divide-[var(--theme-border)] max-h-[400px] overflow-y-auto",
101
+ }), expanded && /* @__PURE__ */ jsx("ul", {
102
+ id: listId,
103
+ className: "max-h-[400px] divide-y divide-(--theme-border) overflow-y-auto",
105
104
  children: keyedByContent(annotations, (a) => a.id ?? `${a.type}:${a.title}:${a.message}`).map(({ key, item: annotation }) => {
106
- const config = typeConfig[annotation.type] || typeConfig.notice;
107
- const Icon = config.icon;
108
- return /* @__PURE__ */ jsxs("div", {
109
- className: cx("flex items-start gap-2.5 px-4 py-2 text-sm", config.bgClass),
110
- children: [/* @__PURE__ */ jsx(Icon, { className: cx("w-4 h-4 mt-0.5 shrink-0", config.accentClass) }), /* @__PURE__ */ jsxs("div", {
111
- className: "flex-1 min-w-0",
105
+ const { icon: Icon, tone } = typeConfig[annotation.type] || typeConfig.notice;
106
+ return /* @__PURE__ */ jsxs("li", {
107
+ className: "flex items-start gap-2.5 px-4 py-2 text-sm",
108
+ children: [/* @__PURE__ */ jsx(Icon, { className: cx("mt-0.5 size-4 shrink-0", toneIcon[tone]) }), /* @__PURE__ */ jsxs("div", {
109
+ className: "min-w-0 flex-1",
112
110
  children: [
113
111
  /* @__PURE__ */ jsxs("span", {
114
- className: cx("font-medium", config.accentClass),
112
+ className: cx("font-medium", toneText[tone]),
115
113
  children: [annotation.title || t.annotationType[annotation.type] || t.annotationType.notice, ":"]
116
114
  }),
117
115
  " ",
118
116
  /* @__PURE__ */ jsx("span", {
119
- className: "text-[var(--theme-app)]",
117
+ className: "text-(--theme-app)",
120
118
  children: annotation.message
121
119
  }),
122
120
  /* @__PURE__ */ jsx("span", {
123
- className: "text-[var(--theme-muted-text-color)] ml-2 text-xs",
121
+ className: "ml-2 text-xs text-(--theme-muted-text-color)",
124
122
  children: t.annotationSource(annotation.jobName, annotation.stepName || t.stepNumber(annotation.stepIndex))
125
123
  })
126
124
  ]
@@ -11,7 +11,8 @@ var KEYFRAMES = [
11
11
  "@keyframes dag-draw-in{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}",
12
12
  "@keyframes dag-draw-out{from{stroke-dashoffset:0}to{stroke-dashoffset:1}}",
13
13
  `@keyframes dag-light{from{fill:${CONNECTOR_COLOR}}to{fill:${HIGHLIGHT_COLOR}}}`,
14
- `@keyframes dag-unlight{from{fill:${HIGHLIGHT_COLOR}}to{fill:${CONNECTOR_COLOR}}}`
14
+ `@keyframes dag-unlight{from{fill:${HIGHLIGHT_COLOR}}to{fill:${CONNECTOR_COLOR}}}`,
15
+ "@media (prefers-reduced-motion:reduce){.dag-lit{animation-duration:0s!important;animation-delay:0s!important}}"
15
16
  ].join("");
16
17
  /** Plays the named keyframes once `delay` seconds pass, holding the first until then and the last after. */
17
18
  var play = (name, seconds, delay) => ({ animation: `${name} ${seconds}s ease ${delay}s both` });
@@ -25,6 +26,7 @@ var LitEdge = memo(function LitEdge({ d, reversed, highlight, animT }) {
25
26
  strokeWidth: STROKE,
26
27
  strokeDasharray: "1 1",
27
28
  strokeDashoffset: lit ? 0 : 1,
29
+ className: "dag-lit",
28
30
  style: play(lit ? "dag-draw-in" : "dag-draw-out", animT, delay)
29
31
  });
30
32
  });
@@ -35,6 +37,7 @@ var LitDot = memo(function LitDot({ x, y, highlight, animT }) {
35
37
  cy: y,
36
38
  r: 8,
37
39
  fill: lit ? HIGHLIGHT_COLOR : CONNECTOR_COLOR,
40
+ className: "dag-lit",
38
41
  style: play(lit ? "dag-light" : "dag-unlight", animT, delay)
39
42
  });
40
43
  });
@@ -3,10 +3,10 @@ import { ArrowLeftIcon, ArrowRightIcon, ChevronLeftIcon, ChevronRightIcon, FileT
3
3
  import { Loader } from "../components/Loader.js";
4
4
  import { useRunFile, useSlots, useStrings, useWorkflowEngine } from "../components/Provider.js";
5
5
  import { Button } from "../components/Button.js";
6
+ import { IconButton } from "../components/IconButton.js";
7
+ import { InfoTip } from "../components/InfoTip.js";
6
8
  import { Modal } from "../components/Modal.js";
7
9
  import { DisclosurePanel } from "../components/Disclosure.js";
8
- import { InfoTip } from "../components/InfoTip.js";
9
- import { IconButton } from "../components/IconButton.js";
10
10
  import { formatDateTime } from "../format.js";
11
11
  import { Elapsed } from "../components/relativeTime.js";
12
12
  import { RunStatusIcon } from "../components/RunStatusIcon.js";
@@ -3,8 +3,8 @@ import { AddIcon, DuplicateIcon, EditIcon, GridIcon, LinkIcon, MatrixIcon, Remov
3
3
  import { useWorkflowEditing } from "../components/Provider.js";
4
4
  import { useCopy } from "../components/useCopy.js";
5
5
  import { menuDivider } from "../components/MenuEntries.js";
6
- import { useContextMenu } from "../components/ContextMenu.js";
7
6
  import { IconButton } from "../components/IconButton.js";
7
+ import { useContextMenu } from "../components/ContextMenu.js";
8
8
  import { createStore, reclaimFocus, returningFocus, trackDrag, useFocusAfterDialog, usePressOutside } from "./editorPrimitives.js";
9
9
  import { jobLabel } from "./util.js";
10
10
  import { EDITOR_HANDLE_CLASS, NO_EDGES, NO_PROBLEMS, NO_SELECTION, NO_STEPS, contentBox, labelsOf, sameEdge, sameStep, selectionBounds, toContent, useUi } from "./graphEditorState.js";
@@ -14,7 +14,7 @@ import { openOnAddOf } from "./editorFields.js";
14
14
  import { refusalText } from "./refusalText.js";
15
15
  import { JobDialog, StepDialog } from "./GraphEditorDialogs.js";
16
16
  import { overlaps, typing } from "./editorApi.js";
17
- import { MOD_KEY } from "./ShortcutsButton.js";
17
+ import { IS_MAC, modifierKeys } from "./ShortcutsButton.js";
18
18
  import { AddChip, BarDivider, DragLabel, EditorBar } from "./editorChrome.js";
19
19
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
20
  import { useEffect, useMemo, useRef, useState } from "react";
@@ -1182,7 +1182,7 @@ function useGraphEditorState({ editor, jobs, yamlJobs, inputs, workflow, layout,
1182
1182
  const editable = editor !== void 0;
1183
1183
  useEffect(() => {
1184
1184
  if (!container || !editable) return;
1185
- const mac = /Mac|iPhone|iPad/.test(navigator.platform);
1185
+ const mac = IS_MAC;
1186
1186
  let pointer = null;
1187
1187
  let pending;
1188
1188
  const pasteCopied = () => {
@@ -1307,6 +1307,7 @@ function useGraphEditorState({ editor, jobs, yamlJobs, inputs, workflow, layout,
1307
1307
  }
1308
1308
  function graphShortcuts(t) {
1309
1309
  const key = t.shortcutKeys;
1310
+ const { mod } = modifierKeys(key);
1310
1311
  const does = t.shortcutDoes;
1311
1312
  return [
1312
1313
  {
@@ -1325,7 +1326,7 @@ function graphShortcuts(t) {
1325
1326
  does: does.dependency
1326
1327
  },
1327
1328
  {
1328
- combos: [["Tab"]],
1329
+ combos: [[key.tab]],
1329
1330
  does: does.focus
1330
1331
  },
1331
1332
  {
@@ -1337,7 +1338,7 @@ function graphShortcuts(t) {
1337
1338
  does: does.pickDependency
1338
1339
  },
1339
1340
  {
1340
- combos: [["Esc"]],
1341
+ combos: [[key.escape]],
1341
1342
  does: does.escape
1342
1343
  }
1343
1344
  ]
@@ -1379,13 +1380,13 @@ function graphShortcuts(t) {
1379
1380
  does: does.menu
1380
1381
  },
1381
1382
  {
1382
- combos: [[MOD_KEY, "C"], [MOD_KEY, "V"]],
1383
+ combos: [[mod, "C"], [mod, "V"]],
1383
1384
  does: does.copy
1384
1385
  },
1385
1386
  {
1386
- combos: [[MOD_KEY, "Z"], [
1387
+ combos: [[mod, "Z"], [
1387
1388
  key.shift,
1388
- MOD_KEY,
1389
+ mod,
1389
1390
  "Z"
1390
1391
  ]],
1391
1392
  does: does.undo
@@ -1461,7 +1462,7 @@ function DragOverlays({ api, container, trashRef }) {
1461
1462
  const problem = drag.target?.kind === "steps" ? drag.target.problem : void 0;
1462
1463
  return /* @__PURE__ */ jsxs(Fragment, { children: [drag.payload.kind === "jobs" && /* @__PURE__ */ jsxs("div", {
1463
1464
  ref: trashRef,
1464
- className: cx("absolute bottom-2 left-1/2 z-20 flex -translate-x-1/2 items-center gap-2 rounded-lg border-2 border-dashed px-4 py-2 text-sm", overTrash ? "border-(--theme-error) bg-(--theme-error-muted) text-(--theme-error)" : "theme-border bg-(--theme-panel-bg) theme-muted-text"),
1465
+ className: cx("absolute bottom-2 left-1/2 z-20 flex -translate-x-1/2 items-center gap-2 rounded-lg border-2 border-dashed px-4 py-2 text-sm", overTrash ? "border-(--theme-error) bg-(--theme-error-muted) text-(--theme-error-text)" : "theme-border bg-(--theme-panel-bg) theme-muted-text"),
1465
1466
  children: [/* @__PURE__ */ jsx(TrashIcon, { className: "h-4 w-4" }), t.dropToDelete]
1466
1467
  }), drag.payload.kind !== "connect" && /* @__PURE__ */ jsx(DragLabel, {
1467
1468
  at: {
@@ -1481,8 +1482,9 @@ function EditorDialogs({ api, editor, jobs, inputs, workflow }) {
1481
1482
  editor.onEdit(edit);
1482
1483
  };
1483
1484
  const openOnAdd = openOnAddOf(editor);
1485
+ const addition = dialog?.addition;
1486
+ const copy = useMemo(() => addition ? asRecord(editing.loadYaml(addition.yml)) : null, [addition, editing]);
1484
1487
  if (!dialog) return null;
1485
- const copy = dialog.addition ? asRecord(editing.loadYaml(dialog.addition.yml)) : null;
1486
1488
  const here = copy ? asRecord(copy["jobs"]) : jobs;
1487
1489
  const source = dialog.addition?.yml ?? editor.readSource?.();
1488
1490
  if (dialog.kind === "job") return Object.hasOwn(here, dialog.job) ? /* @__PURE__ */ jsx(JobDialog, {
@@ -1,10 +1,10 @@
1
1
  import { ArrowDownIcon, ArrowUpIcon, RemoveIcon, TrashIcon } from "../icons.js";
2
2
  import { withPositionKeys } from "../components/keys.js";
3
3
  import { useWorkflowActions, useWorkflowEditing } from "../components/Provider.js";
4
+ import { IconButton } from "../components/IconButton.js";
4
5
  import { Checkbox } from "../components/Checkbox.js";
5
6
  import { ErrorText, FieldOption } from "../components/Field.js";
6
7
  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";
@@ -722,7 +722,7 @@ function JobForm({ job, jobs, inputs, workflow, onEdit, onClose, renderShell, on
722
722
  children: other
723
723
  }),
724
724
  !Object.hasOwn(jobs, other) && /* @__PURE__ */ jsx("span", {
725
- className: "text-xs text-(--theme-error)",
725
+ className: "text-xs text-(--theme-error-text)",
726
726
  children: t.missingJob
727
727
  })
728
728
  ]
@@ -13,10 +13,10 @@ var dimClasses = (depth) => ({
13
13
  /** The rules dimming a level at `depth`, hoisted into the page once for every level that deep. */
14
14
  function DimRules({ depth }) {
15
15
  const { level, node, edge } = dimClasses(depth);
16
- return /* @__PURE__ */ jsx("style", {
16
+ return /* @__PURE__ */ jsxs("style", {
17
17
  href: `dependency-graph-dim-${depth}`,
18
18
  precedence: "default",
19
- children: `.${level} .${node}{opacity:.5}.${level} .${edge}{opacity:.3}`
19
+ children: [`.${level} .${node}{opacity:.5}.${level} .${edge}{opacity:.3}`, "@media (prefers-reduced-motion:reduce){.dag-fade{transition:none!important}}"]
20
20
  });
21
21
  }
22
22
  /** Dims what of a graph level isn't in the hovered job's lineage, while one is hovered. */
@@ -29,6 +29,9 @@ function GraphNode({ id, job, rowsAbove, zBase, children }) {
29
29
  const highlight = useLineage((l) => l.node(job), 0);
30
30
  const enter = () => lineage?.hover(job);
31
31
  const leave = () => lineage?.hover(null);
32
+ const blur = (e) => {
33
+ if (!e.currentTarget.contains(e.relatedTarget)) leave();
34
+ };
32
35
  return /* @__PURE__ */ jsxs("div", {
33
36
  id,
34
37
  role: "none",
@@ -40,9 +43,9 @@ function GraphNode({ id, job, rowsAbove, zBase, children }) {
40
43
  onMouseEnter: enter,
41
44
  onMouseLeave: leave,
42
45
  onFocus: enter,
43
- onBlur: leave,
46
+ onBlur: blur,
44
47
  children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-2xl bg-(--theme-panel-bg)" }), /* @__PURE__ */ jsx("div", {
45
- className: `${dimClasses(lineage?.depth ?? 0).node} relative border-solid shadow py-4 px-8 rounded-xl border-4 whitespace-nowrap bg-(--theme-panel-bg) text-2xl`,
48
+ className: `${dimClasses(lineage?.depth ?? 0).node} dag-fade relative border-solid shadow py-4 px-8 rounded-xl border-4 whitespace-nowrap bg-(--theme-panel-bg) text-2xl`,
46
49
  style: {
47
50
  ...highlight === 2 && { opacity: 1 },
48
51
  ...lineage?.fade && { transition: `opacity ${lineage.animT}s` }
@@ -2,11 +2,11 @@ import { cx } from "../cx.js";
2
2
  import { ArrowDownIcon, ArrowUpIcon, EditIcon, RemoveIcon, TrashIcon } from "../icons.js";
3
3
  import { withPositionKeys } from "../components/keys.js";
4
4
  import { useWorkflowEditing, useWorkflowEngine } from "../components/Provider.js";
5
+ import { IconButton } from "../components/IconButton.js";
5
6
  import { Checkbox, CheckboxGroup } from "../components/Checkbox.js";
6
7
  import { ErrorText, Field, FieldOption } from "../components/Field.js";
7
8
  import { Input, Textarea } from "../components/Input.js";
8
9
  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";
@@ -1,13 +1,14 @@
1
1
  import { cx } from "../cx.js";
2
2
  import { AddIcon, ArrowDownIcon, ArrowUpIcon, CollapseIcon, DragHandleIcon, DuplicateIcon, EditIcon, FilesIcon, MinusIcon, MoreIcon, TrashIcon, WarningIcon } from "../icons.js";
3
- import { EmptyState } from "../components/EmptyState.js";
4
3
  import { Tooltip } from "../components/Tooltip.js";
5
4
  import { useWorkflowEditing } from "../components/Provider.js";
5
+ import { EmptyState } from "../components/EmptyState.js";
6
6
  import { menuDivider } from "../components/MenuEntries.js";
7
- import { useContextMenu } from "../components/ContextMenu.js";
8
7
  import { IconButton } from "../components/IconButton.js";
8
+ import { useContextMenu } from "../components/ContextMenu.js";
9
9
  import { NumberInput } from "../components/NumberInput.js";
10
10
  import { MarqueeBox, createStore, reclaimFocus, returningFocus, trackDrag, useFocusAfterDialog, usePressOutside, useStore } from "./editorPrimitives.js";
11
+ import { prefersReducedMotion } from "../reducedMotion.js";
11
12
  import { useGraphEditorStrings, useInputsEditorStrings } from "./editorStrings.js";
12
13
  import { asRecord } from "./records.js";
13
14
  import { openOnAddOf, text } from "./editorFields.js";
@@ -16,7 +17,7 @@ import { WizardPagesContext } from "../form/Wizard/wizardPages.js";
16
17
  import { dropLayoutEdits, isWizard, resizeLayout, withInputLayouts } from "./inputLayout.js";
17
18
  import { INPUT_TYPE_GROUPS, InputDialog, TypeBadge, allNames, newInputDefinition, withCreatedInputs } from "./InputDialog.js";
18
19
  import { overlaps, typing } from "./editorApi.js";
19
- import { ALT_KEY, MOD_KEY } from "./ShortcutsButton.js";
20
+ import { modifierKeys } from "./ShortcutsButton.js";
20
21
  import { AddChip, BarDivider, DragLabel, EditorBar } from "./editorChrome.js";
21
22
  import { addPageEdit, splitIntoPagesEdits, unsplitPagesEdits, wizardGroupDefinition } from "./inputPages.js";
22
23
  import { inputCell, linesIn, rowsOf, snapSplit } from "./inputRows.js";
@@ -112,7 +113,8 @@ function InputRow({ path, hidden = false, instance, children }) {
112
113
  const actions = /* @__PURE__ */ jsxs(Fragment, { children: [
113
114
  /* @__PURE__ */ jsx("button", {
114
115
  type: "button",
115
- "aria-label": t.inputActions,
116
+ tabIndex: -1,
117
+ "aria-hidden": true,
116
118
  "data-drag-handle": true,
117
119
  className: "flex h-5 w-5 cursor-grab items-center justify-center rounded hover:bg-(--theme-muted-panel-bg)",
118
120
  onPointerDown: (e) => api.startDrag(e, path, name),
@@ -203,7 +205,7 @@ function InputRow({ path, hidden = false, instance, children }) {
203
205
  })
204
206
  ]
205
207
  }) : /* @__PURE__ */ jsx("div", {
206
- className: cx("flex justify-end overflow-hidden transition-[height] duration-150 focus-within:h-7", active ? "h-7" : "h-0"),
208
+ className: cx("flex justify-end overflow-hidden transition-[height] duration-150 focus-within:h-7 motion-reduce:transition-none", active ? "h-7" : "h-0"),
207
209
  children: /* @__PURE__ */ jsx("div", {
208
210
  "data-input-chrome": true,
209
211
  className: "flex h-6 items-center gap-0.5 rounded-md border theme-border bg-(--theme-panel-bg) px-1 py-0.5 text-[11px] leading-4 theme-muted-text shadow-sm",
@@ -306,7 +308,7 @@ function PageNumber({ count, page, onChange }) {
306
308
  if (typed !== null && Number.isInteger(typed) && typed >= 1 && typed <= count) onChange(typed - 1);
307
309
  }
308
310
  }),
309
- /* @__PURE__ */ jsxs("span", { children: ["/ ", count] })
311
+ /* @__PURE__ */ jsx("span", { children: t.pageTotal(count) })
310
312
  ]
311
313
  });
312
314
  }
@@ -638,6 +640,7 @@ function undoKeys(e, editor) {
638
640
  }
639
641
  function formShortcuts(g) {
640
642
  const key = g.shortcutKeys;
643
+ const { mod, alt } = modifierKeys(key);
641
644
  const does = g.shortcutDoes;
642
645
  return [{
643
646
  title: g.shortcutGroups.select,
@@ -664,7 +667,7 @@ function formShortcuts(g) {
664
667
  does: does.extendInputs
665
668
  },
666
669
  {
667
- combos: [["Esc"]],
670
+ combos: [[key.escape]],
668
671
  does: does.escape
669
672
  }
670
673
  ]
@@ -680,7 +683,7 @@ function formShortcuts(g) {
680
683
  does: does.resizeInputs
681
684
  },
682
685
  {
683
- combos: [[ALT_KEY, "↑"], [ALT_KEY, "↓"]],
686
+ combos: [[alt, "↑"], [alt, "↓"]],
684
687
  does: does.reorderInputs
685
688
  },
686
689
  {
@@ -700,9 +703,9 @@ function formShortcuts(g) {
700
703
  does: does.inputMenu
701
704
  },
702
705
  {
703
- combos: [[MOD_KEY, "Z"], [
706
+ combos: [[mod, "Z"], [
704
707
  key.shift,
705
- MOD_KEY,
708
+ mod,
706
709
  "Z"
707
710
  ]],
708
711
  does: does.undo
@@ -1257,7 +1260,7 @@ function InputsFormEditor({ editor, inputs, children }) {
1257
1260
  const key = problem.input ? JSON.stringify(problem.input) : null;
1258
1261
  const row = [...containerRef.current?.querySelectorAll("[data-input-path]") ?? []].find((el) => el.dataset["inputPath"] === key);
1259
1262
  if (!row) return false;
1260
- const still = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1263
+ const still = prefersReducedMotion();
1261
1264
  row.scrollIntoView?.({
1262
1265
  block: "center",
1263
1266
  behavior: still ? "auto" : "smooth"
@@ -4,7 +4,7 @@ import { EditableJobRow } from "./editorRows.js";
4
4
  import { Reveal } from "./Reveal.js";
5
5
  import { Joblist } from "./JobSummary.js";
6
6
  import { GraphNode } from "./GraphNode.js";
7
- import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  import { memo } from "react";
9
9
  //#region src/graph/MatrixGroup.tsx
10
10
  /** Matrix group item in the summary sidebar. */
@@ -55,8 +55,14 @@ var MatrixGroupNode = memo(function MatrixGroupNode({ matrixGroup, jobNames, idP
55
55
  className: "cursor-pointer w-full text-left",
56
56
  onClick: () => toggleMatrix(idPrefix + matrixName),
57
57
  children: [/* @__PURE__ */ jsx("div", {
58
- className: "font-semibold text-md p-0.5",
59
- children: t.matrixOf(matrixName.length > 20 ? `${matrixName.slice(0, 20)}...` : matrixName)
58
+ className: "font-semibold p-0.5",
59
+ children: matrixName.length > 20 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
60
+ "aria-hidden": true,
61
+ children: t.matrixOf(`${matrixName.slice(0, 20)}…`)
62
+ }), /* @__PURE__ */ jsx("span", {
63
+ className: "sr-only",
64
+ children: t.matrixOf(matrixName)
65
+ })] }) : t.matrixOf(matrixName)
60
66
  }), !isExpanded && /* @__PURE__ */ jsxs("div", {
61
67
  className: "mt-1 border-t border-(--theme-border) pt-1 flex items-center gap-x-1",
62
68
  children: [!preview && /* @__PURE__ */ jsx(RunStatusIcon, { status: aggStatus }), /* @__PURE__ */ jsx("span", { children: preview ? t.jobCount(matrixMembers.length) : statusLabel })]
@@ -24,7 +24,7 @@ function ProblemsButton({ problems }) {
24
24
  children: /* @__PURE__ */ jsxs("button", {
25
25
  type: "button",
26
26
  "aria-label": label,
27
- className: "flex h-7 cursor-pointer items-center gap-1 rounded px-2 text-xs font-medium text-(--theme-error) theme-hover",
27
+ className: "flex h-7 cursor-pointer items-center gap-1 rounded px-2 text-xs font-medium text-(--theme-error-text) theme-hover",
28
28
  children: [/* @__PURE__ */ jsx(WarningIcon, { className: "h-3.5 w-3.5" }), problems.length]
29
29
  })
30
30
  }),
@@ -36,7 +36,7 @@ function ProblemsButton({ problems }) {
36
36
  className: "mr-1.5 theme-muted-text",
37
37
  children: t.problemLine(problem.line)
38
38
  }), /* @__PURE__ */ jsx("span", {
39
- className: "text-(--theme-error)",
39
+ className: "text-(--theme-error-text)",
40
40
  children: problem.message
41
41
  })] });
42
42
  return /* @__PURE__ */ jsx("li", { children: pick ? /* @__PURE__ */ jsx("button", {