@patternfly/react-templates 6.0.0-alpha.45 → 6.0.0-alpha.46

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 (58) hide show
  1. package/CHANGELOG.md +4 -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 +4 -0
  6. package/dist/esm/components/Select/CheckboxSelect.d.ts.map +1 -1
  7. package/dist/esm/components/Select/CheckboxSelect.js +5 -0
  8. package/dist/esm/components/Select/CheckboxSelect.js.map +1 -1
  9. package/dist/esm/components/Select/MultiTypeaheadSelect.d.ts +33 -0
  10. package/dist/esm/components/Select/MultiTypeaheadSelect.d.ts.map +1 -0
  11. package/dist/esm/components/Select/MultiTypeaheadSelect.js +186 -0
  12. package/dist/esm/components/Select/MultiTypeaheadSelect.js.map +1 -0
  13. package/dist/esm/components/Select/SimpleSelect.d.ts +2 -0
  14. package/dist/esm/components/Select/SimpleSelect.d.ts.map +1 -1
  15. package/dist/esm/components/Select/SimpleSelect.js +10 -6
  16. package/dist/esm/components/Select/SimpleSelect.js.map +1 -1
  17. package/dist/esm/components/Select/TypeaheadSelect.d.ts +12 -2
  18. package/dist/esm/components/Select/TypeaheadSelect.d.ts.map +1 -1
  19. package/dist/esm/components/Select/TypeaheadSelect.js +61 -22
  20. package/dist/esm/components/Select/TypeaheadSelect.js.map +1 -1
  21. package/dist/esm/components/Select/index.d.ts +1 -0
  22. package/dist/esm/components/Select/index.d.ts.map +1 -1
  23. package/dist/esm/components/Select/index.js +1 -0
  24. package/dist/esm/components/Select/index.js.map +1 -1
  25. package/dist/js/components/Select/CheckboxSelect.d.ts.map +1 -1
  26. package/dist/js/components/Select/CheckboxSelect.js +5 -0
  27. package/dist/js/components/Select/CheckboxSelect.js.map +1 -1
  28. package/dist/js/components/Select/MultiTypeaheadSelect.d.ts +33 -0
  29. package/dist/js/components/Select/MultiTypeaheadSelect.d.ts.map +1 -0
  30. package/dist/js/components/Select/MultiTypeaheadSelect.js +190 -0
  31. package/dist/js/components/Select/MultiTypeaheadSelect.js.map +1 -0
  32. package/dist/js/components/Select/SimpleSelect.d.ts +2 -0
  33. package/dist/js/components/Select/SimpleSelect.d.ts.map +1 -1
  34. package/dist/js/components/Select/SimpleSelect.js +10 -6
  35. package/dist/js/components/Select/SimpleSelect.js.map +1 -1
  36. package/dist/js/components/Select/TypeaheadSelect.d.ts +12 -2
  37. package/dist/js/components/Select/TypeaheadSelect.d.ts.map +1 -1
  38. package/dist/js/components/Select/TypeaheadSelect.js +61 -22
  39. package/dist/js/components/Select/TypeaheadSelect.js.map +1 -1
  40. package/dist/js/components/Select/index.d.ts +1 -0
  41. package/dist/js/components/Select/index.d.ts.map +1 -1
  42. package/dist/js/components/Select/index.js +1 -0
  43. package/dist/js/components/Select/index.js.map +1 -1
  44. package/dist/umd/assets/{output--NzZZ7D3.css → output-DPlyZse9.css} +3498 -3498
  45. package/dist/umd/react-templates.min.js +1 -1
  46. package/package.json +6 -6
  47. package/src/components/Select/CheckboxSelect.tsx +5 -0
  48. package/src/components/Select/MultiTypeaheadSelect.tsx +348 -0
  49. package/src/components/Select/SimpleSelect.tsx +13 -5
  50. package/src/components/Select/TypeaheadSelect.tsx +84 -25
  51. package/src/components/Select/__tests__/MultiTypeaheadSelect.test.tsx +414 -0
  52. package/src/components/Select/__tests__/__snapshots__/MultiTypeaheadSelect.test.tsx.snap +97 -0
  53. package/src/components/Select/examples/CheckboxSelectDemo.tsx +25 -8
  54. package/src/components/Select/examples/MultiTypeaheadSelectDemo.tsx +35 -0
  55. package/src/components/Select/examples/SelectTemplates.md +7 -1
  56. package/src/components/Select/examples/SimpleSelectDemo.tsx +16 -6
  57. package/src/components/Select/examples/TypeaheadSelectDemo.tsx +57 -13
  58. package/src/components/Select/index.ts +1 -0
