sherick-ui 2.5.0 → 2.7.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.
Files changed (75) hide show
  1. package/README.md +57 -3
  2. package/dist/cjs/components/CheckboxGroup.cjs +41 -0
  3. package/dist/cjs/components/CheckboxGroup.cjs.map +1 -0
  4. package/dist/cjs/components/Combobox.cjs +190 -14
  5. package/dist/cjs/components/Combobox.cjs.map +1 -1
  6. package/dist/cjs/components/Form.cjs +27 -0
  7. package/dist/cjs/components/Form.cjs.map +1 -0
  8. package/dist/cjs/components/Input.cjs +20 -2
  9. package/dist/cjs/components/Input.cjs.map +1 -1
  10. package/dist/cjs/components/NumberField.cjs +30 -4
  11. package/dist/cjs/components/NumberField.cjs.map +1 -1
  12. package/dist/cjs/components/RadioGroup.cjs +7 -3
  13. package/dist/cjs/components/RadioGroup.cjs.map +1 -1
  14. package/dist/cjs/components/Search.cjs +1 -1
  15. package/dist/cjs/components/Search.cjs.map +1 -1
  16. package/dist/cjs/components/Select.cjs +4 -2
  17. package/dist/cjs/components/Select.cjs.map +1 -1
  18. package/dist/cjs/components/Tabs.cjs +1 -1
  19. package/dist/cjs/components/Tabs.cjs.map +1 -1
  20. package/dist/cjs/components/Textarea.cjs +6 -1
  21. package/dist/cjs/components/Textarea.cjs.map +1 -1
  22. package/dist/cjs/components/ToggleGroup.cjs +1 -1
  23. package/dist/cjs/components/ToggleGroup.cjs.map +1 -1
  24. package/dist/cjs/components/choice-row.cjs +51 -0
  25. package/dist/cjs/components/choice-row.cjs.map +1 -0
  26. package/dist/cjs/components/date-field.cjs +3 -3
  27. package/dist/cjs/components/date-field.cjs.map +1 -1
  28. package/dist/cjs/components/option-groups.cjs +35 -0
  29. package/dist/cjs/components/option-groups.cjs.map +1 -0
  30. package/dist/cjs/components/ui.common.cjs +100 -50
  31. package/dist/cjs/components/ui.common.cjs.map +1 -1
  32. package/dist/cjs/dev.cjs +2 -0
  33. package/dist/cjs/dev.cjs.map +1 -1
  34. package/dist/cjs/index.cjs +4 -0
  35. package/dist/cjs/index.cjs.map +1 -1
  36. package/dist/esm/components/CheckboxGroup.js +36 -0
  37. package/dist/esm/components/CheckboxGroup.js.map +1 -0
  38. package/dist/esm/components/Combobox.js +195 -19
  39. package/dist/esm/components/Combobox.js.map +1 -1
  40. package/dist/esm/components/Form.js +22 -0
  41. package/dist/esm/components/Form.js.map +1 -0
  42. package/dist/esm/components/Input.js +21 -3
  43. package/dist/esm/components/Input.js.map +1 -1
  44. package/dist/esm/components/NumberField.js +31 -5
  45. package/dist/esm/components/NumberField.js.map +1 -1
  46. package/dist/esm/components/RadioGroup.js +10 -6
  47. package/dist/esm/components/RadioGroup.js.map +1 -1
  48. package/dist/esm/components/Search.js +1 -1
  49. package/dist/esm/components/Search.js.map +1 -1
  50. package/dist/esm/components/Select.js +6 -4
  51. package/dist/esm/components/Select.js.map +1 -1
  52. package/dist/esm/components/Tabs.js +2 -2
  53. package/dist/esm/components/Tabs.js.map +1 -1
  54. package/dist/esm/components/Textarea.js +6 -1
  55. package/dist/esm/components/Textarea.js.map +1 -1
  56. package/dist/esm/components/ToggleGroup.js +2 -2
  57. package/dist/esm/components/ToggleGroup.js.map +1 -1
  58. package/dist/esm/components/choice-row.js +46 -0
  59. package/dist/esm/components/choice-row.js.map +1 -0
  60. package/dist/esm/components/date-field.js +3 -3
  61. package/dist/esm/components/date-field.js.map +1 -1
  62. package/dist/esm/components/option-groups.js +30 -0
  63. package/dist/esm/components/option-groups.js.map +1 -0
  64. package/dist/esm/components/ui.common.js +100 -52
  65. package/dist/esm/components/ui.common.js.map +1 -1
  66. package/dist/esm/dev.js +1 -1
  67. package/dist/esm/index.js +2 -0
  68. package/dist/esm/index.js.map +1 -1
  69. package/dist/styles.css +271 -205
  70. package/dist/theme.css +160 -157
  71. package/dist/types/dev.d.cts +31 -25
  72. package/dist/types/dev.d.ts +31 -25
  73. package/dist/types/index.d.cts +184 -20
  74. package/dist/types/index.d.ts +184 -20
  75. package/package.json +2 -2
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Sherick UI
2
2
 
3
- A React 18/19 component library with soft tonal surfaces, deliberate shape contrast
4
- and restrained motion. `2.0.0` established the stable line; `1.x` is frozen.
5
- This package source is `2.3.0`; verified `main` stages new versions via npm trusted
3
+ A React 18/19 component library in graphite and iris, with deliberate
4
+ shape contrast and restrained motion. `2.0.0` established the stable line; `1.x` is frozen.
5
+ This package source is `2.7.0`; verified `main` stages new versions via npm trusted
6
6
  publishing for maintainer approval. Check the installed version for availability.
7
7
 
8
8
  ## Install and style
@@ -84,6 +84,60 @@ Use `options[].label` for rich, wrapping text, badges and non-interactive hints.
84
84
  the same single-selection, keyboard and form contract; omit `appearance` for the original
