@woosmap/ui 3.119.0 → 3.120.0
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/package.json +1 -1
- package/src/components/DynamicTag/DynamicTag.js +43 -19
- package/src/components/DynamicTag/DynamicTag.stories.js +47 -0
- package/src/components/DynamicTag/DynamicTag.test.js +45 -1
- package/src/components/Select/Select.js +15 -2
- package/src/styles/console/select.styl +12 -1
- package/src/components/DynamicTag/DynalicTag.stories.js +0 -17
package/package.json
CHANGED
|
@@ -5,14 +5,15 @@ import Input from '../Input/Input';
|
|
|
5
5
|
import Button from '../Button/Button';
|
|
6
6
|
import Label from '../Label/Label';
|
|
7
7
|
import { tr } from '../utils/locale';
|
|
8
|
+
import Select from '../Select/Select';
|
|
8
9
|
|
|
9
10
|
export default class DynamicTag extends Component {
|
|
10
11
|
constructor(props) {
|
|
11
12
|
super(props);
|
|
12
|
-
const { defaultTags } = props;
|
|
13
|
+
const { defaultTags, isSelector } = props;
|
|
13
14
|
this.state = {
|
|
14
15
|
inputValue: '',
|
|
15
|
-
tags: defaultTags,
|
|
16
|
+
tags: isSelector ? defaultTags.map((tag) => tag.value) : defaultTags,
|
|
16
17
|
error: null,
|
|
17
18
|
};
|
|
18
19
|
}
|
|
@@ -43,6 +44,10 @@ export default class DynamicTag extends Component {
|
|
|
43
44
|
});
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
handleChange = (tags) => {
|
|
48
|
+
this.setState({ tags: tags.map((tag) => tag.value) });
|
|
49
|
+
};
|
|
50
|
+
|
|
46
51
|
getTags = () => {
|
|
47
52
|
const { tags } = this.state;
|
|
48
53
|
return tags;
|
|
@@ -50,9 +55,23 @@ export default class DynamicTag extends Component {
|
|
|
50
55
|
|
|
51
56
|
renderInput = () => {
|
|
52
57
|
const { inputValue, error } = this.state;
|
|
53
|
-
const { placeholder, testId } = this.props;
|
|
58
|
+
const { placeholder, testId, isSelector, label, options, defaultTags, color } = this.props;
|
|
54
59
|
|
|
55
|
-
return (
|
|
60
|
+
return isSelector ? (
|
|
61
|
+
<Select
|
|
62
|
+
aria-label={`${testId}-select`}
|
|
63
|
+
color={color}
|
|
64
|
+
label={label}
|
|
65
|
+
isMulti
|
|
66
|
+
isCreatable
|
|
67
|
+
options={options}
|
|
68
|
+
closeMenuOnSelect={false}
|
|
69
|
+
noOptionsMessage={() => tr('No options found')}
|
|
70
|
+
placeholder={placeholder}
|
|
71
|
+
defaultValue={defaultTags}
|
|
72
|
+
onChange={this.handleChange}
|
|
73
|
+
/>
|
|
74
|
+
) : (
|
|
56
75
|
<>
|
|
57
76
|
<Input
|
|
58
77
|
placeholder={placeholder}
|
|
@@ -70,24 +89,26 @@ export default class DynamicTag extends Component {
|
|
|
70
89
|
|
|
71
90
|
render() {
|
|
72
91
|
const { tags } = this.state;
|
|
73
|
-
const { color, testId } = this.props;
|
|
92
|
+
const { color, testId, isSelector } = this.props;
|
|
74
93
|
return (
|
|
75
94
|
<div className={cl('dynamic-tag')} data-testid={testId}>
|
|
76
95
|
<div className={cl('dynamic-tag__input')}>{this.renderInput()}</div>
|
|
77
|
-
|
|
78
|
-
{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
{!isSelector && (
|
|
97
|
+
<div className={cl('dynamic-tag__tags')}>
|
|
98
|
+
{tags.map((item) => (
|
|
99
|
+
<Label
|
|
100
|
+
color={color}
|
|
101
|
+
key={`label_${item}`}
|
|
102
|
+
closable
|
|
103
|
+
label={item}
|
|
104
|
+
closeCb={() => {
|
|
105
|
+
this.handleTagRemove(item);
|
|
106
|
+
}}
|
|
107
|
+
testId={`${testId}-label`}
|
|
108
|
+
/>
|
|
109
|
+
))}
|
|
110
|
+
</div>
|
|
111
|
+
)}
|
|
91
112
|
</div>
|
|
92
113
|
);
|
|
93
114
|
}
|
|
@@ -98,6 +119,7 @@ DynamicTag.defaultProps = {
|
|
|
98
119
|
placeholder: '',
|
|
99
120
|
color: '',
|
|
100
121
|
testId: 'dynamic-tag',
|
|
122
|
+
isSelector: false,
|
|
101
123
|
};
|
|
102
124
|
|
|
103
125
|
DynamicTag.propTypes = {
|
|
@@ -105,4 +127,6 @@ DynamicTag.propTypes = {
|
|
|
105
127
|
placeholder: PropTypes.string,
|
|
106
128
|
color: PropTypes.string,
|
|
107
129
|
testId: PropTypes.string,
|
|
130
|
+
isSelector: PropTypes.bool,
|
|
131
|
+
...Select.propTypes,
|
|
108
132
|
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import DynamicTag from './DynamicTag';
|
|
3
|
+
|
|
4
|
+
const Story = {
|
|
5
|
+
title: 'base/DynamicTag',
|
|
6
|
+
component: DynamicTag,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default Story;
|
|
10
|
+
|
|
11
|
+
const Template = (arg) => {
|
|
12
|
+
const { isSelector } = arg;
|
|
13
|
+
const options = [
|
|
14
|
+
{ value: 'java', label: 'Java' },
|
|
15
|
+
{ value: 'swift', label: 'Swift' },
|
|
16
|
+
{ value: 'js', label: 'Js' },
|
|
17
|
+
{
|
|
18
|
+
value: 'python',
|
|
19
|
+
label: 'Python',
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
return (
|
|
23
|
+
<div>
|
|
24
|
+
<DynamicTag
|
|
25
|
+
color="mauve"
|
|
26
|
+
defaultTags={
|
|
27
|
+
isSelector
|
|
28
|
+
? [
|
|
29
|
+
{ label: 'Js', value: 'js' },
|
|
30
|
+
{
|
|
31
|
+
label: 'Python',
|
|
32
|
+
value: 'python',
|
|
33
|
+
},
|
|
34
|
+
]
|
|
35
|
+
: ['js', 'python']
|
|
36
|
+
}
|
|
37
|
+
isSelector={isSelector}
|
|
38
|
+
isMulti
|
|
39
|
+
options={options}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
export const Default = Template.bind({});
|
|
45
|
+
Default.args = {
|
|
46
|
+
isSelector: false,
|
|
47
|
+
};
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen, getByRole } from '@testing-library/react';
|
|
2
|
+
import { render, screen, getByRole, fireEvent } from '@testing-library/react';
|
|
3
3
|
import { act } from 'react-dom/test-utils';
|
|
4
4
|
import '@testing-library/jest-dom/extend-expect';
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
6
6
|
|
|
7
7
|
import DynamicTag from './DynamicTag';
|
|
8
8
|
|
|
9
|
+
const options = [
|
|
10
|
+
{ value: 'java', label: 'java' },
|
|
11
|
+
{ value: 'swift', label: 'swift' },
|
|
12
|
+
{ value: 'js', label: 'js' },
|
|
13
|
+
{
|
|
14
|
+
value: 'python',
|
|
15
|
+
label: 'python',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
|
|
9
19
|
it('renders a DynamicTag component with default tags', () => {
|
|
10
20
|
const { container } = render(<DynamicTag defaultTags={['tag1', 'tag 2']} />);
|
|
11
21
|
expect(container.firstChild).toHaveClass('dynamic-tag');
|
|
@@ -68,3 +78,37 @@ it('cant add the same value twice', () => {
|
|
|
68
78
|
expect(screen.getByTestId('input-error')).toHaveTextContent('The value you’ve entered is already in the list');
|
|
69
79
|
expect(ref.current.getTags()).toEqual(['mytag']);
|
|
70
80
|
});
|
|
81
|
+
|
|
82
|
+
it(
|
|
83
|
+
'should render DynamicTag with Select behavior and default tags and ' +
|
|
84
|
+
'should add a new option when enter a value not present in options',
|
|
85
|
+
() => {
|
|
86
|
+
const ref = React.createRef();
|
|
87
|
+
const { container } = render(
|
|
88
|
+
<DynamicTag
|
|
89
|
+
color="mauve"
|
|
90
|
+
defaultTags={[
|
|
91
|
+
{ label: 'js', value: 'js' },
|
|
92
|
+
{
|
|
93
|
+
label: 'python',
|
|
94
|
+
value: 'python',
|
|
95
|
+
},
|
|
96
|
+
]}
|
|
97
|
+
isSelector
|
|
98
|
+
isMulti
|
|
99
|
+
options={options}
|
|
100
|
+
ref={ref}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
const select = screen.getByLabelText('dynamic-tag-select');
|
|
104
|
+
expect(select).toBeInTheDocument();
|
|
105
|
+
expect(ref.current.getTags()).toEqual(['js', 'python']);
|
|
106
|
+
fireEvent.change(select, { target: { value: 'c' } });
|
|
107
|
+
fireEvent.keyDown(select, { key: 'Enter', code: 'Enter', charCode: 13 });
|
|
108
|
+
expect(ref.current.getTags()).toEqual(['js', 'python', 'c']);
|
|
109
|
+
fireEvent.click(select);
|
|
110
|
+
expect(screen.getByText('java')).toBeInTheDocument();
|
|
111
|
+
expect(screen.getByText('swift')).toBeInTheDocument();
|
|
112
|
+
expect(container.querySelectorAll('div.select__item--mauve')[0]).toBeInTheDocument();
|
|
113
|
+
}
|
|
114
|
+
);
|
|
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
|
|
2
2
|
import ReactSelect from 'react-select';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import cl from 'classnames';
|
|
5
|
+
import CreatableSelect from 'react-select/creatable';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* https://react-select.com/styles#styles
|
|
@@ -9,9 +10,17 @@ import cl from 'classnames';
|
|
|
9
10
|
*/
|
|
10
11
|
export default class Select extends Component {
|
|
11
12
|
renderInput = (props) => {
|
|
12
|
-
const { error, ...rest } = props;
|
|
13
|
+
const { error, isCreatable, color, ...rest } = props;
|
|
13
14
|
|
|
14
|
-
return (
|
|
15
|
+
return isCreatable ? (
|
|
16
|
+
<CreatableSelect
|
|
17
|
+
className={cl('select__item', color ? `select__item--${color}` : null, {
|
|
18
|
+
error,
|
|
19
|
+
})}
|
|
20
|
+
classNamePrefix="select"
|
|
21
|
+
{...rest}
|
|
22
|
+
/>
|
|
23
|
+
) : (
|
|
15
24
|
<ReactSelect
|
|
16
25
|
className={cl('select__item', {
|
|
17
26
|
error,
|
|
@@ -56,6 +65,8 @@ Select.defaultProps = {
|
|
|
56
65
|
icon: null,
|
|
57
66
|
label: null,
|
|
58
67
|
error: null,
|
|
68
|
+
isCreatable: false,
|
|
69
|
+
color: undefined,
|
|
59
70
|
};
|
|
60
71
|
Select.propTypes = {
|
|
61
72
|
className: PropTypes.string,
|
|
@@ -64,4 +75,6 @@ Select.propTypes = {
|
|
|
64
75
|
error: PropTypes.string,
|
|
65
76
|
hideLabel: PropTypes.bool,
|
|
66
77
|
icon: PropTypes.string,
|
|
78
|
+
isCreatable: PropTypes.bool,
|
|
79
|
+
color: PropTypes.oneOf(['bleu', 'mauve', 'green', 'grey', 'orange', 'red', 'white', undefined, '']),
|
|
67
80
|
};
|
|
@@ -67,9 +67,20 @@ select
|
|
|
67
67
|
background-color $primary15 !important
|
|
68
68
|
color $secondary !important
|
|
69
69
|
&__multi-value
|
|
70
|
+
display flex
|
|
71
|
+
align-items center
|
|
70
72
|
background-color $primary !important
|
|
71
73
|
border-radius .4rem !important
|
|
72
|
-
|
|
74
|
+
.select__item--mauve &
|
|
75
|
+
background-color $labelMauve !important
|
|
76
|
+
.select__item--green &
|
|
77
|
+
background-color $labelGreen !important
|
|
78
|
+
.select__item--grey &
|
|
79
|
+
background-color $labelGrey !important
|
|
80
|
+
.select__item--orange &
|
|
81
|
+
background-color $labelOrange !important
|
|
82
|
+
.select__item--red &
|
|
83
|
+
background-color $labelRed !important
|
|
73
84
|
&--is-disabled
|
|
74
85
|
opacity .6
|
|
75
86
|
&__label
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import DynamicTag from './DynamicTag';
|
|
3
|
-
|
|
4
|
-
const Story = {
|
|
5
|
-
title: 'base/DynamicTag',
|
|
6
|
-
component: DynamicTag,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export default Story;
|
|
10
|
-
|
|
11
|
-
const Template = () => (
|
|
12
|
-
<div>
|
|
13
|
-
<DynamicTag color="color1" defaultTags={['js', 'python']} />
|
|
14
|
-
</div>
|
|
15
|
-
);
|
|
16
|
-
export const Default = Template.bind({});
|
|
17
|
-
Default.args = {};
|