@@ -0,0 +1,414 @@
1
+ import * as React from 'react';
2
+ import { render, screen, waitForElementToBeRemoved } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { MultiTypeaheadSelect } from '../MultiTypeaheadSelect';
5
+ import styles from '@patternfly/react-styles/css/components/Menu/menu';
6
+
7
+ const getToggle = () => screen.getByRole('button', { name: 'Multi select Typeahead menu toggle' });
8
+
9
+ describe('MultiTypeaheadSelect', () => {
10
+ it('renders MultiTypeaheadSelect with options', async () => {
11
+ const initialOptions = [
12
+ { content: 'Option 1', value: 'option1' },
13
+ { content: 'Option 2', value: 'option2' },
14
+ { content: 'Option 3', value: 'option3' }
15
+ ];
16
+
17
+ const user = userEvent.setup();
18
+
19
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
20
+
21
+ const toggle = getToggle();
22
+
23
+ await user.click(toggle);
24
+
25
+ const option1 = screen.getByText('Option 1');
26
+ const option2 = screen.getByText('Option 2');
27
+ const option3 = screen.getByText('Option 3');
28
+
29
+ expect(option1).toBeInTheDocument();
30
+ expect(option2).toBeInTheDocument();
31
+ expect(option3).toBeInTheDocument();
32
+ });
33
+
34
+ it('selects options when clicked', async () => {
35
+ const initialOptions = [
36
+ { content: 'Option 1', value: 'option1' },
37
+ { content: 'Option 2', value: 'option2' },
38
+ { content: 'Option 3', value: 'option3' }
39
+ ];
40
+
41
+ const user = userEvent.setup();
42
+
43
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
44
+
45
+ const toggle = getToggle();
46
+
47
+ await user.click(toggle);
48
+
49
+ const option1 = screen.getByRole('option', { name: 'Option 1' });
50
+
51
+ expect(option1).not.toHaveClass(styles.modifiers.selected);
52
+
53
+ await user.click(option1);
54
+
55
+ expect(option1).toHaveClass(styles.modifiers.selected);
56
+ });
57
+
58
+ it('calls the onSelectionChange callback with the selected value when an option is selected', async () => {
59
+ const initialOptions = [
60
+ { content: 'Option 1', value: 'option1' },
61
+ { content: 'Option 2', value: 'option2' },
62
+ { content: 'Option 3', value: 'option3' }
63
+ ];
64
+
65
+ const user = userEvent.setup();
66
+ const onSelectionChangeMock = jest.fn();
67
+
68
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} onSelect={onSelectionChangeMock} />);
69
+
70
+ const toggle = getToggle();
71
+
72
+ await user.click(toggle);
73
+
74
+ expect(onSelectionChangeMock).not.toHaveBeenCalled();
75
+
76
+ const option1 = screen.getByRole('option', { name: 'Option 1' });
77
+
78
+ await user.click(option1);
79
+
80
+ expect(onSelectionChangeMock).toHaveBeenCalledTimes(1);
81
+ expect(onSelectionChangeMock).toHaveBeenCalledWith(expect.anything(), 'option1');
82
+ });
83
+
84
+ it('deselects options when clear button is clicked', async () => {
85
+ const initialOptions = [
86
+ { content: 'Option 1', value: 'option1' },
87
+ { content: 'Option 2', value: 'option2' },
88
+ { content: 'Option 3', value: 'option3' }
89
+ ];
90
+
91
+ const user = userEvent.setup();
92
+
93
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
94
+
95
+ const toggle = getToggle();
96
+
97
+ await user.click(toggle);
98
+
99
+ const option1 = screen.getByRole('option', { name: 'Option 1' });
100
+ await user.click(option1);
101
+ expect(option1).toHaveClass(styles.modifiers.selected);
102
+
103
+ const input = screen.getByRole('combobox');
104
+
105
+ const clearButton = screen.getByRole('button', { name: 'Clear input value' });
106
+ await user.click(clearButton);
107
+
108
+ expect(input).toHaveValue('');
109
+
110
+ await user.click(toggle);
111
+ expect(screen.getByRole('option', { name: 'Option 1' })).not.toHaveClass(styles.modifiers.selected);
112
+ });
113
+
114
+ it('toggles the select menu when the toggle button is clicked', async () => {
115
+ const initialOptions = [
116
+ { content: 'Option 1', value: 'option1' },
117
+ { content: 'Option 2', value: 'option2' },
118
+ { content: 'Option 3', value: 'option3' }
119
+ ];
120
+
121
+ const user = userEvent.setup();
122
+
123
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
124
+
125
+ const toggle = getToggle();
126
+
127
+ await user.click(toggle);
128
+
129
+ const menu = screen.getByRole('listbox');
130
+ expect(menu).toBeInTheDocument();
131
+
132
+ await user.click(toggle);
133
+
134
+ await waitForElementToBeRemoved(menu);
135
+
136
+ expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
137
+ });
138
+
139
+ it('calls the onToggle callback when the toggle is clicked', async () => {
140
+ const initialOptions = [
141
+ { content: 'Option 1', value: 'option1' },
142
+ { content: 'Option 2', value: 'option2' },
143
+ { content: 'Option 3', value: 'option3' }
144
+ ];
145
+
146
+ const user = userEvent.setup();
147
+ const onToggleMock = jest.fn();
148
+
149
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} onToggle={onToggleMock} />);
150
+
151
+ const toggle = getToggle();
152
+
153
+ expect(onToggleMock).not.toHaveBeenCalled();
154
+
155
+ await user.click(toggle);
156
+
157
+ expect(onToggleMock).toHaveBeenCalledTimes(1);
158
+ expect(onToggleMock).toHaveBeenCalledWith(true);
159
+
160
+ await user.click(toggle);
161
+
162
+ expect(onToggleMock).toHaveBeenCalledTimes(2);
163
+ expect(onToggleMock).toHaveBeenCalledWith(false);
164
+ });
165
+
166
+ it('Passes toggleWidth', () => {
167
+ const initialOptions = [
168
+ { content: 'Option 1', value: 'option1' },
169
+ { content: 'Option 2', value: 'option2' },
170
+ { content: 'Option 3', value: 'option3' }
171
+ ];
172
+
173
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} toggleWidth="500px" />);
174
+
175
+ const toggle = getToggle();
176
+ expect(toggle.parentElement).toHaveAttribute('style', 'width: 500px;');
177
+ });
178
+
179
+ it('Passes additional toggleProps', () => {
180
+ const initialOptions = [
181
+ { content: 'Option 1', value: 'option1' },
182
+ { content: 'Option 2', value: 'option2' },
183
+ { content: 'Option 3', value: 'option3' }
184
+ ];
185
+
186
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} toggleProps={{ id: 'toggle' }} />);
187
+
188
+ const toggle = getToggle();
189
+ expect(toggle.parentElement).toHaveAttribute('id', 'toggle');
190
+ });
191
+
192
+ it('passes custom placeholder text', async () => {
193
+ const initialOptions = [
194
+ { content: 'Option 1', value: 'option1' },
195
+ { content: 'Option 2', value: 'option2' },
196
+ { content: 'Option 3', value: 'option3' }
197
+ ];
198
+
199
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} placeholder="custom" />);
200
+
201
+ const input = screen.getByRole('combobox');
202
+
203
+ expect(input).toHaveAttribute('placeholder', 'custom');
204
+ });
205
+
206
+ it('displays noOptionsFoundMessage when filter returns no results', async () => {
207
+ const initialOptions = [
208
+ { content: 'Option 1', value: 'option1' },
209
+ { content: 'Option 2', value: 'option2' },
210
+ { content: 'Option 3', value: 'option3' }
211
+ ];
212
+ const user = userEvent.setup();
213
+
214
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
215
+
216
+ const toggle = getToggle();
217
+ const input = screen.getByRole('combobox');
218
+
219
+ expect(input).toHaveAttribute('placeholder', 'Select an option');
220
+
221
+ await user.click(toggle);
222
+
223
+ const option1 = screen.getByRole('option', { name: 'Option 1' });
224
+ const option2 = screen.getByRole('option', { name: 'Option 2' });
225
+ const option3 = screen.getByRole('option', { name: 'Option 3' });
226
+
227
+ expect(option1).toBeInTheDocument();
228
+ expect(option2).toBeInTheDocument();
229
+ expect(option3).toBeInTheDocument();
230
+
231
+ await user.type(input, '9');
232
+ expect(input).toHaveValue('9');
233
+
234
+ expect(option1).not.toBeInTheDocument();
235
+ expect(option2).not.toBeInTheDocument();
236
+ expect(option3).not.toBeInTheDocument();
237
+ expect(screen.getByRole('option', { name: 'No results found for "9"' })).toBeInTheDocument();
238
+ });
239
+
240
+ it('displays custom noOptionsFoundMessage', async () => {
241
+ const initialOptions = [
242
+ { content: 'Option 1', value: 'option1' },
243
+ { content: 'Option 2', value: 'option2' },
244
+ { content: 'Option 3', value: 'option3' }
245
+ ];
246
+ const user = userEvent.setup();
247
+
248
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} noOptionsFoundMessage="custom" />);
249
+
250
+ const toggle = getToggle();
251
+ const input = screen.getByRole('combobox');
252
+
253
+ expect(input).toHaveAttribute('placeholder', 'Select an option');
254
+
255
+ await user.click(toggle);
256
+
257
+ const option1 = screen.getByRole('option', { name: 'Option 1' });
258
+ const option2 = screen.getByRole('option', { name: 'Option 2' });
259
+ const option3 = screen.getByRole('option', { name: 'Option 3' });
260
+
261
+ expect(option1).toBeInTheDocument();
262
+ expect(option2).toBeInTheDocument();
263
+ expect(option3).toBeInTheDocument();
264
+
265
+ await user.type(input, '9');
266
+ expect(input).toHaveValue('9');
267
+
268
+ expect(option1).not.toBeInTheDocument();
269
+ expect(option2).not.toBeInTheDocument();
270
+ expect(option3).not.toBeInTheDocument();
271
+ expect(screen.getByRole('option', { name: 'custom' })).toBeInTheDocument();
272
+ });
273
+
274
+ it('disables the select when isDisabled prop is true', async () => {
275
+ const initialOptions = [
276
+ { content: 'Option 1', value: 'option1' },
277
+ { content: 'Option 2', value: 'option2' },
278
+ { content: 'Option 3', value: 'option3' }
279
+ ];
280
+
281
+ const user = userEvent.setup();
282
+
283
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} isDisabled={true} />);
284
+
285
+ const toggle = getToggle();
286
+
287
+ expect(toggle.parentElement).toHaveClass(styles.modifiers.disabled);
288
+
289
+ await user.click(toggle);
290
+
291
+ expect(screen.queryByRole('menu')).not.toBeInTheDocument();
292
+ });
293
+
294
+ it('passes other SelectOption props to the SelectOption component', async () => {
295
+ const initialOptions = [{ content: 'Option 1', value: 'option1', isDisabled: true }];
296
+
297
+ const user = userEvent.setup();
298
+
299
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
300
+
301
+ const toggle = getToggle();
302
+
303
+ await user.click(toggle);
304
+
305
+ const option1 = screen.getByRole('option', { name: 'Option 1' });
306
+ expect(option1).toBeDisabled();
307
+ });
308
+
309
+ it('displays the option in chip when option is selected', async () => {
310
+ const initialOptions = [
311
+ { content: 'Option 1', value: 'option1' },
312
+ { content: 'Option 2', value: 'option2' },
313
+ { content: 'Option 3', value: 'option3' }
314
+ ];
315
+
316
+ const user = userEvent.setup();
317
+
318
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
319
+
320
+ const toggle = getToggle();
321
+ const input = screen.getByRole('combobox');
322
+
323
+ expect(input).toHaveAttribute('placeholder', 'Select an option');
324
+
325
+ await user.click(toggle);
326
+
327
+ const option1 = screen.getByRole('option', { name: 'Option 1' });
328
+
329
+ await user.click(option1);
330
+
331
+ await user.click(toggle);
332
+
333
+ // TODO: How to find the chips?
334
+
335
+ const clearButton = screen.getByRole('button', { name: 'Clear input value' });
336
+ await user.click(clearButton);
337
+
338
+ // TODO: How to find the chips?
339
+ });
340
+
341
+ it('typing in input filters options', async () => {
342
+ const initialOptions = [
343
+ { content: 'Option 1', value: 'option1' },
344
+ { content: 'Option 2', value: 'option2' },
345
+ { content: 'Option 3', value: 'option3' }
346
+ ];
347
+
348
+ const user = userEvent.setup();
349
+
350
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
351
+
352
+ const toggle = getToggle();
353
+ const input = screen.getByRole('combobox');
354
+
355
+ expect(input).toHaveAttribute('placeholder', 'Select an option');
356
+
357
+ await user.click(toggle);
358
+
359
+ const option1 = screen.getByRole('option', { name: 'Option 1' });
360
+ const option2 = screen.getByRole('option', { name: 'Option 2' });
361
+ const option3 = screen.getByRole('option', { name: 'Option 3' });
362
+
363
+ expect(option1).toBeInTheDocument();
364
+ expect(option2).toBeInTheDocument();
365
+ expect(option3).toBeInTheDocument();
366
+
367
+ await user.type(input, '1');
368
+ expect(input).toHaveValue('1');
369
+
370
+ expect(option1).toBeInTheDocument();
371
+ expect(option2).not.toBeInTheDocument();
372
+ expect(option3).not.toBeInTheDocument();
373
+ });
374
+
375
+ it('typing in input triggers onInputChange callback', async () => {
376
+ const initialOptions = [
377
+ { content: 'Option 1', value: 'option1' },
378
+ { content: 'Option 2', value: 'option2' },
379
+ { content: 'Option 3', value: 'option3' }
380
+ ];
381
+
382
+ const user = userEvent.setup();
383
+ const onInputChangeMock = jest.fn();
384
+
385
+ render(<MultiTypeaheadSelect initialOptions={initialOptions} onInputChange={onInputChangeMock} />);
386
+
387
+ const input = screen.getByRole('combobox');
388
+
389
+ expect(input).toHaveAttribute('placeholder', 'Select an option');
390
+
391
+ await user.type(input, '1');
392
+
393
+ expect(input).toHaveValue('1');
394
+ expect(onInputChangeMock).toHaveBeenCalledTimes(1);
395
+ expect(onInputChangeMock).toHaveBeenCalledWith('1');
396
+ });
397
+
398
+ it('Matches snapshot', async () => {
399
+ const initialOptions = [
400
+ { content: 'Option 1', value: 'option1' },
401
+ { content: 'Option 2', value: 'option2' },
402
+ { content: 'Option 3', value: 'option3' }
403
+ ];
404
+
405
+ const user = userEvent.setup();
406
+
407
+ const { asFragment } = render(<MultiTypeaheadSelect initialOptions={initialOptions} />);
408
+
409
+ const toggle = getToggle();
410
+ await user.click(toggle);
411
+
412
+ expect(asFragment()).toMatchSnapshot();
413
+ });
414
+ });
@@ -0,0 +1,97 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`MultiTypeaheadSelect Matches snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <div
6
+ class="pf-v6-c-menu-toggle pf-m-expanded pf-m-full-width pf-m-typeahead"
7
+ >
8
+ <div
9
+ class="pf-v6-c-text-input-group pf-m-plain"
10
+ >
11
+ <div
12
+ autocomplete="off"
13
+ class="pf-v6-c-text-input-group__main"
14
+ >
15
+ <span
16
+ class="pf-v6-c-text-input-group__text"
17
+ >
18
+ <input
19
+ aria-controls="select-typeahead-listbox"
20
+ aria-expanded="true"
21
+ aria-label="Type to filter"
22
+ class="pf-v6-c-text-input-group__text-input"
23
+ placeholder="Select an option"
24
+ role="combobox"
25
+ type="text"
26
+ value=""
27
+ />
28
+ </span>
29
+ </div>
30
+ <div
31
+ class="pf-v6-c-text-input-group__utilities"
32
+ style="display: none;"
33
+ >
34
+ <button
35
+ aria-disabled="false"
36
+ aria-label="Clear input value"
37
+ class="pf-v6-c-button pf-m-plain"
38
+ data-ouia-component-id="OUIA-Generated-Button-plain-17"
39
+ data-ouia-component-type="PF6/Button"
40
+ data-ouia-safe="true"
41
+ type="button"
42
+ >
43
+ <span
44
+ class="pf-v6-c-button__text"
45
+ >
46
+ <svg
47
+ aria-hidden="true"
48
+ class="pf-v6-svg"
49
+ fill="currentColor"
50
+ height="1em"
51
+ role="img"
52
+ viewBox="0 0 352 512"
53
+ width="1em"
54
+ >
55
+ <path
56
+ d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"
57
+ />
58
+ </svg>
59
+ </span>
60
+ </button>
61
+ </div>
62
+ </div>
63
+ <button
64
+ aria-expanded="true"
65
+ aria-label="Multi select Typeahead menu toggle"
66
+ class="pf-v6-c-menu-toggle__button"
67
+ data-ouia-component-id="OUIA-Generated-MenuToggle-typeahead-17"
68
+ data-ouia-component-type="PF6/MenuToggle"
69
+ data-ouia-safe="true"
70
+ tabindex="-1"
71
+ type="button"
72
+ >
73
+ <span
74
+ class="pf-v6-c-menu-toggle__controls"
75
+ >
76
+ <span
77
+ class="pf-v6-c-menu-toggle__toggle-icon"
78
+ >
79
+ <svg
80
+ aria-hidden="true"
81
+ class="pf-v6-svg"
82
+ fill="currentColor"
83
+ height="1em"
84
+ role="img"
85
+ viewBox="0 0 320 512"
86
+ width="1em"
87
+ >
88
+ <path
89
+ d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
90
+ />
91
+ </svg>
92
+ </span>
93
+ </span>
94
+ </button>
95
+ </div>
96
+ </DocumentFragment>
97
+ `;
@@ -1,13 +1,30 @@
1
1
  import React from 'react';
