@tulipfarm/sprout 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -53
- package/dist/components/agent-avatar.d.ts +27 -0
- package/dist/components/agent-avatar.js +67 -0
- package/dist/components/alert-dialog.d.ts +2 -2
- package/dist/components/alert-dialog.js +4 -4
- package/dist/components/attachment.d.ts +1 -1
- package/dist/components/attachment.js +2 -2
- package/dist/components/avatar.d.ts +2 -10
- package/dist/components/avatar.js +3 -40
- package/dist/components/board.js +4 -4
- package/dist/components/button.d.ts +2 -2
- package/dist/components/button.js +13 -29
- package/dist/components/card.d.ts +1 -1
- package/dist/components/card.js +2 -2
- package/dist/components/chat-input.js +3 -3
- package/dist/components/chat-sources.js +1 -1
- package/dist/components/combobox.d.ts +10 -4
- package/dist/components/combobox.js +6 -5
- package/dist/components/form.js +1 -1
- package/dist/components/gradient-banner.d.ts +2 -2
- package/dist/components/gradient-banner.js +1 -1
- package/dist/components/input-group.d.ts +7 -7
- package/dist/components/input-group.js +7 -7
- package/dist/components/input-otp.d.ts +6 -2
- package/dist/components/input-otp.js +5 -3
- package/dist/components/input.d.ts +2 -2
- package/dist/components/input.js +2 -2
- package/dist/components/page-header.js +1 -1
- package/dist/components/pagination.js +2 -2
- package/dist/components/questionnaire.js +1 -1
- package/dist/components/record-list.d.ts +2 -2
- package/dist/components/record-list.js +2 -2
- package/dist/components/result-card.js +1 -1
- package/dist/components/rich-text-editor.d.ts +3 -3
- package/dist/components/rich-text-editor.js +3 -3
- package/dist/components/scroll-area.d.ts +2 -2
- package/dist/components/scroll-area.js +2 -2
- package/dist/components/search-field.js +1 -1
- package/dist/components/select.d.ts +2 -6
- package/dist/components/select.js +2 -2
- package/dist/components/spinner.d.ts +2 -2
- package/dist/components/spinner.js +2 -2
- package/dist/components/state-panel-samples.js +13 -13
- package/dist/components/state-sample.d.ts +1 -1
- package/dist/components/state-sample.js +2 -2
- package/dist/components/switch.d.ts +2 -2
- package/dist/components/switch.js +2 -2
- package/dist/components/table.js +1 -1
- package/dist/components/toggle-group.d.ts +2 -2
- package/dist/components/toggle-group.js +3 -3
- package/dist/components/toggle.d.ts +2 -2
- package/dist/components/toggle.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/internal/agent-avatar-artwork.d.ts +4 -0
- package/dist/internal/agent-avatar-artwork.js +219 -0
- package/dist/internal/hash.d.ts +1 -0
- package/dist/internal/hash.js +9 -0
- package/dist/styles/alert-dialog.css +6 -6
- package/dist/styles/attachment.css +13 -13
- package/dist/styles/avatar.css +2 -14
- package/dist/styles/button-group.css +1 -1
- package/dist/styles/button.css +29 -154
- package/dist/styles/chat-sources.css +1 -0
- package/dist/styles/combobox.css +13 -2
- package/dist/styles/command.css +3 -1
- package/dist/styles/context-menu.css +2 -0
- package/dist/styles/dropdown-menu.css +2 -0
- package/dist/styles/gradient-banner.css +0 -5
- package/dist/styles/index.css +5 -4
- package/dist/styles/input-group.css +36 -28
- package/dist/styles/input-otp.css +13 -3
- package/dist/styles/input.css +14 -6
- package/dist/styles/menubar.css +4 -2
- package/dist/styles/navigation-menu.css +1 -1
- package/dist/styles/page-header.css +4 -0
- package/dist/styles/pagination.css +11 -2
- package/dist/styles/record-list.css +1 -1
- package/dist/styles/result-card.css +1 -1
- package/dist/styles/rich-text-editor.css +3 -3
- package/dist/styles/select.css +8 -12
- package/dist/styles/sidebar.css +15 -13
- package/dist/styles/state-sample.css +2 -2
- package/dist/styles/table.css +11 -4
- package/dist/styles/tabs.css +1 -3
- package/dist/styles/toggle-group.css +6 -6
- package/dist/styles/toggle.css +6 -6
- package/dist/styles/view-switcher.css +20 -2
- package/package.json +5 -1
|
@@ -200,7 +200,7 @@ function ModelMark({ model }) {
|
|
|
200
200
|
function OptionPicker({ label, search, options, value, onChange, disabled, icon, align, }) {
|
|
201
201
|
const [open, setOpen] = useState(false);
|
|
202
202
|
const selected = options.find(option => option.id === value);
|
|
203
|
-
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(InputGroupButton, {
|
|
203
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(InputGroupButton, { "aria-label": `${label}: ${selected?.label ?? 'None'}`, disabled: disabled, className: "sprout-chat-input-picker" }), children: [icon(selected), _jsx("span", { className: "sprout-chat-input-picker-label", children: selected?.label ?? label }), _jsx(ChevronDown, { size: 12, "aria-hidden": "true" })] }), _jsx(PopoverContent, { size: "picker", side: "top", align: align, sideOffset: 8, className: "sprout-chat-input-menu", children: _jsxs(Command, { children: [_jsx(CommandInput, { "aria-label": search, placeholder: `${search}…` }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No matches." }), _jsx(CommandGroup, { heading: label, children: options.map(option => (_jsxs(CommandItem, { value: `${option.label} ${option.description ?? ''}`, "data-checked": option.id === value, disabled: 'disabled' in option && !!option.disabled, onSelect: () => {
|
|
204
204
|
onChange(option.id);
|
|
205
205
|
setOpen(false);
|
|
206
206
|
}, children: [icon(option), _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] })] }) })] }));
|
|
@@ -262,11 +262,11 @@ export function ChatInput({ value, onValueChange, onSend, onStop, status = 'idle
|
|
|
262
262
|
: undefined, className: cn('sprout-chat-input', className), children: [_jsxs("form", { ref: form, "aria-label": label, className: "sprout-chat-input-form", onSubmit: event => {
|
|
263
263
|
event.preventDefault();
|
|
264
264
|
send();
|
|
265
|
-
}, children: [_jsxs(InputGroup, { variant: "composer", className: "sprout-chat-input-box", children: [attachments.length > 0 && (_jsx(InputGroupAddon, { align: "block-start", className: "sprout-chat-input-attachments", children: attachments.map(file => (_jsx(FileAttachment, { file: file, variant: "chip", viewable: true, preview: true, onRemove: onRemoveAttachment && !disabled ? () => onRemoveAttachment(file.id) : undefined }, file.id))) })), _jsx(RichTextEditor, { ref: editor, value: value, onChange: onValueChange, onSend: send, extensions: extensions, placeholder: streaming ? streamingPlaceholder : placeholder, disabled: disabled, ariaLabel: label, ariaExpanded: !!panel, ariaControls: panel ? listId : undefined, ariaActiveDescendant: panel?.items.length ? optionId(panel.active) : undefined, className: "sprout-chat-input-editor", toolbarAddon: _jsxs("div", { className: "sprout-chat-input-bar", children: [_jsxs("div", { className: "sprout-chat-input-bar-start", children: [attachActions && attachActions.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon
|
|
265
|
+
}, children: [_jsxs(InputGroup, { variant: "composer", className: "sprout-chat-input-box", children: [attachments.length > 0 && (_jsx(InputGroupAddon, { align: "block-start", className: "sprout-chat-input-attachments", children: attachments.map(file => (_jsx(FileAttachment, { file: file, variant: "chip", viewable: true, preview: true, onRemove: onRemoveAttachment && !disabled ? () => onRemoveAttachment(file.id) : undefined }, file.id))) })), _jsx(RichTextEditor, { ref: editor, value: value, onChange: onValueChange, onSend: send, extensions: extensions, placeholder: streaming ? streamingPlaceholder : placeholder, disabled: disabled, ariaLabel: label, ariaExpanded: !!panel, ariaControls: panel ? listId : undefined, ariaActiveDescendant: panel?.items.length ? optionId(panel.active) : undefined, className: "sprout-chat-input-editor", toolbarAddon: _jsxs("div", { className: "sprout-chat-input-bar", children: [_jsxs("div", { className: "sprout-chat-input-bar-start", children: [attachActions && attachActions.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon", "aria-label": "Add files and more", disabled: disabled }) }), children: _jsx(Plus, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Add files and more" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Add" }), attachActions.map(action => (_jsxs(DropdownMenuItem, { onClick: action.onSelect, children: [action.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: action.label }), action.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: action.description }))] })] }, action.id)))] }) })] })), modes && modes.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon", "aria-label": `Mode: ${activeMode?.label ?? 'Default'}`, disabled: disabled }) }), children: _jsx(Sliders, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Modes" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Mode" }), _jsx(DropdownMenuRadioGroup, { value: mode ?? '', onValueChange: next => onModeChange?.(next === mode || !next ? null : String(next)), children: modes.map(option => (_jsxs(DropdownMenuRadioItem, { value: option.id, closeOnClick: true, style: option.color
|
|
266
266
|
? {
|
|
267
267
|
'--sprout-chat-input-mode': option.color,
|
|
268
268
|
}
|
|
269
|
-
: undefined, className: option.color ? 'sprout-chat-input-mode-option' : undefined, children: [option.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] }) })] })), activeMode && (_jsxs(InputGroupButton, {
|
|
269
|
+
: undefined, className: option.color ? 'sprout-chat-input-mode-option' : undefined, children: [option.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] }) })] })), activeMode && (_jsxs(InputGroupButton, { variant: "secondary", className: "sprout-chat-input-mode", "aria-label": `Turn off ${activeMode.label}`, disabled: disabled, onClick: () => onModeChange?.(null), children: [activeMode.icon, _jsx("span", { className: "sprout-chat-input-picker-label", children: activeMode.label }), _jsx(X, { size: 12, "aria-hidden": "true" })] })), projects && projects.length > 0 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "sprout-chat-input-divider", "aria-hidden": "true" }), _jsx(OptionPicker, { label: "Project", search: "Search projects", options: projects, value: project, onChange: id => onProjectChange?.(id), disabled: disabled, icon: option => option?.icon ?? _jsx(Folder, { size: 16, "aria-hidden": "true" }), align: "start" })] }))] }), _jsxs("div", { className: "sprout-chat-input-bar-end", children: [models && models.length > 0 && (_jsx(OptionPicker, { label: "Model", search: "Search models", options: models, value: model, onChange: id => onModelChange?.(id), disabled: disabled, icon: option => option && _jsx(ModelMark, { model: option }), align: "end" })), streaming ? (_jsx(InputGroupButton, { size: "icon", variant: "default", className: "sprout-chat-input-send", "aria-label": "Stop", onClick: onStop, children: _jsx("span", { className: "sprout-chat-input-stop", "aria-hidden": "true" }) })) : (_jsx(InputGroupButton, { type: "submit", size: "icon", variant: canSend ? 'default' : 'secondary', className: "sprout-chat-input-send", "aria-label": "Send message", disabled: !canSend, children: _jsx(ArrowUp, { size: 16, "aria-hidden": "true" }) }))] })] }) })] }), panel && (_jsx("div", { className: "sprout-chat-input-panel", "data-side": panelBelow ? 'bottom' : 'top', children: _jsx(MentionList, { id: listId, label: triggers[panel.kind].label, announcement: panel.items.length
|
|
270
270
|
? `${panel.items.length} ${triggers[panel.kind].label.toLowerCase()}. Use Up and Down to choose, Enter to add, Escape to close.`
|
|
271
271
|
: triggers[panel.kind].empty, status: panel.items.length ? undefined : (_jsx(MentionStatus, { tone: "empty", children: triggers[panel.kind].empty })), children: panel.items.map((item, index) => (_jsx(MentionOption, { id: optionId(index), active: index === panel.active, onSelect: () => panel.select(index), media: item.media, title: item.label, description: item.description }, item.id))) }) }))] }), prompts && prompts.length > 0 && !filled && !streaming && (_jsx("div", { role: "group", "aria-label": "Suggested prompts", className: "sprout-chat-input-prompts", children: prompts.map(prompt => (_jsxs(Button, { size: "sm", variant: "outline", disabled: disabled, className: "sprout-chat-input-prompt", onClick: () => fill(prompt), children: [prompt.icon, prompt.label] }, prompt.id))) }))] }));
|
|
272
272
|
}
|
|
@@ -58,7 +58,7 @@ export function CheckedCitation({ label, state, onOpen, onRetry }) {
|
|
|
58
58
|
// opened by click or keyboard closes only by click, Escape, or outside press.
|
|
59
59
|
if (details.reason === 'trigger-hover' && openReason.current === 'trigger-press')
|
|
60
60
|
details.cancel();
|
|
61
|
-
}, children: [_jsx(PopoverTrigger, { openOnHover: true, delay: hoverDelay, closeDelay: hoverCloseDelay, "data-slot": "checked-citation", className: "sprout-chat-sources-checked", render: _jsx(Button, { variant: "link",
|
|
61
|
+
}, children: [_jsx(PopoverTrigger, { openOnHover: true, delay: hoverDelay, closeDelay: hoverCloseDelay, "data-slot": "checked-citation", className: "sprout-chat-sources-checked", render: _jsx(Button, { variant: "link", "aria-label": `Source: ${label}` }), children: label }), _jsx(PopoverContent, { ref: popup, "data-citation-state": state.kind, className: "sprout-chat-sources-preview", children: state.kind === 'idle' || state.kind === 'loading' ? (_jsxs("p", { role: "status", className: "sprout-chat-sources-checking", children: [_jsx(Spinner, { "aria-hidden": "true" }), "Checking access to this source\u2026"] })) : state.kind === 'ready' ? (_jsxs("div", { "data-slot": "chat-source", className: "sprout-chat-sources-source", children: [_jsx("p", { className: "sprout-chat-sources-title", children: state.title }), _jsx("p", { className: "sprout-chat-sources-location", children: state.location }), _jsx("p", { className: "sprout-chat-sources-excerpt", "data-preserve-lines": "", children: state.excerpt })] })) : (_jsxs("div", { className: "sprout-chat-sources-source", children: [_jsx("p", { className: "sprout-chat-sources-title", children: state.kind === 'unavailable' ? 'Source unavailable' : 'Couldn’t load this source' }), _jsx("p", { role: "alert", className: "sprout-chat-sources-excerpt", children: state.message }), state.kind === 'error' && (_jsx(Button, { variant: "outline", size: "sm", className: "sprout-chat-sources-retry", onClick: () => {
|
|
62
62
|
// The button leaves as loading starts; keep focus in the passage.
|
|
63
63
|
popup.current?.focus();
|
|
64
64
|
onRetry();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Combobox as ComboboxPrimitive } from '@base-ui/react/combobox';
|
|
2
|
+
import { type InputGroupSize } from './input-group.js';
|
|
2
3
|
export type ComboboxProps<Value, Multiple extends boolean | undefined = false> = ComboboxPrimitive.Root.Props<Value, Multiple>;
|
|
3
4
|
/**
|
|
4
5
|
* Holds the value, the typed query, and the open state. It takes every Base
|
|
@@ -22,9 +23,11 @@ export type ComboboxTriggerProps = ComboboxPrimitive.Trigger.Props;
|
|
|
22
23
|
* its search field inside the list.
|
|
23
24
|
*/
|
|
24
25
|
export declare function ComboboxTrigger({ className, children, ...props }: ComboboxTriggerProps): import("react").JSX.Element;
|
|
25
|
-
export interface ComboboxInputProps extends Omit<ComboboxPrimitive.Input.Props, 'className'> {
|
|
26
|
+
export interface ComboboxInputProps extends Omit<ComboboxPrimitive.Input.Props, 'className' | 'size'> {
|
|
26
27
|
/** Classes for the surrounding `InputGroup`. */
|
|
27
28
|
className?: string;
|
|
29
|
+
/** `sm` is 28px, `md` is 32px (`--sprout-control-height`), and `lg` is 36px. */
|
|
30
|
+
size?: InputGroupSize | null;
|
|
28
31
|
/** Shows the chevron button that opens the list. On by default. */
|
|
29
32
|
showTrigger?: boolean;
|
|
30
33
|
/**
|
|
@@ -39,7 +42,7 @@ export interface ComboboxInputProps extends Omit<ComboboxPrimitive.Input.Props,
|
|
|
39
42
|
* goes on the group; children are added after the addon, for example an
|
|
40
43
|
* inline-start `InputGroupAddon` with an icon.
|
|
41
44
|
*/
|
|
42
|
-
export declare function ComboboxInput({ className, children, disabled, showTrigger, showClear, ...props }: ComboboxInputProps): import("react").JSX.Element;
|
|
45
|
+
export declare function ComboboxInput({ className, children, disabled, showTrigger, showClear, size, ...props }: ComboboxInputProps): import("react").JSX.Element;
|
|
43
46
|
type PositionerProps = Pick<ComboboxPrimitive.Positioner.Props, 'side' | 'align' | 'sideOffset' | 'alignOffset' | 'anchor'>;
|
|
44
47
|
export interface ComboboxContentProps extends ComboboxPrimitive.Popup.Props, PositionerProps {
|
|
45
48
|
}
|
|
@@ -74,13 +77,16 @@ export type ComboboxEmptyProps = ComboboxPrimitive.Empty.Props;
|
|
|
74
77
|
export declare function ComboboxEmpty({ className, ...props }: ComboboxEmptyProps): import("react").JSX.Element;
|
|
75
78
|
export type ComboboxSeparatorProps = ComboboxPrimitive.Separator.Props;
|
|
76
79
|
export declare function ComboboxSeparator({ className, ...props }: ComboboxSeparatorProps): import("react").JSX.Element;
|
|
77
|
-
export
|
|
80
|
+
export interface ComboboxChipsProps extends ComboboxPrimitive.Chips.Props {
|
|
81
|
+
/** `sm` is 28px, `md` is 32px (`--sprout-control-height`), and `lg` is 36px. It is a minimum: chips wrap onto more rows. */
|
|
82
|
+
size?: InputGroupSize | null;
|
|
83
|
+
}
|
|
78
84
|
/**
|
|
79
85
|
* The bordered field for `multiple` comboboxes. Put a `ComboboxValue` that
|
|
80
86
|
* renders `ComboboxChip`s and a `ComboboxChipsInput` inside it. Arrow left
|
|
81
87
|
* and right move between chips; Backspace removes one.
|
|
82
88
|
*/
|
|
83
|
-
export declare function ComboboxChips({ className, ...props }: ComboboxChipsProps): import("react").JSX.Element;
|
|
89
|
+
export declare function ComboboxChips({ className, size, ...props }: ComboboxChipsProps): import("react").JSX.Element;
|
|
84
90
|
export interface ComboboxChipProps extends ComboboxPrimitive.Chip.Props {
|
|
85
91
|
/** Shows the × button that removes the chip. On by default. */
|
|
86
92
|
showRemove?: boolean;
|
|
@@ -33,7 +33,7 @@ export function ComboboxTrigger({ className, children, ...props }) {
|
|
|
33
33
|
return (_jsxs(ComboboxPrimitive.Trigger, { "data-slot": "combobox-trigger", "aria-label": children == null ? 'Show options' : undefined, ...props, className: stateClassName('sprout-combobox-trigger', className), children: [children, _jsx(ChevronDown, { "aria-hidden": "true", className: "sprout-combobox-trigger-icon" })] }));
|
|
34
34
|
}
|
|
35
35
|
function ComboboxClear({ className, ...props }) {
|
|
36
|
-
return (_jsx(ComboboxPrimitive.Clear, { "data-slot": "combobox-clear", "aria-label": "Clear selection", render: _jsx(InputGroupButton, { variant: "ghost", size: "icon
|
|
36
|
+
return (_jsx(ComboboxPrimitive.Clear, { "data-slot": "combobox-clear", "aria-label": "Clear selection", render: _jsx(InputGroupButton, { variant: "ghost", size: "icon" }), ...props, className: stateClassName('sprout-combobox-clear', className), children: _jsx(X, { "aria-hidden": "true" }) }));
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
39
|
* A search field in a Sprout `InputGroup`. Typing filters the list; the
|
|
@@ -41,8 +41,8 @@ function ComboboxClear({ className, ...props }) {
|
|
|
41
41
|
* goes on the group; children are added after the addon, for example an
|
|
42
42
|
* inline-start `InputGroupAddon` with an icon.
|
|
43
43
|
*/
|
|
44
|
-
export function ComboboxInput({ className, children, disabled = false, showTrigger = true, showClear = false, ...props }) {
|
|
45
|
-
return (_jsxs(InputGroup, { className: cn('sprout-combobox-input-group', className), children: [_jsx(ComboboxPrimitive.Input, { render: _jsx(InputGroupInput, {}), disabled: disabled, ...props }), _jsxs(InputGroupAddon, { align: "inline-end", children: [showTrigger && (_jsx(InputGroupButton, { size: "icon
|
|
44
|
+
export function ComboboxInput({ className, children, disabled = false, showTrigger = true, showClear = false, size, ...props }) {
|
|
45
|
+
return (_jsxs(InputGroup, { size: size, className: cn('sprout-combobox-input-group', className), children: [_jsx(ComboboxPrimitive.Input, { render: _jsx(InputGroupInput, {}), disabled: disabled, ...props }), _jsxs(InputGroupAddon, { align: "inline-end", children: [showTrigger && (_jsx(InputGroupButton, { size: "icon", variant: "ghost", render: _jsx(ComboboxTrigger, {}), "data-slot": "input-group-button", className: "sprout-combobox-input-trigger", disabled: disabled })), showClear && _jsx(ComboboxClear, { disabled: disabled })] }), children] }));
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* The list surface. It renders its own portal and positioner, opens below
|
|
@@ -89,8 +89,9 @@ export function ComboboxSeparator({ className, ...props }) {
|
|
|
89
89
|
* renders `ComboboxChip`s and a `ComboboxChipsInput` inside it. Arrow left
|
|
90
90
|
* and right move between chips; Backspace removes one.
|
|
91
91
|
*/
|
|
92
|
-
export function ComboboxChips({ className, ...props }) {
|
|
93
|
-
|
|
92
|
+
export function ComboboxChips({ className, size, ...props }) {
|
|
93
|
+
const scale = size ?? 'md';
|
|
94
|
+
return (_jsx(ComboboxPrimitive.Chips, { "data-slot": "combobox-chips", "data-size": scale, ...props, className: stateClassName(cn('sprout-combobox-chips', `sprout-combobox-chips-size-${scale}`), className) }));
|
|
94
95
|
}
|
|
95
96
|
/** One chosen value inside `ComboboxChips`. */
|
|
96
97
|
export function ComboboxChip({ className, children, showRemove = true, ...props }) {
|
package/dist/components/form.js
CHANGED
|
@@ -41,7 +41,7 @@ export function FormFooter({ form, summary, submit, secondarySubmit, dirty, canc
|
|
|
41
41
|
const action = useActionControl(submit.state);
|
|
42
42
|
const stack = layout === 'stack';
|
|
43
43
|
const compact = layout === 'compact';
|
|
44
|
-
const size = stack ? 'lg' : '
|
|
44
|
+
const size = stack ? 'lg' : 'md';
|
|
45
45
|
const wide = stack ? 'sprout-form-footer-wide' : undefined;
|
|
46
46
|
const save = (_jsx(Button, { type: "submit", form: form, size: size, className: wide, ...action.button, children: submit.state.kind === 'busy' ? submit.pendingLabel : submit.label }));
|
|
47
47
|
const secondary = secondarySubmit && (_jsx(Button, { type: "submit", form: form, size: size, variant: "outline", className: wide, disabled: secondarySubmit.disabled, onClick: secondarySubmit.onSelect, children: secondarySubmit.label }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ComponentProps } from 'react';
|
|
2
2
|
export declare const gradientBannerVariantNames: readonly ["aurora", "citrus", "lagoon", "iris", "cobalt", "mint"];
|
|
3
|
-
export declare const gradientBannerSizeNames: readonly ["sm", "md", "lg"
|
|
3
|
+
export declare const gradientBannerSizeNames: readonly ["sm", "md", "lg"];
|
|
4
4
|
export declare const gradientBannerPanelToneNames: readonly ["light", "dark"];
|
|
5
5
|
export type GradientBannerVariant = (typeof gradientBannerVariantNames)[number];
|
|
6
6
|
export type GradientBannerSize = (typeof gradientBannerSizeNames)[number];
|
|
@@ -8,7 +8,7 @@ export type GradientBannerPanelTone = (typeof gradientBannerPanelToneNames)[numb
|
|
|
8
8
|
export interface GradientBannerProps extends ComponentProps<'div'> {
|
|
9
9
|
/** Color story of the art. Defaults to `"aurora"`. */
|
|
10
10
|
variant?: GradientBannerVariant | undefined;
|
|
11
|
-
/** `sm` 96px, `md` 160px, `lg` 240px (default)
|
|
11
|
+
/** `sm` 96px, `md` 160px, `lg` 240px (default) minimum height. */
|
|
12
12
|
size?: GradientBannerSize | undefined;
|
|
13
13
|
/** Film grain over the art. Defaults to `true`. */
|
|
14
14
|
texture?: boolean | undefined;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Children, useId } from 'react';
|
|
3
3
|
import { cn } from '../internal/classes.js';
|
|
4
4
|
export const gradientBannerVariantNames = ['aurora', 'citrus', 'lagoon', 'iris', 'cobalt', 'mint'];
|
|
5
|
-
export const gradientBannerSizeNames = ['sm', 'md', 'lg'
|
|
5
|
+
export const gradientBannerSizeNames = ['sm', 'md', 'lg'];
|
|
6
6
|
export const gradientBannerPanelToneNames = ['light', 'dark'];
|
|
7
7
|
/**
|
|
8
8
|
* Decorative gradient art with centered content on top. The art is hidden from
|
|
@@ -2,16 +2,16 @@ import type { ComponentProps } from 'react';
|
|
|
2
2
|
import { type ButtonProps } from './button.js';
|
|
3
3
|
import { type InputProps } from './input.js';
|
|
4
4
|
import { type TextareaProps } from './textarea.js';
|
|
5
|
-
export declare const inputGroupSizeNames: readonly ["
|
|
5
|
+
export declare const inputGroupSizeNames: readonly ["md", "sm", "lg"];
|
|
6
6
|
export declare const inputGroupVariantNames: readonly ["default", "composer", "question-composer"];
|
|
7
7
|
export declare const inputGroupAddonAlignNames: readonly ["inline-start", "inline-end", "block-start", "block-end"];
|
|
8
|
-
export declare const inputGroupButtonSizeNames: readonly ["
|
|
8
|
+
export declare const inputGroupButtonSizeNames: readonly ["md", "icon"];
|
|
9
9
|
export type InputGroupSize = (typeof inputGroupSizeNames)[number];
|
|
10
10
|
export type InputGroupVariant = (typeof inputGroupVariantNames)[number];
|
|
11
11
|
export type InputGroupAddonAlign = (typeof inputGroupAddonAlignNames)[number];
|
|
12
12
|
export type InputGroupButtonSize = (typeof inputGroupButtonSizeNames)[number];
|
|
13
13
|
export interface InputGroupProps extends ComponentProps<'div'> {
|
|
14
|
-
/** `
|
|
14
|
+
/** `sm` is 28px, `md` is 32px (`--sprout-control-height`), and `lg` is 36px. */
|
|
15
15
|
size?: InputGroupSize | null;
|
|
16
16
|
/**
|
|
17
17
|
* `default` is a single field row. `composer` stacks a message box with
|
|
@@ -39,14 +39,14 @@ export interface InputGroupAddonProps extends ComponentProps<'div'> {
|
|
|
39
39
|
*/
|
|
40
40
|
export declare function InputGroupAddon({ align, className, onClick, ...props }: InputGroupAddonProps): import("react").JSX.Element;
|
|
41
41
|
export interface InputGroupButtonProps extends Omit<ButtonProps, 'size' | 'type'> {
|
|
42
|
-
/** `
|
|
42
|
+
/** `md` fits a label; `icon` is square. Both follow the group height. */
|
|
43
43
|
size?: InputGroupButtonSize | null;
|
|
44
44
|
type?: 'button' | 'submit' | 'reset';
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* A compact Sprout `Button` sized to sit inside an `InputGroup` addon.
|
|
48
|
-
*
|
|
49
|
-
* submits a form by accident. Use `render` to make it a menu, popover, or
|
|
47
|
+
* A compact Sprout `Button` sized to sit inside an `InputGroup` addon. Its
|
|
48
|
+
* height follows the group, 4px in from each edge. It is `ghost` and a plain
|
|
49
|
+
* `type="button"` by default, so it never submits a form by accident. Use `render` to make it a menu, popover, or
|
|
50
50
|
* combobox trigger.
|
|
51
51
|
*/
|
|
52
52
|
export declare function InputGroupButton({ size, variant, type, className, ...props }: InputGroupButtonProps): import("react").JSX.Element;
|
|
@@ -4,10 +4,10 @@ import { cn } from '../internal/classes.js';
|
|
|
4
4
|
import { Button } from './button.js';
|
|
5
5
|
import { Input } from './input.js';
|
|
6
6
|
import { Textarea } from './textarea.js';
|
|
7
|
-
export const inputGroupSizeNames = ['
|
|
7
|
+
export const inputGroupSizeNames = ['md', 'sm', 'lg'];
|
|
8
8
|
export const inputGroupVariantNames = ['default', 'composer', 'question-composer'];
|
|
9
9
|
export const inputGroupAddonAlignNames = ['inline-start', 'inline-end', 'block-start', 'block-end'];
|
|
10
|
-
export const inputGroupButtonSizeNames = ['
|
|
10
|
+
export const inputGroupButtonSizeNames = ['md', 'icon'];
|
|
11
11
|
/**
|
|
12
12
|
* One bordered field made of a control and its additions: icons, text,
|
|
13
13
|
* shortcuts, and buttons. The group draws the border, fill, focus ring, and
|
|
@@ -16,7 +16,7 @@ export const inputGroupButtonSizeNames = ['xs', 'sm', 'icon-xs', 'icon-sm'];
|
|
|
16
16
|
* `InputGroupTextarea`, or a rich text editor, drives those states.
|
|
17
17
|
*/
|
|
18
18
|
export function InputGroup({ size, variant, className, ...props }) {
|
|
19
|
-
const scale = size ?? '
|
|
19
|
+
const scale = size ?? 'md';
|
|
20
20
|
const kind = variant ?? 'default';
|
|
21
21
|
return (_jsx("div", { "data-slot": "input-group", role: "group", "data-size": scale, "data-variant": kind, ...props, className: cn('sprout-input-group', `sprout-input-group-size-${scale}`, `sprout-input-group-variant-${kind}`, className) }));
|
|
22
22
|
}
|
|
@@ -43,13 +43,13 @@ export function InputGroupAddon({ align, className, onClick, ...props }) {
|
|
|
43
43
|
return (_jsx("div", { role: "group", "data-slot": "input-group-addon", "data-align": side, ...props, onClick: focusControl, className: cn('sprout-input-group-addon', `sprout-input-group-addon-align-${side}`, className) }));
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
46
|
-
* A compact Sprout `Button` sized to sit inside an `InputGroup` addon.
|
|
47
|
-
*
|
|
48
|
-
* submits a form by accident. Use `render` to make it a menu, popover, or
|
|
46
|
+
* A compact Sprout `Button` sized to sit inside an `InputGroup` addon. Its
|
|
47
|
+
* height follows the group, 4px in from each edge. It is `ghost` and a plain
|
|
48
|
+
* `type="button"` by default, so it never submits a form by accident. Use `render` to make it a menu, popover, or
|
|
49
49
|
* combobox trigger.
|
|
50
50
|
*/
|
|
51
51
|
export function InputGroupButton({ size, variant, type = 'button', className, ...props }) {
|
|
52
|
-
const scale = size ?? '
|
|
52
|
+
const scale = size ?? 'md';
|
|
53
53
|
const kind = variant ?? 'ghost';
|
|
54
54
|
return (_jsx(Button, { type: type, variant: kind, "data-size": scale, "data-variant": kind, ...props, className: state => cn('sprout-input-group-button', `sprout-input-group-button-size-${scale}`, typeof className === 'function' ? className(state) : className) }));
|
|
55
55
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
2
|
import { OTPField } from '@base-ui/react/otp-field';
|
|
3
|
+
export declare const inputOTPSizeNames: readonly ["md", "sm", "lg"];
|
|
4
|
+
export type InputOTPSize = (typeof inputOTPSizeNames)[number];
|
|
3
5
|
export type InputOTPState = OTPField.Root.State;
|
|
4
6
|
export type InputOTPSlotState = OTPField.Input.State;
|
|
5
7
|
type Invalid = boolean | 'true' | 'false' | 'grammar' | 'spelling';
|
|
6
|
-
export interface InputOTPProps extends Omit<OTPField.Root.Props, 'length' | 'aria-invalid' | 'children'> {
|
|
8
|
+
export interface InputOTPProps extends Omit<OTPField.Root.Props, 'length' | 'aria-invalid' | 'children' | 'size'> {
|
|
7
9
|
/** Number of character slots. Matches the slot indexes you render. */
|
|
8
10
|
maxLength: number;
|
|
11
|
+
/** Square slots: `sm` is 28px, `md` is 32px (`--sprout-control-height`), and `lg` is 36px. */
|
|
12
|
+
size?: InputOTPSize | null;
|
|
9
13
|
/** Called with the new code on every edit, paste, or autofill. */
|
|
10
14
|
onChange?: ((value: string) => void) | undefined;
|
|
11
15
|
/** Marks every slot invalid and draws the danger ring on its group. */
|
|
@@ -18,7 +22,7 @@ export interface InputOTPProps extends Omit<OTPField.Root.Props, 'length' | 'ari
|
|
|
18
22
|
* End, Backspace, and Delete all work. `aria-label` names the whole code and
|
|
19
23
|
* its first slot; later slots are announced as "Character 2 of 6".
|
|
20
24
|
*/
|
|
21
|
-
export declare function InputOTP({ maxLength, onChange, onValueChange, className, children, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-invalid': ariaInvalid, validationType, ...props }: InputOTPProps): import("react").JSX.Element;
|
|
25
|
+
export declare function InputOTP({ maxLength, size, onChange, onValueChange, className, children, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-invalid': ariaInvalid, validationType, ...props }: InputOTPProps): import("react").JSX.Element;
|
|
22
26
|
export type InputOTPGroupProps = ComponentProps<'div'>;
|
|
23
27
|
/** Joins adjacent slots into one bordered segment. */
|
|
24
28
|
export declare function InputOTPGroup({ className, ...props }: InputOTPGroupProps): import("react").JSX.Element;
|
|
@@ -4,6 +4,7 @@ import { createContext, useContext, useId } from 'react';
|
|
|
4
4
|
import { OTPField } from '@base-ui/react/otp-field';
|
|
5
5
|
import { Minus } from 'reicon-react/icons/Minus';
|
|
6
6
|
import { cn, stateClassName } from '../internal/classes.js';
|
|
7
|
+
export const inputOTPSizeNames = ['md', 'sm', 'lg'];
|
|
7
8
|
const InputOTPContext = createContext(null);
|
|
8
9
|
const isInvalid = (value) => value === true || value === 'true';
|
|
9
10
|
/**
|
|
@@ -12,14 +13,15 @@ const isInvalid = (value) => value === true || value === 'true';
|
|
|
12
13
|
* End, Backspace, and Delete all work. `aria-label` names the whole code and
|
|
13
14
|
* its first slot; later slots are announced as "Character 2 of 6".
|
|
14
15
|
*/
|
|
15
|
-
export function InputOTP({ maxLength, onChange, onValueChange, className, children, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-invalid': ariaInvalid, validationType = 'numeric', ...props }) {
|
|
16
|
+
export function InputOTP({ maxLength, size, onChange, onValueChange, className, children, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-invalid': ariaInvalid, validationType = 'numeric', ...props }) {
|
|
16
17
|
const generated = useId();
|
|
17
18
|
const labelId = ariaLabelledBy ?? (ariaLabel ? `${generated}-label` : undefined);
|
|
18
19
|
const invalid = isInvalid(ariaInvalid);
|
|
19
|
-
|
|
20
|
+
const scale = size ?? 'md';
|
|
21
|
+
return (_jsx(InputOTPContext.Provider, { value: { length: maxLength, labelId, invalid }, children: _jsxs(OTPField.Root, { "data-slot": "input-otp", "data-size": scale, "data-invalid": invalid ? '' : undefined, length: maxLength, validationType: validationType, "aria-labelledby": labelId, onValueChange: (value, details) => {
|
|
20
22
|
onValueChange?.(value, details);
|
|
21
23
|
onChange?.(value);
|
|
22
|
-
}, ...props, className: stateClassName('sprout-input-otp', className), children: [ariaLabel && !ariaLabelledBy ? (_jsx("span", { id: labelId, className: "sprout-input-otp-sr-only", children: ariaLabel })) : null, children] }) }));
|
|
24
|
+
}, ...props, className: stateClassName(cn('sprout-input-otp', `sprout-input-otp-size-${scale}`), className), children: [ariaLabel && !ariaLabelledBy ? (_jsx("span", { id: labelId, className: "sprout-input-otp-sr-only", children: ariaLabel })) : null, children] }) }));
|
|
23
25
|
}
|
|
24
26
|
/** Joins adjacent slots into one bordered segment. */
|
|
25
27
|
export function InputOTPGroup({ className, ...props }) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Input as BaseInput } from '@base-ui/react/input';
|
|
2
|
-
export declare const inputScaleNames: readonly ["
|
|
2
|
+
export declare const inputScaleNames: readonly ["md", "sm", "lg"];
|
|
3
3
|
export type InputScale = (typeof inputScaleNames)[number];
|
|
4
4
|
export type InputState = BaseInput.State;
|
|
5
5
|
export interface InputProps extends BaseInput.Props {
|
|
6
|
-
/** `
|
|
6
|
+
/** `sm` is 28px, `md` is 32px (`--sprout-control-height`), and `lg` is 36px. */
|
|
7
7
|
scale?: InputScale | null;
|
|
8
8
|
}
|
|
9
9
|
/**
|
package/dist/components/input.js
CHANGED
|
@@ -3,7 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { Input as BaseInput } from '@base-ui/react/input';
|
|
4
4
|
import { cn, stateClassName } from '../internal/classes.js';
|
|
5
5
|
import { useFieldControl } from './field.js';
|
|
6
|
-
export const inputScaleNames = ['
|
|
6
|
+
export const inputScaleNames = ['md', 'sm', 'lg'];
|
|
7
7
|
/**
|
|
8
8
|
* A single-line text field on Base UI `Input`. It takes every native input
|
|
9
9
|
* prop, such as `type`, `value`, `required`, and `ref`. Inside a Base UI
|
|
@@ -13,6 +13,6 @@ export const inputScaleNames = ['default', 'lg'];
|
|
|
13
13
|
*/
|
|
14
14
|
export function Input({ scale, className, ...rest }) {
|
|
15
15
|
const props = useFieldControl(rest);
|
|
16
|
-
const size = scale ?? '
|
|
16
|
+
const size = scale ?? 'md';
|
|
17
17
|
return (_jsx(BaseInput, { "data-slot": "input", "data-scale": size, ...props, className: stateClassName(cn('sprout-input', `sprout-input-scale-${size}`), className) }));
|
|
18
18
|
}
|
|
@@ -39,7 +39,7 @@ export function PageHeader({ title, description, actions, back, parent, titleId,
|
|
|
39
39
|
const placement = inChrome ? 'chrome' : 'page';
|
|
40
40
|
const heading = (_jsx("h1", { id: titleId, ref: titleRef, tabIndex: focusable ? -1 : undefined, "data-slot": "page-title", "data-placement": placement, className: "sprout-page-header-title", children: title }));
|
|
41
41
|
const trail = parent && (_jsx("nav", { "aria-label": "Breadcrumb", "data-slot": "page-breadcrumb", "data-placement": placement, className: "sprout-page-header-breadcrumb", children: _jsxs("ol", { className: "sprout-page-header-breadcrumb-list", children: [_jsx("li", { className: "sprout-page-header-breadcrumb-item", children: _jsx(ParentLink, { ...parent }) }), _jsx("li", { role: "presentation", "aria-hidden": "true", className: "sprout-page-header-breadcrumb-separator", children: _jsx(ChevronRight, { size: 14 }) }), _jsx("li", { "aria-current": "page", className: "sprout-page-header-breadcrumb-item sprout-page-header-breadcrumb-current", children: heading })] }) }));
|
|
42
|
-
const backButton = back && (_jsxs(Button, { variant: "ghost", size: "
|
|
42
|
+
const backButton = back && (_jsxs(Button, { variant: "ghost", size: "sm", nativeButton: false, render: back.link, "data-slot": "page-back", className: "sprout-page-header-back", children: [_jsx(ChevronLeft, { "data-icon": "inline-start", "aria-hidden": "true" }), _jsx("span", { className: "sprout-page-header-back-label", children: back.label })] }));
|
|
43
43
|
if (inChrome) {
|
|
44
44
|
return (_jsxs(_Fragment, { children: [createPortal(_jsxs(_Fragment, { children: [backButton, trail ?? heading] }), chrome.title), actions &&
|
|
45
45
|
createPortal(_jsx("div", { "data-slot": "page-actions", "data-placement": "chrome", className: "sprout-page-header-actions", children: actions }), chrome.actions), description && (_jsx("p", { "data-slot": "page-description", className: cn('sprout-page-header-description', className), children: description }))] }));
|
|
@@ -18,10 +18,10 @@ export function PaginationLink({ className, isActive, size = 'icon', render, ...
|
|
|
18
18
|
return (_jsx(Button, { variant: isActive ? 'outline' : 'ghost', size: size, nativeButton: false, render: render, ...props, "aria-current": isActive ? 'page' : undefined, "data-slot": "pagination-link", "data-active": isActive ? 'true' : undefined, className: cn('sprout-pagination-link', className) }));
|
|
19
19
|
}
|
|
20
20
|
export function PaginationPrevious({ className, text = 'Previous', ...props }) {
|
|
21
|
-
return (_jsxs(PaginationLink, { "aria-label": "Go to previous page", size: "
|
|
21
|
+
return (_jsxs(PaginationLink, { "aria-label": "Go to previous page", size: "md", className: cn('sprout-pagination-previous', className), ...props, children: [_jsx(ChevronLeft, { "data-icon": "inline-start", "aria-hidden": "true" }), _jsx("span", { className: "sprout-pagination-label", children: text })] }));
|
|
22
22
|
}
|
|
23
23
|
export function PaginationNext({ className, text = 'Next', ...props }) {
|
|
24
|
-
return (_jsxs(PaginationLink, { "aria-label": "Go to next page", size: "
|
|
24
|
+
return (_jsxs(PaginationLink, { "aria-label": "Go to next page", size: "md", className: cn('sprout-pagination-next', className), ...props, children: [_jsx("span", { className: "sprout-pagination-label", children: text }), _jsx(ChevronRight, { "data-icon": "inline-end", "aria-hidden": "true" })] }));
|
|
25
25
|
}
|
|
26
26
|
/** Marks skipped pages. It is hidden from screen readers. */
|
|
27
27
|
export function PaginationEllipsis({ className, ...props }) {
|
|
@@ -868,7 +868,7 @@ export function QuestionnaireError({ children, className, id, render, ...props }
|
|
|
868
868
|
export function QuestionnaireActions({ className, ...props }) {
|
|
869
869
|
return _jsx("div", { "data-slot": "questionnaire-actions", className: cn('sprout-questionnaire-actions', className), ...props });
|
|
870
870
|
}
|
|
871
|
-
function useNavigationButton(slot, { children, className, disabled = false, onClick, render, size = '
|
|
871
|
+
function useNavigationButton(slot, { children, className, disabled = false, onClick, render, size = 'md', tabIndex, type, variant, ...props }, { label, visible, status, shortcut, action, }) {
|
|
872
872
|
const resolvedVariant = variant ?? (slot === 'next' || slot === 'submit' ? 'default' : 'outline');
|
|
873
873
|
const activeShortcut = visible && !disabled ? (shortcut ?? null) : null;
|
|
874
874
|
function handleClick(event) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ReactNode, type Ref } from 'react';
|
|
2
2
|
export declare const recordListStatusNames: readonly ["ready", "loading", "error"];
|
|
3
|
-
export declare const recordListDensityNames: readonly ["
|
|
3
|
+
export declare const recordListDensityNames: readonly ["md", "sm"];
|
|
4
4
|
export type RecordListStatus = (typeof recordListStatusNames)[number];
|
|
5
5
|
export type RecordListDensity = (typeof recordListDensityNames)[number];
|
|
6
6
|
/** The most labelled values a row shows. Extra values are left out. */
|
|
@@ -50,7 +50,7 @@ export interface RecordListProps<T extends RecordListItem> {
|
|
|
50
50
|
empty?: ReactNode;
|
|
51
51
|
/** Shown under the rows, inside the panel. Put the app's `Pagination` here. */
|
|
52
52
|
footer?: ReactNode;
|
|
53
|
-
/** `"
|
|
53
|
+
/** `"sm"` uses less padding for dense pages. Defaults to `"md"`. */
|
|
54
54
|
density?: RecordListDensity | undefined;
|
|
55
55
|
/** Gets `focusFirst()` for moving focus after a page change. */
|
|
56
56
|
ref?: Ref<RecordListHandle> | undefined;
|
|
@@ -6,7 +6,7 @@ import { Button } from './button.js';
|
|
|
6
6
|
import { Skeleton, SkeletonGroup } from './skeleton.js';
|
|
7
7
|
import { StatePanel } from '../internal/state-panel.js';
|
|
8
8
|
export const recordListStatusNames = ['ready', 'loading', 'error'];
|
|
9
|
-
export const recordListDensityNames = ['
|
|
9
|
+
export const recordListDensityNames = ['md', 'sm'];
|
|
10
10
|
/** The most labelled values a row shows. Extra values are left out. */
|
|
11
11
|
export const recordListMaxValues = 4;
|
|
12
12
|
const SKELETON_ROWS = 5;
|
|
@@ -47,7 +47,7 @@ function SkeletonRows() {
|
|
|
47
47
|
* rows, Enter opens a row, and Tab reaches the focused row's actions. The app
|
|
48
48
|
* owns data, paging, and what the actions do.
|
|
49
49
|
*/
|
|
50
|
-
export function RecordList({ items, label, renderTitle, values, badges, renderActions, onItemOpen, status = 'ready', error, onRetry, empty, footer, density = '
|
|
50
|
+
export function RecordList({ items, label, renderTitle, values, badges, renderActions, onItemOpen, status = 'ready', error, onRetry, empty, footer, density = 'md', ref, className, }) {
|
|
51
51
|
const id = useId();
|
|
52
52
|
const listRef = useRef(null);
|
|
53
53
|
const stateRef = useRef(null);
|
|
@@ -59,7 +59,7 @@ export function ResultCard({ title, kind, apps, status, state = 'default', actio
|
|
|
59
59
|
const hidden = unique.slice(2);
|
|
60
60
|
const busy = state === 'loading' || state === 'running';
|
|
61
61
|
const disabled = state === 'disabled';
|
|
62
|
-
return (_jsxs("section", { "data-slot": "result-card", "data-state": state, "data-kind": kind, "aria-label": `${kind}: ${title}`, "aria-busy": busy, ...props, className: cn('sprout-result-card', className), children: [_jsxs("div", { className: "sprout-result-card-header", children: [visible.length > 0 ? (_jsxs("div", { role: "group", "aria-label": "Apps used", className: "sprout-result-card-apps", children: [visible.map(app => (_jsx("span", { "data-result-app": app.brand ?? 'connected-app', className: "sprout-result-card-app", children: _jsx(AppActionsPopover, { apps: [app], disabled: disabled }) }, app.brand ?? app.name))), hidden.length > 0 && (_jsx("span", { "data-result-overflow": hidden.length, className: "sprout-result-card-app", children: _jsx(AppActionsPopover, { apps: hidden, overflow: true, disabled: disabled }) }))] })) : (icon && (_jsx(BrandTile, { "aria-hidden": "true", className: "sprout-result-card-icon", children: icon }))), _jsxs("div", { className: "sprout-result-card-main", children: [_jsxs("div", { className: "sprout-result-card-text", children: [_jsx("h3", { className: "sprout-result-card-title", children: title }), _jsxs("div", { className: "sprout-result-card-meta", children: [_jsx("span", { children: kind }), _jsx("span", { "aria-hidden": "true", children: "\u00B7" }), _jsxs("span", { role: "status", "data-tone": state === 'success' || state === 'error' ? state : undefined, className: "sprout-result-card-status", children: [busy ? (_jsx(Spinner, { "aria-hidden": "true" })) : state === 'success' ? (_jsx(Check, { size: 14, "aria-hidden": "true" })) : state === 'error' ? (_jsx(Danger, { size: 14, "aria-hidden": "true" })) : null, status] })] })] }), action && (_jsx("div", { className: "sprout-result-card-action", children: _jsx(Button, { variant: "outline",
|
|
62
|
+
return (_jsxs("section", { "data-slot": "result-card", "data-state": state, "data-kind": kind, "aria-label": `${kind}: ${title}`, "aria-busy": busy, ...props, className: cn('sprout-result-card', className), children: [_jsxs("div", { className: "sprout-result-card-header", children: [visible.length > 0 ? (_jsxs("div", { role: "group", "aria-label": "Apps used", className: "sprout-result-card-apps", children: [visible.map(app => (_jsx("span", { "data-result-app": app.brand ?? 'connected-app', className: "sprout-result-card-app", children: _jsx(AppActionsPopover, { apps: [app], disabled: disabled }) }, app.brand ?? app.name))), hidden.length > 0 && (_jsx("span", { "data-result-overflow": hidden.length, className: "sprout-result-card-app", children: _jsx(AppActionsPopover, { apps: hidden, overflow: true, disabled: disabled }) }))] })) : (icon && (_jsx(BrandTile, { "aria-hidden": "true", className: "sprout-result-card-icon", children: icon }))), _jsxs("div", { className: "sprout-result-card-main", children: [_jsxs("div", { className: "sprout-result-card-text", children: [_jsx("h3", { className: "sprout-result-card-title", children: title }), _jsxs("div", { className: "sprout-result-card-meta", children: [_jsx("span", { children: kind }), _jsx("span", { "aria-hidden": "true", children: "\u00B7" }), _jsxs("span", { role: "status", "data-tone": state === 'success' || state === 'error' ? state : undefined, className: "sprout-result-card-status", children: [busy ? (_jsx(Spinner, { "aria-hidden": "true" })) : state === 'success' ? (_jsx(Check, { size: 14, "aria-hidden": "true" })) : state === 'error' ? (_jsx(Danger, { size: 14, "aria-hidden": "true" })) : null, status] })] })] }), action && (_jsx("div", { className: "sprout-result-card-action", children: _jsx(Button, { variant: "outline", disabled: state === 'loading' || disabled || action.disabled === true, onClick: action.onClick, children: action.label }) }))] })] }), children && _jsx("div", { className: "sprout-result-card-body", children: children })] }));
|
|
63
63
|
}
|
|
64
64
|
function AppActionsPopover({ apps, overflow = false, disabled, }) {
|
|
65
65
|
const first = apps[0];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ReactNode, type Ref } from 'react';
|
|
2
2
|
import { type Editor, type Extensions, type JSONContent } from '@tiptap/core';
|
|
3
|
-
export declare const richTextEditorSizeNames: readonly ["
|
|
3
|
+
export declare const richTextEditorSizeNames: readonly ["md", "sm"];
|
|
4
4
|
export type RichTextEditorSize = (typeof richTextEditorSizeNames)[number];
|
|
5
5
|
/** A Tiptap JSON document, such as `{ type: "doc", content: [{ type: "paragraph" }] }`. */
|
|
6
6
|
export type RichTextValue = JSONContent;
|
|
@@ -15,8 +15,8 @@ export type RichTextEditorHandle = {
|
|
|
15
15
|
export interface RichTextEditorProps {
|
|
16
16
|
ref?: Ref<RichTextEditorHandle> | undefined;
|
|
17
17
|
/**
|
|
18
|
-
* `
|
|
19
|
-
* `
|
|
18
|
+
* `md` is an 80px to 256px box with 16px text and a toolbar row below.
|
|
19
|
+
* `sm` is a 40px to 128px box with 14px text and the toolbar inline at
|
|
20
20
|
* the end.
|
|
21
21
|
*/
|
|
22
22
|
size?: RichTextEditorSize | null | undefined;
|
|
@@ -9,7 +9,7 @@ import { canSplit } from '@tiptap/pm/transform';
|
|
|
9
9
|
import StarterKit from '@tiptap/starter-kit';
|
|
10
10
|
import Placeholder from '@tiptap/extension-placeholder';
|
|
11
11
|
import { cn } from '../internal/classes.js';
|
|
12
|
-
export const richTextEditorSizeNames = ['
|
|
12
|
+
export const richTextEditorSizeNames = ['md', 'sm'];
|
|
13
13
|
const fenceLanguage = /^[\w+#.-]{1,32}$/;
|
|
14
14
|
const typedFence = /```([\w+#.-]{1,32})?\s$/;
|
|
15
15
|
const fenceOnly = /^```([\w+#.-]{1,32})?$/;
|
|
@@ -153,8 +153,8 @@ const baseExtensions = [
|
|
|
153
153
|
* the border, focus, and invalid states.
|
|
154
154
|
*/
|
|
155
155
|
export function RichTextEditor({ ref, size, condensed = false, value, onChange, onSend, extensions = [], placeholder = 'Ask anything…', disabled = false, ariaLabel = 'Message', ariaInvalid = false, ariaDescribedBy, ariaExpanded, ariaControls, ariaActiveDescendant, toolbarAddon, className, }) {
|
|
156
|
-
const scale = size ?? '
|
|
157
|
-
const inline = condensed || scale === '
|
|
156
|
+
const scale = size ?? 'md';
|
|
157
|
+
const inline = condensed || scale === 'sm';
|
|
158
158
|
const onSendRef = useRef(onSend);
|
|
159
159
|
const onChangeRef = useRef(onChange);
|
|
160
160
|
const placeholderRef = useRef(placeholder);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ScrollArea as BaseScrollArea } from '@base-ui/react/scroll-area';
|
|
2
|
-
export declare const scrollAreaSizeNames: readonly ["
|
|
2
|
+
export declare const scrollAreaSizeNames: readonly ["sm", "md"];
|
|
3
3
|
export declare const scrollAreaVariantNames: readonly ["plain", "table"];
|
|
4
4
|
export declare const scrollAreaOrientationNames: readonly ["vertical", "horizontal", "both"];
|
|
5
5
|
export type ScrollAreaSize = (typeof scrollAreaSizeNames)[number];
|
|
6
6
|
export type ScrollAreaVariant = (typeof scrollAreaVariantNames)[number];
|
|
7
7
|
export type ScrollAreaOrientation = (typeof scrollAreaOrientationNames)[number];
|
|
8
8
|
export interface ScrollAreaProps extends BaseScrollArea.Root.Props {
|
|
9
|
-
/** `"sm"` is 10rem tall, `"md"` is 16rem tall.
|
|
9
|
+
/** `"sm"` is 10rem tall, `"md"` is 16rem tall. Leave it out to follow the content or your className. */
|
|
10
10
|
size?: ScrollAreaSize;
|
|
11
11
|
/** `"table"` adds a bordered surface, caps the height at 60dvh, and makes the viewport a labeled region. */
|
|
12
12
|
variant?: ScrollAreaVariant;
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { ScrollArea as BaseScrollArea } from '@base-ui/react/scroll-area';
|
|
4
4
|
import { stateClassName } from '../internal/classes.js';
|
|
5
|
-
export const scrollAreaSizeNames = ['
|
|
5
|
+
export const scrollAreaSizeNames = ['sm', 'md'];
|
|
6
6
|
export const scrollAreaVariantNames = ['plain', 'table'];
|
|
7
7
|
export const scrollAreaOrientationNames = ['vertical', 'horizontal', 'both'];
|
|
8
8
|
/** A scrolling region with thin, theme-aware scrollbars that keeps native keyboard and wheel scrolling. */
|
|
9
|
-
export function ScrollArea({ className, children, size
|
|
9
|
+
export function ScrollArea({ className, children, size, variant = 'plain', orientation = 'vertical', viewportLabel, ...props }) {
|
|
10
10
|
return (_jsxs(BaseScrollArea.Root, { "data-slot": "scroll-area", "data-size": size, "data-variant": variant, className: stateClassName('sprout-scroll-area', className), ...props, children: [_jsx(BaseScrollArea.Viewport, { "data-slot": "scroll-area-viewport", role: variant === 'table' ? 'region' : undefined, "aria-label": viewportLabel, className: "sprout-scroll-area-viewport", children: children }), orientation !== 'horizontal' && _jsx(ScrollBar, {}), orientation !== 'vertical' && _jsx(ScrollBar, { orientation: "horizontal" }), _jsx(BaseScrollArea.Corner, { "data-slot": "scroll-area-corner", className: "sprout-scroll-area-corner" })] }));
|
|
11
11
|
}
|
|
12
12
|
/** One scrollbar track and thumb. `ScrollArea` draws these for you from `orientation`. */
|
|
@@ -20,7 +20,7 @@ export function SearchField({ label, value, onChange, placeholder, maxLength, id
|
|
|
20
20
|
event.stopPropagation();
|
|
21
21
|
onChange('');
|
|
22
22
|
};
|
|
23
|
-
return (_jsxs(InputGroup, { "data-slot": "search-field", className: cn('sprout-search-field', className), children: [_jsx(InputGroupAddon, { children: _jsx(Search, { size: 16, "aria-hidden": "true" }) }), _jsx(InputGroupInput, { ref: input, id: id, type: "search", "aria-label": label, maxLength: maxLength, value: value, placeholder: placeholder ?? label, autoComplete: "off", spellCheck: false, onChange: event => onChange(event.currentTarget.value), onKeyDown: onKeyDown }), value && (_jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupButton, { "data-slot": "search-field-clear", size: "icon
|
|
23
|
+
return (_jsxs(InputGroup, { "data-slot": "search-field", className: cn('sprout-search-field', className), children: [_jsx(InputGroupAddon, { children: _jsx(Search, { size: 16, "aria-hidden": "true" }) }), _jsx(InputGroupInput, { ref: input, id: id, type: "search", "aria-label": label, maxLength: maxLength, value: value, placeholder: placeholder ?? label, autoComplete: "off", spellCheck: false, onChange: event => onChange(event.currentTarget.value), onKeyDown: onKeyDown }), value && (_jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupButton, { "data-slot": "search-field-clear", size: "icon", "aria-label": "Clear search", className: "sprout-search-field-clear", onClick: () => {
|
|
24
24
|
onChange('');
|
|
25
25
|
input.current?.focus();
|
|
26
26
|
}, children: _jsx(X, { size: 14, "aria-hidden": "true" }) }) }))] }));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Select as SelectPrimitive } from '@base-ui/react/select';
|
|
2
|
-
export declare const selectTriggerSizeNames: readonly ["
|
|
2
|
+
export declare const selectTriggerSizeNames: readonly ["md", "sm", "lg"];
|
|
3
3
|
export declare const selectTriggerWidthNames: readonly ["fit", "full"];
|
|
4
4
|
export type SelectTriggerSize = (typeof selectTriggerSizeNames)[number];
|
|
5
5
|
export type SelectTriggerWidth = (typeof selectTriggerWidthNames)[number];
|
|
@@ -19,11 +19,7 @@ export type SelectValueProps = SelectPrimitive.Value.Props;
|
|
|
19
19
|
*/
|
|
20
20
|
export declare function SelectValue({ className, ...props }: SelectValueProps): import("react").JSX.Element;
|
|
21
21
|
export interface SelectTriggerProps extends SelectPrimitive.Trigger.Props {
|
|
22
|
-
/**
|
|
23
|
-
* `default` is 32px for forms. `sm` is 28px for toolbars, filters, table
|
|
24
|
-
* rows, and inline sentences. `calendar` is a 32px control with small text
|
|
25
|
-
* for calendar headers.
|
|
26
|
-
*/
|
|
22
|
+
/** `sm` is 28px, `md` is 32px (`--sprout-control-height`), and `lg` is 36px. */
|
|
27
23
|
size?: SelectTriggerSize;
|
|
28
24
|
/** `fit` sizes to the value. `full` fills the parent, as in form fields. */
|
|
29
25
|
width?: SelectTriggerWidth;
|
|
@@ -6,7 +6,7 @@ import { ChevronDown } from 'reicon-react/icons/ChevronDown';
|
|
|
6
6
|
import { ChevronUp } from 'reicon-react/icons/ChevronUp';
|
|
7
7
|
import { cn, stateClassName } from '../internal/classes.js';
|
|
8
8
|
import { useFieldControl } from './field.js';
|
|
9
|
-
export const selectTriggerSizeNames = ['
|
|
9
|
+
export const selectTriggerSizeNames = ['md', 'sm', 'lg'];
|
|
10
10
|
export const selectTriggerWidthNames = ['fit', 'full'];
|
|
11
11
|
/**
|
|
12
12
|
* Holds the value and open state. It takes every Base UI select root prop,
|
|
@@ -24,7 +24,7 @@ export function SelectGroup({ className, ...props }) {
|
|
|
24
24
|
export function SelectValue({ className, ...props }) {
|
|
25
25
|
return (_jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props, className: stateClassName('sprout-select-value', className) }));
|
|
26
26
|
}
|
|
27
|
-
export function SelectTrigger({ className, size = '
|
|
27
|
+
export function SelectTrigger({ className, size = 'md', width = 'fit', children, ...rest }) {
|
|
28
28
|
const props = useFieldControl(rest);
|
|
29
29
|
return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, "data-width": width, ...props, className: stateClassName(cn('sprout-select-trigger', `sprout-select-trigger-${size}`, `sprout-select-trigger-${width}`), className), children: [children, _jsx(SelectPrimitive.Icon, { className: "sprout-select-icon", children: _jsx(ChevronDown, { "aria-hidden": "true" }) })] }));
|
|
30
30
|
}
|