@parallelworks/ui 0.82.1 → 0.83.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.
- package/dist/components/Callout.js +30 -28
- package/dist/components/CodeBlock.d.ts +4 -1
- package/dist/components/CodeBlock.js +2 -2
- package/dist/components/Meter.d.ts +6 -2
- package/dist/components/Meter.js +21 -3
- package/dist/components/Pagination.js +8 -3
- package/dist/components/SettingsCard.d.ts +17 -6
- package/dist/components/SettingsCard.js +42 -34
- package/dist/components/Table.d.ts +3 -3
- package/dist/components/Table.js +9 -4
- package/dist/components/ToggleGroup.js +2 -2
- package/dist/components/buttonClasses.js +1 -1
- package/dist/graph/DependencyGraph.d.ts +4 -1
- package/dist/graph/DependencyGraph.js +85 -39
- package/dist/graph/GraphNode.d.ts +3 -0
- package/dist/graph/GraphNode.js +7 -4
- package/dist/graph/TreeView.js +4 -4
- package/dist/graph/connectorGeometry.d.ts +10 -1
- package/dist/graph/connectorGeometry.js +81 -3
- package/dist/graph/viewport.d.ts +25 -1
- package/dist/graph/viewport.js +27 -5
- package/dist/list/ListTable.d.ts +4 -1
- package/dist/list/ListTable.js +4 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import { CloseIcon, ErrorIcon, InfoIcon, LockIcon, SuccessIcon, WarningIcon } fr
|
|
|
3
3
|
import { toneIcon, toneSurface } from "./tone.js";
|
|
4
4
|
import { useStrings } from "./Provider.js";
|
|
5
5
|
import { IconButton } from "./IconButton.js";
|
|
6
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
//#region src/components/Callout.tsx
|
|
8
8
|
var toneIcons = {
|
|
9
9
|
default: InfoIcon,
|
|
@@ -20,38 +20,40 @@ function Callout({ tone = "info", title, children, action, onDismiss, icon, vari
|
|
|
20
20
|
const { common } = useStrings();
|
|
21
21
|
const small = size === "sm";
|
|
22
22
|
const Icon = toneIcons[tone];
|
|
23
|
+
const controls = /* @__PURE__ */ jsxs(Fragment, { children: [action !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
24
|
+
className: cx("flex shrink-0 items-center gap-2", small ? "h-4" : "h-5"),
|
|
25
|
+
children: action
|
|
26
|
+
}), onDismiss && /* @__PURE__ */ jsx(IconButton, {
|
|
27
|
+
size: "xs",
|
|
28
|
+
icon: /* @__PURE__ */ jsx(CloseIcon, {}),
|
|
29
|
+
label: common.dismiss,
|
|
30
|
+
onClick: onDismiss,
|
|
31
|
+
className: cx("shrink-0", small ? "-my-1 -me-1" : "-my-0.5 -me-1")
|
|
32
|
+
})] });
|
|
23
33
|
return /* @__PURE__ */ jsxs("div", {
|
|
24
34
|
"data-testid": testId,
|
|
25
35
|
...live ? { role: tone === "error" ? "alert" : "status" } : {},
|
|
26
36
|
className: cx("flex items-start", toneSurface[tone], small ? "gap-2 px-3 py-2 text-xs leading-4" : "gap-3 px-4 py-3 text-sm leading-5", variant === "card" ? "rounded-xl border" : "border-0 border-b", className),
|
|
27
|
-
children: [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/* @__PURE__ */ jsxs("div", {
|
|
34
|
-
className: "
|
|
35
|
-
children: [
|
|
36
|
-
className: "m-0 font-medium",
|
|
37
|
+
children: [icon !== false && /* @__PURE__ */ jsx("span", {
|
|
38
|
+
"aria-hidden": "true",
|
|
39
|
+
className: cx("flex shrink-0 items-center", small ? "h-4 [&_svg]:size-4" : "h-5 [&_svg]:size-5", toneIcon[tone]),
|
|
40
|
+
children: icon ?? /* @__PURE__ */ jsx(Icon, {})
|
|
41
|
+
}), title !== void 0 ? /* @__PURE__ */ jsxs("div", {
|
|
42
|
+
className: "min-w-0 flex-1",
|
|
43
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
44
|
+
className: cx("flex items-start", small ? "gap-2" : "gap-3"),
|
|
45
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
46
|
+
className: "m-0 min-w-0 flex-1 font-medium",
|
|
37
47
|
children: title
|
|
38
|
-
}),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
onDismiss && /* @__PURE__ */ jsx(IconButton, {
|
|
48
|
-
size: "xs",
|
|
49
|
-
icon: /* @__PURE__ */ jsx(CloseIcon, {}),
|
|
50
|
-
label: common.dismiss,
|
|
51
|
-
onClick: onDismiss,
|
|
52
|
-
className: small ? "-my-1 -me-1" : "-my-0.5 -me-1"
|
|
53
|
-
})
|
|
54
|
-
]
|
|
48
|
+
}), controls]
|
|
49
|
+
}), children !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
50
|
+
className: "mt-0.5",
|
|
51
|
+
children
|
|
52
|
+
})]
|
|
53
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
54
|
+
className: "min-w-0 flex-1",
|
|
55
|
+
children
|
|
56
|
+
}), controls] })]
|
|
55
57
|
});
|
|
56
58
|
}
|
|
57
59
|
//#endregion
|
|
@@ -31,10 +31,13 @@ export interface CodeBlockProps {
|
|
|
31
31
|
/** The code is still arriving: highlighting is not cached, and the block
|
|
32
32
|
* keeps its end in view while it is scrolled there. */
|
|
33
33
|
streaming?: boolean | undefined;
|
|
34
|
+
/** On a phone, reaches past the host's content padding (`p-4`) to the
|
|
35
|
+
* container's edges, without corners, so long lines get the screen's width. */
|
|
36
|
+
bleed?: boolean | undefined;
|
|
34
37
|
className?: string | undefined;
|
|
35
38
|
}
|
|
36
39
|
/** Code to read on a page, such as a workflow's YAML: highlighted in the
|
|
37
40
|
* theme's code colors, with numbered lines, a copy button and, given a
|
|
38
41
|
* `filename`, a download button. Markdown's fenced code renders as one, so
|
|
39
42
|
* both read the same. */
|
|
40
|
-
export declare function CodeBlock({ code, language, title, label, filename, headerActions, copy, lineNumbers, startLine, wrap, fill, maxHeight, streaming, className, }: CodeBlockProps): import("react").JSX.Element;
|
|
43
|
+
export declare function CodeBlock({ code, language, title, label, filename, headerActions, copy, lineNumbers, startLine, wrap, fill, maxHeight, streaming, bleed, className, }: CodeBlockProps): import("react").JSX.Element;
|
|
@@ -66,7 +66,7 @@ function downloadText(text, name) {
|
|
|
66
66
|
* theme's code colors, with numbered lines, a copy button and, given a
|
|
67
67
|
* `filename`, a download button. Markdown's fenced code renders as one, so
|
|
68
68
|
* both read the same. */
|
|
69
|
-
function CodeBlock({ code, language = "", title, label, filename, headerActions, copy = true, lineNumbers, startLine = 1, wrap = false, fill = false, maxHeight, streaming = false, className }) {
|
|
69
|
+
function CodeBlock({ code, language = "", title, label, filename, headerActions, copy = true, lineNumbers, startLine = 1, wrap = false, fill = false, maxHeight, streaming = false, bleed = false, className }) {
|
|
70
70
|
const { common: t } = useStrings();
|
|
71
71
|
const source = code.endsWith("\n") ? code.slice(0, -1) : code;
|
|
72
72
|
const lines = useMemo(() => source.split("\n"), [source]);
|
|
@@ -100,7 +100,7 @@ function CodeBlock({ code, language = "", title, label, filename, headerActions,
|
|
|
100
100
|
};
|
|
101
101
|
return /* @__PURE__ */ jsxs("div", {
|
|
102
102
|
"data-code-block": "",
|
|
103
|
-
className: cx("not-prose flex flex-col overflow-hidden rounded-xl bg-(--theme-code-bg) text-(--theme-code-text) shadow-[0_0_0_1px_color-mix(in_oklab,var(--theme-app)_8%,transparent)]", fill && "h-full min-h-0", className),
|
|
103
|
+
className: cx("not-prose flex flex-col overflow-hidden rounded-xl bg-(--theme-code-bg) text-(--theme-code-text) shadow-[0_0_0_1px_color-mix(in_oklab,var(--theme-app)_8%,transparent)]", fill && "h-full min-h-0", bleed && "max-sm:-mx-4 max-sm:rounded-none", className),
|
|
104
104
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
105
105
|
className: "flex h-9 shrink-0 items-center gap-2 pr-1.5 pl-4",
|
|
106
106
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
2
|
/** A bar's color: the theme's accent, a status, or muted for something stopped. */
|
|
3
3
|
export type BarTone = 'accent' | 'info' | 'success' | 'warning' | 'error' | 'muted';
|
|
4
4
|
declare const trackHeight: {
|
|
@@ -32,7 +32,7 @@ export declare function levelTone(value: number, warnAt: number, errorAt: number
|
|
|
32
32
|
/** How full something is, such as storage used or a quota spent: a reading,
|
|
33
33
|
* not a task under way (that's `ProgressBar`). The bar is blue, then turns
|
|
34
34
|
* amber, then red, as it passes `warnAt` and `errorAt`; `tone` overrides that. */
|
|
35
|
-
export declare function Meter({ value, min, max, warnAt, errorAt, tone, okTone, format, showValue, valueText, getAriaValueText, minFill, locale, label, 'aria-label': ariaLabel, detail, size, trackClassName, className, }: BarProps & {
|
|
35
|
+
export declare function Meter({ value, min, max, warnAt, errorAt, tone, okTone, format, showValue, valueText, getAriaValueText, minFill, animate, locale, label, 'aria-label': ariaLabel, detail, size, trackClassName, className, }: BarProps & {
|
|
36
36
|
value: number;
|
|
37
37
|
min?: number;
|
|
38
38
|
max?: number;
|
|
@@ -54,6 +54,10 @@ export declare function Meter({ value, min, max, warnAt, errorAt, tone, okTone,
|
|
|
54
54
|
/** The narrowest the fill draws for a value above `min`, as a percent of the
|
|
55
55
|
* track, so a small reading still shows. */
|
|
56
56
|
minFill?: number | undefined;
|
|
57
|
+
/** Grows the fill in from empty when the bar first shows, and eases it to each new value, for a
|
|
58
|
+
* reading that arrives with the page, such as a dashboard's. Still for anyone who asks for
|
|
59
|
+
* less motion. */
|
|
60
|
+
animate?: boolean | undefined;
|
|
57
61
|
}): import("react").JSX.Element;
|
|
58
62
|
/** A further stretch of a progress bar, drawn after its value, such as work
|
|
59
63
|
* started but not yet done. */
|
package/dist/components/Meter.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
2
|
import { toneFill } from "./tone.js";
|
|
3
3
|
import { Tooltip } from "./Tooltip.js";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
import { Meter } from "@base-ui/react/meter";
|
|
6
7
|
import { Progress } from "@base-ui/react/progress";
|
|
@@ -26,6 +27,21 @@ var trackBaseClassName = "w-full overflow-hidden rounded-full bg-(--theme-border
|
|
|
26
27
|
function trackClasses(size, end, own) {
|
|
27
28
|
return cx(trackBaseClassName, trackHeight[size], end && (own ? "shrink-0" : "min-w-0 flex-1"), own);
|
|
28
29
|
}
|
|
30
|
+
function useGrown(grow) {
|
|
31
|
+
const [grown, setGrown] = useState(!grow);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (grown) return;
|
|
34
|
+
let inner = 0;
|
|
35
|
+
const outer = requestAnimationFrame(() => {
|
|
36
|
+
inner = requestAnimationFrame(() => setGrown(true));
|
|
37
|
+
});
|
|
38
|
+
return () => {
|
|
39
|
+
cancelAnimationFrame(outer);
|
|
40
|
+
cancelAnimationFrame(inner);
|
|
41
|
+
};
|
|
42
|
+
}, [grown]);
|
|
43
|
+
return grown;
|
|
44
|
+
}
|
|
29
45
|
/** The tone for `value` against a warning and an error level, for a measure
|
|
30
46
|
* that's worse the higher it reads; `okTone` below the warning. */
|
|
31
47
|
function levelTone(value, warnAt, errorAt, okTone = "info") {
|
|
@@ -34,7 +50,8 @@ function levelTone(value, warnAt, errorAt, okTone = "info") {
|
|
|
34
50
|
/** How full something is, such as storage used or a quota spent: a reading,
|
|
35
51
|
* not a task under way (that's `ProgressBar`). The bar is blue, then turns
|
|
36
52
|
* amber, then red, as it passes `warnAt` and `errorAt`; `tone` overrides that. */
|
|
37
|
-
function Meter$1({ value, min = 0, max = 100, warnAt = 80, errorAt = 90, tone, okTone = "info", format, showValue = "beside", valueText, getAriaValueText, minFill = 0, locale, label, "aria-label": ariaLabel, detail, size = "md", trackClassName, className }) {
|
|
53
|
+
function Meter$1({ value, min = 0, max = 100, warnAt = 80, errorAt = 90, tone, okTone = "info", format, showValue = "beside", valueText, getAriaValueText, minFill = 0, animate = false, locale, label, "aria-label": ariaLabel, detail, size = "md", trackClassName, className }) {
|
|
54
|
+
const grown = useGrown(animate);
|
|
38
55
|
const clamped = Math.min(Math.max(value, min), max);
|
|
39
56
|
const fill = fillClassName[tone ?? levelTone(clamped, warnAt, errorAt, okTone)];
|
|
40
57
|
const end = showValue === "end";
|
|
@@ -45,8 +62,9 @@ function Meter$1({ value, min = 0, max = 100, warnAt = 80, errorAt = 90, tone, o
|
|
|
45
62
|
const track = /* @__PURE__ */ jsx(Meter.Track, {
|
|
46
63
|
className: trackClasses(size, end, trackClassName),
|
|
47
64
|
children: /* @__PURE__ */ jsx(Meter.Indicator, {
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
"data-growing": grown ? void 0 : "",
|
|
66
|
+
className: cx("h-full rounded-full motion-reduce:transition-none", animate ? "transition-[width,min-width] delay-150 duration-500 ease-[cubic-bezier(0.25,0.1,0.25,1)]" : "transition-[width] duration-300", fill),
|
|
67
|
+
style: !grown ? { width: 0 } : minFill > 0 && clamped > min ? { minWidth: `${minFill}%` } : void 0
|
|
50
68
|
})
|
|
51
69
|
});
|
|
52
70
|
const share = formatShare(clamped, min, max, format, locale);
|
|
@@ -59,7 +59,7 @@ function Pagination({ page, pageSize, total, hasNext, onPageChange, pageHref, pa
|
|
|
59
59
|
const position = summary ?? (known ? t.pager(start, end, pastCap ? end : total, pastCap) : null);
|
|
60
60
|
return /* @__PURE__ */ jsxs("nav", {
|
|
61
61
|
"aria-label": t.pagination,
|
|
62
|
-
className: cx("flex h-
|
|
62
|
+
className: cx("flex h-8 shrink-0 items-center justify-between gap-3 px-2.5", className),
|
|
63
63
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
64
64
|
className: "flex min-w-0 flex-1 items-center gap-3 text-xs text-(--theme-muted-text-color)",
|
|
65
65
|
children: [position && /* @__PURE__ */ jsx("span", {
|
|
@@ -118,22 +118,27 @@ function Pagination({ page, pageSize, total, hasNext, onPageChange, pageHref, pa
|
|
|
118
118
|
function PageStep({ to, enabled, label, icon, onPageChange, pageHref }) {
|
|
119
119
|
if (pageHref && enabled) return /* @__PURE__ */ jsx(IconButton, {
|
|
120
120
|
variant: "outline",
|
|
121
|
+
size: "xs",
|
|
122
|
+
className: STEP_TOUCH,
|
|
121
123
|
icon,
|
|
122
124
|
label,
|
|
123
125
|
href: pageHref(to)
|
|
124
126
|
});
|
|
125
127
|
return /* @__PURE__ */ jsx(IconButton, {
|
|
126
128
|
variant: "outline",
|
|
129
|
+
size: "xs",
|
|
130
|
+
className: STEP_TOUCH,
|
|
127
131
|
icon,
|
|
128
132
|
label,
|
|
129
133
|
disabled: !enabled,
|
|
130
134
|
onClick: () => onPageChange?.(to)
|
|
131
135
|
});
|
|
132
136
|
}
|
|
137
|
+
var STEP_TOUCH = "pointer-coarse:size-8";
|
|
133
138
|
var numberClassName = cx(buttonClasses({
|
|
134
139
|
variant: "outline",
|
|
135
|
-
size: "
|
|
136
|
-
}), "min-w-
|
|
140
|
+
size: "xs"
|
|
141
|
+
}), "min-w-6 px-1 tabular-nums pointer-coarse:h-8 pointer-coarse:min-w-8 aria-[current=page]:border-(--theme-link) aria-[current=page]:bg-(--theme-accent-subtle) aria-[current=page]:text-(--theme-app)");
|
|
137
142
|
function PageNumber({ to, current, label, onPageChange, pageHref }) {
|
|
138
143
|
const number = formatInteger(to + 1, useLocale());
|
|
139
144
|
const props = {
|
|
@@ -13,20 +13,30 @@ export interface SettingsCardProps {
|
|
|
13
13
|
/** Lets content such as an inline menu reach past the card's rounded edge. */
|
|
14
14
|
overflowVisible?: boolean | undefined;
|
|
15
15
|
className?: string | undefined;
|
|
16
|
+
/** An error about the whole card, such as its header's Save or Connect failing: at the top of
|
|
17
|
+
* the card, inside it, above its rows, and announced. */
|
|
18
|
+
error?: ReactNode;
|
|
16
19
|
/** SettingRows, and SettingsHeadings between groups of them. */
|
|
17
20
|
children: ReactNode;
|
|
18
21
|
}
|
|
19
22
|
/** A page's settings, grouped: a titled panel of SettingRows, each ruled off from
|
|
20
23
|
* the next. Cards stack with room between them. An error about one setting, such as its
|
|
21
|
-
* Save failing, is its row's `error`; one about the whole card
|
|
22
|
-
*
|
|
23
|
-
export declare function SettingsCard({ title, description, action, actionAlign, headingLevel, overflowVisible, className, children, }: SettingsCardProps): import("react").JSX.Element;
|
|
24
|
+
* Save failing, is its row's `error`; one about the whole card, such as its header's
|
|
25
|
+
* action failing, is the card's `error`. */
|
|
26
|
+
export declare function SettingsCard({ title, description, action, actionAlign, headingLevel, overflowVisible, className, error, children, }: SettingsCardProps): import("react").JSX.Element;
|
|
24
27
|
/** A heading between groups of rows inside a SettingsCard, a level below the card's title. */
|
|
25
28
|
export declare function SettingsHeading({ children }: {
|
|
26
29
|
children: ReactNode;
|
|
27
30
|
}): import("react").JSX.Element;
|
|
28
31
|
/** One setting in a SettingsCard: its name and help on the left, its control on
|
|
29
|
-
* the right, or under the name across the row with `fill`.
|
|
32
|
+
* the right, or under the name across the row with `fill`.
|
|
33
|
+
*
|
|
34
|
+
* On a phone a small control, such as a switch, a checkbox or a short select, stays on the
|
|
35
|
+
* name's line at the row's end. One too wide to fit beside the name, such as a text field
|
|
36
|
+
* with its Save button, moves to a line of its own and takes the row's width from its start:
|
|
37
|
+
* a single wrapper the host puts it in, such as a `<form className="flex gap-2">`, stretches
|
|
38
|
+
* across the row, and a text field in it grows while a button beside it keeps its size. A
|
|
39
|
+
* control of the host's own that should grow there takes `flex-1`. */
|
|
30
40
|
export declare function SettingRow({ label, htmlFor, helpText, fill, onClick, error, children, }: {
|
|
31
41
|
label: string;
|
|
32
42
|
/** The control's id, so the name labels it. */
|
|
@@ -37,8 +47,9 @@ export declare function SettingRow({ label, htmlFor, helpText, fill, onClick, er
|
|
|
37
47
|
/** Makes the whole row press its control, such as a switch. The control still
|
|
38
48
|
* handles its own press; stop it propagating there so it doesn't toggle twice. */
|
|
39
49
|
onClick?: (() => void) | undefined;
|
|
40
|
-
/** An error about this setting, such as its Save failing: under the
|
|
41
|
-
*
|
|
50
|
+
/** An error about this setting, such as its Save failing: under the row from the name's
|
|
51
|
+
* start, or with `fill` under the control from its start, on a wide screen; across the row
|
|
52
|
+
* on a phone. It is announced and describes the control that `htmlFor` names. */
|
|
42
53
|
error?: ReactNode;
|
|
43
54
|
children: ReactNode;
|
|
44
55
|
}): import("react").JSX.Element;
|
|
@@ -6,9 +6,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
var HeadingLevel = createContext(3);
|
|
7
7
|
/** A page's settings, grouped: a titled panel of SettingRows, each ruled off from
|
|
8
8
|
* the next. Cards stack with room between them. An error about one setting, such as its
|
|
9
|
-
* Save failing, is its row's `error`; one about the whole card
|
|
10
|
-
*
|
|
11
|
-
function SettingsCard({ title, description, action, actionAlign = "beside", headingLevel = 2, overflowVisible = false, className, children }) {
|
|
9
|
+
* Save failing, is its row's `error`; one about the whole card, such as its header's
|
|
10
|
+
* action failing, is the card's `error`. */
|
|
11
|
+
function SettingsCard({ title, description, action, actionAlign = "beside", headingLevel = 2, overflowVisible = false, className, error, children }) {
|
|
12
12
|
const Heading = `h${headingLevel}`;
|
|
13
13
|
return /* @__PURE__ */ jsx(HeadingLevel, {
|
|
14
14
|
value: headingLevel + 1,
|
|
@@ -26,9 +26,16 @@ function SettingsCard({ title, description, action, actionAlign = "beside", head
|
|
|
26
26
|
className: "mt-1.5 text-xs leading-snug theme-muted-text",
|
|
27
27
|
children: description
|
|
28
28
|
})]
|
|
29
|
-
}), /* @__PURE__ */
|
|
30
|
-
className: cx("panel
|
|
31
|
-
children
|
|
29
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
30
|
+
className: cx("panel", overflowVisible ? "overflow-visible" : "overflow-hidden"),
|
|
31
|
+
children: [/* @__PURE__ */ jsx(ErrorText, {
|
|
32
|
+
size: "md",
|
|
33
|
+
className: "px-4 pt-4",
|
|
34
|
+
children: error
|
|
35
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
36
|
+
className: "divide-y divide-(--theme-border)",
|
|
37
|
+
children
|
|
38
|
+
})]
|
|
32
39
|
})]
|
|
33
40
|
})
|
|
34
41
|
});
|
|
@@ -42,7 +49,14 @@ function SettingsHeading({ children }) {
|
|
|
42
49
|
});
|
|
43
50
|
}
|
|
44
51
|
/** One setting in a SettingsCard: its name and help on the left, its control on
|
|
45
|
-
* the right, or under the name across the row with `fill`.
|
|
52
|
+
* the right, or under the name across the row with `fill`.
|
|
53
|
+
*
|
|
54
|
+
* On a phone a small control, such as a switch, a checkbox or a short select, stays on the
|
|
55
|
+
* name's line at the row's end. One too wide to fit beside the name, such as a text field
|
|
56
|
+
* with its Save button, moves to a line of its own and takes the row's width from its start:
|
|
57
|
+
* a single wrapper the host puts it in, such as a `<form className="flex gap-2">`, stretches
|
|
58
|
+
* across the row, and a text field in it grows while a button beside it keeps its size. A
|
|
59
|
+
* control of the host's own that should grow there takes `flex-1`. */
|
|
46
60
|
function SettingRow({ label, htmlFor, helpText, fill = false, onClick, error, children }) {
|
|
47
61
|
const errorId = useId();
|
|
48
62
|
const hasError = error !== void 0 && error !== null && error !== false && error !== "";
|
|
@@ -61,39 +75,33 @@ function SettingRow({ label, htmlFor, helpText, fill = false, onClick, error, ch
|
|
|
61
75
|
htmlFor,
|
|
62
76
|
errorId
|
|
63
77
|
]);
|
|
64
|
-
const control = /* @__PURE__ */ jsx("div", {
|
|
65
|
-
className: cx("min-w-0", !fill && [
|
|
66
|
-
"flex items-center justify-end",
|
|
67
|
-
"max-md:has-[input:not([type=checkbox],[type=radio],[type=hidden],[type=range]),textarea,[role=combobox]]:justify-start",
|
|
68
|
-
"max-md:has-[input:not([type=checkbox],[type=radio],[type=hidden],[type=range]),textarea,[role=combobox]]:*:grow",
|
|
69
|
-
"max-md:[&_:is(input:not([type=checkbox],[type=radio],[type=hidden],[type=range]),textarea,[role=combobox])]:min-w-0",
|
|
70
|
-
"max-md:[&_:is(input:not([type=checkbox],[type=radio],[type=hidden],[type=range]),textarea,[role=combobox])]:flex-1"
|
|
71
|
-
]),
|
|
72
|
-
children
|
|
73
|
-
});
|
|
74
78
|
return /* @__PURE__ */ jsxs("div", {
|
|
75
79
|
role: "none",
|
|
76
80
|
onClick,
|
|
77
|
-
className: cx("
|
|
78
|
-
children: [
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
className: cx("gap-x-8 gap-y-2 p-4", "flex flex-wrap items-center", "md:grid md:items-stretch", fill ? "md:grid-cols-[200px_1fr]" : "md:grid-cols-[1fr_auto]", onClick && "cursor-pointer transition-colors select-none hover:theme-hover"),
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("div", {
|
|
84
|
+
className: cx("flex min-w-0 grow-[999] basis-48 flex-col gap-y-1 self-start", fill && "max-md:basis-full"),
|
|
85
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
86
|
+
htmlFor,
|
|
87
|
+
className: "leading-tight font-semibold theme-text",
|
|
88
|
+
children: label
|
|
89
|
+
}), helpText && /* @__PURE__ */ jsx("div", {
|
|
90
|
+
className: "text-xs leading-snug theme-muted-text",
|
|
91
|
+
children: helpText
|
|
92
|
+
})]
|
|
93
|
+
}),
|
|
94
|
+
/* @__PURE__ */ jsx("div", {
|
|
95
|
+
className: cx("flex min-w-0 grow items-center gap-2", !fill && "md:justify-end", fill ? "[&>:only-child]:grow" : "max-md:[&>:only-child]:grow", "max-md:[&_:is(input:not([type=checkbox],[type=radio],[type=hidden],[type=file]),textarea)]:min-w-0", "max-md:[&_:is(input:not([type=checkbox],[type=radio],[type=hidden],[type=file]),textarea)]:flex-1"),
|
|
96
|
+
children
|
|
97
|
+
}),
|
|
98
|
+
hasError && /* @__PURE__ */ jsx(ErrorText, {
|
|
91
99
|
id: errorId,
|
|
92
100
|
size: "md",
|
|
93
|
-
className: "md:w-0 md:min-w-full",
|
|
101
|
+
className: cx("basis-full", fill ? "md:col-start-2 md:w-0 md:min-w-full" : "md:col-span-2"),
|
|
94
102
|
children: error
|
|
95
|
-
})
|
|
96
|
-
|
|
103
|
+
})
|
|
104
|
+
]
|
|
97
105
|
});
|
|
98
106
|
}
|
|
99
107
|
//#endregion
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
/** Which way a column sorts, as `aria-sort` names it. */
|
|
3
3
|
export type SortDirection = 'ascending' | 'descending' | 'none';
|
|
4
|
-
/** `comfortable` gives each row room; `compact` fits
|
|
5
|
-
*
|
|
6
|
-
* a panel of figures. */
|
|
4
|
+
/** `comfortable` gives each row room; `compact` fits many rows in little
|
|
5
|
+
* height, such as a key and value list or a dashboard card's runs; `dense`
|
|
6
|
+
* sets small type in tight rows, for a panel of figures. */
|
|
7
7
|
export type TableDensity = 'comfortable' | 'compact' | 'dense';
|
|
8
8
|
interface ItemProps extends React.TdHTMLAttributes<HTMLTableCellElement> {
|
|
9
9
|
/** Lets the text wrap; by default a cell keeps to one line. */
|
package/dist/components/Table.js
CHANGED
|
@@ -9,20 +9,25 @@ var DensityContext = createContext("comfortable");
|
|
|
9
9
|
var CapsContext = createContext(true);
|
|
10
10
|
var cellY = {
|
|
11
11
|
comfortable: "py-4",
|
|
12
|
-
compact: "py-
|
|
12
|
+
compact: "h-8 py-0 text-sm",
|
|
13
13
|
dense: "py-1 text-xs"
|
|
14
14
|
};
|
|
15
|
+
var wrapY = {
|
|
16
|
+
comfortable: false,
|
|
17
|
+
compact: "py-1",
|
|
18
|
+
dense: false
|
|
19
|
+
};
|
|
15
20
|
var headerY = {
|
|
16
21
|
comfortable: "py-3",
|
|
17
|
-
compact: "py-
|
|
18
|
-
dense: "py-1
|
|
22
|
+
compact: "py-1.5",
|
|
23
|
+
dense: "py-1"
|
|
19
24
|
};
|
|
20
25
|
var cellX = "px-3";
|
|
21
26
|
function Item({ wrap = false, children, className, ...tdProps }) {
|
|
22
27
|
const density = useContext(DensityContext);
|
|
23
28
|
return /* @__PURE__ */ jsx("td", {
|
|
24
29
|
...tdProps,
|
|
25
|
-
className: cx(cellX, cellY[density],
|
|
30
|
+
className: cx(cellX, cellY[density], wrap ? wrapY[density] : "whitespace-nowrap", className),
|
|
26
31
|
children
|
|
27
32
|
});
|
|
28
33
|
}
|
|
@@ -61,10 +61,10 @@ function Chip({ value, label, icon, count, disabled, testId, size }) {
|
|
|
61
61
|
value,
|
|
62
62
|
disabled,
|
|
63
63
|
"data-testid": testId,
|
|
64
|
-
className: cx(
|
|
64
|
+
className: cx(buttonClasses({
|
|
65
65
|
variant: "outline",
|
|
66
66
|
size
|
|
67
|
-
})),
|
|
67
|
+
}), "group focus-visible:-outline-offset-2 aria-pressed:bg-(--theme-accent-subtle)"),
|
|
68
68
|
children: [
|
|
69
69
|
icon && /* @__PURE__ */ jsx("span", {
|
|
70
70
|
className: "inline-flex shrink-0 transition-opacity group-not-aria-pressed:opacity-55",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
2
|
//#region src/components/buttonClasses.ts
|
|
3
|
-
var base = "relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-md font-medium no-underline transition-[color,background-color,border-color,box-shadow,translate] duration-150 hover:not-disabled:not-aria-disabled:-translate-y-px hover:not-disabled:not-aria-disabled:shadow-(--theme-shadow-sm) active:not-disabled:not-aria-disabled:translate-y-0 active:not-disabled:not-aria-disabled:shadow-none motion-reduce:hover:not-disabled:not-aria-disabled:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--theme-focus) disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
|
|
3
|
+
var base = "relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-1.5 whitespace-nowrap rounded-md font-medium no-underline transition-[color,background-color,border-color,box-shadow,translate] duration-150 hover:not-disabled:not-aria-disabled:not-[[aria-pressed]]:-translate-y-px hover:not-disabled:not-aria-disabled:not-[[aria-pressed]]:shadow-(--theme-shadow-sm) active:not-disabled:not-aria-disabled:translate-y-0 active:not-disabled:not-aria-disabled:shadow-none motion-reduce:hover:not-disabled:not-aria-disabled:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--theme-focus) disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50";
|
|
4
4
|
var variants = {
|
|
5
5
|
primary: "bg-(--theme-accent) text-(--theme-accent-text) hover:not-disabled:not-aria-disabled:bg-(--theme-accent-hover)",
|
|
6
6
|
secondary: "border border-(--theme-border) bg-(--theme-panel-bg) text-(--theme-app) hover:not-disabled:not-aria-disabled:bg-(--theme-hover)",
|
|
@@ -21,7 +21,7 @@ interface GraphRun {
|
|
|
21
21
|
* marked on each job and step they're about, which matters most for one skipped without a log. */
|
|
22
22
|
warnings?: readonly RunWarning[] | null | undefined;
|
|
23
23
|
}
|
|
24
|
-
export default function DependencyGraph({ run, preview, removeBorder, viewMode, setViewMode, layout, editor, yamlJobs, inputs, workflow, fixedHeight, openStep, onCloseLog, stickySidebar, }: {
|
|
24
|
+
export default function DependencyGraph({ run, preview, removeBorder, viewMode, setViewMode, layout, editor, yamlJobs, inputs, workflow, fixedHeight, openStep, onCloseLog, stickySidebar, bleed, }: {
|
|
25
25
|
run: GraphRun;
|
|
26
26
|
preview?: boolean;
|
|
27
27
|
removeBorder?: boolean | undefined;
|
|
@@ -44,6 +44,9 @@ export default function DependencyGraph({ run, preview, removeBorder, viewMode,
|
|
|
44
44
|
onCloseLog?: (() => void) | undefined;
|
|
45
45
|
/** Pins the job list as the page scrolls, under whatever the page already pins at its top. */
|
|
46
46
|
stickySidebar?: boolean | undefined;
|
|
47
|
+
/** On a phone, the jobs' panel, graph or list, reaches past the host's content padding (`p-4`) to
|
|
48
|
+
* the container's edges, without side borders or corners, so a job's row has the screen's width. */
|
|
49
|
+
bleed?: boolean | undefined;
|
|
47
50
|
}): import("react").JSX.Element | undefined;
|
|
48
51
|
export declare function DependencyGraphPreview(inputs: {
|
|
49
52
|
yml?: Record<string, unknown>;
|