Skip to content

Commit 26b5d56

Browse files
rvsiaHyperkid123
authored andcommitted
fix(blueprint): add dual list
1 parent 823640a commit 26b5d56

File tree

5 files changed

+376
-21
lines changed

5 files changed

+376
-21
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { componentTypes } from '@data-driven-forms/react-form-renderer';
2+
3+
export default {
4+
fields: [
5+
{
6+
component: componentTypes.DUAL_LIST_SELECT,
7+
name: 'dual-list-select',
8+
label: 'choose favorite animal',
9+
options: [
10+
{
11+
value: 'cats',
12+
label: 'cats'
13+
},
14+
{
15+
value: 'cats_1',
16+
label: 'cats_1'
17+
},
18+
{
19+
value: 'cats_2',
20+
label: 'cats_2'
21+
},
22+
{
23+
value: 'zebras',
24+
label: 'zebras'
25+
},
26+
{
27+
value: 'pigeons',
28+
label: 'pigeons'
29+
}
30+
]
31+
}
32+
]
33+
};

packages/blueprint-component-mapper/demo/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ import {
1515
} from './demo-schemas/wizard-schema';
1616
import sandboxSchema from './demo-schemas/sandbox';
1717
import demoSchema from '@data-driven-forms/common/src/demoschema';
18+
import dualListSchema from './demo-schemas/dual-list-schema';
1819

1920
const Summary = (props) => <div>Custom summary component.</div>;
2021

