ionbase-ui 0.84.0 → 0.88.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/dist/components/Checkbox.d.ts +39 -0
- package/dist/components/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox.js +77 -4
- package/dist/components/Checkbox.js.map +1 -1
- package/dist/components/Fieldset.d.ts +62 -0
- package/dist/components/Fieldset.d.ts.map +1 -0
- package/dist/components/Fieldset.js +58 -0
- package/dist/components/Fieldset.js.map +1 -0
- package/dist/components/MultiSelect.d.ts +90 -0
- package/dist/components/MultiSelect.d.ts.map +1 -0
- package/dist/components/MultiSelect.js +189 -0
- package/dist/components/MultiSelect.js.map +1 -0
- package/dist/components/Radio.d.ts +14 -0
- package/dist/components/Radio.d.ts.map +1 -1
- package/dist/components/Radio.js +15 -4
- package/dist/components/Radio.js.map +1 -1
- package/dist/components/SearchField.d.ts +36 -0
- package/dist/components/SearchField.d.ts.map +1 -0
- package/dist/components/SearchField.js +76 -0
- package/dist/components/SearchField.js.map +1 -0
- package/dist/components/Toolbar.d.ts +35 -0
- package/dist/components/Toolbar.d.ts.map +1 -0
- package/dist/components/Toolbar.js +81 -0
- package/dist/components/Toolbar.js.map +1 -0
- package/dist/components/index.d.ts +10 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -1
- package/dist/components/index.js.map +1 -1
- package/dist/figma-descriptions.json +97 -77
- package/dist/figma-map.json +228 -4
- package/dist/meta/Checkbox.json +8 -6
- package/dist/meta/CheckboxGroup.json +268 -0
- package/dist/meta/Combobox.json +8 -0
- package/dist/meta/Divider.json +2 -2
- package/dist/meta/Fieldset.json +162 -0
- package/dist/meta/MultiSelect.json +269 -0
- package/dist/meta/Radio.json +0 -1
- package/dist/meta/RadioGroup.json +59 -7
- package/dist/meta/SearchField.json +487 -0
- package/dist/meta/Select.json +2 -1
- package/dist/meta/Stepper.json +2 -2
- package/dist/meta/Tabs.json +3 -3
- package/dist/meta/Toolbar.json +130 -0
- package/dist/meta/components.json +1616 -238
- package/dist/meta/contrast.json +398 -74
- package/dist/meta/index.json +84 -8
- package/dist/meta/patterns/DataTable.json +33 -6
- package/dist/meta/patterns/Form.json +27 -2
- package/dist/meta/patterns/index.json +6 -2
- package/dist/styles/fieldset.css +65 -0
- package/dist/styles/index.css +4 -0
- package/dist/styles/multi-select.css +104 -0
- package/dist/styles/radio.css +0 -20
- package/dist/styles/search-field.css +70 -0
- package/dist/styles/toolbar.css +36 -0
- package/llms.txt +2 -2
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { type FieldsetOrientation } from './Fieldset.js';
|
|
2
3
|
import { type SelectionProps } from './resolve-selection.js';
|
|
3
4
|
export type CheckboxSize = 'sm' | 'md' | 'lg';
|
|
4
5
|
export type CheckboxIntent = 'brand' | 'neutral' | 'danger';
|
|
@@ -34,4 +35,42 @@ export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputE
|
|
|
34
35
|
* declaratively and it must be written after every render.
|
|
35
36
|
*/
|
|
36
37
|
export declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
|
|
38
|
+
export interface CheckboxGroupProps extends Omit<React.FieldsetHTMLAttributes<HTMLFieldSetElement>, 'onChange' | 'defaultValue' | 'disabled'> {
|
|
39
|
+
/** The question the options answer. Renders as the `<legend>`. */
|
|
40
|
+
label?: React.ReactNode;
|
|
41
|
+
/** Help text beneath the options. Replaced by `errorMessage` while invalid. */
|
|
42
|
+
description?: React.ReactNode;
|
|
43
|
+
/** Shown in the description's place while `isInvalid` is set. */
|
|
44
|
+
errorMessage?: React.ReactNode;
|
|
45
|
+
/** Marks every box invalid and shows `errorMessage`. */
|
|
46
|
+
isInvalid?: boolean;
|
|
47
|
+
/** At least one option must be selected — enforced by native validation. */
|
|
48
|
+
isRequired?: boolean;
|
|
49
|
+
/** The selected values (controlled). */
|
|
50
|
+
value?: readonly string[];
|
|
51
|
+
/** The initially selected values (uncontrolled). */
|
|
52
|
+
defaultValue?: readonly string[];
|
|
53
|
+
/** Receives the whole new selection, in the order the options were ticked. */
|
|
54
|
+
onChange?: (value: string[]) => void;
|
|
55
|
+
/** Shared input name, so a form submits every ticked value under it. */
|
|
56
|
+
name?: string;
|
|
57
|
+
size?: CheckboxSize;
|
|
58
|
+
intent?: CheckboxIntent;
|
|
59
|
+
/** Whether every checkbox in the group is disabled. */
|
|
60
|
+
isDisabled?: boolean;
|
|
61
|
+
orientation?: FieldsetOrientation;
|
|
62
|
+
/** Checkboxes, each with a `value`. */
|
|
63
|
+
children?: React.ReactNode;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A set of checkboxes that answers one question — "notify me when…", "which
|
|
67
|
+
* regions". Owns the selected values, the group's label, help text and error,
|
|
68
|
+
* and "select at least one".
|
|
69
|
+
*
|
|
70
|
+
* A row of loose Checkboxes can do none of that accessibly: the question is
|
|
71
|
+
* not announced with the options, an error has nothing to attach to, and
|
|
72
|
+
* "at least one" has no native expression at all. See the `required` note in
|
|
73
|
+
* Checkbox for how that last one is done.
|
|
74
|
+
*/
|
|
75
|
+
export declare const CheckboxGroup: React.ForwardRefExoticComponent<CheckboxGroupProps & React.RefAttributes<HTMLFieldSetElement>>;
|
|
37
76
|
//# sourceMappingURL=Checkbox.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../src/components/Checkbox.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../src/components/Checkbox.tsx"],"names":[],"mappings":"AAEA,OAAO,KAQN,MAAM,OAAO,CAAC;AACf,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE/E,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC9C,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAwB5D,MAAM,WAAW,aACf,SACE,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,EAClE,cAAc;IAChB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,iEAAiE;IACjE,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AA2BD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,QAAQ,wFAsGpB,CAAC;AAIF,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAC9C,KAAK,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EACjD,UAAU,GAAG,cAAc,GAAG,UAAU,CACzC;IACC,kEAAkE;IAClE,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,iEAAiE;IACjE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,oDAAoD;IACpD,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,uDAAuD;IACvD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,gGA+DxB,CAAC"}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { forwardRef,
|
|
3
|
+
import { createContext, forwardRef, useContext, useEffect, useImperativeHandle, useRef, useState, } from 'react';
|
|
4
|
+
import { FieldsetShell, useFieldsetHelper, } from './Fieldset.js';
|
|
4
5
|
import { resolveDisabled } from './resolve-disabled.js';
|
|
5
6
|
import { resolveSelection } from './resolve-selection.js';
|
|
7
|
+
/**
|
|
8
|
+
* Lets CheckboxGroup own the selected values the way RadioGroup owns the
|
|
9
|
+
* selected value: each Checkbox reads whether its `value` is in the set and
|
|
10
|
+
* reports its toggles, and the caller wires one `onChange` instead of one per
|
|
11
|
+
* option.
|
|
12
|
+
*/
|
|
13
|
+
const CheckboxGroupContext = createContext(null);
|
|
6
14
|
/** Figma's check glyph. Inlined for the same reason as Select's chevron: it is
|
|
7
15
|
* part of the control, not a slot a caller fills. */
|
|
8
16
|
const CheckMark = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "m5 13 4 4L19 7", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
@@ -20,9 +28,35 @@ const DashMark = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", "aria-
|
|
|
20
28
|
* declaratively and it must be written after every render.
|
|
21
29
|
*/
|
|
22
30
|
export const Checkbox = forwardRef((props, forwardedRef) => {
|
|
23
|
-
const
|
|
24
|
-
const
|
|
31
|
+
const group = useContext(CheckboxGroupContext);
|
|
32
|
+
const { size = group?.size ?? 'md', intent = group?.intent ?? 'brand', isIndeterminate = false, className, children, isDisabled, disabled, isSelected, checked, onChange, onSelectionChange, name = group?.name, 'aria-describedby': describedBy, ...rest } = props;
|
|
33
|
+
const resolvedDisabled = resolveDisabled(isDisabled, disabled) ?? group?.isDisabled;
|
|
25
34
|
const selection = resolveSelection(isSelected, checked, onChange, onSelectionChange);
|
|
35
|
+
/*
|
|
36
|
+
* Inside a group the group owns `checked`, and the box's own handlers still
|
|
37
|
+
* fire after it — the contract RadioGroup settled on, so neither control
|
|
38
|
+
* honours a handler in one mode and drops it in the other.
|
|
39
|
+
*/
|
|
40
|
+
const value = rest.value === undefined ? '' : String(rest.value);
|
|
41
|
+
const groupSelection = group
|
|
42
|
+
? {
|
|
43
|
+
checked: group.selected.includes(value),
|
|
44
|
+
onChange: (event) => {
|
|
45
|
+
group.toggle(value, event.target.checked);
|
|
46
|
+
selection.onChange?.(event);
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
: selection;
|
|
50
|
+
/*
|
|
51
|
+
* "Select at least one", in the platform's own words. `required` on a
|
|
52
|
+
* checkbox means "this one must be ticked", so it is set on every box while
|
|
53
|
+
* none is and dropped from all of them the moment one is: native
|
|
54
|
+
* validation then blocks the submit with the browser's localised message,
|
|
55
|
+
* and each box announces "required" exactly while the rule is unmet.
|
|
56
|
+
*/
|
|
57
|
+
const required = group?.isRequired
|
|
58
|
+
? group.selected.length === 0
|
|
59
|
+
: rest.required;
|
|
26
60
|
const domRef = useRef(null);
|
|
27
61
|
useImperativeHandle(forwardedRef, () => domRef.current);
|
|
28
62
|
useEffect(() => {
|
|
@@ -38,7 +72,46 @@ export const Checkbox = forwardRef((props, forwardedRef) => {
|
|
|
38
72
|
]
|
|
39
73
|
.filter(Boolean)
|
|
40
74
|
.join(' ');
|
|
41
|
-
return (_jsxs("label", { className: classNames, children: [_jsx("input", { ...rest, ref: domRef, type: "checkbox", checked:
|
|
75
|
+
return (_jsxs("label", { className: classNames, children: [_jsx("input", { ...rest, ref: domRef, type: "checkbox", name: name, required: required, checked: groupSelection.checked, onChange: groupSelection.onChange, disabled: resolvedDisabled, "aria-invalid": group?.isInvalid || rest['aria-invalid'], "aria-describedby": [describedBy, group?.helperId].filter(Boolean).join(' ') ||
|
|
76
|
+
undefined, className: "ion-checkbox__input" }), _jsx("span", { className: "ion-checkbox__indicator", "aria-hidden": "true", children: _jsx("span", { className: "ion-checkbox__mark", children: isIndeterminate ? _jsx(DashMark, {}) : _jsx(CheckMark, {}) }) }), children && _jsx("span", { className: "ion-checkbox__label", children: children })] }));
|
|
42
77
|
});
|
|
43
78
|
Checkbox.displayName = 'Checkbox';
|
|
79
|
+
/**
|
|
80
|
+
* A set of checkboxes that answers one question — "notify me when…", "which
|
|
81
|
+
* regions". Owns the selected values, the group's label, help text and error,
|
|
82
|
+
* and "select at least one".
|
|
83
|
+
*
|
|
84
|
+
* A row of loose Checkboxes can do none of that accessibly: the question is
|
|
85
|
+
* not announced with the options, an error has nothing to attach to, and
|
|
86
|
+
* "at least one" has no native expression at all. See the `required` note in
|
|
87
|
+
* Checkbox for how that last one is done.
|
|
88
|
+
*/
|
|
89
|
+
export const CheckboxGroup = forwardRef((props, ref) => {
|
|
90
|
+
const { value: controlledValue, defaultValue, onChange, name, size, intent, isDisabled, isRequired, description, errorMessage, ...rest } = props;
|
|
91
|
+
const [uncontrolled, setUncontrolled] = useState(defaultValue ?? []);
|
|
92
|
+
const selected = controlledValue ?? uncontrolled;
|
|
93
|
+
const toggle = (value, isSelected) => {
|
|
94
|
+
const next = isSelected
|
|
95
|
+
? selected.includes(value)
|
|
96
|
+
? [...selected]
|
|
97
|
+
: [...selected, value]
|
|
98
|
+
: selected.filter((v) => v !== value);
|
|
99
|
+
if (controlledValue === undefined)
|
|
100
|
+
setUncontrolled(next);
|
|
101
|
+
onChange?.(next);
|
|
102
|
+
};
|
|
103
|
+
const { helper, helperId } = useFieldsetHelper(description, errorMessage, rest.isInvalid);
|
|
104
|
+
return (_jsx(CheckboxGroupContext.Provider, { value: {
|
|
105
|
+
name,
|
|
106
|
+
selected,
|
|
107
|
+
toggle,
|
|
108
|
+
size,
|
|
109
|
+
intent,
|
|
110
|
+
isDisabled,
|
|
111
|
+
isInvalid: rest.isInvalid,
|
|
112
|
+
isRequired,
|
|
113
|
+
helperId,
|
|
114
|
+
}, children: _jsx(FieldsetShell, { ...rest, ref: ref, disabled: isDisabled, isChoiceGroup: true, helper: helper, helperId: helperId }) }));
|
|
115
|
+
});
|
|
116
|
+
CheckboxGroup.displayName = 'CheckboxGroup';
|
|
44
117
|
//# sourceMappingURL=Checkbox.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../src/components/Checkbox.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAc,EACZ,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../src/components/Checkbox.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAc,EACZ,aAAa,EACb,UAAU,EACV,UAAU,EACV,SAAS,EACT,mBAAmB,EACnB,MAAM,EACN,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EACL,aAAa,EACb,iBAAiB,GAElB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAuB,MAAM,wBAAwB,CAAC;AAiB/E;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,aAAa,CACxC,IAAI,CACL,CAAC;AAyBF;sDACsD;AACtD,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,CACtB,cAAK,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,iBAAa,MAAM,EAAC,SAAS,EAAC,OAAO,YACvE,eACE,CAAC,EAAC,gBAAgB,EAClB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GACtB,GACE,CACP,CAAC;AAEF,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,CACrB,cAAK,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,iBAAa,MAAM,EAAC,SAAS,EAAC,OAAO,YACvE,eACE,CAAC,EAAC,UAAU,EACZ,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,GACE,CACP,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAChC,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE;IACtB,MAAM,KAAK,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAC/C,MAAM,EACJ,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,IAAI,EAC1B,MAAM,GAAG,KAAK,EAAE,MAAM,IAAI,OAAO,EACjC,eAAe,GAAG,KAAK,EACvB,SAAS,EACT,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,UAAU,EACV,OAAO,EACP,QAAQ,EACR,iBAAiB,EACjB,IAAI,GAAG,KAAK,EAAE,IAAI,EAClB,kBAAkB,EAAE,WAAW,EAC/B,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,gBAAgB,GACpB,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,KAAK,EAAE,UAAU,CAAC;IAC7D,MAAM,SAAS,GAAG,gBAAgB,CAChC,UAAU,EACV,OAAO,EACP,QAAQ,EACR,iBAAiB,CAClB,CAAC;IAEF;;;;OAIG;IACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjE,MAAM,cAAc,GAAG,KAAK;QAC1B,CAAC,CAAC;YACE,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvC,QAAQ,EAAE,CAAC,KAA0C,EAAE,EAAE;gBACvD,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC1C,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;SACF;QACH,CAAC,CAAC,SAAS,CAAC;IAEd;;;;;;OAMG;IACH,MAAM,QAAQ,GAAG,KAAK,EAAE,UAAU;QAChC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC7B,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;IAElB,MAAM,MAAM,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAC9C,mBAAmB,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAQ,CAAC,CAAC;IAEzD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,CAAC,OAAO;YAAE,MAAM,CAAC,OAAO,CAAC,aAAa,GAAG,eAAe,CAAC;IACrE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,MAAM,UAAU,GAAG;QACjB,cAAc;QACd,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;QAC5C,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;QACnD,gBAAgB,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE;QAChD,SAAS,IAAI,EAAE;KAChB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,OAAO,CACL,iBAAO,SAAS,EAAE,UAAU,aAC1B,mBACM,IAAI,EACR,GAAG,EAAE,MAAM,EACX,IAAI,EAAC,UAAU,EACf,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,cAAc,CAAC,OAAO,EAC/B,QAAQ,EAAE,cAAc,CAAC,QAAQ,EACjC,QAAQ,EAAE,gBAAgB,kBACZ,KAAK,EAAE,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC,sBAIpD,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;oBACxD,SAAS,EAEX,SAAS,EAAC,qBAAqB,GAC/B,EACF,eAAM,SAAS,EAAC,yBAAyB,iBAAa,MAAM,YAC1D,eAAM,SAAS,EAAC,oBAAoB,YACjC,eAAe,CAAC,CAAC,CAAC,KAAC,QAAQ,KAAG,CAAC,CAAC,CAAC,KAAC,SAAS,KAAG,GAC1C,GACF,EACN,QAAQ,IAAI,eAAM,SAAS,EAAC,qBAAqB,YAAE,QAAQ,GAAQ,IAC9D,CACT,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAC;AAiClC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAGrC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IACf,MAAM,EACJ,KAAK,EAAE,eAAe,EACtB,YAAY,EACZ,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAC9C,YAAY,IAAI,EAAE,CACnB,CAAC;IACF,MAAM,QAAQ,GAAG,eAAe,IAAI,YAAY,CAAC;IAEjD,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,UAAmB,EAAE,EAAE;QACpD,MAAM,IAAI,GAAG,UAAU;YACrB,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACxB,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;gBACf,CAAC,CAAC,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC;YACxB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC;QACxC,IAAI,eAAe,KAAK,SAAS;YAAE,eAAe,CAAC,IAAI,CAAC,CAAC;QACzD,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,iBAAiB,CAC5C,WAAW,EACX,YAAY,EACZ,IAAI,CAAC,SAAS,CACf,CAAC;IAEF,OAAO,CACL,KAAC,oBAAoB,CAAC,QAAQ,IAC5B,KAAK,EAAE;YACL,IAAI;YACJ,QAAQ;YACR,MAAM;YACN,IAAI;YACJ,MAAM;YACN,UAAU;YACV,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU;YACV,QAAQ;SACT,YAED,KAAC,aAAa,OACR,IAAI,EACR,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,UAAU,EACpB,aAAa,QACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,GAClB,GAC4B,CACjC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type FieldsetOrientation = 'vertical' | 'horizontal';
|
|
3
|
+
export interface FieldsetProps extends Omit<React.FieldsetHTMLAttributes<HTMLFieldSetElement>, 'disabled'> {
|
|
4
|
+
/** The question the fields answer. Renders as the `<legend>`. */
|
|
5
|
+
label?: React.ReactNode;
|
|
6
|
+
/** Help text beneath the fields. Replaced by `errorMessage` while invalid. */
|
|
7
|
+
description?: React.ReactNode;
|
|
8
|
+
/** Shown in the description's place while `isInvalid` is set. */
|
|
9
|
+
errorMessage?: React.ReactNode;
|
|
10
|
+
/** Whether the group as a whole fails validation. */
|
|
11
|
+
isInvalid?: boolean;
|
|
12
|
+
/** How the fields flow. Horizontal wraps rather than overflowing. */
|
|
13
|
+
orientation?: FieldsetOrientation;
|
|
14
|
+
children?: React.ReactNode;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The ids a group hands down to its own controls. Kept separate from the
|
|
18
|
+
* rendering so CheckboxGroup and RadioGroup can give every checkbox and radio
|
|
19
|
+
* the same `aria-describedby` the fieldset carries — see FieldsetShell.
|
|
20
|
+
*/
|
|
21
|
+
export declare function useFieldsetHelper(description: React.ReactNode, errorMessage: React.ReactNode, isInvalid: boolean | undefined): {
|
|
22
|
+
helper: React.ReactNode;
|
|
23
|
+
helperId: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
interface FieldsetShellProps extends Omit<FieldsetProps, 'description' | 'errorMessage'> {
|
|
26
|
+
/** Only the choice groups may disable natively — see Fieldset. */
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
/** Choice groups space their options at 8, not a form's 16. */
|
|
29
|
+
isChoiceGroup?: boolean;
|
|
30
|
+
/** The description or the error, whichever shows — see useFieldsetHelper. */
|
|
31
|
+
helper: React.ReactNode;
|
|
32
|
+
helperId: string | undefined;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The rendering shared by Fieldset, CheckboxGroup and RadioGroup.
|
|
36
|
+
*
|
|
37
|
+
* A real `<fieldset>`: the legend names the group for assistive technology and
|
|
38
|
+
* the inputs stay grouped for form submission, neither of which a div with
|
|
39
|
+
* `role="group"` gets for free.
|
|
40
|
+
*
|
|
41
|
+
* The fieldset is `display: block` on purpose. A rendered `<legend>` is not a
|
|
42
|
+
* flex item — browsers lay it out in the fieldset's border, outside the flex
|
|
43
|
+
* container — so a flex column here would put `gap` everywhere but under the
|
|
44
|
+
* legend. The fields get a flex wrapper of their own instead.
|
|
45
|
+
*/
|
|
46
|
+
export declare const FieldsetShell: React.ForwardRefExoticComponent<FieldsetShellProps & React.RefAttributes<HTMLFieldSetElement>>;
|
|
47
|
+
/**
|
|
48
|
+
* Groups related fields under one label, with one description and one error —
|
|
49
|
+
* an address, a date range typed as two fields, a set of limits.
|
|
50
|
+
*
|
|
51
|
+
* For checkboxes use CheckboxGroup and for radios RadioGroup: both render this
|
|
52
|
+
* same shell, and add the selection state it deliberately does not own.
|
|
53
|
+
*
|
|
54
|
+
* There is no `isDisabled`. A native `disabled` fieldset does disable every
|
|
55
|
+
* control inside, but Input, Select and the rest draw their disabled state from
|
|
56
|
+
* their own prop, so the fields would stop working while still looking live.
|
|
57
|
+
* Disable the fields themselves; the choice groups can cascade because their
|
|
58
|
+
* checkboxes and radios style off `:disabled`.
|
|
59
|
+
*/
|
|
60
|
+
export declare const Fieldset: React.ForwardRefExoticComponent<FieldsetProps & React.RefAttributes<HTMLFieldSetElement>>;
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=Fieldset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Fieldset.d.ts","sourceRoot":"","sources":["../../src/components/Fieldset.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,YAAY,CAAC;AAE5D,MAAM,WAAW,aAAc,SAAQ,IAAI,CACzC,KAAK,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EACjD,UAAU,CACX;IACC,iEAAiE;IACjE,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,iEAAiE;IACjE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qEAAqE;IACrE,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,KAAK,CAAC,SAAS,EAC5B,YAAY,EAAE,KAAK,CAAC,SAAS,EAC7B,SAAS,EAAE,OAAO,GAAG,SAAS;;;EAM/B;AAED,UAAU,kBAAmB,SAAQ,IAAI,CACvC,aAAa,EACb,aAAa,GAAG,cAAc,CAC/B;IACC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6EAA6E;IAC7E,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,gGA4CxB,CAAC;AAIH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,2FAYpB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useId } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* The ids a group hands down to its own controls. Kept separate from the
|
|
5
|
+
* rendering so CheckboxGroup and RadioGroup can give every checkbox and radio
|
|
6
|
+
* the same `aria-describedby` the fieldset carries — see FieldsetShell.
|
|
7
|
+
*/
|
|
8
|
+
export function useFieldsetHelper(description, errorMessage, isInvalid) {
|
|
9
|
+
const helperId = useId();
|
|
10
|
+
// Input's convention: the error takes the helper's slot, it does not stack.
|
|
11
|
+
const helper = isInvalid && errorMessage ? errorMessage : description;
|
|
12
|
+
return { helper, helperId: helper ? helperId : undefined };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The rendering shared by Fieldset, CheckboxGroup and RadioGroup.
|
|
16
|
+
*
|
|
17
|
+
* A real `<fieldset>`: the legend names the group for assistive technology and
|
|
18
|
+
* the inputs stay grouped for form submission, neither of which a div with
|
|
19
|
+
* `role="group"` gets for free.
|
|
20
|
+
*
|
|
21
|
+
* The fieldset is `display: block` on purpose. A rendered `<legend>` is not a
|
|
22
|
+
* flex item — browsers lay it out in the fieldset's border, outside the flex
|
|
23
|
+
* container — so a flex column here would put `gap` everywhere but under the
|
|
24
|
+
* legend. The fields get a flex wrapper of their own instead.
|
|
25
|
+
*/
|
|
26
|
+
export const FieldsetShell = forwardRef((props, ref) => {
|
|
27
|
+
const { label, isInvalid, orientation = 'vertical', isChoiceGroup = false, helper, helperId, className, children, 'aria-describedby': describedBy, ...rest } = props;
|
|
28
|
+
return (_jsxs("fieldset", { ...rest, ref: ref, "aria-describedby": [describedBy, helperId].filter(Boolean).join(' ') || undefined, "data-invalid": isInvalid || undefined, className: [
|
|
29
|
+
'ion-fieldset',
|
|
30
|
+
isChoiceGroup ? 'ion-fieldset--choices' : '',
|
|
31
|
+
orientation === 'horizontal' ? 'ion-fieldset--horizontal' : '',
|
|
32
|
+
isInvalid ? 'ion-fieldset--error' : '',
|
|
33
|
+
className || '',
|
|
34
|
+
]
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.join(' '), children: [label && _jsx("legend", { className: "ion-fieldset__legend", children: label }), _jsx("div", { className: "ion-fieldset__content", children: children }), helper && (_jsx("span", { id: helperId, className: "ion-fieldset__helper", children: helper }))] }));
|
|
37
|
+
});
|
|
38
|
+
FieldsetShell.displayName = 'FieldsetShell';
|
|
39
|
+
/**
|
|
40
|
+
* Groups related fields under one label, with one description and one error —
|
|
41
|
+
* an address, a date range typed as two fields, a set of limits.
|
|
42
|
+
*
|
|
43
|
+
* For checkboxes use CheckboxGroup and for radios RadioGroup: both render this
|
|
44
|
+
* same shell, and add the selection state it deliberately does not own.
|
|
45
|
+
*
|
|
46
|
+
* There is no `isDisabled`. A native `disabled` fieldset does disable every
|
|
47
|
+
* control inside, but Input, Select and the rest draw their disabled state from
|
|
48
|
+
* their own prop, so the fields would stop working while still looking live.
|
|
49
|
+
* Disable the fields themselves; the choice groups can cascade because their
|
|
50
|
+
* checkboxes and radios style off `:disabled`.
|
|
51
|
+
*/
|
|
52
|
+
export const Fieldset = forwardRef((props, ref) => {
|
|
53
|
+
const { description, errorMessage, ...rest } = props;
|
|
54
|
+
const { helper, helperId } = useFieldsetHelper(description, errorMessage, rest.isInvalid);
|
|
55
|
+
return (_jsx(FieldsetShell, { ...rest, ref: ref, helper: helper, helperId: helperId }));
|
|
56
|
+
});
|
|
57
|
+
Fieldset.displayName = 'Fieldset';
|
|
58
|
+
//# sourceMappingURL=Fieldset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Fieldset.js","sourceRoot":"","sources":["../../src/components/Fieldset.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAqBjD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,WAA4B,EAC5B,YAA6B,EAC7B,SAA8B;IAE9B,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;IACzB,4EAA4E;IAC5E,MAAM,MAAM,GAAG,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC;IACtE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC7D,CAAC;AAeD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAGrC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IACf,MAAM,EACJ,KAAK,EACL,SAAS,EACT,WAAW,GAAG,UAAU,EACxB,aAAa,GAAG,KAAK,EACrB,MAAM,EACN,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,kBAAkB,EAAE,WAAW,EAC/B,GAAG,IAAI,EACR,GAAG,KAAK,CAAC;IAEV,OAAO,CACL,uBACM,IAAI,EACR,GAAG,EAAE,GAAG,sBAEN,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,kBAElD,SAAS,IAAI,SAAS,EACpC,SAAS,EAAE;YACT,cAAc;YACd,aAAa,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,EAAE;YAC5C,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,EAAE;YAC9D,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE;YACtC,SAAS,IAAI,EAAE;SAChB;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,GAAG,CAAC,aAEX,KAAK,IAAI,iBAAQ,SAAS,EAAC,sBAAsB,YAAE,KAAK,GAAU,EACnE,cAAK,SAAS,EAAC,uBAAuB,YAAE,QAAQ,GAAO,EACtD,MAAM,IAAI,CACT,eAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAC,sBAAsB,YACjD,MAAM,GACF,CACR,IACQ,CACZ,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAChC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IACb,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,iBAAiB,CAC5C,WAAW,EACX,YAAY,EACZ,IAAI,CAAC,SAAS,CACf,CAAC;IACF,OAAO,CACL,KAAC,aAAa,OAAK,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAC1E,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,QAAQ,CAAC,WAAW,GAAG,UAAU,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ComboboxOption } from './Combobox.js';
|
|
3
|
+
export type MultiSelectSize = 'sm' | 'md' | 'lg';
|
|
4
|
+
/** The same shape as Combobox's option, so a list moves between the two. */
|
|
5
|
+
export type MultiSelectOption = ComboboxOption;
|
|
6
|
+
export interface MultiSelectProps {
|
|
7
|
+
/** The full option list. Filtering happens here, against what is typed. */
|
|
8
|
+
options: readonly MultiSelectOption[];
|
|
9
|
+
/** Field label. Required for a usable control — see `a11y.requires`. */
|
|
10
|
+
label?: React.ReactNode;
|
|
11
|
+
/** Names the field, and its tags, when there is no visible `label`. */
|
|
12
|
+
'aria-label'?: string;
|
|
13
|
+
/** Helper text below the field. */
|
|
14
|
+
description?: React.ReactNode;
|
|
15
|
+
/** Replaces the helper text when `isInvalid` is set. */
|
|
16
|
+
errorMessage?: React.ReactNode;
|
|
17
|
+
isInvalid?: boolean;
|
|
18
|
+
isDisabled?: boolean;
|
|
19
|
+
isReadOnly?: boolean;
|
|
20
|
+
/** At least one value must be chosen. */
|
|
21
|
+
isRequired?: boolean;
|
|
22
|
+
/** Matches Input's `Size` variant: Small, Medium, Large. */
|
|
23
|
+
size?: MultiSelectSize;
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
/** The selected values (controlled), in the order they were chosen. */
|
|
26
|
+
value?: readonly string[];
|
|
27
|
+
/** The initially selected values (uncontrolled). */
|
|
28
|
+
defaultValue?: readonly string[];
|
|
29
|
+
/** Receives the whole new selection. */
|
|
30
|
+
onChange?: (value: string[]) => void;
|
|
31
|
+
/** Controlled filter text. Usually only needed for remote filtering. */
|
|
32
|
+
inputValue?: string;
|
|
33
|
+
onInputChange?: (value: string) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Leave the tags out, when the chosen values are already on screen as
|
|
36
|
+
* removable tags — a table's active-filters row. The values are still read
|
|
37
|
+
* with the field, and still marked in the list.
|
|
38
|
+
*/
|
|
39
|
+
hideTags?: boolean;
|
|
40
|
+
/** Shown in place of the list when nothing matches. */
|
|
41
|
+
emptyLabel?: React.ReactNode;
|
|
42
|
+
/** Accessible label for the disclosure button. */
|
|
43
|
+
buttonLabel?: string;
|
|
44
|
+
/** Posts every selected value under this name, for an uncontrolled form. */
|
|
45
|
+
name?: string;
|
|
46
|
+
/** Class names for the field box (`.ion-input`). */
|
|
47
|
+
className?: string;
|
|
48
|
+
/** Class names for the `.ion-field` wrapper. */
|
|
49
|
+
wrapperClassName?: string;
|
|
50
|
+
id?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* MultiSelect — a text field that filters a list, with any number of selected
|
|
54
|
+
* values shown as removable tags beneath it.
|
|
55
|
+
*
|
|
56
|
+
* WHY IT IS ITS OWN COMPONENT, NOT `Combobox selectionMode="multiple"`
|
|
57
|
+
*
|
|
58
|
+
* The two differ in what the field holds. Combobox's input shows the chosen
|
|
59
|
+
* label — typing edits the value. Here the input only ever holds the filter
|
|
60
|
+
* text, the value lives in the tags, and choosing an option leaves the list
|
|
61
|
+
* open for the next one. One prop switching the meaning of the text in the
|
|
62
|
+
* box is the kind of contract agents get wrong in generated code.
|
|
63
|
+
*
|
|
64
|
+
* WHAT REACT ARIA GIVES IT
|
|
65
|
+
*
|
|
66
|
+
* `useComboBoxState` and `useComboBox` in `selectionMode: 'multiple'`: the
|
|
67
|
+
* listbox is `aria-multiselectable`, Enter and click toggle an option without
|
|
68
|
+
* closing the list, the filter text clears after each pick, and native
|
|
69
|
+
* `required` is set only while nothing is chosen — "at least one", the same
|
|
70
|
+
* rule CheckboxGroup enforces.
|
|
71
|
+
*
|
|
72
|
+
* WHAT IT ADDS
|
|
73
|
+
*
|
|
74
|
+
* - The tags. A TagGroup under the field, named by the field's label, one
|
|
75
|
+
* tab stop, Delete or the × to remove. The selection must be visible with
|
|
76
|
+
* the list closed, and "3 selected" hides which three.
|
|
77
|
+
* - The value is announced with the field. React Aria points the input's
|
|
78
|
+
* `aria-describedby` at a value element; this fills it with the chosen
|
|
79
|
+
* labels joined by `Intl.ListFormat`, so "Billing, Legal and Ops" is read
|
|
80
|
+
* in the user's language with no string shipped for it.
|
|
81
|
+
* - Backspace in an empty field removes the last value, which is what
|
|
82
|
+
* every tag input on the web has taught people to expect.
|
|
83
|
+
* - Focus lands back in the field when the last tag is removed, instead of
|
|
84
|
+
* falling to <body> with the TagGroup that held it.
|
|
85
|
+
*/
|
|
86
|
+
export declare function MultiSelect({ options, label, 'aria-label': ariaLabel, description, errorMessage, isInvalid, isDisabled, isReadOnly, isRequired, size, placeholder, value, defaultValue, onChange, inputValue, onInputChange, hideTags, emptyLabel, buttonLabel, name, className, wrapperClassName, id, }: MultiSelectProps): React.JSX.Element;
|
|
87
|
+
export declare namespace MultiSelect {
|
|
88
|
+
var displayName: string;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=MultiSelect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultiSelect.d.ts","sourceRoot":"","sources":["../../src/components/MultiSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAoC,MAAM,OAAO,CAAC;AAiBzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAIjD,4EAA4E;AAC5E,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAE/C,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtC,wEAAwE;IACxE,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,wDAAwD;IACxD,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,oDAAoD;IACpD,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,wCAAwC;IACxC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uDAAuD;IACvD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAgKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,EACV,UAAU,EACV,IAAW,EACX,WAAW,EACX,KAAK,EACL,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,aAAa,EACb,QAAgB,EAChB,UAAyB,EACzB,WAA4B,EAC5B,IAAI,EACJ,SAAS,EACT,gBAAgB,EAChB,EAAE,GACH,EAAE,gBAAgB,qBAoOlB;yBA5Pe,WAAW"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { DismissButton, Overlay, useButton, useComboBox, useFilter, useListBox, useLocale, useOption, usePopover, } from 'react-aria';
|
|
5
|
+
import { Item, useComboBoxState } from 'react-stately';
|
|
6
|
+
import { Tag, TagGroup } from './TagGroup.js';
|
|
7
|
+
const ChevronDown = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "m6 9 6 6 6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
8
|
+
const CheckMark = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "m5 13 4 4L19 7", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
9
|
+
/* ------------------------------------------------------------------ option */
|
|
10
|
+
function MultiSelectOptionRow({ item, state, }) {
|
|
11
|
+
const ref = useRef(null);
|
|
12
|
+
const { optionProps, isSelected, isFocused, isDisabled } = useOption({ key: item.key }, state, ref);
|
|
13
|
+
const option = item.value;
|
|
14
|
+
return (_jsxs("li", { ...optionProps, ref: ref, className: "ion-combobox-menu__option ion-multi-select-menu__option", "data-focused": isFocused || undefined, "data-selected": isSelected || undefined, "data-disabled": isDisabled || undefined, children: [_jsx("span", { className: "ion-multi-select-menu__check", "aria-hidden": "true", children: _jsx(CheckMark, {}) }), _jsxs("span", { className: "ion-multi-select-menu__text", children: [_jsx("span", { className: "ion-combobox-menu__label", children: item.rendered }), option?.description && (_jsx("span", { className: "ion-combobox-menu__description", children: option.description }))] })] }));
|
|
15
|
+
}
|
|
16
|
+
/** Breathing room kept between the menu and the viewport edge, in px. */
|
|
17
|
+
const GUTTER = 8;
|
|
18
|
+
/* ----------------------------------------------------------------- listbox */
|
|
19
|
+
/**
|
|
20
|
+
* Mounted only while open, for the reason Combobox's is: `usePopover`
|
|
21
|
+
* positions in an effect of the component that calls it. The width is read
|
|
22
|
+
* during render for the reason given there, too — a ResizeObserver feeding a
|
|
23
|
+
* width back into a positioned popover closes it.
|
|
24
|
+
*/
|
|
25
|
+
function MultiSelectListBox({ state, listBoxRef, popoverRef, triggerRef, listBoxProps, emptyLabel, }) {
|
|
26
|
+
const { popoverProps } = usePopover({
|
|
27
|
+
triggerRef,
|
|
28
|
+
popoverRef,
|
|
29
|
+
placement: 'bottom start',
|
|
30
|
+
offset: 4,
|
|
31
|
+
// Non-modal: focus stays in the input — see Combobox.
|
|
32
|
+
isNonModal: true,
|
|
33
|
+
}, state);
|
|
34
|
+
const { listBoxProps: innerListBoxProps } = useListBox(listBoxProps, state, listBoxRef);
|
|
35
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
36
|
+
const width = rect
|
|
37
|
+
? Math.min(rect.width, document.documentElement.clientWidth - rect.left - GUTTER)
|
|
38
|
+
: undefined;
|
|
39
|
+
return (_jsx(Overlay, { children: _jsxs("div", { ...popoverProps, ref: popoverRef, className: "ion-combobox-menu", style: { ...popoverProps.style, width }, children: [_jsx(DismissButton, { onDismiss: () => state.close() }), _jsx("ul", { ...innerListBoxProps, ref: listBoxRef, className: "ion-combobox-menu__list", children: [...state.collection].map((item) => (_jsx(MultiSelectOptionRow, { item: item, state: state }, item.key))) }), state.collection.size === 0 && (_jsx("div", { className: "ion-combobox-menu__empty", role: "presentation", children: emptyLabel })), _jsx(DismissButton, { onDismiss: () => state.close() })] }) }));
|
|
40
|
+
}
|
|
41
|
+
/* ------------------------------------------------------------- multiselect */
|
|
42
|
+
/**
|
|
43
|
+
* MultiSelect — a text field that filters a list, with any number of selected
|
|
44
|
+
* values shown as removable tags beneath it.
|
|
45
|
+
*
|
|
46
|
+
* WHY IT IS ITS OWN COMPONENT, NOT `Combobox selectionMode="multiple"`
|
|
47
|
+
*
|
|
48
|
+
* The two differ in what the field holds. Combobox's input shows the chosen
|
|
49
|
+
* label — typing edits the value. Here the input only ever holds the filter
|
|
50
|
+
* text, the value lives in the tags, and choosing an option leaves the list
|
|
51
|
+
* open for the next one. One prop switching the meaning of the text in the
|
|
52
|
+
* box is the kind of contract agents get wrong in generated code.
|
|
53
|
+
*
|
|
54
|
+
* WHAT REACT ARIA GIVES IT
|
|
55
|
+
*
|
|
56
|
+
* `useComboBoxState` and `useComboBox` in `selectionMode: 'multiple'`: the
|
|
57
|
+
* listbox is `aria-multiselectable`, Enter and click toggle an option without
|
|
58
|
+
* closing the list, the filter text clears after each pick, and native
|
|
59
|
+
* `required` is set only while nothing is chosen — "at least one", the same
|
|
60
|
+
* rule CheckboxGroup enforces.
|
|
61
|
+
*
|
|
62
|
+
* WHAT IT ADDS
|
|
63
|
+
*
|
|
64
|
+
* - The tags. A TagGroup under the field, named by the field's label, one
|
|
65
|
+
* tab stop, Delete or the × to remove. The selection must be visible with
|
|
66
|
+
* the list closed, and "3 selected" hides which three.
|
|
67
|
+
* - The value is announced with the field. React Aria points the input's
|
|
68
|
+
* `aria-describedby` at a value element; this fills it with the chosen
|
|
69
|
+
* labels joined by `Intl.ListFormat`, so "Billing, Legal and Ops" is read
|
|
70
|
+
* in the user's language with no string shipped for it.
|
|
71
|
+
* - Backspace in an empty field removes the last value, which is what
|
|
72
|
+
* every tag input on the web has taught people to expect.
|
|
73
|
+
* - Focus lands back in the field when the last tag is removed, instead of
|
|
74
|
+
* falling to <body> with the TagGroup that held it.
|
|
75
|
+
*/
|
|
76
|
+
export function MultiSelect({ options, label, 'aria-label': ariaLabel, description, errorMessage, isInvalid, isDisabled, isReadOnly, isRequired, size = 'md', placeholder, value, defaultValue, onChange, inputValue, onInputChange, hideTags = false, emptyLabel = 'No matches', buttonLabel = 'Show options', name, className, wrapperClassName, id, }) {
|
|
77
|
+
const { contains } = useFilter({ sensitivity: 'base' });
|
|
78
|
+
const { locale } = useLocale();
|
|
79
|
+
const [uncontrolled, setUncontrolled] = useState(defaultValue ?? []);
|
|
80
|
+
const selected = value ?? uncontrolled;
|
|
81
|
+
const setSelected = (next) => {
|
|
82
|
+
if (value === undefined)
|
|
83
|
+
setUncontrolled(next);
|
|
84
|
+
onChange?.(next);
|
|
85
|
+
};
|
|
86
|
+
const byValue = useMemo(() => new Map(options.map((o) => [o.value, o])), [options]);
|
|
87
|
+
// Filtered here, against label and description, for the reasons Combobox
|
|
88
|
+
// gives: `items` bypasses react-stately's filter, and `textValue` must stay
|
|
89
|
+
// the bare label.
|
|
90
|
+
const [typed, setTyped] = useState('');
|
|
91
|
+
const text = inputValue ?? typed;
|
|
92
|
+
const filtered = useMemo(() => {
|
|
93
|
+
if (!text)
|
|
94
|
+
return options;
|
|
95
|
+
return options.filter((o) => contains([o.label, o.description].filter(Boolean).join(' '), text));
|
|
96
|
+
}, [contains, options, text]);
|
|
97
|
+
const disabledKeys = useMemo(() => options.filter((o) => o.isDisabled).map((o) => o.value), [options]);
|
|
98
|
+
const state = useComboBoxState({
|
|
99
|
+
label: typeof label === 'string' ? label : undefined,
|
|
100
|
+
items: filtered,
|
|
101
|
+
children: (item) => (_jsx(Item, { textValue: item.label, children: item.label }, item.value)),
|
|
102
|
+
selectionMode: 'multiple',
|
|
103
|
+
disabledKeys,
|
|
104
|
+
allowsEmptyCollection: true,
|
|
105
|
+
isDisabled,
|
|
106
|
+
isReadOnly,
|
|
107
|
+
isRequired,
|
|
108
|
+
value: selected,
|
|
109
|
+
// The selection keeps insertion order — the order the tags appear in, and
|
|
110
|
+
// the order `onChange` reports. PickingKeepsTheListOpen pins it.
|
|
111
|
+
onChange: (keys) => setSelected([...keys].map(String)),
|
|
112
|
+
inputValue,
|
|
113
|
+
onInputChange: (v) => {
|
|
114
|
+
setTyped(v);
|
|
115
|
+
onInputChange?.(v);
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
const inputRef = useRef(null);
|
|
119
|
+
const listBoxRef = useRef(null);
|
|
120
|
+
const popoverRef = useRef(null);
|
|
121
|
+
const buttonRef = useRef(null);
|
|
122
|
+
const boxRef = useRef(null);
|
|
123
|
+
const remove = (keys) => {
|
|
124
|
+
const gone = new Set([...keys].map(String));
|
|
125
|
+
const next = selected.filter((v) => !gone.has(v));
|
|
126
|
+
setSelected(next);
|
|
127
|
+
// The TagGroup unmounts with its last tag; focus goes back to the field.
|
|
128
|
+
if (next.length === 0)
|
|
129
|
+
inputRef.current?.focus();
|
|
130
|
+
};
|
|
131
|
+
const { buttonProps: triggerProps, inputProps, listBoxProps, labelProps, descriptionProps, errorMessageProps, valueProps, } = useComboBox({
|
|
132
|
+
id,
|
|
133
|
+
label: typeof label === 'string' ? label : undefined,
|
|
134
|
+
'aria-label': ariaLabel,
|
|
135
|
+
placeholder,
|
|
136
|
+
isDisabled,
|
|
137
|
+
isReadOnly,
|
|
138
|
+
isInvalid,
|
|
139
|
+
isRequired,
|
|
140
|
+
selectionMode: 'multiple',
|
|
141
|
+
inputRef,
|
|
142
|
+
listBoxRef,
|
|
143
|
+
popoverRef,
|
|
144
|
+
buttonRef,
|
|
145
|
+
onKeyDown: (e) => {
|
|
146
|
+
if (e.key === 'Backspace' &&
|
|
147
|
+
state.inputValue === '' &&
|
|
148
|
+
selected.length > 0 &&
|
|
149
|
+
!isReadOnly) {
|
|
150
|
+
remove([selected[selected.length - 1]]);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
e.continuePropagation();
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
}, state);
|
|
157
|
+
const { buttonProps } = useButton({ ...triggerProps, 'aria-label': buttonLabel }, buttonRef);
|
|
158
|
+
const labels = selected.map((v) => byValue.get(v)?.label ?? v);
|
|
159
|
+
const spoken = new Intl.ListFormat(locale, { type: 'conjunction' }).format(labels);
|
|
160
|
+
const helper = isInvalid && errorMessage ? errorMessage : description;
|
|
161
|
+
const boxClassNames = [
|
|
162
|
+
'ion-input',
|
|
163
|
+
'ion-combobox',
|
|
164
|
+
'ion-multi-select',
|
|
165
|
+
size !== 'md' ? `ion-input--${size}` : '',
|
|
166
|
+
isInvalid ? 'ion-input--invalid' : '',
|
|
167
|
+
isDisabled ? 'ion-input--disabled' : '',
|
|
168
|
+
className || '',
|
|
169
|
+
]
|
|
170
|
+
.filter(Boolean)
|
|
171
|
+
.join(' ');
|
|
172
|
+
return (_jsxs("div", { className: [
|
|
173
|
+
'ion-field',
|
|
174
|
+
isInvalid ? 'ion-field--error' : '',
|
|
175
|
+
wrapperClassName || '',
|
|
176
|
+
]
|
|
177
|
+
.filter(Boolean)
|
|
178
|
+
.join(' '), children: [label && (_jsx("label", { ...labelProps, className: "ion-field__label", children: label })), _jsxs("div", { ref: boxRef, className: boxClassNames, "data-open": state.isOpen || undefined, "data-invalid": isInvalid || undefined, "data-disabled": isDisabled || undefined, children: [_jsx("input", { ...inputProps, ref: inputRef, className: "ion-input__field" }), name &&
|
|
179
|
+
selected.map((v) => (_jsx("input", { type: "hidden", name: name, value: v }, v))), _jsx("button", { ...buttonProps, "aria-labelledby": undefined, "aria-label": buttonLabel,
|
|
180
|
+
// Pressing it must not take focus from the input — see Combobox.
|
|
181
|
+
onMouseDown: (e) => {
|
|
182
|
+
e.preventDefault();
|
|
183
|
+
inputRef.current?.focus();
|
|
184
|
+
}, ref: buttonRef, type: "button", tabIndex: -1, className: "ion-combobox__button", children: _jsx(ChevronDown, {}) })] }), _jsx("span", { ...valueProps, className: "ion-visually-hidden", children: spoken }), selected.length > 0 && !hideTags && (_jsx(TagGroup, { "aria-labelledby": label ? labelProps.id : undefined, "aria-label": label ? undefined : ariaLabel, size: size === 'lg' ? 'md' : 'sm', onRemove: isDisabled || isReadOnly ? undefined : remove, className: "ion-multi-select__tags", children: selected.map((v) => (_jsx(Tag, { textValue: byValue.get(v)?.label ?? v, children: byValue.get(v)?.label ?? v }, v))) })), state.isOpen && (_jsx(MultiSelectListBox, { state: state, listBoxRef: listBoxRef, popoverRef: popoverRef, triggerRef: boxRef, listBoxProps: listBoxProps, emptyLabel: emptyLabel })), helper && (_jsx("span", { ...(isInvalid && errorMessage
|
|
185
|
+
? errorMessageProps
|
|
186
|
+
: descriptionProps), className: "ion-field__helper", children: helper }))] }));
|
|
187
|
+
}
|
|
188
|
+
MultiSelect.displayName = 'MultiSelect';
|
|
189
|
+
//# sourceMappingURL=MultiSelect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MultiSelect.js","sourceRoot":"","sources":["../../src/components/MultiSelect.tsx"],"names":[],"mappings":"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"}
|