@patternfly/react-docs 7.6.0-prerelease.7 → 7.6.0-prerelease.8

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 (162) hide show
  1. package/package.json +12 -13
  2. package/patternfly-docs/generated/components/about-modal/react.js +149 -0
  3. package/patternfly-docs/generated/components/accordion/react.js +262 -0
  4. package/patternfly-docs/generated/components/action-list/react.js +144 -0
  5. package/patternfly-docs/generated/components/alert/react-demos.js +56 -0
  6. package/patternfly-docs/generated/components/alert/react.js +1433 -0
  7. package/patternfly-docs/generated/components/avatar/react.js +166 -0
  8. package/patternfly-docs/generated/components/back-to-top/react-demos.js +60 -0
  9. package/patternfly-docs/generated/components/back-to-top/react.js +77 -0
  10. package/patternfly-docs/generated/components/backdrop/react.js +64 -0
  11. package/patternfly-docs/generated/components/background-image/react.js +62 -0
  12. package/patternfly-docs/generated/components/badge/react.js +97 -0
  13. package/patternfly-docs/generated/components/banner/react-demos.js +57 -0
  14. package/patternfly-docs/generated/components/banner/react.js +148 -0
  15. package/patternfly-docs/generated/components/brand/react.js +142 -0
  16. package/patternfly-docs/generated/components/breadcrumb/react.js +206 -0
  17. package/patternfly-docs/generated/components/button/react-demos.js +57 -0
  18. package/patternfly-docs/generated/components/button/react.js +826 -0
  19. package/patternfly-docs/generated/components/card/react-demos.js +201 -0
  20. package/patternfly-docs/generated/components/card/react.js +1015 -0
  21. package/patternfly-docs/generated/components/charts/area-chart/-Victory.js +1350 -0
  22. package/patternfly-docs/generated/components/charts/bar-chart/-Victory.js +1334 -0
  23. package/patternfly-docs/generated/components/charts/box-plot-chart/-Victory.js +1282 -0
  24. package/patternfly-docs/generated/components/charts/bullet-chart/-Victory.js +848 -0
  25. package/patternfly-docs/generated/components/charts/colors-for-charts/-Victory.js +192 -0
  26. package/patternfly-docs/generated/components/charts/donut-chart/-Victory.js +426 -0
  27. package/patternfly-docs/generated/components/charts/donut-utilization-chart/-Victory.js +804 -0
  28. package/patternfly-docs/generated/components/charts/legends/-Victory.js +3230 -0
  29. package/patternfly-docs/generated/components/charts/line-chart/-Victory.js +1178 -0
  30. package/patternfly-docs/generated/components/charts/line-chart/ECharts.js +525 -0
  31. package/patternfly-docs/generated/components/charts/patterns/-Victory.js +3382 -0
  32. package/patternfly-docs/generated/components/charts/pie-chart/-Victory.js +377 -0
  33. package/patternfly-docs/generated/components/charts/resize-observer/-Victory.js +2475 -0
  34. package/patternfly-docs/generated/components/charts/sankey-chart/ECharts.js +538 -0
  35. package/patternfly-docs/generated/components/charts/scatter-chart/-Victory.js +1551 -0
  36. package/patternfly-docs/generated/components/charts/skeletons/-Victory.js +4115 -0
  37. package/patternfly-docs/generated/components/charts/sparkline-chart/-Victory.js +955 -0
  38. package/patternfly-docs/generated/components/charts/stack-chart/-Victory.js +1173 -0
  39. package/patternfly-docs/generated/components/charts/threshold-chart/-Victory.js +1166 -0
  40. package/patternfly-docs/generated/components/charts/tooltips/-Victory.js +413 -0
  41. package/patternfly-docs/generated/components/chip/react-deprecated.js +323 -0
  42. package/patternfly-docs/generated/components/clipboard-copy/react.js +373 -0
  43. package/patternfly-docs/generated/components/code-block/react.js +148 -0
  44. package/patternfly-docs/generated/components/code-editor/react.js +659 -0
  45. package/patternfly-docs/generated/components/compass/react-demos.js +147 -0
  46. package/patternfly-docs/generated/components/compass/react.js +440 -0
  47. package/patternfly-docs/generated/components/content/react.js +248 -0
  48. package/patternfly-docs/generated/components/data-list/react-demos.js +90 -0
  49. package/patternfly-docs/generated/components/data-list/react.js +709 -0
  50. package/patternfly-docs/generated/components/date-and-time/calendar-month/react.js +283 -0
  51. package/patternfly-docs/generated/components/date-and-time/date-and-time-picker/react-demos.js +64 -0
  52. package/patternfly-docs/generated/components/date-and-time/date-picker/react-demos.js +83 -0
  53. package/patternfly-docs/generated/components/date-and-time/date-picker/react.js +395 -0
  54. package/patternfly-docs/generated/components/date-and-time/time-picker/react.js +241 -0
  55. package/patternfly-docs/generated/components/description-list/react-demos.js +58 -0
  56. package/patternfly-docs/generated/components/description-list/react.js +743 -0
  57. package/patternfly-docs/generated/components/divider/react.js +126 -0
  58. package/patternfly-docs/generated/components/drag-and-drop/react-demos.js +351 -0
  59. package/patternfly-docs/generated/components/drag-and-drop/react-deprecated.js +184 -0
  60. package/patternfly-docs/generated/components/drag-and-drop/react.js +137 -0
  61. package/patternfly-docs/generated/components/drawer/react.js +598 -0
  62. package/patternfly-docs/generated/components/dual-list-selector/react-deprecated.js +772 -0
  63. package/patternfly-docs/generated/components/dual-list-selector/react.js +594 -0
  64. package/patternfly-docs/generated/components/empty-state/react.js +199 -0
  65. package/patternfly-docs/generated/components/expandable-section/react-demos.js +65 -0
  66. package/patternfly-docs/generated/components/expandable-section/react.js +408 -0
  67. package/patternfly-docs/generated/components/file-upload/multiple-file-upload/react-demos.js +52 -0
  68. package/patternfly-docs/generated/components/file-upload/multiple-file-upload/react.js +398 -0
  69. package/patternfly-docs/generated/components/file-upload/simple-file-upload/react.js +749 -0
  70. package/patternfly-docs/generated/components/forms/checkbox/react.js +222 -0
  71. package/patternfly-docs/generated/components/forms/form/react.js +1106 -0
  72. package/patternfly-docs/generated/components/forms/form-select/react.js +208 -0
  73. package/patternfly-docs/generated/components/forms/radio/react.js +212 -0
  74. package/patternfly-docs/generated/components/forms/text-area/react.js +160 -0
  75. package/patternfly-docs/generated/components/forms/text-input/react.js +216 -0
  76. package/patternfly-docs/generated/components/helper-text/react-demos.js +180 -0
  77. package/patternfly-docs/generated/components/helper-text/react.js +164 -0
  78. package/patternfly-docs/generated/components/hero/react.js +88 -0
  79. package/patternfly-docs/generated/components/hint/react.js +169 -0
  80. package/patternfly-docs/generated/components/icon/react.js +215 -0
  81. package/patternfly-docs/generated/components/input-group/react.js +182 -0
  82. package/patternfly-docs/generated/components/jump-links/react-demos.js +154 -0
  83. package/patternfly-docs/generated/components/jump-links/react.js +212 -0
  84. package/patternfly-docs/generated/components/label/react-demos.js +57 -0
  85. package/patternfly-docs/generated/components/label/react.js +417 -0
  86. package/patternfly-docs/generated/components/list/react.js +175 -0
  87. package/patternfly-docs/generated/components/login-page/react.js +587 -0
  88. package/patternfly-docs/generated/components/masthead/react-demos.js +79 -0
  89. package/patternfly-docs/generated/components/masthead/react.js +291 -0
  90. package/patternfly-docs/generated/components/menus/application-launcher/react-demos.js +769 -0
  91. package/patternfly-docs/generated/components/menus/context-selector/react-demos.js +665 -0
  92. package/patternfly-docs/generated/components/menus/custom-menus/react-demos.js +187 -0
  93. package/patternfly-docs/generated/components/menus/dropdown/react-templates.js +163 -0
  94. package/patternfly-docs/generated/components/menus/dropdown/react.js +998 -0
  95. package/patternfly-docs/generated/components/menus/menu/react.js +1540 -0
  96. package/patternfly-docs/generated/components/menus/menu-toggle/react.js +747 -0
  97. package/patternfly-docs/generated/components/menus/options-menu/react-demos.js +508 -0
  98. package/patternfly-docs/generated/components/menus/select/react-templates.js +257 -0
  99. package/patternfly-docs/generated/components/menus/select/react.js +998 -0
  100. package/patternfly-docs/generated/components/modal/react-deprecated.js +554 -0
  101. package/patternfly-docs/generated/components/modal/react.js +597 -0
  102. package/patternfly-docs/generated/components/navigation/react-demos.js +356 -0
  103. package/patternfly-docs/generated/components/navigation/react.js +409 -0
  104. package/patternfly-docs/generated/components/notification-badge/react.js +196 -0
  105. package/patternfly-docs/generated/components/notification-drawer/react-demos.js +107 -0
  106. package/patternfly-docs/generated/components/notification-drawer/react.js +394 -0
  107. package/patternfly-docs/generated/components/number-input/react.js +210 -0
  108. package/patternfly-docs/generated/components/overflow-menu/react.js +274 -0
  109. package/patternfly-docs/generated/components/page/react-demos.js +149 -0
  110. package/patternfly-docs/generated/components/page/react.js +1352 -0
  111. package/patternfly-docs/generated/components/pagination/react.js +492 -0
  112. package/patternfly-docs/generated/components/panel/react.js +236 -0
  113. package/patternfly-docs/generated/components/popover/react.js +390 -0
  114. package/patternfly-docs/generated/components/progress/react-demos.js +59 -0
  115. package/patternfly-docs/generated/components/progress/react.js +283 -0
  116. package/patternfly-docs/generated/components/progress-stepper/react-demos.js +45 -0
  117. package/patternfly-docs/generated/components/progress-stepper/react.js +219 -0
  118. package/patternfly-docs/generated/components/search-input/react-demos.js +113 -0
  119. package/patternfly-docs/generated/components/search-input/react.js +263 -0
  120. package/patternfly-docs/generated/components/sidebar/react.js +236 -0
  121. package/patternfly-docs/generated/components/simple-list/react.js +200 -0
  122. package/patternfly-docs/generated/components/skeleton/react-demos.js +44 -0
  123. package/patternfly-docs/generated/components/skeleton/react.js +122 -0
  124. package/patternfly-docs/generated/components/skip-to-content/react.js +73 -0
  125. package/patternfly-docs/generated/components/slider/react.js +309 -0
  126. package/patternfly-docs/generated/components/spinner/react.js +111 -0
  127. package/patternfly-docs/generated/components/switch/react.js +163 -0
  128. package/patternfly-docs/generated/components/table/react-demos.js +355 -0
  129. package/patternfly-docs/generated/components/table/react-deprecated.js +1350 -0
  130. package/patternfly-docs/generated/components/table/react.js +3241 -0
  131. package/patternfly-docs/generated/components/tabs/react-demos.js +108 -0
  132. package/patternfly-docs/generated/components/tabs/react.js +1359 -0
  133. package/patternfly-docs/generated/components/text-input-group/react-demos.js +152 -0
  134. package/patternfly-docs/generated/components/text-input-group/react.js +278 -0
  135. package/patternfly-docs/generated/components/tile/react-deprecated.js +242 -0
  136. package/patternfly-docs/generated/components/timestamp/react.js +283 -0
  137. package/patternfly-docs/generated/components/title/react.js +94 -0
  138. package/patternfly-docs/generated/components/toggle-group/react.js +299 -0
  139. package/patternfly-docs/generated/components/toolbar/react-demos.js +66 -0
  140. package/patternfly-docs/generated/components/toolbar/react.js +932 -0
  141. package/patternfly-docs/generated/components/tooltip/react.js +241 -0
  142. package/patternfly-docs/generated/components/tree-view/react.js +429 -0
  143. package/patternfly-docs/generated/components/truncate/react.js +211 -0
  144. package/patternfly-docs/generated/components/wizard/react-demos.js +87 -0
  145. package/patternfly-docs/generated/components/wizard/react-deprecated.js +788 -0
  146. package/patternfly-docs/generated/components/wizard/react.js +986 -0
  147. package/patternfly-docs/generated/developer-guides/open-ui-automation/react.js +285 -0
  148. package/patternfly-docs/generated/foundations-and-styles/layouts/bullseye/react.js +70 -0
  149. package/patternfly-docs/generated/foundations-and-styles/layouts/flex/react.js +506 -0
  150. package/patternfly-docs/generated/foundations-and-styles/layouts/gallery/react.js +94 -0
  151. package/patternfly-docs/generated/foundations-and-styles/layouts/grid/react.js +272 -0
  152. package/patternfly-docs/generated/foundations-and-styles/layouts/level/react.js +87 -0
  153. package/patternfly-docs/generated/foundations-and-styles/layouts/split/react.js +124 -0
  154. package/patternfly-docs/generated/foundations-and-styles/layouts/stack/react.js +112 -0
  155. package/patternfly-docs/generated/index.js +1769 -0
  156. package/patternfly-docs/generated/patterns/card-view/react-demos.js +78 -0
  157. package/patternfly-docs/generated/patterns/filters/react-demos.js +141 -0
  158. package/patternfly-docs/generated/patterns/password-generator/react-demos.js +51 -0
  159. package/patternfly-docs/generated/patterns/password-strength/react-demos.js +61 -0
  160. package/patternfly-docs/generated/patterns/primary-detail/react-demos.js +124 -0
  161. package/patternfly-docs/generated/patterns/right-to-left/react-demos.js +81 -0
  162. package/LICENSE +0 -21
