@parallelworks/ui 0.49.0 → 0.51.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 (49) hide show
  1. package/README.md +50 -5
  2. package/dist/ai/components/ModelSelector.js +1 -1
  3. package/dist/ai/components/agent/AgentMessageParts.js +3 -3
  4. package/dist/components/Callout.js +3 -7
  5. package/dist/components/CreateModal.js +1 -1
  6. package/dist/components/DescriptionList.d.ts +31 -17
  7. package/dist/components/DescriptionList.js +83 -31
  8. package/dist/components/Field.d.ts +5 -1
  9. package/dist/components/Field.js +18 -5
  10. package/dist/components/MenuEntries.d.ts +39 -12
  11. package/dist/components/MenuEntries.js +24 -8
  12. package/dist/components/Meter.js +3 -3
  13. package/dist/components/PageHeader.d.ts +4 -1
  14. package/dist/components/PageHeader.js +5 -4
  15. package/dist/components/Provider.d.ts +2 -0
  16. package/dist/components/Provider.js +1 -0
  17. package/dist/components/RequiredMark.js +1 -1
  18. package/dist/components/RunStatusIcon.js +2 -2
  19. package/dist/components/StatusIcons.js +2 -2
  20. package/dist/components/ThemeEditor.js +6 -6
  21. package/dist/components/Toast.js +2 -2
  22. package/dist/components/buttonClasses.js +1 -1
  23. package/dist/components/splitter.js +9 -3
  24. package/dist/components/tone.d.ts +5 -2
  25. package/dist/components/tone.js +15 -6
  26. package/dist/form/Wizard/WizardNavigation.js +1 -1
  27. package/dist/form/Wizard/WizardStepIndicator.js +1 -1
  28. package/dist/graph/DependencyGraph.js +1 -1
  29. package/dist/graph/GraphEditor.js +1 -1
  30. package/dist/graph/GraphEditorDialogs.js +1 -1
  31. package/dist/graph/ProblemsButton.js +2 -2
  32. package/dist/graph/ShortcutsButton.js +1 -1
  33. package/dist/graph/editorChrome.js +1 -1
  34. package/dist/graph/fieldProblems.js +1 -1
  35. package/dist/graph/stepWith.js +1 -1
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.js +2 -2
  38. package/dist/list/ActionToolbar.d.ts +2 -2
  39. package/dist/list/ActionToolbar.js +6 -3
  40. package/dist/list/ListPage.js +4 -2
  41. package/dist/list/ListViewControls.js +1 -1
  42. package/dist/list/rowMenu.d.ts +2 -2
  43. package/dist/logviewer/LogViewer.js +1 -1
  44. package/dist/styles/theme.css +24 -10
  45. package/dist/styles.css +1 -1
  46. package/dist/theme/derive.d.ts +1 -1
  47. package/dist/theme/derive.js +46 -21
  48. package/dist/theme/fit.js +10 -4
  49. package/package.json +1 -1
@@ -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")
@@ -3,10 +3,10 @@ import { ErrorIcon, SuccessIcon } from "../icons.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/components/StatusIcons.tsx
5
5
  function SuccessCheckmark({ className, colored = true }) {
6
- return /* @__PURE__ */ jsx(SuccessIcon, { className: cx(colored && "text-green-500", className) });
6
+ return /* @__PURE__ */ jsx(SuccessIcon, { className: cx(colored && "text-(--theme-success)", className) });
7
7
  }
8
8
  function ErrorCheckmark({ className, colored = true }) {
9
- return /* @__PURE__ */ jsx(ErrorIcon, { className: cx(colored && "text-red-400", className) });
9
+ return /* @__PURE__ */ jsx(ErrorIcon, { className: cx(colored && "text-(--theme-error)", className) });
10
10
  }
11
11
  //#endregion
12
12
  export { ErrorCheckmark, SuccessCheckmark };