85
85
  plain rows. Do not put buttons or links inside a radio's label.
86
86
 
87
+ ## Forms (from 2.6.0)
88
+
89
+ `Form` wraps Base UI's form. On submit it validates every named field, keeps the submission
90
+ from leaving while any is invalid and moves focus to the first invalid field. Errors returned
91
+ from a server go in `errors`, keyed by field `name`; each appears under its field, the form
92
+ focuses the first one, and an entry clears as soon as its field changes.
93
+
94
+ ```tsx
95
+ import {
96
+ CheckboxGroup, Combobox, Field, Form, Input, NumberField, Select, type FormErrors,
97
+ } from "sherick-ui";
98
+
99
+ const [errors, setErrors] = useState<FormErrors>({});
100
+
101
+ <Form errors={errors} onFormSubmit={async (values) => setErrors(await save(values))}>
102
+ <Input name="title" label="Rule title" required />
103
+
104
+ {/* Multiple: chosen values are chips; Backspace removes the last, arrows walk the chips. */}
105
+ <Field name="roles" label="Required roles">
106
+ <Combobox multiple options={roles} defaultValue={["admin"]} />
107
+ </Field>
108
+
109
+ {/* Groups: an option outside every group is listed where it stands. */}
110
+ <Field name="channel" label="Channel">
111
+ <Select options={[
112
+ { label: "#rules", value: "rules" },
113
+ { label: "Giveaways", options: [{ label: "#giveaway", value: "giveaway" }] },
114
+ ]} />
115
+ </Field>
116
+
117
+ {/* Units are presentation and hidden from assistive technology: name them in the label. */}
118
+ <Field name="price" label="Price per ticket (€)">
119
+ <NumberField prefix="€" format={{ minimumFractionDigits: 2 }} defaultValue={0.1} step={0.05} />
120
+ </Field>
121
+
122
+ <CheckboxGroup
123
+ name="casinos" label="Casinos" appearance="surface" required
124
+ options={[{ value: "aurora", label: "Aurora", description: "aurora.example, aurora-play.example" }]}
125
+ />
126
+
127
+ {/* Creatable: "Add …" for typed text, one entry per pasted line, duplicates reported. */}
128
+ <Field name="games" label="Allowed games" description="Paste one title per line.">
129
+ <Combobox multiple creatable options={[]} />
130
+ </Field>
131
+ </Form>
132
+ ```
133
+
134
+ `Input`, `Textarea`, `RadioGroup` and `CheckboxGroup` carry their own `Field`, so `name` is
135
+ enough. Put `Select`, `Combobox`, `NumberField`, `Checkbox`, `Switch` and `Slider` inside a
136
+ `Field` with the `name`, or the form cannot report their errors. A multiple `Combobox` reports
137
+ `string[]`; a created entry's value is its own text. `CheckboxGroup required` means at least one
138
+ choice. Option `description` names nothing: the label is the accessible name and the description
139
+ is announced as its description.
140
+
87
141
  ## Themes and direction
88
142
 
