@patternfly/react-templates 1.1.0-prerelease.9 → 1.1.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 (105) hide show
  1. package/CHANGELOG.md +150 -0
  2. package/components/package.json +1 -1
  3. package/dist/dynamic/components/Dropdown/package.json +1 -1
  4. package/dist/dynamic/components/Select/package.json +1 -1
  5. package/dist/dynamic-modules.json +14 -10
  6. package/dist/esm/components/Dropdown/{DropdownSimple.d.ts → SimpleDropdown.d.ts} +11 -6
  7. package/dist/esm/components/Dropdown/SimpleDropdown.d.ts.map +1 -0
  8. package/dist/esm/components/Dropdown/{DropdownSimple.js → SimpleDropdown.js} +13 -7
  9. package/dist/esm/components/Dropdown/SimpleDropdown.js.map +1 -0
  10. package/dist/esm/components/Dropdown/index.d.ts +1 -1
  11. package/dist/esm/components/Dropdown/index.js +1 -1
  12. package/dist/esm/components/Select/CheckboxSelect.d.ts +7 -3
  13. package/dist/esm/components/Select/CheckboxSelect.d.ts.map +1 -1
  14. package/dist/esm/components/Select/CheckboxSelect.js +14 -6
  15. package/dist/esm/components/Select/CheckboxSelect.js.map +1 -1
  16. package/dist/esm/components/Select/MultiTypeaheadSelect.d.ts +33 -0
  17. package/dist/esm/components/Select/MultiTypeaheadSelect.d.ts.map +1 -0
  18. package/dist/esm/components/Select/{SelectTypeahead.js → MultiTypeaheadSelect.js} +52 -45
  19. package/dist/esm/components/Select/MultiTypeaheadSelect.js.map +1 -0
  20. package/dist/{js/components/Select/SelectSimple.d.ts → esm/components/Select/SimpleSelect.d.ts} +12 -7
  21. package/dist/esm/components/Select/SimpleSelect.d.ts.map +1 -0
  22. package/dist/esm/components/Select/SimpleSelect.js +39 -0
  23. package/dist/esm/components/Select/SimpleSelect.js.map +1 -0
  24. package/dist/esm/components/Select/TypeaheadSelect.d.ts +47 -0
  25. package/dist/esm/components/Select/TypeaheadSelect.d.ts.map +1 -0
  26. package/dist/esm/components/Select/TypeaheadSelect.js +228 -0
  27. package/dist/esm/components/Select/TypeaheadSelect.js.map +1 -0
  28. package/dist/esm/components/Select/index.d.ts +3 -2
  29. package/dist/esm/components/Select/index.d.ts.map +1 -1
  30. package/dist/esm/components/Select/index.js +3 -2
  31. package/dist/esm/components/Select/index.js.map +1 -1
  32. package/dist/js/components/Dropdown/{DropdownSimple.d.ts → SimpleDropdown.d.ts} +11 -6
  33. package/dist/js/components/Dropdown/SimpleDropdown.d.ts.map +1 -0
  34. package/dist/js/components/Dropdown/{DropdownSimple.js → SimpleDropdown.js} +14 -9
  35. package/dist/js/components/Dropdown/SimpleDropdown.js.map +1 -0
  36. package/dist/js/components/Dropdown/index.d.ts +1 -1
  37. package/dist/js/components/Dropdown/index.js +1 -1
  38. package/dist/js/components/Select/CheckboxSelect.d.ts +7 -3
  39. package/dist/js/components/Select/CheckboxSelect.d.ts.map +1 -1
  40. package/dist/js/components/Select/CheckboxSelect.js +14 -6
  41. package/dist/js/components/Select/CheckboxSelect.js.map +1 -1
  42. package/dist/js/components/Select/MultiTypeaheadSelect.d.ts +33 -0
  43. package/dist/js/components/Select/MultiTypeaheadSelect.d.ts.map +1 -0
  44. package/dist/js/components/Select/{SelectTypeahead.js → MultiTypeaheadSelect.js} +53 -46
  45. package/dist/js/components/Select/MultiTypeaheadSelect.js.map +1 -0
  46. package/dist/{esm/components/Select/SelectSimple.d.ts → js/components/Select/SimpleSelect.d.ts} +12 -7
  47. package/dist/js/components/Select/SimpleSelect.d.ts.map +1 -0
  48. package/dist/js/components/Select/SimpleSelect.js +42 -0
  49. package/dist/js/components/Select/SimpleSelect.js.map +1 -0
  50. package/dist/js/components/Select/TypeaheadSelect.d.ts +47 -0
  51. package/dist/js/components/Select/TypeaheadSelect.d.ts.map +1 -0
  52. package/dist/js/components/Select/TypeaheadSelect.js +232 -0
  53. package/dist/js/components/Select/TypeaheadSelect.js.map +1 -0
  54. package/dist/js/components/Select/index.d.ts +3 -2
  55. package/dist/js/components/Select/index.d.ts.map +1 -1
  56. package/dist/js/components/Select/index.js +3 -2
  57. package/dist/js/components/Select/index.js.map +1 -1
  58. package/dist/umd/assets/output-D8cue3c6.css +26066 -0
  59. package/dist/umd/react-templates.min.js +1 -1
  60. package/package.json +7 -10
  61. package/rollup.config.mjs +8 -0
  62. package/src/components/Dropdown/{DropdownSimple.tsx → SimpleDropdown.tsx} +28 -11
  63. package/src/components/Dropdown/__tests__/{DropdownSimple.test.tsx → SimpleDropdown.test.tsx} +35 -23
  64. package/src/components/Dropdown/__tests__/__snapshots__/{DropdownSimple.test.tsx.snap → SimpleDropdown.test.tsx.snap} +6 -0
  65. package/src/components/Dropdown/examples/DropdownTemplates.md +4 -16
  66. package/src/components/Dropdown/examples/{DropdownSimpleExample.tsx → SimpleDropdownExample.tsx} +7 -7
  67. package/src/components/Dropdown/index.ts +1 -1
  68. package/src/components/Select/CheckboxSelect.tsx +23 -7
  69. package/src/components/Select/{SelectTypeahead.tsx → MultiTypeaheadSelect.tsx} +91 -64
  70. package/src/components/Select/{SelectSimple.tsx → SimpleSelect.tsx} +39 -18
  71. package/src/components/Select/TypeaheadSelect.tsx +393 -0
  72. package/src/components/Select/{CheckboxSelect.test.tsx → __tests__/CheckboxSelect.test.tsx} +32 -3
  73. package/src/components/Select/{CheckboxSelectSnapshots.test.tsx → __tests__/CheckboxSelectSnapshots.test.tsx} +1 -1
  74. package/src/components/Select/__tests__/MultiTypeaheadSelect.test.tsx +412 -0
  75. package/src/components/Select/__tests__/SimpleSelect.test.tsx +242 -0
  76. package/src/components/Select/__tests__/TypeaheadSelect.test.tsx +372 -0
  77. package/src/components/Select/{__snapshots__ → __tests__/__snapshots__}/CheckboxSelectSnapshots.test.tsx.snap +7 -2
  78. package/src/components/Select/__tests__/__snapshots__/MultiTypeaheadSelect.test.tsx.snap +180 -0
  79. package/src/components/Select/__tests__/__snapshots__/SimpleSelect.test.tsx.snap +170 -0
  80. package/src/components/Select/__tests__/__snapshots__/TypeaheadSelect.test.tsx.snap +180 -0
  81. package/src/components/Select/examples/CheckboxSelectDemo.tsx +25 -8
  82. package/src/components/Select/examples/MultiTypeaheadSelectDemo.tsx +35 -0
  83. package/src/components/Select/examples/SelectTemplates.md +14 -5
  84. package/src/components/Select/examples/SimpleSelectDemo.tsx +36 -0
  85. package/src/components/Select/examples/TypeaheadSelectDemo.tsx +67 -0
  86. package/src/components/Select/index.ts +3 -2
  87. package/dist/esm/components/Dropdown/DropdownSimple.d.ts.map +0 -1
  88. package/dist/esm/components/Dropdown/DropdownSimple.js.map +0 -1
  89. package/dist/esm/components/Select/SelectSimple.d.ts.map +0 -1
  90. package/dist/esm/components/Select/SelectSimple.js +0 -31
  91. package/dist/esm/components/Select/SelectSimple.js.map +0 -1
  92. package/dist/esm/components/Select/SelectTypeahead.d.ts +0 -29
  93. package/dist/esm/components/Select/SelectTypeahead.d.ts.map +0 -1
  94. package/dist/esm/components/Select/SelectTypeahead.js.map +0 -1
  95. package/dist/js/components/Dropdown/DropdownSimple.d.ts.map +0 -1
  96. package/dist/js/components/Dropdown/DropdownSimple.js.map +0 -1
  97. package/dist/js/components/Select/SelectSimple.d.ts.map +0 -1
  98. package/dist/js/components/Select/SelectSimple.js +0 -34
  99. package/dist/js/components/Select/SelectSimple.js.map +0 -1
  100. package/dist/js/components/Select/SelectTypeahead.d.ts +0 -29
  101. package/dist/js/components/Select/SelectTypeahead.d.ts.map +0 -1
  102. package/dist/js/components/Select/SelectTypeahead.js.map +0 -1
  103. package/rollup.config.js +0 -7
  104. package/src/components/Select/examples/SelectSimpleDemo.tsx +0 -26
  105. package/src/components/Select/examples/SelectTypeaheadDemo.tsx +0 -21