@@ -318,13 +318,13 @@ function ThemePreview({ theme, mode }) {
318
318
  /* @__PURE__ */ jsxs("div", {
319
319
  className: "flex flex-wrap items-center gap-2",
320
320
  children: [
321
- /* @__PURE__ */ jsx("span", {
322
- className: "rounded-full bg-(--theme-success-muted) px-2 py-0.5 text-xs text-(--theme-success)",
323
- children: t.previewPassed
321
+ /* @__PURE__ */ jsxs("span", {
322
+ className: "inline-flex items-center gap-1.5 rounded-full bg-(--theme-success-muted) px-2 py-0.5 text-xs text-(--theme-success-text)",
323
+ children: [/* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-(--theme-success)" }), t.previewPassed]
324
324
  }),
325
- /* @__PURE__ */ jsx("span", {
326
- className: "rounded-full bg-(--theme-error-muted) px-2 py-0.5 text-xs text-(--theme-error)",
327
- children: t.previewFailed
325
+ /* @__PURE__ */ jsxs("span", {
326
+ className: "inline-flex items-center gap-1.5 rounded-full bg-(--theme-error-muted) px-2 py-0.5 text-xs text-(--theme-error-text)",
327
+ children: [/* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-(--theme-error)" }), t.previewFailed]
328
328
  }),
329
329
  /* @__PURE__ */ jsx("span", {
330
330
  className: "text-(--theme-link) underline underline-offset-2",
@@ -2,7 +2,7 @@ import { cx } from "../cx.js";
2
2
  import { CloseIcon, ErrorIcon, InfoIcon, SuccessIcon, WarningIcon } from "../icons.js";
3
3
  import { buttonClasses } from "./buttonClasses.js";
4
4
  import { Loader } from "./Loader.js";
5
- import { toneText } from "./tone.js";
5
+ import { toneIcon } from "./tone.js";
6
6
  import { useStrings } from "./Provider.js";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { useEffect, useId, useSyncExternalStore } from "react";
@@ -149,7 +149,7 @@ function ToneIcon({ tone }) {
149
149
  const Icon = ICONS[tone];
150
150
  return /* @__PURE__ */ jsx(Icon, {
151
151
  "aria-hidden": "true",
152
- className: cx("mt-0.5 size-4 shrink-0", toneText[tone])
152
+ className: cx("mt-0.5 size-4 shrink-0", toneIcon[tone])
153
153
  });
154
154
  }
155
155
  function ToastList() {
@@ -6,7 +6,7 @@ var variants = {
6
6
  secondary: "border border-(--theme-border) bg-(--theme-panel-bg) text-(--theme-app) hover:not-disabled:not-aria-disabled:bg-(--theme-hover)",
7
7
  outline: "border border-(--theme-border) text-(--theme-muted-text-color) hover:not-disabled:not-aria-disabled:bg-(--theme-muted-panel-bg) hover:not-disabled:not-aria-disabled:text-(--theme-app) aria-pressed:border-(--theme-link) aria-pressed:text-(--theme-app) data-selected:border-(--theme-link) data-selected:text-(--theme-app) data-popup-open:bg-(--theme-muted-panel-bg) data-popup-open:text-(--theme-app)",
8
8
  ghost: "text-(--theme-muted-text-color) hover:not-disabled:not-aria-disabled:bg-(--theme-muted-panel-bg) hover:not-disabled:not-aria-disabled:text-(--theme-app) aria-pressed:bg-(--theme-muted-panel-bg) aria-pressed:text-(--theme-link) data-selected:bg-(--theme-muted-panel-bg) data-selected:text-(--theme-link) data-popup-open:bg-(--theme-muted-panel-bg) data-popup-open:text-(--theme-app)",
9
- danger: "bg-(--theme-error) text-white hover:not-disabled:not-aria-disabled:bg-(--theme-error)/90"
9
+ danger: "bg-(--theme-error-solid) text-white hover:not-disabled:not-aria-disabled:bg-(--theme-error-solid)/90"
10
10
  };
11
11
  var sizes = {
12
12
  xs: "h-6 px-2 text-xs [&_svg]:size-3",
@@ -18,15 +18,21 @@ function useSplitter({ width, onWidthChange, min, max, side, defaultWidth, label
18
18
  e.currentTarget.setPointerCapture?.(e.pointerId);
19
19
  drag.current = {
20
20
  x: e.clientX,
21
- width
21
+ width,
22
+ live: width
22
23
  };
23
24
  setLive(width);
24
25
  };
25
26
  const onPointerMove = (e) => {
26
- if (drag.current) setLive(clamp(drag.current.width + (e.clientX - drag.current.x) * grows));
27
+ const current = drag.current;
28
+ if (current) {
29
+ current.live = clamp(current.width + (e.clientX - current.x) * grows);
30
+ setLive(current.live);
31
+ }
27
32
  };
28
33
  const onPointerUp = () => {
29
- if (drag.current && live !== null && live !== width) onWidthChange(live);
34
+ const ended = drag.current;
35
+ if (ended && ended.live !== ended.width) onWidthChange(ended.live);
30
36
  drag.current = null;
31
37
  setLive(null);
32
38
  };
@@ -1,9 +1,12 @@
1
1
  /** How a status reads: its colors come from the theme's tone tokens, so every
2
- * theme, dark ones included, sets them once. */
2
+ * theme, dark ones included, sets them once. Words take a status's text shade,
3
+ * and icons and dots its vivid one, which only graphics' 3:1 holds. */
3
4
  export type Tone = 'default' | 'success' | 'warning' | 'error' | 'info' | 'muted';
4
5
  /** Text in the tone, for a status line beside a dot or icon. */
5
6
  export declare const toneText: Record<Tone, string>;
7
+ /** An icon in the tone, through `currentColor`. */
8
+ export declare const toneIcon: Record<Tone, string>;
6
9
  /** A tinted surface with a border and text in the tone, for a badge or a callout. */
7
10
  export declare const toneSurface: Record<Tone, string>;
8
- /** A solid fill in the tone, for a dot. */
11
+ /** A solid fill in the tone, for a dot or a bar. */
9
12
  export declare const toneFill: Record<Tone, string>;
@@ -1,6 +1,15 @@
1
1
  //#region src/components/tone.ts
2
2
  /** Text in the tone, for a status line beside a dot or icon. */
3
3
  var toneText = {
4
+ default: "text-(--theme-app)",
5
+ success: "text-(--theme-success-text)",
6
+ warning: "text-(--theme-warning-text)",
7
+ error: "text-(--theme-error-text)",
8
+ info: "text-(--theme-info-text)",
9
+ muted: "text-(--theme-muted-text-color)"
10
+ };
11
+ /** An icon in the tone, through `currentColor`. */
12
+ var toneIcon = {
4
13
  default: "text-(--theme-app)",
5
14
  success: "text-(--theme-success)",
6
15
  warning: "text-(--theme-warning)",
@@ -11,13 +20,13 @@ var toneText = {
11
20
  /** A tinted surface with a border and text in the tone, for a badge or a callout. */
12
21
  var toneSurface = {
13
22
  default: "bg-(--theme-muted-panel-bg) text-(--theme-app) border-(--theme-border)",
14
- success: "bg-(--theme-success-muted) text-(--theme-success) border-(--theme-success)/25",
15
- warning: "bg-(--theme-warning-muted) text-(--theme-warning) border-(--theme-warning)/25",
16
- error: "bg-(--theme-error-muted) text-(--theme-error) border-(--theme-error)/25",
17
- info: "bg-(--theme-info-muted) text-(--theme-info) border-(--theme-info)/25",
23
+ success: "bg-(--theme-success-muted) text-(--theme-success-text) border-(--theme-success)/25",
24
+ warning: "bg-(--theme-warning-muted) text-(--theme-warning-text) border-(--theme-warning)/25",
25
+ error: "bg-(--theme-error-muted) text-(--theme-error-text) border-(--theme-error)/25",
26
+ info: "bg-(--theme-info-muted) text-(--theme-info-text) border-(--theme-info)/25",
18
27
  muted: "bg-(--theme-muted-panel-bg)/50 text-(--theme-muted-text-color) border-(--theme-border)"
19
28
  };
20
- /** A solid fill in the tone, for a dot. */
29
+ /** A solid fill in the tone, for a dot or a bar. */
21
30
  var toneFill = {
22
31
  default: "bg-(--theme-app)",
23
32
  success: "bg-(--theme-success)",
@@ -27,4 +36,4 @@ var toneFill = {
27
36
  muted: "bg-(--theme-muted-text-color)"
28
37
  };
29
38
  //#endregion
30
- export { toneFill, toneSurface, toneText };
39
+ export { toneFill, toneIcon, toneSurface, toneText };
@@ -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"
@@ -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", {
@@ -5,8 +5,8 @@ import { useRunFile, useSlots, useStrings, useWorkflowEngine } from "../componen
5
5
  import { Button } from "../components/Button.js";
6
6
  import { Modal } from "../components/Modal.js";
7
7
  import { DisclosurePanel } from "../components/Disclosure.js";
8
- import { InfoTip } from "../components/InfoTip.js";
9
8
  import { IconButton } from "../components/IconButton.js";
9
+ import { InfoTip } from "../components/InfoTip.js";
10
10
  import { formatDateTime } from "../format.js";
11
11
  import { Elapsed } from "../components/relativeTime.js";
12
12
  import { RunStatusIcon } from "../components/RunStatusIcon.js";
@@ -1461,7 +1461,7 @@ function DragOverlays({ api, container, trashRef }) {
1461
1461
  const problem = drag.target?.kind === "steps" ? drag.target.problem : void 0;
1462
1462
  return /* @__PURE__ */ jsxs(Fragment, { children: [drag.payload.kind === "jobs" && /* @__PURE__ */ jsxs("div", {
1463
1463
  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"),
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-text)" : "theme-border bg-(--theme-panel-bg) theme-muted-text"),
1465
1465
  children: [/* @__PURE__ */ jsx(TrashIcon, { className: "h-4 w-4" }), t.dropToDelete]
1466
1466
  }), drag.payload.kind !== "connect" && /* @__PURE__ */ jsx(DragLabel, {
1467
1467
  at: {
@@ -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
  ]
@@ -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", {
@@ -1,6 +1,6 @@
1
1
  import { KeyboardIcon } from "../icons.js";
2
- import { Popover } from "../components/Popover.js";
3
2
  import { IconButton } from "../components/IconButton.js";
3
+ import { Popover } from "../components/Popover.js";
4
4
  import { useGraphEditorStrings } from "./editorStrings.js";
5
5
  import { toolbarPanel } from "./toolbarPanel.js";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -10,7 +10,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
10
  /** What a drag carries, beside the pointer at `at` in its layer's coordinates. */
11
11
  function DragLabel({ at, text, refused = false }) {
12
12
  return /* @__PURE__ */ jsx("div", {
13
- className: cx("pointer-events-none absolute z-30 rounded-md border bg-(--theme-panel-bg) px-2 py-1 text-xs shadow", refused ? "border-(--theme-error) text-(--theme-error)" : "theme-border"),
13
+ className: cx("pointer-events-none absolute z-30 rounded-md border bg-(--theme-panel-bg) px-2 py-1 text-xs shadow", refused ? "border-(--theme-error) text-(--theme-error-text)" : "theme-border"),
14
14
  style: {
15
15
  left: at.x + 12,
16
16
  top: at.y + 12
@@ -92,7 +92,7 @@ function ProblemList({ problems }) {
92
92
  if (problems.length === 0) return null;
93
93
  const fieldOf = (problem) => [...fields ?? []].filter(([key]) => within(problem, key)).sort(([a], [b]) => b.length - a.length)[0]?.[1];
94
94
  return /* @__PURE__ */ jsx("ul", {
95
- className: "flex flex-col gap-1 text-sm text-(--theme-error)",
95
+ className: "flex flex-col gap-1 text-sm text-(--theme-error-text)",
96
96
  children: keyedByContent(problems, (problem) => `${problem.at.join(".")}:${problem.message}`).map(({ key, item: problem }) => {
97
97
  const field = fieldOf(problem);
98
98
  return /* @__PURE__ */ jsxs("li", {
@@ -515,7 +515,7 @@ function ExtraKey({ name, uses, draft, original, onChange }) {
515
515
  children: name
516
516
  }),
517
517
  /* @__PURE__ */ jsx("span", {
518
- className: "text-xs text-(--theme-error)",
518
+ className: "text-xs text-(--theme-error-text)",
519
519
  children: t.notActionInput
520
520
  }),
521
521
  /* @__PURE__ */ jsx(IconButton, {
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export { type OpenMenu, type OpenMenuOptions, useContextMenu, } from './componen
13
13
  export { CopyCodeBlock, default as CopyToClipboard } from './components/CopyToClipboard.js';
14
14
  export { CreateModal, CreateModalSelect, CreateModalSwitch, } from './components/CreateModal.js';
15
15
  export { DatePicker, type DatePickerProps } from './components/DatePicker.js';
16
- export { DescriptionListItem, default as DescriptionList } from './components/DescriptionList.js';
16
+ export { DescriptionListItem, type DescriptionListItemProps, type DescriptionListProps, type DescriptionListVariant, default as DescriptionList, } from './components/DescriptionList.js';
17
17
  export { Disclosure, DisclosurePanel, type DisclosureProps } from './components/Disclosure.js';
18
18
  export { Drawer, type DrawerProps } from './components/Drawer.js';
19
19
  export { EmptyState, type EmptyStateProps } from './components/EmptyState.js';
package/dist/index.js CHANGED
@@ -35,14 +35,14 @@ import { Disclosure, DisclosurePanel } from "./components/Disclosure.js";
35
35
  import { Switch } from "./components/Switch.js";
36
36
  import { CreateModal, CreateModalSelect, CreateModalSwitch } from "./components/CreateModal.js";
37
37
  import { DatePicker } from "./components/DatePicker.js";
38
+ import { isTextEntryContext, useShortcutKey } from "./components/shortcutKey.js";
39
+ import { IconButton } from "./components/IconButton.js";
38
40
  import { ExternalLink } from "./components/ExternalLink.js";
39
41
  import { Popover, PopoverClose, useClosePopover } from "./components/Popover.js";
40
42
  import { InfoTip, formatInfoTipContent } from "./components/InfoTip.js";
41
43
  import DescriptionList, { DescriptionListItem } from "./components/DescriptionList.js";
42
44
  import { Drawer } from "./components/Drawer.js";
43
45
  import { HoverCard } from "./components/HoverCard.js";
44
- import { isTextEntryContext, useShortcutKey } from "./components/shortcutKey.js";
45
- import { IconButton } from "./components/IconButton.js";
46
46
  import { LetterBadge } from "./components/LetterBadge.js";
47
47
  import Markdown from "./components/Markdown.js";
48
48
  import { Meter, ProgressBar, levelTone } from "./components/Meter.js";
@@ -1,10 +1,10 @@
1
1
  import type { RowAction } from './rowMenu.js';
2
2
  /** A toolbar button, which moves into the `…` menu as a row when the toolbar runs out of room. */
3
- export interface ToolbarAction extends RowAction {
3
+ export type ToolbarAction = RowAction & {
4
4
  /** A hint on the enabled button. */
5
5
  tooltip?: string | undefined;
6
6
  hidden?: boolean;
7
- }
7
+ };
8
8
  /** A pre-rendered element (e.g. a button component that owns its modal). */
9
9
  interface ToolbarElement {
10
10
  key: string;
@@ -4,7 +4,7 @@ import { MenuPopup } from "../components/Menu.js";
4
4
  import { buttonClasses } from "../components/buttonClasses.js";
5
5
  import { Tooltip } from "../components/Tooltip.js";
6
6
  import { useLink, useStrings } from "../components/Provider.js";
7
- import { MenuEntries } from "../components/MenuEntries.js";
7
+ import { MenuEntries, useRunAction, warnIfInert } from "../components/MenuEntries.js";
8
8
  import { Button } from "../components/Button.js";
9
9
  import { Menu } from "@base-ui/react/menu";
10
10
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -20,12 +20,15 @@ function ToolbarItemView({ item }) {
20
20
  function ToolbarButton({ action }) {
21
21
  const inOverflowMenu = useContext(OverflowMenuContext);
22
22
  const Link = useLink();
23
+ const runAction = useRunAction();
23
24
  if (inOverflowMenu) return /* @__PURE__ */ jsx(MenuEntries, { entries: [action] });
24
25
  const className = buttonClasses({
25
26
  variant: action.checked === false ? "outline" : "primary",
26
27
  size: "md"
27
28
  });
28
29
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [action.icon, action.label] });
30
+ warnIfInert(action, "ActionToolbar");
31
+ const run = () => runAction(action);
29
32
  let control;
30
33
  if (action.href && !action.disabled) control = /* @__PURE__ */ jsx(Link, {
31
34
  href: action.href,
@@ -34,7 +37,7 @@ function ToolbarButton({ action }) {
34
37
  });
35
38
  else if (action.checked !== void 0) control = /* @__PURE__ */ jsx(Toggle, {
36
39
  pressed: action.checked,
37
- onPressedChange: () => action.onClick?.(),
40
+ onPressedChange: run,
38
41
  disabled: action.disabled,
39
42
  className,
40
43
  children: content
@@ -42,7 +45,7 @@ function ToolbarButton({ action }) {
42
45
  else control = /* @__PURE__ */ jsx(Button, {
43
46
  variant: "primary",
44
47
  size: "md",
45
- onClick: action.onClick,
48
+ onClick: run,
46
49
  disabled: action.disabled,
47
50
  focusableWhenDisabled: true,
48
51
  children: content
@@ -1,7 +1,7 @@
1
1
  import { cx } from "../cx.js";
2
2
  import { Tooltip } from "../components/Tooltip.js";
3
3
  import { useLink, useNavigation } from "../components/Provider.js";
4
- import { isMenuDivider, isMenuSubmenu } from "../components/MenuEntries.js";
4
+ import { isMenuDivider, isMenuSubmenu, useRunAction, warnIfInert } from "../components/MenuEntries.js";
5
5
  import { PageHeader } from "../components/PageHeader.js";
6
6
  import { Table } from "../components/Table.js";
7
7
  import { ListActionsHeader } from "./ListTable.js";
@@ -136,7 +136,9 @@ function ListRow({ href, onActivate, items, goTo, openMenu, pinnedActions, selec
136
136
  });
137
137
  }
138
138
  function PinnedActionButton({ action, visible }) {
139
+ warnIfInert(action, "ListPage pinned action");
139
140
  const Link = useLink();
141
+ const runAction = useRunAction();
140
142
  const reason = action.disabled ? action.disabledReason : void 0;
141
143
  const props = {
142
144
  "aria-label": reason ? `${action.label}. ${reason}` : action.label,
@@ -154,7 +156,7 @@ function PinnedActionButton({ action, visible }) {
154
156
  "aria-disabled": action.disabled,
155
157
  onClick: (e) => {
156
158
  e.stopPropagation();
157
- if (!action.disabled) action.onClick?.();
159
+ if (!action.disabled) runAction(action);
158
160
  },
159
161
  ...props,
160
162
  children: action.icon
@@ -5,9 +5,9 @@ import { Tooltip } from "../components/Tooltip.js";
5
5
  import { useStrings } from "../components/Provider.js";
6
6
  import { useQueryMatch } from "../components/search.js";
7
7
  import { Switch } from "../components/Switch.js";
8
+ import { IconButton } from "../components/IconButton.js";
8
9
  import { Popover } from "../components/Popover.js";
9
10
  import { InfoTip } from "../components/InfoTip.js";
10
- import { IconButton } from "../components/IconButton.js";
11
11
  import { Select } from "../components/Select.js";
12
12
  import { Menu } from "@base-ui/react/menu";
13
13
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -2,9 +2,9 @@ import type { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
2
2
  import type { OpenMenu } from '../components/ContextMenu.js';
3
3
  import type { MenuAction, MenuEntry, MenuSubmenu } from '../components/MenuEntries.js';
4
4
  /** An action on a row, which its menu lists and its pinned buttons show, named by `key`. */
5
- export interface RowAction extends MenuAction {
5
+ export type RowAction = MenuAction & {
6
6
  key: string;
7
- }
7
+ };
8
8
  /** Assembles a row's context menu in the shared order: leading link(s) → middle
9
9
  * actions → extra items → Copy submenu → trailing (destructive) actions last. */
10
10
  export declare function assembleRowMenu({ lead, actions, exclude, order, trailing, extra, copy, }: {
@@ -6,9 +6,9 @@ import { useOptionalWorkflowEngine, useStrings } from "../components/Provider.js
6
6
  import { useCopy } from "../components/useCopy.js";
7
7
  import { Button } from "../components/Button.js";
8
8
  import { DatePicker } from "../components/DatePicker.js";
9
+ import { IconButton } from "../components/IconButton.js";
9
10
  import { Popover } from "../components/Popover.js";
10
11
  import { InfoTip } from "../components/InfoTip.js";
11
- import { IconButton } from "../components/IconButton.js";
12
12
  import { SearchInput } from "../components/SearchInput.js";
13
13
  import { highlightSegments, parseAnsiSegments, plainSegments } from "./segments.js";
14
14
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -29,16 +29,26 @@
29
29
  --theme-accent-subtle: #d3ebfc;
30
30
  --theme-focus: #06354f;
31
31
  --theme-focus-ring: rgba(6, 53, 79, 0.25);
32
- --theme-success: #005f23;
33
- --theme-success-muted: rgba(0, 95, 35, 0.1);
34
- --theme-error: #95050f;
35
- --theme-error-muted: rgba(149, 5, 15, 0.1);
36
- --theme-warning: #794800;
37
- --theme-warning-muted: rgba(121, 72, 0, 0.1);
38
- --theme-info: #004caa;
39
- --theme-info-muted: rgba(0, 76, 170, 0.1);
40
- --theme-favorite: #920242;
41
- --theme-favorite-muted: rgba(146, 2, 66, 0.1);
32
+ --theme-success: #00973d;
33
+ --theme-success-text: #006226;
34
+ --theme-success-solid: #00873c;
35
+ --theme-success-muted: rgba(0, 151, 61, 0.1);
36
+ --theme-error: #ea4841;
37
+ --theme-error-text: #a11a1b;
38
+ --theme-error-solid: #db3934;
39
+ --theme-error-muted: rgba(234, 72, 65, 0.1);
40
+ --theme-warning: #bd7100;
41
+ --theme-warning-text: #7b4a00;
42
+ --theme-warning-solid: #a76900;
43
+ --theme-warning-muted: rgba(189, 113, 0, 0.1);
44
+ --theme-info: #0681f8;
45
+ --theme-info-text: #0050af;
46
+ --theme-info-solid: #0073e8;
47
+ --theme-info-muted: rgba(6, 129, 248, 0.1);
48
+ --theme-favorite: #e7457a;
49
+ --theme-favorite-text: #9e174b;
50
+ --theme-favorite-solid: #d7366e;
51
+ --theme-favorite-muted: rgba(231, 69, 122, 0.1);
42
52
  --theme-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.07);
43
53
  --theme-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -2px rgba(0, 0, 0, 0.07);
44
54
  --theme-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.07), 0 4px 6px -4px rgba(0, 0, 0, 0.07);
@@ -64,6 +74,10 @@
64
74
 
65
75
  @media (color-gamut: p3) {
66
76
  :root {
77
+ --theme-success: color(display-p3 0.1559 0.5942 0.2459);
78
+ --theme-success-solid: color(display-p3 0.0738 0.5422 0.1959);
79
+ --theme-success-muted: color(display-p3 0.1559 0.5942 0.2459 / 0.1);
80
+ --theme-warning-solid: color(display-p3 0.6474 0.4089 0);
67
81
  --theme-ansi-cyan: color(display-p3 0 0.4024 0.4329);
68
82
  }
69
83
  }