@ceed/cds 1.36.0-next.1 → 1.36.1
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/Alert/Alert.d.ts +1 -1
- package/dist/components/FilterableCheckboxGroup/FilterableCheckboxGroup.d.ts +1 -1
- package/dist/components/Pagination/Pagination.d.ts +1 -1
- package/dist/components/Select/Select.d.ts +9 -1
- package/dist/components/ThemeProvider/ThemeProvider.d.ts +0 -15
- package/dist/components/inputs/Select.md +78 -25
- package/dist/index.browser.js +4 -4
- package/dist/index.browser.js.map +3 -3
- package/dist/index.cjs +216 -214
- package/dist/index.js +50 -48
- package/framer/index.js +1 -1
- package/package.json +2 -3
|
@@ -14,7 +14,7 @@ export interface CustomAlertProps {
|
|
|
14
14
|
size?: AlertSize;
|
|
15
15
|
}
|
|
16
16
|
export type AlertProps = CustomAlertProps & Omit<JoyAlertProps, 'content' | 'actions' | 'title' | 'size'> & Omit<MotionProps, 'children'>;
|
|
17
|
-
declare function Alert(
|
|
17
|
+
declare function Alert(props: AlertProps): React.JSX.Element;
|
|
18
18
|
declare namespace Alert {
|
|
19
19
|
var displayName: string;
|
|
20
20
|
}
|
|
@@ -16,7 +16,7 @@ export type FilterableCheckboxGroupProps = {
|
|
|
16
16
|
maxHeight?: string | number;
|
|
17
17
|
disabled?: boolean;
|
|
18
18
|
};
|
|
19
|
-
declare function FilterableCheckboxGroup(
|
|
19
|
+
declare function FilterableCheckboxGroup(props: FilterableCheckboxGroupProps): React.JSX.Element;
|
|
20
20
|
declare namespace FilterableCheckboxGroup {
|
|
21
21
|
var displayName: string;
|
|
22
22
|
}
|
|
@@ -23,7 +23,7 @@ export interface PaginationProps extends React.ComponentProps<typeof PaginationR
|
|
|
23
23
|
size?: 'sm' | 'md' | 'lg';
|
|
24
24
|
variant?: 'standard' | 'compact';
|
|
25
25
|
}
|
|
26
|
-
declare function Pagination(
|
|
26
|
+
declare function Pagination(props: PaginationProps): React.JSX.Element;
|
|
27
27
|
declare namespace Pagination {
|
|
28
28
|
var displayName: string;
|
|
29
29
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import React, { ComponentProps } from 'react';
|
|
2
2
|
import { Select as JoySelect, type SelectProps as JoySelectProps } from '@mui/joy';
|
|
3
|
+
import FormControl from '../FormControl';
|
|
4
|
+
import FormLabel from '../FormLabel';
|
|
5
|
+
import FormHelperText from '../FormHelperText';
|
|
3
6
|
import { SelectValue } from '@mui/base';
|
|
4
7
|
export type { JoySelectProps };
|
|
5
8
|
export type { OptionProps } from '@mui/joy';
|
|
@@ -24,11 +27,16 @@ export { Option };
|
|
|
24
27
|
export type InferOptionValue<OptionValue> = OptionValue extends {
|
|
25
28
|
value: infer V;
|
|
26
29
|
} ? V : OptionValue;
|
|
27
|
-
export interface SelectProps<OptionValue extends OptionType, Multiple extends boolean = false> extends Omit<ComponentProps<typeof JoySelect<OptionValue, any, Multiple>>, 'value' | 'onChange' | 'multiple'> {
|
|
30
|
+
export interface SelectProps<OptionValue extends OptionType, Multiple extends boolean = false> extends Omit<ComponentProps<typeof JoySelect<OptionValue, any, Multiple>>, 'value' | 'onChange' | 'multiple' | 'slotProps'> {
|
|
28
31
|
options: OptionValue[];
|
|
29
32
|
label?: string;
|
|
30
33
|
helperText?: string;
|
|
31
34
|
error?: boolean;
|
|
35
|
+
slotProps?: ComponentProps<typeof JoySelect<OptionValue, any, Multiple>>['slotProps'] & {
|
|
36
|
+
formControl?: ComponentProps<typeof FormControl>;
|
|
37
|
+
formLabel?: ComponentProps<typeof FormLabel>;
|
|
38
|
+
formHelperText?: ComponentProps<typeof FormHelperText>;
|
|
39
|
+
};
|
|
32
40
|
value?: SelectValue<InferOptionValue<OptionValue>, Multiple>;
|
|
33
41
|
onChange?: (event: Omit<React.SyntheticEvent<HTMLElement>, 'target'> & {
|
|
34
42
|
target: {
|
|
@@ -8,9 +8,6 @@ import { MonthPickerProps } from '../MonthPicker';
|
|
|
8
8
|
import { MonthRangePickerProps } from '../MonthRangePicker';
|
|
9
9
|
import { PercentageInputProps } from '../PercentageInput';
|
|
10
10
|
import type { SearchBarOwnerState, SearchBarProps, SearchBarSlot } from '../SearchBar/SearchBar';
|
|
11
|
-
import type { AlertProps } from '../Alert/Alert';
|
|
12
|
-
import type { PaginationProps } from '../Pagination/Pagination';
|
|
13
|
-
import type { FilterableCheckboxGroupProps } from '../FilterableCheckboxGroup/FilterableCheckboxGroup';
|
|
14
11
|
declare module '@mui/joy/styles' {
|
|
15
12
|
interface TypographySystemOverrides {
|
|
16
13
|
'marketing-lg': true;
|
|
@@ -50,18 +47,6 @@ declare module '@mui/joy/styles' {
|
|
|
50
47
|
defaultProps?: Partial<SearchBarProps>;
|
|
51
48
|
styleOverrides?: StyleOverrides<SearchBarSlot, SearchBarOwnerState, Theme>;
|
|
52
49
|
};
|
|
53
|
-
Alert?: {
|
|
54
|
-
defaultProps?: Partial<AlertProps>;
|
|
55
|
-
styleOverrides?: StyleOverrides<'root', {}, Theme>;
|
|
56
|
-
};
|
|
57
|
-
Pagination?: {
|
|
58
|
-
defaultProps?: Partial<PaginationProps>;
|
|
59
|
-
styleOverrides?: StyleOverrides<'root' | 'button' | 'container', {}, Theme>;
|
|
60
|
-
};
|
|
61
|
-
FilterableCheckboxGroup?: {
|
|
62
|
-
defaultProps?: Partial<FilterableCheckboxGroupProps>;
|
|
63
|
-
styleOverrides?: StyleOverrides<'root', {}, Theme>;
|
|
64
|
-
};
|
|
65
50
|
}
|
|
66
51
|
}
|
|
67
52
|
declare module '@mui/joy/Avatar' {
|
|
@@ -207,6 +207,58 @@ Combining `label`, `helperText`, and `error` produces a complete form field. Her
|
|
|
207
207
|
</>
|
|
208
208
|
```
|
|
209
209
|
|
|
210
|
+
## Slot Props and Deterministic Ids
|
|
211
|
+
|
|
212
|
+
The `slotProps` prop targets both Joy Select's own slots (`button`, `listbox`, `root`, …) and the wrapper slots that `Select` composes around it (`formControl`, `formLabel`, `formHelperText`). Pass `id` (or `slotProps.formControl.id`) to pin the field's ids deterministically — `FormControl` derives the button `id` and the label `id` (`${id}-label`) from it, which keeps `byLabelText` / `byRole('combobox', { name })` queries stable in tests.
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
<Stack
|
|
216
|
+
spacing={3}
|
|
217
|
+
sx={{
|
|
218
|
+
minWidth: 240
|
|
219
|
+
}}
|
|
220
|
+
>
|
|
221
|
+
{/* id seeds deterministic FormControl ids: button#pet, label#pet-label (testable via byLabelText/byRole) */}
|
|
222
|
+
<Select
|
|
223
|
+
id="pet"
|
|
224
|
+
label="Pet"
|
|
225
|
+
defaultValue="cat"
|
|
226
|
+
options={options}
|
|
227
|
+
slotProps={{
|
|
228
|
+
formLabel: {
|
|
229
|
+
sx: {
|
|
230
|
+
color: "primary.500"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
formHelperText: {
|
|
234
|
+
sx: {
|
|
235
|
+
fontStyle: "italic"
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
button: {
|
|
239
|
+
"aria-describedby": "pet-extra"
|
|
240
|
+
}
|
|
241
|
+
}}
|
|
242
|
+
helperText="Wired via slotProps"
|
|
243
|
+
/>
|
|
244
|
+
</Stack>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
<Select
|
|
249
|
+
id="pet"
|
|
250
|
+
label="Pet"
|
|
251
|
+
helperText="Wired via slotProps"
|
|
252
|
+
options={options}
|
|
253
|
+
slotProps={{
|
|
254
|
+
formLabel: { sx: { color: 'primary.500' } },
|
|
255
|
+
formHelperText: { sx: { fontStyle: 'italic' } },
|
|
256
|
+
button: { 'aria-describedby': 'pet-extra' },
|
|
257
|
+
}}
|
|
258
|
+
/>
|
|
259
|
+
// → renders button#pet and label#pet-label, connected via aria-labelledby
|
|
260
|
+
```
|
|
261
|
+
|
|
210
262
|
## Required Field
|
|
211
263
|
|
|
212
264
|
Set `required` to mark the field as required. An asterisk is added to the label automatically.
|
|
@@ -373,9 +425,7 @@ const numericOptions = [
|
|
|
373
425
|
<Select options={numericOptions} defaultValue={1} />;
|
|
374
426
|
```
|
|
375
427
|
|
|
376
|
-
##
|
|
377
|
-
|
|
378
|
-
### Form with Validation
|
|
428
|
+
## Form with Validation
|
|
379
429
|
|
|
380
430
|
```tsx
|
|
381
431
|
import { useState } from 'react';
|
|
@@ -417,7 +467,7 @@ function UserForm() {
|
|
|
417
467
|
}
|
|
418
468
|
```
|
|
419
469
|
|
|
420
|
-
|
|
470
|
+
## Filter Bar
|
|
421
471
|
|
|
422
472
|
```tsx
|
|
423
473
|
import { Select, Stack } from '@ceed/cds';
|
|
@@ -459,7 +509,7 @@ function ProductFilter({ onFilterChange }) {
|
|
|
459
509
|
}
|
|
460
510
|
```
|
|
461
511
|
|
|
462
|
-
|
|
512
|
+
## Dependent Selects
|
|
463
513
|
|
|
464
514
|
```tsx
|
|
465
515
|
import { useState, useMemo } from 'react';
|
|
@@ -559,25 +609,27 @@ function LocationSelect() {
|
|
|
559
609
|
|
|
560
610
|
### Key Props
|
|
561
611
|
|
|
562
|
-
| Prop | Type
|
|
563
|
-
| ---------------- |
|
|
564
|
-
| `options` | `OptionType[]`
|
|
565
|
-
| `value` | `InferOptionValue<OptionType> \| InferOptionValue<OptionType>[]`
|
|
566
|
-
| `defaultValue` | `InferOptionValue<OptionType> \| InferOptionValue<OptionType>[]`
|
|
567
|
-
| `onChange` | `(event: { target: { name?, value } }, newValue) => void`
|
|
568
|
-
| `multiple` | `boolean`
|
|
569
|
-
| `label` | `string`
|
|
570
|
-
| `helperText` | `string`
|
|
571
|
-
| `error` | `boolean`
|
|
572
|
-
| `required` | `boolean`
|
|
573
|
-
| `disabled` | `boolean`
|
|
574
|
-
| `placeholder` | `string`
|
|
575
|
-
| `size` | `'sm' \| 'md' \| 'lg'`
|
|
576
|
-
| `variant` | `'outlined' \| 'plain' \| 'solid' \| 'soft'`
|
|
577
|
-
| `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'`
|
|
578
|
-
| `startDecorator` | `ReactNode`
|
|
579
|
-
| `endDecorator` | `ReactNode`
|
|
580
|
-
| `
|
|
612
|
+
| Prop | Type | Default | Description |
|
|
613
|
+
| ---------------- | ----------------------------------------------------------------------- | ----------------- | -------------------------------------------------------------- |
|
|
614
|
+
| `options` | `OptionType[]` | `[]` | Array of options (objects or primitives) |
|
|
615
|
+
| `value` | `InferOptionValue<OptionType> \| InferOptionValue<OptionType>[]` | - | Selected value(s) for controlled mode |
|
|
616
|
+
| `defaultValue` | `InferOptionValue<OptionType> \| InferOptionValue<OptionType>[]` | - | Initial value for uncontrolled mode |
|
|
617
|
+
| `onChange` | `(event: { target: { name?, value } }, newValue) => void` | - | Callback when selection changes |
|
|
618
|
+
| `multiple` | `boolean` | `false` | Allow multiple selections (value becomes an array) |
|
|
619
|
+
| `label` | `string` | - | Form label displayed above the select |
|
|
620
|
+
| `helperText` | `string` | - | Helper text displayed below the select |
|
|
621
|
+
| `error` | `boolean` | `false` | Applies danger color to indicate validation error |
|
|
622
|
+
| `required` | `boolean` | `false` | Marks the field as required (adds asterisk to label) |
|
|
623
|
+
| `disabled` | `boolean` | `false` | Disables the select |
|
|
624
|
+
| `placeholder` | `string` | `'Choose one...'` | Placeholder text when no value is selected |
|
|
625
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Select size |
|
|
626
|
+
| `variant` | `'outlined' \| 'plain' \| 'solid' \| 'soft'` | `'outlined'` | Visual style variant |
|
|
627
|
+
| `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Color scheme |
|
|
628
|
+
| `startDecorator` | `ReactNode` | - | Content rendered before the select trigger text |
|
|
629
|
+
| `endDecorator` | `ReactNode` | - | Content rendered after the select trigger text |
|
|
630
|
+
| `id` | `string` | - | Seeds deterministic ids: button `id`, label `${id}-label` |
|
|
631
|
+
| `slotProps` | `{ formControl?, formLabel?, formHelperText?, button?, listbox?, ... }` | - | Props forwarded to composed wrapper slots and Joy Select slots |
|
|
632
|
+
| `sx` | `SxProps` | - | Custom styles using the MUI system |
|
|
581
633
|
|
|
582
634
|
### Option Type
|
|
583
635
|
|
|
@@ -613,7 +665,8 @@ const options = [
|
|
|
613
665
|
|
|
614
666
|
## Accessibility
|
|
615
667
|
|
|
616
|
-
- **Label association**: When you use the `label` prop, the component automatically connects the label to the select element via `aria-labelledby
|
|
668
|
+
- **Label association**: When you use the `label` prop, the component automatically connects the label to the select element via `aria-labelledby` (the internal `FormControl` propagates a `labelId` to both the label and the button slot). You do not need to wire `useId` or a custom `FormLabel` externally. Always provide a label for screen reader users.
|
|
669
|
+
- **Deterministic ids for tests**: Pass `id` (or `slotProps.formControl.id`) to fix the generated ids, so `byLabelText` / `byRole('combobox', { name })` resolve to a stable accessible name.
|
|
617
670
|
- **Keyboard navigation**: The select can be opened with Enter or Space, navigated with Arrow Up/Down and Home/End, confirmed with Enter, and dismissed with Escape.
|
|
618
671
|
- **Error announcement**: When `error` is set, `aria-invalid` is applied. Pair it with a descriptive `helperText` so assistive technology can announce the error reason.
|
|
619
672
|
- **Required state**: The `required` prop adds `aria-required` and a visible asterisk to the label, communicating the requirement both visually and programmatically.
|