@patternfly/react-templates 1.1.0-prerelease.3 → 1.1.0-prerelease.31

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 (108) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/README.md +2 -17
  3. package/components/package.json +1 -1
  4. package/dist/dynamic/components/Dropdown/package.json +1 -0
  5. package/dist/dynamic/components/Select/package.json +1 -1
  6. package/dist/dynamic-modules.json +14 -3
  7. package/dist/esm/components/Dropdown/SimpleDropdown.d.ts +48 -0
  8. package/dist/esm/components/Dropdown/SimpleDropdown.d.ts.map +1 -0
  9. package/dist/esm/components/Dropdown/SimpleDropdown.js +33 -0
  10. package/dist/esm/components/Dropdown/SimpleDropdown.js.map +1 -0
  11. package/dist/esm/components/Dropdown/index.d.ts +2 -0
  12. package/dist/esm/components/Dropdown/index.d.ts.map +1 -0
  13. package/dist/esm/components/Dropdown/index.js +2 -0
  14. package/dist/esm/components/Dropdown/index.js.map +1 -0
  15. package/dist/esm/components/Select/CheckboxSelect.d.ts +7 -3
  16. package/dist/esm/components/Select/CheckboxSelect.d.ts.map +1 -1
  17. package/dist/esm/components/Select/CheckboxSelect.js +14 -6
  18. package/dist/esm/components/Select/CheckboxSelect.js.map +1 -1
  19. package/dist/esm/components/Select/MultiTypeaheadSelect.d.ts +33 -0
  20. package/dist/esm/components/Select/MultiTypeaheadSelect.d.ts.map +1 -0
  21. package/dist/esm/components/Select/MultiTypeaheadSelect.js +186 -0
  22. package/dist/esm/components/Select/MultiTypeaheadSelect.js.map +1 -0
  23. package/dist/esm/components/Select/{SelectSimple.d.ts → SimpleSelect.d.ts} +12 -7
  24. package/dist/esm/components/Select/SimpleSelect.d.ts.map +1 -0
  25. package/dist/esm/components/Select/SimpleSelect.js +39 -0
  26. package/dist/esm/components/Select/SimpleSelect.js.map +1 -0
  27. package/dist/esm/components/Select/TypeaheadSelect.d.ts +35 -0
  28. package/dist/esm/components/Select/TypeaheadSelect.d.ts.map +1 -0
  29. package/dist/esm/components/Select/TypeaheadSelect.js +194 -0
  30. package/dist/esm/components/Select/TypeaheadSelect.js.map +1 -0
  31. package/dist/esm/components/Select/index.d.ts +3 -1
  32. package/dist/esm/components/Select/index.d.ts.map +1 -1
  33. package/dist/esm/components/Select/index.js +3 -1
  34. package/dist/esm/components/Select/index.js.map +1 -1
  35. package/dist/esm/components/index.d.ts +1 -0
  36. package/dist/esm/components/index.d.ts.map +1 -1
  37. package/dist/esm/components/index.js +1 -0
  38. package/dist/esm/components/index.js.map +1 -1
  39. package/dist/js/components/Dropdown/SimpleDropdown.d.ts +48 -0
  40. package/dist/js/components/Dropdown/SimpleDropdown.d.ts.map +1 -0
  41. package/dist/js/components/Dropdown/SimpleDropdown.js +36 -0
  42. package/dist/js/components/Dropdown/SimpleDropdown.js.map +1 -0
  43. package/dist/js/components/Dropdown/index.d.ts +2 -0
  44. package/dist/js/components/Dropdown/index.d.ts.map +1 -0
  45. package/dist/js/components/Dropdown/index.js +5 -0
  46. package/dist/js/components/Dropdown/index.js.map +1 -0
  47. package/dist/js/components/Select/CheckboxSelect.d.ts +7 -3
  48. package/dist/js/components/Select/CheckboxSelect.d.ts.map +1 -1
  49. package/dist/js/components/Select/CheckboxSelect.js +14 -6
  50. package/dist/js/components/Select/CheckboxSelect.js.map +1 -1
  51. package/dist/js/components/Select/MultiTypeaheadSelect.d.ts +33 -0
  52. package/dist/js/components/Select/MultiTypeaheadSelect.d.ts.map +1 -0
  53. package/dist/js/components/Select/MultiTypeaheadSelect.js +190 -0
  54. package/dist/js/components/Select/MultiTypeaheadSelect.js.map +1 -0
  55. package/dist/js/components/Select/{SelectSimple.d.ts → SimpleSelect.d.ts} +12 -7
  56. package/dist/js/components/Select/SimpleSelect.d.ts.map +1 -0
  57. package/dist/js/components/Select/SimpleSelect.js +42 -0
  58. package/dist/js/components/Select/SimpleSelect.js.map +1 -0
  59. package/dist/js/components/Select/TypeaheadSelect.d.ts +35 -0
  60. package/dist/js/components/Select/TypeaheadSelect.d.ts.map +1 -0
  61. package/dist/js/components/Select/TypeaheadSelect.js +198 -0
  62. package/dist/js/components/Select/TypeaheadSelect.js.map +1 -0
  63. package/dist/js/components/Select/index.d.ts +3 -1
  64. package/dist/js/components/Select/index.d.ts.map +1 -1
  65. package/dist/js/components/Select/index.js +3 -1
  66. package/dist/js/components/Select/index.js.map +1 -1
  67. package/dist/js/components/index.d.ts +1 -0
  68. package/dist/js/components/index.d.ts.map +1 -1
  69. package/dist/js/components/index.js +1 -0
  70. package/dist/js/components/index.js.map +1 -1
  71. package/dist/umd/assets/output-DV5sTbNI.css +26066 -0
  72. package/dist/umd/react-templates.min.js +1 -1
  73. package/package.json +7 -10
  74. package/rollup.config.mjs +8 -0
  75. package/src/components/Dropdown/SimpleDropdown.tsx +139 -0
  76. package/src/components/Dropdown/__tests__/SimpleDropdown.test.tsx +266 -0
  77. package/src/components/Dropdown/__tests__/__snapshots__/SimpleDropdown.test.tsx.snap +153 -0
  78. package/src/components/Dropdown/examples/DropdownTemplates.md +24 -0
  79. package/src/components/Dropdown/examples/SimpleDropdownExample.tsx +53 -0
  80. package/src/components/Dropdown/index.ts +1 -0
  81. package/src/components/Select/CheckboxSelect.tsx +23 -7
  82. package/src/components/Select/MultiTypeaheadSelect.tsx +348 -0
  83. package/src/components/Select/{SelectSimple.tsx → SimpleSelect.tsx} +39 -18
  84. package/src/components/Select/TypeaheadSelect.tsx +342 -0
  85. package/src/components/Select/{CheckboxSelect.test.tsx → __tests__/CheckboxSelect.test.tsx} +29 -1
  86. package/src/components/Select/{CheckboxSelectSnapshots.test.tsx → __tests__/CheckboxSelectSnapshots.test.tsx} +1 -1
  87. package/src/components/Select/__tests__/MultiTypeaheadSelect.test.tsx +414 -0
  88. package/src/components/Select/__tests__/SimpleSelect.test.tsx +241 -0
  89. package/src/components/Select/__tests__/TypeaheadSelect.test.tsx +408 -0
  90. package/src/components/Select/{__snapshots__ → __tests__/__snapshots__}/CheckboxSelectSnapshots.test.tsx.snap +7 -2
  91. package/src/components/Select/__tests__/__snapshots__/MultiTypeaheadSelect.test.tsx.snap +180 -0
  92. package/src/components/Select/__tests__/__snapshots__/SimpleSelect.test.tsx.snap +170 -0
  93. package/src/components/Select/__tests__/__snapshots__/TypeaheadSelect.test.tsx.snap +180 -0
  94. package/src/components/Select/examples/CheckboxSelectDemo.tsx +25 -8
  95. package/src/components/Select/examples/MultiTypeaheadSelectDemo.tsx +35 -0
  96. package/src/components/Select/examples/SelectTemplates.md +17 -4
  97. package/src/components/Select/examples/SimpleSelectDemo.tsx +36 -0
  98. package/src/components/Select/examples/TypeaheadSelectDemo.tsx +35 -0
  99. package/src/components/Select/index.ts +3 -1
  100. package/src/components/index.ts +1 -0
  101. package/dist/esm/components/Select/SelectSimple.d.ts.map +0 -1
  102. package/dist/esm/components/Select/SelectSimple.js +0 -31
  103. package/dist/esm/components/Select/SelectSimple.js.map +0 -1
  104. package/dist/js/components/Select/SelectSimple.d.ts.map +0 -1
  105. package/dist/js/components/Select/SelectSimple.js +0 -34
  106. package/dist/js/components/Select/SelectSimple.js.map +0 -1
  107. package/rollup.config.js +0 -7
  108. package/src/components/Select/examples/SelectSimpleDemo.tsx +0 -26
