@ciridae/ui 1.0.3 → 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/chat/conversation-source.d.ts +15 -1
- package/dist/chat/describe-tool-call.d.ts +3 -3
- package/dist/chat/describe-tool-call.js +3 -3
- package/dist/chat/message-text.js +2 -2
- package/dist/ciridae.css +16 -4
- package/dist/components/activity-feed.d.ts +1 -0
- package/dist/components/activity-feed.js +1 -0
- package/dist/components/app-frame.d.ts +13 -1
- package/dist/components/app-frame.js +45 -3
- package/dist/components/app-navigation.d.ts +28 -1
- package/dist/components/app-navigation.js +105 -14
- package/dist/components/badge.d.ts +29 -4
- package/dist/components/badge.js +134 -15
- package/dist/components/bulk-action-bar.js +3 -3
- package/dist/components/button.d.ts +10 -3
- package/dist/components/button.js +77 -44
- package/dist/components/calendar.js +44 -17
- package/dist/components/centered-page.js +2 -2
- package/dist/components/chart.d.ts +1 -1
- package/dist/components/chart.js +16 -11
- package/dist/components/chat-client-source.js +47 -6
- package/dist/components/chat-sheet-controller.d.ts +1 -0
- package/dist/components/chat-sheet-controller.js +1 -0
- package/dist/components/chat-sheet.d.ts +10 -2
- package/dist/components/chat-sheet.js +76 -39
- package/dist/components/chat.d.ts +90 -14
- package/dist/components/chat.js +402 -101
- package/dist/components/checkbox-item.d.ts +5 -2
- package/dist/components/checkbox-item.js +9 -5
- package/dist/components/chip.d.ts +5 -0
- package/dist/components/chip.js +27 -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 +6 -2
- package/dist/components/command-palette.js +20 -10
- package/dist/components/data-display.d.ts +35 -4
- package/dist/components/data-display.js +138 -19
- package/dist/components/data-grid.d.ts +14 -2
- package/dist/components/data-grid.js +61 -26
- package/dist/components/date-range-picker.js +9 -20
- package/dist/components/drawer.d.ts +5 -0
- package/dist/components/drawer.js +91 -54
- package/dist/components/editable-field.d.ts +12 -3
- package/dist/components/editable-field.js +57 -27
- package/dist/components/email-input.js +6 -5
- package/dist/components/environment-frame.d.ts +1 -1
- package/dist/components/environment-frame.js +37 -6
- package/dist/components/filter-bar.js +39 -28
- package/dist/components/form-controls.d.ts +9 -0
- package/dist/components/form-controls.js +46 -22
- package/dist/components/form-layout.d.ts +7 -3
- 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/input.d.ts +4 -2
- package/dist/components/input.js +26 -15
- package/dist/components/keycap.d.ts +9 -5
- package/dist/components/keycap.js +57 -19
- package/dist/components/lightbox.js +2 -1
- package/dist/components/locale.d.ts +10 -0
- package/dist/components/locale.js +18 -2
- package/dist/components/log-entry.d.ts +40 -0
- package/dist/components/log-entry.js +146 -0
- package/dist/components/mention-input.js +4 -3
- package/dist/components/menu.d.ts +6 -2
- package/dist/components/menu.js +34 -37
- package/dist/components/meter.d.ts +9 -1
- 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.js +5 -4
- package/dist/components/overlays.d.ts +3 -1
- package/dist/components/overlays.js +69 -40
- package/dist/components/page-frame.js +1 -1
- package/dist/components/panel.d.ts +1 -1
- package/dist/components/panel.js +18 -12
- package/dist/components/radio-card.js +10 -9
- package/dist/components/record.d.ts +25 -1
- package/dist/components/record.js +147 -18
- package/dist/components/segmented-bar.d.ts +3 -1
- package/dist/components/segmented-bar.js +16 -6
- package/dist/components/select.d.ts +5 -2
- package/dist/components/select.js +103 -127
- package/dist/components/shell-skeleton.js +1 -1
- package/dist/components/shell.d.ts +2 -2
- package/dist/components/shell.js +43 -45
- package/dist/components/sidebar.d.ts +7 -2
- 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 +7 -6
- package/dist/components/skeleton.js +28 -16
- package/dist/components/skeletons.d.ts +12 -0
- package/dist/components/skeletons.js +71 -8
- package/dist/components/stages.d.ts +78 -6
- package/dist/components/stages.js +512 -156
- package/dist/components/stat-card.d.ts +10 -2
- package/dist/components/stat-card.js +92 -37
- package/dist/components/status-banner.js +1 -1
- package/dist/components/tabs.js +26 -13
- package/dist/components/theme-toggle.d.ts +4 -0
- package/dist/components/theme-toggle.js +67 -0
- package/dist/components/toast.d.ts +9 -2
- package/dist/components/toast.js +78 -29
- package/dist/preset.js +289 -33
- package/dist/styled-system/styles.css +3115 -1044
- 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 +9 -1
|
@@ -7,14 +7,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
7
7
|
* alone, such as a column head's "Filter by". Nothing here filters rows: `matchesFilter` tests one
|
|
8
8
|
* value for a list that filters on the client.
|
|
9
9
|
*/
|
|
10
|
-
import { CaretDownIcon, CaretLeftIcon, PlusIcon, XIcon } from "@phosphor-icons/react";
|
|
10
|
+
import { CaretDownIcon, CaretLeftIcon, CaretRightIcon, PlusIcon, XIcon, } from "@phosphor-icons/react";
|
|
11
11
|
import { useState } from "react";
|
|
12
12
|
import { css, cx } from "#primitives/css";
|
|
13
13
|
import { Button, IconButton } from "./button.js";
|
|
14
14
|
import { CheckboxItem } from "./checkbox-item.js";
|
|
15
15
|
import { useControllableState } from "./controllable-state.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { glassMenuDivider, glassMenuRow } from "./glass-menu.js";
|
|
17
|
+
import { faceEdge } from "./gradient-edge.js";
|
|
18
|
+
import { directional, icon } from "./icon.js";
|
|
18
19
|
import { Input, SearchField } from "./input.js";
|
|
19
20
|
import { useCiridaeLocale } from "./locale.js";
|
|
20
21
|
import { Menu } from "./menu.js";
|
|
@@ -90,6 +91,10 @@ export function describeFilter(field, filter, locale) {
|
|
|
90
91
|
: values.join(", "),
|
|
91
92
|
};
|
|
92
93
|
}
|
|
94
|
+
/*
|
|
95
|
+
* The slicer's face: the selected tint, hovering to the raised face. The field reads in the
|
|
96
|
+
* secondary grey, the operator a step quieter.
|
|
97
|
+
*/
|
|
93
98
|
const chip = css({
|
|
94
99
|
display: "inline-flex",
|
|
95
100
|
alignItems: "center",
|
|
@@ -99,7 +104,9 @@ const chip = css({
|
|
|
99
104
|
paddingInlineStart: "control.compactInline",
|
|
100
105
|
paddingInlineEnd: "control.iconGap",
|
|
101
106
|
borderRadius: "pill",
|
|
102
|
-
background: "
|
|
107
|
+
background: "token(gradients.selected)",
|
|
108
|
+
_hover: { background: "token(gradients.raisedHover)" },
|
|
109
|
+
_light: { color: "fg.secondary" },
|
|
103
110
|
color: "fg.muted",
|
|
104
111
|
fontSize: "caption",
|
|
105
112
|
fontWeight: "medium",
|
|
@@ -122,6 +129,7 @@ const chipBody = css({
|
|
|
122
129
|
_focusVisible: { focusRing: "outer" },
|
|
123
130
|
"& svg": { flexShrink: "0" },
|
|
124
131
|
});
|
|
132
|
+
const chipOperator = css({ color: "fg.muted" });
|
|
125
133
|
const chipValue = css({ color: "fg.primary", overflow: "hidden", textOverflow: "ellipsis" });
|
|
126
134
|
const chipRemove = css({
|
|
127
135
|
display: "inline-grid",
|
|
@@ -138,10 +146,11 @@ const chipRemove = css({
|
|
|
138
146
|
_hover: { color: "fg.primary", background: "bg.hover" },
|
|
139
147
|
_focusVisible: { focusRing: "outer" },
|
|
140
148
|
});
|
|
149
|
+
const toolbarEdge = faceEdge("toolbar");
|
|
141
150
|
/** One set filter: the field and operator muted, its values in full; the text reopens it. */
|
|
142
151
|
export function FilterChip({ label, icon: fieldIcon, operator, values, onEdit, onRemove, className, ...props }) {
|
|
143
152
|
const { labels } = useCiridaeLocale();
|
|
144
|
-
return (_jsxs("span", { ...props, className: cx(chip, className), "data-ciridae-ui": "", "data-edge": "
|
|
153
|
+
return (_jsxs("span", { ...props, className: cx(chip, toolbarEdge.className, className), "data-ciridae-ui": "", "data-edge": toolbarEdge["data-edge"], children: [_jsxs("button", { type: "button", className: chipBody, onClick: onEdit, children: [fieldIcon, label, " ", _jsx("span", { className: chipOperator, children: operator }), _jsx("span", { className: chipValue, children: values })] }), _jsx("button", { type: "button", className: chipRemove, "aria-label": labels.filters.remove(label), onClick: onRemove, children: _jsx(XIcon, { className: icon({ size: "small" }) }) })] }));
|
|
145
154
|
}
|
|
146
155
|
const bar = css({
|
|
147
156
|
display: "flex",
|
|
@@ -170,28 +179,29 @@ const tools = css({
|
|
|
170
179
|
"& > button": { flexShrink: "0" },
|
|
171
180
|
"& > :not(button)": { minWidth: "0" },
|
|
172
181
|
});
|
|
173
|
-
const builder = css({
|
|
174
|
-
const fieldItem = css({
|
|
182
|
+
const builder = css({
|
|
175
183
|
display: "flex",
|
|
176
|
-
|
|
177
|
-
|
|
184
|
+
flexDirection: "column",
|
|
185
|
+
width: "overlay.popover",
|
|
186
|
+
maxWidth: "100%",
|
|
187
|
+
});
|
|
188
|
+
// A menu row: the field's icon, its name, and an arrow on to its operator and values.
|
|
189
|
+
const fieldItem = css(glassMenuRow, {
|
|
178
190
|
width: "100%",
|
|
179
|
-
minHeight: "control.compact",
|
|
180
|
-
paddingInline: "menu.itemInline",
|
|
181
191
|
border: "0",
|
|
182
|
-
borderRadius: "control",
|
|
183
192
|
background: "transparent",
|
|
184
|
-
|
|
185
|
-
font: "inherit",
|
|
186
|
-
fontSize: "body",
|
|
187
|
-
fontWeight: "medium",
|
|
188
|
-
letterSpacing: "compact",
|
|
193
|
+
fontFamily: "inherit",
|
|
189
194
|
textAlign: "start",
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
195
|
+
"& > span": { flex: "1", minWidth: "0" },
|
|
196
|
+
"& svg": {
|
|
197
|
+
flexShrink: "0",
|
|
198
|
+
color: "fg.muted",
|
|
199
|
+
fontSize: "icon.small",
|
|
200
|
+
width: "1em",
|
|
201
|
+
height: "1em",
|
|
202
|
+
},
|
|
194
203
|
});
|
|
204
|
+
const menuDivider = css(glassMenuDivider);
|
|
195
205
|
const groupLabel = css({
|
|
196
206
|
paddingBlockStart: "control.block",
|
|
197
207
|
paddingBlockEnd: "layout.tightGap",
|
|
@@ -201,7 +211,8 @@ const groupLabel = css({
|
|
|
201
211
|
fontWeight: "medium",
|
|
202
212
|
letterSpacing: "compact",
|
|
203
213
|
});
|
|
204
|
-
|
|
214
|
+
// The quiet search's hairline is inset as the dividers are.
|
|
215
|
+
const searchWrap = css({ paddingInline: "menu.itemInline", paddingBlockEnd: "layout.tightGap" });
|
|
205
216
|
const noMatches = css({
|
|
206
217
|
paddingBlock: "control.block",
|
|
207
218
|
paddingInline: "menu.itemInline",
|
|
@@ -235,7 +246,7 @@ export function FilterBar({ fields, value, defaultValue = [], onValueChange, ope
|
|
|
235
246
|
setEditing(field.key);
|
|
236
247
|
setOpen(true);
|
|
237
248
|
}, onRemove: () => setFilters(filters.filter((candidate) => candidate.field !== filter.field)) }, filter.field));
|
|
238
|
-
}) })), _jsxs("div", { className: tools, children: [filters.length > 0 && (_jsx(Button, { variant: "ghost", onClick: () => setFilters([]), children: labels.filters.clearAll })), _jsx(Popover, { open: open, onOpenChange: changeOpen, density: "compact", trigger: _jsx(Button, { variant: "
|
|
249
|
+
}) })), _jsxs("div", { className: tools, children: [filters.length > 0 && (_jsx(Button, { variant: "ghost", onClick: () => setFilters([]), children: labels.filters.clearAll })), _jsx(Popover, { open: open, onOpenChange: changeOpen, density: "compact", trigger: _jsx(Button, { variant: "secondary", size: "medium", icon: _jsx(PlusIcon, { className: icon({ size: "small" }) }), onClick: () => setEditing(null), children: labels.filters.addFilter }), children: open && (_jsx(FilterBuilder, { fields: fields, startField: editing, filters: filters, onChange: (filter) => setFilters(replaceFilter(filters, filter)) }, editing ?? "")) }), children] })] }));
|
|
239
250
|
}
|
|
240
251
|
function FilterBuilder({ fields, startField, filters, onChange, }) {
|
|
241
252
|
const { labels } = useCiridaeLocale();
|
|
@@ -254,10 +265,10 @@ function FilterBuilder({ fields, startField, filters, onChange, }) {
|
|
|
254
265
|
else
|
|
255
266
|
groups.push({ label: candidate.group, fields: [candidate] });
|
|
256
267
|
}
|
|
257
|
-
return (_jsxs("div", { className: builder, children: [_jsx("div", { className: searchWrap, children: _jsx(SearchField, { size: "compact", "aria-label": labels.filters.filterBy, placeholder: labels.filters.filterBy, value: query, onChange: (event) => setQuery(event.target.value) }) }), groups.map((group, index) => (_jsxs("div", { className: css({ display: "grid" }), children: [index > 0 && _jsx(
|
|
268
|
+
return (_jsxs("div", { className: builder, children: [_jsx("div", { className: searchWrap, children: _jsx(SearchField, { size: "compact", quiet: true, "aria-label": labels.filters.filterBy, placeholder: labels.filters.filterBy, value: query, onChange: (event) => setQuery(event.target.value) }) }), groups.map((group, index) => (_jsxs("div", { className: css({ display: "grid" }), children: [index > 0 && _jsx("div", { className: menuDivider, role: "separator" }), group.label && _jsx("span", { className: groupLabel, children: group.label }), group.fields.map((candidate) => (_jsxs("button", { type: "button", className: fieldItem, onClick: () => {
|
|
258
269
|
setFieldKey(candidate.key);
|
|
259
270
|
setQuery("");
|
|
260
|
-
}, children: [candidate.icon, candidate.label] }, candidate.key)))] }, group.label ?? ""))), matching.length === 0 && _jsx("span", { className: noMatches, children: labels.filters.noFields })] }));
|
|
271
|
+
}, children: [candidate.icon, _jsx("span", { children: candidate.label }), _jsx(CaretRightIcon, { className: directional, "aria-hidden": "true" })] }, candidate.key)))] }, group.label ?? ""))), matching.length === 0 && _jsx("span", { className: noMatches, children: labels.filters.noFields })] }));
|
|
261
272
|
}
|
|
262
273
|
const editorHeader = css({
|
|
263
274
|
display: "flex",
|
|
@@ -329,13 +340,13 @@ export function FilterValueEditor({ field, value, onChange, onBack, }) {
|
|
|
329
340
|
const keepsValues = multiValueOperators.includes(candidate) === multiple && candidate !== "between";
|
|
330
341
|
report(candidate, keepsValues ? values : values.slice(0, 1));
|
|
331
342
|
},
|
|
332
|
-
})) })) : (_jsx("span", { className: fixedOperator, children: operatorLabel }))] }), options ? (_jsxs(_Fragment, { children: [field.options && field.options.length > 6 && (_jsx("div", { className: searchWrap, children: _jsx(SearchField, { size: "compact", "aria-label": labels.filters.searchValues(field.label), placeholder: labels.filters.searchValues(field.label), value: query, onChange: (event) => setQuery(event.target.value) }) })), _jsxs("div", { className: valueList, children: [options.map((option) => (_jsxs(CheckboxItem, { checked: values.includes(option.value), onCheckedChange: (checked) => report(operator, multiple
|
|
343
|
+
})) })) : (_jsx("span", { className: fixedOperator, children: operatorLabel }))] }), options ? (_jsxs(_Fragment, { children: [field.options && field.options.length > 6 && (_jsx("div", { className: searchWrap, children: _jsx(SearchField, { size: "compact", quiet: true, "aria-label": labels.filters.searchValues(field.label), placeholder: labels.filters.searchValues(field.label), value: query, onChange: (event) => setQuery(event.target.value) }) })), _jsxs("div", { className: valueList, children: [options.map((option) => (_jsxs(CheckboxItem, { checked: values.includes(option.value), onCheckedChange: (checked) => report(operator, multiple
|
|
333
344
|
? checked
|
|
334
345
|
? [...values, option.value]
|
|
335
346
|
: values.filter((candidate) => candidate !== option.value)
|
|
336
347
|
: checked
|
|
337
348
|
? [option.value]
|
|
338
|
-
: []), meta: option.count, children: [option.icon, option.label] }, option.value))), options.length === 0 && _jsx("span", { className: noMatches, children: labels.filters.noValues })] })] })) : (_jsx("div", { className: inputs, children: (operator === "between" ? [0, 1] : [0]).map((index) => (_jsx(Input, { type: field.kind === "date" ? "date" : field.kind === "number" ? "number" : "text", "aria-label": operator === "between"
|
|
349
|
+
: []), meta: option.count, children: [option.icon, option.label] }, option.value))), options.length === 0 && _jsx("span", { className: noMatches, children: labels.filters.noValues })] })] })) : (_jsx("div", { className: inputs, children: (operator === "between" ? [0, 1] : [0]).map((index) => (_jsx(Input, { size: "small", type: field.kind === "date" ? "date" : field.kind === "number" ? "number" : "text", "aria-label": operator === "between"
|
|
339
350
|
? index === 0
|
|
340
351
|
? labels.filters.from
|
|
341
352
|
: labels.filters.to
|
|
@@ -347,7 +358,7 @@ export function FilterValueEditor({ field, value, onChange, onBack, }) {
|
|
|
347
358
|
const next = [...values];
|
|
348
359
|
next[index] = event.target.value;
|
|
349
360
|
report(operator, next);
|
|
350
|
-
} }, index))) })), _jsx(
|
|
361
|
+
} }, index))) })), _jsx("div", { className: menuDivider, role: "separator" }), _jsxs("div", { className: editorFooter, children: [options
|
|
351
362
|
? `${labels.filters.selectedCount(picked)} · ${labels.filters.updatesAsYouPick}`
|
|
352
363
|
: labels.filters.updatesAsYouPick, _jsx(Button, { variant: "ghost", onClick: () => report(operator, []), children: labels.common.clear })] })] }));
|
|
353
364
|
}
|
|
@@ -23,7 +23,16 @@ export declare const checkMark: import("../styled-system/types/index.js").Recipe
|
|
|
23
23
|
};
|
|
24
24
|
};
|
|
25
25
|
}>;
|
|
26
|
+
/** What a check mark's element carries, so its filled face can draw the gradient edge. */
|
|
27
|
+
export declare const checkMarkEdge: {
|
|
28
|
+
readonly "data-ciridae-ui": "";
|
|
29
|
+
readonly "data-edge": "gradient";
|
|
30
|
+
};
|
|
26
31
|
export declare const checkIndicator: string;
|
|
32
|
+
/** The tick, or the dash of a mixed checkbox. */
|
|
33
|
+
export declare function CheckGlyph({ mixed }: {
|
|
34
|
+
mixed: boolean | undefined;
|
|
35
|
+
}): import("react").JSX.Element;
|
|
27
36
|
export declare function Checkbox({ children, className, wrapperClassName, ...props }: Omit<ComponentProps<typeof BaseCheckbox.Root>, "children" | "className"> & {
|
|
28
37
|
children?: ReactNode;
|
|
29
38
|
className?: string;
|
|
@@ -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
|
}
|
|
@@ -6,13 +6,17 @@ import type { ComponentProps, ReactNode } from "react";
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function Form({ className, ...props }: ComponentProps<"form">): import("react").JSX.Element;
|
|
8
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;
|
|
19
|
+
hint?: ReactNode;
|
|
16
20
|
}): import("react").JSX.Element;
|
|
17
21
|
export declare function FieldLabel({ children }: {
|
|
18
22
|
children: ReactNode;
|
|
@@ -28,5 +32,5 @@ export type SegmentedOptionProps = Omit<ButtonProps, "variant" | "type" | "aria-
|
|
|
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
|
|
35
|
+
/** One option of a `SegmentedControl`: the selected one is raised, the others bare. */
|
|
32
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
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
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
6
|
export declare function Input({ className, size, ...props }: InputProps): import("react").JSX.Element;
|
|
7
7
|
export type SearchInputProps = Omit<ComponentProps<"input">, "size" | "value" | "defaultValue"> & {
|
|
@@ -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("react").JSX.Element;
|
|
38
|
+
export declare function SearchField({ size: ownSize, onClear, quiet, shortcut, wrapperClassName, className, disabled, ...props }: SearchFieldProps): import("react").JSX.Element;
|