89
143
  With no root `data-sherick-theme`, the library follows `prefers-color-scheme`. Set
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var checkbox = require('@base-ui/react/checkbox');
8
+ var checkboxGroup = require('@base-ui/react/checkbox-group');
9
+ var field = require('@base-ui/react/field');
10
+ var lucideReact = require('lucide-react');
11
+ var React = require('react');
12
+ var utils = require('../libs/utils.cjs');
13
+ var ui_common = require('./ui.common.cjs');
14
+ var ui_motion = require('./ui.motion.cjs');
15
+ var choiceRow = require('./choice-row.cjs');
16
+
17
+ /**
18
+ * Any number of choices out of a list — the options-API sibling of `RadioGroup`, with the same rows,
19
+ * the same opt-in `surface` row and the same labelled column. Base UI owns the value, the group
20
+ * semantics and the form participation; Sherick UI owns the rows and the marks.
21
+ */
22
+ const CheckboxGroup = React.forwardRef(({ options, appearance = "default", label, description, error, value, defaultValue, onValueChange, name, required, requiredMessage = "Choose at least one option.", disabled, readOnly, className, ...groupProps }, ref) => {
23
+ const idBase = React.useId();
24
+ return (
25
+ // The group is the field's one control, so the field takes its name and its validation; each
26
+ // option is scoped to its own `Field.Item`, which labels and describes that checkbox alone.
27
+ jsxRuntime.jsxs(field.Field.Root, { className: utils.cn(ui_common.fieldLayout, className), name: name, disabled: disabled, invalid: error ? true : undefined, validate: required
28
+ ? (current) => (Array.isArray(current) && current.length > 0 ? null : requiredMessage)
29
+ : undefined, children: [label && (jsxRuntime.jsxs(field.Field.Label, { className: utils.cn("mb-2 text-sm font-medium", ui_common.text.high), children: [label, required && (jsxRuntime.jsx("span", { className: utils.cn("ms-1 text-sherick-danger"), "aria-hidden": "true", children: "*" }))] })), jsxRuntime.jsx(checkboxGroup.CheckboxGroup, { ...groupProps, ref: ref, value: value, defaultValue: defaultValue, onValueChange: onValueChange, disabled: disabled, className: utils.cn("flex flex-col", appearance === "surface" && "gap-2"), children: options.map((option, index) => {
30
+ const labelId = `${idBase}-option-${index}`;
31
+ return (jsxRuntime.jsx(field.Field.Item, { ...(appearance === "surface" && readOnly ? { "data-readonly": "" } : {}), className: utils.cn(...choiceRow.choiceItemClasses(appearance)), children: jsxRuntime.jsx(field.Field.Label, { className: utils.cn(...choiceRow.choiceLabelClasses(appearance)), children: jsxRuntime.jsxs("span", { className: utils.cn(choiceRow.choiceLineClassName), children: [jsxRuntime.jsx(checkbox.Checkbox.Root, { value: option.value, disabled: option.disabled, readOnly: readOnly, ...(option.description != null ? { "aria-labelledby": labelId } : {}), className: utils.cn(
32
+ // The control takes the mark's corner so a forced-colors outline follows the
33
+ // box rather than squaring it off. The whole row is its label and its target.
34
+ "group relative my-0.5 flex size-5 shrink-0 items-center justify-center outline-none", ui_common.shape.mark), children: jsxRuntime.jsx("span", { "aria-hidden": "true", className: utils.cn("flex size-5 items-center justify-center", ui_common.shape.mark, ui_common.selectable.markSurface, ui_common.selectable.mark, ui_common.selectable.selected, ui_common.stateLayer.mark, appearance === "default" && ui_common.groupFocusRing), children: jsxRuntime.jsx(checkbox.Checkbox.Indicator, { className: utils.cn("relative flex items-center justify-center", ui_motion.motionArrive), children: jsxRuntime.jsx(lucideReact.Check, { className: utils.cn("size-3.5"), strokeWidth: 3 }) }) }) }), jsxRuntime.jsx(choiceRow.ChoiceCopy, { appearance: appearance, label: option.label, description: option.description, labelId: labelId })] }) }) }, option.value));
35
+ }) }), description && (jsxRuntime.jsx(field.Field.Description, { className: utils.cn(ui_common.fieldMessage.description), children: description })), jsxRuntime.jsx(field.Field.Error, { match: error ? true : undefined, className: utils.cn(ui_common.fieldMessage.error), ...(error ? { children: error } : {}) })] }));
36
+ });
37
+ CheckboxGroup.displayName = "CheckboxGroup";
38
+
39
+ exports.CheckboxGroup = CheckboxGroup;
40
+ exports.default = CheckboxGroup;
41
+ //# sourceMappingURL=CheckboxGroup.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckboxGroup.cjs","sources":["../../../src/components/CheckboxGroup.tsx"],"sourcesContent":["\"use client\";\n\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { Field } from \"@base-ui/react/field\";\nimport { Check } from \"lucide-react\";\nimport React, { forwardRef, useId, type ComponentProps, type ReactNode } from \"react\";\nimport { cn } from \"@/libs/utils\";\nimport {\n fieldLayout,\n fieldMessage,\n groupFocusRing,\n selectable,\n shape,\n stateLayer,\n text,\n} from \"./ui.common\";\nimport { motionArrive } from \"./ui.motion\";\nimport {\n ChoiceCopy,\n choiceItemClasses,\n choiceLabelClasses,\n choiceLineClassName,\n type ChoiceAppearance,\n} from \"./choice-row\";\n\nexport interface CheckboxGroupOption {\n value: string;\n label: ReactNode;\n /** Supporting copy beneath the label, such as the domains a casino answers on. */\n description?: ReactNode;\n disabled?: boolean;\n}\n\ntype CheckboxGroupChangeDetails = Parameters<NonNullable<BaseCheckboxGroup.Props[\"onValueChange\"]>>[1];\n\nexport interface CheckboxGroupProps\n extends Omit<ComponentProps<\"div\">, \"onChange\" | \"defaultValue\" | \"children\"> {\n options: CheckboxGroupOption[];\n /** Gives each choice its own selectable surface. The default keeps the compact, unfilled rows. */\n appearance?: ChoiceAppearance;\n /** The group's own label. Base names the group from it. */\n label?: ReactNode;\n /** Supporting copy beneath the group. */\n description?: ReactNode;\n /**\n * The message shown while the group is invalid. Its presence is what makes the group invalid; omit\n * it and the group shows what Base reports, including an error a `Form` returns for its `name`.\n */\n error?: ReactNode;\n /** The ticked options' values. */\n value?: string[];\n defaultValue?: string[];\n /** Base's own change callback, event details included. */\n onValueChange?: (value: string[], eventDetails: CheckboxGroupChangeDetails) => void;\n /** Identifies the group when a form is submitted: one entry per ticked option. */\n name?: string;\n /**\n * At least one option must be ticked. It marks the label and is checked when a `Form` validates;\n * the message is `requiredMessage`.\n */\n required?: boolean;\n /** The message a required group shows when nothing is ticked. */\n requiredMessage?: string;\n disabled?: boolean;\n readOnly?: boolean;\n /** Styles the labelled group. */\n className?: string;\n}\n\n/**\n * Any number of choices out of a list — the options-API sibling of `RadioGroup`, with the same rows,\n * the same opt-in `surface` row and the same labelled column. Base UI owns the value, the group\n * semantics and the form participation; Sherick UI owns the rows and the marks.\n */\nexport const CheckboxGroup = forwardRef<HTMLDivElement, CheckboxGroupProps>(\n (\n {\n options,\n appearance = \"default\",\n label,\n description,\n error,\n value,\n defaultValue,\n onValueChange,\n name,\n required,\n requiredMessage = \"Choose at least one option.\",\n disabled,\n readOnly,\n className,\n ...groupProps\n },\n ref\n ) => {\n const idBase = useId();\n\n return (\n // The group is the field's one control, so the field takes its name and its validation; each\n // option is scoped to its own `Field.Item`, which labels and describes that checkbox alone.\n <Field.Root\n className={cn(fieldLayout, className)}\n name={name}\n disabled={disabled}\n invalid={error ? true : undefined}\n validate={\n required\n ? (current) => (Array.isArray(current) && current.length > 0 ? null : requiredMessage)\n : undefined\n }\n >\n {label && (\n <Field.Label className={cn(\"mb-2 text-sm font-medium\", text.high)}>\n {label}\n {required && (\n <span className={cn(\"ms-1 text-sherick-danger\")} aria-hidden=\"true\">\n *\n </span>\n )}\n </Field.Label>\n )}\n <BaseCheckboxGroup\n {...groupProps}\n ref={ref}\n value={value}\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n disabled={disabled}\n className={cn(\"flex flex-col\", appearance === \"surface\" && \"gap-2\")}\n >\n {options.map((option, index) => {\n const labelId = `${idBase}-option-${index}`;\n return (\n <Field.Item\n key={option.value}\n {...(appearance === \"surface\" && readOnly ? { \"data-readonly\": \"\" } : {})}\n className={cn(...choiceItemClasses(appearance))}\n >\n <Field.Label className={cn(...choiceLabelClasses(appearance))}>\n <span className={cn(choiceLineClassName)}>\n <BaseCheckbox.Root\n value={option.value}\n disabled={option.disabled}\n readOnly={readOnly}\n {...(option.description != null ? { \"aria-labelledby\": labelId } : {})}\n className={cn(\n // The control takes the mark's corner so a forced-colors outline follows the\n // box rather than squaring it off. The whole row is its label and its target.\n \"group relative my-0.5 flex size-5 shrink-0 items-center justify-center outline-none\",\n shape.mark\n )}\n >\n {/* An empty box is identified by its rim; a ticked one fills edge to edge. */}\n <span\n aria-hidden=\"true\"\n className={cn(\n \"flex size-5 items-center justify-center\",\n shape.mark,\n selectable.markSurface,\n selectable.mark,\n selectable.selected,\n stateLayer.mark,\n appearance === \"default\" && groupFocusRing\n )}\n >\n {/* Positioned so the tick paints above the box's hover layer. */}\n <BaseCheckbox.Indicator className={cn(\"relative flex items-center justify-center\", motionArrive)}>\n {/* A heavier stroke than the icon default: at 14px the default draws a hairline tick. */}\n <Check className={cn(\"size-3.5\")} strokeWidth={3} />\n </BaseCheckbox.Indicator>\n </span>\n </BaseCheckbox.Root>\n <ChoiceCopy\n appearance={appearance}\n label={option.label}\n description={option.description}\n labelId={labelId}\n />\n </span>\n </Field.Label>\n </Field.Item>\n );\n })}\n </BaseCheckboxGroup>\n {description && (\n <Field.Description className={cn(fieldMessage.description)}>{description}</Field.Description>\n )}\n {/* Mounted whether or not a message was passed: without `match` this part renders what Base\n reports — a required group left empty, or the error a `Form` returns for this name. */}\n <Field.Error\n match={error ? true : undefined}\n className={cn(fieldMessage.error)}\n {...(error ? { children: error } : {})}\n />\n </Field.Root>\n );\n }\n);\n\nCheckboxGroup.displayName = \"CheckboxGroup\";\n\nexport default CheckboxGroup;\n"],"names":["forwardRef","useId","_jsxs","Field","cn","fieldLayout","text","_jsx","BaseCheckboxGroup","choiceItemClasses","choiceLabelClasses","choiceLineClassName","BaseCheckbox","shape","selectable","stateLayer","groupFocusRing","motionArrive","Check","ChoiceCopy","fieldMessage"],"mappings":"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"}
@@ -10,7 +10,10 @@ var lucideReact = require('lucide-react');
10
10
  var utils = require('../libs/utils.cjs');