2122
const fieldArrayState = {
22-
schema: arraySchemaDDF,
23+
schema: dualListSchema,
2324
additionalOptions: {
2425
initialValues: {
2526
number: [1, 2, 3, 4],
@@ -46,6 +47,7 @@ class App extends React.Component {
4647
<Button onClick={() => this.setState((state) => fieldArrayState)}>arraySchema</Button>
4748
<Button onClick={() => this.setState((state) => ({ schema: sandboxSchema, additionalOptions: {} }))}>Sandbox</Button>
4849
<Button onClick={() => this.setState((state) => ({ schema: demoSchema, additionalOptions: {} }))}>Super schema</Button>
50+
<Button onClick={() => this.setState((state) => ({ schema: dualListSchema, additionalOptions: {} }))}>Dual list</Button>
4951
<FormRenderer
5052
onSubmit={console.log}
5153
componentMapper={{
Lines changed: 301 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,304 @@
1-
const DualListSelect = (props) => {
2-
return 'DualListSelect';
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import DualListSelectCommon from '@data-driven-forms/common/src/dual-list-select';
5+
import { Menu, MenuItem, Classes, ButtonGroup, Button, ControlGroup, InputGroup } from '@blueprintjs/core';
6+
import clsx from 'clsx';
7+
8+
import { FormGroupInternal } from './form-group';
9+
10+
import './dual-list-select.scss';
11+
12+
const List = ({ value, optionClick, noOptionsTitle, filterValue, filterValueText, selectedValues, MenuProps, MenuItemProps }) => (
13+
<Menu {...MenuProps} className={clsx(Classes.ELEVATION_1, 'ddorg__blueprint_mapper--dls-menu', MenuProps.className)}>
14+
{value.length < 1 && <MenuItem text={filterValue ? filterValueText : noOptionsTitle} disabled {...MenuItemProps} />}
15+
{value.length > 0 &&
16+
value.map(({ value, label, MenuItemProps: ItemMenuItemProps }) => (
17+
<MenuItem
18+
onClick={(e) => optionClick(e, value)}
19+
key={value}
20+
active={selectedValues.includes(value)}
21+
text={label}
22+
{...MenuItemProps}
23+
{...ItemMenuItemProps}
24+
/>
25+
))}
26+
</Menu>
27+
);
28+
29+
List.propTypes = {
30+
value: PropTypes.arrayOf(
31+
PropTypes.shape({
32+
value: PropTypes.string.isRequired,
33+
label: PropTypes.string.isRequired
34+
})
35+
),
36+
optionClick: PropTypes.func.isRequired,
37+
noOptionsTitle: PropTypes.node,
38+
filterValue: PropTypes.string,
39+
filterValueText: PropTypes.node,
40+
selectedValues: PropTypes.array,
41+
checkboxVariant: PropTypes.bool,
42+
MenuProps: PropTypes.object,
43+
MenuItemProps: PropTypes.object
44+
};
45+
46+
List.defaultProps = {
47+
value: [],
48+
MenuProps: {},
49+
MenuItemProps: {}
50+
};
51+
52+
const Toolbar = ({ sortTitle, onFilter, onSort, sortDirection, value, placeholder, ControlGroupProps, InputGroupProps, ButtonProps }) => (
53+
<ControlGroup {...ControlGroupProps}>
54+
<InputGroup placeholder={placeholder} onChange={(e) => onFilter(e.target.value)} value={value} {...InputGroupProps} />
55+
<Button icon={sortDirection ? 'sort-desc' : 'sort-asc'} title={sortTitle} onClick={onSort} {...ButtonProps} />
56+
</ControlGroup>
57+
);
58+
59+
Toolbar.propTypes = {
60+
sortTitle: PropTypes.node,
61+
onFilter: PropTypes.func.isRequired,
62+
onSort: PropTypes.func.isRequired,
63+
sortDirection: PropTypes.bool,
64+
value: PropTypes.string,
65+
placeholder: PropTypes.string,
66+
ControlGroupProps: PropTypes.object,
67+
InputGroupProps: PropTypes.object,
68+
ButtonProps: PropTypes.object
369
};
470

71+
Toolbar.defaultProps = {
72+
ControlGroupProps: {},
73+
InputGroupProps: {},
74+
ButtonProps: {}
75+
};
76+
77+
const DualListInternal = ({
78+
allToRight,
79+
allToLeft,
80+
leftTitle,
81+
moveAllLeftTitle,
82+
moveAllRightTitle,
83+
moveRightTitle,
84+
moveLeftTitle,
85+
rightTitle,
86+
noValueTitle,
87+
noOptionsTitle,
88+
filterOptionsTitle,
89+
filterValueTitle,
90+
filterValueText,
91+
filterOptionsText,
92+
state,
93+
sortOptions,
94+
filterOptions,
95+
handleOptionsClick,
96+
leftValues,
97+
handleMoveRight,
98+
handleMoveLeft,
99+
handleClearLeftValues,
100+
handleClearRightValues,
101+
sortValues,
102+
filterValues,
103+
rightValues,
104+
handleValuesClick,
105+
WrapperProps,
106+
LeftWrapperProps,
107+
RightWrapperProps,
108+
ButtonGroupProps,
109+
ToRightButtonProps,
110+
AllToRightButtonProps,
111+
AllToLeftButtonProps,
112+
ToLeftButtonProps,
113+
LeftControlGroupProps,
114+
LeftInputGroupProps,
115+
LeftButtonProps,
116+
RightControlGroupProps,
117+
RightInputGroupProps,
118+
RightButtonProps,
119+
LeftMenuProps,
120+
LeftMenuItemProps,
121+
RightMenuProps,
122+
RightMenuItemProps
123+
}) => {
124+
return (
125+
<div {...WrapperProps} className={clsx('ddorg__blueprint_mapper--dls-wrapper', WrapperProps.className)}>
126+
<div {...LeftWrapperProps}>
127+
{leftTitle}
128+
<Toolbar
129+
sortDirection={state.sortLeftDesc}
130+
onSort={sortOptions}
131+
onFilter={filterOptions}
132+
value={state.filterOptions}
133+
placeholder={filterOptionsTitle}
134+
ControlGroupProps={LeftControlGroupProps}
135+
InputGroupProps={LeftInputGroupProps}
136+
ButtonProps={LeftButtonProps}
137+
/>
138+
<List
139+
optionClick={handleOptionsClick}
140+
value={leftValues}
141+
noOptionsTitle={noOptionsTitle}
142+
filterValue={state.filterOptions}
143+
filterValueText={filterOptionsText}
144+
selectedValues={state.selectedLeftValues}
145+
MenuProps={LeftMenuProps}
146+
MenuItemProps={LeftMenuItemProps}
147+
/>
148+
</div>
149+
<ButtonGroup
150+
vertical
151+
alignText="center"
152+
{...ButtonGroupProps}
153+
className={clsx('ddorg__blueprint_mapper--dls-button-group', ButtonGroupProps.className)}
154+
>
155+
<Button
156+
disabled={state.selectedLeftValues.length === 0}
157+
onClick={handleMoveRight}
158+
title={moveRightTitle}
159+
icon="chevron-right"
160+
{...ToRightButtonProps}
161+
/>
162+
{allToRight && (
163+
<Button
164+
disabled={leftValues.length === 0}
165+
onClick={handleClearLeftValues}
166+
title={moveAllRightTitle}
167+
icon="double-chevron-right"
168+
{...AllToRightButtonProps}
169+
/>
170+
)}
171+
{allToLeft && (
172+
<Button
173+
disabled={rightValues.length === 0}
174+
onClick={handleClearRightValues}
175+
title={moveAllLeftTitle}
176+
icon="double-chevron-left"
177+
{...AllToLeftButtonProps}
178+
/>
179+
)}
180+
<Button
181+
disabled={state.selectedRightValues.length === 0}
182+
onClick={handleMoveLeft}
183+
title={moveLeftTitle}
184+
icon="chevron-left"
185+
{...ToLeftButtonProps}
186+
/>
187+
</ButtonGroup>
188+
<div {...RightWrapperProps}>
189+
{rightTitle}
190+
<Toolbar
191+
sortDirection={state.sortRightDesc}
192+
onSort={sortValues}
193+
onFilter={filterValues}
194+
value={state.filterValue}
195+
placeholder={filterValueTitle}
196+
ControlGroupProps={RightControlGroupProps}
197+
InputGroupProps={RightInputGroupProps}
198+
ButtonProps={RightButtonProps}
199+
/>
200+
<List
201+
optionClick={handleValuesClick}
202+
value={rightValues}
203+
noOptionsTitle={noValueTitle}
204+
filterValue={state.filterValue}
205+
filterValueText={filterValueText}
206+
selectedValues={state.selectedRightValues}
207+
MenuProps={RightMenuProps}
208+
MenuItemProps={RightMenuItemProps}
209+
/>
210+
</div>
211+
</div>
212+
);
213+
};
214+
215+
DualListInternal.propTypes = {
216+
leftTitle: PropTypes.node,
217+
rightTitle: PropTypes.node,
218+
moveLeftTitle: PropTypes.node,
219+
moveRightTitle: PropTypes.node,
220+
allToLeft: PropTypes.bool,
221+
allToRight: PropTypes.bool,
222+
validateOnMount: PropTypes.bool,
223+
moveAllLeftTitle: PropTypes.node,
224+
moveAllRightTitle: PropTypes.node,
225+
noValueTitle: PropTypes.node,
226+
noOptionsTitle: PropTypes.node,
227+
filterOptionsTitle: PropTypes.node,
228+
filterValueTitle: PropTypes.node,
229+
filterValueText: PropTypes.node,
230+
filterOptionsText: PropTypes.node,
231+
state: PropTypes.object,
232+
sortOptions: PropTypes.func,
233+
filterOptions: PropTypes.func,
234+
handleOptionsClick: PropTypes.func,
235+
leftValues: PropTypes.array,
236+
handleMoveRight: PropTypes.func,
237+
handleMoveLeft: PropTypes.func,
238+
handleClearLeftValues: PropTypes.func,
239+
handleClearRightValues: PropTypes.func,
240+
sortValues: PropTypes.func,
241+
filterValues: PropTypes.func,
242+
rightValues: PropTypes.array,
243+
handleValuesClick: PropTypes.func,
244+
FormFieldGridProps: PropTypes.object,
245+
WrapperProps: PropTypes.object,
246+
LeftWrapperProps: PropTypes.object,
247+
RightWrapperProps: PropTypes.object,
248+
ButtonGroupProps: PropTypes.object,
249+
ToRightButtonProps: PropTypes.object,
250+
AllToRightButtonProps: PropTypes.object,
251+
AllToLeftButtonProps: PropTypes.object,
252+
ToLeftButtonProps: PropTypes.object,
253+
LeftControlGroupProps: PropTypes.object,
254+
LeftInputGroupProps: PropTypes.object,
255+
LeftButtonProps: PropTypes.object,
256+
RightControlGroupProps: PropTypes.object,
257+
RightInputGroupProps: PropTypes.object,
258+
RightButtonProps: PropTypes.object,
259+
LeftMenuProps: PropTypes.object,
260+
LeftMenuItemProps: PropTypes.object,
261+
RightMenuProps: PropTypes.object,
262+
RightMenuItemProps: PropTypes.object
263+
};
264+
265+
DualListInternal.defaultProps = {
266+
leftTitle: 'Options',
267+
rightTitle: 'Selected',
268+
moveLeftTitle: 'Move selected to left',
269+
moveRightTitle: 'Move selected to right',
270+
moveAllRightTitle: 'Move all to right',
271+
moveAllLeftTitle: 'Move all to left',
272+
noOptionsTitle: 'No available options',
273+
noValueTitle: 'No selected',
274+
filterOptionsTitle: 'Filter options',
275+
filterValueTitle: 'Filter selected value',
276+
filterOptionsText: 'Remove your filter to see all options',
277+
filterValueText: 'Remove your filter to see all selected',
278+
options: [],
279+
allToLeft: true,
280+
allToRight: true,
281+
WrapperProps: {},
282+
LeftWrapperProps: {},
283+
RightWrapperProps: {},
284+
ButtonGroupProps: {},
285+
ToRightButtonProps: {},
286+
AllToRightButtonProps: {},
287+
AllToLeftButtonProps: {},
288+
ToLeftButtonProps: {},
289+
LeftControlGroupProps: {},
290+
LeftInputGroupProps: {},
291+
LeftButtonProps: {},
292+
RightControlGroupProps: {},
293+
RightInputGroupProps: {},
294+
RightButtonProps: {},
295+
LeftMenuProps: {},
296+
LeftMenuItemProps: {},
297+
RightMenuProps: {},
298+
RightMenuItemProps: {}
299+
};
300+
301+
const DualListWrapper = (props) => <FormGroupInternal {...props} Component={DualListInternal} />;
302+
const DualListSelect = (props) => <DualListSelectCommon {...props} DualListSelect={DualListWrapper} />;
303+
5304
export default DualListSelect;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.ddorg__blueprint_mapper--dls-wrapper {
2+
display: flex;
3+
justify-content: space-evenly;
4+
min-height: 250px;
5+
}
6+
7+
.ddorg__blueprint_mapper--dls-button-group {
8+
justify-content: center;
9+
}
10+
11+
.ddorg__blueprint_mapper--dls-menu {
12+
height: 80%;
13+
overflow: auto;
14+
}

0 commit comments

Comments
 (0)