@ciridae/ui 1.0.5 → 1.0.9
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/README.md +3 -2
- package/dist/chat/conversation-source.d.ts +1 -3
- package/dist/chat/message-text.js +6 -6
- package/dist/chat/use-chat-conversation.d.ts +7 -2
- package/dist/chat/use-chat-conversation.js +2 -1
- package/dist/components/activity-feed.d.ts +0 -1
- package/dist/components/activity-feed.js +6 -7
- package/dist/components/agent-work.d.ts +5 -1
- package/dist/components/agent-work.js +27 -13
- package/dist/components/app-frame.d.ts +3 -17
- package/dist/components/app-frame.js +11 -30
- package/dist/components/app-navigation.d.ts +5 -6
- package/dist/components/app-navigation.js +65 -40
- package/dist/components/badge.d.ts +0 -4
- package/dist/components/badge.js +17 -27
- package/dist/components/bulk-action-bar.js +2 -2
- package/dist/components/button.js +41 -50
- package/dist/components/calendar.js +5 -8
- package/dist/components/centered-page.js +4 -4
- package/dist/components/chart.js +3 -4
- package/dist/components/chat-client-source.js +55 -34
- package/dist/components/chat-page.js +1 -1
- package/dist/components/chat-sheet.d.ts +30 -20
- package/dist/components/chat-sheet.js +109 -51
- package/dist/components/chat.d.ts +27 -56
- package/dist/components/chat.js +151 -129
- package/dist/components/checkbox-item.js +4 -4
- package/dist/components/checkbox-list.js +6 -6
- package/dist/components/chip.js +2 -2
- package/dist/components/collapsible.js +3 -3
- package/dist/components/color-theme.d.ts +3 -6
- package/dist/components/color-theme.js +10 -11
- package/dist/components/column-settings.js +3 -3
- package/dist/components/command-menu.d.ts +1 -2
- package/dist/components/command-menu.js +56 -77
- package/dist/components/command-palette.js +5 -2
- package/dist/components/copyable-id.js +5 -5
- package/dist/components/data-display.d.ts +1 -7
- package/dist/components/data-display.js +32 -55
- package/dist/components/data-grid.d.ts +4 -7
- package/dist/components/data-grid.js +106 -90
- package/dist/components/date-range-picker.js +4 -5
- package/dist/components/document-viewer.js +23 -23
- package/dist/components/drawer.d.ts +2 -1
- package/dist/components/drawer.js +45 -20
- package/dist/components/dropzone.js +13 -13
- package/dist/components/editable-field.d.ts +2 -12
- package/dist/components/editable-field.js +13 -26
- package/dist/components/email-input.js +2 -3
- package/dist/components/environment-frame.js +7 -7
- package/dist/components/expandable-text.js +2 -2
- package/dist/components/feedback-screenshot.js +7 -7
- package/dist/components/feedback-sheet.js +8 -8
- package/dist/components/filter-bar.js +41 -27
- package/dist/components/form-controls.d.ts +3 -6
- package/dist/components/form-controls.js +15 -22
- package/dist/components/form-layout.d.ts +6 -6
- package/dist/components/form-layout.js +10 -16
- package/dist/components/glass-menu.d.ts +2 -0
- package/dist/components/glass-menu.js +14 -18
- package/dist/components/gradient-edge.d.ts +0 -1
- package/dist/components/gradient-edge.js +8 -9
- package/dist/components/icon.js +1 -1
- package/dist/components/input.js +18 -17
- package/dist/components/keycap.d.ts +2 -6
- package/dist/components/keycap.js +4 -12
- package/dist/components/layout.js +11 -10
- package/dist/components/lightbox.js +8 -8
- package/dist/components/link.js +1 -1
- package/dist/components/locale.d.ts +23 -7
- package/dist/components/locale.js +19 -7
- package/dist/components/log-entry.d.ts +2 -14
- package/dist/components/log-entry.js +11 -22
- package/dist/components/log-list.js +1 -1
- package/dist/components/mention-input.js +13 -14
- package/dist/components/menu.d.ts +7 -4
- package/dist/components/menu.js +23 -10
- package/dist/components/meter.d.ts +2 -3
- package/dist/components/meter.js +12 -16
- package/dist/components/navigation.d.ts +0 -7
- package/dist/components/navigation.js +3 -12
- package/dist/components/notification-tray.js +7 -7
- package/dist/components/overlays.d.ts +5 -2
- package/dist/components/overlays.js +24 -24
- package/dist/components/panel.js +3 -3
- package/dist/components/progress.js +2 -2
- package/dist/components/radio-card.d.ts +1 -1
- package/dist/components/radio-card.js +9 -9
- package/dist/components/record.d.ts +2 -4
- package/dist/components/record.js +19 -32
- package/dist/components/scroll-area.js +10 -10
- package/dist/components/segmented-bar.js +9 -9
- package/dist/components/select.d.ts +3 -5
- package/dist/components/select.js +26 -44
- package/dist/components/settings.js +1 -1
- package/dist/components/shell-skeleton.js +1 -1
- package/dist/components/shell.d.ts +1 -1
- package/dist/components/shell.js +69 -24
- package/dist/components/side-panel.js +3 -3
- package/dist/components/sidebar.d.ts +0 -5
- package/dist/components/sidebar.js +25 -33
- package/dist/components/single-line-text.js +3 -4
- package/dist/components/site-banner.js +4 -4
- package/dist/components/skeleton.js +19 -22
- package/dist/components/skeletons.d.ts +0 -3
- package/dist/components/skeletons.js +5 -10
- package/dist/components/stages.d.ts +6 -3
- package/dist/components/stages.js +77 -105
- package/dist/components/stat-card.d.ts +2 -5
- package/dist/components/stat-card.js +23 -31
- package/dist/components/status-banner.js +6 -6
- package/dist/components/status.js +3 -3
- package/dist/components/steps.js +2 -2
- package/dist/components/switch.js +1 -1
- package/dist/components/tabs.js +15 -18
- package/dist/components/theme-customizer.d.ts +5 -8
- package/dist/components/theme-customizer.js +9 -41
- package/dist/components/theme-toggle.d.ts +0 -1
- package/dist/components/theme-toggle.js +6 -11
- package/dist/components/toast.d.ts +1 -7
- package/dist/components/toast.js +19 -22
- package/dist/components/user-chip.js +8 -8
- package/dist/components/wizard.js +6 -4
- package/dist/preset.d.ts +1 -2
- package/dist/preset.js +39 -89
- package/dist/styled-system/css/conditions.mjs +1 -1
- package/dist/styled-system/css/css.mjs +1 -1
- package/dist/styled-system/styles.css +805 -1279
- package/dist/styled-system/tokens/index.mjs +74 -1926
- package/dist/styled-system/tokens/tokens.d.ts +18 -33
- package/dist/styled-system/types/conditions.d.ts +0 -74
- package/dist/styled-system/types/prop-type.d.ts +15 -40
- package/dist/styled-system/types/style-props.d.ts +705 -705
- package/dist/theme/color.d.ts +0 -1
- package/dist/theme/color.js +0 -16
- package/dist/theme/derive.d.ts +3 -3
- package/dist/theme/derive.js +9 -32
- package/dist/theme/index.d.ts +1 -2
- package/dist/theme/index.js +3 -5
- package/dist/theme/options.d.ts +2 -4
- package/dist/theme/options.js +0 -1
- package/dist/theme/{palettes.d.ts → palette.d.ts} +12 -23
- package/dist/theme/palette.js +127 -0
- package/dist/theme/tokens.d.ts +8 -13
- package/dist/theme/tokens.js +38 -92
- package/package.json +1 -1
- package/dist/theme/palettes.js +0 -254
|
@@ -25,7 +25,7 @@ const row = css({
|
|
|
25
25
|
transitionDuration: "fast",
|
|
26
26
|
// The selected tint in dark and the row wash in light, as a menu row hovers; focus rings the row
|
|
27
27
|
// inside its own edge.
|
|
28
|
-
_hover: { background: "token(gradients.selected)", _light: { background: "bg.rowHover" } },
|
|
28
|
+
_hover: { background: "[token(gradients.selected)]", _light: { background: "bg.rowHover" } },
|
|
29
29
|
"&:has(:focus-visible)": { focusRing: "inset" },
|
|
30
30
|
"&:has([data-disabled])": { opacity: "disabled", cursor: "not-allowed" },
|
|
31
31
|
});
|
|
@@ -35,10 +35,10 @@ const grip = css({
|
|
|
35
35
|
flexShrink: "0",
|
|
36
36
|
color: "fg.muted",
|
|
37
37
|
cursor: "grab",
|
|
38
|
-
opacity: "0",
|
|
39
|
-
transitionProperty: "opacity",
|
|
38
|
+
opacity: "[0]",
|
|
39
|
+
transitionProperty: "[opacity]",
|
|
40
40
|
transitionDuration: "fast",
|
|
41
|
-
"label:hover > &, label:focus-within > &": { opacity: "1" },
|
|
41
|
+
"label:hover > &, label:focus-within > &": { opacity: "[1]" },
|
|
42
42
|
// A locked row keeps the grip's room, so its label lines up with the rows that move.
|
|
43
43
|
"&[data-locked]": { visibility: "hidden" },
|
|
44
44
|
});
|
|
@@ -17,7 +17,7 @@ const list = css({
|
|
|
17
17
|
gridTemplateColumns: "minmax(0, 1fr)",
|
|
18
18
|
gap: "layout.tightGap",
|
|
19
19
|
paddingBottom: "layout.controlGap",
|
|
20
|
-
paddingInlineEnd: "calc(token(sizes.scroll.bar) + token(spacing.layout.tightGap))",
|
|
20
|
+
paddingInlineEnd: "[calc(token(sizes.scroll.bar) + token(spacing.layout.tightGap))]",
|
|
21
21
|
});
|
|
22
22
|
const itemStack = css({
|
|
23
23
|
display: "grid",
|
|
@@ -31,7 +31,7 @@ const itemRowEnd = css({ paddingInlineEnd: "panel.compact" });
|
|
|
31
31
|
const flushRow = css({ paddingInlineStart: "panel.compact" });
|
|
32
32
|
// Grouped rows sit under their group's label, so their boxes line up with its text.
|
|
33
33
|
const groupedRow = css({
|
|
34
|
-
paddingInlineStart: "calc(token(spacing.panel.compact) + token(sizes.control.checkbox) + token(spacing.layout.controlGap))",
|
|
34
|
+
paddingInlineStart: "[calc(token(spacing.panel.compact) + token(sizes.control.checkbox) + token(spacing.layout.controlGap))]",
|
|
35
35
|
});
|
|
36
36
|
const groupBlock = css({
|
|
37
37
|
display: "grid",
|
|
@@ -55,7 +55,7 @@ const groupLabel = css({ flex: "1", minWidth: "0", fontSize: "caption", fontWeig
|
|
|
55
55
|
const label = css({ flex: "1", minWidth: "0", fontSize: "caption" });
|
|
56
56
|
// A description lines up with its label's text, past the checkbox.
|
|
57
57
|
const description = css({
|
|
58
|
-
paddingInlineStart: "calc(token(sizes.control.checkbox) + token(spacing.layout.controlGap))",
|
|
58
|
+
paddingInlineStart: "[calc(token(sizes.control.checkbox) + token(spacing.layout.controlGap))]",
|
|
59
59
|
minWidth: "0",
|
|
60
60
|
});
|
|
61
61
|
const box = css({ flexShrink: "0" });
|
|
@@ -129,7 +129,7 @@ function SearchableCheckboxes({ items, emptyMessage, selectedKeys, onChange, dis
|
|
|
129
129
|
}
|
|
130
130
|
onChange(next);
|
|
131
131
|
};
|
|
132
|
-
const listed = shown.length === 0 ? (_jsx("div", { className: cx(list, muted), children: searching ? labels.noMatches(search.trim()) : emptyMessage })) : (_jsx(ListedCheckboxes, { items: shown, selectedKeys: selectedKeys, onChange: onChange, disabled: disabled }));
|
|
132
|
+
const listed = shown.length === 0 ? (_jsx("div", { className: cx(list, muted), children: searching ? labels.noMatches(search.trim()) : emptyMessage })) : (_jsx(ListedCheckboxes, { items: shown, selectedKeys: selectedKeys, onChange: onChange, disabled: disabled, labels: labels }));
|
|
133
133
|
if (items.length === 0 || (!offerSearch && !offerBulkActions))
|
|
134
134
|
return listed;
|
|
135
135
|
return (_jsxs("div", { className: withToolbar, "data-ciridae-ui": "", children: [_jsxs(Toolbar, { children: [offerSearch && (_jsx(SearchInput, { "aria-label": labels.search, placeholder: labels.search, value: search, onChange: (event) => setSearch(event.target.value),
|
|
@@ -139,7 +139,7 @@ function SearchableCheckboxes({ items, emptyMessage, selectedKeys, onChange, dis
|
|
|
139
139
|
event.preventDefault();
|
|
140
140
|
} })), offerBulkActions && (_jsxs("div", { className: toolbarActions, children: [_jsxs("div", { className: bulkActions, role: "group", "aria-label": labels.bulkActions, children: [_jsx(Button, { variant: "secondary", size: "small", focusableWhenDisabled: true, disabled: disabled || shownKeys.every((key) => selectedKeys.has(key)), onClick: () => setShown(true), children: searching ? labels.selectMatches : labels.selectAll }), _jsx(Button, { variant: "secondary", size: "small", focusableWhenDisabled: true, disabled: disabled || !shownKeys.some((key) => selectedKeys.has(key)), onClick: () => setShown(false), children: searching ? labels.clearMatches : labels.clear })] }), _jsx("span", { className: selectedCount, "aria-live": "polite", children: labels.selectedCount(items.filter((item) => selectedKeys.has(item.key)).length, items.length) })] }))] }), listed] }));
|
|
141
141
|
}
|
|
142
|
-
function ListedCheckboxes({ items, selectedKeys, onChange, disabled, }) {
|
|
142
|
+
function ListedCheckboxes({ items, selectedKeys, onChange, disabled, labels, }) {
|
|
143
143
|
const toggle = (keys, checked) => {
|
|
144
144
|
const next = new Set(selectedKeys);
|
|
145
145
|
for (const key of keys) {
|
|
@@ -162,6 +162,6 @@ function ListedCheckboxes({ items, selectedKeys, onChange, disabled, }) {
|
|
|
162
162
|
return (_jsx(ScrollArea, { viewportClassName: listViewport, children: _jsxs("div", { className: list, "data-ciridae-ui": "", children: [items.filter((item) => item.group === undefined).map((item) => itemRow(item, "flush")), [...groups].map(([groupKey, { label: group, members }]) => {
|
|
163
163
|
const keys = members.map((item) => item.key);
|
|
164
164
|
const selectedCount = keys.filter((key) => selectedKeys.has(key)).length;
|
|
165
|
-
return (_jsxs("div", { role: "group", "aria-label": group, className: groupBlock, children: [_jsxs("div", { className: groupHeading, children: [_jsx(Checkbox, { disabled: disabled, wrapperClassName: groupLabel, className: box, checked: selectedCount === keys.length, indeterminate: selectedCount > 0 && selectedCount < keys.length, onCheckedChange: (checked) => toggle(keys, checked), children: group }), _jsx("span", { className: muted, children:
|
|
165
|
+
return (_jsxs("div", { role: "group", "aria-label": group, className: groupBlock, children: [_jsxs("div", { className: groupHeading, children: [_jsx(Checkbox, { disabled: disabled, wrapperClassName: groupLabel, className: box, checked: selectedCount === keys.length, indeterminate: selectedCount > 0 && selectedCount < keys.length, onCheckedChange: (checked) => toggle(keys, checked), children: group }), _jsx("span", { className: muted, children: labels.groupSelectedCount(selectedCount, keys.length) })] }), members.map((item) => itemRow(item, "under-group"))] }, groupKey));
|
|
166
166
|
})] }) }));
|
|
167
167
|
}
|
package/dist/components/chip.js
CHANGED
|
@@ -7,7 +7,7 @@ import { icon as iconStyle } from "./icon.js";
|
|
|
7
7
|
import { useCiridaeLocale } from "./locale.js";
|
|
8
8
|
const chip = css({
|
|
9
9
|
display: "inline-flex",
|
|
10
|
-
maxWidth: "
|
|
10
|
+
maxWidth: "full",
|
|
11
11
|
overflowWrap: "anywhere",
|
|
12
12
|
alignItems: "center",
|
|
13
13
|
gap: "control.iconGap",
|
|
@@ -47,7 +47,7 @@ const tag = css({
|
|
|
47
47
|
paddingInlineEnd: "layout.controlGap",
|
|
48
48
|
border: "1px solid transparent",
|
|
49
49
|
borderRadius: "round",
|
|
50
|
-
background: "token(gradients.raised)",
|
|
50
|
+
background: "[token(gradients.raised)]",
|
|
51
51
|
color: "fg.label",
|
|
52
52
|
fontFamily: "sans",
|
|
53
53
|
fontSize: "code",
|
|
@@ -10,7 +10,7 @@ const trigger = css({
|
|
|
10
10
|
gap: "control.iconGap",
|
|
11
11
|
padding: "none",
|
|
12
12
|
border: "none",
|
|
13
|
-
background: "none",
|
|
13
|
+
background: "[none]",
|
|
14
14
|
color: "fg.primary",
|
|
15
15
|
font: "inherit",
|
|
16
16
|
textAlign: "start",
|
|
@@ -21,7 +21,7 @@ const trigger = css({
|
|
|
21
21
|
const caret = css({
|
|
22
22
|
flexShrink: "0",
|
|
23
23
|
color: "fg.muted",
|
|
24
|
-
transitionProperty: "transform",
|
|
24
|
+
transitionProperty: "[transform]",
|
|
25
25
|
transitionDuration: "fast",
|
|
26
26
|
"[data-panel-open] > &": { transform: "rotate(180deg)" },
|
|
27
27
|
});
|
|
@@ -32,7 +32,7 @@ const panel = css({
|
|
|
32
32
|
overflow: "hidden",
|
|
33
33
|
// Clips for the height animation, with room for the focus rings of the fields inside.
|
|
34
34
|
ringRoom: true,
|
|
35
|
-
transitionProperty: "height",
|
|
35
|
+
transitionProperty: "[height]",
|
|
36
36
|
transitionDuration: "fast",
|
|
37
37
|
"&[data-starting-style], &[data-ending-style]": { height: "0" },
|
|
38
38
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { Brand, CiridaeTheme, ColorTheme } from "../theme/options.js";
|
|
3
|
-
import type { PaletteName } from "../theme/palettes.js";
|
|
4
3
|
export type { Brand, ColorTheme } from "../theme/options.js";
|
|
5
4
|
/** What the reader chose: a theme, or to follow the operating system's. */
|
|
6
5
|
export type ColorThemePreference = ColorTheme | "system";
|
|
@@ -20,11 +19,9 @@ export type ThemeProviderProps = {
|
|
|
20
19
|
/** What the product calls itself, for `useBrand`. */
|
|
21
20
|
brand?: Brand;
|
|
22
21
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* Faces to show over the ones the stylesheet was built with, switchable at runtime, such as a
|
|
23
|
+
* preview. Leave it out to keep the built faces.
|
|
25
24
|
*/
|
|
26
|
-
palette?: PaletteName;
|
|
27
|
-
/** Faces to show over the built ones, at runtime, as `palette` does for colors. */
|
|
28
25
|
fonts?: CiridaeTheme["fonts"];
|
|
29
26
|
};
|
|
30
27
|
/**
|
|
@@ -33,7 +30,7 @@ export type ThemeProviderProps = {
|
|
|
33
30
|
* `_light` values resolve through, so every component follows without
|
|
34
31
|
* threading a prop.
|
|
35
32
|
*/
|
|
36
|
-
export declare function ThemeProvider({ children, defaultColorTheme, storageKey, brand,
|
|
33
|
+
export declare function ThemeProvider({ children, defaultColorTheme, storageKey, brand, fonts, }: ThemeProviderProps): import("react").JSX.Element;
|
|
37
34
|
/** Throws outside a `ThemeProvider`, where there is no theme to report or change. */
|
|
38
35
|
export declare function useColorTheme(): ColorThemeContextValue;
|
|
39
36
|
/** Throws outside a `ThemeProvider` given a `brand`, where there is no name to show. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { fontStylesheet } from "../theme/tokens.js";
|
|
4
4
|
/** The attribute the `light` Panda condition and `ciridae.css` both select on. */
|
|
5
5
|
const THEME_ATTRIBUTE = "data-ciridae-theme";
|
|
6
6
|
const DEFAULT_STORAGE_KEY = "ciridae-ui-color-theme";
|
|
@@ -33,23 +33,22 @@ function readSystemTheme() {
|
|
|
33
33
|
}
|
|
34
34
|
const ColorThemeContext = createContext(null);
|
|
35
35
|
const BrandContext = createContext(null);
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
function useRuntimeTheme(palette, fonts) {
|
|
36
|
+
const RUNTIME_FONTS_ELEMENT_ID = "ciridae-runtime-fonts";
|
|
37
|
+
function useRuntimeFonts(fonts) {
|
|
39
38
|
const display = fonts?.display;
|
|
40
39
|
const sans = fonts?.sans;
|
|
41
40
|
const mono = fonts?.mono;
|
|
42
41
|
useEffect(() => {
|
|
43
42
|
const document = globalThis.document;
|
|
44
|
-
if (!document || (
|
|
43
|
+
if (!document || (!display && !sans && !mono))
|
|
45
44
|
return;
|
|
46
|
-
const existing = document.getElementById(
|
|
45
|
+
const existing = document.getElementById(RUNTIME_FONTS_ELEMENT_ID);
|
|
47
46
|
const style = existing instanceof HTMLStyleElement ? existing : document.createElement("style");
|
|
48
|
-
style.id =
|
|
49
|
-
style.textContent =
|
|
47
|
+
style.id = RUNTIME_FONTS_ELEMENT_ID;
|
|
48
|
+
style.textContent = fontStylesheet({ display, sans, mono });
|
|
50
49
|
document.head.append(style);
|
|
51
50
|
return () => style.remove();
|
|
52
|
-
}, [
|
|
51
|
+
}, [display, sans, mono]);
|
|
53
52
|
}
|
|
54
53
|
/**
|
|
55
54
|
* Owns the document's color theme. The chosen theme is written to
|
|
@@ -57,8 +56,8 @@ function useRuntimeTheme(palette, fonts) {
|
|
|
57
56
|
* `_light` values resolve through, so every component follows without
|
|
58
57
|
* threading a prop.
|
|
59
58
|
*/
|
|
60
|
-
export function ThemeProvider({ children, defaultColorTheme = "dark", storageKey = DEFAULT_STORAGE_KEY, brand,
|
|
61
|
-
|
|
59
|
+
export function ThemeProvider({ children, defaultColorTheme = "dark", storageKey = DEFAULT_STORAGE_KEY, brand, fonts, }) {
|
|
60
|
+
useRuntimeFonts(fonts);
|
|
62
61
|
const [preference, setPreferenceState] = useState(() => readStoredPreference(storageKey) ?? defaultColorTheme);
|
|
63
62
|
const [systemTheme, setSystemTheme] = useState(readSystemTheme);
|
|
64
63
|
// Only a `system` preference follows the operating system as it changes.
|
|
@@ -16,7 +16,7 @@ import { SegmentedControl, SegmentedOption } from "./form-layout.js";
|
|
|
16
16
|
import { icon } from "./icon.js";
|
|
17
17
|
import { useCiridaeLocale } from "./locale.js";
|
|
18
18
|
import { Popover } from "./overlays.js";
|
|
19
|
-
const panel = css({ display: "grid", width: "260px", maxWidth: "
|
|
19
|
+
const panel = css({ display: "grid", width: "[260px]", maxWidth: "full" });
|
|
20
20
|
const heading = css({
|
|
21
21
|
display: "flex",
|
|
22
22
|
alignItems: "center",
|
|
@@ -39,7 +39,7 @@ const dropSlot = css({
|
|
|
39
39
|
paddingInline: "layout.tightGap",
|
|
40
40
|
"& > span": {
|
|
41
41
|
display: "block",
|
|
42
|
-
height: "
|
|
42
|
+
height: "full",
|
|
43
43
|
border: "1px solid token(colors.border.focus)",
|
|
44
44
|
borderRadius: "keycap",
|
|
45
45
|
},
|
|
@@ -52,7 +52,7 @@ const hint = css({
|
|
|
52
52
|
fontSize: "code",
|
|
53
53
|
letterSpacing: "compact",
|
|
54
54
|
});
|
|
55
|
-
const densityControl = css({ display: "flex!", width: "
|
|
55
|
+
const densityControl = css({ display: "flex!", width: "full", "& > *": { flex: "1" } });
|
|
56
56
|
export function ColumnSettings({ columns, columnVisibility, onColumnVisibilityChange, columnOrder, onColumnOrderChange, onReset, density, onDensityChange, trigger, open, onOpenChange, labels: ownLabels, }) {
|
|
57
57
|
const { labels: localeLabels } = useCiridaeLocale();
|
|
58
58
|
const labels = { ...localeLabels.table, ...ownLabels };
|
|
@@ -6,7 +6,6 @@ export type CommandMenuItem = {
|
|
|
6
6
|
icon?: ReactNode;
|
|
7
7
|
/** Muted text after the label, such as a record's title. */
|
|
8
8
|
detail?: string;
|
|
9
|
-
/** What the row is, at its end, such as "Invoice" or "Job". */
|
|
10
9
|
kind?: string;
|
|
11
10
|
/** The hotkey that runs it while the menu is open, such as "Mod+J", shown at the row's end. */
|
|
12
11
|
shortcut?: HotkeyChord;
|
|
@@ -41,7 +40,7 @@ export type CommandMenuProps = {
|
|
|
41
40
|
placeholder?: string;
|
|
42
41
|
/** Shown when no row matches, above any `unfiltered` row; the locale's "No results" by default. */
|
|
43
42
|
empty?: ReactNode;
|
|
44
|
-
/**
|
|
43
|
+
/** Drawn under the footer's key hints, such as what the search covers. */
|
|
45
44
|
searchScope?: ReactNode;
|
|
46
45
|
};
|
|
47
46
|
export declare function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, searchScope, }: CommandMenuProps): import("react").JSX.Element;
|
|
@@ -2,7 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
/*
|
|
3
3
|
* A keyboard-first command palette: a search field over grouped rows in a dialog near the top of
|
|
4
4
|
* the window. Arrows move, Enter runs the highlighted row, Escape closes. `cmdk` owns the list's
|
|
5
|
-
* keyboard
|
|
5
|
+
* keyboard; the menu matches rows itself, so their order stays the caller's, and holds which row
|
|
6
|
+
* is highlighted, so the field names it to a screen reader from the first result on.
|
|
6
7
|
*/
|
|
7
8
|
import { Dialog as BaseDialog } from "@base-ui/react/dialog";
|
|
8
9
|
import { useRender } from "@base-ui/react/use-render";
|
|
@@ -21,34 +22,34 @@ const backdrop = css({
|
|
|
21
22
|
inset: "none",
|
|
22
23
|
zIndex: "dialog",
|
|
23
24
|
background: "bg.backdrop",
|
|
24
|
-
transitionProperty: "opacity",
|
|
25
|
+
transitionProperty: "[opacity]",
|
|
25
26
|
transitionDuration: "fast",
|
|
26
|
-
"&[data-starting-style], &[data-ending-style]": { opacity: "0" },
|
|
27
|
-
_motionReduce: { transition: "none" },
|
|
27
|
+
"&[data-starting-style], &[data-ending-style]": { opacity: "[0]" },
|
|
28
|
+
_motionReduce: { transition: "[none]" },
|
|
28
29
|
});
|
|
29
30
|
// The palette is a sheet in a glass shell, as a modal is: the shell blurs the page in dark, the
|
|
30
31
|
// sheet blurs it in light.
|
|
31
32
|
const popup = css({
|
|
32
33
|
zIndex: "dialog",
|
|
33
34
|
position: "fixed",
|
|
34
|
-
top: "18dvh",
|
|
35
|
-
left: "50%",
|
|
35
|
+
top: "[18dvh]",
|
|
36
|
+
left: "[50%]",
|
|
36
37
|
display: "flex",
|
|
37
|
-
width: "calc(100vw - token(spacing.layout.pageGap) * 2)",
|
|
38
|
-
maxWidth: "calc(token(sizes.overlay.palette) + token(spacing.menu.inset) * 2 + 2px)",
|
|
38
|
+
width: "[calc(100vw - token(spacing.layout.pageGap) * 2)]",
|
|
39
|
+
maxWidth: "[calc(token(sizes.overlay.palette) + token(spacing.menu.inset) * 2 + 2px)]",
|
|
39
40
|
padding: "menu.inset",
|
|
40
41
|
border: "1px solid token(colors.border.divider)",
|
|
41
42
|
borderRadius: "shell",
|
|
42
43
|
background: "bg.modalShell",
|
|
43
|
-
backdropFilter: "blur(token(blurs.modalShell))",
|
|
44
|
+
backdropFilter: "[blur(token(blurs.modalShell))]",
|
|
44
45
|
color: "fg.primary",
|
|
45
46
|
textStyle: "body",
|
|
46
|
-
outline: "
|
|
47
|
+
outline: "0",
|
|
47
48
|
transform: "translateX(-50%)",
|
|
48
|
-
transitionProperty: "opacity",
|
|
49
|
+
transitionProperty: "[opacity]",
|
|
49
50
|
transitionDuration: "fast",
|
|
50
|
-
"&[data-starting-style], &[data-ending-style]": { opacity: "0" },
|
|
51
|
-
_motionReduce: { transition: "none" },
|
|
51
|
+
"&[data-starting-style], &[data-ending-style]": { opacity: "[0]" },
|
|
52
|
+
_motionReduce: { transition: "[none]" },
|
|
52
53
|
_phone: { top: "layout.pageGap" },
|
|
53
54
|
"& > [cmdk-root]": {
|
|
54
55
|
display: "flex",
|
|
@@ -59,21 +60,11 @@ const popup = css({
|
|
|
59
60
|
border: "1px solid token(colors.border.divider)",
|
|
60
61
|
borderRadius: "inset",
|
|
61
62
|
background: "bg.modalSheet",
|
|
62
|
-
backdropFilter: "blur(token(blurs.modalSheet))",
|
|
63
|
+
backdropFilter: "[blur(token(blurs.modalSheet))]",
|
|
63
64
|
boxShadow: "soft",
|
|
64
65
|
},
|
|
65
66
|
});
|
|
66
|
-
const visuallyHidden = css({
|
|
67
|
-
position: "absolute",
|
|
68
|
-
width: "1px",
|
|
69
|
-
height: "1px",
|
|
70
|
-
padding: "none",
|
|
71
|
-
margin: "-1px",
|
|
72
|
-
overflow: "hidden",
|
|
73
|
-
clip: "rect(0, 0, 0, 0)",
|
|
74
|
-
whiteSpace: "nowrap",
|
|
75
|
-
border: "0",
|
|
76
|
-
});
|
|
67
|
+
const visuallyHidden = css({ srOnly: true });
|
|
77
68
|
const field = css({
|
|
78
69
|
display: "flex",
|
|
79
70
|
alignItems: "center",
|
|
@@ -85,7 +76,7 @@ const field = css({
|
|
|
85
76
|
"& > input": {
|
|
86
77
|
flex: "1",
|
|
87
78
|
minWidth: "0",
|
|
88
|
-
height: "
|
|
79
|
+
height: "full",
|
|
89
80
|
border: "0",
|
|
90
81
|
outline: "0",
|
|
91
82
|
background: "transparent",
|
|
@@ -104,7 +95,7 @@ const divider = css({
|
|
|
104
95
|
background: "border.divider",
|
|
105
96
|
});
|
|
106
97
|
const list = css({
|
|
107
|
-
maxHeight: "min(60dvh, 420px)",
|
|
98
|
+
maxHeight: "[min(60dvh, 420px)]",
|
|
108
99
|
overflowY: "auto",
|
|
109
100
|
overscrollBehavior: "contain",
|
|
110
101
|
padding: "panel.compact",
|
|
@@ -134,18 +125,19 @@ const row = css({
|
|
|
134
125
|
lineHeight: "tight",
|
|
135
126
|
cursor: "pointer",
|
|
136
127
|
"&[data-selected=true]": {
|
|
137
|
-
background: "token(gradients.selected)",
|
|
138
|
-
boxShadow: "inset 0 0 0 1px token(colors.border.divider)",
|
|
128
|
+
background: "[token(gradients.selected)]",
|
|
129
|
+
boxShadow: "[inset 0 0 0 1px token(colors.border.divider)]",
|
|
139
130
|
},
|
|
140
|
-
|
|
141
|
-
"& > [data-
|
|
131
|
+
// A link row's content sits in its anchor and lays out as a plain row's does.
|
|
132
|
+
"& > svg, & > [data-row-link] > svg": { flexShrink: "0", color: "fg.muted" },
|
|
133
|
+
"& > [data-label], & > [data-row-link] > [data-label]": {
|
|
142
134
|
flexShrink: "0",
|
|
143
|
-
maxWidth: "60%",
|
|
135
|
+
maxWidth: "[60%]",
|
|
144
136
|
overflow: "hidden",
|
|
145
137
|
textOverflow: "ellipsis",
|
|
146
138
|
whiteSpace: "nowrap",
|
|
147
139
|
},
|
|
148
|
-
"& > [data-detail]": {
|
|
140
|
+
"& > [data-detail], & > [data-row-link] > [data-detail]": {
|
|
149
141
|
flex: "1",
|
|
150
142
|
minWidth: "0",
|
|
151
143
|
overflow: "hidden",
|
|
@@ -154,48 +146,25 @@ const row = css({
|
|
|
154
146
|
color: "fg.subtle",
|
|
155
147
|
fontSize: "code",
|
|
156
148
|
},
|
|
157
|
-
"& > [data-kind]": {
|
|
149
|
+
"& > [data-kind], & > [data-row-link] > [data-kind]": {
|
|
158
150
|
flexShrink: "0",
|
|
159
151
|
marginInlineStart: "auto",
|
|
160
152
|
color: "fg.subtle",
|
|
161
153
|
fontSize: "code",
|
|
162
154
|
},
|
|
163
155
|
"& > [data-shortcut]": { marginInlineStart: "auto" },
|
|
164
|
-
//
|
|
165
|
-
//
|
|
156
|
+
// The anchor fills the row. Choosing the row clicks it, so it takes no pointer of its own and
|
|
157
|
+
// never navigates twice.
|
|
166
158
|
"& > [data-row-link]": {
|
|
167
159
|
pointerEvents: "none",
|
|
168
160
|
display: "flex",
|
|
169
161
|
alignItems: "center",
|
|
170
|
-
gap: "inherit",
|
|
162
|
+
gap: "[inherit]",
|
|
171
163
|
flex: "1",
|
|
172
164
|
minWidth: "0",
|
|
173
165
|
alignSelf: "stretch",
|
|
174
|
-
color: "inherit",
|
|
166
|
+
color: "[inherit]",
|
|
175
167
|
textDecoration: "none",
|
|
176
|
-
"& > svg": { flexShrink: "0", color: "fg.muted" },
|
|
177
|
-
"& > [data-label]": {
|
|
178
|
-
flexShrink: "0",
|
|
179
|
-
maxWidth: "60%",
|
|
180
|
-
overflow: "hidden",
|
|
181
|
-
textOverflow: "ellipsis",
|
|
182
|
-
whiteSpace: "nowrap",
|
|
183
|
-
},
|
|
184
|
-
"& > [data-detail]": {
|
|
185
|
-
flex: "1",
|
|
186
|
-
minWidth: "0",
|
|
187
|
-
overflow: "hidden",
|
|
188
|
-
textOverflow: "ellipsis",
|
|
189
|
-
whiteSpace: "nowrap",
|
|
190
|
-
color: "fg.subtle",
|
|
191
|
-
fontSize: "code",
|
|
192
|
-
},
|
|
193
|
-
"& > [data-kind]": {
|
|
194
|
-
flexShrink: "0",
|
|
195
|
-
marginInlineStart: "auto",
|
|
196
|
-
color: "fg.subtle",
|
|
197
|
-
fontSize: "code",
|
|
198
|
-
},
|
|
199
168
|
},
|
|
200
169
|
});
|
|
201
170
|
const emptyRow = css({
|
|
@@ -204,7 +173,6 @@ const emptyRow = css({
|
|
|
204
173
|
color: "fg.muted",
|
|
205
174
|
fontSize: "caption",
|
|
206
175
|
});
|
|
207
|
-
// How to drive the palette from the keyboard, and what it searches.
|
|
208
176
|
const footer = css({
|
|
209
177
|
display: "flex",
|
|
210
178
|
alignItems: "center",
|
|
@@ -238,7 +206,6 @@ function CommandMenuShortcuts({ items, run, }) {
|
|
|
238
206
|
: []));
|
|
239
207
|
return null;
|
|
240
208
|
}
|
|
241
|
-
/** The keys the palette's footer names, as its keycaps write them. */
|
|
242
209
|
const escapeKey = formatForDisplay("Escape");
|
|
243
210
|
const moveKeys = [formatForDisplay("ArrowUp"), formatForDisplay("ArrowDown")];
|
|
244
211
|
const openKey = formatForDisplay("Enter");
|
|
@@ -249,7 +216,7 @@ const menuRowHeight = 40;
|
|
|
249
216
|
// The rows lie over a box as tall as all of them, each moved down to its place.
|
|
250
217
|
const virtualLines = css({
|
|
251
218
|
position: "relative",
|
|
252
|
-
"& > *": { position: "absolute", top: "
|
|
219
|
+
"& > *": { position: "absolute", top: "none", insetInline: "none" },
|
|
253
220
|
});
|
|
254
221
|
/** Every word of the query matches the row's label, detail or keywords (`scoreCommandMatch`). */
|
|
255
222
|
function matchesQuery(item, query) {
|
|
@@ -289,15 +256,10 @@ export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups,
|
|
|
289
256
|
const before = focusedBeforeOpen.current;
|
|
290
257
|
return before?.isConnected ? before : true;
|
|
291
258
|
};
|
|
292
|
-
const setOpen = (next) => {
|
|
293
|
-
if (!next)
|
|
294
|
-
onQueryChange("");
|
|
295
|
-
onOpenChange(next);
|
|
296
|
-
};
|
|
297
259
|
const links = useRef(new Map());
|
|
298
260
|
const run = (item) => {
|
|
299
261
|
ranItem.current = true;
|
|
300
|
-
|
|
262
|
+
onOpenChange(false);
|
|
301
263
|
// A link row navigates through its anchor, so a router's link handles it as a click.
|
|
302
264
|
const link = links.current.get(item.id);
|
|
303
265
|
if (link)
|
|
@@ -330,12 +292,24 @@ export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups,
|
|
|
330
292
|
overscan: 8,
|
|
331
293
|
enabled: virtualized,
|
|
332
294
|
});
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
295
|
+
// The row the reader moved to for this query; the first row until they do, and again once they
|
|
296
|
+
// type.
|
|
297
|
+
const [chosen, setChosen] = useState({ id: "", query: "" });
|
|
298
|
+
const chooseRow = (id) => setChosen({ id, query });
|
|
299
|
+
const selectedId = chosen.query === query && shownItems.some((item) => item.id === chosen.id)
|
|
300
|
+
? chosen.id
|
|
336
301
|
: (shownItems[0]?.id ?? "");
|
|
302
|
+
// cmdk names the highlighted row on the field only once an arrow has moved it, so the field
|
|
303
|
+
// takes the row's id from the drawn list instead, again whenever the rows are drawn anew.
|
|
304
|
+
const [highlightedRowElementId, setHighlightedRowElementId] = useState();
|
|
305
|
+
const drawnVirtualRows = virtualizer.getVirtualItems();
|
|
306
|
+
useLayoutEffect(() => {
|
|
307
|
+
const row = listElement?.querySelector(`[data-command-item-id="${CSS.escape(selectedId)}"]`);
|
|
308
|
+
setHighlightedRowElementId(row?.id || undefined);
|
|
309
|
+
}, [listElement, selectedId, query, groups, drawnVirtualRows]);
|
|
337
310
|
const moveSelection = (event) => {
|
|
338
|
-
|
|
311
|
+
// While an input method composes, its keys pick a candidate, not a row.
|
|
312
|
+
if (!virtualized || event.nativeEvent.isComposing)
|
|
339
313
|
return;
|
|
340
314
|
const index = shownItems.findIndex((item) => item.id === selectedId);
|
|
341
315
|
const last = shownItems.length - 1;
|
|
@@ -364,16 +338,21 @@ export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups,
|
|
|
364
338
|
if (!item)
|
|
365
339
|
return;
|
|
366
340
|
event.preventDefault();
|
|
367
|
-
|
|
341
|
+
chooseRow(item.id);
|
|
368
342
|
virtualizer.scrollToIndex(lines.findIndex((line) => line.key === item.id), { align: "auto" });
|
|
369
343
|
};
|
|
370
|
-
const drawItem = (item, measured) => (_jsxs(Command.Item, { ref: measured?.ref, "data-index": measured?.index, style: measured?.style, value: item.id, className: row, onSelect: () => run(item), children: [item.href !== undefined || item.render !== undefined ? (_jsx(CommandMenuLink, { item: item, register: (element) => {
|
|
344
|
+
const drawItem = (item, measured) => (_jsxs(Command.Item, { ref: measured?.ref, "data-index": measured?.index, style: measured?.style, value: item.id, className: row, "data-command-item-id": item.id, onSelect: () => run(item), children: [item.href !== undefined || item.render !== undefined ? (_jsx(CommandMenuLink, { item: item, register: (element) => {
|
|
371
345
|
if (element)
|
|
372
346
|
links.current.set(item.id, element);
|
|
373
347
|
else
|
|
374
348
|
links.current.delete(item.id);
|
|
375
349
|
} })) : (_jsx(CommandMenuRowContent, { item: item })), item.shortcut && _jsx(ShortcutHint, { boxed: true, "data-shortcut": "", hotkey: item.shortcut })] }, item.id));
|
|
376
|
-
return (_jsx(BaseDialog.Root, { open: open, onOpenChange:
|
|
350
|
+
return (_jsx(BaseDialog.Root, { open: open, onOpenChange: onOpenChange,
|
|
351
|
+
// However it closes, by its own keys or by the host's toggle, the next open starts empty.
|
|
352
|
+
onOpenChangeComplete: (isOpen) => {
|
|
353
|
+
if (!isOpen)
|
|
354
|
+
onQueryChange("");
|
|
355
|
+
}, children: _jsx(BaseDialog.Portal, { children: _jsxs(HotkeyLayer, { children: [_jsx(CommandMenuShortcuts, { items: shownGroups.flatMap((group) => group.items), run: run }), _jsx(BaseDialog.Backdrop, { className: backdrop, "data-ciridae-ui": "" }), _jsxs(BaseDialog.Popup, { className: popup, "data-ciridae-ui": "", ref: popupRef, finalFocus: restoreFocus, children: [_jsx(BaseDialog.Title, { className: visuallyHidden, children: title }), _jsxs(Command, { label: title, shouldFilter: false, loop: true, value: selectedId, onValueChange: chooseRow, onKeyDown: moveSelection, children: [_jsxs("div", { className: field, children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), _jsx(Command.Input, { asChild: true, autoFocus: true, placeholder: placeholder, value: query, onValueChange: onQueryChange, children: _jsx("input", { "aria-activedescendant": highlightedRowElementId }) }), _jsx(Keycap, { "aria-hidden": "true", children: escapeKey })] }), _jsx("div", { className: divider }), _jsxs(Command.List, { ref: setListElement, className: list, children: [!matched && (_jsx("div", { className: emptyRow, role: "presentation", children: empty })), virtualized ? (_jsx("div", { className: virtualLines, style: { height: virtualizer.getTotalSize() }, children: drawnVirtualRows.map((virtualItem) => {
|
|
377
356
|
const line = lines[virtualItem.index];
|
|
378
357
|
if (!line)
|
|
379
358
|
return null;
|
|
@@ -15,6 +15,7 @@ import { useHotkey } from "./hotkeys.js";
|
|
|
15
15
|
import { icon } from "./icon.js";
|
|
16
16
|
import { ShortcutHint } from "./keycap.js";
|
|
17
17
|
import { useCiridaeLocale } from "./locale.js";
|
|
18
|
+
import { Tooltip } from "./overlays.js";
|
|
18
19
|
/** Whether the palette is open; `hotkey` (Cmd/Ctrl+K by default) toggles it from anywhere. */
|
|
19
20
|
export function useCommandPalette({ hotkey = "Mod+K" } = {}) {
|
|
20
21
|
const { labels } = useCiridaeLocale();
|
|
@@ -54,7 +55,7 @@ const trigger = css({
|
|
|
54
55
|
display: "flex",
|
|
55
56
|
alignItems: "center",
|
|
56
57
|
gap: "control.iconGap",
|
|
57
|
-
width: "
|
|
58
|
+
width: "full",
|
|
58
59
|
height: "control.sidebarSearch",
|
|
59
60
|
paddingInlineStart: "control.compactInline",
|
|
60
61
|
paddingInlineEnd: "control.block",
|
|
@@ -82,5 +83,7 @@ const trigger = css({
|
|
|
82
83
|
/** A search field's face, as a button that opens the palette; reads "Search" unless given text. */
|
|
83
84
|
export function CommandPaletteTrigger({ hotkey = "Mod+K", compact = false, className, children, ...props }) {
|
|
84
85
|
const { labels } = useCiridaeLocale();
|
|
85
|
-
|
|
86
|
+
const button = (_jsxs("button", { type: "button", "aria-haspopup": "dialog", "aria-label": compact ? labels.common.search : undefined, ...props, className: cx(trigger, className), "data-ciridae-ui": "", "data-compact": compact || undefined, children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), !compact && (_jsxs(_Fragment, { children: [children ?? labels.common.search, _jsx(ShortcutHint, { boxed: true, "data-shortcut": "", hotkey: hotkey })] }))] }));
|
|
87
|
+
// The rail's icon-only search names itself on hover and focus, as the rail's other icons do.
|
|
88
|
+
return compact ? (_jsx(Tooltip, { content: labels.common.search, side: "inline-end", children: button })) : (button);
|
|
86
89
|
}
|
|
@@ -69,7 +69,7 @@ const inlineCopy = css({
|
|
|
69
69
|
padding: "none",
|
|
70
70
|
border: "0",
|
|
71
71
|
background: "transparent",
|
|
72
|
-
color: "inherit",
|
|
72
|
+
color: "[inherit]",
|
|
73
73
|
cursor: "pointer",
|
|
74
74
|
_hover: { color: "fg.primary" },
|
|
75
75
|
_focusVisible: { focusRing: "outer", borderRadius: "control" },
|
|
@@ -108,7 +108,7 @@ const copyableText = css({
|
|
|
108
108
|
"&:hover > button, &:focus-within > button, & > button[data-copied]": {
|
|
109
109
|
width: "auto",
|
|
110
110
|
marginInlineStart: "control.iconGap",
|
|
111
|
-
opacity: "1",
|
|
111
|
+
opacity: "[1]",
|
|
112
112
|
},
|
|
113
113
|
"&:hover > span > span": {
|
|
114
114
|
transform: "translateX(calc(var(--marquee-shift, 0px) * -1))",
|
|
@@ -121,11 +121,11 @@ const marqueeBox = css({
|
|
|
121
121
|
whiteSpace: "nowrap",
|
|
122
122
|
"& > span": {
|
|
123
123
|
display: "inline-block",
|
|
124
|
-
transitionProperty: "transform",
|
|
124
|
+
transitionProperty: "[transform]",
|
|
125
125
|
transitionTimingFunction: "linear",
|
|
126
126
|
transitionDuration: "var(--marquee-duration, 0s)",
|
|
127
127
|
},
|
|
128
|
-
_motionReduce: { "& > span": { transitionDuration: "0s" } },
|
|
128
|
+
_motionReduce: { "& > span": { transitionDuration: "[0s]" } },
|
|
129
129
|
});
|
|
130
130
|
const copyTextButton = css({
|
|
131
131
|
display: "inline-flex",
|
|
@@ -137,7 +137,7 @@ const copyTextButton = css({
|
|
|
137
137
|
cursor: "pointer",
|
|
138
138
|
width: "0",
|
|
139
139
|
overflow: "hidden",
|
|
140
|
-
opacity: "0",
|
|
140
|
+
opacity: "[0]",
|
|
141
141
|
_hover: { color: "fg.primary" },
|
|
142
142
|
_focusVisible: { focusRing: "outer" },
|
|
143
143
|
});
|
|
@@ -23,7 +23,6 @@ export declare function Avatar({ label, src, size, kind, icon, badge, color, cla
|
|
|
23
23
|
badge?: ReactNode;
|
|
24
24
|
color?: AvatarColor;
|
|
25
25
|
}): import("react").JSX.Element;
|
|
26
|
-
/** The slot where an owner's avatar goes, before anyone owns the record. */
|
|
27
26
|
export declare function UnassignedAvatar({ size, className, ...props }: ComponentProps<"span"> & {
|
|
28
27
|
size?: "small" | "owner" | "row";
|
|
29
28
|
}): import("react").JSX.Element;
|
|
@@ -54,7 +53,6 @@ export declare function CodeBlock({ className, copy, copyLabel, ...props }: Comp
|
|
|
54
53
|
copy?: string;
|
|
55
54
|
copyLabel?: string;
|
|
56
55
|
}): import("react").JSX.Element;
|
|
57
|
-
/** Where a field's value came from, or who vouches for it: a 14px icon and a line. */
|
|
58
56
|
export type DetailFieldNote = {
|
|
59
57
|
icon?: ReactNode;
|
|
60
58
|
label: ReactNode;
|
|
@@ -62,17 +60,13 @@ export type DetailFieldNote = {
|
|
|
62
60
|
export type DetailFieldProps = Omit<ComponentProps<"div">, "children"> & {
|
|
63
61
|
label: ReactNode;
|
|
64
62
|
value: ReactNode;
|
|
65
|
-
/** Where the value came from, such as "Net 30 from Aug 22". */
|
|
66
63
|
source?: DetailFieldNote;
|
|
67
|
-
/** Who or what vouches for it, such as "Checked by Dana R.". */
|
|
68
64
|
assurance?: DetailFieldNote;
|
|
69
|
-
/** Beside the value, such as a Contested badge; its line under the value is `description`. */
|
|
70
65
|
badge?: ReactNode;
|
|
71
66
|
description?: ReactNode;
|
|
72
|
-
/** A trailing button, such as Resolve. */
|
|
73
67
|
action?: ReactNode;
|
|
74
68
|
state?: "default" | "selected" | "inset" | "highlighted";
|
|
75
|
-
/** A hairline under the row; the last row of a list leaves it out.
|
|
69
|
+
/** A hairline under the row; the last row of a list leaves it out. */
|
|
76
70
|
divider?: boolean;
|
|
77
71
|
};
|
|
78
72
|
export declare function DetailField({ label, value, source, assurance, badge, description, action, state, divider, className, ...props }: DetailFieldProps): import("react").JSX.Element;
|