2
2
  import { CheckboxSelect, CheckboxSelectOption } from '@patternfly/react-templates';
3
3
 
4
+ const Options: { content: string; value: string; description?: string; isDisabled?: boolean }[] = [
5
+ { content: 'Option 1', value: 'option-1' },
6
+ { content: 'Option 2', value: 'option-2', description: 'Option with description' },
7
+ { content: 'Option 3', value: 'option-3', isDisabled: true },
8
+ { content: 'Option 4', value: 'option-4' }
9
+ ];
10
+
4
11
  export const SelectBasic: React.FunctionComponent = () => {
5
- const initialOptions: CheckboxSelectOption[] = [
6
- { content: 'Option 1', value: 'option-1' },
7
- { content: 'Option 2', value: 'option-2', description: 'Option with description' },
8
- { content: 'Option 3', value: 'option-3', isDisabled: true },
9
- { content: 'Option 4', value: 'option-4' }
10
- ];
11
-
12
- return <CheckboxSelect initialOptions={initialOptions} />;
12
+ const [selected, setSelected] = React.useState<string[]>(['option-2']);
13
+
14
+ const initialOptions = React.useMemo<CheckboxSelectOption[]>(
15
+ () => Options.map((o) => ({ ...o, selected: selected.includes(o.value) })),
16
+ [selected]
17
+ );
18
+
19
+ return (
20
+ <CheckboxSelect
21
+ initialOptions={initialOptions}
22
+ onSelect={(_ev, value) => {
23
+ const val = String(value);
24
+ setSelected((prevSelected) =>
25
+ prevSelected.includes(val) ? prevSelected.filter((item) => item !== val) : [...prevSelected, String(val)]
26
+ );
27
+ }}
28
+ />
29
+ );
13
30
  };
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { MultiTypeaheadSelect, MultiTypeaheadSelectOption } from '@patternfly/react-templates';
3
+
4
+ const Options = [
5
+ { content: 'Alabama', value: 'option1' },
6
+ { content: 'Arizona', value: 'option2' },
7
+ { content: 'California', value: 'option3' },
8
+ { content: 'Florida', value: 'option4' },
9
+ { content: 'Massachusetts', value: 'option5' },
10
+ { content: 'Maine', value: 'option6' },
11
+ { content: 'New Jersey', value: 'option7' },
12
+ { content: 'New Mexico', value: 'option8' },
13
+ { content: 'New York', value: 'option9' },
14
+ { content: 'North Carolina', value: 'option10' }
15
+ ];
16
+
17
+ type SelectionsType = (string | number)[];
18
+
19
+ export const MultiSelectTypeaheadDemo: React.FunctionComponent = () => {
20
+ const [selected, setSelected] = React.useState<SelectionsType>(['option5']);
21
+
22
+ const initialOptions = React.useMemo<MultiTypeaheadSelectOption[]>(
23
+ () => Options.map((o) => ({ ...o, selected: selected.includes(o.value) })),
24
+ [selected]
25
+ );
26
+
27
+ return (
28
+ <MultiTypeaheadSelect
29
+ initialOptions={initialOptions}
30
+ placeholder="Select a state"
31
+ noOptionsFoundMessage={(filter) => `No state was found for "${filter}"`}
32
+ onSelectionChange={(_ev, selections) => setSelected(selections)}
33
+ />
34
+ );
35
+ };
@@ -12,7 +12,7 @@ Note: Templates live in their own package at [@patternfly/react-templates](https
12
12
  For custom use cases, please see the select component suite from [@patternfly/react-core](https://www.npmjs.com/package/@patternfly/react-core).
13
13
 
14
14
  import { Checkbox } from '@patternfly/react-core';
15
- import { SimpleSelect, CheckboxSelect, TypeaheadSelect } from '@patternfly/react-templates';
15
+ import { SimpleSelect, CheckboxSelect, TypeaheadSelect, MultiTypeaheadSelect } from '@patternfly/react-templates';
16
16
 
17
17
  ## Select template examples
18
18
 
@@ -33,3 +33,9 @@ import { SimpleSelect, CheckboxSelect, TypeaheadSelect } from '@patternfly/react
33
33
  ```ts file="TypeaheadSelectDemo.tsx"
34
34
 
35
35
  ```
36
+
37
+ ### Multi-Typeahead
38
+
39
+ ```ts file="MultiTypeaheadSelectDemo.tsx"
40
+
41
+ ```
@@ -2,14 +2,20 @@ import React from 'react';
2
2
  import { Checkbox } from '@patternfly/react-core';
3
3
  import { SimpleSelect, SimpleSelectOption } from '@patternfly/react-templates';
4
4
 
5
+ const Options: SimpleSelectOption[] = [
6
+ { content: 'Option 1', value: 'Option1' },
7
+ { content: 'Option 2', value: 'Option2', description: 'Option with description' },
8
+ { content: 'Option 3', value: 'Option3' }
9
+ ];
10
+
5
11
  export const SelectSimpleDemo: React.FunctionComponent = () => {
6
12
  const [isDisabled, setIsDisabled] = React.useState<boolean>(false);
13
+ const [selected, setSelected] = React.useState<string | undefined>('Option1');
7
14
 
8
- const initialOptions: SimpleSelectOption[] = [
9
- { content: 'Option 1', value: 'Option 1' },
10
- { content: 'Option 2', value: 'Option 2', description: 'Option with description' },
11
- { content: 'Option 3', value: 'Option 3' }
12
- ];
15
+ const initialOptions = React.useMemo<SimpleSelectOption[]>(
16
+ () => Options.map((o) => ({ ...o, selected: o.value === selected })),
17
+ [selected]
18
+ );
13
19
 
14
20
  return (
15
21
  <React.Fragment>
@@ -20,7 +26,11 @@ export const SelectSimpleDemo: React.FunctionComponent = () => {
20
26
  onChange={(_event, checked) => setIsDisabled(checked)}
21
27
  style={{ marginBottom: 20 }}
22
28
  />
23
- <SimpleSelect initialOptions={initialOptions} isDisabled={isDisabled} />
29
+ <SimpleSelect
30
+ initialOptions={initialOptions}
31
+ isDisabled={isDisabled}
32
+ onSelect={(_ev, selection) => setSelected(String(selection))}
33
+ />
24
34
  </React.Fragment>
25
35
  );
26
36
  };