@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
|
@@ -3,8 +3,11 @@ import { CheckIcon, CopyIcon } from "@phosphor-icons/react";
|
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
import { css, cx } from "#primitives/css";
|
|
5
5
|
import { IconButton } from "./button.js";
|
|
6
|
+
import { Field, FieldLabel } from "./form-layout.js";
|
|
6
7
|
import { icon } from "./icon.js";
|
|
8
|
+
import { Input } from "./input.js";
|
|
7
9
|
import { useCiridaeLocale } from "./locale.js";
|
|
10
|
+
import { useToast } from "./toast.js";
|
|
8
11
|
const copyableId = css({
|
|
9
12
|
display: "inline-flex",
|
|
10
13
|
alignItems: "center",
|
|
@@ -23,20 +26,41 @@ const shownLength = 8;
|
|
|
23
26
|
const copiedFeedbackMs = 1500;
|
|
24
27
|
/**
|
|
25
28
|
* Copies `value` (or what it returns, read at the moment of copying) and reports `copied` for a
|
|
26
|
-
* moment afterwards, for a check-mark confirmation.
|
|
29
|
+
* moment afterwards, for a check-mark confirmation. A copy the browser refuses, such as a denied
|
|
30
|
+
* permission or an insecure origin with no clipboard, goes to `onError`, or without one raises the
|
|
31
|
+
* kit's error toast, so a reader never pastes a stale clipboard thinking it holds the value.
|
|
27
32
|
*/
|
|
28
|
-
export function useCopy(value, onCopied) {
|
|
33
|
+
export function useCopy(value, onCopied, onError) {
|
|
29
34
|
const [copied, setCopied] = useState(false);
|
|
35
|
+
const { labels } = useCiridaeLocale();
|
|
36
|
+
const toast = useToast();
|
|
30
37
|
useEffect(() => {
|
|
31
38
|
if (!copied)
|
|
32
39
|
return;
|
|
33
40
|
const timer = setTimeout(() => setCopied(false), copiedFeedbackMs);
|
|
34
41
|
return () => clearTimeout(timer);
|
|
35
42
|
}, [copied]);
|
|
36
|
-
|
|
43
|
+
// `await` rather than `.catch`: an insecure origin has no `navigator.clipboard` at all and
|
|
44
|
+
// throws before a promise exists.
|
|
45
|
+
const writeValue = async () => {
|
|
46
|
+
try {
|
|
47
|
+
await navigator.clipboard.writeText(typeof value === "function" ? value() : value);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (onError)
|
|
51
|
+
onError(error);
|
|
52
|
+
else
|
|
53
|
+
toast.add({
|
|
54
|
+
variant: "error",
|
|
55
|
+
title: labels.clipboard.copyFailed,
|
|
56
|
+
description: labels.clipboard.copyByHand,
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
37
60
|
setCopied(true);
|
|
38
61
|
onCopied?.();
|
|
39
|
-
}
|
|
62
|
+
};
|
|
63
|
+
const copy = () => void writeValue();
|
|
40
64
|
return { copied, copy };
|
|
41
65
|
}
|
|
42
66
|
const inlineCopy = css({
|
|
@@ -51,8 +75,8 @@ const inlineCopy = css({
|
|
|
51
75
|
_focusVisible: { focusRing: "outer", borderRadius: "control" },
|
|
52
76
|
});
|
|
53
77
|
/** A button that copies `value`, its icon turning into a check once copied. */
|
|
54
|
-
export function CopyButton({ value, label, variant = "raised", size, onCopied, className, }) {
|
|
55
|
-
const { copied, copy } = useCopy(value, onCopied);
|
|
78
|
+
export function CopyButton({ value, label, variant = "raised", size, onCopied, onError, className, }) {
|
|
79
|
+
const { copied, copy } = useCopy(value, onCopied, onError);
|
|
56
80
|
const { labels } = useCiridaeLocale();
|
|
57
81
|
const name = copied
|
|
58
82
|
? labels.common.copied
|
|
@@ -134,3 +158,19 @@ export function CopyableText({ text, label, className, }) {
|
|
|
134
158
|
};
|
|
135
159
|
return (_jsxs("span", { className: copyableText, "data-ciridae-ui": "", onMouseEnter: measureOverflow, children: [_jsx("span", { ref: box, className: cx(marqueeBox, className), title: text, children: _jsx("span", { children: text }) }), _jsx("button", { type: "button", className: copyTextButton, "aria-label": labels.common.copy(label), "data-copied": copied || undefined, onClick: copy, children: copied ? (_jsx(CheckIcon, { className: icon({ size: "small" }) })) : (_jsx(CopyIcon, { className: icon({ size: "small" }) })) })] }));
|
|
136
160
|
}
|
|
161
|
+
const copyFieldRow = css({
|
|
162
|
+
display: "grid",
|
|
163
|
+
gridTemplateColumns: "minmax(0, 1fr) auto",
|
|
164
|
+
alignItems: "end",
|
|
165
|
+
gap: "layout.tightGap",
|
|
166
|
+
});
|
|
167
|
+
const copyFieldValue = css({ fontFamily: "mono", fontSize: "code" });
|
|
168
|
+
/**
|
|
169
|
+
* A value to paste elsewhere, such as a command or a connection code, as a labelled read-only
|
|
170
|
+
* field with a copy button: it selects on focus and reads like the field it is pasted into. The
|
|
171
|
+
* row stays while there is no value yet, showing `placeholder`. The value is masked from session
|
|
172
|
+
* recorders, since such values are often credentials.
|
|
173
|
+
*/
|
|
174
|
+
export function CopyField({ label, value, placeholder, className, }) {
|
|
175
|
+
return (_jsxs("div", { className: cx(copyFieldRow, className), "data-ciridae-ui": "", children: [_jsxs(Field, { children: [_jsx(FieldLabel, { children: label }), _jsx(Input, { className: cx("ph-no-capture", copyFieldValue), "data-sentry-mask": true, onFocus: (event) => event.target.select(), placeholder: placeholder, readOnly: true, value: value ?? "" })] }), value !== undefined && _jsx(CopyButton, { label: label, value: value, variant: "ghost" })] }));
|
|
176
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Separator as BaseSeparator } from "@base-ui/react/separator";
|
|
2
2
|
import type { ComponentProps, ReactNode } from "react";
|
|
3
3
|
export type AvatarColor = "neutral" | "blue" | "violet" | "green" | "teal" | "yellow" | "orange" | "pink" | "red";
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* 12, 14, 20, 24, 26, 28, 32 (`row` and `medium`) and 44 pixels; the kit's set is `menu` through
|
|
6
|
+
* `large`.
|
|
7
|
+
*/
|
|
8
|
+
export type AvatarSize = "micro" | "mark" | "small" | "menu" | "agent" | "owner" | "row" | "medium" | "large";
|
|
6
9
|
/**
|
|
7
10
|
* The one mark for a person, an organization, a project, or the agent: `src` shows the photo or
|
|
8
11
|
* logo, and the initials derived from `label` stand in until it loads or when there is none. A
|
|
@@ -19,24 +22,30 @@ export declare function Avatar({ label, src, size, kind, icon, badge, color, cla
|
|
|
19
22
|
icon?: ReactNode;
|
|
20
23
|
badge?: ReactNode;
|
|
21
24
|
color?: AvatarColor;
|
|
22
|
-
}): import("
|
|
25
|
+
}): import("react").JSX.Element;
|
|
26
|
+
/** The slot where an owner's avatar goes, before anyone owns the record. */
|
|
27
|
+
export declare function UnassignedAvatar({ size, className, ...props }: ComponentProps<"span"> & {
|
|
28
|
+
size?: "small" | "owner" | "row";
|
|
29
|
+
}): import("react").JSX.Element;
|
|
23
30
|
export declare function Divider({ inset, className, ...props }: Omit<ComponentProps<typeof BaseSeparator>, "className"> & {
|
|
24
31
|
className?: string;
|
|
25
32
|
/** `menu` insets it to a menu's or a popover's rows. */
|
|
26
33
|
inset?: "none" | "menu";
|
|
27
|
-
}): import("
|
|
34
|
+
}): import("react").JSX.Element;
|
|
28
35
|
export type DescriptionRow = [label: string, value: ReactNode];
|
|
29
36
|
/**
|
|
30
37
|
* Label-value pairs in two columns. Rows whose value is `null` or `undefined` are left out, so
|
|
31
|
-
* callers can list every field a record may carry. `compact`
|
|
38
|
+
* callers can list every field a record may carry. `compact` sets them as key-value pairs;
|
|
39
|
+
* `layout="facts"` as fact rows, each value at the far edge over a hairline.
|
|
32
40
|
* `loading` keeps every row's label and draws a placeholder for its value, so the list arrives at
|
|
33
41
|
* the size it loads to; build the rows from the record that may not have loaded yet.
|
|
34
42
|
*/
|
|
35
|
-
export declare function DescriptionList({ rows, density, loading, className, ...props }: ComponentProps<"dl"> & {
|
|
43
|
+
export declare function DescriptionList({ rows, density, layout, loading, className, ...props }: ComponentProps<"dl"> & {
|
|
36
44
|
rows: DescriptionRow[];
|
|
37
45
|
density?: "default" | "compact";
|
|
46
|
+
layout?: "columns" | "facts";
|
|
38
47
|
loading?: boolean;
|
|
39
|
-
}): import("
|
|
48
|
+
}): import("react").JSX.Element;
|
|
40
49
|
/**
|
|
41
50
|
* Scrollable block of literal text, such as a command or a generated file. `copy` adds a copy
|
|
42
51
|
* button with that text, which can differ from what is shown (e.g. masked secrets).
|
|
@@ -44,4 +53,26 @@ export declare function DescriptionList({ rows, density, loading, className, ...
|
|
|
44
53
|
export declare function CodeBlock({ className, copy, copyLabel, ...props }: ComponentProps<"pre"> & {
|
|
45
54
|
copy?: string;
|
|
46
55
|
copyLabel?: string;
|
|
47
|
-
}): import("
|
|
56
|
+
}): import("react").JSX.Element;
|
|
57
|
+
/** Where a field's value came from, or who vouches for it: a 14px icon and a line. */
|
|
58
|
+
export type DetailFieldNote = {
|
|
59
|
+
icon?: ReactNode;
|
|
60
|
+
label: ReactNode;
|
|
61
|
+
};
|
|
62
|
+
export type DetailFieldProps = Omit<ComponentProps<"div">, "children"> & {
|
|
63
|
+
label: ReactNode;
|
|
64
|
+
value: ReactNode;
|
|
65
|
+
/** Where the value came from, such as "Net 30 from Aug 22". */
|
|
66
|
+
source?: DetailFieldNote;
|
|
67
|
+
/** Who or what vouches for it, such as "Checked by Dana R.". */
|
|
68
|
+
assurance?: DetailFieldNote;
|
|
69
|
+
/** Beside the value, such as a Contested badge; its line under the value is `description`. */
|
|
70
|
+
badge?: ReactNode;
|
|
71
|
+
description?: ReactNode;
|
|
72
|
+
/** A trailing button, such as Resolve. */
|
|
73
|
+
action?: ReactNode;
|
|
74
|
+
state?: "default" | "selected" | "inset" | "highlighted";
|
|
75
|
+
/** A hairline under the row; the last row of a list leaves it out. Defaults to true. */
|
|
76
|
+
divider?: boolean;
|
|
77
|
+
};
|
|
78
|
+
export declare function DetailField({ label, value, source, assurance, badge, description, action, state, divider, className, ...props }: DetailFieldProps): import("react").JSX.Element;
|
|
@@ -6,10 +6,11 @@ import { Fragment } from "react";
|
|
|
6
6
|
import { css, cva, cx } from "#primitives/css";
|
|
7
7
|
import { CopyButton } from "./copyable-id.js";
|
|
8
8
|
import { Skeleton } from "./skeleton.js";
|
|
9
|
-
// The neutral avatar is
|
|
10
|
-
// organization
|
|
11
|
-
// fill, text, and border from one `--avatar-hue`, mixed toward the surface or
|
|
12
|
-
// holds in both themes. The hues are brighter than the accent tokens so
|
|
9
|
+
// The neutral avatar is a person or the agent on the raised glass gradient inside its gradient
|
|
10
|
+
// hairline, an organization the text-colored tile the workspace switcher shows. A colored one
|
|
11
|
+
// derives its fill, text, and border from one `--avatar-hue`, mixed toward the opaque surface or
|
|
12
|
+
// the text color so it holds in both themes. The hues are brighter than the accent tokens so
|
|
13
|
+
// avatars read apart.
|
|
13
14
|
const avatar = css({
|
|
14
15
|
display: "inline-grid",
|
|
15
16
|
placeItems: "center",
|
|
@@ -41,24 +42,25 @@ const avatar = css({
|
|
|
41
42
|
// A person, or the agent: a circle on the glass face, or a pale circle in its hue.
|
|
42
43
|
"&[data-kind=user], &[data-kind=agent]": {
|
|
43
44
|
borderRadius: "round",
|
|
44
|
-
background: "
|
|
45
|
+
background: "token(gradients.raised)",
|
|
45
46
|
color: "fg.primary",
|
|
46
47
|
},
|
|
48
|
+
"--edge": "token(gradients.border.raised)",
|
|
47
49
|
"&[data-kind=agent], &[data-icon]": { color: "fg.secondary" },
|
|
48
50
|
// An icon fills the same share of every size, so marks match whatever avatar they sit beside.
|
|
49
51
|
"&:is([data-kind=agent], [data-icon]) svg": { width: "58%", height: "58%" },
|
|
50
52
|
// An icon stands on its own, with no circle or ring, so it fills most of its box.
|
|
51
53
|
"&[data-icon]": { background: "transparent", "& svg": { width: "80%", height: "80%" } },
|
|
52
54
|
"&:is([data-kind=user], [data-kind=agent]):not([data-color=neutral])": {
|
|
53
|
-
borderColor: "color-mix(in srgb, var(--avatar-hue) 30%, token(colors.bg.
|
|
54
|
-
background: "color-mix(in srgb, var(--avatar-hue) 16%, token(colors.bg.
|
|
55
|
+
borderColor: "color-mix(in srgb, var(--avatar-hue) 30%, token(colors.bg.surface))",
|
|
56
|
+
background: "color-mix(in srgb, var(--avatar-hue) 16%, token(colors.bg.surface))",
|
|
55
57
|
color: "color-mix(in srgb, var(--avatar-hue) 70%, token(colors.fg.primary))",
|
|
56
58
|
},
|
|
57
59
|
// A project: a pale tile edged and lettered in the hue's strong shade.
|
|
58
60
|
"&[data-kind=project]": {
|
|
59
61
|
borderRadius: "20%",
|
|
60
|
-
borderColor: "color-mix(in srgb, var(--avatar-hue) 70%, token(colors.bg.
|
|
61
|
-
background: "color-mix(in srgb, var(--avatar-hue) 14%, token(colors.bg.
|
|
62
|
+
borderColor: "color-mix(in srgb, var(--avatar-hue) 70%, token(colors.bg.surface))",
|
|
63
|
+
background: "color-mix(in srgb, var(--avatar-hue) 14%, token(colors.bg.surface))",
|
|
62
64
|
color: "color-mix(in srgb, var(--avatar-hue) 75%, token(colors.fg.primary))",
|
|
63
65
|
fontWeight: "semibold",
|
|
64
66
|
},
|
|
@@ -81,12 +83,16 @@ const avatar = css({
|
|
|
81
83
|
"&[data-size=large]": {
|
|
82
84
|
width: "avatar.large",
|
|
83
85
|
height: "avatar.large",
|
|
84
|
-
fontSize: "
|
|
86
|
+
fontSize: "body",
|
|
85
87
|
},
|
|
86
88
|
// A list row's owner, and the workspace switcher's mark.
|
|
87
89
|
"&[data-size=row]": { width: "avatar.row", height: "avatar.row" },
|
|
90
|
+
// A record's owner, and the empty slot where one goes.
|
|
91
|
+
"&[data-size=owner]": { width: "avatar.owner", height: "avatar.owner" },
|
|
88
92
|
// A menu item's leading avatar.
|
|
89
93
|
"&[data-size=menu]": { width: "avatar.menu", height: "avatar.menu" },
|
|
94
|
+
// The agent standing on its own, the kit's Agent avatar.
|
|
95
|
+
"&[data-size=agent]": { width: "avatar.agent", height: "avatar.agent" },
|
|
90
96
|
"&[data-size=small]": { width: "avatar.small", height: "avatar.small", fontSize: "avatar.small" },
|
|
91
97
|
// The inline mark's size, so a project's tile lines up with icons and provider logos.
|
|
92
98
|
"&[data-size=mark]": { width: "mark.inline", height: "mark.inline", fontSize: "avatar.mark" },
|
|
@@ -125,7 +131,22 @@ const avatarBadge = css({
|
|
|
125
131
|
export function Avatar({ label, src, size = "medium", kind = "user", icon, badge, color = "neutral", className, ...props }) {
|
|
126
132
|
const initials = labelInitials(label, kind === "organization" ? 1 : 2);
|
|
127
133
|
const glass = !icon && color === "neutral" && (kind === "user" || kind === "agent");
|
|
128
|
-
return (_jsxs(BaseAvatar.Root, { ...props, "aria-label": label, "data-ciridae-ui": "", "data-size": size, "data-kind": kind, "data-color": color, "data-icon": icon ? "" : undefined, "data-edge": glass ? "
|
|
134
|
+
return (_jsxs(BaseAvatar.Root, { ...props, "aria-label": label, "data-ciridae-ui": "", "data-size": size, "data-kind": kind, "data-color": color, "data-icon": icon ? "" : undefined, "data-edge": glass ? "gradient" : undefined, className: cx(avatar, className), children: [src && _jsx(BaseAvatar.Image, { src: src, alt: "", className: avatarImage }), _jsx(BaseAvatar.Fallback, { className: avatarFallback, children: icon ?? (kind === "agent" ? _jsx(SparkleIcon, { weight: "fill" }) : initials) }), badge && _jsx("span", { className: avatarBadge, children: badge })] }));
|
|
135
|
+
}
|
|
136
|
+
// No owner yet: the avatar's circle as a dashed ring, empty.
|
|
137
|
+
const unassignedAvatar = css({
|
|
138
|
+
display: "inline-block",
|
|
139
|
+
flexShrink: "0",
|
|
140
|
+
width: "avatar.owner",
|
|
141
|
+
height: "avatar.owner",
|
|
142
|
+
border: "1px dashed token(colors.border.control)",
|
|
143
|
+
borderRadius: "round",
|
|
144
|
+
"&[data-size=small]": { width: "avatar.small", height: "avatar.small" },
|
|
145
|
+
"&[data-size=row]": { width: "avatar.row", height: "avatar.row" },
|
|
146
|
+
});
|
|
147
|
+
/** The slot where an owner's avatar goes, before anyone owns the record. */
|
|
148
|
+
export function UnassignedAvatar({ size = "owner", className, ...props }) {
|
|
149
|
+
return (_jsx("span", { ...props, className: cx(unassignedAvatar, className), "data-ciridae-ui": "", "data-size": size }));
|
|
129
150
|
}
|
|
130
151
|
/** Up to `count` capital initials from a name's first words. */
|
|
131
152
|
function labelInitials(label, count) {
|
|
@@ -141,13 +162,13 @@ const divider = cva({
|
|
|
141
162
|
variants: {
|
|
142
163
|
inset: {
|
|
143
164
|
none: {},
|
|
144
|
-
// Between a menu's or a popover's groups: inset to its rows'
|
|
145
|
-
// below.
|
|
165
|
+
// Between a menu's or a popover's groups, as the glass menu's divider: inset to its rows'
|
|
166
|
+
// text, a little room above and below.
|
|
146
167
|
menu: {
|
|
147
168
|
width: "auto",
|
|
148
169
|
marginBlock: "layout.tightGap",
|
|
149
170
|
marginInline: "menu.itemInline",
|
|
150
|
-
background: "border.
|
|
171
|
+
background: "border.divider",
|
|
151
172
|
},
|
|
152
173
|
},
|
|
153
174
|
},
|
|
@@ -155,31 +176,60 @@ const divider = cva({
|
|
|
155
176
|
export function Divider({ inset = "none", className, ...props }) {
|
|
156
177
|
return (_jsx(BaseSeparator, { ...props, "data-ciridae-ui": "", className: cx(divider({ inset }), className) }));
|
|
157
178
|
}
|
|
179
|
+
/*
|
|
180
|
+
* Labels are the muted grey, values the text color. `facts` sets each label against its value at
|
|
181
|
+
* the far edge, a hairline under every row but the last; `compact` is the key-value pair, its
|
|
182
|
+
* labels a 120px column of 12px type.
|
|
183
|
+
*/
|
|
158
184
|
const descriptionList = cva({
|
|
159
185
|
base: {
|
|
160
186
|
display: "grid",
|
|
161
187
|
gridTemplateColumns: "max-content minmax(0, 1fr)",
|
|
162
188
|
margin: "none",
|
|
163
|
-
"& dt": { color: "fg.
|
|
189
|
+
"& dt": { color: "fg.label" },
|
|
164
190
|
"& dd": { margin: "none", overflowWrap: "anywhere" },
|
|
165
191
|
"& a": { color: "inherit" },
|
|
166
192
|
},
|
|
167
193
|
variants: {
|
|
168
194
|
density: {
|
|
169
195
|
default: { rowGap: "layout.controlGap", columnGap: "layout.sectionGap" },
|
|
170
|
-
compact: {
|
|
196
|
+
compact: {
|
|
197
|
+
gridTemplateColumns: "120px minmax(0, 1fr)",
|
|
198
|
+
rowGap: "layout.clusterGap",
|
|
199
|
+
columnGap: "layout.contentGap",
|
|
200
|
+
"& dt": { fontSize: "code", fontWeight: "medium" },
|
|
201
|
+
"& dd": { fontSize: "body", fontWeight: "medium" },
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
layout: {
|
|
205
|
+
columns: {},
|
|
206
|
+
facts: {
|
|
207
|
+
gridTemplateColumns: "minmax(0, 1fr) auto",
|
|
208
|
+
alignItems: "center",
|
|
209
|
+
rowGap: "0",
|
|
210
|
+
columnGap: "layout.contentGap",
|
|
211
|
+
"& dt, & dd": {
|
|
212
|
+
paddingBlock: "panel.default",
|
|
213
|
+
borderBottom: "1px solid token(colors.border.divider)",
|
|
214
|
+
lineHeight: "tight",
|
|
215
|
+
},
|
|
216
|
+
"& > :nth-last-child(-n+2)": { borderBottom: "0" },
|
|
217
|
+
"& dt": { fontSize: "code", fontWeight: "medium" },
|
|
218
|
+
"& dd": { fontSize: "body", fontWeight: "medium", textAlign: "end" },
|
|
219
|
+
},
|
|
171
220
|
},
|
|
172
221
|
},
|
|
173
222
|
});
|
|
174
223
|
const placeholderValueWidths = [96, 120, 144];
|
|
175
224
|
/**
|
|
176
225
|
* Label-value pairs in two columns. Rows whose value is `null` or `undefined` are left out, so
|
|
177
|
-
* callers can list every field a record may carry. `compact`
|
|
226
|
+
* callers can list every field a record may carry. `compact` sets them as key-value pairs;
|
|
227
|
+
* `layout="facts"` as fact rows, each value at the far edge over a hairline.
|
|
178
228
|
* `loading` keeps every row's label and draws a placeholder for its value, so the list arrives at
|
|
179
229
|
* the size it loads to; build the rows from the record that may not have loaded yet.
|
|
180
230
|
*/
|
|
181
|
-
export function DescriptionList({ rows, density = "default", loading = false, className, ...props }) {
|
|
182
|
-
return (_jsx("dl", { ...props, "aria-busy": loading || undefined, "data-ciridae-ui": "", className: cx(descriptionList({ density }), className), children: rows.map(([label, value], index) => loading ? (_jsxs(Fragment, { children: [_jsx("dt", { children: label }), _jsx("dd", { children: _jsx(Skeleton, { shape: "text", style: { width: placeholderValueWidths[index % placeholderValueWidths.length] } }) })] }, label)) : value === null || value === undefined ? null : (_jsxs(Fragment, { children: [_jsx("dt", { children: label }), _jsx("dd", { children: value })] }, label))) }));
|
|
231
|
+
export function DescriptionList({ rows, density = "default", layout = "columns", loading = false, className, ...props }) {
|
|
232
|
+
return (_jsx("dl", { ...props, "aria-busy": loading || undefined, "data-ciridae-ui": "", className: cx(descriptionList({ density, layout }), className), children: rows.map(([label, value], index) => loading ? (_jsxs(Fragment, { children: [_jsx("dt", { children: label }), _jsx("dd", { children: _jsx(Skeleton, { shape: "text", style: { width: placeholderValueWidths[index % placeholderValueWidths.length] } }) })] }, label)) : value === null || value === undefined ? null : (_jsxs(Fragment, { children: [_jsx("dt", { children: label }), _jsx("dd", { children: value })] }, label))) }));
|
|
183
233
|
}
|
|
184
234
|
const codeBlock = css({
|
|
185
235
|
margin: "none",
|
|
@@ -219,3 +269,72 @@ export function CodeBlock({ className, copy, copyLabel = "text", ...props }) {
|
|
|
219
269
|
return block;
|
|
220
270
|
return (_jsxs("div", { className: codeBlockFrame, children: [block, _jsx("span", { className: codeBlockCopy, children: _jsx(CopyButton, { value: copy, label: copyLabel }) })] }));
|
|
221
271
|
}
|
|
272
|
+
/*
|
|
273
|
+
* Detail field: one field of a record as a row, the kit's Detail field. A 150px label column of
|
|
274
|
+
* 12px grey beside the 14px value and, under it, where the value came from and who vouches for it,
|
|
275
|
+
* or a description when a badge rides beside the value. `selected` is the open field; `inset`
|
|
276
|
+
* sets it in the selected glass between hairlines; `highlighted` is the warm band for a field that
|
|
277
|
+
* needs a look, such as two sources that disagree.
|
|
278
|
+
*/
|
|
279
|
+
const detailField = css({
|
|
280
|
+
display: "flex",
|
|
281
|
+
alignItems: "flex-start",
|
|
282
|
+
gap: "layout.contentGap",
|
|
283
|
+
paddingBlock: "panel.default",
|
|
284
|
+
paddingInline: "panel.comfortable",
|
|
285
|
+
fontWeight: "medium",
|
|
286
|
+
letterSpacing: "compact",
|
|
287
|
+
lineHeight: "tight",
|
|
288
|
+
"&[data-divider]": { borderBottom: "1px solid token(colors.border.divider)" },
|
|
289
|
+
"&[data-state=default]:hover": { background: "bg.rowHover" },
|
|
290
|
+
"&[data-state=selected]": { background: "token(gradients.selected)" },
|
|
291
|
+
"&:is([data-state=inset], [data-state=highlighted])": {
|
|
292
|
+
borderBlock: "1px solid token(colors.border.divider)",
|
|
293
|
+
},
|
|
294
|
+
"&[data-state=inset]": { background: "token(gradients.selected)" },
|
|
295
|
+
"&[data-state=highlighted]": { background: "bg.warningTint" },
|
|
296
|
+
});
|
|
297
|
+
// The label sits on the value's first line: 14px of text, or the badge's 24.
|
|
298
|
+
const detailFieldLabel = css({
|
|
299
|
+
display: "flex",
|
|
300
|
+
alignItems: "center",
|
|
301
|
+
flexShrink: "0",
|
|
302
|
+
width: "150px",
|
|
303
|
+
minHeight: "token(fontSizes.body)",
|
|
304
|
+
color: "fg.label",
|
|
305
|
+
fontSize: "code",
|
|
306
|
+
"[data-badge] > &": { minHeight: "control.shortcut" },
|
|
307
|
+
});
|
|
308
|
+
const detailFieldValue = css({ display: "grid", gap: "control.iconGap", flex: "1", minWidth: "0" });
|
|
309
|
+
// A badge that does not fit beside the value drops under it.
|
|
310
|
+
const detailFieldValueLine = css({
|
|
311
|
+
display: "flex",
|
|
312
|
+
alignItems: "center",
|
|
313
|
+
flexWrap: "wrap",
|
|
314
|
+
gap: "layout.controlGap",
|
|
315
|
+
minWidth: "0",
|
|
316
|
+
color: "fg.primary",
|
|
317
|
+
fontSize: "body",
|
|
318
|
+
"[data-badge] &": { minHeight: "control.shortcut" },
|
|
319
|
+
});
|
|
320
|
+
const detailFieldNote = css({
|
|
321
|
+
display: "flex",
|
|
322
|
+
alignItems: "center",
|
|
323
|
+
flexWrap: "wrap",
|
|
324
|
+
columnGap: "layout.contentGap",
|
|
325
|
+
rowGap: "layout.tightGap",
|
|
326
|
+
color: "fg.muted",
|
|
327
|
+
fontSize: "code",
|
|
328
|
+
_light: { color: "fg.secondary" },
|
|
329
|
+
});
|
|
330
|
+
const detailFieldNoteItem = css({
|
|
331
|
+
display: "inline-flex",
|
|
332
|
+
alignItems: "center",
|
|
333
|
+
gap: "layout.tightGap",
|
|
334
|
+
"& > svg": { flexShrink: "0", fontSize: "icon.small" },
|
|
335
|
+
});
|
|
336
|
+
const detailFieldAction = css({ flexShrink: "0", alignSelf: "center" });
|
|
337
|
+
export function DetailField({ label, value, source, assurance, badge, description, action, state = "default", divider = true, className, ...props }) {
|
|
338
|
+
const notes = [source, assurance].filter((note) => note !== undefined);
|
|
339
|
+
return (_jsxs("div", { ...props, className: cx(detailField, className), "data-ciridae-ui": "", "data-state": state, "data-divider": divider || undefined, "data-badge": badge !== undefined || undefined, children: [_jsx("span", { className: detailFieldLabel, children: label }), _jsxs("span", { className: detailFieldValue, children: [_jsxs("span", { className: detailFieldValueLine, children: [value, badge] }), notes.length > 0 && (_jsx("span", { className: detailFieldNote, children: notes.map((note, index) => (_jsxs("span", { className: detailFieldNoteItem, children: [note.icon, note.label] }, index))) })), description !== undefined && _jsx("span", { className: detailFieldNote, children: description })] }), action !== undefined && _jsx("span", { className: detailFieldAction, children: action })] }));
|
|
340
|
+
}
|
|
@@ -33,15 +33,19 @@ export type TableColumnMeta = {
|
|
|
33
33
|
locked?: boolean;
|
|
34
34
|
/** Holds the row's own link instead of the first column, when the first holds links of its own. */
|
|
35
35
|
rowLink?: boolean;
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* What the column draws while the list loads, shaped like its cells: `lines` a primary line over
|
|
38
|
+
* a smaller one, `pill` a badge, `person` an avatar and a name, or any node. A line by default.
|
|
39
|
+
*/
|
|
40
|
+
skeleton?: "lines" | "pill" | "person" | ReactNode;
|
|
37
41
|
/** Drops the column on phone-width screens, so the columns that identify a row keep their room. */
|
|
38
42
|
hideOnNarrow?: boolean;
|
|
39
43
|
};
|
|
40
44
|
declare const tableFeatureSet: {
|
|
41
|
-
rowSortingFeature: import("@tanstack/react-table
|
|
42
|
-
columnVisibilityFeature: import("@tanstack/react-table
|
|
43
|
-
columnOrderingFeature: import("@tanstack/react-table
|
|
44
|
-
sortedRowModel: (table: import("@tanstack/react-table
|
|
45
|
+
rowSortingFeature: import("@tanstack/react-table").TableFeature;
|
|
46
|
+
columnVisibilityFeature: import("@tanstack/react-table").TableFeature;
|
|
47
|
+
columnOrderingFeature: import("@tanstack/react-table").TableFeature;
|
|
48
|
+
sortedRowModel: (table: import("@tanstack/react-table").Table<any, any>) => () => import("@tanstack/react-table").RowModel<any, any>;
|
|
45
49
|
columnMeta: TableColumnMeta;
|
|
46
50
|
};
|
|
47
51
|
export type TableFeatureSet = typeof tableFeatureSet;
|
|
@@ -52,10 +56,10 @@ export type TableColumns<Row extends RowData> = ReturnType<ColumnHelper<TableFea
|
|
|
52
56
|
* columns render without one. See `TableColumnMeta` for the per-column options.
|
|
53
57
|
*/
|
|
54
58
|
export declare function createTableColumns<Row extends RowData>(): ColumnHelper<{
|
|
55
|
-
rowSortingFeature: import("@tanstack/react-table
|
|
56
|
-
columnVisibilityFeature: import("@tanstack/react-table
|
|
57
|
-
columnOrderingFeature: import("@tanstack/react-table
|
|
58
|
-
sortedRowModel: (table: import("@tanstack/react-table
|
|
59
|
+
rowSortingFeature: import("@tanstack/react-table").TableFeature;
|
|
60
|
+
columnVisibilityFeature: import("@tanstack/react-table").TableFeature;
|
|
61
|
+
columnOrderingFeature: import("@tanstack/react-table").TableFeature;
|
|
62
|
+
sortedRowModel: (table: import("@tanstack/react-table").Table<any, any>) => () => import("@tanstack/react-table").RowModel<any, any>;
|
|
59
63
|
columnMeta: TableColumnMeta;
|
|
60
64
|
}, Row>;
|
|
61
65
|
/** A column's id and name as column settings list them. */
|
|
@@ -87,6 +91,14 @@ export type DataGridProps<Row extends RowData> = Omit<ComponentProps<"div">, "ch
|
|
|
87
91
|
onSortingChange?: (sorting: SortingState) => void;
|
|
88
92
|
/** The rows arrive in the order `sorting` asks for, such as from a server. */
|
|
89
93
|
manualSorting?: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Shows one page of the sorted rows, `number` counting from 1, for a list paged in the browser
|
|
96
|
+
* under a `Pagination`. Leave it out when `data` is already the page.
|
|
97
|
+
*/
|
|
98
|
+
page?: {
|
|
99
|
+
number: number;
|
|
100
|
+
rowsPerPage: number;
|
|
101
|
+
};
|
|
90
102
|
/** Adds a checkbox column; a function says which rows can be ticked. */
|
|
91
103
|
enableRowSelection?: boolean | ((row: Row) => boolean);
|
|
92
104
|
rowSelection?: RowSelectionState;
|
|
@@ -156,7 +168,7 @@ export type DataGridProps<Row extends RowData> = Omit<ComponentProps<"div">, "ch
|
|
|
156
168
|
* hover-revealed row actions, groups, loading, empty and no-results states. `role="table"`; Enter
|
|
157
169
|
* on a pressable row opens it.
|
|
158
170
|
*/
|
|
159
|
-
export declare function DataGrid<Row extends RowData>({ data, columns, getRowId, variant, density, sorting: sortingProp, defaultSorting, onSortingChange, manualSorting, enableRowSelection, rowSelection: rowSelectionProp, defaultRowSelection, onRowSelectionChange, stickySelectColumn, columnVisibility: columnVisibilityProp, defaultColumnVisibility, onColumnVisibilityChange, columnOrder: columnOrderProp, defaultColumnOrder, onColumnOrderChange, headerMenu, filters, onFiltersChange, getRowHref, renderRowLink, onRowClick, activeRowId, keyboardNavigation, virtualize, rowActions, renderRowDetail, groupBy, renderGroupRow, loading, empty, noResults, filtered, hideHeader, fill, narrowScreenLayout, footer, labels: ownLabels, className, frameClassName, style, ...props }: DataGridProps<Row>): import("
|
|
171
|
+
export declare function DataGrid<Row extends RowData>({ data, columns, getRowId, variant, density, sorting: sortingProp, defaultSorting, onSortingChange, manualSorting, page, enableRowSelection, rowSelection: rowSelectionProp, defaultRowSelection, onRowSelectionChange, stickySelectColumn, columnVisibility: columnVisibilityProp, defaultColumnVisibility, onColumnVisibilityChange, columnOrder: columnOrderProp, defaultColumnOrder, onColumnOrderChange, headerMenu, filters, onFiltersChange, getRowHref, renderRowLink, onRowClick, activeRowId, keyboardNavigation, virtualize, rowActions, renderRowDetail, groupBy, renderGroupRow, loading, empty, noResults, filtered, hideHeader, fill, narrowScreenLayout, footer, labels: ownLabels, className, frameClassName, style, ...props }: DataGridProps<Row>): import("react").JSX.Element;
|
|
160
172
|
export type TableProps<Row extends RowData> = Omit<DataGridProps<Row>, "defaultSorting" | "empty"> & {
|
|
161
173
|
/** The sort the table starts with; `defaultSorting` on `DataGrid`. */
|
|
162
174
|
initialSorting?: SortingState;
|
|
@@ -167,4 +179,4 @@ export type TableProps<Row extends RowData> = Omit<DataGridProps<Row>, "defaultS
|
|
|
167
179
|
* `DataGrid` with the plain look: flush with its section, heads in caps, rows that light on hover
|
|
168
180
|
* when they lead somewhere.
|
|
169
181
|
*/
|
|
170
|
-
export declare function Table<Row extends RowData>({ variant, initialSorting, emptyMessage, ...props }: TableProps<Row>): import("
|
|
182
|
+
export declare function Table<Row extends RowData>({ variant, initialSorting, emptyMessage, ...props }: TableProps<Row>): import("react").JSX.Element;
|