@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
|
@@ -4,8 +4,11 @@ export type CheckboxItemProps = Omit<ComponentProps<typeof BaseCheckbox.Root>, "
|
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
/** Shown muted at the row's end, such as where the item comes from. */
|
|
6
6
|
meta?: ReactNode;
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Shows a drag handle on hover, for a row that can be reordered; `locked` keeps the handle's
|
|
9
|
+
* room empty, for a row that stays put among ones that move.
|
|
10
|
+
*/
|
|
11
|
+
grip?: boolean | "locked";
|
|
9
12
|
className?: string;
|
|
10
13
|
};
|
|
11
|
-
export declare function CheckboxItem({ children, meta, grip: showGrip, className, ...props }: CheckboxItemProps): import("
|
|
14
|
+
export declare function CheckboxItem({ children, meta, grip: showGrip, className, ...props }: CheckboxItemProps): import("react").JSX.Element;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
|
|
3
|
-
import {
|
|
3
|
+
import { DotsSixVerticalIcon } from "@phosphor-icons/react";
|
|
4
4
|
import { css, cx } from "#primitives/css";
|
|
5
|
-
import { checkIndicator, checkMark } from "./form-controls.js";
|
|
5
|
+
import { CheckGlyph, checkIndicator, checkMark, checkMarkEdge } from "./form-controls.js";
|
|
6
6
|
import { icon } from "./icon.js";
|
|
7
7
|
/*
|
|
8
8
|
* A checkbox as a whole row: the mark, its label, and what else the row has to say, with the hover
|
|
@@ -23,8 +23,10 @@ const row = css({
|
|
|
23
23
|
cursor: "pointer",
|
|
24
24
|
transitionProperty: "background",
|
|
25
25
|
transitionDuration: "fast",
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
// The selected tint in dark and the row wash in light, as a menu row hovers; focus rings the row
|
|
27
|
+
// inside its own edge.
|
|
28
|
+
_hover: { background: "token(gradients.selected)", _light: { background: "bg.rowHover" } },
|
|
29
|
+
"&:has(:focus-visible)": { focusRing: "inset" },
|
|
28
30
|
"&:has([data-disabled])": { opacity: "disabled", cursor: "not-allowed" },
|
|
29
31
|
});
|
|
30
32
|
// The grip only shows once the row is pointed at, so a list of rows is not a column of grips.
|
|
@@ -37,9 +39,11 @@ const grip = css({
|
|
|
37
39
|
transitionProperty: "opacity",
|
|
38
40
|
transitionDuration: "fast",
|
|
39
41
|
"label:hover > &, label:focus-within > &": { opacity: "1" },
|
|
42
|
+
// A locked row keeps the grip's room, so its label lines up with the rows that move.
|
|
43
|
+
"&[data-locked]": { visibility: "hidden" },
|
|
40
44
|
});
|
|
41
45
|
const labelText = css({ flex: "1", minWidth: "0" });
|
|
42
46
|
const metaText = css({ flexShrink: "0", color: "fg.subtle", fontSize: "code" });
|
|
43
47
|
export function CheckboxItem({ children, meta, grip: showGrip, className, ...props }) {
|
|
44
|
-
return (_jsxs("label", { className: cx(row, className), "data-ciridae-ui": "", children: [showGrip && (_jsx("span", { className: grip, "aria-hidden": "true", children: _jsx(DotsSixVerticalIcon, { className: icon({ size: "small" }) }) })), _jsx(BaseCheckbox.Root, { ...props, className: checkMark({ focus: "row" }), children: _jsx(BaseCheckbox.Indicator, { className: checkIndicator, children:
|
|
48
|
+
return (_jsxs("label", { className: cx(row, className), "data-ciridae-ui": "", children: [showGrip && (_jsx("span", { className: grip, "aria-hidden": "true", "data-locked": showGrip === "locked" || undefined, children: _jsx(DotsSixVerticalIcon, { className: icon({ size: "small" }) }) })), _jsx(BaseCheckbox.Root, { ...props, ...checkMarkEdge, className: checkMark({ focus: "row" }), children: _jsx(BaseCheckbox.Indicator, { className: checkIndicator, children: _jsx(CheckGlyph, { mixed: props.indeterminate }) }) }), _jsx("span", { className: labelText, children: children }), meta !== undefined && _jsx("span", { className: metaText, children: meta })] }));
|
|
45
49
|
}
|
|
@@ -48,4 +48,4 @@ export type CheckboxListProps = {
|
|
|
48
48
|
* group. A long list can take a search, and bulk actions that touch only the items it leaves shown,
|
|
49
49
|
* so nothing is ticked or cleared out of sight.
|
|
50
50
|
*/
|
|
51
|
-
export declare function CheckboxList(props: CheckboxListProps): import("
|
|
51
|
+
export declare function CheckboxList(props: CheckboxListProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { Tone } from "./badge.js";
|
|
2
2
|
import type { ComponentProps, ReactNode } from "react";
|
|
3
|
+
/** A small neutral label naming a category, such as "Prefilled". A status takes a `Badge`. */
|
|
4
|
+
export declare function Tag({ icon, children, className, ...props }: Omit<ComponentProps<"span">, "children"> & {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
icon?: ReactNode;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
3
8
|
export type ChipProps = Omit<ComponentProps<"span">, "children"> & {
|
|
4
9
|
children: ReactNode;
|
|
5
10
|
/** A mark before the label. */
|
|
@@ -14,4 +19,4 @@ export type ChipProps = Omit<ComponentProps<"span">, "children"> & {
|
|
|
14
19
|
/** Compact recipients and inline tags; regular preserves the standalone chip. */
|
|
15
20
|
size?: "regular" | "compact";
|
|
16
21
|
};
|
|
17
|
-
export declare function Chip({ children, icon, tone, onRemove, removeLabel, disabled, invalid, size, className, ...props }: ChipProps): import("
|
|
22
|
+
export declare function Chip({ children, icon, tone, onRemove, removeLabel, disabled, invalid, size, className, ...props }: ChipProps): import("react").JSX.Element;
|
package/dist/components/chip.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { XIcon } from "@phosphor-icons/react";
|
|
3
3
|
import { css, cx } from "#primitives/css";
|
|
4
4
|
import { IconButton } from "./button.js";
|
|
5
|
+
import { faceEdge } from "./gradient-edge.js";
|
|
5
6
|
import { icon as iconStyle } from "./icon.js";
|
|
6
7
|
import { useCiridaeLocale } from "./locale.js";
|
|
7
8
|
const chip = css({
|
|
@@ -36,6 +37,31 @@ const chip = css({
|
|
|
36
37
|
"&[data-tone=warning]": { background: "bg.warningSubtle", color: "accent.yellow" },
|
|
37
38
|
"&[data-tone=danger], &[data-invalid]": { borderColor: "accent.red", color: "accent.red" },
|
|
38
39
|
});
|
|
40
|
+
/* An 18px label on the raised face: 12px text over a 2px inset and the edge's 1px. */
|
|
41
|
+
const tag = css({
|
|
42
|
+
display: "inline-flex",
|
|
43
|
+
alignItems: "center",
|
|
44
|
+
gap: "layout.tightGap",
|
|
45
|
+
paddingBlock: "control.trackInset",
|
|
46
|
+
paddingInlineStart: "control.iconGap",
|
|
47
|
+
paddingInlineEnd: "layout.controlGap",
|
|
48
|
+
border: "1px solid transparent",
|
|
49
|
+
borderRadius: "round",
|
|
50
|
+
background: "token(gradients.raised)",
|
|
51
|
+
color: "fg.label",
|
|
52
|
+
fontFamily: "sans",
|
|
53
|
+
fontSize: "code",
|
|
54
|
+
fontWeight: "medium",
|
|
55
|
+
lineHeight: "tight",
|
|
56
|
+
letterSpacing: "compact",
|
|
57
|
+
whiteSpace: "nowrap",
|
|
58
|
+
"& > svg": { flexShrink: "0", fontSize: "icon.small" },
|
|
59
|
+
});
|
|
60
|
+
/** A small neutral label naming a category, such as "Prefilled". A status takes a `Badge`. */
|
|
61
|
+
export function Tag({ icon, children, className, ...props }) {
|
|
62
|
+
const edge = faceEdge("raised");
|
|
63
|
+
return (_jsxs("span", { ...props, className: cx(tag, edge.className, className), "data-ciridae-ui": "", "data-edge": edge["data-edge"], children: [icon, children] }));
|
|
64
|
+
}
|
|
39
65
|
export function Chip({ children, icon, tone = "neutral", onRemove, removeLabel, disabled = false, invalid = false, size = "regular", className, ...props }) {
|
|
40
66
|
const { labels } = useCiridaeLocale();
|
|
41
67
|
const name = removeLabel ?? (typeof children === "string" ? children : "");
|
|
@@ -5,4 +5,4 @@ export type CollapsibleProps = Omit<ComponentProps<typeof BaseCollapsible.Root>,
|
|
|
5
5
|
label: ReactNode;
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
};
|
|
8
|
-
export declare function Collapsible({ label, children, ...rootProps }: CollapsibleProps): import("
|
|
8
|
+
export declare function Collapsible({ label, children, ...rootProps }: CollapsibleProps): import("react").JSX.Element;
|
|
@@ -33,7 +33,7 @@ export type ThemeProviderProps = {
|
|
|
33
33
|
* `_light` values resolve through, so every component follows without
|
|
34
34
|
* threading a prop.
|
|
35
35
|
*/
|
|
36
|
-
export declare function ThemeProvider({ children, defaultColorTheme, storageKey, brand, palette, fonts, }: ThemeProviderProps): import("
|
|
36
|
+
export declare function ThemeProvider({ children, defaultColorTheme, storageKey, brand, palette, fonts, }: ThemeProviderProps): import("react").JSX.Element;
|
|
37
37
|
/** Throws outside a `ThemeProvider`, where there is no theme to report or change. */
|
|
38
38
|
export declare function useColorTheme(): ColorThemeContextValue;
|
|
39
39
|
/** Throws outside a `ThemeProvider` given a `brand`, where there is no name to show. */
|
|
@@ -102,7 +102,7 @@ export function ColumnSettings({ columns, columnVisibility, onColumnVisibilityCh
|
|
|
102
102
|
};
|
|
103
103
|
const setShown = (id, visible) => onColumnVisibilityChange({ ...columnVisibility, [id]: visible });
|
|
104
104
|
const dropMarker = (_jsx("span", { className: dropSlot, "aria-hidden": "true", children: _jsx("span", {}) }));
|
|
105
|
-
return (_jsx(Popover, { open: open, onOpenChange: onOpenChange, density: "compact", trigger: trigger ?? (_jsx(Button, { variant: "secondary", size: "medium", icon: _jsx(ColumnsIcon, { className: icon({ size: "small" }) }), children: labels.columns })), children: _jsxs("div", { className: panel, children: [_jsxs("div", { className: heading, children: [labels.columns, onReset && (_jsx(Button, { variant: "ghost", onClick: onReset, children: labels.reset }))] }), _jsxs("div", { className: list, onDragEnd: finishDrag, children: [locked.map((column) => (_jsx(CheckboxItem, { checked: true, disabled: true, meta: labels.alwaysShown, children: column.label }, column.id))), shown.map((column, index) => (_jsxs("span", { className: css({ display: "contents" }), children: [dropIndex === index && dragging !== column.id && dropMarker, _jsx("span", { className: draggable, draggable: reorderable, "data-dragging": dragging === column.id || undefined, onDragStart: (event) => {
|
|
105
|
+
return (_jsx(Popover, { open: open, onOpenChange: onOpenChange, density: "compact", trigger: trigger ?? (_jsx(Button, { variant: "secondary", size: "medium", icon: _jsx(ColumnsIcon, { className: icon({ size: "small" }) }), children: labels.columns })), children: _jsxs("div", { className: panel, children: [_jsxs("div", { className: heading, children: [labels.columns, onReset && (_jsx(Button, { variant: "ghost", onClick: onReset, children: labels.reset }))] }), _jsxs("div", { className: list, onDragEnd: finishDrag, children: [locked.map((column) => (_jsx(CheckboxItem, { checked: true, disabled: true, grip: reorderable && "locked", meta: labels.alwaysShown, children: column.label }, column.id))), shown.map((column, index) => (_jsxs("span", { className: css({ display: "contents" }), children: [dropIndex === index && dragging !== column.id && dropMarker, _jsx("span", { className: draggable, draggable: reorderable, "data-dragging": dragging === column.id || undefined, onDragStart: (event) => {
|
|
106
106
|
event.dataTransfer.effectAllowed = "move";
|
|
107
107
|
setDragging(column.id);
|
|
108
108
|
}, onDragOver: (event) => dragOver(event, index), onDrop: (event) => {
|
|
@@ -6,6 +6,8 @@ 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
|
+
kind?: string;
|
|
9
11
|
/** The hotkey that runs it while the menu is open, such as "Mod+J", shown at the row's end. */
|
|
10
12
|
shortcut?: HotkeyChord;
|
|
11
13
|
/** More text the query matches, such as a job's customer. */
|
|
@@ -39,5 +41,7 @@ export type CommandMenuProps = {
|
|
|
39
41
|
placeholder?: string;
|
|
40
42
|
/** Shown when no row matches, above any `unfiltered` row; the locale's "No results" by default. */
|
|
41
43
|
empty?: ReactNode;
|
|
44
|
+
/** What the menu searches, at the end of its footer, such as "Records, people and actions". */
|
|
45
|
+
searchScope?: ReactNode;
|
|
42
46
|
};
|
|
43
|
-
export declare function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, }: CommandMenuProps): import("
|
|
47
|
+
export declare function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, searchScope, }: CommandMenuProps): import("react").JSX.Element;
|
|
@@ -12,9 +12,9 @@ import { Command } from "cmdk";
|
|
|
12
12
|
import { useLayoutEffect, useRef, useState, } from "react";
|
|
13
13
|
import { css } from "#primitives/css";
|
|
14
14
|
import { scoreCommandMatch } from "./command-match.js";
|
|
15
|
-
import { HotkeyLayer, useHotkeys } from "./hotkeys.js";
|
|
15
|
+
import { formatForDisplay, HotkeyLayer, useHotkeys } from "./hotkeys.js";
|
|
16
16
|
import { icon } from "./icon.js";
|
|
17
|
-
import { ShortcutHint } from "./keycap.js";
|
|
17
|
+
import { Keycap, ShortcutHint } from "./keycap.js";
|
|
18
18
|
import { useCiridaeLocale } from "./locale.js";
|
|
19
19
|
const backdrop = css({
|
|
20
20
|
position: "fixed",
|
|
@@ -26,22 +26,23 @@ const backdrop = css({
|
|
|
26
26
|
"&[data-starting-style], &[data-ending-style]": { opacity: "0" },
|
|
27
27
|
_motionReduce: { transition: "none" },
|
|
28
28
|
});
|
|
29
|
+
// The palette is a sheet in a glass shell, as a modal is: the shell blurs the page in dark, the
|
|
30
|
+
// sheet blurs it in light.
|
|
29
31
|
const popup = css({
|
|
30
32
|
zIndex: "dialog",
|
|
31
33
|
position: "fixed",
|
|
32
|
-
top: "
|
|
34
|
+
top: "18dvh",
|
|
33
35
|
left: "50%",
|
|
34
36
|
display: "flex",
|
|
35
|
-
flexDirection: "column",
|
|
36
37
|
width: "calc(100vw - token(spacing.layout.pageGap) * 2)",
|
|
37
|
-
maxWidth: "overlay.
|
|
38
|
-
|
|
39
|
-
border: "1px solid token(colors.border.
|
|
40
|
-
borderRadius: "
|
|
41
|
-
background: "bg.
|
|
38
|
+
maxWidth: "calc(token(sizes.overlay.palette) + token(spacing.menu.inset) * 2 + 2px)",
|
|
39
|
+
padding: "menu.inset",
|
|
40
|
+
border: "1px solid token(colors.border.divider)",
|
|
41
|
+
borderRadius: "shell",
|
|
42
|
+
background: "bg.modalShell",
|
|
43
|
+
backdropFilter: "blur(token(blurs.modalShell))",
|
|
42
44
|
color: "fg.primary",
|
|
43
45
|
textStyle: "body",
|
|
44
|
-
boxShadow: "card",
|
|
45
46
|
outline: "none",
|
|
46
47
|
transform: "translateX(-50%)",
|
|
47
48
|
transitionProperty: "opacity",
|
|
@@ -49,6 +50,18 @@ const popup = css({
|
|
|
49
50
|
"&[data-starting-style], &[data-ending-style]": { opacity: "0" },
|
|
50
51
|
_motionReduce: { transition: "none" },
|
|
51
52
|
_phone: { top: "layout.pageGap" },
|
|
53
|
+
"& > [cmdk-root]": {
|
|
54
|
+
display: "flex",
|
|
55
|
+
flexDirection: "column",
|
|
56
|
+
flex: "1",
|
|
57
|
+
minWidth: "0",
|
|
58
|
+
overflow: "hidden",
|
|
59
|
+
border: "1px solid token(colors.border.divider)",
|
|
60
|
+
borderRadius: "inset",
|
|
61
|
+
background: "bg.modalSheet",
|
|
62
|
+
backdropFilter: "blur(token(blurs.modalSheet))",
|
|
63
|
+
boxShadow: "soft",
|
|
64
|
+
},
|
|
52
65
|
});
|
|
53
66
|
const visuallyHidden = css({
|
|
54
67
|
position: "absolute",
|
|
@@ -65,9 +78,9 @@ const field = css({
|
|
|
65
78
|
display: "flex",
|
|
66
79
|
alignItems: "center",
|
|
67
80
|
gap: "layout.controlGap",
|
|
68
|
-
height: "
|
|
69
|
-
|
|
70
|
-
|
|
81
|
+
height: "commandPalette.query",
|
|
82
|
+
flexShrink: "0",
|
|
83
|
+
paddingInline: "control.inline",
|
|
71
84
|
color: "fg.muted",
|
|
72
85
|
"& > input": {
|
|
73
86
|
flex: "1",
|
|
@@ -78,35 +91,52 @@ const field = css({
|
|
|
78
91
|
background: "transparent",
|
|
79
92
|
color: "fg.primary",
|
|
80
93
|
font: "inherit",
|
|
94
|
+
fontWeight: "medium",
|
|
95
|
+
letterSpacing: "compact",
|
|
81
96
|
_placeholder: { color: "fg.muted" },
|
|
82
97
|
},
|
|
83
98
|
});
|
|
99
|
+
// The rules between the query, the results and the footer stop short of the sheet's edges.
|
|
100
|
+
const divider = css({
|
|
101
|
+
flexShrink: "0",
|
|
102
|
+
height: "border.hairline",
|
|
103
|
+
marginInline: "panel.compact",
|
|
104
|
+
background: "border.divider",
|
|
105
|
+
});
|
|
84
106
|
const list = css({
|
|
85
107
|
maxHeight: "min(60dvh, 420px)",
|
|
86
108
|
overflowY: "auto",
|
|
87
109
|
overscrollBehavior: "contain",
|
|
88
|
-
|
|
110
|
+
padding: "panel.compact",
|
|
111
|
+
"& [cmdk-group-items]": { display: "grid", gap: "control.trackInset" },
|
|
89
112
|
"& [cmdk-group-heading]": {
|
|
90
113
|
paddingInline: "control.compactInline",
|
|
91
114
|
paddingTop: "control.block",
|
|
92
|
-
paddingBottom: "
|
|
93
|
-
color: "fg.
|
|
115
|
+
paddingBottom: "control.compactBlock",
|
|
116
|
+
color: "fg.subtle",
|
|
94
117
|
fontSize: "code",
|
|
95
118
|
fontWeight: "medium",
|
|
119
|
+
letterSpacing: "compact",
|
|
120
|
+
lineHeight: "tight",
|
|
96
121
|
},
|
|
97
|
-
|
|
98
|
-
"& [cmdk-group]:last-child": { paddingBottom: "layout.tightGap" },
|
|
122
|
+
"& [cmdk-group] + [cmdk-group]": { marginTop: "control.trackInset" },
|
|
99
123
|
});
|
|
100
124
|
const row = css({
|
|
101
125
|
display: "flex",
|
|
102
126
|
alignItems: "center",
|
|
103
|
-
gap: "layout.
|
|
104
|
-
minHeight: "
|
|
127
|
+
gap: "layout.contentGap",
|
|
128
|
+
minHeight: "commandPalette.row",
|
|
105
129
|
paddingInline: "control.compactInline",
|
|
106
|
-
|
|
107
|
-
|
|
130
|
+
borderRadius: "control",
|
|
131
|
+
fontSize: "body",
|
|
132
|
+
fontWeight: "medium",
|
|
133
|
+
letterSpacing: "compact",
|
|
134
|
+
lineHeight: "tight",
|
|
108
135
|
cursor: "pointer",
|
|
109
|
-
"&[data-selected=true]": {
|
|
136
|
+
"&[data-selected=true]": {
|
|
137
|
+
background: "token(gradients.selected)",
|
|
138
|
+
boxShadow: "inset 0 0 0 1px token(colors.border.divider)",
|
|
139
|
+
},
|
|
110
140
|
"& > svg": { flexShrink: "0", color: "fg.muted" },
|
|
111
141
|
"& > [data-label]": {
|
|
112
142
|
flexShrink: "0",
|
|
@@ -121,7 +151,14 @@ const row = css({
|
|
|
121
151
|
overflow: "hidden",
|
|
122
152
|
textOverflow: "ellipsis",
|
|
123
153
|
whiteSpace: "nowrap",
|
|
124
|
-
color: "fg.
|
|
154
|
+
color: "fg.subtle",
|
|
155
|
+
fontSize: "code",
|
|
156
|
+
},
|
|
157
|
+
"& > [data-kind]": {
|
|
158
|
+
flexShrink: "0",
|
|
159
|
+
marginInlineStart: "auto",
|
|
160
|
+
color: "fg.subtle",
|
|
161
|
+
fontSize: "code",
|
|
125
162
|
},
|
|
126
163
|
"& > [data-shortcut]": { marginInlineStart: "auto" },
|
|
127
164
|
// A link row's anchor fills the row, so its content lays out as a plain row's does. Choosing
|
|
@@ -150,7 +187,14 @@ const row = css({
|
|
|
150
187
|
overflow: "hidden",
|
|
151
188
|
textOverflow: "ellipsis",
|
|
152
189
|
whiteSpace: "nowrap",
|
|
153
|
-
color: "fg.
|
|
190
|
+
color: "fg.subtle",
|
|
191
|
+
fontSize: "code",
|
|
192
|
+
},
|
|
193
|
+
"& > [data-kind]": {
|
|
194
|
+
flexShrink: "0",
|
|
195
|
+
marginInlineStart: "auto",
|
|
196
|
+
color: "fg.subtle",
|
|
197
|
+
fontSize: "code",
|
|
154
198
|
},
|
|
155
199
|
},
|
|
156
200
|
});
|
|
@@ -160,6 +204,24 @@ const emptyRow = css({
|
|
|
160
204
|
color: "fg.muted",
|
|
161
205
|
fontSize: "caption",
|
|
162
206
|
});
|
|
207
|
+
// How to drive the palette from the keyboard, and what it searches.
|
|
208
|
+
const footer = css({
|
|
209
|
+
display: "flex",
|
|
210
|
+
alignItems: "center",
|
|
211
|
+
justifyContent: "space-between",
|
|
212
|
+
gap: "layout.clusterGap",
|
|
213
|
+
minHeight: "commandPalette.footer",
|
|
214
|
+
flexShrink: "0",
|
|
215
|
+
paddingInline: "control.inline",
|
|
216
|
+
color: "fg.subtle",
|
|
217
|
+
fontSize: "code",
|
|
218
|
+
fontWeight: "medium",
|
|
219
|
+
letterSpacing: "compact",
|
|
220
|
+
_phone: { display: "none" },
|
|
221
|
+
});
|
|
222
|
+
const footerHints = css({ display: "flex", alignItems: "center", gap: "layout.clusterGap" });
|
|
223
|
+
const footerHint = css({ display: "flex", alignItems: "center", gap: "control.iconGap" });
|
|
224
|
+
const footerKeys = css({ display: "flex", alignItems: "center", gap: "layout.tightGap" });
|
|
163
225
|
/**
|
|
164
226
|
* The shown rows' hotkeys, in the menu's layer: it is the newest scope, so a row's hotkey wins over
|
|
165
227
|
* the page's own binding for the same keys, such as Cmd+J opening the chat empty.
|
|
@@ -176,10 +238,14 @@ function CommandMenuShortcuts({ items, run, }) {
|
|
|
176
238
|
: []));
|
|
177
239
|
return null;
|
|
178
240
|
}
|
|
241
|
+
/** The keys the palette's footer names, as its keycaps write them. */
|
|
242
|
+
const escapeKey = formatForDisplay("Escape");
|
|
243
|
+
const moveKeys = [formatForDisplay("ArrowUp"), formatForDisplay("ArrowDown")];
|
|
244
|
+
const openKey = formatForDisplay("Enter");
|
|
179
245
|
/** Past this many rows the menu draws only those near the view. */
|
|
180
246
|
const virtualizeRowsPast = 50;
|
|
181
|
-
/** A row's height before it is measured: the
|
|
182
|
-
const menuRowHeight =
|
|
247
|
+
/** A row's height before it is measured: the palette's row height, `sizes.commandPalette.row`. */
|
|
248
|
+
const menuRowHeight = 40;
|
|
183
249
|
// The rows lie over a box as tall as all of them, each moved down to its place.
|
|
184
250
|
const virtualLines = css({
|
|
185
251
|
position: "relative",
|
|
@@ -189,7 +255,7 @@ const virtualLines = css({
|
|
|
189
255
|
function matchesQuery(item, query) {
|
|
190
256
|
return item.unfiltered === true || scoreCommandMatch(item, query) > 0;
|
|
191
257
|
}
|
|
192
|
-
export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, }) {
|
|
258
|
+
export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, searchScope, }) {
|
|
193
259
|
const { labels } = useCiridaeLocale();
|
|
194
260
|
const title = ownTitle ?? labels.commandMenu.title;
|
|
195
261
|
const placeholder = ownPlaceholder ?? labels.common.search;
|
|
@@ -306,8 +372,8 @@ export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups,
|
|
|
306
372
|
links.current.set(item.id, element);
|
|
307
373
|
else
|
|
308
374
|
links.current.delete(item.id);
|
|
309
|
-
} })) : (_jsx(CommandMenuRowContent, { item: item })), item.shortcut && _jsx(ShortcutHint, { "data-shortcut": "", hotkey: item.shortcut })] }, item.id));
|
|
310
|
-
return (_jsx(BaseDialog.Root, { open: open, onOpenChange: setOpen, 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, ...(virtualized ? { value: selectedId, onValueChange: setChosenId } : {}), onKeyDown: moveSelection, children: [_jsxs("div", { className: field, children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), _jsx(Command.Input, { autoFocus: true, placeholder: placeholder, value: query, onValueChange: onQueryChange })] }), _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: virtualizer.getVirtualItems().map((virtualItem) => {
|
|
375
|
+
} })) : (_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: setOpen, 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, ...(virtualized ? { value: selectedId, onValueChange: setChosenId } : {}), onKeyDown: moveSelection, children: [_jsxs("div", { className: field, children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), _jsx(Command.Input, { autoFocus: true, placeholder: placeholder, value: query, onValueChange: onQueryChange }), _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: virtualizer.getVirtualItems().map((virtualItem) => {
|
|
311
377
|
const line = lines[virtualItem.index];
|
|
312
378
|
if (!line)
|
|
313
379
|
return null;
|
|
@@ -317,10 +383,10 @@ export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups,
|
|
|
317
383
|
style: { transform: `translateY(${virtualItem.start}px)` },
|
|
318
384
|
};
|
|
319
385
|
return line.kind === "heading" ? (_jsx("div", { ref: measured.ref, "data-index": measured.index, style: measured.style, "cmdk-group-heading": "", role: "presentation", children: line.heading }, line.key)) : (drawItem(line.item, measured));
|
|
320
|
-
}) })) : (shownGroups.map((group, groupIndex) => (_jsx(Command.Group, { heading: group.heading, children: group.items.map((item) => drawItem(item)) }, group.id ?? group.heading ?? groupIndex))))] })] })] })] }) }) }));
|
|
386
|
+
}) })) : (shownGroups.map((group, groupIndex) => (_jsx(Command.Group, { heading: group.heading, children: group.items.map((item) => drawItem(item)) }, group.id ?? group.heading ?? groupIndex))))] }), _jsx("div", { className: divider }), _jsxs("div", { className: footer, children: [_jsxs("div", { className: footerHints, children: [_jsxs("span", { className: footerHint, children: [_jsx("span", { className: footerKeys, children: moveKeys.map((key) => (_jsx(Keycap, { "aria-hidden": "true", children: key }, key))) }), labels.commandMenu.move] }), _jsxs("span", { className: footerHint, children: [_jsx(Keycap, { "aria-hidden": "true", children: openKey }), labels.commandMenu.open] }), _jsxs("span", { className: footerHint, children: [_jsx(Keycap, { "aria-hidden": "true", children: escapeKey }), labels.common.close] })] }), searchScope] })] })] })] }) }) }));
|
|
321
387
|
}
|
|
322
388
|
function CommandMenuRowContent({ item }) {
|
|
323
|
-
return (_jsxs(_Fragment, { children: [item.icon, _jsx("span", { "data-label": "", children: item.label }), item.detail && _jsx("span", { "data-detail": "", children: item.detail })] }));
|
|
389
|
+
return (_jsxs(_Fragment, { children: [item.icon, _jsx("span", { "data-label": "", children: item.label }), item.detail && _jsx("span", { "data-detail": "", children: item.detail }), item.kind && _jsx("span", { "data-kind": "", children: item.kind })] }));
|
|
324
390
|
}
|
|
325
391
|
/** A link row's anchor; the row's own selection clicks it, so it never takes focus itself. */
|
|
326
392
|
function CommandMenuLink({ item, register, }) {
|
|
@@ -18,19 +18,23 @@ export type CommandPaletteProps = {
|
|
|
18
18
|
title?: string;
|
|
19
19
|
placeholder?: string;
|
|
20
20
|
empty?: ReactNode;
|
|
21
|
+
/** What the palette searches, at the end of its footer, such as "Records, people and actions". */
|
|
22
|
+
searchScope?: ReactNode;
|
|
21
23
|
};
|
|
22
24
|
/** Whether the palette is open; `hotkey` (Cmd/Ctrl+K by default) toggles it from anywhere. */
|
|
23
25
|
export declare function useCommandPalette({ hotkey }?: {
|
|
24
26
|
hotkey?: HotkeyChord;
|
|
25
27
|
}): {
|
|
26
28
|
open: boolean;
|
|
27
|
-
setOpen: import("
|
|
29
|
+
setOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
28
30
|
toggle: () => void;
|
|
29
31
|
};
|
|
30
|
-
export declare function CommandPalette({ open, onOpenChange, groups, onQueryChange, footerItem, title, placeholder, empty, }: CommandPaletteProps): import("
|
|
32
|
+
export declare function CommandPalette({ open, onOpenChange, groups, onQueryChange, footerItem, title, placeholder, empty, searchScope, }: CommandPaletteProps): import("react").JSX.Element;
|
|
31
33
|
export type CommandPaletteTriggerProps = ComponentProps<"button"> & {
|
|
32
34
|
/** The hotkey `useCommandPalette` opens it with, shown at the end; Cmd/Ctrl+K by default. */
|
|
33
35
|
hotkey?: HotkeyChord;
|
|
36
|
+
/** The icon alone, round, for the rail; it is named "Search" unless given an `aria-label`. */
|
|
37
|
+
compact?: boolean;
|
|
34
38
|
};
|
|
35
39
|
/** A search field's face, as a button that opens the palette; reads "Search" unless given text. */
|
|
36
|
-
export declare function CommandPaletteTrigger({ hotkey, className, children, ...props }: CommandPaletteTriggerProps): import("
|
|
40
|
+
export declare function CommandPaletteTrigger({ hotkey, compact, className, children, ...props }: CommandPaletteTriggerProps): import("react").JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/*
|
|
3
3
|
* The app's Cmd+K palette on `CommandMenu`: groups of pages, records, people and actions the app
|
|
4
4
|
* supplies, matched loosely on label, detail and keywords and ranked closest first within each
|
|
@@ -25,7 +25,7 @@ export function useCommandPalette({ hotkey = "Mod+K" } = {}) {
|
|
|
25
25
|
const toggle = useCallback(() => setOpen((current) => !current), []);
|
|
26
26
|
return { open, setOpen, toggle };
|
|
27
27
|
}
|
|
28
|
-
export function CommandPalette({ open, onOpenChange, groups, onQueryChange, footerItem, title, placeholder, empty, }) {
|
|
28
|
+
export function CommandPalette({ open, onOpenChange, groups, onQueryChange, footerItem, title, placeholder, empty, searchScope, }) {
|
|
29
29
|
const [query, setQuery] = useState("");
|
|
30
30
|
const changeQuery = (next) => {
|
|
31
31
|
setQuery(next);
|
|
@@ -47,31 +47,40 @@ export function CommandPalette({ open, onOpenChange, groups, onQueryChange, foot
|
|
|
47
47
|
const footer = typed && footerItem ? footerItem(typed) : null;
|
|
48
48
|
return (_jsx(CommandMenu, { open: open, onOpenChange: onOpenChange, query: query, onQueryChange: changeQuery, groups: footer
|
|
49
49
|
? [...rankedGroups, { id: "footer", items: [{ ...footer, unfiltered: true }] }]
|
|
50
|
-
: rankedGroups, title: title, placeholder: placeholder, empty: empty }));
|
|
50
|
+
: rankedGroups, title: title, placeholder: placeholder, empty: empty, searchScope: searchScope }));
|
|
51
51
|
}
|
|
52
|
+
// A form field's well on the canvas, as the sidebar draws it; in the rail, a round icon.
|
|
52
53
|
const trigger = css({
|
|
53
54
|
display: "flex",
|
|
54
55
|
alignItems: "center",
|
|
55
56
|
gap: "control.iconGap",
|
|
56
57
|
width: "100%",
|
|
57
|
-
|
|
58
|
-
height: "control.small",
|
|
58
|
+
height: "control.sidebarSearch",
|
|
59
59
|
paddingInlineStart: "control.compactInline",
|
|
60
|
-
paddingInlineEnd: "control.
|
|
61
|
-
border: "1px solid token(colors.border.
|
|
62
|
-
borderRadius: "
|
|
63
|
-
background: "bg.
|
|
60
|
+
paddingInlineEnd: "control.block",
|
|
61
|
+
border: "1px solid token(colors.border.canvas)",
|
|
62
|
+
borderRadius: "control",
|
|
63
|
+
background: "bg.formField",
|
|
64
64
|
color: "fg.muted",
|
|
65
|
+
_light: { color: "fg.primary" },
|
|
65
66
|
font: "inherit",
|
|
66
67
|
fontWeight: "medium",
|
|
67
68
|
letterSpacing: "compact",
|
|
69
|
+
lineHeight: "tight",
|
|
68
70
|
cursor: "pointer",
|
|
69
71
|
_hover: { color: "fg.primary" },
|
|
70
72
|
_focusVisible: { focusRing: "outer" },
|
|
71
73
|
"& > [data-shortcut]": { marginInlineStart: "auto", _phone: { display: "none" } },
|
|
74
|
+
"&[data-compact]": {
|
|
75
|
+
justifyContent: "center",
|
|
76
|
+
width: "control.compact",
|
|
77
|
+
height: "control.compact",
|
|
78
|
+
padding: "none",
|
|
79
|
+
borderRadius: "round",
|
|
80
|
+
},
|
|
72
81
|
});
|
|
73
82
|
/** A search field's face, as a button that opens the palette; reads "Search" unless given text. */
|
|
74
|
-
export function CommandPaletteTrigger({ hotkey = "Mod+K", className, children, ...props }) {
|
|
83
|
+
export function CommandPaletteTrigger({ hotkey = "Mod+K", compact = false, className, children, ...props }) {
|
|
75
84
|
const { labels } = useCiridaeLocale();
|
|
76
|
-
return (_jsxs("button", { type: "button", "aria-haspopup": "dialog", ...props, className: cx(trigger, className), "data-ciridae-ui": "", children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), children ?? labels.common.search, _jsx(ShortcutHint, { "data-shortcut": "", hotkey: hotkey })] }));
|
|
85
|
+
return (_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 })] }))] }));
|
|
77
86
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { type IconButtonProps } from "./button.js";
|
|
2
2
|
/**
|
|
3
3
|
* Copies `value` (or what it returns, read at the moment of copying) and reports `copied` for a
|
|
4
|
-
* moment afterwards, for a check-mark confirmation.
|
|
4
|
+
* moment afterwards, for a check-mark confirmation. A copy the browser refuses, such as a denied
|
|
5
|
+
* permission or an insecure origin with no clipboard, goes to `onError`, or without one raises the
|
|
6
|
+
* kit's error toast, so a reader never pastes a stale clipboard thinking it holds the value.
|
|
5
7
|
*/
|
|
6
|
-
export declare function useCopy(value: string | (() => string), onCopied?: () => void): {
|
|
8
|
+
export declare function useCopy(value: string | (() => string), onCopied?: () => void, onError?: (error: unknown) => void): {
|
|
7
9
|
copied: boolean;
|
|
8
10
|
copy: () => undefined;
|
|
9
11
|
};
|
|
@@ -16,10 +18,12 @@ export type CopyButtonProps = {
|
|
|
16
18
|
variant?: "raised" | "ghost" | "inline";
|
|
17
19
|
size?: IconButtonProps["size"];
|
|
18
20
|
onCopied?: () => void;
|
|
21
|
+
/** A refused copy; the kit's error toast without it. */
|
|
22
|
+
onError?: (error: unknown) => void;
|
|
19
23
|
className?: string;
|
|
20
24
|
};
|
|
21
25
|
/** A button that copies `value`, its icon turning into a check once copied. */
|
|
22
|
-
export declare function CopyButton({ value, label, variant, size, onCopied, className, }: CopyButtonProps): import("
|
|
26
|
+
export declare function CopyButton({ value, label, variant, size, onCopied, onError, className, }: CopyButtonProps): import("react").JSX.Element;
|
|
23
27
|
/**
|
|
24
28
|
* A long identifier, such as an error's trace ID, shown short and copied whole on click so a
|
|
25
29
|
* reader can hand it to support.
|
|
@@ -28,10 +32,23 @@ export declare function CopyableId({ value, label, className, }: {
|
|
|
28
32
|
value: string;
|
|
29
33
|
label?: string;
|
|
30
34
|
className?: string;
|
|
31
|
-
}): import("
|
|
35
|
+
}): import("react").JSX.Element;
|
|
32
36
|
/** Text shown in full with a copy control; `label` names what gets copied, such as a key's name. */
|
|
33
37
|
export declare function CopyableText({ text, label, className, }: {
|
|
34
38
|
text: string;
|
|
35
39
|
label: string;
|
|
36
40
|
className?: string;
|
|
37
|
-
}): import("
|
|
41
|
+
}): import("react").JSX.Element;
|
|
42
|
+
/**
|
|
43
|
+
* A value to paste elsewhere, such as a command or a connection code, as a labelled read-only
|
|
44
|
+
* field with a copy button: it selects on focus and reads like the field it is pasted into. The
|
|
45
|
+
* row stays while there is no value yet, showing `placeholder`. The value is masked from session
|
|
46
|
+
* recorders, since such values are often credentials.
|
|
47
|
+
*/
|
|
48
|
+
export declare function CopyField({ label, value, placeholder, className, }: {
|
|
49
|
+
label: string;
|
|
50
|
+
value: string | undefined;
|
|
51
|
+
/** What an absent value means, such as that it is not generated yet. */
|
|
52
|
+
placeholder?: string;
|
|
53
|
+
className?: string;
|
|
54
|
+
}): import("react").JSX.Element;
|