@ciridae/ui 1.0.2 → 1.0.4
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/app/auth.d.ts +10 -0
- package/dist/app/auth.js +60 -0
- package/dist/app/error-boundary.d.ts +18 -0
- package/dist/app/error-boundary.js +45 -0
- package/dist/app/feedback.d.ts +12 -0
- package/dist/app/feedback.js +128 -0
- package/dist/app/index.d.ts +8 -0
- package/dist/app/index.js +8 -0
- package/dist/app/request-errors.d.ts +63 -0
- package/dist/app/request-errors.js +172 -0
- package/dist/app/sentry.d.ts +18 -0
- package/dist/app/sentry.js +52 -0
- package/dist/app/telemetry.d.ts +7 -0
- package/dist/app/telemetry.js +28 -0
- package/dist/app/trail.d.ts +9 -0
- package/dist/app/trail.js +18 -0
- package/dist/chat/chat-query-keys.d.ts +3 -3
- package/dist/chat/contract.d.ts +15 -15
- package/dist/chat/conversation-items-query-options.d.ts +114 -114
- package/dist/chat/conversation-source.d.ts +89 -0
- package/dist/chat/conversation-source.js +1 -0
- package/dist/chat/describe-tool-call.d.ts +3 -3
- package/dist/chat/describe-tool-call.js +3 -3
- package/dist/chat/message-text.d.ts +1 -1
- package/dist/chat/message-text.js +116 -48
- package/dist/chat/use-conversation-list.d.ts +6 -6
- package/dist/ciridae.css +16 -4
- package/dist/components/activity-feed.d.ts +3 -2
- package/dist/components/activity-feed.js +1 -0
- package/dist/components/agent-work.d.ts +3 -3
- package/dist/components/app-frame.d.ts +91 -0
- package/dist/components/app-frame.js +134 -0
- package/dist/components/app-navigation.d.ts +30 -3
- package/dist/components/app-navigation.js +105 -14
- package/dist/components/badge.d.ts +30 -5
- package/dist/components/badge.js +134 -15
- package/dist/components/brand-icons.d.ts +3 -3
- package/dist/components/bulk-action-bar.d.ts +1 -1
- package/dist/components/bulk-action-bar.js +3 -3
- package/dist/components/button.d.ts +12 -5
- package/dist/components/button.js +77 -44
- package/dist/components/calendar.d.ts +1 -1
- package/dist/components/calendar.js +44 -17
- package/dist/components/centered-page.d.ts +1 -1
- package/dist/components/centered-page.js +2 -2
- package/dist/components/chart.d.ts +22 -2
- package/dist/components/chart.js +251 -51
- package/dist/components/chat-client-source.d.ts +16 -0
- package/dist/components/chat-client-source.js +297 -0
- package/dist/components/chat-page.d.ts +9 -8
- package/dist/components/chat-page.js +7 -11
- package/dist/components/chat-sheet-controller.d.ts +11 -14
- package/dist/components/chat-sheet-controller.js +3 -3
- package/dist/components/chat-sheet.d.ts +18 -11
- package/dist/components/chat-sheet.js +188 -289
- package/dist/components/chat.d.ts +109 -19
- package/dist/components/chat.js +520 -124
- package/dist/components/checkbox-item.d.ts +6 -3
- package/dist/components/checkbox-item.js +9 -5
- package/dist/components/checkbox-list.d.ts +1 -1
- package/dist/components/chip.d.ts +6 -1
- package/dist/components/chip.js +27 -1
- package/dist/components/collapsible.d.ts +1 -1
- package/dist/components/color-theme.d.ts +1 -1
- package/dist/components/column-settings.d.ts +1 -1
- package/dist/components/column-settings.js +1 -1
- package/dist/components/command-menu.d.ts +5 -1
- package/dist/components/command-menu.js +98 -32
- package/dist/components/command-palette.d.ts +7 -3
- package/dist/components/command-palette.js +20 -11
- package/dist/components/copyable-id.d.ts +22 -5
- package/dist/components/copyable-id.js +46 -6
- package/dist/components/data-display.d.ts +39 -8
- package/dist/components/data-display.js +138 -19
- package/dist/components/data-grid.d.ts +23 -11
- package/dist/components/data-grid.js +61 -26
- package/dist/components/date-range-picker.d.ts +1 -1
- package/dist/components/date-range-picker.js +9 -20
- package/dist/components/date-time.d.ts +1 -1
- package/dist/components/dialog-height-context.d.ts +1 -1
- package/dist/components/document-viewer.d.ts +2 -2
- package/dist/components/drawer.d.ts +11 -6
- package/dist/components/drawer.js +91 -54
- package/dist/components/dropzone.d.ts +4 -4
- package/dist/components/editable-field.d.ts +12 -3
- package/dist/components/editable-field.js +57 -27
- package/dist/components/email-input.d.ts +1 -1
- package/dist/components/email-input.js +6 -5
- package/dist/components/environment-frame.d.ts +2 -2
- package/dist/components/environment-frame.js +37 -6
- package/dist/components/expandable-text.d.ts +1 -1
- package/dist/components/feedback-screenshot.d.ts +1 -1
- package/dist/components/feedback-sheet.d.ts +18 -3
- package/dist/components/feedback-sheet.js +216 -55
- package/dist/components/field-context.d.ts +1 -1
- package/dist/components/filter-bar.d.ts +3 -3
- package/dist/components/filter-bar.js +43 -29
- package/dist/components/form-controls.d.ts +12 -3
- package/dist/components/form-controls.js +46 -22
- package/dist/components/form-layout.d.ts +14 -10
- package/dist/components/form-layout.js +68 -23
- package/dist/components/glass-menu.d.ts +3 -0
- package/dist/components/glass-menu.js +63 -0
- package/dist/components/gradient-edge.d.ts +9 -0
- package/dist/components/gradient-edge.js +31 -0
- package/dist/components/hotkeys.d.ts +2 -2
- package/dist/components/icon.d.ts +1 -1
- package/dist/components/input.d.ts +7 -5
- package/dist/components/input.js +29 -17
- package/dist/components/keyboard-shortcuts.d.ts +2 -2
- package/dist/components/keycap.d.ts +10 -6
- package/dist/components/keycap.js +57 -19
- package/dist/components/layout.d.ts +13 -13
- package/dist/components/lightbox.d.ts +9 -3
- package/dist/components/lightbox.js +13 -9
- package/dist/components/link.d.ts +1 -1
- package/dist/components/locale.d.ts +42 -2
- package/dist/components/locale.js +43 -3
- package/dist/components/log-entry.d.ts +40 -0
- package/dist/components/log-entry.js +146 -0
- package/dist/components/log-list.d.ts +3 -3
- package/dist/components/mention-input.d.ts +2 -2
- package/dist/components/mention-input.js +4 -3
- package/dist/components/menu.d.ts +7 -3
- package/dist/components/menu.js +34 -37
- package/dist/components/meter.d.ts +10 -2
- package/dist/components/meter.js +64 -6
- package/dist/components/navigation.d.ts +21 -4
- package/dist/components/navigation.js +84 -19
- package/dist/components/notification-tray.d.ts +1 -1
- package/dist/components/notification-tray.js +5 -4
- package/dist/components/overlays.d.ts +6 -4
- package/dist/components/overlays.js +69 -40
- package/dist/components/page-frame.d.ts +4 -4
- package/dist/components/page-frame.js +1 -1
- package/dist/components/panel.d.ts +4 -4
- package/dist/components/panel.js +18 -12
- package/dist/components/profile-header.d.ts +1 -1
- package/dist/components/progress.d.ts +1 -1
- package/dist/components/project-avatar.d.ts +1 -1
- package/dist/components/radio-card.d.ts +2 -2
- package/dist/components/radio-card.js +10 -9
- package/dist/components/record.d.ts +29 -5
- package/dist/components/record.js +147 -18
- package/dist/components/resolved-file-url.d.ts +19 -0
- package/dist/components/resolved-file-url.js +49 -0
- package/dist/components/scroll-area.d.ts +1 -1
- package/dist/components/secret-dialog.d.ts +1 -1
- package/dist/components/segmented-bar.d.ts +4 -2
- package/dist/components/segmented-bar.js +16 -6
- package/dist/components/select.d.ts +9 -6
- package/dist/components/select.js +103 -127
- package/dist/components/settings.d.ts +4 -4
- package/dist/components/shell-skeleton.d.ts +1 -1
- package/dist/components/shell-skeleton.js +1 -1
- package/dist/components/shell.d.ts +21 -21
- package/dist/components/shell.js +43 -43
- package/dist/components/side-panel.d.ts +3 -3
- package/dist/components/sidebar.d.ts +13 -8
- package/dist/components/sidebar.js +55 -27
- package/dist/components/single-line-text.d.ts +2 -0
- package/dist/components/single-line-text.js +16 -0
- package/dist/components/site-banner.d.ts +5 -2
- package/dist/components/site-banner.js +17 -6
- package/dist/components/skeleton.d.ts +8 -7
- package/dist/components/skeleton.js +28 -16
- package/dist/components/skeletons.d.ts +17 -5
- package/dist/components/skeletons.js +71 -8
- package/dist/components/stages.d.ts +83 -11
- package/dist/components/stages.js +512 -156
- package/dist/components/stat-card.d.ts +12 -4
- package/dist/components/stat-card.js +92 -37
- package/dist/components/status-banner.d.ts +1 -1
- package/dist/components/status-banner.js +1 -1
- package/dist/components/status.d.ts +2 -2
- package/dist/components/steps.d.ts +1 -1
- package/dist/components/switch.d.ts +1 -1
- package/dist/components/tabs.d.ts +8 -8
- package/dist/components/tabs.js +26 -13
- package/dist/components/theme-customizer.d.ts +2 -2
- package/dist/components/theme-toggle.d.ts +4 -0
- package/dist/components/theme-toggle.js +67 -0
- package/dist/components/toast.d.ts +10 -3
- package/dist/components/toast.js +78 -29
- package/dist/components/use-new-version-available.d.ts +6 -0
- package/dist/components/use-new-version-available.js +29 -0
- package/dist/components/user-chip.d.ts +3 -3
- package/dist/components/wizard.d.ts +2 -2
- package/dist/feedback/contract.d.ts +136 -136
- package/dist/feedback/feedback-controller.d.ts +6 -6
- package/dist/feedback/generated/zod.gen.d.ts +28 -28
- package/dist/feedback/operator-contract.d.ts +11 -11
- package/dist/feedback/operator-controller.d.ts +32 -13
- package/dist/feedback/operator-controller.js +44 -11
- package/dist/preset.js +289 -33
- package/dist/styled-system/styles.css +3294 -1079
- package/dist/styled-system/tokens/index.mjs +598 -22
- package/dist/styled-system/tokens/tokens.d.ts +11 -11
- package/dist/styled-system/types/prop-type.d.ts +2 -2
- package/dist/styles.css +16 -4
- package/dist/theme/color.d.ts +3 -0
- package/dist/theme/color.js +5 -0
- package/dist/theme/derive.d.ts +9 -2
- package/dist/theme/derive.js +72 -12
- package/dist/theme/palettes.d.ts +49 -6
- package/dist/theme/palettes.js +84 -15
- package/dist/theme/tokens.d.ts +3 -3
- package/dist/theme/tokens.js +107 -32
- package/package.json +40 -3
|
@@ -2,11 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Radio as BaseRadio } from "@base-ui/react/radio";
|
|
3
3
|
import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
|
|
4
4
|
import { css, cx } from "#primitives/css";
|
|
5
|
-
import { checkMark, radioDot } from "./form-controls.js";
|
|
5
|
+
import { checkMark, checkMarkEdge, radioDot } from "./form-controls.js";
|
|
6
6
|
/*
|
|
7
7
|
* A choice drawn as a card: the radio, a title with its detail, and where the option comes from
|
|
8
8
|
* at the far edge. The whole card is the radio, so it takes the hover wash, the focus ring, and,
|
|
9
|
-
* once chosen, the
|
|
9
|
+
* once chosen, the selected tint under an edge in the text color.
|
|
10
10
|
*/
|
|
11
11
|
const cards = css({ display: "grid", gap: "layout.controlGap" });
|
|
12
12
|
const card = css({
|
|
@@ -28,10 +28,10 @@ const card = css({
|
|
|
28
28
|
cursor: "pointer",
|
|
29
29
|
transitionProperty: "background, border-color",
|
|
30
30
|
transitionDuration: "fast",
|
|
31
|
-
_hover: { background: "
|
|
31
|
+
_hover: { background: "token(gradients.raisedHover)" },
|
|
32
32
|
"&[data-checked]": {
|
|
33
|
-
background: "
|
|
34
|
-
borderColor: "
|
|
33
|
+
background: "token(gradients.selected)",
|
|
34
|
+
borderColor: "fg.primary",
|
|
35
35
|
},
|
|
36
36
|
_focusVisible: { focusRing: "outer" },
|
|
37
37
|
"&[data-disabled]": { opacity: "disabled", cursor: "not-allowed" },
|
|
@@ -42,10 +42,11 @@ const mark = css({
|
|
|
42
42
|
// the mark down.
|
|
43
43
|
marginTop: "calc((1em - token(sizes.control.radio)) / 2)",
|
|
44
44
|
"[data-checked] > &": {
|
|
45
|
-
background: "
|
|
46
|
-
|
|
45
|
+
background: "token(gradients.primary)",
|
|
46
|
+
_light: { background: "token(gradients.primary)" },
|
|
47
|
+
_before: { background: "token(gradients.border.primary)" },
|
|
47
48
|
},
|
|
48
|
-
"[data-checked]:hover > &": {
|
|
49
|
+
"[data-checked]:hover > &": { opacity: "checkedHover", _light: { opacity: "1" } },
|
|
49
50
|
});
|
|
50
51
|
const copy = css({ flex: "1", minWidth: "0", display: "grid", gap: "layout.tightGap" });
|
|
51
52
|
const detailText = css({ color: "fg.muted", fontSize: "code" });
|
|
@@ -62,5 +63,5 @@ export function RadioCardGroup({ name, label, defaultValue, value, onValueChange
|
|
|
62
63
|
}
|
|
63
64
|
/** One option of a `RadioCardGroup`. */
|
|
64
65
|
export function RadioCard({ title, detail, source: sourceContent, className, ...props }) {
|
|
65
|
-
return (_jsxs(BaseRadio.Root, { ...props, className: cx(card, className), "data-ciridae-ui": "", children: [_jsx("span", { className: cx(checkMark({ shape: "round", focus: "row" }), mark), children: _jsx(BaseRadio.Indicator, { className: radioDot }) }), _jsxs("span", { className: copy, children: [_jsx("span", { children: title }), detail !== undefined && _jsx("span", { className: detailText, children: detail })] }), sourceContent !== undefined && _jsx("span", { className: source, children: sourceContent })] }));
|
|
66
|
+
return (_jsxs(BaseRadio.Root, { ...props, className: cx(card, className), "data-ciridae-ui": "", children: [_jsx("span", { ...checkMarkEdge, className: cx(checkMark({ shape: "round", focus: "row" }), mark), children: _jsx(BaseRadio.Indicator, { className: radioDot }) }), _jsxs("span", { className: copy, children: [_jsx("span", { children: title }), detail !== undefined && _jsx("span", { className: detailText, children: detail })] }), sourceContent !== undefined && _jsx("span", { className: source, children: sourceContent })] }));
|
|
66
67
|
}
|
|
@@ -20,7 +20,7 @@ export type DetailLayoutProps = Omit<ComponentProps<"div">, "children"> & {
|
|
|
20
20
|
aside: ReactNode;
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
|
-
export declare function DetailLayout({ header, main, aside, stackBelow, stickyAside, stacking, tabLabels, className, ...props }: DetailLayoutProps): import("
|
|
23
|
+
export declare function DetailLayout({ header, main, aside, stackBelow, stickyAside, stacking, tabLabels, className, ...props }: DetailLayoutProps): import("react").JSX.Element;
|
|
24
24
|
/** The record's title row is the page's: `PageHeading`, with `leading`, `badge` and menu `actions`. */
|
|
25
25
|
export { PageHeading, type PageHeadingProps } from "./page-frame.js";
|
|
26
26
|
export type RelatedTab = {
|
|
@@ -39,7 +39,7 @@ export type RelatedTabsProps = Omit<ComponentProps<typeof TabsRoot>, "children"
|
|
|
39
39
|
defaultValue?: string;
|
|
40
40
|
onValueChange?: (value: string) => void;
|
|
41
41
|
};
|
|
42
|
-
export declare function RelatedTabs({ tabs, value, defaultValue, onValueChange, className, ...props }: RelatedTabsProps): import("
|
|
42
|
+
export declare function RelatedTabs({ tabs, value, defaultValue, onValueChange, className, ...props }: RelatedTabsProps): import("react").JSX.Element | null;
|
|
43
43
|
export type ItemCardField = {
|
|
44
44
|
label: ReactNode;
|
|
45
45
|
value: ReactNode;
|
|
@@ -48,7 +48,7 @@ export type ItemCardField = {
|
|
|
48
48
|
};
|
|
49
49
|
export type ItemCardProps = Omit<useRender.ComponentProps<"button">, "children" | "onSelect"> & {
|
|
50
50
|
title: ReactNode;
|
|
51
|
-
/** One
|
|
51
|
+
/** One dot per stage, in its status. */
|
|
52
52
|
progress?: readonly StepStatus[];
|
|
53
53
|
fields: readonly ItemCardField[];
|
|
54
54
|
/** The footer's start: the stage the item is at. */
|
|
@@ -63,7 +63,31 @@ export type ItemCardProps = Omit<useRender.ComponentProps<"button">, "children"
|
|
|
63
63
|
onSelect?: () => void;
|
|
64
64
|
href?: string;
|
|
65
65
|
};
|
|
66
|
-
export declare function ItemCard({ title, progress, fields, status, footer, selected, onSelect, href, render, className, style, ...props }: ItemCardProps): import("
|
|
66
|
+
export declare function ItemCard({ title, progress, fields, status, footer, selected, onSelect, href, render, className, style, ...props }: ItemCardProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
67
|
+
export type PartRowProps = Omit<ComponentProps<"div">, "children" | "onSelect"> & {
|
|
68
|
+
/** `wide` is one line, as in a table; `compact` stacks for a narrow column. */
|
|
69
|
+
layout?: "wide" | "compact";
|
|
70
|
+
name: ReactNode;
|
|
71
|
+
/** Under the name, such as the part's phase and amount. */
|
|
72
|
+
detail?: ReactNode;
|
|
73
|
+
/** One dot per step, in its status; the kit draws at most four. */
|
|
74
|
+
progress: readonly StepStatus[];
|
|
75
|
+
/** The stage the part is at. */
|
|
76
|
+
stage: ReactNode;
|
|
77
|
+
/** Whose move it is: `yourMove` sets the next step in the ink, the others in grey. */
|
|
78
|
+
state: "yourMove" | "waiting" | "done" | "notStarted";
|
|
79
|
+
/** Before the next step, such as a "Your move" badge. */
|
|
80
|
+
badge?: ReactNode;
|
|
81
|
+
next: ReactNode;
|
|
82
|
+
/** The part's one button, for the reader's move or a nudge while waiting. */
|
|
83
|
+
action?: {
|
|
84
|
+
label: ReactNode;
|
|
85
|
+
onClick: () => void;
|
|
86
|
+
};
|
|
87
|
+
selected?: boolean;
|
|
88
|
+
onSelect?: () => void;
|
|
89
|
+
};
|
|
90
|
+
export declare function PartRow({ layout, name, detail, progress, stage, state, badge, next, action, selected, onSelect, className, ...props }: PartRowProps): import("react").JSX.Element;
|
|
67
91
|
export type RelatedListItem = {
|
|
68
92
|
id: string;
|
|
69
93
|
title: ReactNode;
|
|
@@ -92,4 +116,4 @@ export type RelatedListProps = Omit<ComponentProps<"div">, "children"> & {
|
|
|
92
116
|
/** After the groups, such as a button that links another record. */
|
|
93
117
|
footer?: ReactNode;
|
|
94
118
|
};
|
|
95
|
-
export declare function RelatedList({ groups, footer, className, ...props }: RelatedListProps): import("
|
|
119
|
+
export declare function RelatedList({ groups, footer, className, ...props }: RelatedListProps): import("react").JSX.Element;
|
|
@@ -2,13 +2,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
/*
|
|
3
3
|
* The pieces a record's page is laid out with. `DetailLayout` splits it into the work and a side
|
|
4
4
|
* column; `PageHeading` (also exported here) is the record's title row; `RelatedTabs` is the tabbed card of what the
|
|
5
|
-
* record holds; `ItemCard` is one of a record's parts, such as a shipment or a draw
|
|
5
|
+
* record holds; `ItemCard` is one of a record's parts, such as a shipment or a draw, as a card and `PartRow` as
|
|
6
|
+
* a row; `RelatedList`
|
|
6
7
|
* lists the records and documents it points at.
|
|
7
8
|
*/
|
|
8
9
|
import { useRender } from "@base-ui/react/use-render";
|
|
9
10
|
import { CaretRightIcon } from "@phosphor-icons/react";
|
|
10
|
-
import { useLayoutEffect, useRef, useState, } from "react";
|
|
11
|
+
import { Fragment, useLayoutEffect, useRef, useState, } from "react";
|
|
11
12
|
import { css, cx } from "#primitives/css";
|
|
13
|
+
import { Button } from "./button.js";
|
|
12
14
|
import { useControllableState } from "./controllable-state.js";
|
|
13
15
|
import { directional, icon } from "./icon.js";
|
|
14
16
|
import { MutedText } from "./layout.js";
|
|
@@ -110,7 +112,10 @@ export function RelatedTabs({ tabs, value, defaultValue, onValueChange, classNam
|
|
|
110
112
|
return null;
|
|
111
113
|
return (_jsxs(TabsRoot, { value: open.value, onValueChange: (next) => setChosen(String(next)), ...props, className: cx(relatedCard, className), "data-ciridae-ui": "", children: [_jsxs("div", { className: relatedHeader, children: [_jsx(TabsList, { variant: "contained", children: tabs.map((tab) => (_jsx(TabsTab, { value: tab.value, count: tab.count, children: tab.label }, tab.value))) }), open.meta !== undefined && _jsx(MutedText, { className: relatedMeta, children: open.meta })] }), tabs.map((tab) => (_jsx(TabsPanel, { value: tab.value, children: tab.content }, tab.value)))] }));
|
|
112
114
|
}
|
|
113
|
-
/*
|
|
115
|
+
/*
|
|
116
|
+
* Item card: one of a record's parts, the kit's Part card, with its progress as a mini strip of
|
|
117
|
+
* step dots. The chosen one lifts onto the solid card inside a green edge.
|
|
118
|
+
*/
|
|
114
119
|
const itemCard = css(cardSurface, {
|
|
115
120
|
display: "grid",
|
|
116
121
|
gap: "layout.clusterGap",
|
|
@@ -121,7 +126,11 @@ const itemCard = css(cardSurface, {
|
|
|
121
126
|
letterSpacing: "compact",
|
|
122
127
|
textDecoration: "none",
|
|
123
128
|
"&:is(button, a)": { cursor: "pointer", _hover: { borderColor: "border.glass" } },
|
|
124
|
-
"&[data-selected]": {
|
|
129
|
+
"&[data-selected]": {
|
|
130
|
+
borderColor: "accent.green",
|
|
131
|
+
boxShadow: "soft",
|
|
132
|
+
_hover: { borderColor: "accent.green" },
|
|
133
|
+
},
|
|
125
134
|
_focusVisible: { focusRing: "outer" },
|
|
126
135
|
});
|
|
127
136
|
const itemHeader = css({
|
|
@@ -131,20 +140,27 @@ const itemHeader = css({
|
|
|
131
140
|
gap: "layout.controlGap",
|
|
132
141
|
fontSize: "body",
|
|
133
142
|
fontWeight: "medium",
|
|
143
|
+
lineHeight: "tight",
|
|
134
144
|
whiteSpace: "nowrap",
|
|
135
145
|
});
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
const progressStrip = css({
|
|
147
|
+
display: "inline-flex",
|
|
148
|
+
flexShrink: "0",
|
|
149
|
+
alignItems: "center",
|
|
150
|
+
gap: "layout.tightGap",
|
|
151
|
+
});
|
|
152
|
+
// 16px between dots, green out of a finished step as the stage strip's connectors are.
|
|
153
|
+
const progressConnector = css({
|
|
154
|
+
width: "token(spacing.layout.clusterGap)",
|
|
155
|
+
height: "border.hairline",
|
|
156
|
+
borderRadius: "round",
|
|
157
|
+
background: "border.divider",
|
|
158
|
+
"&[data-after=done]": { background: "accent.green" },
|
|
147
159
|
});
|
|
160
|
+
/** A part's progress: one 12px dot a step, joined by 16px connectors. */
|
|
161
|
+
function MiniStrip({ progress }) {
|
|
162
|
+
return (_jsx("span", { className: progressStrip, "aria-hidden": "true", children: progress.map((step, index) => (_jsxs(Fragment, { children: [index > 0 && (_jsx("span", { className: progressConnector, "data-after": progress[index - 1] === "done" ? "done" : undefined })), _jsx(StepDot, { status: step, size: "chip" })] }, index))) }));
|
|
163
|
+
}
|
|
148
164
|
const itemFields = css({
|
|
149
165
|
display: "grid",
|
|
150
166
|
gap: "layout.controlGap",
|
|
@@ -155,7 +171,7 @@ const itemFields = css({
|
|
|
155
171
|
const itemFieldLabel = css({
|
|
156
172
|
display: "block",
|
|
157
173
|
marginBottom: "layout.controlGap",
|
|
158
|
-
color: "fg.
|
|
174
|
+
color: "fg.subtle",
|
|
159
175
|
fontWeight: "regular",
|
|
160
176
|
letterSpacing: "normal",
|
|
161
177
|
});
|
|
@@ -188,10 +204,117 @@ export function ItemCard({ title, progress, fields, status, footer, selected = f
|
|
|
188
204
|
"data-ciridae-ui": "",
|
|
189
205
|
"data-selected": selected || undefined,
|
|
190
206
|
"aria-pressed": onSelect !== undefined && href === undefined ? selected : undefined,
|
|
191
|
-
children: (_jsxs(_Fragment, { children: [_jsxs("span", { className: itemHeader, children: [title, progress &&
|
|
207
|
+
children: (_jsxs(_Fragment, { children: [_jsxs("span", { className: itemHeader, children: [title, progress && _jsx(MiniStrip, { progress: progress })] }), _jsxs("span", { className: css({ display: "grid" }), children: [_jsx("span", { className: itemFields, style: columns, children: fields.map((field, index) => (_jsxs("span", { children: [_jsx("span", { className: itemFieldLabel, children: field.label }), field.value] }, index))) }), _jsxs("span", { className: itemFooter, children: [_jsxs("span", { className: itemStatus, children: [_jsx(StepDot, { status: status.status, size: "small" }), status.label] }), footer] })] })] })),
|
|
192
208
|
},
|
|
193
209
|
});
|
|
194
210
|
}
|
|
211
|
+
/*
|
|
212
|
+
* Part row: one of a record's parts as a table-like row, the kit's Part in its Wide and Compact
|
|
213
|
+
* layouts: name over detail, the mini strip, the stage, a badge for the reader's move, the next
|
|
214
|
+
* step and at most one action. Wide keeps it on one 56px line, wrapping the detail and next step
|
|
215
|
+
* only when the row is narrow; compact stacks the name and strip over the rest. The whole row chooses the part through its name; the action stays its own button.
|
|
216
|
+
*/
|
|
217
|
+
const partRow = css({
|
|
218
|
+
position: "relative",
|
|
219
|
+
display: "flex",
|
|
220
|
+
alignItems: "center",
|
|
221
|
+
gap: "layout.clusterGap",
|
|
222
|
+
minHeight: "calc(token(sizes.control.compact) + token(spacing.panel.default) * 2)",
|
|
223
|
+
paddingBlock: "panel.default",
|
|
224
|
+
paddingInline: "panel.comfortable",
|
|
225
|
+
borderBottom: "1px solid token(colors.border.divider)",
|
|
226
|
+
fontWeight: "medium",
|
|
227
|
+
letterSpacing: "compact",
|
|
228
|
+
lineHeight: "tight",
|
|
229
|
+
"&:has([data-part-name]:hover)": { background: "bg.rowHover" },
|
|
230
|
+
"&[data-selected]": { background: "token(gradients.selected)" },
|
|
231
|
+
// Wide is a grid, so the strips and stages of a list of parts line up. The name and the next
|
|
232
|
+
// step share what the strip, stage and action leave, two parts to three, close to the kit's
|
|
233
|
+
// 240 and 488 in its 1092 row, so a narrow row narrows both rather than starving one.
|
|
234
|
+
"&[data-layout=wide]": {
|
|
235
|
+
display: "grid",
|
|
236
|
+
gridTemplateColumns: "minmax(0, 2fr) max-content 90px minmax(0, 3fr) max-content",
|
|
237
|
+
},
|
|
238
|
+
"&[data-layout=compact]": {
|
|
239
|
+
flexDirection: "column",
|
|
240
|
+
alignItems: "stretch",
|
|
241
|
+
gap: "layout.tightGap",
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
const partLine = css({
|
|
245
|
+
display: "flex",
|
|
246
|
+
alignItems: "center",
|
|
247
|
+
gap: "layout.contentGap",
|
|
248
|
+
minWidth: "0",
|
|
249
|
+
"[data-layout=wide] > &": { display: "contents" },
|
|
250
|
+
});
|
|
251
|
+
const partName = css({
|
|
252
|
+
display: "grid",
|
|
253
|
+
gap: "control.trackInset",
|
|
254
|
+
flex: "1 1 0",
|
|
255
|
+
minWidth: "0",
|
|
256
|
+
textAlign: "start",
|
|
257
|
+
"& > *": { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
258
|
+
});
|
|
259
|
+
// The name is the row's button: its box stretches over the whole row.
|
|
260
|
+
const partNameButton = css({
|
|
261
|
+
padding: "none",
|
|
262
|
+
border: "none",
|
|
263
|
+
background: "transparent",
|
|
264
|
+
color: "fg.primary",
|
|
265
|
+
font: "inherit",
|
|
266
|
+
fontSize: "body",
|
|
267
|
+
textAlign: "start",
|
|
268
|
+
cursor: "pointer",
|
|
269
|
+
_after: { content: '""', position: "absolute", inset: "0" },
|
|
270
|
+
_focusVisible: { outline: "none", _after: { focusRing: "inset" } },
|
|
271
|
+
});
|
|
272
|
+
// A narrow wide row wraps the detail rather than cut off its amount.
|
|
273
|
+
const partDetail = css({
|
|
274
|
+
color: "fg.subtle",
|
|
275
|
+
fontSize: "code",
|
|
276
|
+
"[data-layout=wide] &": { whiteSpace: "normal", lineHeight: "compact" },
|
|
277
|
+
});
|
|
278
|
+
const partStage = css({
|
|
279
|
+
flexShrink: "0",
|
|
280
|
+
color: "fg.subtle",
|
|
281
|
+
fontSize: "code",
|
|
282
|
+
whiteSpace: "nowrap",
|
|
283
|
+
"[data-layout=wide] &": { overflow: "hidden", textOverflow: "ellipsis" },
|
|
284
|
+
});
|
|
285
|
+
const partStatus = css({
|
|
286
|
+
display: "flex",
|
|
287
|
+
alignItems: "center",
|
|
288
|
+
gap: "layout.controlGap",
|
|
289
|
+
flexShrink: "0",
|
|
290
|
+
"[data-layout=wide] > * > &": { display: "contents" },
|
|
291
|
+
});
|
|
292
|
+
// Wide sets the badge after the stage, in the next step's cell; compact leads the status with it.
|
|
293
|
+
const partNextCell = css({
|
|
294
|
+
display: "flex",
|
|
295
|
+
alignItems: "center",
|
|
296
|
+
gap: "layout.clusterGap",
|
|
297
|
+
minWidth: "0",
|
|
298
|
+
"[data-layout=compact] &": { display: "contents" },
|
|
299
|
+
});
|
|
300
|
+
const partBadge = css({
|
|
301
|
+
display: "inline-flex",
|
|
302
|
+
flexShrink: "0",
|
|
303
|
+
"[data-layout=compact] &": { order: "-1" },
|
|
304
|
+
});
|
|
305
|
+
// The step the reader acts on wraps in a narrow row, never cut short.
|
|
306
|
+
const partNext = css({
|
|
307
|
+
minWidth: "0",
|
|
308
|
+
color: "fg.secondary",
|
|
309
|
+
fontSize: "caption",
|
|
310
|
+
lineHeight: "compact",
|
|
311
|
+
"[data-state=yourMove] &": { color: "fg.primary" },
|
|
312
|
+
});
|
|
313
|
+
// The action sits over the stretched name, so it stays its own button.
|
|
314
|
+
const partAction = css({ position: "relative", flexShrink: "0" });
|
|
315
|
+
export function PartRow({ layout = "wide", name, detail, progress, stage, state, badge, next, action, selected = false, onSelect, className, ...props }) {
|
|
316
|
+
return (_jsxs("div", { ...props, className: cx(partRow, className), "data-ciridae-ui": "", "data-layout": layout, "data-state": state, "data-selected": selected || undefined, children: [_jsxs("span", { className: partLine, children: [_jsxs("span", { className: partName, children: [onSelect ? (_jsx("button", { type: "button", className: partNameButton, "data-part-name": "", "aria-pressed": selected, onClick: onSelect, children: name })) : (_jsx("span", { className: css({ fontSize: "body" }), children: name })), layout === "wide" && detail !== undefined && (_jsx("span", { className: partDetail, children: detail }))] }), _jsx(MiniStrip, { progress: progress })] }), _jsxs("span", { className: partLine, children: [layout === "compact" && _jsx("span", { className: cx(partName, partDetail), children: detail }), _jsxs("span", { className: partStatus, children: [_jsx("span", { className: partStage, children: stage }), _jsxs("span", { className: partNextCell, children: [badge !== undefined && _jsx("span", { className: partBadge, children: badge }), _jsx("span", { className: partNext, children: next })] }), action && (_jsx(Button, { variant: "secondary", className: partAction, onClick: action.onClick, children: action.label }))] })] })] }));
|
|
317
|
+
}
|
|
195
318
|
/* Related list: the records and documents a record points at, grouped by relation. */
|
|
196
319
|
const groupHeader = css({
|
|
197
320
|
display: "flex",
|
|
@@ -221,7 +344,11 @@ const relatedRow = css({
|
|
|
221
344
|
font: "inherit",
|
|
222
345
|
textAlign: "start",
|
|
223
346
|
textDecoration: "none",
|
|
224
|
-
|
|
347
|
+
// The kit's Linked record hovers to the selected glass in dark and the row wash in light.
|
|
348
|
+
"&:is(button, a)": {
|
|
349
|
+
cursor: "pointer",
|
|
350
|
+
_hover: { background: "token(gradients.selected)", _light: { background: "bg.rowHover" } },
|
|
351
|
+
},
|
|
225
352
|
_focusVisible: { focusRing: "outer" },
|
|
226
353
|
});
|
|
227
354
|
const tile = css({
|
|
@@ -234,6 +361,7 @@ const tile = css({
|
|
|
234
361
|
borderRadius: "action",
|
|
235
362
|
background: "bg.panel",
|
|
236
363
|
color: "fg.secondary",
|
|
364
|
+
_light: { background: "bg.field" },
|
|
237
365
|
"& svg": { fontSize: "icon.small" },
|
|
238
366
|
});
|
|
239
367
|
const rowTitle = css({
|
|
@@ -251,6 +379,7 @@ const rowMeta = css({
|
|
|
251
379
|
color: "fg.secondary",
|
|
252
380
|
fontSize: "code",
|
|
253
381
|
fontWeight: "medium",
|
|
382
|
+
lineHeight: "tight",
|
|
254
383
|
"& [data-separator]": { color: "fg.muted" },
|
|
255
384
|
"& [data-tone=info]": { color: "accent.blue" },
|
|
256
385
|
"& [data-tone=success]": { color: "accent.green" },
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** A file whose bytes load from `url`, or from what the resolver hands back when it has none. */
|
|
2
|
+
export type ResolvableFile = {
|
|
3
|
+
id: string;
|
|
4
|
+
url?: string | null;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Hands back a browser-loadable link for a file without one, such as one served behind a bearer
|
|
8
|
+
* token, which the app downloads and serves from an object URL. Keep the function stable: its
|
|
9
|
+
* links are cached per function and file id, so a redraw does not load the file again.
|
|
10
|
+
*/
|
|
11
|
+
export type ResolveFileUrl<File extends ResolvableFile = ResolvableFile> = (file: File) => Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* The file's link: its own `url`, else the resolver's once it settles. `state` is `failed` when the
|
|
14
|
+
* resolver rejected, and `pending` while it runs or while `enabled` is false.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useResolvedFileUrl<File extends ResolvableFile>(file: File | undefined, resolve: ResolveFileUrl<File> | undefined, enabled?: boolean): {
|
|
17
|
+
url: string | null;
|
|
18
|
+
state: "ready" | "pending" | "failed" | "none";
|
|
19
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
const resolvedUrls = new WeakMap();
|
|
3
|
+
function resolveOnce(resolve, file) {
|
|
4
|
+
let cache = resolvedUrls.get(resolve);
|
|
5
|
+
if (!cache) {
|
|
6
|
+
cache = new Map();
|
|
7
|
+
resolvedUrls.set(resolve, cache);
|
|
8
|
+
}
|
|
9
|
+
const cached = cache.get(file.id);
|
|
10
|
+
if (cached)
|
|
11
|
+
return cached;
|
|
12
|
+
const pending = resolve(file);
|
|
13
|
+
cache.set(file.id, pending);
|
|
14
|
+
// A failed load is not kept, so the next look at the file tries again.
|
|
15
|
+
pending.catch(() => cache.delete(file.id));
|
|
16
|
+
return pending;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The file's link: its own `url`, else the resolver's once it settles. `state` is `failed` when the
|
|
20
|
+
* resolver rejected, and `pending` while it runs or while `enabled` is false.
|
|
21
|
+
*/
|
|
22
|
+
export function useResolvedFileUrl(file, resolve, enabled = true) {
|
|
23
|
+
const direct = file?.url ?? null;
|
|
24
|
+
const [resolved, setResolved] = useState(null);
|
|
25
|
+
const fileId = file?.id;
|
|
26
|
+
// The file's id names it: a new object for the same file is not a new file to load.
|
|
27
|
+
const fileRef = useRef(file);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
fileRef.current = file;
|
|
30
|
+
});
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const file = fileRef.current;
|
|
33
|
+
if (!file || direct || !resolve || !enabled)
|
|
34
|
+
return;
|
|
35
|
+
let current = true;
|
|
36
|
+
resolveOnce(resolve, file).then((url) => current && setResolved({ id: file.id, url, failed: false }), () => current && setResolved({ id: file.id, url: null, failed: true }));
|
|
37
|
+
return () => {
|
|
38
|
+
current = false;
|
|
39
|
+
};
|
|
40
|
+
}, [fileId, direct, resolve, enabled]);
|
|
41
|
+
if (direct)
|
|
42
|
+
return { url: direct, state: "ready" };
|
|
43
|
+
if (!file || !resolve)
|
|
44
|
+
return { url: null, state: "none" };
|
|
45
|
+
const settled = resolved?.id === file.id ? resolved : null;
|
|
46
|
+
if (settled?.url)
|
|
47
|
+
return { url: settled.url, state: "ready" };
|
|
48
|
+
return { url: null, state: settled?.failed ? "failed" : "pending" };
|
|
49
|
+
}
|
|
@@ -13,4 +13,4 @@ export declare function ScrollArea({ className, viewportClassName, scrollDirecti
|
|
|
13
13
|
scrollDirections?: "vertical" | "vertical-and-horizontal";
|
|
14
14
|
children: ReactNode;
|
|
15
15
|
"aria-label"?: string;
|
|
16
|
-
}): import("
|
|
16
|
+
}): import("react").JSX.Element;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { type ComponentProps, type ReactNode } from "react";
|
|
2
2
|
import type { Tone } from "./badge.js";
|
|
3
|
+
/** A segment's hue: a tone by meaning, or `indigo`, the chart's category no status hue covers. */
|
|
4
|
+
export type SegmentedBarHue = Tone | "indigo";
|
|
3
5
|
export type SegmentedBarSegment = {
|
|
4
6
|
id: string;
|
|
5
7
|
label: string;
|
|
6
8
|
value: number;
|
|
7
9
|
/** The segment's color by meaning; `neutral` by default. */
|
|
8
|
-
tone?:
|
|
10
|
+
tone?: SegmentedBarHue;
|
|
9
11
|
/** A color of its own, such as a CSS variable the app themes, over `tone`. */
|
|
10
12
|
color?: string;
|
|
11
13
|
};
|
|
@@ -20,4 +22,4 @@ export type SegmentedBarProps = Omit<ComponentProps<"div">, "children"> & {
|
|
|
20
22
|
/** How a value reads in the legend and a segment's name; the locale's number by default. */
|
|
21
23
|
formatValue?: (value: number) => string;
|
|
22
24
|
};
|
|
23
|
-
export declare function SegmentedBar({ segments, legend, renderDetail, onSegmentSelect, formatValue, className, ...props }: SegmentedBarProps): import("
|
|
25
|
+
export declare function SegmentedBar({ segments, legend, renderDetail, onSegmentSelect, formatValue, className, ...props }: SegmentedBarProps): import("react").JSX.Element;
|
|
@@ -11,14 +11,16 @@ import { useCiridaeLocale } from "./locale.js";
|
|
|
11
11
|
import { Popover } from "./overlays.js";
|
|
12
12
|
const root = css({ display: "flex", flexDirection: "column", gap: "layout.sectionGap" });
|
|
13
13
|
const bar = css({ display: "flex", gap: "layout.tightGap", height: "8px" });
|
|
14
|
+
// The chart's data marks, so a segment and its swatch match the series in a chart.
|
|
14
15
|
const toneColor = cva({
|
|
15
16
|
variants: {
|
|
16
17
|
tone: {
|
|
17
|
-
neutral: { background: "
|
|
18
|
-
info: { background: "
|
|
19
|
-
success: { background: "
|
|
20
|
-
warning: { background: "
|
|
21
|
-
|
|
18
|
+
neutral: { background: "chart.neutral" },
|
|
19
|
+
info: { background: "chart.trend" },
|
|
20
|
+
success: { background: "chart.category2" },
|
|
21
|
+
warning: { background: "chart.category1" },
|
|
22
|
+
indigo: { background: "chart.category3" },
|
|
23
|
+
danger: { background: "chart.category4" },
|
|
22
24
|
},
|
|
23
25
|
},
|
|
24
26
|
});
|
|
@@ -42,7 +44,15 @@ const legendRow = css({
|
|
|
42
44
|
paddingTop: "panel.comfortable",
|
|
43
45
|
borderTop: "1px solid token(colors.border.panel)",
|
|
44
46
|
});
|
|
45
|
-
const legendItem = css({
|
|
47
|
+
const legendItem = css({
|
|
48
|
+
display: "inline-flex",
|
|
49
|
+
alignItems: "center",
|
|
50
|
+
gap: "layout.contentGap",
|
|
51
|
+
color: "fg.primary",
|
|
52
|
+
fontSize: "body",
|
|
53
|
+
fontWeight: "medium",
|
|
54
|
+
lineHeight: "tight",
|
|
55
|
+
});
|
|
46
56
|
const legendKey = css({
|
|
47
57
|
display: "inline-flex",
|
|
48
58
|
alignItems: "center",
|
|
@@ -18,20 +18,23 @@ export type SelectProps = {
|
|
|
18
18
|
label?: string;
|
|
19
19
|
/** `medium` is the Round 2 field height; `small` is the pill beside other filters. */
|
|
20
20
|
size?: ControlSize;
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Defaults to the flat `field` at medium and the glass `raised` face when small. `underline` is
|
|
23
|
+
* a 34px row control at the body size, such as a table footer's rows per page, whatever `size`.
|
|
24
|
+
*/
|
|
25
|
+
variant?: "field" | "raised" | "underline";
|
|
23
26
|
/** Submits the value with an enclosing form under this name. */
|
|
24
27
|
name?: string;
|
|
25
28
|
/** Blocks the enclosing form's submission until a value is chosen. */
|
|
26
29
|
required?: boolean;
|
|
27
30
|
disabled?: boolean;
|
|
28
31
|
};
|
|
29
|
-
export declare function Select({ options, value, onValueChange, placeholder, label, size: controlSize, variant, name, required, disabled, }: SelectProps): import("
|
|
32
|
+
export declare function Select({ options, value, onValueChange, placeholder, label, size: controlSize, variant, name, required, disabled, }: SelectProps): import("react").JSX.Element;
|
|
30
33
|
export type SlicerProps = Omit<SelectProps, "size" | "variant" | "placeholder"> & {
|
|
31
34
|
/** What the slicer filters by, shown muted before the chosen value. */
|
|
32
35
|
label: string;
|
|
33
36
|
};
|
|
34
|
-
export declare function Slicer({ options, value, onValueChange, label, name, required, disabled, }: SlicerProps): import("
|
|
37
|
+
export declare function Slicer({ options, value, onValueChange, label, name, required, disabled, }: SlicerProps): import("react").JSX.Element;
|
|
35
38
|
export type ComboboxProps<Option extends SelectOption> = {
|
|
36
39
|
options: readonly Option[];
|
|
37
40
|
value?: string;
|
|
@@ -69,7 +72,7 @@ export type ComboboxProps<Option extends SelectOption> = {
|
|
|
69
72
|
* itself. With `onSearch`, the caller owns the options: typing reports the query once it pauses,
|
|
70
73
|
* and the list shows whatever `options` the caller passes back, with `loading` while it fetches.
|
|
71
74
|
*/
|
|
72
|
-
export declare function Combobox<Option extends SelectOption>({ options, value, onValueChange, placeholder: ownPlaceholder, label: ownLabel, size: controlSize, renderOption, emptyMessage, name, required, disabled, onSearch, loading, defaultOpen, onOpenChange, autoFocus, }: ComboboxProps<Option>): import("
|
|
75
|
+
export declare function Combobox<Option extends SelectOption>({ options, value, onValueChange, placeholder: ownPlaceholder, label: ownLabel, size: controlSize, renderOption, emptyMessage, name, required, disabled, onSearch, loading, defaultOpen, onOpenChange, autoFocus, }: ComboboxProps<Option>): import("react").JSX.Element;
|
|
73
76
|
export declare function FilterPopover({ label, count, open, onOpenChange, onClear, children, }: {
|
|
74
77
|
/** The locale's "Filters" by default. */
|
|
75
78
|
label?: ReactNode;
|
|
@@ -81,4 +84,4 @@ export declare function FilterPopover({ label, count, open, onOpenChange, onClea
|
|
|
81
84
|
onClear?: () => void;
|
|
82
85
|
/** The filters, such as compact `Combobox` and `Slicer` pills. */
|
|
83
86
|
children: ReactNode;
|
|
84
|
-
}): import("
|
|
87
|
+
}): import("react").JSX.Element;
|