@woosmap/ui 3.117.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.117.0",
3
+ "version": "3.120.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/WebGeoServices/ui.git"
@@ -33,7 +33,7 @@
33
33
  "test:generate-output": "react-scripts test --json --outputFile=./.storybook/jest-test-results.json --silent",
34
34
  "prestorybook:dev": "clear && echo \"DOING FIRST TEST RUN\" && CI=true npm run test:generate-output",
35
35
  "storybook:dev": "clear && concurrently -k \"npm run storybook\" \"npm run test:generate-output\"",
36
- "storybook": "start-storybook -p 9009 -s public",
36
+ "storybook": "start-storybook -p 9009 -s public -h localhost",
37
37
  "build-storybook": "build-storybook -s public",
38
38
  "icons": "svgo -f ./src/icons --config ./svgo-config.js",
39
39
  "deploy-storybook": "storybook-to-ghpages",
@@ -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
  };
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M50 37.486c3.248 0 6.546-1.2 8.401-3.057a1.501 1.501 0 0 0-2.122-2.121c-1.301 1.302-3.824 2.177-6.278 2.177s-4.978-.875-6.278-2.177a1.5 1.5 0 1 0-2.122 2.121c1.855 1.857 5.153 3.057 8.401 3.057Z"/><path d="M64.111 37.855c2.279-2.987 3.649-6.702 3.649-10.741a17.64 17.64 0 0 0-1.154-6.252c.238-.244.45-.516.594-.839a2.894 2.894 0 0 0-.245-2.809l-.724-1.073 1.565-4.669a2.93 2.93 0 0 0-.343-2.577 2.929 2.929 0 0 0-2.248-1.306L50.104 6.523a1.486 1.486 0 0 0-.211 0L34.792 7.589a2.932 2.932 0 0 0-2.248 1.306 2.928 2.928 0 0 0-.343 2.576l1.565 4.67-.724 1.073a2.894 2.894 0 0 0-.245 2.809c.144.323.356.595.594.839a17.64 17.64 0 0 0-1.154 6.252c0 4.038 1.37 7.754 3.649 10.741-9.402 1.748-16.514 10.121-16.514 19.855v32.243a3.533 3.533 0 0 0 3.529 3.529h8.783a5.193 5.193 0 0 0 4.963-3.684H64.13a5.195 5.195 0 0 0 4.963 3.684h7.999a3.533 3.533 0 0 0 3.529-3.529V57.71c0-9.734-7.112-18.107-16.514-19.855ZM35.615 18.771l.609-.904h27.574l.634.898L50 20.804l-14.386-2.032Zm14.389-9.249 14.95.996-1.458 4.349H36.502l-1.453-4.289 14.955-1.056ZM36.212 21.885l13.579 1.918a1.473 1.473 0 0 0 .42 0l13.579-1.918c.636 1.672.971 3.428.971 5.23 0 8.139-6.621 14.76-14.76 14.76s-14.76-6.621-14.76-14.76c0-1.802.335-3.557.971-5.23Zm12.541 28.734c.12-.806.825-1.414 1.641-1.414s1.521.608 1.632 1.345l1.718 16.84a1.967 1.967 0 0 1-.39 1.489l-2.129 2.748a1.033 1.033 0 0 1-.832.408c-.192 0-.557-.053-.831-.408l-2.129-2.748c-.325-.42-.468-.963-.381-1.558l1.701-16.702Zm3.068-5.745-1.264 1.263a.234.234 0 0 1-.138.07l-.026-.002c-.009 0-.018.003-.028.003a.24.24 0 0 1-.138-.071l-1.263-1.263h2.856Zm25.805 45.079a.53.53 0 0 1-.529.529h-7.999a2.187 2.187 0 0 1-2.184-2.184V60.882a1.5 1.5 0 1 0-3 0v25.916H36.873V60.882a1.5 1.5 0 1 0-3 0v27.416c0 1.204-.98 2.184-2.185 2.184h-8.783a.53.53 0 0 1-.529-.529V57.71c0-8.843 6.892-16.366 15.688-17.126.112-.01.218-.033.321-.066a17.707 17.707 0 0 0 6.789 3.672 2.41 2.41 0 0 0 .695 1.831l1.409 1.409a4.744 4.744 0 0 0-1.502 2.815l-1.701 16.703a4.987 4.987 0 0 0 .985 3.769l2.129 2.748c.772.998 1.94 1.57 3.202 1.57s2.431-.572 3.203-1.57l2.129-2.748c.825-1.065 1.185-2.439.994-3.7l-1.718-16.84a4.64 4.64 0 0 0-1.489-2.751l1.404-1.404a2.405 2.405 0 0 0 .673-2.062 17.737 17.737 0 0 0 6.027-3.442c.103.032.209.056.321.066 8.797.761 15.688 8.284 15.688 17.126v32.243Z"/></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="m77.924 62.799-16.547-7.421a1.498 1.498 0 0 0-1.824.481L50 68.885l-9.553-13.026a1.501 1.501 0 0 0-1.824-.481l-16.547 7.421a10.716 10.716 0 0 0-6.322 9.765v13.534a1.5 1.5 0 1 0 3 0V72.564a7.71 7.71 0 0 1 4.551-7.027l6.63-2.974-1.541 4.789a1.5 1.5 0 0 0 1.786 1.916l7.459-1.834 11.142 15.575c.012.017.029.029.042.045a1.57 1.57 0 0 0 .251.255c.019.015.034.033.054.047.022.016.049.021.072.036.089.057.181.103.279.139.039.015.077.031.118.043.13.036.263.06.398.061h.014c.135 0 .268-.024.398-.061.04-.011.078-.028.118-.043.097-.036.19-.083.279-.139.023-.015.049-.02.072-.036.02-.014.035-.032.054-.047.031-.025.06-.052.09-.079a1.48 1.48 0 0 0 .161-.176c.013-.016.029-.028.041-.045l11.142-15.575 7.459 1.834a1.5 1.5 0 0 0 1.786-1.916l-1.541-4.789 6.63 2.974a7.712 7.712 0 0 1 4.551 7.027v13.534a1.5 1.5 0 1 0 3 0V72.564c0-4.209-2.481-8.042-6.322-9.765Zm-9.996 2.914-5.837-1.435a1.5 1.5 0 0 0-1.578.584L50 79.559 39.487 64.862a1.5 1.5 0 0 0-1.578-.584l-5.837 1.435 1.545-4.802 5.128-2.3L48.79 72.309c.566.771 1.854.771 2.42 0l10.045-13.698 5.128 2.3 1.545 4.802Z"/><path d="M29.821 78.93a1.5 1.5 0 0 0-1.5 1.5v5.592a1.5 1.5 0 1 0 3 0V80.43a1.5 1.5 0 0 0-1.5-1.5ZM70.125 78.93a1.5 1.5 0 0 0-1.5 1.5v5.592a1.5 1.5 0 1 0 3 0V80.43a1.5 1.5 0 0 0-1.5-1.5ZM49.294 55.738c9.802 0 17.776-8.546 17.776-19.051 0-1.029-.103-2.053-.255-3.065.112-.167.191-.355.229-.557l1.324-6.97a6.578 6.578 0 0 0-3.018-6.806 48.374 48.374 0 0 0-19.654-6.811l-.25-.03a6.548 6.548 0 0 0-7.006 4.498l-1.601 4.983c-.119.371-.077.753.078 1.086-3.449 3.578-5.401 8.462-5.401 13.671 0 10.505 7.975 19.051 17.777 19.051Zm0-3c-8.148 0-14.777-7.201-14.777-16.051 0-4.616 1.805-8.907 4.953-11.955a101.76 101.76 0 0 0 24.358 9.18c.147.915.243 1.842.243 2.775 0 8.851-6.629 16.051-14.776 16.051Zm-7.998-34.875a3.566 3.566 0 0 1 3.795-2.437l.251.03a45.4 45.4 0 0 1 18.444 6.392 3.56 3.56 0 0 1 1.656 3.493c-2.464-.985-7.567-2.984-12.34-4.586a1.5 1.5 0 1 0-.955 2.844c5.108 1.714 10.611 3.894 12.739 4.752l-.498 2.623a98.773 98.773 0 0 1-24.312-9.308l1.221-3.803Z"/></svg>
@@ -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
@@ -105,6 +105,8 @@
105
105
  margin-bottom 2rem
106
106
  width 28.8rem
107
107
  height 20.6rem
108
+ img
109
+ fullwh()
108
110
  .title-container
109
111
  display flex !important
110
112
  align-items center
@@ -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 = {};