@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@woosmap/ui",
3
- "version": "3.119.0",
3
+ "version": "3.120.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/WebGeoServices/ui.git"
@@ -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
- <div className={cl('dynamic-tag__tags')}>
78
- {tags.map((item) => (
79
- <Label
80
- color={color}
81
- key={`label_${item}`}
82
- closable
83
- label={item}
84
- closeCb={() => {
85
- this.handleTagRemove(item);
86
- }}
87
- testId={`${testId}-label`}
88
- />
89
- ))}
90
- </div>
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
- flexMiddle()
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 = {};