@@ -0,0 +1,266 @@
1
+ import * as React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { SimpleDropdown } from '../SimpleDropdown';
5
+ import styles from '@patternfly/react-styles/css/components/MenuToggle/menu-toggle';
6
+
7
+ describe('Dropdown toggle', () => {
8
+ test('Renders dropdown toggle as not disabled when isDisabled is not true', () => {
9
+ render(<SimpleDropdown toggleContent="Dropdown" />);
10
+
11
+ expect(screen.getByRole('button', { name: 'Dropdown' })).not.toBeDisabled();
12
+ });
13
+
14
+ test('Renders dropdown toggle as disabled when isDisabled is true', () => {
15
+ render(<SimpleDropdown toggleContent="Dropdown" isDisabled />);
16
+
17
+ expect(screen.getByRole('button', { name: 'Dropdown' })).toBeDisabled();
18
+ });
19
+
20
+ test('Passes toggleVariant', () => {
21
+ render(<SimpleDropdown toggleContent="Dropdown" toggleVariant="plain" />);
22
+
23
+ expect(screen.getByRole('button', { name: 'Dropdown' })).toHaveClass(styles.modifiers.plain);
24
+ });
25
+
26
+ test('Passes toggleWidth', () => {
27
+ render(<SimpleDropdown toggleContent="Dropdown" toggleWidth="500px" />);
28
+
29
+ expect(screen.getByRole('button', { name: 'Dropdown' })).toHaveAttribute('style', 'width: 500px;');
30
+ });
31
+
32
+ test('Passes additional toggleProps', () => {
33
+ render(<SimpleDropdown toggleContent="Dropdown" toggleProps={{ id: 'toggle' }} />);
34
+
35
+ expect(screen.getByRole('button', { name: 'Dropdown' })).toHaveAttribute('id', 'toggle');
36
+ });
37
+
38
+ test('Passes toggleAriaLabel', () => {
39
+ render(<SimpleDropdown toggleContent="Dropdown" toggleAriaLabel="Aria label content" />);
40
+
41
+ expect(screen.getByRole('button')).toHaveAccessibleName('Aria label content');
42
+ });
43
+
44
+ test('Calls onToggle with next isOpen state when dropdown toggle is clicked', async () => {
45
+ const onToggle = jest.fn();
46
+ const user = userEvent.setup();
47
+ render(<SimpleDropdown onToggle={onToggle} toggleContent="Dropdown" />);
48
+
49
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
50
+ await user.click(toggle);
51
+ expect(onToggle).toHaveBeenCalledWith(true);
52
+ });
53
+
54
+ test('Does not call onToggle when dropdown toggle is not clicked', async () => {
55
+ const onToggle = jest.fn();
56
+ const items = [{ content: 'Action', value: 1 }];
57
+ const user = userEvent.setup();
58
+ render(
59
+ <div>
60
+ <button>Actual</button>
61
+ <SimpleDropdown initialItems={items} onToggle={onToggle} toggleContent="Dropdown" />
62
+ </div>
63
+ );
64
+
65
+ const btn = screen.getByRole('button', { name: 'Actual' });
66
+ await user.click(btn);
67
+ expect(onToggle).not.toHaveBeenCalled();
68
+ });
69
+
70
+ test('Calls toggle onSelect when item is clicked', async () => {
71
+ const onSelect = jest.fn();
72
+ const items = [{ content: 'Action', value: 1 }];
73
+ const user = userEvent.setup();
74
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" onSelect={onSelect} />);
75
+
76
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
77
+ await user.click(toggle);
78
+
79
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
80
+ await user.click(actionItem);
81
+ expect(onSelect).toHaveBeenCalledTimes(1);
82
+ });
83
+
84
+ test('Does not call toggle onSelect when item is not clicked', async () => {
85
+ const onSelect = jest.fn();
86
+ const items = [{ content: 'Action', value: 1 }];
87
+ const user = userEvent.setup();
88
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" onSelect={onSelect} />);
89
+
90
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
91
+ await user.click(toggle);
92
+ await user.click(toggle);
93
+ expect(onSelect).not.toHaveBeenCalled();
94
+ });
95
+
96
+ test('Does not pass isToggleFullWidth to menu toggle by default', () => {
97
+ render(<SimpleDropdown toggleContent="Dropdown" />);
98
+
99
+ expect(screen.getByRole('button', { name: 'Dropdown' })).not.toHaveClass(styles.modifiers.fullWidth);
100
+ });
101
+
102
+ test('Passes isToggleFullWidth to menu toggle when passed in', () => {
103
+ render(<SimpleDropdown isToggleFullWidth toggleContent="Dropdown" />);
104
+
105
+ expect(screen.getByRole('button', { name: 'Dropdown' })).toHaveClass(styles.modifiers.fullWidth);
106
+ });
107
+
108
+ test('Does not focus toggle on item select by default', async () => {
109
+ const items = [{ content: 'Action', value: 1 }];
110
+ const user = userEvent.setup();
111
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
112
+
113
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
114
+ await user.click(toggle);
115
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
116
+ await user.click(actionItem);
117
+
118
+ expect(toggle).not.toHaveFocus();
119
+ });
120
+
121
+ test('Focuses toggle on item select when shouldFocusToggleOnSelect is true', async () => {
122
+ const items = [{ content: 'Action', value: 1 }];
123
+ const user = userEvent.setup();
124
+ render(<SimpleDropdown shouldFocusToggleOnSelect initialItems={items} toggleContent="Dropdown" />);
125
+
126
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
127
+ await user.click(toggle);
128
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
129
+ await user.click(actionItem);
130
+
131
+ expect(toggle).toHaveFocus();
132
+ });
133
+
134
+ test('Matches snapshot', () => {
135
+ const { asFragment } = render(<SimpleDropdown toggleContent="Dropdown" />);
136
+
137
+ expect(asFragment()).toMatchSnapshot();
138
+ });
139
+ });
140
+
141
+ describe('Dropdown items', () => {
142
+ test('Renders with items', async () => {
143
+ const items = [
144
+ { content: 'Action', value: 1 },
145
+ { value: 'separator', isDivider: true }
146
+ ];
147
+ const user = userEvent.setup();
148
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
149
+
150
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
151
+ await user.click(toggle);
152
+
153
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
154
+ const dividerItem = screen.getByRole('separator');
155
+ expect(actionItem).toBeInTheDocument();
156
+ expect(dividerItem).toBeInTheDocument();
157
+ });
158
+
159
+ test('Renders with a link item', async () => {
160
+ const items = [{ content: 'Link', value: 1, to: '#' }];
161
+ const user = userEvent.setup();
162
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
163
+
164
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
165
+ await user.click(toggle);
166
+
167
+ const linkItem = screen.getByRole('menuitem', { name: 'Link' });
168
+ expect(linkItem.getAttribute('href')).toBe('#');
169
+ });
170
+
171
+ test('Renders with items not disabled by default', async () => {
172
+ const items = [{ content: 'Action', value: 1 }];
173
+ const user = userEvent.setup();
174
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
175
+
176
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
177
+ await user.click(toggle);
178
+
179
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
180
+ expect(actionItem).not.toBeDisabled();
181
+ });
182
+
183
+ test('Renders with a disabled item', async () => {
184
+ const items = [{ content: 'Action', value: 1, isDisabled: true }];
185
+ const user = userEvent.setup();
186
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
187
+
188
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
189
+ await user.click(toggle);
190
+
191
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
192
+ expect(actionItem).toBeDisabled();
193
+ });
194
+
195
+ test('Spreads props on item', async () => {
196
+ const items = [{ content: 'Action', value: 1, id: 'Test' }];
197
+ const user = userEvent.setup();
198
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
199
+
200
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
201
+ await user.click(toggle);
202
+
203
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
204
+ expect(actionItem.getAttribute('id')).toBe('Test');
205
+ });
206
+
207
+ test('Calls item onClick when clicked', async () => {
208
+ const onClick = jest.fn();
209
+ const items = [{ content: 'Action', value: 1, onClick }];
210
+ const user = userEvent.setup();
211
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
212
+
213
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
214
+ await user.click(toggle);
215
+
216
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
217
+ await user.click(actionItem);
218
+ expect(onClick).toHaveBeenCalledTimes(1);
219
+ });
220
+
221
+ test('Does not call item onClick when not clicked', async () => {
222
+ const onClick = jest.fn();
223
+ const items = [
224
+ { content: 'Action', value: 1, onClick },
225
+ { content: 'Action 2', value: 2 }
226
+ ];
227
+ const user = userEvent.setup();
228
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
229
+
230
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
231
+ await user.click(toggle);
232
+
233
+ const actionItem = screen.getByRole('menuitem', { name: 'Action 2' });
234
+ await user.click(actionItem);
235
+ expect(onClick).not.toHaveBeenCalled();
236
+ });
237
+
238
+ test('Does not call item onClick when clicked and item is disabled', async () => {
239
+ const onClick = jest.fn();
240
+ const items = [{ content: 'Action', value: 1, onClick, isDisabled: true }];
241
+ const user = userEvent.setup();
242
+ render(<SimpleDropdown initialItems={items} toggleContent="Dropdown" />);
243
+
244
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
245
+ await user.click(toggle);
246
+
247
+ const actionItem = screen.getByRole('menuitem', { name: 'Action' });
248
+ await user.click(actionItem);
249
+ expect(onClick).not.toHaveBeenCalled();
250
+ });
251
+
252
+ test('Matches snapshot', async () => {
253
+ const items = [
254
+ { content: 'Action', value: 1, ouiaId: '1' },
255
+ { value: 'separator', isDivider: true, ouiaId: '2' },
256
+ { content: 'Link', value: 'separator', to: '#', ouiaId: '3' }
257
+ ];
258
+ const user = userEvent.setup();
259
+ const { asFragment } = render(<SimpleDropdown ouiaId={4} initialItems={items} toggleContent="Dropdown" />);
260
+
261
+ const toggle = screen.getByRole('button', { name: 'Dropdown' });
262
+ await user.click(toggle);
263
+
264
+ expect(asFragment()).toMatchSnapshot();
265
+ });
266
+ });
@@ -0,0 +1,153 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Dropdown items Matches snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <button
6
+ aria-expanded="true"
7
+ class="pf-v5-c-menu-toggle pf-m-expanded"
8
+ data-ouia-component-id="OUIA-Generated-MenuToggle-default-23"
9
+ data-ouia-component-type="PF5/MenuToggle"
10
+ data-ouia-safe="true"
11
+ type="button"
12
+ >
13
+ <span
14
+ class="pf-v5-c-menu-toggle__text"
15
+ >
16
+ Dropdown
17
+ </span>
18
+ <span
19
+ class="pf-v5-c-menu-toggle__controls"
20
+ >
21
+ <span
22
+ class="pf-v5-c-menu-toggle__toggle-icon"
23
+ >
24
+ <svg
25
+ aria-hidden="true"
26
+ class="pf-v5-svg"
27
+ fill="currentColor"
28
+ height="1em"
29
+ role="img"
30
+ viewBox="0 0 320 512"
31
+ width="1em"
32
+ >
33
+ <path
34
+ 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"
35
+ />
36
+ </svg>
37
+ </span>
38
+ </span>
39
+ </button>
40
+ <div
41
+ class="pf-v5-c-menu"
42
+ data-ouia-component-id="4"
43
+ data-ouia-component-type="PF5/Dropdown"
44
+ data-ouia-safe="true"
45
+ data-popper-escaped="true"
46
+ data-popper-placement="bottom-start"
47
+ data-popper-reference-hidden="true"
48
+ style="position: absolute; left: 0px; top: 0px; z-index: 9999; opacity: 1; transition: opacity 0ms cubic-bezier(.54, 1.5, .38, 1.11); min-width: 0px; transform: translate(0px, 0px);"
49
+ >
50
+ <div
51
+ class="pf-v5-c-menu__content"
52
+ >
53
+ <ul
54
+ class="pf-v5-c-menu__list"
55
+ role="menu"
56
+ >
57
+ <li
58
+ class="pf-v5-c-menu__list-item"
59
+ data-ouia-component-id="1"
60
+ data-ouia-component-type="PF5/DropdownItem"
61
+ data-ouia-safe="true"
62
+ role="none"
63
+ >
64
+ <button
65
+ class="pf-v5-c-menu__item"
66
+ role="menuitem"
67
+ tabindex="0"
68
+ type="button"
69
+ >
70
+ <span
71
+ class="pf-v5-c-menu__item-main"
72
+ >
73
+ <span
74
+ class="pf-v5-c-menu__item-text"
75
+ >
76
+ Action
77
+ </span>
78
+ </span>
79
+ </button>
80
+ </li>
81
+ <li
82
+ class="pf-v5-c-divider"
83
+ role="separator"
84
+ />
85
+ <li
86
+ class="pf-v5-c-menu__list-item"
87
+ data-ouia-component-id="3"
88
+ data-ouia-component-type="PF5/DropdownItem"
89
+ data-ouia-safe="true"
90
+ role="none"
91
+ >
92
+ <a
93
+ class="pf-v5-c-menu__item"
94
+ href="#"
95
+ role="menuitem"
96
+ tabindex="-1"
97
+ >
98
+ <span
99
+ class="pf-v5-c-menu__item-main"
100
+ >
101
+ <span
102
+ class="pf-v5-c-menu__item-text"
103
+ >
104
+ Link
105
+ </span>
106
+ </span>
107
+ </a>
108
+ </li>
109
+ </ul>
110
+ </div>
111
+ </div>
112
+ </DocumentFragment>
113
+ `;
114
+
115
+ exports[`Dropdown toggle Matches snapshot 1`] = `
116
+ <DocumentFragment>
117
+ <button
118
+ aria-expanded="false"
119
+ class="pf-v5-c-menu-toggle"
120
+ data-ouia-component-id="OUIA-Generated-MenuToggle-default-14"
121
+ data-ouia-component-type="PF5/MenuToggle"
122
+ data-ouia-safe="true"
123
+ type="button"
124
+ >
125
+ <span
126
+ class="pf-v5-c-menu-toggle__text"
127
+ >
128
+ Dropdown
129
+ </span>
130
+ <span
131
+ class="pf-v5-c-menu-toggle__controls"
132
+ >
133
+ <span
134
+ class="pf-v5-c-menu-toggle__toggle-icon"
135
+ >
136
+ <svg
137
+ aria-hidden="true"
138
+ class="pf-v5-svg"
139
+ fill="currentColor"
140
+ height="1em"
141
+ role="img"
142
+ viewBox="0 0 320 512"
143
+ width="1em"
144
+ >
145
+ <path
146
+ 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"
147
+ />
148
+ </svg>
149
+ </span>
150
+ </span>
151
+ </button>
152
+ </DocumentFragment>
153
+ `;
@@ -0,0 +1,24 @@
1
+ ---
2
+ id: Dropdown
3
+ section: components
4
+ subsection: menus
5
+ template: true
6
+ beta: true
7
+ propComponents: ['SimpleDropdown', 'SimpleDropdownItem']
8
+ ---
9
+
10
+ Note: Templates live in their own package at [@patternfly/react-templates](https://www.npmjs.com/package/@patternfly/react-templates)!
11
+
12
+ For custom use cases, please see the dropdown component suite from [@patternfly/react-core](https://www.npmjs.com/package/@patternfly/react-core).
13
+
14
+ import { Checkbox, Flex, FlexItem } from '@patternfly/react-core';
15
+ import { SimpleDropdown } from '@patternfly/react-templates';
16
+ import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
17
+
18
+ ## Examples
19
+
20
+ ### Simple
21
+
22
+ ```ts file="./SimpleDropdownExample.tsx"
23
+
24
+ ```
@@ -0,0 +1,53 @@
1
+ import React from 'react';
2
+ import { Checkbox, Flex, FlexItem } from '@patternfly/react-core';
3
+ import { SimpleDropdown, SimpleDropdownItem } from '@patternfly/react-templates';
4
+ import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
5
+
6
+ export const SimpleDropdownExample: React.FunctionComponent = () => {
7
+ const [isDisabled, setIsDisabled] = React.useState(false);
8
+
9
+ const items: SimpleDropdownItem[] = [
10
+ // eslint-disable-next-line no-console
11
+ { content: 'Action', value: 1, onClick: () => console.log('Action clicked') },
12
+ // Prevent default click behavior on link for example purposes
13
+ { content: 'Link', value: 2, to: '#', onClick: (event: any) => event.preventDefault() },
14
+ { content: 'Disabled Action', value: 3, isDisabled: true },
15
+ { value: 'separator', isDivider: true },
16
+ // eslint-disable-next-line no-console
17
+ { content: 'Second action', value: 4, onClick: () => console.log('Second action clicked') }
18
+ ];
19
+
20
+ return (
21
+ <React.Fragment>
22
+ <Checkbox
23
+ id="simple-example-disabled-toggle"
24
+ label="Disable simple dropdown toggles"
25
+ isChecked={isDisabled}
26
+ onChange={(_event: React.FormEvent<HTMLInputElement>, checked: boolean) => setIsDisabled(checked)}
27
+ style={{ marginBottom: 20 }}
28
+ />
29
+ <Flex gap={{ default: 'gapLg' }}>
30
+ <FlexItem>
31
+ <SimpleDropdown initialItems={items} isDisabled={isDisabled} toggleContent="Dropdown" />
32
+ </FlexItem>
33
+ <FlexItem>
34
+ <SimpleDropdown
35
+ toggleVariant="plainText"
36
+ initialItems={items}
37
+ isDisabled={isDisabled}
38
+ toggleContent="Dropdown with plainText styling"
39
+ />
40
+ </FlexItem>
41
+ <FlexItem>
42
+ <SimpleDropdown
43
+ toggleVariant="plain"
44
+ initialItems={items}
45
+ isDisabled={isDisabled}
46
+ toggleContent={<EllipsisVIcon aria-hidden="true" />}
47
+ toggleAriaLabel="Plain dropdown toggle"
48
+ />
49
+ </FlexItem>
50
+ </Flex>
51
+ </React.Fragment>
52
+ );
53
+ };
@@ -0,0 +1 @@
1
+ export * from './SimpleDropdown';
@@ -3,10 +3,12 @@ import {
3
3
  Badge,
4
4
  MenuToggle,
5
5
  MenuToggleElement,
6
+ MenuToggleProps,
6
7
  Select,
7
8
  SelectList,
8
9
  SelectOption,
9
- SelectOptionProps
10
+ SelectOptionProps,
11
+ SelectProps
10
12
  } from '@patternfly/react-core';
11
13
 
12
14
  export interface CheckboxSelectOption extends Omit<SelectOptionProps, 'content'> {
@@ -16,7 +18,7 @@ export interface CheckboxSelectOption extends Omit<SelectOptionProps, 'content'>
16
18
  value: string | number;
17
19
  }
18
20
 
19
- export interface CheckboxSelectProps {
21
+ export interface CheckboxSelectProps extends Omit<SelectProps, 'toggle'> {
20
22
  /** @hide Forwarded ref */
21
23
  innerRef?: React.Ref<any>;
22
24
  /** Initial options of the select. */
@@ -27,8 +29,12 @@ export interface CheckboxSelectProps {
27
29
  onToggle?: (nextIsOpen: boolean) => void;
28
30
  /** Flag indicating the select should be disabled. */
29
31
  isDisabled?: boolean;
30
- /** Content of the toggle. Defaults to the selected option. */
32
+ /** Content of the toggle. Defaults to a string with badge count of selected options. */
31
33
  toggleContent?: React.ReactNode;
34
+ /** Width of the toggle. */
35
+ toggleWidth?: string;
36
+ /** Additional props passed to the toggle. */
37
+ toggleProps?: MenuToggleProps;
32
38
  }
33
39
 
34
40
  const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
@@ -38,16 +44,23 @@ const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
38
44
  onSelect: passedOnSelect,
39
45
  onToggle,
40
46
  toggleContent,
47
+ toggleWidth = '200px',
48
+ toggleProps,
41
49
  ...props
42
50
  }: CheckboxSelectProps) => {
43
51
  const [isOpen, setIsOpen] = React.useState(false);
44
52
  const [selected, setSelected] = React.useState<string[]>([]);
45
53
 
54
+ React.useEffect(() => {
55
+ const selectedOptions = initialOptions?.filter((option) => option.selected);
56
+ setSelected(selectedOptions?.map((selectedOption) => String(selectedOption.value)) ?? []);
57
+ }, [initialOptions]);
58
+
46
59
  const checkboxSelectOptions = initialOptions?.map((option) => {
47
60
  const { content, value, ...props } = option;
48
61
  const isSelected = selected.includes(`${value}`);
49
62
  return (
50
- <SelectOption {...props} value={value} key={value} hasCheckbox isSelected={isSelected}>
63
+ <SelectOption value={value} key={value} hasCheckbox isSelected={isSelected} {...props}>
51
64
  {content}
52
65
  </SelectOption>
53
66
  );
@@ -83,9 +96,10 @@ const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
83
96
  isDisabled={isDisabled}
84
97
  style={
85
98
  {
86
- width: '200px'
99
+ width: toggleWidth
87
100
  } as React.CSSProperties
88
101
  }
102
+ {...toggleProps}
89
103
  >
90
104
  {toggleContent || defaultToggleContent}
91
105
  </MenuToggle>
@@ -93,11 +107,13 @@ const CheckboxSelectBase: React.FunctionComponent<CheckboxSelectProps> = ({
93
107
 
94
108
  return (
95
109
  <Select
96
- id="checkbox-select"
97
110
  isOpen={isOpen}
98
111
  selected={selected}
99
112
  onSelect={onSelect}
100
- onOpenChange={(isOpen) => setIsOpen(isOpen)}
113
+ onOpenChange={(isOpen) => {
114
+ onToggle && onToggle(isOpen);
115
+ setIsOpen(isOpen);
116
+ }}
101
117
  toggle={toggle}
102
118
  ref={innerRef}
103
119
  role="menu"