11
11
  var ui_common = require('./ui.common.cjs');
12
12
  var ui_motion = require('./ui.motion.cjs');
13
+ var optionGroups = require('./option-groups.cjs');
13
14
 
15
+ const isCreateItem = (item) => item.create === true;
16
+ const sameText = (a, b) => a.localeCompare(b, undefined, { sensitivity: "accent" }) === 0;
14
17
  /* The composite field's own controls are not standalone `IconButton`s: the field owns their
15
18
  focus treatment, and they are one cluster at the field's trailing edge rather than two targets
16
19
  beside it, so they take `density.part` instead of the standalone target floor.
@@ -20,32 +23,205 @@ var ui_motion = require('./ui.motion.cjs');
20
23
  a read-only combobox still opens and browses, only its value is fixed. The clear control is
21
24
  handed its own `disabled` for that case because Base itself refuses to clear a read-only
22
25
  control; nothing here has to be derived from Sherick's props. */
23
- const partClassName = `inline-flex shrink-0 items-center justify-center ${ui_common.density.part} ${ui_common.shape.circle} ${ui_common.text.medium} [&>svg]:size-5 ${ui_motion.motionFeedback} ${ui_common.stateLayer.quiet} ${ui_common.state.enabled} ${ui_common.state.disabledPart} [&:not([data-disabled]):not(:disabled)]:hover:text-sherick-ink`;
26
+ const partClassName = `inline-flex shrink-0 items-center justify-center ${ui_common.density.part} ${ui_common.shape.circle} ${ui_common.text.medium} [&>svg]:size-5 ${ui_motion.motionFeedback} ${ui_common.stateLayer.fieldPart} ${ui_common.state.enabled} ${ui_common.state.disabledPart} [&:not([data-disabled]):not(:disabled)]:hover:text-sherick-ink`;
27
+ /* A chosen value inside the field is a held choice riding in the field's tray, so it is the tray's
28
+ puck: the brightest surface in the view, at `elevation.control`, with its copy at full emphasis. A
29
+ neutral tonal pill is the tray's own tone, and a row of them read as one grey band rather than as
30
+ separate values. It is shorter than a standalone chip because it
31
+ rides a text field's line rather than standing in a row of its own: 28px leaves the field's 48px
32
+ resting height intact around one line of chips. Base gives a chip real focus while the arrow keys
33
+ walk the row, so the focused chip takes the inset ring — the one this chip is, inside the field's
34
+ own ring, which keeps marking the field as engaged. */
35
+ const valueChipClassName = utils.cn("inline-flex h-7 min-w-0 max-w-full items-center gap-0.5 ps-3 pe-0.5 text-sm leading-5 font-medium outline-none", ui_common.shape.pill, ui_common.puck, ui_common.elevation.control, ui_common.text.high, ui_common.focusRingInset);
36
+ /* The dismiss target is a part of the chip the pointer is already in: 24px clears the pointer
37
+ minimum, its circle nests in the chip's pill at the chip's own 2px end inset, and the glyph inside
38
+ it takes the press so the target never moves. Base keeps it out of the tab order — Backspace and
39
+ Delete remove a focused chip — and marks it disabled with the combobox. */
40
+ const chipRemoveClassName = utils.cn("group inline-flex size-6 shrink-0 items-center justify-center", ui_common.shape.circle, ui_common.text.medium, "[&:not([data-disabled]):not(:disabled)]:hover:text-sherick-ink", ui_motion.motionFeedback, ui_common.stateLayer.quiet, ui_common.state.enabled, ui_common.state.disabledPart);
24
41
  /**
25
- * A text field that filters a list of options and selects one of them. It is the searchable
26
- * sibling of `Select`: the same option shape, the same value contract and the same box, with an
27
- * input instead of a trigger. Base UI owns filtering, the listbox semantics, keyboard
28
- * interaction, the anchored popup and the hidden form input; Sherick UI owns the field, the row
29
- * treatment and the tone of the selected option.
42
+ * A text field that filters a list of options and selects one of them, or several. It is the
43
+ * searchable sibling of `Select`: the same option shape, the same value contract and the same box,
44
+ * with an input instead of a trigger. Base UI owns filtering, the listbox semantics, keyboard
45
+ * interaction, chip navigation and removal, the anchored popup and the hidden form inputs; Sherick UI
46
+ * owns the field, the row treatment, the chips and the tone of the selected option.
30
47
  *
31
48
  * Filtering is Base's and it is local — an application that needs remote results owns the
32
49
  * fetching, the debounce and the loading state around this control.
33
50
  */
