uikit-react-public 0.14.21 → 0.17.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/components/Accordion/Accordion.Heading.d.ts +4 -4
- package/dist/components/Accordion/Accordion.Panel.d.ts +2 -2
- package/dist/components/Accordion/Accordion.d.ts +1 -1
- package/dist/components/Accordion/Accordion.stories.d.ts +57 -0
- package/dist/components/Accordion/index.d.ts +2 -0
- package/dist/components/Avatar/Avatar.stories.d.ts +107 -1
- package/dist/components/Button/Button.d.ts +1 -0
- package/dist/components/Calendar/index.d.ts +1 -1
- package/dist/components/Datepicker/Datepicker.d.ts +1 -1
- package/dist/components/Datepicker/Datepicker.stories.d.ts +4 -3
- package/dist/components/Datepicker/Datepicker.types.d.ts +4 -5
- package/dist/components/Datepicker/subcomponents/CustomDatepicker.d.ts +4 -1
- package/dist/components/Datepicker/subcomponents/DatepickerInput.d.ts +15 -2
- package/dist/components/Datepicker/subcomponents/Panel.d.ts +1 -1
- package/dist/components/Datepicker/subcomponents/VisibleField.d.ts +6 -1
- package/dist/components/Datepicker/subcomponents/index.d.ts +0 -1
- package/dist/components/Datepicker/utils/index.d.ts +0 -1
- package/dist/components/Dialog/BaseDialog.d.ts +2 -1
- package/dist/components/Dialog/Dialog.d.ts +2 -0
- package/dist/components/Header/Header.d.ts +4 -1
- package/dist/components/Header/Header.stories.d.ts +40 -0
- package/dist/components/Main/Main.d.ts +21 -0
- package/dist/components/Main/Main.stories.d.ts +15 -0
- package/dist/components/Main/index.d.ts +2 -0
- package/dist/components/NativeDatepicker/NativeDatepicker.d.ts +3 -0
- package/dist/components/NativeDatepicker/NativeDatepicker.stories.d.ts +36 -0
- package/dist/components/NativeDatepicker/NativeDatepicker.types.d.ts +10 -0
- package/dist/components/NativeDatepicker/index.d.ts +2 -0
- package/dist/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.d.ts +1 -1
- package/dist/components/NativeDatepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts +1 -0
- package/dist/components/NativeDatepicker/utils/index.d.ts +1 -0
- package/dist/components/Select/Select.stories.d.ts +154 -2
- package/dist/components/Select/Select.types.d.ts +51 -22
- package/dist/components/Select/subcomponents/CustomOption.d.ts +1 -1
- package/dist/components/Select/subcomponents/CustomSelect.d.ts +3 -2
- package/dist/components/Select/subcomponents/FilterInput.d.ts +14 -0
- package/dist/components/Select/subcomponents/NativeSelect.d.ts +5 -1
- package/dist/components/Select/subcomponents/VisibleField.d.ts +3 -1
- package/dist/components/Select/subcomponents/index.d.ts +1 -0
- package/dist/components/WeekPicker/WeekPicker.d.ts +2 -2
- package/dist/components/WeekPicker/WeekPicker.stories.d.ts +41 -0
- package/dist/components/WeekPicker/WeekPicker.types.d.ts +16 -0
- package/dist/components/WeekPicker/index.d.ts +1 -0
- package/dist/components/WeekPicker/subcomponents/CustomDatepicker.d.ts +1 -1
- package/dist/components/index.d.ts +8 -0
- package/dist/hooks/useFocusTrap.d.ts +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4366 -3768
- package/dist/utils/__tests__/announce.test.d.ts +1 -0
- package/dist/utils/announce.d.ts +6 -0
- package/dist/utils/index.d.ts +1 -0
- package/lib/components/Accordion/Accordion.Heading.tsx +27 -8
- package/lib/components/Accordion/Accordion.Panel.tsx +11 -3
- package/lib/components/Accordion/Accordion.stories.tsx +139 -0
- package/lib/components/Accordion/Accordion.tsx +10 -8
- package/lib/components/Accordion/__tests__/__snapshots__/Accordion.test.tsx.snap +7 -7
- package/lib/components/Accordion/index.ts +2 -0
- package/lib/components/Alert/Alert.stories.tsx +1 -1
- package/lib/components/Avatar/Avatar.mdx +117 -0
- package/lib/components/Avatar/Avatar.stories.tsx +110 -2
- package/lib/components/Blanket/Blanket.stories.tsx +1 -1
- package/lib/components/Button/Button.stories.tsx +1 -1
- package/lib/components/Button/Button.tsx +1 -0
- package/lib/components/Calendar/Calendar.stories.tsx +12 -32
- package/lib/components/Calendar/__tests__/Calendar.test.tsx +23 -15
- package/lib/components/Calendar/index.ts +1 -5
- package/lib/components/Calendar/subcomponents/AcademicWeeks.tsx +2 -1
- package/lib/components/Calendar/subcomponents/ColumnHeading.tsx +5 -1
- package/lib/components/Calendar/subcomponents/EventDot.tsx +2 -1
- package/lib/components/Calendar/subcomponents/index.ts +1 -1
- package/lib/components/Calendar/utils/getDatesForCalendarGrid/getDatesForCalendarGrid.ts +43 -11
- package/lib/components/Calendar/utils/normaliseMonth/normaliseMonth.test.ts +5 -5
- package/lib/components/Datepicker/Datepicker.lld.md +108 -0
- package/lib/components/Datepicker/Datepicker.stories.tsx +44 -5
- package/lib/components/Datepicker/Datepicker.tsx +14 -36
- package/lib/components/Datepicker/Datepicker.types.ts +5 -14
- package/lib/components/Datepicker/__tests__/Datepicker.test.tsx +150 -8
- package/lib/components/Datepicker/__tests__/__snapshots__/Datepicker.test.tsx.snap +10 -4
- package/lib/components/Datepicker/subcomponents/CustomDatepicker.tsx +39 -5
- package/lib/components/Datepicker/subcomponents/DatepickerInput.tsx +30 -17
- package/lib/components/Datepicker/subcomponents/Panel.tsx +6 -2
- package/lib/components/Datepicker/subcomponents/VisibleField.tsx +40 -3
- package/lib/components/Datepicker/subcomponents/index.ts +0 -1
- package/lib/components/Datepicker/utils/index.ts +0 -1
- package/lib/components/Dialog/BaseDialog.tsx +11 -0
- package/lib/components/Dialog/Dialog.tsx +8 -1
- package/lib/components/Dialog/DialogBody.tsx +5 -1
- package/lib/components/Dialog/DialogHeader.tsx +2 -1
- package/lib/components/Divider/Divider.stories.tsx +1 -1
- package/lib/components/Field/ErrorText.tsx +1 -0
- package/lib/components/Field/Field.stories.tsx +1 -1
- package/lib/components/Field/__tests__/Field.test.tsx +13 -0
- package/lib/components/FileInput/FileInput.stories.tsx +1 -1
- package/lib/components/Footer/Footer.stories.tsx +1 -1
- package/lib/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +3 -3
- package/lib/components/Header/Header.mdx +52 -0
- package/lib/components/Header/Header.stories.tsx +98 -0
- package/lib/components/Header/Header.tsx +51 -6
- package/lib/components/Header/__tests__/Header.test.tsx +17 -1
- package/lib/components/Heading/Heading.stories.tsx +1 -1
- package/lib/components/Icon/Icon.stories.tsx +1 -1
- package/lib/components/IconButton/IconButton.stories.tsx +1 -1
- package/lib/components/Input/Input.stories.tsx +1 -1
- package/lib/components/Label/Label.stories.tsx +1 -1
- package/lib/components/Main/Main.stories.tsx +36 -0
- package/lib/components/Main/Main.tsx +46 -0
- package/lib/components/Main/__tests__/Main.test.tsx +80 -0
- package/lib/components/Main/__tests__/__snapshots__/Main.test.tsx.snap +33 -0
- package/lib/components/Main/index.ts +2 -0
- package/lib/components/NativeDatepicker/NativeDatepicker.stories.tsx +100 -0
- package/lib/components/{Datepicker/subcomponents → NativeDatepicker}/NativeDatepicker.tsx +14 -15
- package/lib/components/NativeDatepicker/NativeDatepicker.types.ts +19 -0
- package/lib/components/NativeDatepicker/index.ts +2 -0
- package/lib/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.ts +1 -1
- package/lib/components/NativeDatepicker/utils/index.ts +1 -0
- package/lib/components/Pagination/PaginationControls.tsx +55 -12
- package/lib/components/Pagination/PaginationInfo.tsx +5 -1
- package/lib/components/Paragraph/Paragraph.stories.tsx +1 -1
- package/lib/components/Search/Search.stories.tsx +1 -1
- package/lib/components/Search/Search.tsx +4 -1
- package/lib/components/Search/__tests__/Search.test.tsx +19 -1
- package/lib/components/Select/Select.mdx +169 -0
- package/lib/components/Select/Select.stories.tsx +191 -43
- package/lib/components/Select/Select.tsx +36 -12
- package/lib/components/Select/Select.types.ts +66 -48
- package/lib/components/Select/__tests__/Select.test.tsx +448 -7
- package/lib/components/Select/__tests__/__snapshots__/Select.test.tsx.snap +1 -1
- package/lib/components/Select/subcomponents/CustomOption.tsx +2 -1
- package/lib/components/Select/subcomponents/CustomSelect.tsx +303 -33
- package/lib/components/Select/subcomponents/FilterInput.tsx +80 -0
- package/lib/components/Select/subcomponents/NativeSelect.tsx +13 -1
- package/lib/components/Select/subcomponents/VisibleField.tsx +11 -3
- package/lib/components/Select/subcomponents/index.tsx +1 -0
- package/lib/components/Snackbar/Snackbar.stories.tsx +1 -1
- package/lib/components/Spinner/Spinner.stories.tsx +1 -1
- package/lib/components/Textarea/Textarea.stories.tsx +1 -1
- package/lib/components/Timepicker/Timepicker.tsx +4 -0
- package/lib/components/Timepicker/__tests__/__snapshots__/Timepicker.test.tsx.snap +2 -2
- package/lib/components/Toggle/Toggle.stories.tsx +1 -1
- package/lib/components/Tooltip/Tooltip.stories.tsx +1 -1
- package/lib/components/WeekPicker/WeekPicker.stories.tsx +147 -0
- package/lib/components/WeekPicker/WeekPicker.tsx +2 -2
- package/lib/components/WeekPicker/WeekPicker.types.ts +21 -0
- package/lib/components/WeekPicker/index.ts +1 -0
- package/lib/components/WeekPicker/subcomponents/CustomDatepicker.tsx +1 -1
- package/lib/components/common/Common.mdx +1 -1
- package/lib/components/index.ts +11 -2
- package/lib/hooks/useFocusTrap.ts +40 -4
- package/lib/index.ts +1 -0
- package/lib/utils/__tests__/announce.test.ts +121 -0
- package/lib/utils/announce.ts +134 -0
- package/lib/utils/index.ts +1 -0
- package/package.json +3 -6
- package/dist/components/Datepicker/subcomponents/NativeDatepicker.d.ts +0 -6
- package/lib/components/Accordion/Accordion.stories.tsx.NOT_READY +0 -93
- /package/dist/components/{Datepicker/utils/dateToLocaleISOString/dateToLocaleISOString.test.d.ts → Main/__tests__/Main.test.d.ts} +0 -0
- /package/lib/components/{Datepicker → NativeDatepicker}/utils/dateToLocaleISOString/dateToLocaleISOString.test.ts +0 -0
|
@@ -1,37 +1,128 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
import { useArgs } from '@storybook/preview-api';
|
|
3
3
|
import Select from './Select';
|
|
4
|
+
import { css } from '@emotion/css';
|
|
5
|
+
|
|
6
|
+
const select400pxWidthClass = css`
|
|
7
|
+
width: 400px;
|
|
8
|
+
`;
|
|
9
|
+
const storyWrapperStyle: React.CSSProperties = { minHeight: 150, width: 400 };
|
|
4
10
|
|
|
5
11
|
const meta = {
|
|
6
|
-
title: 'Components/
|
|
12
|
+
title: 'Components/Select',
|
|
7
13
|
component: Select,
|
|
8
14
|
argTypes: {
|
|
9
|
-
|
|
15
|
+
selectionBehaviour: {
|
|
16
|
+
description:
|
|
17
|
+
'Keyboard selection behaviour for custom variant: `focus` commits on arrow keys, `commit` commits on Enter/click',
|
|
18
|
+
control: { type: 'radio' },
|
|
19
|
+
options: ['focus', 'commit'],
|
|
20
|
+
table: { type: { summary: "'focus' | 'commit'" } },
|
|
21
|
+
},
|
|
22
|
+
options: {
|
|
23
|
+
description: 'Array of option objects `{ label, value, optionProps? }`',
|
|
24
|
+
control: { type: 'object' },
|
|
25
|
+
table: { type: { summary: 'OptionData[]' } },
|
|
26
|
+
},
|
|
27
|
+
value: {
|
|
28
|
+
description: 'Selected value (string | number)',
|
|
29
|
+
control: { type: 'text' },
|
|
30
|
+
table: { type: { summary: 'string | number' } },
|
|
31
|
+
},
|
|
32
|
+
onValueChange: {
|
|
33
|
+
description:
|
|
34
|
+
'Change handler for the custom select variant (value, event)',
|
|
35
|
+
control: false,
|
|
36
|
+
table: {
|
|
37
|
+
type: {
|
|
38
|
+
summary: '(value: string | number, ev: React.UIEvent) => void',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
10
42
|
native: {
|
|
43
|
+
description: 'Render the native `<select>` variant when true',
|
|
11
44
|
control: { type: 'boolean' },
|
|
45
|
+
table: { type: { summary: 'boolean' } },
|
|
46
|
+
},
|
|
47
|
+
nativeHtmlAttributes: {
|
|
48
|
+
description: 'Additional props to spread onto the native `<select>`',
|
|
49
|
+
control: false,
|
|
50
|
+
table: {
|
|
51
|
+
type: { summary: 'React.SelectHTMLAttributes<HTMLSelectElement>' },
|
|
52
|
+
},
|
|
12
53
|
},
|
|
13
54
|
disabled: {
|
|
55
|
+
description: 'Disable interaction',
|
|
14
56
|
control: { type: 'boolean' },
|
|
57
|
+
table: { type: { summary: 'boolean' } },
|
|
15
58
|
},
|
|
16
59
|
placeholder: {
|
|
60
|
+
description: 'Helper text when no value is selected',
|
|
17
61
|
control: { type: 'text' },
|
|
62
|
+
table: { type: { summary: 'string' } },
|
|
18
63
|
},
|
|
19
|
-
|
|
64
|
+
filterable: {
|
|
65
|
+
description:
|
|
66
|
+
'Show a filter input to narrow options in the custom variant',
|
|
67
|
+
control: { type: 'boolean' },
|
|
68
|
+
table: { type: { summary: 'boolean' } },
|
|
69
|
+
},
|
|
70
|
+
filterInputProps: {
|
|
71
|
+
description:
|
|
72
|
+
'Additional props to spread onto the filter input (when filterable)',
|
|
73
|
+
control: { type: 'object' },
|
|
74
|
+
table: {
|
|
75
|
+
type: {
|
|
76
|
+
summary: 'React.InputHTMLAttributes<HTMLInputElement>',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
id: {
|
|
81
|
+
description: 'Standard HTML id forwarded to the combobox/native select',
|
|
82
|
+
control: { type: 'text' },
|
|
83
|
+
table: { type: { summary: 'string' } },
|
|
84
|
+
},
|
|
85
|
+
title: {
|
|
86
|
+
description:
|
|
87
|
+
'Standard title attribute forwarded to the combobox/native select',
|
|
20
88
|
control: { type: 'text' },
|
|
89
|
+
table: { type: { summary: 'string' } },
|
|
21
90
|
},
|
|
22
91
|
lineBreak: {
|
|
92
|
+
description: 'Wrap long option labels',
|
|
23
93
|
control: { type: 'boolean' },
|
|
94
|
+
table: { type: { summary: 'boolean' } },
|
|
95
|
+
},
|
|
96
|
+
panelClassName: {
|
|
97
|
+
description: 'Custom className for the options panel',
|
|
98
|
+
control: { type: 'text' },
|
|
99
|
+
table: { type: { summary: 'string' } },
|
|
100
|
+
},
|
|
101
|
+
className: {
|
|
102
|
+
description: 'Custom className for the root element',
|
|
103
|
+
control: { type: 'text' },
|
|
104
|
+
table: { type: { summary: 'string' } },
|
|
105
|
+
},
|
|
106
|
+
testId: {
|
|
107
|
+
description: 'Test id applied to the root element',
|
|
108
|
+
control: { type: 'text' },
|
|
109
|
+
table: { type: { summary: 'string' } },
|
|
24
110
|
},
|
|
25
111
|
},
|
|
26
112
|
args: {
|
|
113
|
+
selectionBehaviour: 'focus',
|
|
27
114
|
value: undefined,
|
|
28
|
-
onChange: () => {},
|
|
29
115
|
options: [
|
|
30
116
|
{ label: 'Option one', value: '1' },
|
|
31
117
|
{ label: 'Option two', value: '2' },
|
|
32
118
|
{ label: 'Option three', value: '3' },
|
|
33
119
|
],
|
|
34
120
|
},
|
|
121
|
+
parameters: {
|
|
122
|
+
docs: {
|
|
123
|
+
story: { inline: true },
|
|
124
|
+
},
|
|
125
|
+
},
|
|
35
126
|
} satisfies Meta<typeof Select>;
|
|
36
127
|
|
|
37
128
|
export default meta;
|
|
@@ -44,12 +135,15 @@ export const Default: Story = {
|
|
|
44
135
|
updateArgs({ value });
|
|
45
136
|
};
|
|
46
137
|
return (
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
138
|
+
<div style={storyWrapperStyle}>
|
|
139
|
+
<Select
|
|
140
|
+
{...args}
|
|
141
|
+
className={select400pxWidthClass}
|
|
142
|
+
options={args.options}
|
|
143
|
+
value={args.value}
|
|
144
|
+
onValueChange={onValueChange}
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
53
147
|
);
|
|
54
148
|
},
|
|
55
149
|
};
|
|
@@ -60,16 +154,18 @@ export const Native: Story = {
|
|
|
60
154
|
},
|
|
61
155
|
render: () => {
|
|
62
156
|
const [args, updateArgs] = useArgs();
|
|
63
|
-
const
|
|
64
|
-
updateArgs({ value });
|
|
65
|
-
};
|
|
157
|
+
const onNativeChange = (event: React.ChangeEvent<HTMLSelectElement>) =>
|
|
158
|
+
updateArgs({ value: event.target.value });
|
|
66
159
|
return (
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
160
|
+
<div style={storyWrapperStyle}>
|
|
161
|
+
<Select
|
|
162
|
+
{...args}
|
|
163
|
+
className={select400pxWidthClass}
|
|
164
|
+
options={args.options}
|
|
165
|
+
value={args.value}
|
|
166
|
+
nativeHtmlAttributes={{ onChange: onNativeChange }}
|
|
167
|
+
/>
|
|
168
|
+
</div>
|
|
73
169
|
);
|
|
74
170
|
},
|
|
75
171
|
};
|
|
@@ -85,12 +181,15 @@ export const Disabled: Story = {
|
|
|
85
181
|
};
|
|
86
182
|
|
|
87
183
|
return (
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
184
|
+
<div style={storyWrapperStyle}>
|
|
185
|
+
<Select
|
|
186
|
+
{...args}
|
|
187
|
+
className={select400pxWidthClass}
|
|
188
|
+
options={args.options}
|
|
189
|
+
value={args.value}
|
|
190
|
+
onValueChange={onValueChange}
|
|
191
|
+
/>
|
|
192
|
+
</div>
|
|
94
193
|
);
|
|
95
194
|
},
|
|
96
195
|
};
|
|
@@ -104,12 +203,15 @@ export const WithPlaceholder: Story = {
|
|
|
104
203
|
};
|
|
105
204
|
|
|
106
205
|
return (
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
206
|
+
<div style={storyWrapperStyle}>
|
|
207
|
+
<Select
|
|
208
|
+
{...args}
|
|
209
|
+
className={select400pxWidthClass}
|
|
210
|
+
options={args.options}
|
|
211
|
+
value={args.value}
|
|
212
|
+
onValueChange={onValueChange}
|
|
213
|
+
/>
|
|
214
|
+
</div>
|
|
113
215
|
);
|
|
114
216
|
},
|
|
115
217
|
};
|
|
@@ -130,12 +232,15 @@ export const SingleLongOption: Story = {
|
|
|
130
232
|
};
|
|
131
233
|
|
|
132
234
|
return (
|
|
133
|
-
<
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
235
|
+
<div style={storyWrapperStyle}>
|
|
236
|
+
<Select
|
|
237
|
+
{...args}
|
|
238
|
+
className={select400pxWidthClass}
|
|
239
|
+
options={args.options}
|
|
240
|
+
value={args.value}
|
|
241
|
+
onValueChange={onValueChange}
|
|
242
|
+
/>
|
|
243
|
+
</div>
|
|
139
244
|
);
|
|
140
245
|
},
|
|
141
246
|
};
|
|
@@ -167,12 +272,55 @@ export const ManyOptions: Story = {
|
|
|
167
272
|
updateArgs({ value });
|
|
168
273
|
};
|
|
169
274
|
return (
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
275
|
+
<div style={storyWrapperStyle}>
|
|
276
|
+
<Select
|
|
277
|
+
{...args}
|
|
278
|
+
className={select400pxWidthClass}
|
|
279
|
+
options={args.options}
|
|
280
|
+
value={args.value}
|
|
281
|
+
onValueChange={onValueChange}
|
|
282
|
+
/>
|
|
283
|
+
</div>
|
|
284
|
+
);
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
export const filterable: Story = {
|
|
289
|
+
args: { filterable: true },
|
|
290
|
+
render: () => {
|
|
291
|
+
const [args, updateArgs] = useArgs();
|
|
292
|
+
const onValueChange = (value: string | number) => updateArgs({ value });
|
|
293
|
+
return (
|
|
294
|
+
<div style={storyWrapperStyle}>
|
|
295
|
+
<Select
|
|
296
|
+
{...args}
|
|
297
|
+
className={select400pxWidthClass}
|
|
298
|
+
options={args.options}
|
|
299
|
+
value={args.value}
|
|
300
|
+
onValueChange={onValueChange}
|
|
301
|
+
placeholder='Type to filter...'
|
|
302
|
+
/>
|
|
303
|
+
</div>
|
|
304
|
+
);
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export const SelectionBehaviourCommit: Story = {
|
|
309
|
+
name: 'Selection behaviour: commit',
|
|
310
|
+
args: { selectionBehaviour: 'commit' },
|
|
311
|
+
render: () => {
|
|
312
|
+
const [args, updateArgs] = useArgs();
|
|
313
|
+
const onValueChange = (value: string | number) => updateArgs({ value });
|
|
314
|
+
return (
|
|
315
|
+
<div style={storyWrapperStyle}>
|
|
316
|
+
<Select
|
|
317
|
+
{...args}
|
|
318
|
+
className={select400pxWidthClass}
|
|
319
|
+
options={args.options}
|
|
320
|
+
value={args.value}
|
|
321
|
+
onValueChange={onValueChange}
|
|
322
|
+
/>
|
|
323
|
+
</div>
|
|
176
324
|
);
|
|
177
325
|
},
|
|
178
326
|
};
|
|
@@ -2,24 +2,48 @@ import { NativeSelect, CustomSelect } from './subcomponents';
|
|
|
2
2
|
import { SelectProps } from './Select.types';
|
|
3
3
|
|
|
4
4
|
const Select = <T extends string | number = string>(props: SelectProps<T>) => {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const {
|
|
6
|
+
native,
|
|
7
|
+
nativeHtmlAttributes,
|
|
8
|
+
filterable,
|
|
9
|
+
onValueChange,
|
|
10
|
+
ref,
|
|
11
|
+
...rest
|
|
12
|
+
} = props;
|
|
13
|
+
|
|
14
|
+
if (native) {
|
|
15
|
+
if (filterable) {
|
|
16
|
+
console.warn('filterable is not supported on native Select; ignoring.');
|
|
17
|
+
}
|
|
18
|
+
const { value, ...nativeRest } = rest;
|
|
19
|
+
const {
|
|
20
|
+
value: nativeAttrValue,
|
|
21
|
+
onChange,
|
|
22
|
+
...nativeAttrs
|
|
23
|
+
} = nativeHtmlAttributes || {};
|
|
24
|
+
const nativeValue: string | number | undefined =
|
|
25
|
+
typeof value === 'string' || typeof value === 'number'
|
|
26
|
+
? value
|
|
27
|
+
: undefined;
|
|
7
28
|
return (
|
|
8
29
|
<NativeSelect
|
|
30
|
+
value={nativeValue ?? (nativeAttrValue as string | number | undefined)}
|
|
9
31
|
onChange={onChange}
|
|
10
|
-
|
|
11
|
-
{...
|
|
12
|
-
|
|
13
|
-
);
|
|
14
|
-
} else {
|
|
15
|
-
const { onValueChange, ...rest } = props;
|
|
16
|
-
return (
|
|
17
|
-
<CustomSelect<T>
|
|
18
|
-
onValueChange={onValueChange}
|
|
19
|
-
{...rest}
|
|
32
|
+
ref={ref as React.Ref<HTMLSelectElement>}
|
|
33
|
+
{...nativeRest}
|
|
34
|
+
{...nativeAttrs}
|
|
20
35
|
/>
|
|
21
36
|
);
|
|
22
37
|
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<CustomSelect<T>
|
|
41
|
+
onValueChange={onValueChange}
|
|
42
|
+
filterable={filterable}
|
|
43
|
+
ref={ref as React.Ref<HTMLDivElement>}
|
|
44
|
+
{...rest}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
23
47
|
};
|
|
24
48
|
|
|
25
49
|
export default Select;
|
|
@@ -24,9 +24,30 @@ export type OptionData<T> = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Additional props forwarded to the filter input when `filterable` is true
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
export type FilterInputProps = Omit<
|
|
30
|
+
React.InputHTMLAttributes<HTMLInputElement>,
|
|
31
|
+
| 'value'
|
|
32
|
+
| 'onChange'
|
|
33
|
+
| 'disabled'
|
|
34
|
+
| 'ref'
|
|
35
|
+
| 'role'
|
|
36
|
+
| 'aria-autocomplete'
|
|
37
|
+
| 'aria-label'
|
|
38
|
+
>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Public props for <Select>, used by both custom and native render paths.
|
|
42
|
+
*/
|
|
43
|
+
export interface SelectProps<T = string | number>
|
|
44
|
+
extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
45
|
+
/**
|
|
46
|
+
* Controls keyboard selection behaviour in the custom select variant.
|
|
47
|
+
* - `focus` (default): arrow keys move focus and commit value immediately.
|
|
48
|
+
* - `commit`: arrow keys only move focus; Enter or click commits value.
|
|
49
|
+
*/
|
|
50
|
+
selectionBehaviour?: 'focus' | 'commit';
|
|
30
51
|
/**
|
|
31
52
|
* An array of option data, to be rendered either natively or custom
|
|
32
53
|
*/
|
|
@@ -51,53 +72,49 @@ interface BaseSelectProps<T = string> {
|
|
|
51
72
|
* Native flag determines which implementation to use
|
|
52
73
|
*/
|
|
53
74
|
native?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Adds a text input to filter options in the custom variant; ignored for native
|
|
77
|
+
*/
|
|
78
|
+
filterable?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Extra props to apply to the filter input when `filterable` is true
|
|
81
|
+
*/
|
|
82
|
+
filterInputProps?: FilterInputProps;
|
|
83
|
+
/**
|
|
84
|
+
* Extra attributes forwarded to the native <select> when `native` is true
|
|
85
|
+
*/
|
|
86
|
+
nativeHtmlAttributes?: React.SelectHTMLAttributes<HTMLSelectElement>;
|
|
87
|
+
/**
|
|
88
|
+
* Current value (controlled)
|
|
89
|
+
*/
|
|
90
|
+
value?: T;
|
|
91
|
+
/**
|
|
92
|
+
* Disable interaction
|
|
93
|
+
*/
|
|
94
|
+
disabled?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Allow long option labels to wrap instead of truncating
|
|
97
|
+
*/
|
|
98
|
+
lineBreak?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Custom className for the root element
|
|
101
|
+
*/
|
|
102
|
+
className?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Custom className for the options panel
|
|
105
|
+
*/
|
|
106
|
+
panelClassName?: string;
|
|
107
|
+
/**
|
|
108
|
+
* Change handler for the custom variant
|
|
109
|
+
*/
|
|
110
|
+
onValueChange?: (value: T, ev: React.UIEvent) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Ref forwarded to the rendered element
|
|
113
|
+
* (div for custom, select for native)
|
|
114
|
+
*/
|
|
115
|
+
ref?: React.Ref<HTMLDivElement | HTMLSelectElement | null>;
|
|
54
116
|
}
|
|
55
117
|
|
|
56
|
-
// export type SelectProps = BaseSelectProps &
|
|
57
|
-
// // Discriminated union to determine which implementation to use
|
|
58
|
-
// (| ({ native: true; ref?: React.RefObject<HTMLSelectElement | null> } & Omit<
|
|
59
|
-
// React.SelectHTMLAttributes<HTMLSelectElement>,
|
|
60
|
-
// keyof BaseSelectProps
|
|
61
|
-
// >)
|
|
62
|
-
// | ({ native?: false; ref?: React.RefObject<HTMLDivElement | null> } & Omit<
|
|
63
|
-
// React.HTMLAttributes<HTMLDivElement>,
|
|
64
|
-
// keyof BaseSelectProps
|
|
65
|
-
// >)
|
|
66
|
-
// );
|
|
67
|
-
|
|
68
|
-
// Props interface for the two variants are separated.
|
|
69
|
-
// We expose SelectProps for developers to use, and handle discrepancies internally.
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Internal props for the custom implementation, with <div> as root element
|
|
73
|
-
* onChange already exists on <div>. We override it.
|
|
74
|
-
*/
|
|
75
|
-
export type CustomSelectProps<T> = Omit<
|
|
76
|
-
React.HTMLAttributes<HTMLDivElement>,
|
|
77
|
-
'onChange'
|
|
78
|
-
> &
|
|
79
|
-
BaseSelectProps<T> & {
|
|
80
|
-
native?: false;
|
|
81
|
-
value?: T;
|
|
82
|
-
disabled?: boolean;
|
|
83
|
-
lineBreak?: boolean;
|
|
84
|
-
panelClassName?: string;
|
|
85
|
-
onValueChange?: (value: T, ev: React.UIEvent) => void;
|
|
86
|
-
ref?: React.RefObject<HTMLDivElement | null>;
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Internal props for native implementation, with <select> as root element
|
|
91
|
-
* Default props like value and onChange are passed to the <select> element automatically
|
|
92
|
-
*/
|
|
93
|
-
export type NativeSelectProps = React.SelectHTMLAttributes<HTMLSelectElement> &
|
|
94
|
-
BaseSelectProps & {
|
|
95
|
-
native: true;
|
|
96
|
-
ref?: React.RefObject<HTMLSelectElement | null>;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
export type SelectProps<T> = NativeSelectProps | CustomSelectProps<T>;
|
|
100
|
-
|
|
101
118
|
/**
|
|
102
119
|
* Each option as displayed in the Panel of <CustomSelect>
|
|
103
120
|
* Roughly equivalent to a custom version of <option>
|
|
@@ -105,8 +122,9 @@ export type SelectProps<T> = NativeSelectProps | CustomSelectProps<T>;
|
|
|
105
122
|
export interface CustomOptionProps<T>
|
|
106
123
|
extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {
|
|
107
124
|
value: T;
|
|
125
|
+
optionIndex?: number;
|
|
108
126
|
testId?: string;
|
|
109
127
|
isSelected?: boolean;
|
|
110
|
-
onSelect: (event: React.MouseEvent, value: T) => void;
|
|
128
|
+
onSelect: (event: React.MouseEvent, value: T, optionIndex?: number) => void;
|
|
111
129
|
lineBreak?: boolean;
|
|
112
130
|
}
|