@@ -0,0 +1,772 @@
1
+ import React from 'react';
2
+ import { AutoLinkHeader, Example, Link as PatternflyThemeLink } from '@patternfly/documentation-framework/components';
3
+ import { Fragment, useMemo, useState } from 'react';
4
+ import {
5
+ DragDrop,
6
+ Draggable,
7
+ Droppable,
8
+ DualListSelector as DLSDeprecated,
9
+ DualListSelectorPane as DLSPaneDeprecated,
10
+ DualListSelectorList as DLSListDeprecated,
11
+ DualListSelectorListItem as DLSListItemDeprecated,
12
+ DualListSelectorControlsWrapper as DLSControlsWrapperDeprecated,
13
+ DualListSelectorControl as DLSControlDeprecated,
14
+ DualListSelectorTree as DLSTreeDeprecated,
15
+ } from '@patternfly/react-core/deprecated';
16
+ import RhMicronsDoubleCaretLeftIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-double-caret-left-icon';
17
+ import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon';
18
+ import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon';
19
+ import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
20
+ import RhMicronsSortDownSmallToLargeIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-sort-down-small-to-large-icon';
21
+ import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
22
+ const pageData = {
23
+ "id": "Dual list selector",
24
+ "section": "components",
25
+ "subsection": "",
26
+ "deprecated": true,
27
+ "template": false,
28
+ "beta": false,
29
+ "demo": false,
30
+ "newImplementationLink": false,
31
+ "source": "react-deprecated",
32
+ "tabName": null,
33
+ "slug": "/components/dual-list-selector/react-deprecated",
34
+ "sourceLink": "https://github.com/patternfly/patternfly-react/blob/main/packages/react-core/src/deprecated/components/DualListSelector/examples/DualListSelector.md",
35
+ "relPath": "packages/react-core/src/deprecated/components/DualListSelector/examples/DualListSelector.md",
36
+ "propComponents": [
37
+ {
38
+ "name": "DualListSelector",
39
+ "description": "Acts as a container for all other DualListSelector sub-components when using a\ncomposable dual list selector.",
40
+ "props": [
41
+ {
42
+ "name": "addAll",
43
+ "type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
44
+ "description": "Optional callback for the dynamically built add all button"
45
+ },
46
+ {
47
+ "name": "addAllAriaLabel",
48
+ "type": "string",
49
+ "description": "Accessible label for the dynamically built add all button",
50
+ "defaultValue": "'Add all'"
51
+ },
52
+ {
53
+ "name": "addAllTooltip",
54
+ "type": "React.ReactNode",
55
+ "description": "Tooltip content for the dynamically built add all button"
56
+ },
57
+ {
58
+ "name": "addAllTooltipProps",
59
+ "type": "any",
60
+ "description": "Additional tooltip properties for the dynamically built add all tooltip"
61
+ },
62
+ {
63
+ "name": "addSelected",
64
+ "type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
65
+ "description": "Optional callback for the dynamically built add selected button"
66
+ },
67
+ {
68
+ "name": "addSelectedAriaLabel",
69
+ "type": "string",
70
+ "description": "Accessible label for the dynamically built add selected button",
71
+ "defaultValue": "'Add selected'"
72
+ },
73
+ {
74
+ "name": "addSelectedTooltip",
75
+ "type": "React.ReactNode",
76
+ "description": "Tooltip content for the dynamically built add selected button"
77
+ },
78
+ {
79
+ "name": "addSelectedTooltipProps",
80
+ "type": "any",
81
+ "description": "Additional tooltip properties for the dynamically built add selected tooltip"
82
+ },
83
+ {
84
+ "name": "availableOptions",
85
+ "type": "React.ReactNode[] | DualListSelectorTreeItemData[]",
86
+ "description": "Options to display in the dynamically built available options pane. When using trees, the options should be in the DualListSelectorTreeItemData[] format.",
87
+ "defaultValue": "[]"
88
+ },
89
+ {
90
+ "name": "availableOptionsActions",
91
+ "type": "React.ReactNode[]",
92
+ "description": "Actions to be displayed above the dynamically built available options pane."
93
+ },
94
+ {
95
+ "name": "availableOptionsSearchAriaLabel",
96
+ "type": "string",
97
+ "description": "Accessible label for the search input on the dynamically built available options pane.",
98
+ "defaultValue": "'Available search input'"
99
+ },
100
+ {
101
+ "name": "availableOptionsStatus",
102
+ "type": "string",
103
+ "description": "Status message to display above the dynamically built available options pane."
104
+ },
105
+ {
106
+ "name": "availableOptionsTitle",
107
+ "type": "string",
108
+ "description": "Title applied to the dynamically built available options pane.",
109
+ "defaultValue": "'Available options'"
110
+ },
111
+ {
112
+ "name": "children",
113
+ "type": "React.ReactNode",
114
+ "description": "Content to be rendered in the dual list selector. Panes & controls will not be built dynamically when children are provided.",
115
+ "defaultValue": "''"
116
+ },
117
+ {
118
+ "name": "chosenOptions",
119
+ "type": "React.ReactNode[] | DualListSelectorTreeItemData[]",
120
+ "description": "Options to display in the dynamically built chosen options pane. When using trees, the options should be in the DualListSelectorTreeItemData[] format.",
121
+ "defaultValue": "[]"
122
+ },
123
+ {
124
+ "name": "chosenOptionsActions",
125
+ "type": "React.ReactNode[]",
126
+ "description": "Actions to be displayed above the dynamically built chosen options pane."
127
+ },
128
+ {
129
+ "name": "chosenOptionsSearchAriaLabel",
130
+ "type": "string",
131
+ "description": "Accessible label for the search input on the dynamically built chosen options pane.",
132
+ "defaultValue": "'Chosen search input'"
133
+ },
134
+ {
135
+ "name": "chosenOptionsStatus",
136
+ "type": "string",
137
+ "description": "Status message to display above the dynamically built chosen options pane."
138
+ },
139
+ {
140
+ "name": "chosenOptionsTitle",
141
+ "type": "string",
142
+ "description": "Title applied to the dynamically built chosen options pane.",
143
+ "defaultValue": "'Chosen options'"
144
+ },
145
+ {
146
+ "name": "className",
147
+ "type": "string",
148
+ "description": "Additional classes applied to the dual list selector."
149
+ },
150
+ {
151
+ "name": "controlsAriaLabel",
152
+ "type": "string",
153
+ "description": "Accessible label for the dynamically built controls between the two panes.",
154
+ "defaultValue": "'Selector controls'"
155
+ },
156
+ {
157
+ "name": "filterOption",
158
+ "type": "(option: React.ReactNode, input: string) => boolean",
159
+ "description": "Optional filter function for custom filtering based on search string. Used with a dynamically built search input."
160
+ },
161
+ {
162
+ "name": "id",
163
+ "type": "string",
164
+ "description": "Id of the dual list selector."
165
+ },
166
+ {
167
+ "name": "isDisabled",
168
+ "type": "boolean",
169
+ "description": "Flag indicating if the dual list selector is in a disabled state",
170
+ "defaultValue": "false"
171
+ },
172
+ {
173
+ "name": "isSearchable",
174
+ "type": "boolean",
175
+ "description": "Flag indicating a search bar should be included above both the dynamically built available and chosen panes."
176
+ },
177
+ {
178
+ "name": "isTree",
179
+ "type": "boolean",
180
+ "description": "Flag indicating if the dual list selector uses trees instead of simple lists",
181
+ "defaultValue": "false"
182
+ },
183
+ {
184
+ "name": "onAvailableOptionsSearchInputChanged",
185
+ "type": "(event: React.FormEvent<HTMLInputElement>, value: string) => void",
186
+ "description": "A callback for when the search input value for the dynamically built available options changes."
187
+ },
188
+ {
189
+ "name": "onChosenOptionsSearchInputChanged",
190
+ "type": "(event: React.FormEvent<HTMLInputElement>, value: string) => void",
191
+ "description": "A callback for when the search input value for the dynamically built chosen options changes."
192
+ },
193
+ {
194
+ "name": "onListChange",
195
+ "type": "(\n event: React.MouseEvent<HTMLElement>,\n newAvailableOptions: React.ReactNode[],\n newChosenOptions: React.ReactNode[]\n) => void",
196
+ "description": "Callback fired every time dynamically built options are chosen or removed"
197
+ },
198
+ {
199
+ "name": "onOptionCheck",
200
+ "type": "(\n event: React.MouseEvent | React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent,\n checked: boolean,\n checkedId: string,\n newCheckedItems: string[]\n) => void",
201
+ "description": "Optional callback fired when a dynamically built option is checked"
202
+ },
203
+ {
204
+ "name": "onOptionSelect",
205
+ "type": "(\n event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent,\n index: number,\n isChosen: boolean,\n id: string,\n itemData: any,\n parentData: any\n) => void",
206
+ "description": "Optional callback fired when a dynamically built option is selected"
207
+ },
208
+ {
209
+ "name": "removeAll",
210
+ "type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
211
+ "description": "Optional callback for the dynamically built remove all button"
212
+ },
213
+ {
214
+ "name": "removeAllAriaLabel",
215
+ "type": "string",
216
+ "description": "Accessible label for the dynamically built remove all button",
217
+ "defaultValue": "'Remove all'"
218
+ },
219
+ {
220
+ "name": "removeAllTooltip",
221
+ "type": "React.ReactNode",
222
+ "description": "Tooltip content for the dynamically built remove all button"
223
+ },
224
+ {
225
+ "name": "removeAllTooltipProps",
226
+ "type": "any",
227
+ "description": "Additional tooltip properties for the dynamically built remove all tooltip"
228
+ },
229
+ {
230
+ "name": "removeSelected",
231
+ "type": "(newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => void",
232
+ "description": "Optional callback for the dynamically built remove selected button"
233
+ },
234
+ {
235
+ "name": "removeSelectedAriaLabel",
236
+ "type": "string",
237
+ "description": "Accessible label for the dynamically built remove selected button",
238
+ "defaultValue": "'Remove selected'"
239
+ },
240
+ {
241
+ "name": "removeSelectedTooltip",
242
+ "type": "React.ReactNode",
243
+ "description": "Tooltip content for the dynamically built remove selected button"
244
+ },
245
+ {
246
+ "name": "removeSelectedTooltipProps",
247
+ "type": "any",
248
+ "description": "Additional tooltip properties for the dynamically built remove selected tooltip"
249
+ }
250
+ ]
251
+ },
252
+ {
253
+ "name": "DualListSelectorPane",
254
+ "description": "Acts as the container for a list of options that are either available or chosen,\ndepending on the pane type (available or chosen). A search input and other actions,\nsuch as sorting, can also be passed into this sub-component.",
255
+ "props": [
256
+ {
257
+ "name": "actions",
258
+ "type": "React.ReactNode[]",
259
+ "description": "Actions to place above the pane."
260
+ },
261
+ {
262
+ "name": "children",
263
+ "type": "React.ReactNode",
264
+ "description": "A dual list selector list or dual list selector tree to be rendered in the pane."
265
+ },
266
+ {
267
+ "name": "className",
268
+ "type": "string",
269
+ "description": "Additional classes applied to the dual list selector pane.",
270
+ "defaultValue": "''"
271
+ },
272
+ {
273
+ "name": "id",
274
+ "type": "string",
275
+ "description": "Id of the pane."
276
+ },
277
+ {
278
+ "name": "isChosen",
279
+ "type": "boolean",
280
+ "description": "Flag indicating if this pane is the chosen pane.",
281
+ "defaultValue": "false"
282
+ },
283
+ {
284
+ "name": "isDisabled",
285
+ "type": "boolean",
286
+ "description": "Flag indicating whether the component is disabled.",
287
+ "defaultValue": "false"
288
+ },
289
+ {
290
+ "name": "listMinHeight",
291
+ "type": "string",
292
+ "description": "Minimum height of the list of options rendered in the pane. *"
293
+ },
294
+ {
295
+ "name": "onSearch",
296
+ "type": "(event: React.ChangeEvent<HTMLInputElement>) => void",
297
+ "description": "Callback for search input. To be used when isSearchable is true."
298
+ },
299
+ {
300
+ "name": "searchInput",
301
+ "type": "React.ReactNode",
302
+ "description": "A search input placed above the list at the top of the pane, before actions."
303
+ },
304
+ {
305
+ "name": "status",
306
+ "type": "string",
307
+ "description": "Status to display above the pane.",
308
+ "defaultValue": "''"
309
+ },
310
+ {
311
+ "name": "title",
312
+ "type": "React.ReactNode",
313
+ "description": "Title of the pane.",
314
+ "defaultValue": "''"
315
+ }
316
+ ]
317
+ },
318
+ {
319
+ "name": "DualListSelectorList",
320
+ "description": "Acts as the container for DualListSelectorListItem sub-components.",
321
+ "props": [
322
+ {
323
+ "name": "children",
324
+ "type": "React.ReactNode",
325
+ "description": "Content rendered inside the dual list selector list"
326
+ }
327
+ ]
328
+ },
329
+ {
330
+ "name": "DualListSelectorListItem",
331
+ "description": "Creates an individual option that can be selected and moved between the\ndual list selector panes. This is contained within the DualListSelectorList sub-component.",
332
+ "props": [
333
+ {
334
+ "name": "children",
335
+ "type": "React.ReactNode",
336
+ "description": "Content rendered inside the dual list selector."
337
+ },
338
+ {
339
+ "name": "className",
340
+ "type": "string",
341
+ "description": "Additional classes applied to the dual list selector."
342
+ },
343
+ {
344
+ "name": "draggableButtonAriaLabel",
345
+ "type": "string",
346
+ "description": "Accessible label for the draggable button on draggable list items"
347
+ },
348
+ {
349
+ "name": "id",
350
+ "type": "string",
351
+ "description": "ID of the option."
352
+ },
353
+ {
354
+ "name": "isDisabled",
355
+ "type": "boolean",
356
+ "description": "Flag indicating if the dual list selector is in a disabled state"
357
+ },
358
+ {
359
+ "name": "isDraggable",
360
+ "type": "boolean",
361
+ "description": "Flag indicating this item is draggable for reordering"
362
+ },
363
+ {
364
+ "name": "isSelected",
365
+ "type": "boolean",
366
+ "description": "Flag indicating the list item is currently selected."
367
+ },
368
+ {
369
+ "name": "onOptionSelect",
370
+ "type": "(event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, id?: string) => void",
371
+ "description": "Callback fired when an option is selected."
372
+ }
373
+ ]
374
+ },
375
+ {
376
+ "name": "DualListSelectorControlsWrapper",
377
+ "description": "Acts as the container for the DualListSelectorControl sub-components.",
378
+ "props": [
379
+ {
380
+ "name": "aria-label",
381
+ "type": "string",
382
+ "description": "Accessible label for the dual list selector controls wrapper."
383
+ },
384
+ {
385
+ "name": "children",
386
+ "type": "React.ReactNode",
387
+ "description": "Anything that can be rendered inside of the wrapper."
388
+ },
389
+ {
390
+ "name": "className",
391
+ "type": "string",
392
+ "description": "Additional classes added to the wrapper."
393
+ }
394
+ ]
395
+ },
396
+ {
397
+ "name": "DualListSelectorControl",
398
+ "description": "Renders an individual control button for moving selected options between each\ndual list selector pane.",
399
+ "props": [
400
+ {
401
+ "name": "aria-label",
402
+ "type": "string",
403
+ "description": "Accessible label for the dual list selector control."
404
+ },
405
+ {
406
+ "name": "children",
407
+ "type": "React.ReactNode",
408
+ "description": "Content to be rendered in the dual list selector control."
409
+ },
410
+ {
411
+ "name": "className",
412
+ "type": "string",
413
+ "description": "Additional classes applied to the dual list selector control."
414
+ },
415
+ {
416
+ "name": "isDisabled",
417
+ "type": "boolean",
418
+ "description": "Flag indicating the control is disabled."
419
+ },
420
+ {
421
+ "name": "onClick",
422
+ "type": "(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void",
423
+ "description": "Callback fired when dual list selector control is selected."
424
+ },
425
+ {
426
+ "name": "tooltipContent",
427
+ "type": "React.ReactNode",
428
+ "description": "Content to be displayed in a tooltip on hover of control."
429
+ },
430
+ {
431
+ "name": "tooltipProps",
432
+ "type": "any",
433
+ "description": "Additional tooltip properties passed to the tooltip."
434
+ }
435
+ ]
436
+ },
437
+ {
438
+ "name": "DualListSelectorTree",
439
+ "description": "Used in place of the DualListSelectorListItem sub-component when building a\ncomposable dual list selector with a tree.",
440
+ "props": [
441
+ {
442
+ "name": "data",
443
+ "type": "DualListSelectorTreeItemData[] | (() => DualListSelectorTreeItemData[])",
444
+ "description": "Data of the tree view",
445
+ "required": true
446
+ },
447
+ {
448
+ "name": "defaultAllExpanded",
449
+ "type": "boolean",
450
+ "description": "Sets the default expanded behavior",
451
+ "defaultValue": "false"
452
+ },
453
+ {
454
+ "name": "hasBadges",
455
+ "type": "boolean",
456
+ "description": "Flag indicating if all options should have badges",
457
+ "defaultValue": "false"
458
+ },
459
+ {
460
+ "name": "id",
461
+ "type": "string",
462
+ "description": "ID of the tree view"
463
+ },
464
+ {
465
+ "name": "isDisabled",
466
+ "type": "boolean",
467
+ "description": "Flag indicating if the dual list selector tree is in the disabled state",
468
+ "defaultValue": "false"
469
+ },
470
+ {
471
+ "name": "onOptionCheck",
472
+ "type": "(\n event: React.MouseEvent | React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent,\n isChecked: boolean,\n itemData: DualListSelectorTreeItemData\n) => void",
473
+ "description": "Callback fired when an option is checked"
474
+ }
475
+ ]
476
+ },
477
+ {
478
+ "name": "DualListSelectorTreeItemData",
479
+ "description": "",
480
+ "props": [
481
+ {
482
+ "name": "badgeProps",
483
+ "type": "any",
484
+ "description": "Additional properties to pass to the option badge"
485
+ },
486
+ {
487
+ "name": "checkProps",
488
+ "type": "any",
489
+ "description": "Additional properties to pass to the option checkbox"
490
+ },
491
+ {
492
+ "name": "children",
493
+ "type": "DualListSelectorTreeItemData[]",
494
+ "description": "Content rendered inside the dual list selector."
495
+ },
496
+ {
497
+ "name": "className",
498
+ "type": "string",
499
+ "description": "Additional classes applied to the dual list selector."
500
+ },
501
+ {
502
+ "name": "defaultExpanded",
503
+ "type": "boolean",
504
+ "description": "Flag indicating this option is expanded by default."
505
+ },
506
+ {
507
+ "name": "hasBadge",
508
+ "type": "boolean",
509
+ "description": "Flag indicating this option has a badge"
510
+ },
511
+ {
512
+ "name": "id",
513
+ "type": "string",
514
+ "description": "ID of the option",
515
+ "required": true
516
+ },
517
+ {
518
+ "name": "isChecked",
519
+ "type": "boolean",
520
+ "description": "Checked state of the option",
521
+ "required": true
522
+ },
523
+ {
524
+ "name": "isDisabled",
525
+ "type": "boolean",
526
+ "description": "Flag indicating whether the component is disabled."
527
+ },
528
+ {
529
+ "name": "onOptionCheck",
530
+ "type": "(\n event: React.MouseEvent | React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent,\n isChecked: boolean,\n isChosen: boolean,\n itemData: DualListSelectorTreeItemData\n ) => void",
531
+ "description": "Callback fired when an option is checked"
532
+ },
533
+ {
534
+ "name": "parentId",
535
+ "type": "string",
536
+ "description": "Parent id of an option"
537
+ },
538
+ {
539
+ "name": "text",
540
+ "type": "string",
541
+ "description": "Text of the option",
542
+ "required": true
543
+ }
544
+ ]
545
+ }
546
+ ],
547
+ "cssPrefix": [
548
+ "pf-v6-c-dual-list-selector"
549
+ ],
550
+ "examples": [
551
+ "Basic",
552
+ "Basic with tooltips",
553
+ "Basic with search",
554
+ "Using more complex options with actions",
555
+ "With tree",
556
+ "Composable dual list selector",
557
+ "Composable with drag and drop",
558
+ "Composable with tree"
559
+ ]
560
+ };
561
+ pageData.liveContext = {
562
+ Fragment,
563
+ useMemo,
564
+ useState,
565
+ DragDrop,
566
+ Draggable,
567
+ Droppable,
568
+ DLSDeprecated,
569
+ DLSPaneDeprecated,
570
+ DLSListDeprecated,
571
+ DLSListItemDeprecated,
572
+ DLSControlsWrapperDeprecated,
573
+ DLSControlDeprecated,
574
+ DLSTreeDeprecated,
575
+ RhMicronsDoubleCaretLeftIcon,
576
+ AngleLeftIcon,
577
+ AngleDoubleRightIcon,
578
+ AngleRightIcon,
579
+ RhMicronsSortDownSmallToLargeIcon,
580
+ SearchIcon
581
+ };
582
+ pageData.examples = {
583
+ 'Basic': props =>
584
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { DualListSelector as DLSDeprecated } from '@patternfly/react-core/deprecated';\n\nexport const DualListSelectorBasic: React.FunctionComponent = () => {\n const [availableOptions, setAvailableOptions] = useState<React.ReactNode[]>([\n 'Option 1',\n 'Option 2',\n 'Option 3',\n 'Option 4'\n ]);\n const [chosenOptions, setChosenOptions] = useState<React.ReactNode[]>([]);\n\n const onListChange = (\n event: React.MouseEvent<HTMLElement>,\n newAvailableOptions: React.ReactNode[],\n newChosenOptions: React.ReactNode[]\n ) => {\n setAvailableOptions(newAvailableOptions.sort());\n setChosenOptions(newChosenOptions.sort());\n };\n\n return (\n <DLSDeprecated\n availableOptions={availableOptions}\n chosenOptions={chosenOptions}\n onListChange={onListChange}\n id=\"dual-list-selector-basic\"\n />\n );\n};\n","title":"Basic","lang":"ts","className":""}}>
585
+
586
+ </Example>,
587
+ 'Basic with tooltips': props =>
588
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { DualListSelector as DLSDeprecated } from '@patternfly/react-core/deprecated';\n\nexport const DualListSelectorBasicTooltips: React.FunctionComponent = () => {\n const [availableOptions, setAvailableOptions] = useState<React.ReactNode[]>([\n 'Option 1',\n 'Option 2',\n 'Option 3',\n 'Option 4'\n ]);\n const [chosenOptions, setChosenOptions] = useState<React.ReactNode[]>([]);\n\n const onListChange = (\n event: React.MouseEvent<HTMLElement>,\n newAvailableOptions: React.ReactNode[],\n newChosenOptions: React.ReactNode[]\n ) => {\n setAvailableOptions(newAvailableOptions.sort());\n setChosenOptions(newChosenOptions.sort());\n };\n\n return (\n <DLSDeprecated\n availableOptions={availableOptions}\n chosenOptions={chosenOptions}\n onListChange={onListChange}\n addAllTooltip=\"Add all options\"\n addAllTooltipProps={{ position: 'top' }}\n addSelectedTooltip=\"Add selected options\"\n addSelectedTooltipProps={{ position: 'right' }}\n removeSelectedTooltip=\"Remove selected options\"\n removeSelectedTooltipProps={{ position: 'left' }}\n removeAllTooltip=\"Remove all options\"\n removeAllTooltipProps={{ position: 'bottom' }}\n id=\"dual-list-selector-basic-tooltips\"\n />\n );\n};\n","title":"Basic with tooltips","lang":"ts","className":""}}>
589
+
590
+ </Example>,
591
+ 'Basic with search': props =>
592
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { DualListSelector as DLSDeprecated } from '@patternfly/react-core/deprecated';\n\nexport const DualListSelectorBasicSearch: React.FunctionComponent = () => {\n const [availableOptions, setAvailableOptions] = useState<React.ReactNode[]>([\n 'Option 1',\n 'Option 2',\n 'Option 3',\n 'Option 4'\n ]);\n const [chosenOptions, setChosenOptions] = useState<React.ReactNode[]>([]);\n\n const onListChange = (\n event: React.MouseEvent<HTMLElement>,\n newAvailableOptions: React.ReactNode[],\n newChosenOptions: React.ReactNode[]\n ) => {\n setAvailableOptions(newAvailableOptions.sort());\n setChosenOptions(newChosenOptions.sort());\n };\n\n return (\n <DLSDeprecated\n isSearchable\n availableOptions={availableOptions}\n chosenOptions={chosenOptions}\n onListChange={onListChange}\n id=\"dual-list-selector-basic-search\"\n />\n );\n};\n","title":"Basic with search","lang":"ts","className":""}}>
593
+
594
+ </Example>,
595
+ 'Using more complex options with actions': props =>
596
+ <Example {...pageData} {...props} {...{"code":"import { Fragment, useState } from 'react';\nimport { Button, ButtonVariant, Checkbox } from '@patternfly/react-core';\nimport { DualListSelector as DLSDeprecated } from '@patternfly/react-core/deprecated';\nimport RhMicronsSortDownSmallToLargeIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-sort-down-small-to-large-icon';\n\nexport const DualListSelectorComplexOptionsActions: React.FunctionComponent = () => {\n const [availableOptions, setAvailableOptions] = useState<React.ReactNode[]>([\n <span key=\"option1\">Option 1</span>,\n <span key=\"option3\">Option 3</span>,\n <span key=\"option4\">Option 4</span>,\n <span key=\"option2\">Option 2</span>\n ]);\n const [chosenOptions, setChosenOptions] = useState<React.ReactNode[]>([]);\n const [isDisabled, setIsDisabled] = useState(false);\n\n const onListChange = (newAvailableOptions: React.ReactNode[], newChosenOptions: React.ReactNode[]) => {\n setAvailableOptions(newAvailableOptions);\n setChosenOptions(newChosenOptions);\n };\n\n const onSort = (pane: string) => {\n const toSort = pane === 'available' ? [...availableOptions] : [...chosenOptions];\n (toSort as React.ReactElement<any>[]).sort((a, b) => {\n if (a.props.children > b.props.children) {\n return 1;\n }\n if (a.props.children < b.props.children) {\n return -1;\n }\n return 0;\n });\n\n if (pane === 'available') {\n setAvailableOptions(toSort);\n } else {\n setChosenOptions(toSort);\n }\n };\n\n const filterOption = (option: React.ReactNode, input: string) =>\n (option as React.ReactElement<any>).props.children.includes(input);\n\n const availableOptionsActions = [\n <Button\n variant={ButtonVariant.plain}\n onClick={() => onSort('available')}\n aria-label=\"Sort available options\"\n key=\"availableSortButton\"\n isDisabled={isDisabled}\n icon={<RhMicronsSortDownSmallToLargeIcon />}\n />\n ];\n\n const chosenOptionsActions = [\n <Button\n variant={ButtonVariant.plain}\n onClick={() => onSort('chosen')}\n aria-label=\"Sort chosen options\"\n key=\"chosenSortButton\"\n isDisabled={isDisabled}\n icon={<RhMicronsSortDownSmallToLargeIcon />}\n />\n ];\n\n return (\n <Fragment>\n <DLSDeprecated\n isSearchable\n availableOptions={availableOptions}\n availableOptionsActions={availableOptionsActions}\n chosenOptions={chosenOptions}\n chosenOptionsActions={chosenOptionsActions}\n addAll={onListChange}\n removeAll={onListChange}\n addSelected={onListChange}\n removeSelected={onListChange}\n filterOption={filterOption}\n isDisabled={isDisabled}\n id=\"dual-list-selector-complex\"\n />\n <Checkbox\n key=\"isDisabled\"\n id=\"isDisabled\"\n label=\"isDisabled\"\n aria-label=\"isDisabled\"\n isChecked={isDisabled}\n onChange={() => setIsDisabled(!isDisabled)}\n />\n </Fragment>\n );\n};\n","title":"Using more complex options with actions","lang":"ts","className":""}}>
597
+
598
+ </Example>,
599
+ 'With tree': props =>
600
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport {\n DualListSelector as DLSDeprecated,\n DualListSelectorTreeItemData as DLSTreeItemDataDeprecated\n} from '@patternfly/react-core/deprecated';\n\nexport const DualListSelectorTreeExample: React.FunctionComponent = () => {\n const [availableOptions, setAvailableOptions] = useState<DLSTreeItemDataDeprecated[]>([\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 const [chosenOptions, setChosenOptions] = useState<DLSTreeItemDataDeprecated[]>([\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\n const onListChange = (\n event: React.MouseEvent<HTMLElement>,\n newAvailableOptions: DLSTreeItemDataDeprecated[],\n newChosenOptions: DLSTreeItemDataDeprecated[]\n ) => {\n setAvailableOptions(newAvailableOptions.sort());\n setChosenOptions(newChosenOptions.sort());\n };\n\n return (\n <DLSDeprecated\n isSearchable\n isTree\n availableOptions={availableOptions}\n chosenOptions={chosenOptions}\n onListChange={onListChange as any}\n id=\"dual-list-selector-tree\"\n />\n );\n};\n","title":"With tree","lang":"ts","className":""}}>
601
+
602
+ </Example>,
603
+ 'Composable dual list selector': props =>
604
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport {\n Button,\n ButtonVariant,\n SearchInput,\n EmptyState,\n EmptyStateVariant,\n EmptyStateFooter,\n EmptyStateBody,\n EmptyStateActions\n} from '@patternfly/react-core';\nimport {\n DualListSelector as DLSDeprecated,\n DualListSelectorPane as DLSPaneDeprecated,\n DualListSelectorList as DLSListDeprecated,\n DualListSelectorListItem as DLSListItemDeprecated,\n DualListSelectorControlsWrapper as DLSControlsWrapperDeprecated,\n DualListSelectorControl as DLSControlDeprecated\n} from '@patternfly/react-core/deprecated';\nimport RhMicronsDoubleCaretLeftIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-double-caret-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 RhMicronsSortDownSmallToLargeIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-sort-down-small-to-large-icon';\nimport SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';\n\ninterface Option {\n text: string;\n selected: boolean;\n isVisible: boolean;\n}\n\nexport const DualListSelectorComposable: React.FunctionComponent = () => {\n const [availableOptions, setAvailableOptions] = useState<Option[]>([\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] = useState<Option[]>([]);\n const [availableFilter, setAvailableFilter] = useState('');\n const [chosenFilter, setChosenFilter] = useState('');\n\n // callback for moving selected options between lists\n const moveSelected = (fromAvailable: boolean) => {\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: boolean) => {\n if (fromAvailable) {\n setChosenOptions([...availableOptions.filter((option) => option.isVisible), ...chosenOptions]);\n setAvailableOptions([...availableOptions.filter((option) => !option.isVisible)]);\n } else {\n setAvailableOptions([...chosenOptions.filter((option) => option.isVisible), ...availableOptions]);\n setChosenOptions([...chosenOptions.filter((option) => !option.isVisible)]);\n }\n };\n\n // callback when option is selected\n const onOptionSelect = (\n event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent,\n index: number,\n isChosen: boolean\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 onFilterChange = (value: string, isAvailable: boolean) => {\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 // builds a search input - used in each dual list selector pane\n const buildSearchInput = (isAvailable: boolean) => (\n <SearchInput\n value={isAvailable ? availableFilter : chosenFilter}\n onChange={(_event, value) => onFilterChange(value, isAvailable)}\n onClear={() => onFilterChange('', isAvailable)}\n />\n );\n\n // builds a sort control - passed to both dual list selector panes\n const buildSort = (isAvailable: boolean) => {\n const onSort = () => {\n const toSort = isAvailable ? [...availableOptions] : [...chosenOptions];\n toSort.sort((a, b) => {\n if (a.text > b.text) {\n return 1;\n }\n if (a.text < b.text) {\n return -1;\n }\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 icon={<RhMicronsSortDownSmallToLargeIcon />}\n />\n );\n };\n\n const buildEmptyState = (isAvailable: boolean) => (\n <EmptyState headingLevel=\"h4\" titleText=\"No results found\" icon={SearchIcon} variant={EmptyStateVariant.sm}>\n <EmptyStateBody>No results match the filter criteria. Clear all filters and try again.</EmptyStateBody>\n <EmptyStateFooter>\n <EmptyStateActions>\n <Button variant=\"link\" onClick={() => onFilterChange('', isAvailable)}>\n Clear all filters\n </Button>\n </EmptyStateActions>\n </EmptyStateFooter>\n </EmptyState>\n );\n\n return (\n <DLSDeprecated>\n <DLSPaneDeprecated\n title=\"Available\"\n status={`${availableOptions.filter((option) => option.selected && option.isVisible).length} of ${\n availableOptions.filter((option) => option.isVisible).length\n } options selected`}\n searchInput={buildSearchInput(true)}\n actions={[buildSort(true)]}\n listMinHeight=\"300px\"\n >\n {availableFilter !== '' &&\n availableOptions.filter((option) => option.isVisible).length === 0 &&\n buildEmptyState(true)}\n {availableOptions.filter((option) => option.isVisible).length > 0 && (\n <DLSListDeprecated>\n {availableOptions.map((option, index) =>\n option.isVisible ? (\n <DLSListItemDeprecated\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 </DLSListItemDeprecated>\n ) : null\n )}\n </DLSListDeprecated>\n )}\n </DLSPaneDeprecated>\n <DLSControlsWrapperDeprecated>\n <DLSControlDeprecated\n isDisabled={!availableOptions.some((option) => option.selected)}\n onClick={() => moveSelected(true)}\n aria-label=\"Add selected\"\n tooltipContent=\"Add selected\"\n >\n <AngleRightIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n isDisabled={availableOptions.length === 0}\n onClick={() => moveAll(true)}\n aria-label=\"Add all\"\n tooltipContent=\"Add all\"\n >\n <AngleDoubleRightIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n isDisabled={chosenOptions.length === 0}\n onClick={() => moveAll(false)}\n aria-label=\"Remove all\"\n tooltipContent=\"Remove all\"\n >\n <RhMicronsDoubleCaretLeftIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n onClick={() => moveSelected(false)}\n isDisabled={!chosenOptions.some((option) => option.selected)}\n aria-label=\"Remove selected\"\n tooltipContent=\"Remove selected\"\n >\n <AngleLeftIcon />\n </DLSControlDeprecated>\n </DLSControlsWrapperDeprecated>\n <DLSPaneDeprecated\n title=\"Chosen\"\n status={`${chosenOptions.filter((option) => option.selected && option.isVisible).length} of ${\n chosenOptions.filter((option) => option.isVisible).length\n } options selected`}\n searchInput={buildSearchInput(false)}\n actions={[buildSort(false)]}\n isChosen\n listMinHeight=\"300px\"\n >\n {chosenFilter !== '' &&\n chosenOptions.filter((option) => option.isVisible).length === 0 &&\n buildEmptyState(false)}\n {chosenOptions.filter((option) => option.isVisible).length > 0 && (\n <DLSListDeprecated>\n {chosenOptions.map((option, index) =>\n option.isVisible ? (\n <DLSListItemDeprecated\n key={index}\n isSelected={option.selected}\n id={`composable-chosen-option-${index}`}\n onOptionSelect={(e) => onOptionSelect(e, index, true)}\n >\n {option.text}\n </DLSListItemDeprecated>\n ) : null\n )}\n </DLSListDeprecated>\n )}\n </DLSPaneDeprecated>\n </DLSDeprecated>\n );\n};\n","title":"Composable dual list selector","lang":"ts","className":""}}>
605
+
606
+ </Example>,
607
+ 'Composable with drag and drop': props =>
608
+ <Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport {\n DragDrop,\n Draggable,\n Droppable,\n DraggableItemPosition,\n DualListSelector as DLSDeprecated,\n DualListSelectorPane as DLSPaneDeprecated,\n DualListSelectorList as DLSListDeprecated,\n DualListSelectorListItem as DLSListItemDeprecated,\n DualListSelectorControlsWrapper as DLSControlsWrapperDeprecated,\n DualListSelectorControl as DLSControlDeprecated\n} from '@patternfly/react-core/deprecated';\nimport RhMicronsDoubleCaretLeftIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-double-caret-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\nexport const DualListSelectorComposableDragDrop: React.FunctionComponent = () => {\n const [ignoreNextOptionSelect, setIgnoreNextOptionSelect] = useState(false);\n const [availableOptions, setAvailableOptions] = 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] = 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: boolean) => {\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: boolean) => {\n if (fromAvailable) {\n setChosenOptions([...availableOptions.filter((option) => option.isVisible), ...chosenOptions]);\n setAvailableOptions([...availableOptions.filter((option) => !option.isVisible)]);\n } else {\n setAvailableOptions([...chosenOptions.filter((option) => option.isVisible), ...availableOptions]);\n setChosenOptions([...chosenOptions.filter((option) => !option.isVisible)]);\n }\n };\n\n const onOptionSelect = (\n event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent,\n index: number,\n isChosen: boolean\n ) => {\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: DraggableItemPosition, dest: DraggableItemPosition | undefined) => {\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 <DLSDeprecated>\n <DLSPaneDeprecated\n title=\"Available\"\n status={`${availableOptions.filter((option) => option.selected && option.isVisible).length} of ${\n availableOptions.filter((option) => option.isVisible).length\n } options selected`}\n >\n <DLSListDeprecated>\n {availableOptions.map((option, index) =>\n option.isVisible ? (\n <DLSListItemDeprecated\n key={index}\n isSelected={option.selected}\n id={`composable-drag-drop-available-option-${index}`}\n onOptionSelect={(e) => onOptionSelect(e, index, false)}\n >\n {option.text}\n </DLSListItemDeprecated>\n ) : null\n )}\n </DLSListDeprecated>\n </DLSPaneDeprecated>\n <DLSControlsWrapperDeprecated>\n <DLSControlDeprecated\n isDisabled={!availableOptions.some((option) => option.selected)}\n onClick={() => moveSelected(true)}\n aria-label=\"Add selected\"\n >\n <AngleRightIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n isDisabled={availableOptions.length === 0}\n onClick={() => moveAll(true)}\n aria-label=\"Add all\"\n >\n <AngleDoubleRightIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n isDisabled={chosenOptions.length === 0}\n onClick={() => moveAll(false)}\n aria-label=\"Remove all\"\n >\n <RhMicronsDoubleCaretLeftIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n onClick={() => moveSelected(false)}\n isDisabled={!chosenOptions.some((option) => option.selected)}\n aria-label=\"Remove selected\"\n >\n <AngleLeftIcon />\n </DLSControlDeprecated>\n </DLSControlsWrapperDeprecated>\n <DragDrop\n onDrag={() => {\n setIgnoreNextOptionSelect(true);\n return true;\n }}\n onDrop={onDrop}\n >\n <DLSPaneDeprecated\n title=\"Chosen\"\n status={`${chosenOptions.filter((option) => option.selected && option.isVisible).length} of ${\n chosenOptions.filter((option) => option.isVisible).length\n } options selected`}\n isChosen\n >\n <Droppable hasNoWrapper>\n <DLSListDeprecated>\n {chosenOptions.map((option, index) =>\n option.isVisible ? (\n <Draggable key={index} hasNoWrapper>\n <DLSListItemDeprecated\n isSelected={option.selected}\n id={`composable-drag-drop-chosen-option-${index}`}\n onOptionSelect={(e) => onOptionSelect(e, index, true)}\n isDraggable\n >\n {option.text}\n </DLSListItemDeprecated>\n </Draggable>\n ) : null\n )}\n </DLSListDeprecated>\n </Droppable>\n </DLSPaneDeprecated>\n </DragDrop>\n </DLSDeprecated>\n );\n};\n","title":"Composable with drag and drop","lang":"ts","isDeprecated":true,"className":""}}>
609
+
610
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
611
+ {`Note: There is a new recommended drag and drop implementation with full keyboard functionality, which replaces this implementation. To adhere to our new recommendations, refer to the `}
612
+
613
+ <PatternflyThemeLink {...{"to":"/components/drag-and-drop/react-demos","className":""}}>
614
+ {`drag and drop demos`}
615
+ </PatternflyThemeLink>
616
+ {`.`}
617
+ </p>
618
+
619
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
620
+ {`This example only allows reordering the contents of the "chosen" pane with drag and drop. To make a pane able to be reordered:`}
621
+ </p>
622
+
623
+ <ul {...{"className":"pf-v6-c-content--ul pf-m-editorial ws-ul "}}>
624
+
625
+
626
+
627
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
628
+ {`wrap the `}
629
+
630
+ <code {...{"className":"ws-code "}}>
631
+ {`DualListSelectorPane`}
632
+ </code>
633
+ {` in a `}
634
+
635
+ <code {...{"className":"ws-code "}}>
636
+ {`DragDrop`}
637
+ </code>
638
+ {` component`}
639
+ </li>
640
+
641
+
642
+
643
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
644
+ {`wrap the `}
645
+
646
+ <code {...{"className":"ws-code "}}>
647
+ {`DualListSelectorList`}
648
+ </code>
649
+ {` in a `}
650
+
651
+ <code {...{"className":"ws-code "}}>
652
+ {`Droppable`}
653
+ </code>
654
+ {` component`}
655
+ </li>
656
+
657
+
658
+
659
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
660
+ {`wrap the `}
661
+
662
+ <code {...{"className":"ws-code "}}>
663
+ {`DualListSelectorListItem`}
664
+ </code>
665
+ {` components in a `}
666
+
667
+ <code {...{"className":"ws-code "}}>
668
+ {`Draggable`}
669
+ </code>
670
+ {` component`}
671
+ </li>
672
+
673
+
674
+
675
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
676
+ {`define an `}
677
+
678
+ <code {...{"className":"ws-code "}}>
679
+ {`onDrop`}
680
+ </code>
681
+ {` callback which reorders the sortable options.`}
682
+
683
+
684
+
685
+ <ul {...{"className":"pf-v6-c-content--ul pf-m-editorial ws-ul "}}>
686
+
687
+
688
+
689
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
690
+ {`The `}
691
+
692
+ <code {...{"className":"ws-code "}}>
693
+ {`onDrop`}
694
+ </code>
695
+ {` function provides the starting location and destination location for a dragged item. It should return
696
+ true to enable the 'drop' animation in the new location and false to enable the 'drop' animation back to the item's
697
+ old position.`}
698
+ </li>
699
+
700
+
701
+
702
+ <li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
703
+ {`define an `}
704
+
705
+ <code {...{"className":"ws-code "}}>
706
+ {`onDrag`}
707
+ </code>
708
+ {` callback which ensures that the drag event will not cross hairs with the `}
709
+
710
+ <code {...{"className":"ws-code "}}>
711
+ {`onOptionSelect`}
712
+ </code>
713
+ {` click
714
+ event set on the option. Note: the `}
715
+
716
+ <code {...{"className":"ws-code "}}>
717
+ {`ignoreNextOptionSelect`}
718
+ </code>
719
+ {` state value is used to prevent selection while dragging.`}
720
+ </li>
721
+
722
+
723
+ </ul>
724
+
725
+
726
+ </li>
727
+
728
+
729
+ </ul>
730
+
731
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
732
+ {`Keyboard and screen reader accessibility for the `}
733
+
734
+ <code {...{"className":"ws-code "}}>
735
+ {`<DragDrop>`}
736
+ </code>
737
+ {` component is still in development.`}
738
+ </p>
739
+ </Example>,
740
+ 'Composable with tree': props =>
741
+ <Example {...pageData} {...props} {...{"code":"import { useMemo, useState } from 'react';\nimport {\n SearchInput,\n Button,\n EmptyState,\n EmptyStateVariant,\n EmptyStateFooter,\n EmptyStateBody,\n EmptyStateActions\n} from '@patternfly/react-core';\nimport {\n DualListSelector as DLSDeprecated,\n DualListSelectorPane as DLSPaneDeprecated,\n DualListSelectorList as DLSListDeprecated,\n DualListSelectorControlsWrapper as DLSControlsWrapperDeprecated,\n DualListSelectorControl as DLSControlDeprecated,\n DualListSelectorTree as DLSTreeDeprecated,\n DualListSelectorTreeItemData as DLSTreeItemDataDeprecated\n} from '@patternfly/react-core/deprecated';\nimport RhMicronsDoubleCaretLeftIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-double-caret-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 SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';\n\ninterface FoodNode {\n id: string;\n text: string;\n children?: FoodNode[];\n}\n\ninterface ExampleProps {\n data: FoodNode[];\n}\n\nexport const DualListSelectorComposableTree: React.FunctionComponent<ExampleProps> = ({ data }: ExampleProps) => {\n const [checkedLeafIds, setCheckedLeafIds] = useState<string[]>([]);\n const [chosenLeafIds, setChosenLeafIds] = useState<string[]>(['beans', 'beef', 'chicken', 'tofu']);\n const [chosenFilter, setChosenFilter] = useState<string>('');\n const [availableFilter, setAvailableFilter] = useState<string>('');\n let hiddenChosen: string[] = [];\n let hiddenAvailable: string[] = [];\n\n // helper function to build memoized lists\n const buildTextById = (node: FoodNode): { [key: string]: string } => {\n let textById = {};\n if (!node) {\n return textById;\n }\n textById[node.id] = node.text;\n if (node.children) {\n node.children.forEach((child) => {\n textById = { ...textById, ...buildTextById(child) };\n });\n }\n return textById;\n };\n\n // helper function to build memoized lists\n const getDescendantLeafIds = (node: FoodNode): string[] => {\n if (!node.children || !node.children.length) {\n return [node.id];\n } else {\n let childrenIds: string[] = [];\n node.children.forEach((child) => {\n childrenIds = [...childrenIds, ...getDescendantLeafIds(child)];\n });\n return childrenIds;\n }\n };\n\n // helper function to build memoized lists\n const getLeavesById = (node: FoodNode): { [key: string]: string[] } => {\n let leavesById = {};\n if (!node.children || !node.children.length) {\n leavesById[node.id] = [node.id];\n } else {\n node.children.forEach((child) => {\n leavesById[node.id] = getDescendantLeafIds(node);\n leavesById = { ...leavesById, ...getLeavesById(child) };\n });\n }\n return leavesById;\n };\n\n // Builds a map of child leaf nodes by node id - memoized so that it only rebuilds the list if the data changes.\n const { memoizedLeavesById, memoizedAllLeaves, memoizedNodeText } = useMemo(() => {\n let leavesById = {};\n let allLeaves: string[] = [];\n let nodeTexts = {};\n data.forEach((foodNode) => {\n nodeTexts = { ...nodeTexts, ...buildTextById(foodNode) };\n leavesById = { ...leavesById, ...getLeavesById(foodNode) };\n allLeaves = [...allLeaves, ...getDescendantLeafIds(foodNode)];\n });\n return {\n memoizedLeavesById: leavesById,\n memoizedAllLeaves: allLeaves,\n memoizedNodeText: nodeTexts\n };\n }, [data]);\n\n const moveChecked = (toChosen: boolean) => {\n setChosenLeafIds(\n (prevChosenIds) =>\n toChosen\n ? [...prevChosenIds, ...checkedLeafIds] // add checked ids to chosen list\n : [...prevChosenIds.filter((x) => !checkedLeafIds.includes(x))] // remove checked ids from chosen list\n );\n\n // uncheck checked ids that just moved\n setCheckedLeafIds((prevChecked) =>\n toChosen\n ? [...prevChecked.filter((x) => chosenLeafIds.includes(x))]\n : [...prevChecked.filter((x) => !chosenLeafIds.includes(x))]\n );\n };\n\n const moveAll = (toChosen: boolean) => {\n if (toChosen) {\n setChosenLeafIds(memoizedAllLeaves);\n } else {\n setChosenLeafIds([]);\n }\n };\n\n const areAllDescendantsSelected = (node: FoodNode, isChosen: boolean) =>\n memoizedLeavesById[node.id].every(\n (id) => checkedLeafIds.includes(id) && (isChosen ? chosenLeafIds.includes(id) : !chosenLeafIds.includes(id))\n );\n const areSomeDescendantsSelected = (node: FoodNode, isChosen: boolean) =>\n memoizedLeavesById[node.id].some(\n (id) => checkedLeafIds.includes(id) && (isChosen ? chosenLeafIds.includes(id) : !chosenLeafIds.includes(id))\n );\n\n const isNodeChecked = (node: FoodNode, isChosen: boolean) => {\n if (areAllDescendantsSelected(node, isChosen)) {\n return true;\n }\n if (areSomeDescendantsSelected(node, isChosen)) {\n return false;\n }\n return false;\n };\n\n const onOptionCheck = (\n event: React.MouseEvent | React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent,\n isChecked: boolean,\n node: DLSTreeItemDataDeprecated,\n isChosen: boolean\n ) => {\n const nodeIdsToCheck = memoizedLeavesById[node.id].filter((id) =>\n isChosen\n ? chosenLeafIds.includes(id) && !hiddenChosen.includes(id)\n : !chosenLeafIds.includes(id) && !hiddenAvailable.includes(id)\n );\n if (isChosen) {\n hiddenChosen = [];\n } else {\n hiddenAvailable = [];\n }\n setCheckedLeafIds((prevChecked) => {\n const otherCheckedNodeNames = prevChecked.filter((id) => !nodeIdsToCheck.includes(id));\n return !isChecked ? otherCheckedNodeNames : [...otherCheckedNodeNames, ...nodeIdsToCheck];\n });\n };\n\n // builds a search input - used in each dual list selector pane\n const buildSearchInput = (isChosen: boolean) => {\n const onChange = (value) => (isChosen ? setChosenFilter(value) : setAvailableFilter(value));\n\n return (\n <SearchInput\n value={isChosen ? chosenFilter : availableFilter}\n onChange={(_event, value) => onChange(value)}\n onClear={() => onChange('')}\n />\n );\n };\n\n // Builds the DualListSelectorTreeItems from the FoodNodes\n const buildOptions = (\n isChosen: boolean,\n [node, ...remainingNodes]: FoodNode[],\n hasParentMatch: boolean\n ): DLSTreeItemDataDeprecated[] => {\n if (!node) {\n return [];\n }\n\n const isChecked = isNodeChecked(node, isChosen);\n\n const filterValue = isChosen ? chosenFilter : availableFilter;\n const descendentLeafIds = memoizedLeavesById[node.id];\n const descendentsOnThisPane = isChosen\n ? descendentLeafIds.filter((id) => chosenLeafIds.includes(id))\n : descendentLeafIds.filter((id) => !chosenLeafIds.includes(id));\n\n const hasMatchingChildren =\n filterValue && descendentsOnThisPane.some((id) => memoizedNodeText[id].includes(filterValue));\n const isFilterMatch = filterValue && node.text.includes(filterValue) && descendentsOnThisPane.length > 0;\n\n // A node is displayed if either of the following is true:\n // - There is no filter value and this node or its descendents belong on this pane\n // - There is a filter value and this node or one of this node's descendents or ancestors match on this pane\n const isDisplayed =\n (!filterValue && descendentsOnThisPane.length > 0) ||\n hasMatchingChildren ||\n (hasParentMatch && descendentsOnThisPane.length > 0) ||\n isFilterMatch;\n\n if (!isDisplayed) {\n if (isChosen) {\n hiddenChosen.push(node.id);\n } else {\n hiddenAvailable.push(node.id);\n }\n }\n\n return [\n ...(isDisplayed\n ? [\n {\n id: node.id,\n text: node.text,\n isChecked,\n checkProps: { 'aria-label': `Select ${node.text}` },\n hasBadge: node.children && node.children.length > 0,\n badgeProps: { isRead: true },\n defaultExpanded: isChosen ? !!chosenFilter : !!availableFilter,\n children: node.children\n ? buildOptions(isChosen, node.children, isFilterMatch || hasParentMatch)\n : undefined\n }\n ]\n : []),\n ...(!isDisplayed && node.children && node.children.length\n ? buildOptions(isChosen, node.children, hasParentMatch)\n : []),\n ...(remainingNodes ? buildOptions(isChosen, remainingNodes, hasParentMatch) : [])\n ];\n };\n\n const buildPane = (isChosen: boolean): React.ReactNode => {\n const options: DLSTreeItemDataDeprecated[] = buildOptions(isChosen, data, false);\n const numOptions = isChosen ? chosenLeafIds.length : memoizedAllLeaves.length - chosenLeafIds.length;\n const numSelected = checkedLeafIds.filter((id) =>\n isChosen ? chosenLeafIds.includes(id) : !chosenLeafIds.includes(id)\n ).length;\n const status = `${numSelected} of ${numOptions} options selected`;\n const filterApplied = isChosen ? chosenFilter !== '' : availableFilter !== '';\n return (\n <DLSPaneDeprecated\n title={isChosen ? 'Chosen' : 'Available'}\n status={status}\n searchInput={buildSearchInput(isChosen)}\n isChosen={isChosen}\n listMinHeight=\"300px\"\n >\n {filterApplied && options.length === 0 && (\n <EmptyState headingLevel=\"h4\" titleText=\"No results found\" icon={SearchIcon} variant={EmptyStateVariant.sm}>\n <EmptyStateBody>No results match the filter criteria. Clear all filters and try again.</EmptyStateBody>\n <EmptyStateFooter>\n <EmptyStateActions>\n <Button variant=\"link\" onClick={() => (isChosen ? setChosenFilter('') : setAvailableFilter(''))}>\n Clear all filters\n </Button>\n </EmptyStateActions>\n </EmptyStateFooter>\n </EmptyState>\n )}\n {options.length > 0 && (\n <DLSListDeprecated>\n <DLSTreeDeprecated\n data={options}\n onOptionCheck={(e, isChecked, itemData) => onOptionCheck(e, isChecked, itemData, isChosen)}\n />\n </DLSListDeprecated>\n )}\n </DLSPaneDeprecated>\n );\n };\n\n return (\n <DLSDeprecated isTree>\n {buildPane(false)}\n <DLSControlsWrapperDeprecated>\n <DLSControlDeprecated\n isDisabled={!checkedLeafIds.filter((x) => !chosenLeafIds.includes(x)).length}\n onClick={() => moveChecked(true)}\n aria-label=\"Add selected\"\n >\n <AngleRightIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n isDisabled={chosenLeafIds.length === memoizedAllLeaves.length}\n onClick={() => moveAll(true)}\n aria-label=\"Add all\"\n >\n <AngleDoubleRightIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n isDisabled={chosenLeafIds.length === 0}\n onClick={() => moveAll(false)}\n aria-label=\"Remove all\"\n >\n <RhMicronsDoubleCaretLeftIcon />\n </DLSControlDeprecated>\n <DLSControlDeprecated\n onClick={() => moveChecked(false)}\n isDisabled={!checkedLeafIds.filter((x) => !!chosenLeafIds.includes(x)).length}\n aria-label=\"Remove selected\"\n >\n <AngleLeftIcon />\n </DLSControlDeprecated>\n </DLSControlsWrapperDeprecated>\n {buildPane(true)}\n </DLSDeprecated>\n );\n};\n\nexport const DualListSelectorComposableTreeExample: React.FunctionComponent = () => (\n <DualListSelectorComposableTree\n data={[\n {\n id: 'fruits',\n text: 'Fruits',\n children: [\n { id: 'apple', text: 'Apple' },\n {\n id: 'berries',\n text: 'Berries',\n children: [\n { id: 'blueberry', text: 'Blueberry' },\n { id: 'strawberry', text: 'Strawberry' }\n ]\n },\n { id: 'banana', text: 'Banana' }\n ]\n },\n { id: 'bread', text: 'Bread' },\n {\n id: 'vegetables',\n text: 'Vegetables',\n children: [\n { id: 'broccoli', text: 'Broccoli' },\n { id: 'cauliflower', text: 'Cauliflower' }\n ]\n },\n {\n id: 'proteins',\n text: 'Proteins',\n children: [\n { id: 'beans', text: 'Beans' },\n {\n id: 'meats',\n text: 'Meats',\n children: [\n {\n id: 'beef',\n text: 'Beef'\n },\n {\n id: 'chicken',\n text: 'Chicken'\n }\n ]\n },\n { id: 'tofu', text: 'Tofu' }\n ]\n }\n ]}\n />\n);\n","title":"Composable with tree","lang":"ts","className":""}}>
742
+
743
+ </Example>
744
+ };
745
+
746
+ const Component = () => (
747
+ <React.Fragment>
748
+ <AutoLinkHeader {...{"id":"examples","headingLevel":"h2","className":"ws-title ws-h2"}}>
749
+ {`Examples`}
750
+ </AutoLinkHeader>
751
+ {React.createElement(pageData.examples["Basic"])}
752
+ {React.createElement(pageData.examples["Basic with tooltips"])}
753
+ {React.createElement(pageData.examples["Basic with search"])}
754
+ {React.createElement(pageData.examples["Using more complex options with actions"])}
755
+ {React.createElement(pageData.examples["With tree"])}
756
+ <AutoLinkHeader {...{"id":"composable-structure","headingLevel":"h2","className":"ws-title ws-h2"}}>
757
+ {`Composable structure`}
758
+ </AutoLinkHeader>
759
+ <p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
760
+ {`The dual list selector can also be built in a composable manner to make customization easier. The standard sub-component relationships are arranged as follows:`}
761
+ </p>
762
+ <Example {...{"code":"<DualListSelector>\n <DualListSelectorPane>\n <DualListSelectorList>\n <DualListSelectorListItem />\n </DualListSelectorList>\n </DualListSelectorPane>\n\n <DualListSelectorControlsWrapper>\n <DualListSelectorControl /> /* A standard Dual list selector has 4 controls */\n </DualListSelectorControlsWrapper>\n\n <DualListSelectorPane isChosen>\n <DualListSelectorList>\n <DualListSelectorListItem />\n </DualListSelectorList>\n </DualListSelectorPane>\n</DualListSelector>","lang":"noLive","className":""}}>
763
+ </Example>
764
+ {React.createElement(pageData.examples["Composable dual list selector"])}
765
+ {React.createElement(pageData.examples["Composable with drag and drop"])}
766
+ {React.createElement(pageData.examples["Composable with tree"])}
767
+ </React.Fragment>
768
+ );
769
+ Component.displayName = 'ComponentsDualListSelectorReactDeprecatedDocs';
770
+ Component.pageData = pageData;
771
+
772
+ export default Component;