@ciridae/ui 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/auth.d.ts +10 -0
- package/dist/app/auth.js +60 -0
- package/dist/app/error-boundary.d.ts +18 -0
- package/dist/app/error-boundary.js +45 -0
- package/dist/app/feedback.d.ts +12 -0
- package/dist/app/feedback.js +128 -0
- package/dist/app/index.d.ts +8 -0
- package/dist/app/index.js +8 -0
- package/dist/app/request-errors.d.ts +63 -0
- package/dist/app/request-errors.js +172 -0
- package/dist/app/sentry.d.ts +18 -0
- package/dist/app/sentry.js +52 -0
- package/dist/app/telemetry.d.ts +7 -0
- package/dist/app/telemetry.js +28 -0
- package/dist/app/trail.d.ts +9 -0
- package/dist/app/trail.js +18 -0
- package/dist/chat/chat-query-keys.d.ts +3 -3
- package/dist/chat/contract.d.ts +15 -15
- package/dist/chat/conversation-items-query-options.d.ts +114 -114
- package/dist/chat/conversation-source.d.ts +89 -0
- package/dist/chat/conversation-source.js +1 -0
- package/dist/chat/describe-tool-call.d.ts +3 -3
- package/dist/chat/describe-tool-call.js +3 -3
- package/dist/chat/message-text.d.ts +1 -1
- package/dist/chat/message-text.js +116 -48
- package/dist/chat/use-conversation-list.d.ts +6 -6
- package/dist/ciridae.css +16 -4
- package/dist/components/activity-feed.d.ts +3 -2
- package/dist/components/activity-feed.js +1 -0
- package/dist/components/agent-work.d.ts +3 -3
- package/dist/components/app-frame.d.ts +91 -0
- package/dist/components/app-frame.js +134 -0
- package/dist/components/app-navigation.d.ts +30 -3
- package/dist/components/app-navigation.js +105 -14
- package/dist/components/badge.d.ts +30 -5
- package/dist/components/badge.js +134 -15
- package/dist/components/brand-icons.d.ts +3 -3
- package/dist/components/bulk-action-bar.d.ts +1 -1
- package/dist/components/bulk-action-bar.js +3 -3
- package/dist/components/button.d.ts +12 -5
- package/dist/components/button.js +77 -44
- package/dist/components/calendar.d.ts +1 -1
- package/dist/components/calendar.js +44 -17
- package/dist/components/centered-page.d.ts +1 -1
- package/dist/components/centered-page.js +2 -2
- package/dist/components/chart.d.ts +22 -2
- package/dist/components/chart.js +251 -51
- package/dist/components/chat-client-source.d.ts +16 -0
- package/dist/components/chat-client-source.js +297 -0
- package/dist/components/chat-page.d.ts +9 -8
- package/dist/components/chat-page.js +7 -11
- package/dist/components/chat-sheet-controller.d.ts +11 -14
- package/dist/components/chat-sheet-controller.js +3 -3
- package/dist/components/chat-sheet.d.ts +18 -11
- package/dist/components/chat-sheet.js +188 -289
- package/dist/components/chat.d.ts +109 -19
- package/dist/components/chat.js +520 -124
- package/dist/components/checkbox-item.d.ts +6 -3
- package/dist/components/checkbox-item.js +9 -5
- package/dist/components/checkbox-list.d.ts +1 -1
- package/dist/components/chip.d.ts +6 -1
- package/dist/components/chip.js +27 -1
- package/dist/components/collapsible.d.ts +1 -1
- package/dist/components/color-theme.d.ts +1 -1
- package/dist/components/column-settings.d.ts +1 -1
- package/dist/components/column-settings.js +1 -1
- package/dist/components/command-menu.d.ts +5 -1
- package/dist/components/command-menu.js +98 -32
- package/dist/components/command-palette.d.ts +7 -3
- package/dist/components/command-palette.js +20 -11
- package/dist/components/copyable-id.d.ts +22 -5
- package/dist/components/copyable-id.js +46 -6
- package/dist/components/data-display.d.ts +39 -8
- package/dist/components/data-display.js +138 -19
- package/dist/components/data-grid.d.ts +23 -11
- package/dist/components/data-grid.js +61 -26
- package/dist/components/date-range-picker.d.ts +1 -1
- package/dist/components/date-range-picker.js +9 -20
- package/dist/components/date-time.d.ts +1 -1
- package/dist/components/dialog-height-context.d.ts +1 -1
- package/dist/components/document-viewer.d.ts +2 -2
- package/dist/components/drawer.d.ts +11 -6
- package/dist/components/drawer.js +91 -54
- package/dist/components/dropzone.d.ts +4 -4
- package/dist/components/editable-field.d.ts +12 -3
- package/dist/components/editable-field.js +57 -27
- package/dist/components/email-input.d.ts +1 -1
- package/dist/components/email-input.js +6 -5
- package/dist/components/environment-frame.d.ts +2 -2
- package/dist/components/environment-frame.js +37 -6
- package/dist/components/expandable-text.d.ts +1 -1
- package/dist/components/feedback-screenshot.d.ts +1 -1
- package/dist/components/feedback-sheet.d.ts +18 -3
- package/dist/components/feedback-sheet.js +216 -55
- package/dist/components/field-context.d.ts +1 -1
- package/dist/components/filter-bar.d.ts +3 -3
- package/dist/components/filter-bar.js +43 -29
- package/dist/components/form-controls.d.ts +12 -3
- package/dist/components/form-controls.js +46 -22
- package/dist/components/form-layout.d.ts +14 -10
- package/dist/components/form-layout.js +68 -23
- package/dist/components/glass-menu.d.ts +3 -0
- package/dist/components/glass-menu.js +63 -0
- package/dist/components/gradient-edge.d.ts +9 -0
- package/dist/components/gradient-edge.js +31 -0
- package/dist/components/hotkeys.d.ts +2 -2
- package/dist/components/icon.d.ts +1 -1
- package/dist/components/input.d.ts +7 -5
- package/dist/components/input.js +29 -17
- package/dist/components/keyboard-shortcuts.d.ts +2 -2
- package/dist/components/keycap.d.ts +10 -6
- package/dist/components/keycap.js +57 -19
- package/dist/components/layout.d.ts +13 -13
- package/dist/components/lightbox.d.ts +9 -3
- package/dist/components/lightbox.js +13 -9
- package/dist/components/link.d.ts +1 -1
- package/dist/components/locale.d.ts +42 -2
- package/dist/components/locale.js +43 -3
- package/dist/components/log-entry.d.ts +40 -0
- package/dist/components/log-entry.js +146 -0
- package/dist/components/log-list.d.ts +3 -3
- package/dist/components/mention-input.d.ts +2 -2
- package/dist/components/mention-input.js +4 -3
- package/dist/components/menu.d.ts +7 -3
- package/dist/components/menu.js +34 -37
- package/dist/components/meter.d.ts +10 -2
- package/dist/components/meter.js +64 -6
- package/dist/components/navigation.d.ts +21 -4
- package/dist/components/navigation.js +84 -19
- package/dist/components/notification-tray.d.ts +1 -1
- package/dist/components/notification-tray.js +5 -4
- package/dist/components/overlays.d.ts +6 -4
- package/dist/components/overlays.js +69 -40
- package/dist/components/page-frame.d.ts +4 -4
- package/dist/components/page-frame.js +1 -1
- package/dist/components/panel.d.ts +4 -4
- package/dist/components/panel.js +18 -12
- package/dist/components/profile-header.d.ts +1 -1
- package/dist/components/progress.d.ts +1 -1
- package/dist/components/project-avatar.d.ts +1 -1
- package/dist/components/radio-card.d.ts +2 -2
- package/dist/components/radio-card.js +10 -9
- package/dist/components/record.d.ts +29 -5
- package/dist/components/record.js +147 -18
- package/dist/components/resolved-file-url.d.ts +19 -0
- package/dist/components/resolved-file-url.js +49 -0
- package/dist/components/scroll-area.d.ts +1 -1
- package/dist/components/secret-dialog.d.ts +1 -1
- package/dist/components/segmented-bar.d.ts +4 -2
- package/dist/components/segmented-bar.js +16 -6
- package/dist/components/select.d.ts +9 -6
- package/dist/components/select.js +103 -127
- package/dist/components/settings.d.ts +4 -4
- package/dist/components/shell-skeleton.d.ts +1 -1
- package/dist/components/shell-skeleton.js +1 -1
- package/dist/components/shell.d.ts +21 -21
- package/dist/components/shell.js +43 -43
- package/dist/components/side-panel.d.ts +3 -3
- package/dist/components/sidebar.d.ts +13 -8
- package/dist/components/sidebar.js +55 -27
- package/dist/components/single-line-text.d.ts +2 -0
- package/dist/components/single-line-text.js +16 -0
- package/dist/components/site-banner.d.ts +5 -2
- package/dist/components/site-banner.js +17 -6
- package/dist/components/skeleton.d.ts +8 -7
- package/dist/components/skeleton.js +28 -16
- package/dist/components/skeletons.d.ts +17 -5
- package/dist/components/skeletons.js +71 -8
- package/dist/components/stages.d.ts +83 -11
- package/dist/components/stages.js +512 -156
- package/dist/components/stat-card.d.ts +12 -4
- package/dist/components/stat-card.js +92 -37
- package/dist/components/status-banner.d.ts +1 -1
- package/dist/components/status-banner.js +1 -1
- package/dist/components/status.d.ts +2 -2
- package/dist/components/steps.d.ts +1 -1
- package/dist/components/switch.d.ts +1 -1
- package/dist/components/tabs.d.ts +8 -8
- package/dist/components/tabs.js +26 -13
- package/dist/components/theme-customizer.d.ts +2 -2
- package/dist/components/theme-toggle.d.ts +4 -0
- package/dist/components/theme-toggle.js +67 -0
- package/dist/components/toast.d.ts +10 -3
- package/dist/components/toast.js +78 -29
- package/dist/components/use-new-version-available.d.ts +6 -0
- package/dist/components/use-new-version-available.js +29 -0
- package/dist/components/user-chip.d.ts +3 -3
- package/dist/components/wizard.d.ts +2 -2
- package/dist/feedback/contract.d.ts +136 -136
- package/dist/feedback/feedback-controller.d.ts +6 -6
- package/dist/feedback/generated/zod.gen.d.ts +28 -28
- package/dist/feedback/operator-contract.d.ts +11 -11
- package/dist/feedback/operator-controller.d.ts +32 -13
- package/dist/feedback/operator-controller.js +44 -11
- package/dist/preset.js +289 -33
- package/dist/styled-system/styles.css +3294 -1079
- package/dist/styled-system/tokens/index.mjs +598 -22
- package/dist/styled-system/tokens/tokens.d.ts +11 -11
- package/dist/styled-system/types/prop-type.d.ts +2 -2
- package/dist/styles.css +16 -4
- package/dist/theme/color.d.ts +3 -0
- package/dist/theme/color.js +5 -0
- package/dist/theme/derive.d.ts +9 -2
- package/dist/theme/derive.js +72 -12
- package/dist/theme/palettes.d.ts +49 -6
- package/dist/theme/palettes.js +84 -15
- package/dist/theme/tokens.d.ts +3 -3
- package/dist/theme/tokens.js +107 -32
- package/package.json +40 -3
|
@@ -2,13 +2,16 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
|
|
3
3
|
import { Radio as BaseRadio } from "@base-ui/react/radio";
|
|
4
4
|
import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
|
|
5
|
-
import { CheckIcon
|
|
5
|
+
import { CheckIcon } from "@phosphor-icons/react";
|
|
6
6
|
import { css, cva, cx } from "#primitives/css";
|
|
7
7
|
import { useFieldControl } from "./field-context.js";
|
|
8
8
|
/*
|
|
9
|
-
* The one mark for a checkbox and a radio:
|
|
10
|
-
* fills with the primary face once on.
|
|
11
|
-
*
|
|
9
|
+
* The one mark for a checkbox and a radio: the selected tint in dark, a near-white well in light,
|
|
10
|
+
* that fills with the primary button's face and gradient edge once on. The edge is the `[data-edge]`
|
|
11
|
+
* ring the element carries through `checkMarkEdge`: the selected face's gradient in dark, the
|
|
12
|
+
* control hairline in light. Hover darkens the edge of an empty mark, washes it in light, and fades
|
|
13
|
+
* a filled one in dark. The ring is a variant, because a row that holds the mark draws its own
|
|
14
|
+
* ring instead.
|
|
12
15
|
*/
|
|
13
16
|
export const checkMark = cva({
|
|
14
17
|
base: {
|
|
@@ -18,25 +21,31 @@ export const checkMark = cva({
|
|
|
18
21
|
display: "inline-grid",
|
|
19
22
|
placeItems: "center",
|
|
20
23
|
padding: "none",
|
|
21
|
-
border: "1px solid
|
|
22
|
-
background: "
|
|
24
|
+
border: "1px solid transparent",
|
|
25
|
+
background: "token(gradients.selected)",
|
|
23
26
|
color: "bg.canvas",
|
|
24
|
-
_light: { color: "fg.onAccent" },
|
|
27
|
+
_light: { color: "fg.onAccent", background: "bg.check" },
|
|
25
28
|
cursor: "pointer",
|
|
26
|
-
transitionProperty: "background,
|
|
29
|
+
transitionProperty: "background, opacity",
|
|
27
30
|
transitionDuration: "fast",
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
_before: {
|
|
32
|
+
background: "token(gradients.border.selected)",
|
|
33
|
+
_light: { background: "border.control" },
|
|
31
34
|
},
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
// Pointing anywhere at a row's label marks the box it would tick, while it is empty: a filled
|
|
36
|
+
// mark, or a radio card's once chosen, keeps its face.
|
|
37
|
+
"&:not([data-checked], [data-indeterminate], [data-checked] > *):is(label:hover > *, label:hover *, :hover):not([data-disabled])": {
|
|
38
|
+
_before: { background: "fg.muted", _light: { background: "fg.secondary" } },
|
|
39
|
+
_light: {
|
|
40
|
+
background: "linear-gradient(token(colors.bg.controlHover), token(colors.bg.controlHover)), token(colors.bg.check)",
|
|
41
|
+
},
|
|
35
42
|
},
|
|
36
|
-
"
|
|
37
|
-
background: "
|
|
38
|
-
|
|
43
|
+
"&[data-checked], &[data-indeterminate]": {
|
|
44
|
+
background: "token(gradients.primary)",
|
|
45
|
+
_light: { background: "token(gradients.primary)" },
|
|
46
|
+
_before: { background: "token(gradients.border.primary)" },
|
|
39
47
|
},
|
|
48
|
+
"&:is([data-checked], [data-indeterminate]):is(label:hover > *, label:hover *, :hover):not([data-disabled])": { opacity: "checkedHover", _light: { opacity: "1" } },
|
|
40
49
|
"&[data-disabled]": { opacity: "disabled", cursor: "not-allowed" },
|
|
41
50
|
},
|
|
42
51
|
variants: {
|
|
@@ -58,13 +67,25 @@ const label = css({
|
|
|
58
67
|
fontWeight: "normal",
|
|
59
68
|
cursor: "pointer",
|
|
60
69
|
});
|
|
70
|
+
/** What a check mark's element carries, so its filled face can draw the gradient edge. */
|
|
71
|
+
export const checkMarkEdge = { "data-ciridae-ui": "", "data-edge": "gradient" };
|
|
61
72
|
export const checkIndicator = css({
|
|
62
73
|
display: "inline-flex",
|
|
63
74
|
lineHeight: "1",
|
|
64
|
-
fontSize: "icon.
|
|
75
|
+
fontSize: "icon.small",
|
|
76
|
+
});
|
|
77
|
+
// A mixed checkbox's mark: a short dash rather than a minus glyph.
|
|
78
|
+
const mixedDash = css({
|
|
79
|
+
width: "indicator.swatch",
|
|
80
|
+
height: "border.hairline",
|
|
81
|
+
background: "currentColor",
|
|
65
82
|
});
|
|
83
|
+
/** The tick, or the dash of a mixed checkbox. */
|
|
84
|
+
export function CheckGlyph({ mixed }) {
|
|
85
|
+
return mixed ? _jsx("span", { className: mixedDash }) : _jsx(CheckIcon, { weight: "bold" });
|
|
86
|
+
}
|
|
66
87
|
export function Checkbox({ children, className, wrapperClassName, ...props }) {
|
|
67
|
-
return (_jsxs("label", { className: cx(label, wrapperClassName), "data-ciridae-ui": "", children: [_jsx(BaseCheckbox.Root, { ...props, className: cx(checkMark(), className), children: _jsx(BaseCheckbox.Indicator, { className: checkIndicator, children:
|
|
88
|
+
return (_jsxs("label", { className: cx(label, wrapperClassName), "data-ciridae-ui": "", children: [_jsx(BaseCheckbox.Root, { ...props, ...checkMarkEdge, className: cx(checkMark(), className), children: _jsx(BaseCheckbox.Indicator, { className: checkIndicator, children: _jsx(CheckGlyph, { mixed: props.indeterminate }) }) }), children] }));
|
|
68
89
|
}
|
|
69
90
|
const textarea = css({
|
|
70
91
|
width: "100%",
|
|
@@ -74,7 +95,7 @@ const textarea = css({
|
|
|
74
95
|
paddingInline: "control.compactInline",
|
|
75
96
|
border: "1px solid token(colors.border.control)",
|
|
76
97
|
borderRadius: "control",
|
|
77
|
-
background: "bg.
|
|
98
|
+
background: "bg.formField",
|
|
78
99
|
color: "fg.primary",
|
|
79
100
|
fontFamily: "sans",
|
|
80
101
|
fontSize: "body",
|
|
@@ -108,7 +129,10 @@ const menuRadio = css({
|
|
|
108
129
|
fontWeight: "medium",
|
|
109
130
|
letterSpacing: "compact",
|
|
110
131
|
cursor: "pointer",
|
|
111
|
-
_hover: {
|
|
132
|
+
_hover: {
|
|
133
|
+
background: "bg.hover",
|
|
134
|
+
boxShadow: "inset 0 0 0 1px token(colors.border.menuHover)",
|
|
135
|
+
},
|
|
112
136
|
"&:has([data-disabled])": { opacity: "disabled", cursor: "not-allowed" },
|
|
113
137
|
});
|
|
114
138
|
const menuRadioMeta = css({ marginInlineStart: "auto", color: "fg.muted" });
|
|
@@ -119,5 +143,5 @@ export const radioDot = css({
|
|
|
119
143
|
background: "currentColor",
|
|
120
144
|
});
|
|
121
145
|
export function RadioGroup({ name, options, label: groupLabel, defaultValue, value, onValueChange, layout = "inline", className, ...props }) {
|
|
122
|
-
return (_jsx(BaseRadioGroup, { ...props, className: cx(layout === "menu" ? menuRadios : radios, className), "aria-label": props["aria-label"] ?? groupLabel, "data-ciridae-ui": "", defaultValue: defaultValue, name: name, onValueChange: (nextValue) => onValueChange?.(String(nextValue)), value: value, children: options.map((option) => (_jsxs("label", { className: layout === "menu" ? menuRadio : label, children: [_jsx(BaseRadio.Root, { className: checkMark({ shape: "round" }), disabled: option.disabled, value: option.value, children: _jsx(BaseRadio.Indicator, { className: radioDot }) }), option.label, option.meta !== undefined && _jsx("span", { className: menuRadioMeta, children: option.meta })] }, option.value))) }));
|
|
146
|
+
return (_jsx(BaseRadioGroup, { ...props, className: cx(layout === "menu" ? menuRadios : radios, className), "aria-label": props["aria-label"] ?? groupLabel, "data-ciridae-ui": "", defaultValue: defaultValue, name: name, onValueChange: (nextValue) => onValueChange?.(String(nextValue)), value: value, children: options.map((option) => (_jsxs("label", { className: layout === "menu" ? menuRadio : label, children: [_jsx(BaseRadio.Root, { ...checkMarkEdge, className: checkMark({ shape: "round" }), disabled: option.disabled, value: option.value, children: _jsx(BaseRadio.Indicator, { className: radioDot }) }), option.label, option.meta !== undefined && _jsx("span", { className: menuRadioMeta, children: option.meta })] }, option.value))) }));
|
|
123
147
|
}
|
|
@@ -4,29 +4,33 @@ import type { ComponentProps, ReactNode } from "react";
|
|
|
4
4
|
* Stacked form fields. Validation is the form library's, never the browser's, so this always
|
|
5
5
|
* carries `noValidate`.
|
|
6
6
|
*/
|
|
7
|
-
export declare function Form({ className, ...props }: ComponentProps<"form">): import("
|
|
8
|
-
export declare function FormActions({ className, ...props }: ComponentProps<"div">): import("
|
|
7
|
+
export declare function Form({ className, ...props }: ComponentProps<"form">): import("react").JSX.Element;
|
|
8
|
+
export declare function FormActions({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
9
|
+
/** Fields in one row of a `Form`, sharing its width equally. */
|
|
10
|
+
export declare function FieldRow({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
9
11
|
/**
|
|
10
12
|
* A label round a `FieldLabel`, its control and any `FieldError`: the label names the control it
|
|
11
13
|
* holds, and while `invalid` the control is marked and described by the error, so `Input`,
|
|
12
|
-
* `Textarea`, `Select` and `Combobox` inside need no ids of their own.
|
|
14
|
+
* `Textarea`, `Select` and `Combobox` inside need no ids of their own. A `hint` sits under the
|
|
15
|
+
* control and describes it until the error takes its place.
|
|
13
16
|
*/
|
|
14
|
-
export declare function Field({ className, htmlFor, invalid, ...props }: ComponentProps<"label"> & {
|
|
17
|
+
export declare function Field({ className, htmlFor, invalid, hint, children, ...props }: ComponentProps<"label"> & {
|
|
15
18
|
invalid?: boolean;
|
|
16
|
-
|
|
19
|
+
hint?: ReactNode;
|
|
20
|
+
}): import("react").JSX.Element;
|
|
17
21
|
export declare function FieldLabel({ children }: {
|
|
18
22
|
children: ReactNode;
|
|
19
|
-
}): import("
|
|
23
|
+
}): import("react").JSX.Element;
|
|
20
24
|
/** The field's error; its id is the one the field's control is described by. */
|
|
21
25
|
export declare function FieldError({ id, children }: {
|
|
22
26
|
id?: string;
|
|
23
27
|
children: ReactNode;
|
|
24
|
-
}): import("
|
|
25
|
-
export declare function SegmentedControl({ className, ...props }: ComponentProps<"div">): import("
|
|
28
|
+
}): import("react").JSX.Element;
|
|
29
|
+
export declare function SegmentedControl({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
26
30
|
export type SegmentedOptionProps = Omit<ButtonProps, "variant" | "type" | "aria-pressed"> & {
|
|
27
31
|
selected: boolean;
|
|
28
32
|
/** Shown muted after the label, such as how many items the option lists. */
|
|
29
33
|
count?: number;
|
|
30
34
|
};
|
|
31
|
-
/** One option of a `SegmentedControl
|
|
32
|
-
export declare function SegmentedOption({ selected, count, children, ...props }: SegmentedOptionProps): import("
|
|
35
|
+
/** One option of a `SegmentedControl`: the selected one is raised, the others bare. */
|
|
36
|
+
export declare function SegmentedOption({ selected, count, children, ...props }: SegmentedOptionProps): import("react").JSX.Element;
|
|
@@ -3,31 +3,65 @@ import { useContext, useId, useMemo } from "react";
|
|
|
3
3
|
import { css, cx } from "#primitives/css";
|
|
4
4
|
import { Button } from "./button.js";
|
|
5
5
|
import { FieldControlContext } from "./field-context.js";
|
|
6
|
+
import { faceEdge } from "./gradient-edge.js";
|
|
6
7
|
import { useInToolbar } from "./layout.js";
|
|
7
8
|
const field = css({ display: "grid", gap: "control.iconGap", minWidth: "0", fontSize: "caption" });
|
|
8
|
-
|
|
9
|
-
const
|
|
9
|
+
// A single line, its box the type's own 12px, so the gap to the control is the field's 6px alone.
|
|
10
|
+
const labelText = css({
|
|
11
|
+
color: "fg.primary",
|
|
12
|
+
fontSize: "code",
|
|
13
|
+
fontWeight: "medium",
|
|
14
|
+
lineHeight: "tight",
|
|
15
|
+
letterSpacing: "compact",
|
|
16
|
+
});
|
|
17
|
+
// Help and error lines under the control, which can wrap.
|
|
18
|
+
const noteText = css({
|
|
19
|
+
margin: "none",
|
|
20
|
+
fontSize: "code",
|
|
21
|
+
fontWeight: "medium",
|
|
22
|
+
lineHeight: "body",
|
|
23
|
+
letterSpacing: "compact",
|
|
24
|
+
});
|
|
25
|
+
const hintText = css({ color: "fg.muted" });
|
|
26
|
+
const errorText = css({ color: "accent.red" });
|
|
27
|
+
/*
|
|
28
|
+
* A grey well holding its options, the selected one raised on the secondary button's face. The
|
|
29
|
+
* track is a default button's height, or in a toolbar a small one's on a thinner inset, and each
|
|
30
|
+
* option clears it by the inset and a hairline.
|
|
31
|
+
*/
|
|
10
32
|
const segmented = css({
|
|
33
|
+
"--track-inset": "token(spacing.layout.tightGap)",
|
|
34
|
+
"--track-height": "token(sizes.control.default)",
|
|
11
35
|
display: "inline-flex",
|
|
12
36
|
alignSelf: "flex-start",
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
37
|
+
alignItems: "center",
|
|
38
|
+
gap: "control.trackInset",
|
|
39
|
+
height: "var(--track-height)",
|
|
40
|
+
padding: "var(--track-inset)",
|
|
41
|
+
borderRadius: "inset",
|
|
42
|
+
// The well grey in light; in dark the panel's, where the field's white wash would read as glass.
|
|
43
|
+
background: "bg.panel",
|
|
44
|
+
_light: { background: "bg.field" },
|
|
45
|
+
"&[data-density=compact]": {
|
|
46
|
+
"--track-inset": "token(spacing.control.trackInset)",
|
|
47
|
+
"--track-height": "token(sizes.control.compact)",
|
|
23
48
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
49
|
+
"& > *": {
|
|
50
|
+
height: "calc(var(--track-height) - 2 * (var(--track-inset) + token(sizes.border.hairline)))!",
|
|
51
|
+
borderRadius: "action!",
|
|
27
52
|
},
|
|
53
|
+
"& > [aria-pressed=false]:not(:hover)": { color: "fg.muted" },
|
|
54
|
+
"& > [aria-pressed=true]": { boxShadow: "soft" },
|
|
28
55
|
});
|
|
29
56
|
const countText = css({ color: "fg.muted", fontVariantNumeric: "tabular-nums" });
|
|
30
57
|
const formStack = css({ display: "grid", gap: "layout.clusterGap", minWidth: "0" });
|
|
58
|
+
// Fields side by side sit closer than stacked ones.
|
|
59
|
+
const fieldRow = css({
|
|
60
|
+
display: "grid",
|
|
61
|
+
gridAutoFlow: "column",
|
|
62
|
+
gridAutoColumns: "minmax(0, 1fr)",
|
|
63
|
+
gap: "layout.contentGap",
|
|
64
|
+
});
|
|
31
65
|
const formActions = css({
|
|
32
66
|
display: "flex",
|
|
33
67
|
justifyContent: "flex-end",
|
|
@@ -43,16 +77,26 @@ export function Form({ className, ...props }) {
|
|
|
43
77
|
export function FormActions({ className, ...props }) {
|
|
44
78
|
return _jsx("div", { ...props, className: cx(formActions, className), "data-ciridae-ui": "" });
|
|
45
79
|
}
|
|
80
|
+
/** Fields in one row of a `Form`, sharing its width equally. */
|
|
81
|
+
export function FieldRow({ className, ...props }) {
|
|
82
|
+
return _jsx("div", { ...props, className: cx(fieldRow, className), "data-ciridae-ui": "" });
|
|
83
|
+
}
|
|
46
84
|
/**
|
|
47
85
|
* A label round a `FieldLabel`, its control and any `FieldError`: the label names the control it
|
|
48
86
|
* holds, and while `invalid` the control is marked and described by the error, so `Input`,
|
|
49
|
-
* `Textarea`, `Select` and `Combobox` inside need no ids of their own.
|
|
87
|
+
* `Textarea`, `Select` and `Combobox` inside need no ids of their own. A `hint` sits under the
|
|
88
|
+
* control and describes it until the error takes its place.
|
|
50
89
|
*/
|
|
51
|
-
export function Field({ className, htmlFor, invalid = false, ...props }) {
|
|
90
|
+
export function Field({ className, htmlFor, invalid = false, hint, children, ...props }) {
|
|
52
91
|
const generatedId = useId();
|
|
53
92
|
const controlId = htmlFor ?? `${generatedId}-control`;
|
|
54
|
-
const
|
|
55
|
-
|
|
93
|
+
const showsHint = hint !== undefined && !invalid;
|
|
94
|
+
const fieldControl = useMemo(() => ({
|
|
95
|
+
controlId,
|
|
96
|
+
descriptionId: invalid ? `${controlId}-error` : showsHint ? `${controlId}-hint` : undefined,
|
|
97
|
+
invalid,
|
|
98
|
+
}), [controlId, invalid, showsHint]);
|
|
99
|
+
return (_jsx(FieldControlContext, { value: fieldControl, children: _jsxs("label", { ...props, htmlFor: htmlFor, className: cx(field, className), "data-ciridae-ui": "", children: [children, showsHint && (_jsx("span", { id: `${controlId}-hint`, className: cx(noteText, hintText), children: hint }))] }) }));
|
|
56
100
|
}
|
|
57
101
|
export function FieldLabel({ children }) {
|
|
58
102
|
return _jsx("span", { className: labelText, children: children });
|
|
@@ -60,13 +104,14 @@ export function FieldLabel({ children }) {
|
|
|
60
104
|
/** The field's error; its id is the one the field's control is described by. */
|
|
61
105
|
export function FieldError({ id, children }) {
|
|
62
106
|
const field = useContext(FieldControlContext);
|
|
63
|
-
return (_jsx("p", { id: id ?? (field ? `${field.controlId}-error` : undefined), role: "alert", className: errorText, children: children }));
|
|
107
|
+
return (_jsx("p", { id: id ?? (field ? `${field.controlId}-error` : undefined), role: "alert", className: cx(noteText, errorText), children: children }));
|
|
64
108
|
}
|
|
65
109
|
export function SegmentedControl({ className, ...props }) {
|
|
66
110
|
const inToolbar = useInToolbar();
|
|
67
|
-
|
|
111
|
+
const edge = faceEdge("raised");
|
|
112
|
+
return (_jsx("div", { ...props, className: cx(segmented, edge.className, className), "data-density": inToolbar ? "compact" : undefined, "data-ciridae-ui": "", "data-edge": edge["data-edge"] }));
|
|
68
113
|
}
|
|
69
|
-
/** One option of a `SegmentedControl
|
|
114
|
+
/** One option of a `SegmentedControl`: the selected one is raised, the others bare. */
|
|
70
115
|
export function SegmentedOption({ selected, count, children, ...props }) {
|
|
71
|
-
return (_jsxs(Button, { ...props, type: "button", variant: "ghost", "aria-pressed": selected, children: [children, count !== undefined && _jsx("span", { className: countText, children: count })] }));
|
|
116
|
+
return (_jsxs(Button, { ...props, type: "button", variant: selected ? "secondary" : "ghost", "aria-pressed": selected, children: [children, count !== undefined && _jsx("span", { className: countText, children: count })] }));
|
|
72
117
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const glassMenuSurface: import("../styled-system/types/index.js").SystemStyleObject;
|
|
2
|
+
export declare const glassMenuRow: import("../styled-system/types/index.js").SystemStyleObject;
|
|
3
|
+
export declare const glassMenuDivider: import("../styled-system/types/index.js").SystemStyleObject;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { css } from "#primitives/css";
|
|
2
|
+
/*
|
|
3
|
+
* The glass sheet every menu, popover and select list floats on, and the rows inside it, as raw
|
|
4
|
+
* styles for `css()` to merge with each popup's own: an 8-round sheet padded 4px all round that
|
|
5
|
+
* blurs what lies under it, holding 4-round rows 32px tall.
|
|
6
|
+
*/
|
|
7
|
+
export const glassMenuSurface = css.raw({
|
|
8
|
+
padding: "menu.inset",
|
|
9
|
+
border: "1px solid token(colors.border.control)",
|
|
10
|
+
borderRadius: "action",
|
|
11
|
+
background: "bg.popover",
|
|
12
|
+
backdropFilter: "blur(token(blurs.popover))",
|
|
13
|
+
boxShadow: "soft",
|
|
14
|
+
color: "fg.primary",
|
|
15
|
+
textStyle: "body",
|
|
16
|
+
// The popup takes focus as it opens; it is a container, not a control, so it draws no ring.
|
|
17
|
+
outline: "none",
|
|
18
|
+
});
|
|
19
|
+
/*
|
|
20
|
+
* A row: hovered, it takes a wash inside the menu hover hairline, the raised glass in dark and the
|
|
21
|
+
* row's hover wash in light. A row that is a plain button has no highlight state, so it takes the
|
|
22
|
+
* wash on hover. Reached by the keyboard, away from the pointer, it draws the focus ring inside its
|
|
23
|
+
* own edge in place of the wash and the hairline.
|
|
24
|
+
*/
|
|
25
|
+
export const glassMenuRow = css.raw({
|
|
26
|
+
display: "flex",
|
|
27
|
+
alignItems: "center",
|
|
28
|
+
gap: "layout.controlGap",
|
|
29
|
+
minHeight: "control.compact",
|
|
30
|
+
paddingInline: "menu.itemInline",
|
|
31
|
+
borderRadius: "control",
|
|
32
|
+
color: "fg.primary",
|
|
33
|
+
fontSize: "body",
|
|
34
|
+
fontWeight: "medium",
|
|
35
|
+
lineHeight: "tight",
|
|
36
|
+
letterSpacing: "compact",
|
|
37
|
+
cursor: "pointer",
|
|
38
|
+
outline: "none",
|
|
39
|
+
"&[data-highlighted], &:is(button):hover": {
|
|
40
|
+
background: "token(gradients.raised)",
|
|
41
|
+
boxShadow: "inset 0 0 0 1px token(colors.border.menuHover)",
|
|
42
|
+
_light: { background: "bg.rowHover" },
|
|
43
|
+
},
|
|
44
|
+
// Under the pointer the row keeps the wash, so the ring marks only the row the keys reached.
|
|
45
|
+
"&:focus-visible:not(:hover), &[data-highlighted]:focus-visible:not(:hover)": {
|
|
46
|
+
focusRing: "inset",
|
|
47
|
+
background: "transparent",
|
|
48
|
+
boxShadow: "none",
|
|
49
|
+
_light: { background: "transparent" },
|
|
50
|
+
},
|
|
51
|
+
"&[data-disabled]": { opacity: "disabled", cursor: "not-allowed" },
|
|
52
|
+
});
|
|
53
|
+
/*
|
|
54
|
+
* The rule between groups of rows, inset 8px from the sheet's sides with 4px above and below: a
|
|
55
|
+
* hairline along the top of a 2px band, as the design draws it.
|
|
56
|
+
*/
|
|
57
|
+
export const glassMenuDivider = css.raw({
|
|
58
|
+
flexShrink: "0",
|
|
59
|
+
height: "calc(token(sizes.border.hairline) * 2)",
|
|
60
|
+
marginBlock: "layout.tightGap",
|
|
61
|
+
marginInline: "menu.itemInline",
|
|
62
|
+
borderTop: "1px solid token(colors.border.divider)",
|
|
63
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type GradientEdge = "raised" | "primary" | "danger" | "tinted" | "toolbar";
|
|
2
|
+
/** A face's edge: a flat hairline ciridae.css paints by name, or one of the gradient edges. */
|
|
3
|
+
export type FaceEdge = "glass" | "control" | GradientEdge;
|
|
4
|
+
/** The class and `data-edge` that draw `edge`; nothing for a face with no edge. */
|
|
5
|
+
export declare function faceEdge(edge: FaceEdge | undefined): {
|
|
6
|
+
className: string | undefined;
|
|
7
|
+
"data-edge": string | undefined;
|
|
8
|
+
};
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { cva } from "#primitives/css";
|
|
2
|
+
/*
|
|
3
|
+
* The 1px edge a face draws as a gradient. A gradient cannot be a border color, so it paints the
|
|
4
|
+
* `[data-edge]` ring ciridae.css draws inside the element's box, which also keeps its corners:
|
|
5
|
+
* `faceEdge` gives the class that paints the ring and the `data-edge` that turns it on. Dark draws
|
|
6
|
+
* no edge on the primary or destructive face. A toolbar control's edge is the selected face's: the
|
|
7
|
+
* raised gradient in dark and a paler grey gradient in light.
|
|
8
|
+
*/
|
|
9
|
+
const gradientEdge = cva({
|
|
10
|
+
base: {},
|
|
11
|
+
variants: {
|
|
12
|
+
edge: {
|
|
13
|
+
raised: { _before: { background: "token(gradients.border.raised)" } },
|
|
14
|
+
primary: { _before: { background: "token(gradients.border.primary)" } },
|
|
15
|
+
danger: { _before: { background: "token(gradients.border.danger)" } },
|
|
16
|
+
tinted: { _before: { background: "token(gradients.border.tinted)" } },
|
|
17
|
+
toolbar: { _before: { background: "token(gradients.border.selected)" } },
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
function isGradientEdge(edge) {
|
|
22
|
+
return edge !== "glass" && edge !== "control";
|
|
23
|
+
}
|
|
24
|
+
/** The class and `data-edge` that draw `edge`; nothing for a face with no edge. */
|
|
25
|
+
export function faceEdge(edge) {
|
|
26
|
+
if (edge === undefined)
|
|
27
|
+
return { className: undefined, "data-edge": undefined };
|
|
28
|
+
if (isGradientEdge(edge))
|
|
29
|
+
return { className: gradientEdge({ edge }), "data-edge": "gradient" };
|
|
30
|
+
return { className: undefined, "data-edge": edge };
|
|
31
|
+
}
|
|
@@ -7,7 +7,7 @@ export declare const PAGE_HOTKEY_SCOPE = "page";
|
|
|
7
7
|
/** Gives the hotkeys registered inside it to the page, paused while an overlay is open. */
|
|
8
8
|
export declare function PageHotkeys({ children }: {
|
|
9
9
|
children: ReactNode;
|
|
10
|
-
}): import("
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
11
|
/**
|
|
12
12
|
* An overlay's keyboard: while mounted (and `enabled`), only the hotkeys registered inside it and
|
|
13
13
|
* the global ones fire, so the top overlay owns the keyboard and the page under it pauses.
|
|
@@ -15,7 +15,7 @@ export declare function PageHotkeys({ children }: {
|
|
|
15
15
|
export declare function HotkeyLayer({ enabled, children }: {
|
|
16
16
|
enabled?: boolean;
|
|
17
17
|
children: ReactNode;
|
|
18
|
-
}): import("
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
19
|
/**
|
|
20
20
|
* The person's rebound hotkeys, kept in `localStorage` as JSON under `storageKey`, as the root
|
|
21
21
|
* `HotkeysProvider`'s `customHotkeys` and `onCustomHotkeysChange`. Entries that are no hotkey are
|
|
@@ -55,4 +55,4 @@ export type SpinnerProps = Omit<IconProps, "size"> & {
|
|
|
55
55
|
label?: string;
|
|
56
56
|
};
|
|
57
57
|
/** The one in-progress glyph: every pending state spins this, never a refresh or notch icon. */
|
|
58
|
-
export declare function Spinner({ size, label, className, ...props }: SpinnerProps): import("
|
|
58
|
+
export declare function Spinner({ size, label, className, ...props }: SpinnerProps): import("react").JSX.Element;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type ComponentProps, type MouseEvent } from "react";
|
|
2
2
|
import type { Hotkey } from "./hotkeys.js";
|
|
3
3
|
export type InputProps = Omit<ComponentProps<"input">, "size"> & {
|
|
4
|
-
size?: "small" | "medium" | "large";
|
|
4
|
+
size?: "inline" | "small" | "medium" | "large";
|
|
5
5
|
};
|
|
6
|
-
export declare function Input({ className, size, ...props }: InputProps): import("
|
|
6
|
+
export declare function Input({ className, size, ...props }: InputProps): import("react").JSX.Element;
|
|
7
7
|
export type SearchInputProps = Omit<ComponentProps<"input">, "size" | "value" | "defaultValue"> & {
|
|
8
|
-
variant?: "regular" | "flat" | "sidebar" | "
|
|
8
|
+
variant?: "regular" | "flat" | "sidebar" | "ghost";
|
|
9
9
|
/** Defaults to `compact` in a `Toolbar`, `regular` elsewhere. */
|
|
10
10
|
size?: "regular" | "compact";
|
|
11
11
|
/** `fill` takes the row's width; `field` grows from a name's width to a search field's. */
|
|
@@ -23,7 +23,7 @@ export type SearchInputProps = Omit<ComponentProps<"input">, "size" | "value" |
|
|
|
23
23
|
shortcut?: Hotkey;
|
|
24
24
|
wrapperClassName?: string;
|
|
25
25
|
};
|
|
26
|
-
export declare function SearchInput({ variant, size: ownSize, width, value, defaultValue, onValueCommit, debounceMs, shortcut, wrapperClassName, className, onChange, onKeyDown, ...props }: SearchInputProps): import("
|
|
26
|
+
export declare function SearchInput({ variant, size: ownSize, width, value, defaultValue, onValueCommit, debounceMs, shortcut, wrapperClassName, className, onChange, onKeyDown, ...props }: SearchInputProps): import("react").JSX.Element;
|
|
27
27
|
export type SearchFieldProps = Omit<ComponentProps<"input">, "size" | "type"> & {
|
|
28
28
|
/** Defaults to `compact` in a `Toolbar`, `regular` elsewhere. */
|
|
29
29
|
size?: "regular" | "compact";
|
|
@@ -31,6 +31,8 @@ export type SearchFieldProps = Omit<ComponentProps<"input">, "size" | "type"> &
|
|
|
31
31
|
onClear?: (event: MouseEvent<HTMLButtonElement>) => void;
|
|
32
32
|
/** Shows this hotkey's hint while the field is empty, such as "/"; the host binds it. */
|
|
33
33
|
shortcut?: Hotkey;
|
|
34
|
+
/** In a menu or popover: the hairline alone, as the sheet's divider, with no hover or ring. */
|
|
35
|
+
quiet?: boolean;
|
|
34
36
|
wrapperClassName?: string;
|
|
35
37
|
};
|
|
36
|
-
export declare function SearchField({ size: ownSize, onClear, shortcut, wrapperClassName, className, disabled, ...props }: SearchFieldProps): import("
|
|
38
|
+
export declare function SearchField({ size: ownSize, onClear, quiet, shortcut, wrapperClassName, className, disabled, ...props }: SearchFieldProps): import("react").JSX.Element;
|
package/dist/components/input.js
CHANGED
|
@@ -16,7 +16,7 @@ import { useCiridaeLocale } from "./locale.js";
|
|
|
16
16
|
const fieldFace = {
|
|
17
17
|
border: "1px solid token(colors.border.control)",
|
|
18
18
|
borderRadius: "control",
|
|
19
|
-
background: "bg.
|
|
19
|
+
background: "bg.formField",
|
|
20
20
|
color: "fg.primary",
|
|
21
21
|
fontFamily: "sans",
|
|
22
22
|
fontWeight: "medium",
|
|
@@ -34,13 +34,19 @@ const field = cva({
|
|
|
34
34
|
base: { ...fieldFace, width: "100%", lineHeight: "tight" },
|
|
35
35
|
variants: {
|
|
36
36
|
size: {
|
|
37
|
-
/**
|
|
37
|
+
/** The editor an inline-edit row opens in place of its value. */
|
|
38
|
+
inline: {
|
|
39
|
+
height: "field.inline",
|
|
40
|
+
paddingInline: "menu.itemInline",
|
|
41
|
+
fontSize: "body",
|
|
42
|
+
},
|
|
43
|
+
/** For a row of filters, beside compact selects and small buttons. */
|
|
38
44
|
small: {
|
|
39
45
|
height: "control.compact",
|
|
40
46
|
paddingInline: "control.compactInline",
|
|
41
47
|
fontSize: "caption",
|
|
42
48
|
},
|
|
43
|
-
/** The
|
|
49
|
+
/** The field: the height of the default button. */
|
|
44
50
|
medium: {
|
|
45
51
|
height: "control.default",
|
|
46
52
|
paddingInline: "control.compactInline",
|
|
@@ -55,9 +61,9 @@ const field = cva({
|
|
|
55
61
|
},
|
|
56
62
|
},
|
|
57
63
|
},
|
|
58
|
-
defaultVariants: { size: "
|
|
64
|
+
defaultVariants: { size: "medium" },
|
|
59
65
|
});
|
|
60
|
-
export function Input({ className, size = "
|
|
66
|
+
export function Input({ className, size = "medium", ...props }) {
|
|
61
67
|
const fieldIds = useFieldControl(props);
|
|
62
68
|
return (_jsx(BaseInput, { ...props, ...fieldIds, className: cx(field({ size }), className), "data-ciridae-ui": "" }));
|
|
63
69
|
}
|
|
@@ -89,7 +95,8 @@ const search = cva({
|
|
|
89
95
|
border: "1px solid token(colors.border.control)",
|
|
90
96
|
background: "bg.field",
|
|
91
97
|
},
|
|
92
|
-
|
|
98
|
+
// No face: the field reads as text until focused, beside ghost buttons in a toolbar.
|
|
99
|
+
ghost: {
|
|
93
100
|
borderRadius: "action",
|
|
94
101
|
paddingInline: "control.compactInline",
|
|
95
102
|
border: "0",
|
|
@@ -142,7 +149,7 @@ const searchText = cva({
|
|
|
142
149
|
regular: {},
|
|
143
150
|
sidebar: {},
|
|
144
151
|
flat: {},
|
|
145
|
-
|
|
152
|
+
ghost: { fontSize: "caption", fontWeight: "regular" },
|
|
146
153
|
},
|
|
147
154
|
size: { regular: {}, compact: { fontSize: "caption", fontWeight: "regular" } },
|
|
148
155
|
},
|
|
@@ -178,12 +185,13 @@ export function SearchInput({ variant = "regular", size: ownSize, width = "fill"
|
|
|
178
185
|
onValueCommit(event.currentTarget.value);
|
|
179
186
|
}
|
|
180
187
|
onKeyDown?.(event);
|
|
181
|
-
}, className: cx(searchText({ variant, size }), className) }), shortcut && _jsx(ShortcutHint, { hotkey: shortcut })] }));
|
|
188
|
+
}, className: cx(searchText({ variant, size }), className) }), shortcut && _jsx(ShortcutHint, { boxed: true, hotkey: shortcut })] }));
|
|
182
189
|
}
|
|
183
190
|
/*
|
|
184
191
|
* The Round 2 search field is an underline, not a box: an icon, the text, and a clear button on
|
|
185
|
-
* one hairline.
|
|
186
|
-
*
|
|
192
|
+
* one hairline. Hovered it takes the hover wash, and focused the ring, both on its own nearly
|
|
193
|
+
* square corners. Quiet, in a menu or popover, the hairline is the sheet's divider and nothing
|
|
194
|
+
* else changes: the popup opens with the field focused, and its caret shows that.
|
|
187
195
|
*/
|
|
188
196
|
const underline = cva({
|
|
189
197
|
base: {
|
|
@@ -194,10 +202,6 @@ const underline = cva({
|
|
|
194
202
|
paddingInline: "search.inline",
|
|
195
203
|
borderBottom: "1px solid token(colors.border.control)",
|
|
196
204
|
color: "fg.muted",
|
|
197
|
-
"&:has(:focus-visible)": {
|
|
198
|
-
borderBottomColor: "border.focus",
|
|
199
|
-
boxShadow: "inset 0 -1px 0 0 token(colors.border.focus)",
|
|
200
|
-
},
|
|
201
205
|
"&:has(:disabled)": { opacity: "disabled" },
|
|
202
206
|
},
|
|
203
207
|
variants: {
|
|
@@ -205,8 +209,16 @@ const underline = cva({
|
|
|
205
209
|
regular: { height: "control.default" },
|
|
206
210
|
compact: { height: "control.compact" },
|
|
207
211
|
},
|
|
212
|
+
quiet: {
|
|
213
|
+
false: {
|
|
214
|
+
borderRadius: "control",
|
|
215
|
+
_hover: { background: "bg.controlHover" },
|
|
216
|
+
"&:has(:focus-visible)": { focusRing: "outer" },
|
|
217
|
+
},
|
|
218
|
+
true: { paddingInline: "none", borderBottomColor: "border.divider" },
|
|
219
|
+
},
|
|
208
220
|
},
|
|
209
|
-
defaultVariants: { size: "regular" },
|
|
221
|
+
defaultVariants: { size: "regular", quiet: false },
|
|
210
222
|
});
|
|
211
223
|
const underlineText = css({
|
|
212
224
|
flex: "1",
|
|
@@ -241,9 +253,9 @@ const clear = css({
|
|
|
241
253
|
_hover: { color: "fg.primary", background: "bg.hover" },
|
|
242
254
|
_focusVisible: { focusRing: "inset" },
|
|
243
255
|
});
|
|
244
|
-
export function SearchField({ size: ownSize, onClear, shortcut, wrapperClassName, className, disabled, ...props }) {
|
|
256
|
+
export function SearchField({ size: ownSize, onClear, quiet = false, shortcut, wrapperClassName, className, disabled, ...props }) {
|
|
245
257
|
const inToolbar = useInToolbar();
|
|
246
258
|
const { labels } = useCiridaeLocale();
|
|
247
259
|
const size = ownSize ?? (inToolbar ? "compact" : "regular");
|
|
248
|
-
return (_jsxs("label", { className: cx(underline({ size }), wrapperClassName), "data-ciridae-ui": "", children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), _jsx(BaseInput, { ...props, type: "search", disabled: disabled, className: cx(underlineText, className) }), onClear && (_jsx("button", { type: "button", className: clear, "aria-label": labels.common.clear, disabled: disabled, onClick: onClear, children: _jsx(XIcon, { className: icon({ size: "small" }) }) })), shortcut && !onClear && _jsx(ShortcutHint, { hotkey: shortcut })] }));
|
|
260
|
+
return (_jsxs("label", { className: cx(underline({ size, quiet }), wrapperClassName), "data-ciridae-ui": "", children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), _jsx(BaseInput, { ...props, type: "search", disabled: disabled, className: cx(underlineText, className) }), onClear && (_jsx("button", { type: "button", className: clear, "aria-label": labels.common.clear, disabled: disabled, onClick: onClear, children: _jsx(XIcon, { className: icon({ size: "small" }) }) })), shortcut && !onClear && _jsx(ShortcutHint, { boxed: true, hotkey: shortcut })] }));
|
|
249
261
|
}
|
|
@@ -5,6 +5,6 @@ export type KeyboardShortcutsProps = {
|
|
|
5
5
|
open?: boolean;
|
|
6
6
|
onOpenChange?: (open: boolean) => void;
|
|
7
7
|
};
|
|
8
|
-
export declare function KeyboardShortcuts({ hotkey, open: ownOpen, onOpenChange, }: KeyboardShortcutsProps): import("
|
|
8
|
+
export declare function KeyboardShortcuts({ hotkey, open: ownOpen, onOpenChange, }: KeyboardShortcutsProps): import("react").JSX.Element;
|
|
9
9
|
/** The app's rebindable hotkeys under their groups, each with Change and, once changed, Reset. */
|
|
10
|
-
export declare function KeyboardShortcutSettings(): import("
|
|
10
|
+
export declare function KeyboardShortcutSettings(): import("react").JSX.Element[];
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { type Hotkey } from "./hotkeys.js";
|
|
2
2
|
import type { ComponentProps } from "react";
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* One key as a 22px square cap, such as the `K` after a search field. A label of more than one
|
|
5
|
+
* character, such as `Esc`, takes the wider word cap on its own.
|
|
6
|
+
*/
|
|
7
|
+
export declare function Keycap({ className, children, ...props }: ComponentProps<"kbd">): import("react").JSX.Element;
|
|
5
8
|
/**
|
|
6
9
|
* A hotkey as one quiet line, as the hotkeys layer writes it: `Mod` is "⌘" on a Mac and "Ctrl"
|
|
7
|
-
* elsewhere, and a sequence's steps are spaced ("G I"). `
|
|
8
|
-
*
|
|
10
|
+
* elsewhere, and a sequence's steps are spaced ("G I"). `boxed` sets each key in its own
|
|
11
|
+
* `Keycap`, 2px apart, as a menu row or a search field shows it.
|
|
9
12
|
*/
|
|
10
|
-
export declare function ShortcutHint({ hotkey, className, ...props }: ComponentProps<"kbd"> & {
|
|
13
|
+
export declare function ShortcutHint({ hotkey, boxed, className, ...props }: ComponentProps<"kbd"> & {
|
|
11
14
|
hotkey: Hotkey;
|
|
12
|
-
|
|
15
|
+
boxed?: boolean;
|
|
16
|
+
}): import("react").JSX.Element;
|