34
- const Combobox = React.forwardRef(({ options, value, defaultValue, onValueChange, placeholder = "Select an option", emptyMessage = "No results found.", className, disabled, readOnly, filter, ...rootProps }, ref) => {
35
- const selectedOption = (next) => { var _a; return next == null ? null : (_a = options.find((option) => option.value === next)) !== null && _a !== void 0 ? _a : null; };
36
- return (jsxRuntime.jsxs(combobox.Combobox.Root, { ...rootProps, items: options, value: value === undefined ? undefined : selectedOption(value), defaultValue: selectedOption(defaultValue),
51
+ const Combobox = React.forwardRef((props, ref) => {
52
+ var _a, _b, _c;
53
+ const { options, multiple, value, defaultValue, onValueChange, creatable, createLabel = (query) => `Add “${query}”`, chipsLabel = "Selected", placeholder = "Select an option", emptyMessage, className, disabled, readOnly, filter, autoHighlight, inputValue, defaultInputValue, onInputValueChange, onOpenChange, ...rootProps } = props;
54
+ const flatOptions = optionGroups.flattenOptions(options);
55
+ const optionByValue = new Map(flatOptions.map((option) => [option.value, option]));
56
+ /* A value that is not among the options — a created entry — is shown under its own text. */
57
+ const toOption = (next) => { var _a; return (_a = optionByValue.get(next)) !== null && _a !== void 0 ? _a : { label: next, value: next }; };
58
+ /* A multiple combobox reads its current value to append a pasted batch, and a creatable one reads
59
+ its query to offer the "Add" row, so both are mirrored here when the application leaves them
60
+ uncontrolled. Base still owns every change; this only remembers what it last reported. */
61
+ const [uncontrolledValues, setUncontrolledValues] = React.useState(() => { var _a; return multiple ? ((_a = defaultValue) !== null && _a !== void 0 ? _a : []) : []; });
62
+ const [uncontrolledQuery, setUncontrolledQuery] = React.useState(defaultInputValue !== null && defaultInputValue !== void 0 ? defaultInputValue : "");
63
+ const [notice, setNotice] = React.useState({ visible: "", announced: "" });
64
+ const values = multiple ? ((_a = value) !== null && _a !== void 0 ? _a : uncontrolledValues) : [];
65
+ const query = creatable ? (inputValue !== null && inputValue !== void 0 ? inputValue : uncontrolledQuery) : inputValue;
66
+ const trimmedQuery = (query !== null && query !== void 0 ? query : "").trim();
67
+ const isChosen = (text) => values.some((chosen) => sameText(chosen, text) || sameText(toOption(chosen).label, text));
68
+ /* The "Add" row leads the list, so `Enter` adds exactly what was typed and the arrow keys still
69
+ reach the suggestions beneath it. It is offered only while the text names nothing that exists. */
70
+ const createItem = creatable && trimmedQuery !== "" && !isChosen(trimmedQuery) && !flatOptions.some((option) => sameText(option.label, trimmedQuery))
71
+ ? { create: true, label: trimmedQuery, value: trimmedQuery }
72
+ : null;
73
+ const grouped = optionGroups.hasOptionGroups(options);
74
+ const sections = optionGroups.toOptionSections(options);
75
+ const items = grouped
76
+ ? [...(createItem ? [{ key: "create", items: [createItem] }] : []), ...sections]
77
+ : [...(createItem ? [createItem] : []), ...flatOptions];
78
+ /* Reports a change and, unless the application refused it through Base's `cancel()`, applies it.
79
+ Returns whether it was applied. */
80
+ const commitValues = (next, eventDetails) => {
81
+ onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(next, eventDetails);
82
+ if ("isCanceled" in eventDetails && eventDetails.isCanceled)
83
+ return false;
84
+ if (value === undefined)
85
+ setUncontrolledValues(next);
86
+ return true;
87
+ };
88
+ /* Pasting several lines adds one entry per line. An entry that names an option takes that option;
89
+ one that is already chosen — or repeats an earlier line — is skipped and reported, so a long list
90
+ pasted twice cannot double up. A single line is ordinary typing and is left to the input. */
91
+ const handlePaste = (event) => {
92
+ if (!creatable || readOnly || disabled)
93
+ return;
94
+ const pasted = event.clipboardData.getData("text");
95
+ if (!/[\r\n]/.test(pasted))
96
+ return;
97
+ event.preventDefault();
98
+ const lines = pasted.split(/\r?\n|\r/).map((line) => line.trim()).filter(Boolean);
99
+ const next = [...values];
100
+ const added = [];
101
+ const skipped = [];
102
+ for (const line of lines) {
103
+ const match = flatOptions.find((option) => sameText(option.label, line) || sameText(option.value, line));
104
+ const entry = match ? match.value : line;
105
+ const duplicate = next.some((chosen) => sameText(chosen, entry) || sameText(toOption(chosen).label, line));
106
+ if (duplicate || (match === null || match === void 0 ? void 0 : match.disabled))
107
+ skipped.push(line);
108
+ else {
109
+ next.push(entry);
110
+ added.push(line);
111
+ }
112
+ }
113
+ if (added.length > 0)
114
+ commitValues(next, { reason: "input-paste", event: event.nativeEvent });
115
+ flagNotice(added.length, skipped);
116
+ };
117
+ const flagNotice = (addedCount, skipped) => {
118
+ const visible = skipped.length === 0
119
+ ? ""
120
+ : `Skipped ${skipped.length === 1 ? "1 duplicate" : `${skipped.length} duplicates`}: ${skipped.join(", ")}.`;
121
+ const added = addedCount === 0 ? "" : `Added ${addedCount === 1 ? "1 entry" : `${addedCount} entries`}.`;
122
+ setNotice({ visible, announced: [added, visible].filter(Boolean).join(" ") });
123
+ };
124
+ const handleInputValueChange = (next, eventDetails) => {
125
+ onInputValueChange === null || onInputValueChange === void 0 ? void 0 : onInputValueChange(next, eventDetails);
126
+ if (eventDetails.isCanceled)
127
+ return;
128
+ if (inputValue === undefined)
129
+ setUncontrolledQuery(next);
130
+ if (next !== "" && notice.announced !== "")
131
+ setNotice({ visible: "", announced: "" });
132
+ };
133
+ const renderItem = (option) => isCreateItem(option) ? (jsxRuntime.jsxs(combobox.Combobox.Item, { value: option, className: utils.cn(ui_common.list.option, "justify-start gap-3"), children: [jsxRuntime.jsx(lucideReact.Plus, { "aria-hidden": "true", className: utils.cn("size-4 shrink-0", ui_common.tone.text.primary) }), jsxRuntime.jsx("span", { className: utils.cn("min-w-0 flex-1 truncate"), children: createLabel(option.label) })] }, "sui-create")) : (jsxRuntime.jsxs(combobox.Combobox.Item, { value: option, disabled: option.disabled, className: ({ selected: isSelected }) => utils.cn(ui_common.list.option, isSelected && utils.cn(ui_common.tone.selected.primary, ui_common.elevation.control)), children: [jsxRuntime.jsx("span", { className: utils.cn("min-w-0 flex-1 truncate"), children: option.label }), jsxRuntime.jsx(combobox.Combobox.ItemIndicator, { children: jsxRuntime.jsx(lucideReact.Check, { "aria-hidden": "true", className: utils.cn("size-4", ui_motion.motionArrive, ui_common.tone.text.primary) }) })] }, option.value));
134
+ const input = (chosenCount) => (jsxRuntime.jsx(combobox.Combobox.Input, { ref: ref, placeholder: chosenCount > 0 ? undefined : placeholder, onPaste: handlePaste, className: utils.cn("min-w-0 flex-1 bg-transparent outline-none placeholder:text-sherick-ink-muted disabled:cursor-not-allowed", multiple && "h-7 min-w-16") }));
135
+ const selectedOptions = values.map(toOption);
136
+ /* Base types its single and multiple roots as two different components; the value contract is
137
+ chosen here, once, and the rest of the root is shared. */
138
+ const selectionProps = (multiple
139
+ ? {
140
+ multiple: true,
141
+ value: selectedOptions,
142
+ onValueChange: (next, eventDetails) => {
143
+ const created = next.find(isCreateItem);
144
+ const removed = values.filter((chosen) => !next.some((option) => option.value === chosen));
145
+ const added = next.filter((option) => !values.includes(option.value));
146
+ /* An option whose text names an entry already chosen — a created "book of dead" before the
147
+ catalog's "Book of Dead" — is a duplicate under another value, so it is refused too. */
148
+ if (creatable &&
149
+ added.length === 1 &&
150
+ !isCreateItem(added[0]) &&
151
+ isChosen(added[0].label)) {
152
+ eventDetails.cancel();
153
+ flagNotice(0, [added[0].label]);
154
+ return;
155
+ }
156
+ /* With a query typed, `Enter` on an option that is already chosen would quietly remove
157
+ it. Naming an entry that exists is a duplicate, not a removal, so it is refused and
158
+ reported; the chip's own control and Backspace still remove. */
159
+ if (creatable &&
160
+ eventDetails.reason === "item-press" &&
161
+ eventDetails.event instanceof KeyboardEvent &&
162
+ removed.length === 1 &&
163
+ trimmedQuery !== "" &&
164
+ sameText(toOption(removed[0]).label, trimmedQuery)) {
165
+ eventDetails.cancel();
166
+ flagNotice(0, [trimmedQuery]);
167
+ return;
168
+ }
169
+ const applied = commitValues(next.map((option) => option.value), eventDetails);
170
+ if (applied && created) {
171
+ /* Base keeps the typed filter while the list stays open, so several matches can be
172
+ chosen from one query. A created entry used the query up, so it starts over. */
173
+ onInputValueChange === null || onInputValueChange === void 0 ? void 0 : onInputValueChange("", eventDetails);
174
+ if (inputValue === undefined)
175
+ setUncontrolledQuery("");
176
+ flagNotice(1, []);
177
+ }
178
+ },
179
+ }
180
+ : {
181
+ value: value === undefined ? undefined : value == null ? null : ((_b = optionByValue.get(value)) !== null && _b !== void 0 ? _b : null),
182
+ defaultValue: defaultValue == null ? null : ((_c = optionByValue.get(defaultValue)) !== null && _c !== void 0 ? _c : null),
183
+ onValueChange: (next, eventDetails) => { var _a; return onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange((_a = next === null || next === void 0 ? void 0 : next.value) !== null && _a !== void 0 ? _a : null, eventDetails); },
184
+ });
185
+ return (jsxRuntime.jsxs(combobox.Combobox.Root, { ...rootProps, items: items, ...selectionProps,
37
186
  // The public value is the option's own `value`, so two equal options are equal even when a
38
187
  // caller rebuilds its options array every render.
39
- isItemEqualToValue: (itemValue, currentValue) => (itemValue === null || itemValue === void 0 ? void 0 : itemValue.value) === (currentValue === null || currentValue === void 0 ? void 0 : currentValue.value), onValueChange: (next, eventDetails) => { var _a; return onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange((_a = next === null || next === void 0 ? void 0 : next.value) !== null && _a !== void 0 ? _a : null, eventDetails); }, filter: filter ? (item, query) => filter(item, query) : filter, disabled: disabled, readOnly: readOnly, children: [jsxRuntime.jsxs(combobox.Combobox.InputGroup, { className: ({ open, disabled: fieldDisabled }) => utils.cn(
188
+ isItemEqualToValue: (itemValue, currentValue) => (itemValue === null || itemValue === void 0 ? void 0 : itemValue.value) === (currentValue === null || currentValue === void 0 ? void 0 : currentValue.value), filter: filter
189
+ ? (item, search) => isCreateItem(item) || filter(item, search)
190
+ : filter, autoHighlight: autoHighlight !== null && autoHighlight !== void 0 ? autoHighlight : (creatable ? true : undefined), ...(creatable ? { inputValue: query } : { inputValue, defaultInputValue }), onInputValueChange: handleInputValueChange, onOpenChange: (open, eventDetails) => {
191
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(open, eventDetails);
192
+ /* Several choices are made from one open list: choosing one keeps the list where it is, so
193
+ the next can be chosen without reopening it. Escape, Tab and a press outside still close. */
194
+ if (multiple && !open && eventDetails.reason === "item-press")
195
+ eventDetails.cancel();
196
+ }, disabled: disabled, readOnly: readOnly, children: [jsxRuntime.jsxs(combobox.Combobox.InputGroup, { className: ({ open, disabled: fieldDisabled }) => utils.cn(
40
197
  /* The field's own inline padding is what places the trailing cluster, and it is set on the
41
198
  logical ends so the cluster stays at the field's end in either writing direction. The
42
- 20px a mark's box then sits from the edge — 12px of padding plus the 8px each `density.part`
199
+ 20px a mark's box then sits from the edge — 14px of padding plus the 6px each `density.part`
43
200
  holds around its 20px glyph — is the same 20px the input's own leading padding uses, so the
44
- field reads with one inset at both ends. */
45
- "group/field flex min-w-0 w-full items-center ps-5 pe-3", ui_common.density.normal, ui_common.shape.control, ui_common.material.control, ui_common.rim.field, ui_motion.motionTactileField, ui_common.focusRingWithin, !fieldDisabled && !open && ui_common.state.field.hover, !fieldDisabled && ui_common.state.field.focusWithin, open && ui_common.state.field.engaged, ui_common.state.field.invalid, open && ui_common.state.field.invalidEngaged, !fieldDisabled && !open && ui_common.state.field.invalidHover, !fieldDisabled && ui_common.state.field.invalidFocusWithin, fieldDisabled ? ui_common.state.disabled : ui_common.state.text, className), children: [jsxRuntime.jsx(combobox.Combobox.Input, { ref: ref, placeholder: placeholder, className: utils.cn("min-w-0 flex-1 bg-transparent outline-none placeholder:text-sherick-ink-muted disabled:cursor-not-allowed") }), jsxRuntime.jsx(combobox.Combobox.Clear, { "aria-label": "Clear selection",
201
+ field reads with one inset at both ends. Once chips lead the field, its start inset
202
+ drops to the chips' own block inset, so the first pill sits as far from the field's
203
+ start as from its top. */
204
+ "group/field flex min-w-0 w-full items-center ps-5 pe-3.5", multiple && "has-[[data-sui-value-chip]]:ps-2.5", ui_common.density.normal, ui_common.shape.control, ui_common.material.control, ui_common.rim.field, ui_motion.motionTactileField, ui_common.focusRingWithin, !fieldDisabled && !open && ui_common.state.field.hover, !fieldDisabled && ui_common.state.field.focusWithin, open && ui_common.state.field.engaged, ui_common.state.field.invalid, open && ui_common.state.field.invalidEngaged, !fieldDisabled && !open && ui_common.state.field.invalidHover, !fieldDisabled && ui_common.state.field.invalidFocusWithin, fieldDisabled ? ui_common.state.disabled : ui_common.state.text, className), children: [multiple ? (
205
+ /* The chips and the input wrap together, so a long selection grows the field downward
206
+ rather than squeezing the query. Base names the row a toolbar once it holds chips. */
207
+ jsxRuntime.jsxs(combobox.Combobox.Chips, { "aria-label": selectedOptions.length > 0 ? chipsLabel : undefined, className: utils.cn("flex min-w-0 flex-1 flex-wrap items-center gap-1.5 py-2"), children: [selectedOptions.map((option) => (jsxRuntime.jsxs(combobox.Combobox.Chip, { "data-sui-value-chip": "", "aria-readonly": undefined,
208
+ // Without its dismiss target the chip ends on its copy, so it takes its start inset again.
209
+ className: utils.cn(valueChipClassName, (readOnly || disabled) && "pe-3"), children: [jsxRuntime.jsx("span", { className: utils.cn("min-w-0 truncate"), children: option.label }), !readOnly && !disabled && (jsxRuntime.jsx(combobox.Combobox.ChipRemove, { "aria-label": `Remove ${option.label}`, className: utils.cn(chipRemoveClassName), children: jsxRuntime.jsx("span", { className: utils.cn("inline-flex items-center justify-center", ui_motion.motionInkPress), children: jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true", className: utils.cn("size-4") }) }) }))] }, option.value))), input(selectedOptions.length)] })) : (input(0)), jsxRuntime.jsx(combobox.Combobox.Clear, { "aria-label": multiple ? "Clear all" : "Clear selection",
46
210
  // Clearing changes the value, so a read-only control cannot offer it — which is Base's own
47
211
  // reading of the same state, since its clear control refuses the press.
48
- disabled: disabled || readOnly, className: utils.cn(partClassName), children: jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" }) }), jsxRuntime.jsx(combobox.Combobox.Trigger, { "aria-label": "Show options", className: utils.cn(partClassName, "group"), children: jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": "true", className: utils.cn("size-5", ui_motion.motionOrient, "group-data-[popup-open]:rotate-180") }) })] }), jsxRuntime.jsx(combobox.Combobox.Portal, { children: jsxRuntime.jsx(combobox.Combobox.Positioner, { side: "bottom", align: "start", sideOffset: 8, className: utils.cn(ui_common.stacking.float), children: jsxRuntime.jsxs(combobox.Combobox.Popup, { className: utils.cn(ui_common.list.sheet, "w-max min-w-[var(--anchor-width)] p-2", ui_common.overlay.popup, ui_motion.motionPresenceAnchored), children: [jsxRuntime.jsx(combobox.Combobox.Empty, { children: jsxRuntime.jsx("div", { className: utils.cn("px-4 py-3 text-sm", ui_common.text.medium), children: emptyMessage }) }), jsxRuntime.jsx(combobox.Combobox.List, { className: utils.cn("space-y-1"), children: (option) => (jsxRuntime.jsxs(combobox.Combobox.Item, { value: option, disabled: option.disabled, className: ({ selected: isSelected }) => utils.cn(ui_common.list.option, isSelected && utils.cn(ui_common.tone.selected.primary, ui_common.elevation.control)), children: [jsxRuntime.jsx("span", { className: utils.cn("min-w-0 flex-1 truncate"), children: option.label }), jsxRuntime.jsx(combobox.Combobox.ItemIndicator, { children: jsxRuntime.jsx(lucideReact.Check, { "aria-hidden": "true", className: utils.cn("size-4", ui_motion.motionArrive, ui_common.tone.text.primary) }) })] }, option.value)) })] }) }) })] }));
212
+ disabled: disabled || readOnly, className: utils.cn(partClassName), children: jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" }) }), jsxRuntime.jsx(combobox.Combobox.Trigger, { "aria-label": "Show options", className: utils.cn(partClassName, "group"), children: jsxRuntime.jsx(lucideReact.ChevronDown, { "aria-hidden": "true", className: utils.cn("size-5", ui_motion.motionOrient, "group-data-[popup-open]:rotate-180") }) })] }), creatable && (
213
+ /* Mounted from the start so a screen reader is already listening when a paste or a refused
214
+ duplicate reports itself. Only the skipped entries are shown: the chips already show what
215
+ was added. While the list is open Base hides everything outside it from assistive
216
+ technology, so the same report is also made from inside the list (below). */
217
+ jsxRuntime.jsx("div", { role: "status", className: utils.cn(notice.visible !== "" && ui_common.fieldMessage.description), children: notice.announced === notice.visible ? (notice.visible) : (
218
+ // The spoken report is the fuller one; the visible line is not read a second time.
219
+ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { "aria-hidden": "true", children: notice.visible }), jsxRuntime.jsx("span", { className: utils.cn("sr-only"), children: notice.announced })] })) })), jsxRuntime.jsx(combobox.Combobox.Portal, { children: jsxRuntime.jsx(combobox.Combobox.Positioner, { side: "bottom", align: "start", sideOffset: 8, className: utils.cn(ui_common.stacking.float), children: jsxRuntime.jsxs(combobox.Combobox.Popup, { className: utils.cn(ui_common.list.sheet, "w-max min-w-[var(--anchor-width)] p-2", ui_common.overlay.popup, ui_motion.motionPresenceAnchored), children: [creatable && (jsxRuntime.jsx(combobox.Combobox.Status, { className: utils.cn("sr-only"), children: notice.announced })), jsxRuntime.jsx(combobox.Combobox.Empty, { children: jsxRuntime.jsx("div", { className: utils.cn("px-4 py-3 text-sm", ui_common.text.medium), children: emptyMessage !== null && emptyMessage !== void 0 ? emptyMessage : (creatable ? "Type to add an entry." : "No results found.") }) }), jsxRuntime.jsx(combobox.Combobox.List, { className: utils.cn("space-y-1"), children: grouped
220
+ ? (section) => (
221
+ /* A heading names the group it opens. A run of options outside every group is a
222
+ section without one, because the primitive reads a list as all groups or none. */
223
+ jsxRuntime.jsxs(combobox.Combobox.Group, { items: section.items, className: utils.cn("space-y-1"), children: [section.label !== undefined && (jsxRuntime.jsx(combobox.Combobox.GroupLabel, { className: utils.cn(ui_common.list.groupLabel), children: section.label })), jsxRuntime.jsx(combobox.Combobox.Collection, { children: renderItem })] }, section.key))
224
+ : renderItem })] }) }) })] }));
49
225
  });
50
226
  Combobox.displayName = "Combobox";
51
227