@patternfly/react-docs 5.22.11 → 5.23.3
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/CHANGELOG.md +35 -0
- package/package.json +15 -15
- package/src/generated/components/dual-list-selector/react.js +439 -41
- package/src/generated/components/page/react-demos/sticky-section-group-alternate-syntax.png +0 -0
- package/src/generated/components/select/react.js +1 -1
- package/src/generated/components/table/react-composable.js +38 -7
- package/src/generated/components/table/react-demos/sortable---responsive.png +0 -0
- package/src/generated/components/table/react-demos.js +20 -6
- package/src/generated/components/table/react-legacy.js +24 -13
- package/src/generated/index.js +8 -8
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { AutoLinkHeader, Example, Link as PatternflyThemeLink } from 'theme-patternfly-org/components';
|
|
3
|
+
import AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon';
|
|
4
|
+
import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon';
|
|
5
|
+
import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon';
|
|
6
|
+
import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
|
|
3
7
|
import PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pficon-sort-common-asc-icon';
|
|
4
8
|
const pageData = {
|
|
5
9
|
"id": "Dual list selector",
|
|
@@ -15,99 +19,105 @@ const pageData = {
|
|
|
15
19
|
{
|
|
16
20
|
"name": "addAll",
|
|
17
21
|
"type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
|
|
18
|
-
"description": "Optional callback for the add all button"
|
|
22
|
+
"description": "Optional callback for the dynamically built add all button"
|
|
19
23
|
},
|
|
20
24
|
{
|
|
21
25
|
"name": "addAllAriaLabel",
|
|
22
26
|
"type": "string",
|
|
23
|
-
"description": "Accessible label for the add all button",
|
|
27
|
+
"description": "Accessible label for the dynamically built add all button",
|
|
24
28
|
"defaultValue": "'Add all'"
|
|
25
29
|
},
|
|
26
30
|
{
|
|
27
31
|
"name": "addAllTooltip",
|
|
28
32
|
"type": "React.ReactNode",
|
|
29
|
-
"description": "Tooltip content for the add all button"
|
|
33
|
+
"description": "Tooltip content for the dynamically built add all button"
|
|
30
34
|
},
|
|
31
35
|
{
|
|
32
36
|
"name": "addAllTooltipProps",
|
|
33
37
|
"type": "any",
|
|
34
|
-
"description": "Additonal tooltip properties for the add all tooltip"
|
|
38
|
+
"description": "Additonal tooltip properties for the dynamically built add all tooltip"
|
|
35
39
|
},
|
|
36
40
|
{
|
|
37
41
|
"name": "addSelected",
|
|
38
42
|
"type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
|
|
39
|
-
"description": "Optional callback for the add selected button"
|
|
43
|
+
"description": "Optional callback for the dynamically built add selected button"
|
|
40
44
|
},
|
|
41
45
|
{
|
|
42
46
|
"name": "addSelectedAriaLabel",
|
|
43
47
|
"type": "string",
|
|
44
|
-
"description": "Accessible label for the add selected button",
|
|
48
|
+
"description": "Accessible label for the dynamically built add selected button",
|
|
45
49
|
"defaultValue": "'Add selected'"
|
|
46
50
|
},
|
|
47
51
|
{
|
|
48
52
|
"name": "addSelectedTooltip",
|
|
49
53
|
"type": "React.ReactNode",
|
|
50
|
-
"description": "Tooltip content for the add selected button"
|
|
54
|
+
"description": "Tooltip content for the dynamically built add selected button"
|
|
51
55
|
},
|
|
52
56
|
{
|
|
53
57
|
"name": "addSelectedTooltipProps",
|
|
54
58
|
"type": "any",
|
|
55
|
-
"description": "Additonal tooltip properties for the add selected tooltip"
|
|
59
|
+
"description": "Additonal tooltip properties for the dynamically built add selected tooltip"
|
|
56
60
|
},
|
|
57
61
|
{
|
|
58
62
|
"name": "availableOptions",
|
|
59
63
|
"type": "React.ReactNode[] | DualListSelectorTreeItemData[]",
|
|
60
|
-
"description": "Options to display in the available options pane. When using trees, the options should be in the DualListSelectorTreeItemData[] format.",
|
|
64
|
+
"description": "Options to display in the dynamically built available options pane. When using trees, the options should be in the DualListSelectorTreeItemData[] format.",
|
|
61
65
|
"defaultValue": "[]"
|
|
62
66
|
},
|
|
63
67
|
{
|
|
64
68
|
"name": "availableOptionsActions",
|
|
65
69
|
"type": "React.ReactNode[]",
|
|
66
|
-
"description": "Actions to be displayed above the available options pane."
|
|
70
|
+
"description": "Actions to be displayed above the dynamically built available options pane."
|
|
67
71
|
},
|
|
68
72
|
{
|
|
69
73
|
"name": "availableOptionsSearchAriaLabel",
|
|
70
74
|
"type": "string",
|
|
71
|
-
"description": "Accessible label for the search input on the available options pane.",
|
|
75
|
+
"description": "Accessible label for the search input on the dynamically built available options pane.",
|
|
72
76
|
"defaultValue": "'Available search input'"
|
|
73
77
|
},
|
|
74
78
|
{
|
|
75
79
|
"name": "availableOptionsStatus",
|
|
76
80
|
"type": "string",
|
|
77
|
-
"description": "Status message to display above the available options pane."
|
|
81
|
+
"description": "Status message to display above the dynamically built available options pane."
|
|
78
82
|
},
|
|
79
83
|
{
|
|
80
84
|
"name": "availableOptionsTitle",
|
|
81
85
|
"type": "string",
|
|
82
|
-
"description": "Title applied to the available options pane.",
|
|
86
|
+
"description": "Title applied to the dynamically built available options pane.",
|
|
83
87
|
"defaultValue": "'Available options'"
|
|
84
88
|
},
|
|
89
|
+
{
|
|
90
|
+
"name": "children",
|
|
91
|
+
"type": "React.ReactNode",
|
|
92
|
+
"description": "Content to be rendered in the dual list selector. Panes & controls will not be built dynamically when children are provided.",
|
|
93
|
+
"defaultValue": "''"
|
|
94
|
+
},
|
|
85
95
|
{
|
|
86
96
|
"name": "chosenOptions",
|
|
87
97
|
"type": "React.ReactNode[] | DualListSelectorTreeItemData[]",
|
|
88
|
-
"description": "Options to display in the chosen options pane. When using trees, the options should be in the DualListSelectorTreeItemData[] format.",
|
|
98
|
+
"description": "Options to display in the dynamically built chosen options pane. When using trees, the options should be in the DualListSelectorTreeItemData[] format.",
|
|
89
99
|
"defaultValue": "[]"
|
|
90
100
|
},
|
|
91
101
|
{
|
|
92
102
|
"name": "chosenOptionsActions",
|
|
93
103
|
"type": "React.ReactNode[]",
|
|
94
|
-
"description": "Actions to be displayed above the chosen options pane."
|
|
104
|
+
"description": "Actions to be displayed above the dynamically built chosen options pane."
|
|
95
105
|
},
|
|
96
106
|
{
|
|
97
107
|
"name": "chosenOptionsSearchAriaLabel",
|
|
98
108
|
"type": "string",
|
|
99
|
-
"description": "Accessible label for the search input on the chosen options pane.",
|
|
109
|
+
"description": "Accessible label for the search input on the dynamically built chosen options pane.",
|
|
100
110
|
"defaultValue": "'Chosen search input'"
|
|
101
111
|
},
|
|
102
112
|
{
|
|
103
113
|
"name": "chosenOptionsStatus",
|
|
104
114
|
"type": "string",
|
|
105
|
-
"description": "Status message to display above the chosen options pane."
|
|
115
|
+
"description": "Status message to display above the dynamically built chosen options pane."
|
|
106
116
|
},
|
|
107
117
|
{
|
|
108
118
|
"name": "chosenOptionsTitle",
|
|
109
119
|
"type": "string",
|
|
110
|
-
"description": "Title applied to the chosen options pane.",
|
|
120
|
+
"description": "Title applied to the dynamically built chosen options pane.",
|
|
111
121
|
"defaultValue": "'Chosen options'"
|
|
112
122
|
},
|
|
113
123
|
{
|
|
@@ -118,13 +128,13 @@ const pageData = {
|
|
|
118
128
|
{
|
|
119
129
|
"name": "controlsAriaLabel",
|
|
120
130
|
"type": "string",
|
|
121
|
-
"description": "Accessible label for the controls between the two panes.",
|
|
131
|
+
"description": "Accessible label for the dynamically built controls between the two panes.",
|
|
122
132
|
"defaultValue": "'Selector controls'"
|
|
123
133
|
},
|
|
124
134
|
{
|
|
125
135
|
"name": "filterOption",
|
|
126
136
|
"type": "(option: React.ReactNode, input: string) => boolean",
|
|
127
|
-
"description": "Optional filter function for custom filtering based on search string."
|
|
137
|
+
"description": "Optional filter function for custom filtering based on search string. Used with a dynamically built search input."
|
|
128
138
|
},
|
|
129
139
|
{
|
|
130
140
|
"name": "id",
|
|
@@ -135,79 +145,332 @@ const pageData = {
|
|
|
135
145
|
{
|
|
136
146
|
"name": "isSearchable",
|
|
137
147
|
"type": "boolean",
|
|
138
|
-
"description": "Flag indicating a search bar should be included above both the available and chosen panes."
|
|
148
|
+
"description": "Flag indicating a search bar should be included above both the dynamically built available and chosen panes."
|
|
139
149
|
},
|
|
140
150
|
{
|
|
141
151
|
"name": "isTree",
|
|
142
152
|
"type": "boolean",
|
|
143
|
-
"description": ""
|
|
153
|
+
"description": "Flag indicating if the dual list selector uses trees instead of simple lists",
|
|
154
|
+
"defaultValue": "false"
|
|
144
155
|
},
|
|
145
156
|
{
|
|
146
157
|
"name": "onAvailableOptionsSearchInputChanged",
|
|
147
158
|
"type": "(value: string, event: React.FormEvent<HTMLInputElement>) => void",
|
|
148
|
-
"description": "A callback for when the search input value for available options changes."
|
|
159
|
+
"description": "A callback for when the search input value for the dynamically built available options changes."
|
|
149
160
|
},
|
|
150
161
|
{
|
|
151
162
|
"name": "onChosenOptionsSearchInputChanged",
|
|
152
163
|
"type": "(value: string, event: React.FormEvent<HTMLInputElement>) => void",
|
|
153
|
-
"description": "A callback for when the search input value for chosen options changes."
|
|
164
|
+
"description": "A callback for when the search input value for the dynamically built chosen options changes."
|
|
154
165
|
},
|
|
155
166
|
{
|
|
156
167
|
"name": "onListChange",
|
|
157
168
|
"type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
|
|
158
|
-
"description": "Callback fired every time options are chosen or removed"
|
|
169
|
+
"description": "Callback fired every time dynamically built options are chosen or removed"
|
|
159
170
|
},
|
|
160
171
|
{
|
|
161
172
|
"name": "onOptionCheck",
|
|
162
|
-
"type": "(\n e: React.MouseEvent | React.ChangeEvent<HTMLInputElement
|
|
163
|
-
"description": "Optional callback fired when
|
|
173
|
+
"type": "(\n e: React.MouseEvent | React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent,\n checked: boolean,\n checkedId: string,\n newCheckedItems: string[]\n) => void",
|
|
174
|
+
"description": "Optional callback fired when a dynamically built option is checked"
|
|
164
175
|
},
|
|
165
176
|
{
|
|
166
177
|
"name": "onOptionSelect",
|
|
167
|
-
"type": "(\n e: React.MouseEvent | React.ChangeEvent,\n index: number,\n isChosen: boolean,\n id: string,\n itemData: any,\n parentData: any\n) => void",
|
|
168
|
-
"description": "Optional callback fired when
|
|
178
|
+
"type": "(\n e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent,\n index: number,\n isChosen: boolean,\n id: string,\n itemData: any,\n parentData: any\n) => void",
|
|
179
|
+
"description": "Optional callback fired when a dynamically built option is selected"
|
|
169
180
|
},
|
|
170
181
|
{
|
|
171
182
|
"name": "removeAll",
|
|
172
183
|
"type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
|
|
173
|
-
"description": "Optional callback for the remove all button"
|
|
184
|
+
"description": "Optional callback for the dynamically built remove all button"
|
|
174
185
|
},
|
|
175
186
|
{
|
|
176
187
|
"name": "removeAllAriaLabel",
|
|
177
188
|
"type": "string",
|
|
178
|
-
"description": "Accessible label for the remove all button",
|
|
189
|
+
"description": "Accessible label for the dynamically built remove all button",
|
|
179
190
|
"defaultValue": "'Remove all'"
|
|
180
191
|
},
|
|
181
192
|
{
|
|
182
193
|
"name": "removeAllTooltip",
|
|
183
194
|
"type": "React.ReactNode",
|
|
184
|
-
"description": "Tooltip content for the remove all button"
|
|
195
|
+
"description": "Tooltip content for the dynamically built remove all button"
|
|
185
196
|
},
|
|
186
197
|
{
|
|
187
198
|
"name": "removeAllTooltipProps",
|
|
188
199
|
"type": "any",
|
|
189
|
-
"description": "Additonal tooltip properties for the remove all tooltip"
|
|
200
|
+
"description": "Additonal tooltip properties for the dynamically built remove all tooltip"
|
|
190
201
|
},
|
|
191
202
|
{
|
|
192
203
|
"name": "removeSelected",
|
|
193
204
|
"type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
|
|
194
|
-
"description": "Optional callback for the remove selected button"
|
|
205
|
+
"description": "Optional callback for the dynamically built remove selected button"
|
|
195
206
|
},
|
|
196
207
|
{
|
|
197
208
|
"name": "removeSelectedAriaLabel",
|
|
198
209
|
"type": "string",
|
|
199
|
-
"description": "Accessible label for the remove selected button",
|
|
210
|
+
"description": "Accessible label for the dynamically built remove selected button",
|
|
200
211
|
"defaultValue": "'Remove selected'"
|
|
201
212
|
},
|
|
202
213
|
{
|
|
203
214
|
"name": "removeSelectedTooltip",
|
|
204
215
|
"type": "React.ReactNode",
|
|
205
|
-
"description": "Tooltip content for the remove selected button"
|
|
216
|
+
"description": "Tooltip content for the dynamically built remove selected button"
|
|
206
217
|
},
|
|
207
218
|
{
|
|
208
219
|
"name": "removeSelectedTooltipProps",
|
|
209
220
|
"type": "any",
|
|
210
|
-
"description": "Additonal tooltip properties for the remove selected tooltip"
|
|
221
|
+
"description": "Additonal tooltip properties for the dynamically built remove selected tooltip"
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"name": "DualListSelectorPane",
|
|
227
|
+
"description": "",
|
|
228
|
+
"props": [
|
|
229
|
+
{
|
|
230
|
+
"name": "actions",
|
|
231
|
+
"type": "React.ReactNode[]",
|
|
232
|
+
"description": "Actions to place above the pane."
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"name": "children",
|
|
236
|
+
"type": "React.ReactNode",
|
|
237
|
+
"description": "A dual list selector list or dual list selector tree to be rendered in the pane."
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"name": "className",
|
|
241
|
+
"type": "string",
|
|
242
|
+
"description": "Additional classes applied to the dual list selector pane.",
|
|
243
|
+
"defaultValue": "''"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"name": "id",
|
|
247
|
+
"type": "string",
|
|
248
|
+
"description": "Id of the pane.",
|
|
249
|
+
"defaultValue": "getUniqueId('dual-list-selector-pane')"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"name": "isChosen",
|
|
253
|
+
"type": "boolean",
|
|
254
|
+
"description": "Flag indicating if this pane is the chosen pane.",
|
|
255
|
+
"defaultValue": "false"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"name": "searchInput",
|
|
259
|
+
"type": "React.ReactNode",
|
|
260
|
+
"description": "A search input placed above the list at the top of the pane, before actions."
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"name": "status",
|
|
264
|
+
"type": "string",
|
|
265
|
+
"description": "Status to display above the pane.",
|
|
266
|
+
"defaultValue": "''"
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
"name": "title",
|
|
270
|
+
"type": "React.ReactNode",
|
|
271
|
+
"description": "Title of the pane.",
|
|
272
|
+
"defaultValue": "''"
|
|
273
|
+
}
|
|
274
|
+
]
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"name": "DualListSelectorControl",
|
|
278
|
+
"description": "",
|
|
279
|
+
"props": [
|
|
280
|
+
{
|
|
281
|
+
"name": "aria-label",
|
|
282
|
+
"type": "string",
|
|
283
|
+
"description": "Accessible label for the dual list selector control."
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"name": "children",
|
|
287
|
+
"type": "React.ReactNode",
|
|
288
|
+
"description": "Content to be rendered in the dual list selector control."
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"name": "className",
|
|
292
|
+
"type": "string",
|
|
293
|
+
"description": "Additional classes applied to the dual list selector control."
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"name": "isDisabled",
|
|
297
|
+
"type": "boolean",
|
|
298
|
+
"description": "Flag indicating the control is disabled."
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"name": "onClick",
|
|
302
|
+
"type": "(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void",
|
|
303
|
+
"description": "Callback fired when dual list selector control is selected."
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"name": "tooltipContent",
|
|
307
|
+
"type": "React.ReactNode",
|
|
308
|
+
"description": "Content to be displayed in a tooltip on hover of control."
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"name": "tooltipProps",
|
|
312
|
+
"type": "any",
|
|
313
|
+
"description": "Additional tooltip properties passed to the tooltip."
|
|
314
|
+
}
|
|
315
|
+
]
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"name": "DualListSelectorControlsWrapper",
|
|
319
|
+
"description": "",
|
|
320
|
+
"props": [
|
|
321
|
+
{
|
|
322
|
+
"name": "aria-label",
|
|
323
|
+
"type": "string",
|
|
324
|
+
"description": "Accessible label for the dual list selector controls wrapper."
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
"name": "children",
|
|
328
|
+
"type": "React.ReactNode",
|
|
329
|
+
"description": "Anything that can be rendered inside of the wrapper."
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"name": "className",
|
|
333
|
+
"type": "string",
|
|
334
|
+
"description": "Additional classes added to the wrapper."
|
|
335
|
+
}
|
|
336
|
+
]
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"name": "DualListSelectorTree",
|
|
340
|
+
"description": "",
|
|
341
|
+
"props": [
|
|
342
|
+
{
|
|
343
|
+
"name": "data",
|
|
344
|
+
"type": "DualListSelectorTreeItemData[]",
|
|
345
|
+
"description": "Data of the tree view",
|
|
346
|
+
"required": true
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
"name": "defaultAllExpanded",
|
|
350
|
+
"type": "boolean",
|
|
351
|
+
"description": "Sets the default expanded behavior",
|
|
352
|
+
"defaultValue": "false"
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"name": "hasBadges",
|
|
356
|
+
"type": "boolean",
|
|
357
|
+
"description": "Flag indicating if all options should have badges",
|
|
358
|
+
"defaultValue": "false"
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"name": "id",
|
|
362
|
+
"type": "string",
|
|
363
|
+
"description": "ID of the tree view"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"name": "onOptionCheck",
|
|
367
|
+
"type": "(\n event: React.MouseEvent | React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent,\n isChecked: boolean,\n itemData: DualListSelectorTreeItemData\n) => void",
|
|
368
|
+
"description": "Callback fired when an option is checked"
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"name": "DualListSelectorListItem",
|
|
374
|
+
"description": "",
|
|
375
|
+
"props": [
|
|
376
|
+
{
|
|
377
|
+
"name": "children",
|
|
378
|
+
"type": "React.ReactNode",
|
|
379
|
+
"description": "Content rendered inside the dual list selector."
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"name": "className",
|
|
383
|
+
"type": "string",
|
|
384
|
+
"description": "Additional classes applied to the dual list selector."
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"name": "draggableButtonAriaLabel",
|
|
388
|
+
"type": "string",
|
|
389
|
+
"description": "Accessible label for the draggable button on draggable list items"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"name": "id",
|
|
393
|
+
"type": "string",
|
|
394
|
+
"description": "ID of the option."
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
"name": "isDraggable",
|
|
398
|
+
"type": "boolean",
|
|
399
|
+
"description": "Flag indicating this item is draggable for reordring"
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"name": "isSelected",
|
|
403
|
+
"type": "boolean",
|
|
404
|
+
"description": "Flag indicating the list item is currently selected."
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
"name": "onOptionSelect",
|
|
408
|
+
"type": "(e: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, id?: string) => void",
|
|
409
|
+
"description": "Callback fired when an option is selected."
|
|
410
|
+
}
|
|
411
|
+
]
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
"name": "DualListSelectorTreeItemData",
|
|
415
|
+
"description": "",
|
|
416
|
+
"props": [
|
|
417
|
+
{
|
|
418
|
+
"name": "badgeProps",
|
|
419
|
+
"type": "any",
|
|
420
|
+
"description": "Additional properties to pass to the option badge"
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"name": "checkProps",
|
|
424
|
+
"type": "any",
|
|
425
|
+
"description": "Additional properties to pass to the option checkbox"
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"name": "children",
|
|
429
|
+
"type": "DualListSelectorTreeItemData[]",
|
|
430
|
+
"description": "Content rendered inside the dual list selector."
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
"name": "className",
|
|
434
|
+
"type": "string",
|
|
435
|
+
"description": "Additional classes applied to the dual list selector."
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"name": "defaultExpanded",
|
|
439
|
+
"type": "boolean",
|
|
440
|
+
"description": "Flag indicating this option is expanded by default."
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"name": "hasBadge",
|
|
444
|
+
"type": "boolean",
|
|
445
|
+
"description": "Flag indicating this option has a badge"
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"name": "id",
|
|
449
|
+
"type": "string",
|
|
450
|
+
"description": "ID of the option",
|
|
451
|
+
"required": true
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"name": "isChecked",
|
|
455
|
+
"type": "boolean",
|
|
456
|
+
"description": "Checked state of the option",
|
|
457
|
+
"required": true
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
"name": "onOptionCheck",
|
|
461
|
+
"type": "(\n event: React.MouseEvent | React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent,\n isChecked: boolean,\n isChosen: boolean,\n itemData: DualListSelectorTreeItemData\n ) => void",
|
|
462
|
+
"description": "Callback fired when an option is checked"
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
"name": "parentId",
|
|
466
|
+
"type": "string",
|
|
467
|
+
"description": "Parent id of an option"
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
"name": "text",
|
|
471
|
+
"type": "string",
|
|
472
|
+
"description": "Text of the option",
|
|
473
|
+
"required": true
|
|
211
474
|
}
|
|
212
475
|
]
|
|
213
476
|
}
|
|
@@ -221,10 +484,16 @@ const pageData = {
|
|
|
221
484
|
"Basic with tooltips",
|
|
222
485
|
"Basic with search",
|
|
223
486
|
"Using more complex options with actions",
|
|
224
|
-
"Expandable options
|
|
487
|
+
"Expandable options",
|
|
488
|
+
"Composable dual list selector",
|
|
489
|
+
"Reordering lists using drag and drop"
|
|
225
490
|
]
|
|
226
491
|
};
|
|
227
492
|
pageData.liveContext = {
|
|
493
|
+
AngleDoubleLeftIcon,
|
|
494
|
+
AngleLeftIcon,
|
|
495
|
+
AngleDoubleRightIcon,
|
|
496
|
+
AngleRightIcon,
|
|
228
497
|
PficonSortCommonAscIcon
|
|
229
498
|
};
|
|
230
499
|
pageData.examples = {
|
|
@@ -244,9 +513,136 @@ pageData.examples = {
|
|
|
244
513
|
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { Button, ButtonVariant, Dropdown, DropdownItem, DualListSelector, KebabToggle } from '@patternfly/react-core';\nimport PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pficon-sort-common-asc-icon';\n\nclass ComplexDualListSelector extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n availableOptions: [<span>Option 1</span>, <span>Option 3</span>, <span>Option 4</span>, <span>Option 2</span>],\n chosenOptions: [],\n isAvailableKebabOpen: false,\n isChosenKebabOpen: false\n };\n\n this.onSort = panel => {\n if (panel === 'available') {\n this.setState(prevState => {\n const available = prevState.availableOptions.sort((a, b) => {\n let returnValue = 0;\n if (a.props.children > b.props.children) returnValue = 1;\n if (a.props.children < b.props.children) returnValue = -1;\n return returnValue;\n });\n return {\n availableOptions: available\n };\n });\n }\n\n if (panel === 'chosen') {\n this.setState(prevState => {\n const chosen = prevState.chosenOptions.sort((a, b) => {\n let returnValue = 0;\n if (a.props.children > b.props.children) returnValue = 1;\n if (a.props.children < b.props.children) returnValue = -1;\n return returnValue;\n });\n return {\n chosenOptions: chosen\n };\n });\n }\n };\n\n this.onListChange = (newAvailableOptions, newChosenOptions) => {\n this.setState({\n availableOptions: newAvailableOptions,\n chosenOptions: newChosenOptions\n });\n };\n\n this.onToggle = (isOpen, pane) => {\n this.setState(prevState => {\n return {\n isAvailableKebabOpen: pane === 'available' ? isOpen : prevState.isAvailableKebabOpen,\n isChosenKebabOpen: pane === 'chosen' ? isOpen : prevState.isChosenKebabOpen\n };\n });\n };\n\n this.filterOption = (option, input) => {\n return option.props.children.includes(input);\n };\n }\n\n render() {\n const dropdownItems = [\n <DropdownItem key=\"link\">Link</DropdownItem>,\n <DropdownItem key=\"action\" component=\"button\">\n Action\n </DropdownItem>,\n <DropdownItem key=\"second action\" component=\"button\">\n Second Action\n </DropdownItem>\n ];\n\n const availableOptionsActions = [\n <Button\n variant={ButtonVariant.plain}\n onClick={() => this.onSort('available')}\n aria-label=\"Sort\"\n key=\"availableSortButton\"\n >\n <PficonSortCommonAscIcon />\n </Button>,\n <Dropdown\n toggle={<KebabToggle onToggle={isOpen => this.onToggle(isOpen, 'available')} id=\"toggle-id-1\" />}\n isOpen={this.state.isAvailableKebabOpen}\n isPlain\n dropdownItems={dropdownItems}\n key=\"availableDropdown\"\n />\n ];\n\n const chosenOptionsActions = [\n <Button\n variant={ButtonVariant.plain}\n onClick={() => this.onSort('chosen')}\n aria-label=\"Sort\"\n key=\"chosenSortButton\"\n >\n <PficonSortCommonAscIcon />\n </Button>,\n <Dropdown\n toggle={<KebabToggle onToggle={isOpen => this.onToggle(isOpen, 'chosen')} id=\"toggle-id-2\" />}\n isOpen={this.state.isChosenKebabOpen}\n isPlain\n dropdownItems={dropdownItems}\n key=\"chosenDropdown\"\n />\n ];\n\n return (\n <DualListSelector\n isSearchable\n availableOptions={this.state.availableOptions}\n availableOptionsActions={availableOptionsActions}\n chosenOptions={this.state.chosenOptions}\n chosenOptionsActions={chosenOptionsActions}\n addAll={this.onListChange}\n removeAll={this.onListChange}\n addSelected={this.onListChange}\n removeSelected={this.onListChange}\n filterOption={this.filterOption}\n id=\"withActions\"\n />\n );\n }\n}","title":"Using more complex options with actions","lang":"js"}}>
|
|
245
514
|
|
|
246
515
|
</Example>,
|
|
247
|
-
'Expandable options
|
|
248
|
-
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { DualListSelector } from '@patternfly/react-core';\n\nclass TreeDualListSelector extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n chosenOptions: [\n {\n id: 'CF1',\n text: 'Chosen Folder 1',\n isChecked: false,\n checkProps: { 'aria-label': 'Chosen Folder 1' },\n hasBadge: true,\n badgeProps: { isRead: true },\n children: [\n { id: 'CO1', text: 'Chosen Option 1', isChecked: false, checkProps: { 'aria-label': 'Chosen Option 1' } },\n {\n id: 'CF1A',\n text: 'Chosen Folder 1A',\n isChecked: false,\n checkProps: { 'aria-label': 'Chosen Folder 1A' },\n children: [\n {\n id: 'CO2',\n text: 'Chosen Option 2',\n isChecked: false,\n checkProps: { 'aria-label': 'Chosen Option 2' }\n },\n {\n id: 'CO3',\n text: 'Chosen Option 3',\n isChecked: false,\n checkProps: { 'aria-label': 'Chosen Option 3' }\n }\n ]\n },\n { id: 'CO4', text: 'Chosen Option 4', isChecked: false, checkProps: { 'aria-label': 'Chosen Option 4' } }\n ]\n }\n ],\n availableOptions: [\n {\n id: 'F1',\n text: 'Folder 1',\n isChecked: false,\n checkProps: { 'aria-label': 'Folder 1' },\n hasBadge: true,\n badgeProps: { isRead: true },\n children: [\n { id: 'O1', text: 'Option 1', isChecked: false, checkProps: { 'aria-label': 'Option 1' } },\n {\n id: 'F1A',\n text: 'Folder 1A',\n isChecked: false,\n checkProps: { 'aria-label': 'Folder 1A' },\n children: [\n { id: 'O2', text: 'Option 2', isChecked: false, checkProps: { 'aria-label': 'Option 2' } },\n { id: 'O3', text: 'Option 3', isChecked: false, checkProps: { 'aria-label': 'Option 3' } }\n ]\n },\n { id: 'O4', text: 'Option 4', isChecked: false, checkProps: { 'aria-label': 'Option 4' } }\n ]\n },\n { id: 'O5', text: 'Option 5', isChecked: false, checkProps: { 'aria-label': 'Option 5' } },\n {\n id: 'F2',\n text: 'Folder 2',\n isChecked: false,\n checkProps: { 'aria-label': 'Folder 2' },\n children: [\n { id: 'O6', text: 'Option 6', isChecked: false, checkProps: { 'aria-label': 'Option 6' } },\n { id: 'O7', text: 'Option 5', isChecked: false, checkProps: { 'aria-label': 'Option 5 duplicate' } }\n ]\n }\n ]\n };\n\n this.onListChange = (newAvailableOptions, newChosenOptions) => {\n this.setState({\n availableOptions: newAvailableOptions,\n chosenOptions: newChosenOptions\n });\n };\n }\n\n render() {\n return (\n <DualListSelector\n availableOptions={this.state.availableOptions}\n chosenOptions={this.state.chosenOptions}\n onListChange={this.onListChange}\n id=\"basicSelector\"\n isSearchable\n isTree\n />\n );\n }\n}","title":"Expandable options
|
|
516
|
+
'Expandable options': props =>
|
|
517
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { DualListSelector } from '@patternfly/react-core';\n\nclass TreeDualListSelector extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n chosenOptions: [\n {\n id: 'CF1',\n text: 'Chosen Folder 1',\n isChecked: false,\n checkProps: { 'aria-label': 'Chosen Folder 1' },\n hasBadge: true,\n badgeProps: { isRead: true },\n children: [\n { id: 'CO1', text: 'Chosen Option 1', isChecked: false, checkProps: { 'aria-label': 'Chosen Option 1' } },\n {\n id: 'CF1A',\n text: 'Chosen Folder 1A',\n isChecked: false,\n checkProps: { 'aria-label': 'Chosen Folder 1A' },\n children: [\n {\n id: 'CO2',\n text: 'Chosen Option 2',\n isChecked: false,\n checkProps: { 'aria-label': 'Chosen Option 2' }\n },\n {\n id: 'CO3',\n text: 'Chosen Option 3',\n isChecked: false,\n checkProps: { 'aria-label': 'Chosen Option 3' }\n }\n ]\n },\n { id: 'CO4', text: 'Chosen Option 4', isChecked: false, checkProps: { 'aria-label': 'Chosen Option 4' } }\n ]\n }\n ],\n availableOptions: [\n {\n id: 'F1',\n text: 'Folder 1',\n isChecked: false,\n checkProps: { 'aria-label': 'Folder 1' },\n hasBadge: true,\n badgeProps: { isRead: true },\n children: [\n { id: 'O1', text: 'Option 1', isChecked: false, checkProps: { 'aria-label': 'Option 1' } },\n {\n id: 'F1A',\n text: 'Folder 1A',\n isChecked: false,\n checkProps: { 'aria-label': 'Folder 1A' },\n children: [\n { id: 'O2', text: 'Option 2', isChecked: false, checkProps: { 'aria-label': 'Option 2' } },\n { id: 'O3', text: 'Option 3', isChecked: false, checkProps: { 'aria-label': 'Option 3' } }\n ]\n },\n { id: 'O4', text: 'Option 4', isChecked: false, checkProps: { 'aria-label': 'Option 4' } }\n ]\n },\n { id: 'O5', text: 'Option 5', isChecked: false, checkProps: { 'aria-label': 'Option 5' } },\n {\n id: 'F2',\n text: 'Folder 2',\n isChecked: false,\n checkProps: { 'aria-label': 'Folder 2' },\n children: [\n { id: 'O6', text: 'Option 6', isChecked: false, checkProps: { 'aria-label': 'Option 6' } },\n { id: 'O7', text: 'Option 5', isChecked: false, checkProps: { 'aria-label': 'Option 5 duplicate' } }\n ]\n }\n ]\n };\n\n this.onListChange = (newAvailableOptions, newChosenOptions) => {\n this.setState({\n availableOptions: newAvailableOptions,\n chosenOptions: newChosenOptions\n });\n };\n }\n\n render() {\n return (\n <DualListSelector\n availableOptions={this.state.availableOptions}\n chosenOptions={this.state.chosenOptions}\n onListChange={this.onListChange}\n id=\"basicSelector\"\n isSearchable\n isTree\n />\n );\n }\n}","title":"Expandable options","lang":"js"}}>
|
|
518
|
+
|
|
519
|
+
</Example>,
|
|
520
|
+
'Composable dual list selector': props =>
|
|
521
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { \n Button,\n ButtonVariant,\n DualListSelector, \n DualListSelectorPane,\n DualListSelectorList,\n DualListSelectorListItem,\n DualListSelectorControlsWrapper,\n DualListSelectorControl,\n SearchInput\n} from '@patternfly/react-core';\nimport AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon';\nimport AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon';\nimport AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon';\nimport AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';\nimport PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pficon-sort-common-asc-icon';\n\nconst ComposableDualListSelector = () => {\n const [availableOptions, setAvailableOptions] = React.useState([\n { text: 'Apple', selected: false, isVisible: true },\n { text: 'Banana', selected: false, isVisible: true },\n { text: 'Pineapple', selected: false, isVisible: true },\n { text: 'Orange', selected: false, isVisible: true },\n { text: 'Grape', selected: false, isVisible: true },\n { text: 'Peach', selected: false, isVisible: true },\n { text: 'Strawberry', selected: false, isVisible: true }\n ]);\n const [chosenOptions, setChosenOptions] = React.useState([]);\n const [availableFilter, setAvailableFilter] = React.useState('');\n const [chosenFilter, setChosenFilter] = React.useState('');\n\n // callback for moving selected options between lists\n const moveSelected = (fromAvailable) => {\n const sourceOptions = fromAvailable ? availableOptions : chosenOptions;\n const destinationOptions = fromAvailable ? chosenOptions : availableOptions;\n for (let i = 0; i < sourceOptions.length; i++) {\n const option = sourceOptions[i];\n if (option.selected && option.isVisible) {\n sourceOptions.splice(i, 1);\n destinationOptions.push(option);\n option.selected = false;\n i--;\n }\n }\n if (fromAvailable) {\n setAvailableOptions([...sourceOptions]);\n setChosenOptions([...destinationOptions]);\n } else {\n setChosenOptions([...sourceOptions]);\n setAvailableOptions([...destinationOptions]);\n }\n };\n \n // callback for moving all options between lists\n const moveAll = (fromAvailable) => {\n if (fromAvailable) {\n setChosenOptions([...availableOptions.filter(x => x.isVisible), ...chosenOptions]);\n setAvailableOptions([...availableOptions.filter(x => !x.isVisible)]);\n } else {\n setAvailableOptions([...chosenOptions.filter(x => x.isVisible), ...availableOptions]);\n setChosenOptions([...chosenOptions.filter(x => !x.isVisible)]);\n }\n };\n \n // callback when option is selected\n const onOptionSelect = (event, index, isChosen) => {\n if (isChosen) {\n const newChosen = [...chosenOptions];\n newChosen[index].selected = !chosenOptions[index].selected;\n setChosenOptions(newChosen);\n } else {\n const newAvailable = [...availableOptions];\n newAvailable[index].selected = !availableOptions[index].selected;\n setAvailableOptions(newAvailable);\n }\n };\n \n // builds a search input - used in each dual list selector pane\n const buildSearchInput = (isAvailable) => {\n const onChange = (value) => {\n isAvailable ? setAvailableFilter(value) : setChosenFilter(value);\n const toFilter = isAvailable ? [...availableOptions] : [...chosenOptions];\n toFilter.forEach((option) => {\n option.isVisible = value === '' || option.text.toLowerCase().includes(value.toLowerCase());\n })\n };\n \n return (\n <SearchInput\n value={isAvailable ? availableFilter : chosenFilter}\n onChange={onChange}\n onClear={() => onChange('')}\n />\n );\n };\n \n // builds a sort control - passed to both dual list selector panes\n const buildSort = (isAvailable) => {\n const onSort = () => {\n const toSort = isAvailable ? [...availableOptions] : [...chosenOptions];\n toSort.sort((a,b) => {\n if (a.text > b.text) return 1;\n if (a.text < b.text) return -1;\n return 0;\n });\n if (isAvailable) {\n setAvailableOptions(toSort);\n } else {\n setChosenOptions(toSort);\n }\n };\n \n return (\n <Button\n variant={ButtonVariant.plain}\n onClick={onSort}\n aria-label=\"Sort\"\n key=\"sortButton\"\n >\n <PficonSortCommonAscIcon />\n </Button>\n );\n };\n\n return (\n <DualListSelector>\n <DualListSelectorPane\n title=\"Available\"\n status={`${availableOptions.filter(x => x.selected && x.isVisible).length} of ${availableOptions.filter(x => x.isVisible).length} options selected`}\n searchInput={buildSearchInput(true)}\n actions={[buildSort(true)]}\n >\n <DualListSelectorList>\n {availableOptions.map((option, index) => {\n return option.isVisible ? (\n <DualListSelectorListItem\n key={index}\n isSelected={option.selected}\n id={`composable-option-${index}`}\n onOptionSelect={(e) => onOptionSelect(e, index, false)}\n >\n {option.text}\n </DualListSelectorListItem>\n ) : null;\n })}\n </DualListSelectorList>\n </DualListSelectorPane>\n <DualListSelectorControlsWrapper\n aria-label=\"Selector controls\"\n >\n <DualListSelectorControl\n isDisabled={!availableOptions.some(option => option.selected)}\n onClick={() => moveSelected(true)}\n aria-label=\"Add selected\"\n tooltipContent=\"Add selected\"\n >\n <AngleRightIcon />\n </DualListSelectorControl>\n <DualListSelectorControl\n isDisabled={availableOptions.length === 0}\n onClick={() => moveAll(true)}\n aria-label=\"Add all\"\n tooltipContent=\"Add all\"\n >\n <AngleDoubleRightIcon />\n </DualListSelectorControl>\n <DualListSelectorControl\n isDisabled={chosenOptions.length === 0}\n onClick={() => moveAll(false)}\n aria-label=\"Remove all\"\n tooltipContent=\"Remove all\"\n >\n <AngleDoubleLeftIcon />\n </DualListSelectorControl>\n <DualListSelectorControl\n onClick={() => moveSelected(false)}\n isDisabled={!chosenOptions.some(option => option.selected)}\n aria-label=\"Remove selected\"\n tooltipContent=\"Remove selected\"\n >\n <AngleLeftIcon />\n </DualListSelectorControl>\n </DualListSelectorControlsWrapper>\n <DualListSelectorPane\n title=\"Chosen\"\n status={`${chosenOptions.filter(x => x.selected && x.isVisible).length} of ${chosenOptions.filter(x => x.isVisible).length} options selected`}\n searchInput={buildSearchInput(false)}\n actions={[buildSort(false)]}\n isChosen\n >\n <DualListSelectorList>\n {chosenOptions.map((option, index) => {\n return option.isVisible ? (\n <DualListSelectorListItem\n key={index}\n isSelected={option.selected}\n id={`composable-option-${index}`}\n onOptionSelect={(e) => onOptionSelect(e, index, true)}\n >\n {option.text}\n </DualListSelectorListItem>\n ) : null;\n })}\n </DualListSelectorList>\n </DualListSelectorPane>\n </DualListSelector>\n );\n}","title":"Composable dual list selector","lang":"js"}}>
|
|
522
|
+
|
|
523
|
+
<p {...{"className":"ws-p"}}>
|
|
524
|
+
{`For more flexibility, a Dual list selector can be built using sub components. When doing so, the intended component
|
|
525
|
+
relationships are arranged as follows:`}
|
|
526
|
+
</p>
|
|
527
|
+
|
|
528
|
+
<Example {...{"code":"import React from 'react';\nimport { DualListSelector, DualListSelectorPane, DualListSelectorList, DualListSelectorListItem, DualListSelectorControlsWrapper, DualListSelectorControl } from '@patternfly/react-core';\n<DualListSelector>\n\n <DualListSelectorPane>\n <DualListSelectorList>\n <DualListSelectorListItem/>\n </DualListSelectorList>\n </DualListSelectorPane>\n \n <DualListSelectorControlsWrapper>\n <DualListSelectorControl/> {/* The standard Dual list selector has 4 controls */}\n </DualListSelectorControlsWrapper>\n \n <DualListSelectorPane isChosen>\n <DualListSelectorList>\n <DualListSelectorListItem/>\n </DualListSelectorList>\n </DualListSelectorPane>\n \n</DualListSelector>","lang":"js","noLive":true}}>
|
|
529
|
+
|
|
530
|
+
</Example>
|
|
531
|
+
</Example>,
|
|
532
|
+
'Reordering lists using drag and drop': props =>
|
|
533
|
+
<Example {...pageData} {...props} {...{"code":"import React from 'react';\nimport { \n DragDrop,\n Droppable,\n Draggable,\n DualListSelector, \n DualListSelectorPane,\n DualListSelectorList,\n DualListSelectorListItem,\n DualListSelectorControlsWrapper,\n DualListSelectorControl,\n} from '@patternfly/react-core';\nimport AngleDoubleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-left-icon';\nimport AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon';\nimport AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon';\nimport AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';\n\nconst ComposableDualListSelector = () => {\n const [ignoreNextOptionSelect, setIgnoreNextOptionSelect] = React.useState(false);\n const [availableOptions, setAvailableOptions] = React.useState([\n { text: 'Apple', selected: false, isVisible: true },\n { text: 'Banana', selected: false, isVisible: true },\n { text: 'Pineapple', selected: false, isVisible: true }\n ]);\n const [chosenOptions, setChosenOptions] = React.useState([\n { text: 'Orange', selected: false, isVisible: true },\n { text: 'Grape', selected: false, isVisible: true },\n { text: 'Peach', selected: false, isVisible: true },\n { text: 'Strawberry', selected: false, isVisible: true }\n ]);\n\n const moveSelected = (fromAvailable) => {\n const sourceOptions = fromAvailable ? availableOptions : chosenOptions;\n const destinationOptions = fromAvailable ? chosenOptions : availableOptions;\n for (let i = 0; i < sourceOptions.length; i++) {\n const option = sourceOptions[i];\n if (option.selected && option.isVisible) {\n sourceOptions.splice(i, 1);\n destinationOptions.push(option);\n option.selected = false;\n i--;\n }\n }\n if (fromAvailable) {\n setAvailableOptions([...sourceOptions]);\n setChosenOptions([...destinationOptions]);\n } else {\n setChosenOptions([...sourceOptions]);\n setAvailableOptions([...destinationOptions]);\n }\n };\n \n const moveAll = (fromAvailable) => {\n if (fromAvailable) {\n setChosenOptions([...availableOptions.filter(x => x.isVisible), ...chosenOptions]);\n setAvailableOptions([...availableOptions.filter(x => !x.isVisible)]);\n } else {\n setAvailableOptions([...chosenOptions.filter(x => x.isVisible), ...availableOptions]);\n setChosenOptions([...chosenOptions.filter(x => !x.isVisible)]);\n }\n };\n \n const onOptionSelect = (event, index, isChosen) => {\n if (ignoreNextOptionSelect) {\n setIgnoreNextOptionSelect(false);\n return;\n }\n if (isChosen) {\n const newChosen = [...chosenOptions];\n newChosen[index].selected = !chosenOptions[index].selected;\n setChosenOptions(newChosen);\n } else {\n const newAvailable = [...availableOptions];\n newAvailable[index].selected = !availableOptions[index].selected;\n setAvailableOptions(newAvailable);\n }\n };\n \n const onDrop = (source, dest) => {\n if (dest){\n const newList = [...chosenOptions];\n const [removed] = newList.splice(source.index, 1);\n newList.splice(dest.index, 0, removed);\n setChosenOptions(newList);\n return true;\n }\n return false;\n };\n\n return (\n <DualListSelector>\n <DualListSelectorPane\n title=\"Available\"\n status={`${availableOptions.filter(x => x.selected && x.isVisible).length} of ${availableOptions.filter(x => x.isVisible).length} options selected`}\n >\n <DualListSelectorList>\n {availableOptions.map((option, index) => {\n return option.isVisible ? (\n <DualListSelectorListItem\n key={index}\n isSelected={option.selected}\n id={`composable-available-option-${index}`}\n onOptionSelect={(e) => onOptionSelect(e, index, false)}\n >\n {option.text}\n </DualListSelectorListItem>\n ) : null;\n })}\n </DualListSelectorList>\n </DualListSelectorPane>\n <DualListSelectorControlsWrapper\n aria-label=\"Selector controls\"\n >\n <DualListSelectorControl\n isDisabled={!availableOptions.some(option => option.selected)}\n onClick={() => moveSelected(true)}\n aria-label=\"Add selected\"\n >\n <AngleRightIcon />\n </DualListSelectorControl>\n <DualListSelectorControl\n isDisabled={availableOptions.length === 0}\n onClick={() => moveAll(true)}\n aria-label=\"Add all\"\n >\n <AngleDoubleRightIcon />\n </DualListSelectorControl>\n <DualListSelectorControl\n isDisabled={chosenOptions.length === 0}\n onClick={() => moveAll(false)}\n aria-label=\"Remove all\"\n >\n <AngleDoubleLeftIcon />\n </DualListSelectorControl>\n <DualListSelectorControl\n onClick={() => moveSelected(false)}\n isDisabled={!chosenOptions.some(option => option.selected)}\n aria-label=\"Remove selected\"\n >\n <AngleLeftIcon />\n </DualListSelectorControl>\n </DualListSelectorControlsWrapper>\n <DragDrop onDrag={() => { setIgnoreNextOptionSelect(true); return true; }} onDrop={onDrop}>\n <DualListSelectorPane\n title=\"Chosen\"\n status={`${chosenOptions.filter(x => x.selected && x.isVisible).length} of ${chosenOptions.filter(x => x.isVisible).length} options selected`}\n isChosen\n >\n <Droppable hasNoWrapper>\n <DualListSelectorList>\n {chosenOptions.map((option, index) => {\n return option.isVisible ? (\n <Draggable key={index} hasNoWrapper>\n <DualListSelectorListItem\n isSelected={option.selected}\n id={`composable-chosen-option-${index}`}\n onOptionSelect={(e) => onOptionSelect(e, index, true)}\n isDraggable\n >\n {option.text}\n </DualListSelectorListItem>\n </Draggable>\n ) : null;\n })}\n </DualListSelectorList>\n </Droppable>\n </DualListSelectorPane>\n </DragDrop>\n </DualListSelector>\n );\n}","title":"Reordering lists using drag and drop","lang":"js"}}>
|
|
534
|
+
|
|
535
|
+
<p {...{"className":"ws-p"}}>
|
|
536
|
+
{`To make a pane able to be reordered:`}
|
|
537
|
+
</p>
|
|
249
538
|
|
|
539
|
+
<ul {...{"className":"ws-ul"}}>
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
<li {...{"className":"ws-li"}}>
|
|
544
|
+
{`wrap the `}
|
|
545
|
+
|
|
546
|
+
<code {...{"className":"ws-code"}}>
|
|
547
|
+
{`DualListSelectorPane`}
|
|
548
|
+
</code>
|
|
549
|
+
{` in a `}
|
|
550
|
+
|
|
551
|
+
<code {...{"className":"ws-code"}}>
|
|
552
|
+
{`DragDrop`}
|
|
553
|
+
</code>
|
|
554
|
+
{` component`}
|
|
555
|
+
</li>
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
<li {...{"className":"ws-li"}}>
|
|
560
|
+
{`wrap the `}
|
|
561
|
+
|
|
562
|
+
<code {...{"className":"ws-code"}}>
|
|
563
|
+
{`DualListSelectorList`}
|
|
564
|
+
</code>
|
|
565
|
+
{` in a `}
|
|
566
|
+
|
|
567
|
+
<code {...{"className":"ws-code"}}>
|
|
568
|
+
{`Droppable`}
|
|
569
|
+
</code>
|
|
570
|
+
{` component`}
|
|
571
|
+
</li>
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
<li {...{"className":"ws-li"}}>
|
|
576
|
+
{`wrap the `}
|
|
577
|
+
|
|
578
|
+
<code {...{"className":"ws-code"}}>
|
|
579
|
+
{`DualListSelectorListItem`}
|
|
580
|
+
</code>
|
|
581
|
+
{` components in a `}
|
|
582
|
+
|
|
583
|
+
<code {...{"className":"ws-code"}}>
|
|
584
|
+
{`Draggable`}
|
|
585
|
+
</code>
|
|
586
|
+
{` component`}
|
|
587
|
+
</li>
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
<li {...{"className":"ws-li"}}>
|
|
592
|
+
{`define an `}
|
|
593
|
+
|
|
594
|
+
<code {...{"className":"ws-code"}}>
|
|
595
|
+
{`onDrop`}
|
|
596
|
+
</code>
|
|
597
|
+
{` callback which reorders the sortable options.`}
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
<ul {...{"className":"ws-ul"}}>
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
<li {...{"className":"ws-li"}}>
|
|
606
|
+
{`The `}
|
|
607
|
+
|
|
608
|
+
<code {...{"className":"ws-code"}}>
|
|
609
|
+
{`onDrop`}
|
|
610
|
+
</code>
|
|
611
|
+
{` function provides the starting location and destination location for a dragged item. It should return
|
|
612
|
+
true to enable the 'drop' animation in the new location and false to enable the 'drop' animation back to the item's
|
|
613
|
+
old position.`}
|
|
614
|
+
</li>
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
<li {...{"className":"ws-li"}}>
|
|
619
|
+
{`define an `}
|
|
620
|
+
|
|
621
|
+
<code {...{"className":"ws-code"}}>
|
|
622
|
+
{`onDrag`}
|
|
623
|
+
</code>
|
|
624
|
+
{` callback which ensures that the drag event will not cross hairs with the `}
|
|
625
|
+
|
|
626
|
+
<code {...{"className":"ws-code"}}>
|
|
627
|
+
{`onOptionSelect`}
|
|
628
|
+
</code>
|
|
629
|
+
{` click
|
|
630
|
+
event set on the option. Note: the `}
|
|
631
|
+
|
|
632
|
+
<code {...{"className":"ws-code"}}>
|
|
633
|
+
{`ignoreNextOptionSelect`}
|
|
634
|
+
</code>
|
|
635
|
+
{` state value is used to prevent selection while dragging.`}
|
|
636
|
+
</li>
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
</ul>
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
</li>
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
</ul>
|
|
250
646
|
</Example>
|
|
251
647
|
};
|
|
252
648
|
|
|
@@ -259,7 +655,9 @@ const Component = () => (
|
|
|
259
655
|
{React.createElement(pageData.examples["Basic with tooltips"])}
|
|
260
656
|
{React.createElement(pageData.examples["Basic with search"])}
|
|
261
657
|
{React.createElement(pageData.examples["Using more complex options with actions"])}
|
|
262
|
-
{React.createElement(pageData.examples["Expandable options
|
|
658
|
+
{React.createElement(pageData.examples["Expandable options"])}
|
|
659
|
+
{React.createElement(pageData.examples["Composable dual list selector"])}
|
|
660
|
+
{React.createElement(pageData.examples["Reordering lists using drag and drop"])}
|
|
263
661
|
</React.Fragment>
|
|
264
662
|
);
|
|
265
663
|
Component.displayName = 'ComponentsDualListSelectorReactDocs';
|