@@ -9,26 +9,30 @@ import {
9
9
  TextInputGroup,
10
10
  TextInputGroupMain,
11
11
  TextInputGroupUtilities,
12
- Button
12
+ Button,
13
+ MenuToggleProps,
14
+ SelectProps,
15
+ ChipGroup,
16
+ Chip
13
17
  } from '@patternfly/react-core';
14
18
  import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
15
19
 
16
- export interface SelectTypeaheadOption extends Omit<SelectOptionProps, 'content'> {
20
+ export interface MultiTypeaheadSelectOption extends Omit<SelectOptionProps, 'content'> {
17
21
  /** Content of the select option. */
18
22
  content: string | number;
19
23
  /** Value of the select option. */
20
24
  value: string | number;
21
25
  }
22
26
 
23
- export interface SelectTypeaheadProps {
27
+ export interface MultiTypeaheadSelectProps extends Omit<SelectProps, 'toggle' | 'onSelect'> {
24
28
  /** @hide Forwarded ref */
25
29
  innerRef?: React.Ref<any>;
26
30
  /** Initial options of the select. */
27
- initialOptions: SelectTypeaheadOption[];
31
+ initialOptions: MultiTypeaheadSelectOption[];
28
32
  /** Callback triggered on selection. */
29
- onSelect?: (
33
+ onSelectionChange?: (
30
34
  _event: React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<HTMLInputElement>,
31
- selection: string | number
35
+ selections: (string | number)[]
32
36
  ) => void;
33
37
  /** Callback triggered when the select opens or closes. */
34
38
  onToggle?: (nextIsOpen: boolean) => void;
@@ -40,37 +44,49 @@ export interface SelectTypeaheadProps {
40
44
  noOptionsFoundMessage?: string | ((filter: string) => string);
41
45
  /** Flag indicating the select should be disabled. */
42
46
  isDisabled?: boolean;
47
+ /** Width of the toggle. */
48
+ toggleWidth?: string;
49
+ /** Additional props passed to the toggle. */
50
+ toggleProps?: MenuToggleProps;
43
51
  }
44
52
 
45
- export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps> = ({
53
+ export const MultiTypeaheadSelectBase: React.FunctionComponent<MultiTypeaheadSelectProps> = ({
46
54
  innerRef,
47
55
  initialOptions,
48
- onSelect,
56
+ onSelectionChange,
49
57
  onToggle,
50
58
  onInputChange,
51
59
  placeholder = 'Select an option',
52
60
  noOptionsFoundMessage = (filter) => `No results found for "${filter}"`,
53
61
  isDisabled,
62
+ toggleWidth,
63
+ toggleProps,
54
64
  ...props
55
- }: SelectTypeaheadProps) => {
65
+ }: MultiTypeaheadSelectProps) => {
56
66
  const [isOpen, setIsOpen] = React.useState(false);
57
- const [selected, setSelected] = React.useState<string>('');
58
- const [inputValue, setInputValue] = React.useState<string>('');
59
- const [filterValue, setFilterValue] = React.useState<string>('');
60
- const [selectOptions, setSelectOptions] = React.useState<SelectTypeaheadOption[]>(initialOptions);
67
+ const [selected, setSelected] = React.useState<(string | number)[]>(
68
+ (initialOptions?.filter((o) => o.selected) ?? []).map((o) => o.value)
69
+ );
70
+ const [inputValue, setInputValue] = React.useState<string>();
71
+ const [selectOptions, setSelectOptions] = React.useState<MultiTypeaheadSelectOption[]>(initialOptions);
61
72
  const [focusedItemIndex, setFocusedItemIndex] = React.useState<number | null>(null);
62
73
  const [activeItemId, setActiveItemId] = React.useState<string | null>(null);
63
74
  const textInputRef = React.useRef<HTMLInputElement>();
64
75
 
65
76
  const NO_RESULTS = 'no results';
66
77
 
78
+ const openMenu = () => {
79
+ onToggle && onToggle(true);
80
+ setIsOpen(true);
81
+ };
82
+
67
83
  React.useEffect(() => {
68
- let newSelectOptions: SelectTypeaheadOption[] = initialOptions;
84
+ let newSelectOptions: MultiTypeaheadSelectOption[] = initialOptions;
69
85
 
70
86
  // Filter menu items based on the text input value when one exists
71
- if (filterValue) {
87
+ if (inputValue) {
72
88
  newSelectOptions = initialOptions.filter((option) =>
73
- String(option.content).toLowerCase().includes(filterValue.toLowerCase())
89
+ String(option.content).toLowerCase().includes(inputValue.toLowerCase())
74
90
  );
75
91
 
76
92
  // When no options are found after filtering, display 'No results found'
@@ -79,27 +95,29 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
79
95
  {
80
96
  isAriaDisabled: true,
81
97
  content:
82
- typeof noOptionsFoundMessage === 'string' ? noOptionsFoundMessage : noOptionsFoundMessage(filterValue),
98
+ typeof noOptionsFoundMessage === 'string' ? noOptionsFoundMessage : noOptionsFoundMessage(inputValue),
83
99
  value: NO_RESULTS
84
100
  }
85
101
  ];
86
102
  }
87
103
 
88
104
  // Open the menu when the input value changes and the new value is not empty
89
- if (!isOpen) {
90
- openMenu();
91
- }
105
+ openMenu();
92
106
  }
93
107
 
94
108
  setSelectOptions(newSelectOptions);
95
- }, [filterValue]);
109
+ // eslint-disable-next-line react-hooks/exhaustive-deps
110
+ }, [inputValue, initialOptions]);
96
111
 
97
- const createItemId = (value: string | number) => `select-typeahead-${String(value).replace(' ', '-')}`;
112
+ React.useEffect(
113
+ () => setSelected((initialOptions?.filter((o) => o.selected) ?? []).map((o) => o.value)),
114
+ [initialOptions]
115
+ );
98
116
 
99
117
  const setActiveAndFocusedItem = (itemIndex: number) => {
100
118
  setFocusedItemIndex(itemIndex);
101
119
  const focusedItem = selectOptions[itemIndex];
102
- setActiveItemId(createItemId(focusedItem.value));
120
+ setActiveItemId(focusedItem.value as string);
103
121
  };
104
122
 
105
123
  const resetActiveAndFocusedItem = () => {
@@ -107,15 +125,11 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
107
125
  setActiveItemId(null);
108
126
  };
109
127
 
110
- const openMenu = () => {
111
- onToggle && onToggle(true);
112
- setIsOpen(true);
113
- };
114
-
115
128
  const closeMenu = () => {
116
129
  onToggle && onToggle(false);
117
130
  setIsOpen(false);
118
131
  resetActiveAndFocusedItem();
132
+ setInputValue('');
119
133
  };
120
134
 
121
135
  const onInputClick = () => {
@@ -128,34 +142,34 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
128
142
 
129
143
  const selectOption = (
130
144
  _event: React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<HTMLInputElement> | undefined,
131
- option: SelectTypeaheadOption
145
+ option: string | number
132
146
  ) => {
133
- onSelect && onSelect(_event, option.value);
147
+ const selections = selected.includes(option) ? selected.filter((o) => option !== o) : [...selected, option];
134
148
 
135
- setInputValue(String(option.content));
136
- setFilterValue('');
137
- setSelected(String(option.value));
149
+ onSelectionChange && onSelectionChange(_event, selections);
150
+ setSelected(selections);
151
+ };
138
152
 
139
- closeMenu();
153
+ const clearOption = (
154
+ _event: React.MouseEvent<Element, MouseEvent> | React.KeyboardEvent<HTMLInputElement> | undefined,
155
+ option: string | number
156
+ ) => {
157
+ const selections = selected.filter((o) => option !== o);
158
+ onSelectionChange && onSelectionChange(_event, selections);
159
+ setSelected(selections);
140
160
  };
141
161
 
142
162
  const _onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {
143
163
  if (value && value !== NO_RESULTS) {
144
- const optionToSelect = selectOptions.find((option) => option.value === value);
145
- selectOption(_event, optionToSelect);
164
+ selectOption(_event, value);
146
165
  }
147
166
  };
148
167
 
149
168
  const onTextInputChange = (_event: React.FormEvent<HTMLInputElement>, value: string) => {
150
169
  setInputValue(value);
151
170
  onInputChange && onInputChange(value);
152
- setFilterValue(value);
153
171
 
154
172
  resetActiveAndFocusedItem();
155
-
156
- if (value !== selected) {
157
- setSelected('');
158
- }
159
173
  };
160
174
 
161
175
  const handleMenuArrowKeys = (key: string) => {
@@ -212,10 +226,11 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
212
226
  switch (event.key) {
213
227
  case 'Enter':
214
228
  if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) {
215
- selectOption(event, focusedItem);
229
+ selectOption(event, focusedItem?.value);
216
230
  }
217
231
 
218
232
  if (!isOpen) {
233
+ onToggle && onToggle(true);
219
234
  setIsOpen(true);
220
235
  }
221
236
 
@@ -234,24 +249,29 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
234
249
  textInputRef?.current?.focus();
235
250
  };
236
251
 
237
- const onClearButtonClick = () => {
238
- setSelected('');
239
- setInputValue('');
252
+ const onClearButtonClick = (ev: React.MouseEvent) => {
253
+ setSelected([]);
240
254
  onInputChange && onInputChange('');
241
- setFilterValue('');
242
255
  resetActiveAndFocusedItem();
243
256
  textInputRef?.current?.focus();
257
+ onSelectionChange && onSelectionChange(ev, []);
244
258
  };
245
259
 
246
260
  const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
247
261
  <MenuToggle
248
262
  ref={toggleRef}
249
263
  variant="typeahead"
250
- aria-label="Typeahead menu toggle"
264
+ aria-label="Multi select Typeahead menu toggle"
251
265
  onClick={onToggleClick}
252
266
  isExpanded={isOpen}
253
267
  isDisabled={isDisabled}
254
268
  isFullWidth
269
+ style={
270
+ {
271
+ width: toggleWidth
272
+ } as React.CSSProperties
273
+ }
274
+ {...toggleProps}
255
275
  >
256
276
  <TextInputGroup isPlain>
257
277
  <TextInputGroupMain
@@ -259,7 +279,6 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
259
279
  onClick={onInputClick}
260
280
  onChange={onTextInputChange}
261
281
  onKeyDown={onInputKeyDown}
262
- id="typeahead-select-input"
263
282
  autoComplete="off"
264
283
  innerRef={textInputRef}
265
284
  placeholder={placeholder}
@@ -267,9 +286,23 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
267
286
  role="combobox"
268
287
  isExpanded={isOpen}
269
288
  aria-controls="select-typeahead-listbox"
270
- />
271
-
272
- <TextInputGroupUtilities {...(!inputValue ? { style: { display: 'none' } } : {})}>
289
+ >
290
+ <ChipGroup aria-label="Current selections">
291
+ {selected.map((selection, index) => (
292
+ <Chip
293
+ key={index}
294
+ datatest-id={`${selection}-chip`}
295
+ onClick={(ev) => {
296
+ ev.stopPropagation();
297
+ clearOption(ev, selection);
298
+ }}
299
+ >
300
+ {initialOptions.find((o) => o.value === selection)?.content}
301
+ </Chip>
302
+ ))}
303
+ </ChipGroup>
304
+ </TextInputGroupMain>
305
+ <TextInputGroupUtilities {...(selected.length === 0 ? { style: { display: 'none' } } : {})}>
273
306
  <Button variant="plain" onClick={onClearButtonClick} aria-label="Clear input value">
274
307
  <TimesIcon aria-hidden />
275
308
  </Button>
@@ -280,7 +313,6 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
280
313
 
281
314
  return (
282
315
  <Select
283
- id="typeahead-select"
284
316
  isOpen={isOpen}
285
317
  selected={selected}
286
318
  onSelect={_onSelect}
@@ -292,18 +324,12 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
292
324
  ref={innerRef}
293
325
  {...props}
294
326
  >
295
- <SelectList id="select-typeahead-listbox">
327
+ <SelectList>
296
328
  {selectOptions.map((option, index) => {
297
329
  const { content, value, ...props } = option;
298
330
 
299
331
  return (
300
- <SelectOption
301
- {...props}
302
- key={value}
303
- value={value}
304
- isFocused={focusedItemIndex === index}
305
- id={createItemId(value)}
306
- >
332
+ <SelectOption key={value} value={value} isFocused={focusedItemIndex === index} {...props}>
307
333
  {content}
308
334
  </SelectOption>
309
335
  );
@@ -312,10 +338,11 @@ export const SelectTypeaheadBase: React.FunctionComponent<SelectTypeaheadProps>
312
338
  </Select>
313
339
  );
314
340
  };
315
- SelectTypeaheadBase.displayName = 'SelectTypeaheadBase';
316
341
 
317
- export const SelectTypeahead = React.forwardRef((props: SelectTypeaheadProps, ref: React.Ref<any>) => (
318
- <SelectTypeaheadBase {...props} innerRef={ref} />
342
+ MultiTypeaheadSelectBase.displayName = 'MultiTypeaheadSelectBase';
343
+
344
+ export const MultiTypeaheadSelect = React.forwardRef((props: MultiTypeaheadSelectProps, ref: React.Ref<any>) => (
345
+ <MultiTypeaheadSelectBase {...props} innerRef={ref} />
319
346
  ));
320
347
 
321
- SelectTypeahead.displayName = 'SelectTypeahead';
348
+ MultiTypeaheadSelect.displayName = 'MultiTypeaheadSelect';
@@ -1,19 +1,25 @@
1
1
  import React from 'react';
2
- import { Select, SelectList, SelectOption, SelectOptionProps } from '@patternfly/react-core/dist/esm/components/Select';
3
- import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/esm/components/MenuToggle';
2
+ import {
3
+ Select,
4
+ SelectList,
5
+ SelectOption,
6
+ SelectOptionProps,
7
+ SelectProps
8
+ } from '@patternfly/react-core/dist/esm/components/Select';
9
+ import { MenuToggle, MenuToggleElement, MenuToggleProps } from '@patternfly/react-core/dist/esm/components/MenuToggle';
4
10
 
5
- export interface SelectSimpleOption extends Omit<SelectOptionProps, 'content'> {
11
+ export interface SimpleSelectOption extends Omit<SelectOptionProps, 'content'> {
6
12
  /** Content of the select option. */
7
13
  content: React.ReactNode;
8
14
  /** Value of the select option. */
9
15
  value: string | number;
10
16
  }
11
17
 
12
- export interface SelectSimpleProps {
18
+ export interface SimpleSelectProps extends Omit<SelectProps, 'toggle'> {
13
19
  /** @hide Forwarded ref */
14
20
  innerRef?: React.Ref<any>;
15
21
  /** Initial options of the select. */
16
- initialOptions?: SelectSimpleOption[];
22
+ initialOptions?: SimpleSelectOption[];
17
23
  /** Callback triggered on selection. */
18
24
  onSelect?: (_event: React.MouseEvent<Element, MouseEvent>, selection: string | number) => void;
19
25
  /** Callback triggered when the select opens or closes. */
@@ -22,11 +28,15 @@ export interface SelectSimpleProps {
22
28
  isDisabled?: boolean;
23
29
  /** Content of the toggle. Defaults to the selected option. */
24
30
  toggleContent?: React.ReactNode;
25
- /** Width of the toggle */
31
+ /** Placeholder text for the select input. */
32
+ placeholder?: string;
33
+ /** Width of the toggle. */
26
34
  toggleWidth?: string;
35
+ /** Additional props passed to the toggle. */
36
+ toggleProps?: MenuToggleProps;
27
37
  }
28
38
 
29
- const SelectSimpleBase: React.FunctionComponent<SelectSimpleProps> = ({
39
+ const SimpleSelectBase: React.FunctionComponent<SimpleSelectProps> = ({
30
40
  innerRef,
31
41
  initialOptions,
32
42
  isDisabled,
@@ -34,16 +44,23 @@ const SelectSimpleBase: React.FunctionComponent<SelectSimpleProps> = ({
34
44
  onToggle,
35
45
  toggleContent,
36
46
  toggleWidth = '200px',
47
+ toggleProps,
48
+ placeholder = 'Select a value',
37
49
  ...props
38
- }: SelectSimpleProps) => {
50
+ }: SimpleSelectProps) => {
39
51
  const [isOpen, setIsOpen] = React.useState(false);
40
- const [selected, setSelected] = React.useState<string>('Select a value');
52
+ const [selected, setSelected] = React.useState<SimpleSelectOption | undefined>();
53
+
54
+ React.useEffect(() => {
55
+ const selectedOption = initialOptions?.find((option) => option.selected);
56
+ setSelected(selectedOption);
57
+ }, [initialOptions]);
41
58
 
42
59
  const simpleSelectOptions = initialOptions?.map((option) => {
43
60
  const { content, value, ...props } = option;
44
- const isSelected = selected.includes(`${value}`);
61
+ const isSelected = selected?.value === value;
45
62
  return (
46
- <SelectOption {...props} value={value} key={value} isSelected={isSelected}>
63
+ <SelectOption value={value} key={value} isSelected={isSelected} {...props}>
47
64
  {content}
48
65
  </SelectOption>
49
66
  );
@@ -56,7 +73,8 @@ const SelectSimpleBase: React.FunctionComponent<SelectSimpleProps> = ({
56
73
 
57
74
  const _onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {
58
75
  onSelect && onSelect(_event, value);
59
- setSelected(value as string);
76
+ setSelected(initialOptions.find((o) => o.value === value));
77
+ onToggle && onToggle(true);
60
78
  setIsOpen(false);
61
79
  };
62
80
 
@@ -71,18 +89,21 @@ const SelectSimpleBase: React.FunctionComponent<SelectSimpleProps> = ({
71
89
  width: toggleWidth
72
90
  } as React.CSSProperties
73
91
  }
92
+ {...toggleProps}
74
93
  >
75
- {toggleContent ? toggleContent : selected}
94
+ {toggleContent ? toggleContent : selected?.content || placeholder}
76
95
  </MenuToggle>
77
96
  );
78
97
 
79
98
  return (
80
99
  <Select
81
- id="single-select"
82
100
  isOpen={isOpen}
83
101
  selected={selected}
84
102
  onSelect={_onSelect}
85
- onOpenChange={(isOpen) => setIsOpen(isOpen)}
103
+ onOpenChange={(isOpen) => {
104
+ onToggle && onToggle(isOpen);
105
+ setIsOpen(isOpen);
106
+ }}
86
107
  toggle={toggle}
87
108
  shouldFocusToggleOnSelect
88
109
  ref={innerRef}
@@ -93,8 +114,8 @@ const SelectSimpleBase: React.FunctionComponent<SelectSimpleProps> = ({
93
114
  );
94
115
  };
95
116
 
96
- export const SelectSimple = React.forwardRef((props: SelectSimpleProps, ref: React.Ref<any>) => (
97
- <SelectSimpleBase {...props} innerRef={ref} />
117
+ export const SimpleSelect = React.forwardRef((props: SimpleSelectProps, ref: React.Ref<any>) => (
118
+ <SimpleSelectBase {...props} innerRef={ref} />
98
119
  ));
99
120
 
100
- SelectSimple.displayName = 'SelectSimple';
121
+ SimpleSelect.displayName = 'SimpleSelect';