@spothero/ui 15.8.0 → 15.9.1

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": "@spothero/ui",
3
- "version": "15.8.0",
3
+ "version": "15.9.1",
4
4
  "description": "SpotHero's React component UI library.",
5
5
  "main": "v2/index.js",
6
6
  "repository": "https://github.com/spothero/fe-monorepo",
@@ -15,6 +15,7 @@ const AutoSuggestSelect = forwardRef(
15
15
  isInvalid,
16
16
  isDisabled,
17
17
  isRequired,
18
+ isOptional,
18
19
  getOptions,
19
20
  onChange,
20
21
  iconSrc,
@@ -135,6 +136,7 @@ const AutoSuggestSelect = forwardRef(
135
136
  <FormControl
136
137
  errorMessage={errorMessage}
137
138
  isRequired={isRequired}
139
+ isOptional={isOptional}
138
140
  helperText={helperText}
139
141
  label={label}
140
142
  inputId={id}
@@ -171,7 +173,7 @@ AutoSuggestSelect.propTypes = {
171
173
  placeholder: PropTypes.string,
172
174
  /** Optional helper text displayed below the select */
173
175
  helperText: PropTypes.string,
174
- /** Error message that would dispplay under the select */
176
+ /** Error message that would display under the select */
175
177
  errorMessage: PropTypes.string,
176
178
  /** Boolean that sets whether the select is valid */
177
179
  isInvalid: PropTypes.bool,
@@ -179,6 +181,8 @@ AutoSuggestSelect.propTypes = {
179
181
  isDisabled: PropTypes.bool,
180
182
  /** Boolean that sets whether the select is required */
181
183
  isRequired: PropTypes.bool,
184
+ /** Boolean that sets whether the select is optional */
185
+ isOptional: PropTypes.bool,
182
186
  /** Function that is called with the value typed into the input that returns a list of options for the select */
183
187
  getOptions: PropTypes.func.isRequired,
184
188
  /** Function that is called when an option is selected, it returns the label and value of the selection */
@@ -10,13 +10,20 @@ const baseStyle = {
10
10
  borderColor: 'gray.200',
11
11
  _hover: {borderColor: 'gray.300'},
12
12
  _readOnly: {boxShadow: 'none !important', userSelect: 'all'},
13
- _disabled: {opacity: 0.4, cursor: 'not-allowed'},
13
+ _disabled: {
14
+ opacity: 0.4,
15
+ cursor: 'not-allowed',
16
+ _hover: {borderColor: 'gray.200'},
17
+ },
14
18
  _focus: {
15
19
  zIndex: 1,
16
20
  borderColor: 'primary.400',
17
21
  boxShadow: t => `0 0 0 1px ${t.colors.primary['400']}`,
18
22
  },
19
23
  },
24
+ label: {
25
+ _disabled: {opacity: 0.4, cursor: 'not-allowed'},
26
+ },
20
27
  };
21
28
 
22
29
  export default merge(chakraDefaultTheme.components.Checkbox, {
@@ -1,7 +1,8 @@
1
+ import React, {forwardRef} from 'react';
1
2
  import cn from 'classnames';
2
3
  import PropTypes from 'prop-types';
3
- import React, {forwardRef} from 'react';
4
- import {Select as ChakraSelect} from '@chakra-ui/react';
4
+ import ReactSelect from 'react-select';
5
+
5
6
  import IconChevronDown from '@spothero/icons/chevron-down';
6
7
 
7
8
  import Icon from '../Icon/Icon';
@@ -17,12 +18,127 @@ const Select = forwardRef(
17
18
  isDisabled,
18
19
  isRequired,
19
20
  isOptional,
21
+ options,
20
22
  ...props
21
23
  },
22
24
  ref
23
25
  ) => {
24
26
  const classes = cn({'FormElement-contains-error': isInvalid});
25
27
 
28
+ const baseText = {
29
+ fontSize: 'var(--chakra-fontSizes-base)',
30
+ color: 'var(--chakra-colors-text-primary-light)',
31
+ };
32
+
33
+ /** React Select doesn't use Chakra but it does use Emotion so it's not too difficult to use values from our Chakra theme. Here is the documentation for React Select styling: https://react-select.com/styles */
34
+ const customStyles = {
35
+ select: (provided, state) => ({
36
+ ...provided,
37
+
38
+ '&:hover': {
39
+ cursor: state.isDisabled ? 'not-allowed' : 'auto',
40
+ },
41
+ }),
42
+ menu: provided => ({
43
+ ...provided,
44
+ ...baseText,
45
+ borderColor: 'var(--chakra-colors-gray-200)',
46
+ borderWidth: '1px',
47
+ boxShadow: 'none',
48
+ }),
49
+ control: (provided, state) => ({
50
+ ...provided,
51
+ borderColor: isInvalid
52
+ ? 'var(--chakra-colors-error)'
53
+ : state.isFocused
54
+ ? 'var(--chakra-colors-primary-default)'
55
+ : 'var(--chakra-colors-gray-200)',
56
+ borderWidth: '1px',
57
+ borderRadius: '4px',
58
+ backgroundColor: state.isDisabled
59
+ ? 'var(--chakra-colors-gray-50)'
60
+ : 'transparent',
61
+ boxShadow: 'none',
62
+ height: 'var(--chakra-sizes-10)',
63
+ minWidth: 'var(--chakra-sizes-48)',
64
+ width: props.width && props.width,
65
+
66
+ '&:hover': {
67
+ borderColor: isInvalid
68
+ ? 'var(--chakra-colors-error)'
69
+ : state.isFocused
70
+ ? 'var(--chakra-colors-primary-default)'
71
+ : 'var(--chakra-colors-gray-200)',
72
+ },
73
+ }),
74
+ input: (provided, state) => ({
75
+ ...provided,
76
+ ...baseText,
77
+ borderRadius: '4px',
78
+ color: state.isDisabled
79
+ ? 'var(--chakra-colors-text-secondary-light)'
80
+ : 'var(--chakra-colors-text-primary-light)',
81
+ backgroundColor: state.isDisabled
82
+ ? 'var(--chakra-colors-gray-50)'
83
+ : 'transparent',
84
+ }),
85
+ placeholder: provided => ({
86
+ ...provided,
87
+ fontSize: 'var(--chakra-fontSizes-base)',
88
+ color: 'var(--chakra-colors-gray-600)',
89
+ }),
90
+ singleValue: (provided, state) => ({
91
+ ...provided,
92
+ ...baseText,
93
+ color: state.isDisabled
94
+ ? 'var(--chakra-colors-text-secondary-light)'
95
+ : 'var(--chakra-colors-text-primary-light)',
96
+
97
+ '&:hover': {
98
+ cursor: state.isDisabled ? 'not-allowed' : 'auto',
99
+ },
100
+ }),
101
+ option: (provided, state) => ({
102
+ ...provided,
103
+ backgroundColor: state.isSelected
104
+ ? 'var(--chakra-colors-gray-200)'
105
+ : state.isFocused
106
+ ? 'var(--chakra-colors-gray-50)'
107
+ : 'transparent',
108
+ color: 'var(--chakra-colors-text-primary-light)',
109
+ fontWeight: state.isSelected
110
+ ? 'var(--chakra-fontWeights-semibold)'
111
+ : 'var(--chakra-fontWeights-normal)',
112
+
113
+ ':active': {
114
+ fontWeight: 'var(--chakra-fontWeights-semibold)',
115
+ color: 'var(--chakra-colors-text-primary-light)',
116
+ backgroundColor:
117
+ !state.isDisabled && 'var(--chakra-colors-gray-200)',
118
+ },
119
+ }),
120
+ };
121
+
122
+ const dropdownIndicatorStyles = {
123
+ width: 18,
124
+ display: 'flex',
125
+ marginRight: 'var(--chakra-space-4)',
126
+ marginLeft: 'var(--chakra-space-7)',
127
+ color: 'var(--chakra-colors-gray-600)',
128
+ '&:hover': {
129
+ color: 'var(--chakra-colors-gray-600)',
130
+ },
131
+ };
132
+
133
+ const DropdownIndicator = ({innerRef, innerProps}) => (
134
+ <Icon
135
+ as={IconChevronDown}
136
+ style={dropdownIndicatorStyles}
137
+ ref={innerRef}
138
+ {...innerProps}
139
+ />
140
+ );
141
+
26
142
  return (
27
143
  <FormControl
28
144
  isInvalid={isInvalid}
@@ -33,12 +149,19 @@ const Select = forwardRef(
33
149
  helperText={helperText}
34
150
  label={label}
35
151
  inputId={props.id}
152
+ minWidth={48}
153
+ width={props.width && props.width}
36
154
  >
37
- <ChakraSelect
38
- icon={<Icon as={IconChevronDown} />}
39
- iconSize={12}
40
- fontWeight="regular"
41
- fontSize="sm"
155
+ <ReactSelect
156
+ options={options?.length && options}
157
+ isSearchable={false}
158
+ isDisabled={isDisabled}
159
+ components={{
160
+ DropdownIndicator,
161
+ IndicatorSeparator: () => null,
162
+ }}
163
+ maxMenuHeight={280}
164
+ styles={customStyles}
42
165
  ref={ref}
43
166
  className={classes}
44
167
  {...props}
@@ -50,8 +173,11 @@ const Select = forwardRef(
50
173
 
51
174
  Select.propTypes = {
52
175
  id: PropTypes.string.isRequired,
176
+ options: PropTypes.array,
53
177
  label: PropTypes.string,
178
+ isRequired: PropTypes.bool,
54
179
  helperText: PropTypes.string,
180
+ placeholder: PropTypes.string,
55
181
  errorMessage: PropTypes.string,
56
182
  isInvalid: PropTypes.bool,
57
183
  isDisabled: PropTypes.bool,
@@ -11,14 +11,7 @@ export default {
11
11
  },
12
12
  };
13
13
 
14
- const SelectTemplate = props => (
15
- <Component variant="outline" maxWidth="200px" {...props}>
16
- <option value="one">One</option>
17
- <option value="two">Two</option>
18
- <option value="three">Three</option>
19
- <option value="four">Four</option>
20
- </Component>
21
- );
14
+ const SelectTemplate = props => <Component options {...props} />;
22
15
 
23
16
  SelectTemplate.propTypes = {
24
17
  placeholder: PropTypes.string,
@@ -28,33 +21,54 @@ SelectTemplate.propTypes = {
28
21
  isInvalid: PropTypes.bool,
29
22
  isDisabled: PropTypes.bool,
30
23
  isReadOnly: PropTypes.bool,
24
+ isOptional: PropTypes.bool,
31
25
  };
32
26
 
33
27
  export const Select = SelectTemplate.bind({});
34
28
 
35
29
  Select.argTypes = {
36
- placeholder: {
37
- control: {type: 'text'},
30
+ id: {control: {type: 'text'}},
31
+ options: {
32
+ control: {type: 'object'},
38
33
  },
39
34
  label: {
40
35
  control: {type: 'text'},
41
36
  },
37
+ isRequired: {control: {type: 'boolean'}},
42
38
  helperText: {
43
39
  control: {type: 'text'},
44
40
  },
41
+ placeholder: {
42
+ control: {type: 'text'},
43
+ },
45
44
  errorMessage: {
46
45
  control: {type: 'text'},
47
46
  },
47
+ isInvalid: {control: {type: 'boolean'}},
48
+ isDisabled: {control: {type: 'boolean'}},
48
49
  };
49
50
 
50
51
  Select.args = {
51
- placeholder: 'Placeholder text',
52
+ id: 'input_id',
53
+ options: [
54
+ {value: 'One', label: 'Option One'},
55
+ {value: 'Two', label: 'Option Two'},
56
+ {value: 'Three', label: 'Option Three'},
57
+ {value: 'Four', label: 'Option Four'},
58
+ {value: 'Five', label: 'Option Five'},
59
+ {value: 'Six', label: 'Option Six'},
60
+ {value: 'Seven', label: 'Option Seven'},
61
+ {value: 'Eight', label: 'Option Eight'},
62
+ {value: 'Nine', label: 'Option Nine'},
63
+ {value: 'Ten', label: 'Option Ten'},
64
+ ],
52
65
  label: 'Label',
66
+ isRequired: false,
53
67
  helperText: 'Helper text',
68
+ placeholder: 'Select One...',
54
69
  errorMessage: 'Error message',
55
70
  isInvalid: false,
56
71
  isDisabled: false,
57
72
  isReadOnly: false,
58
- isRequired: false,
59
73
  isOptional: false,
60
74
  };
@@ -9,7 +9,6 @@ export {default as Spinner} from './Spinner/Spinner.styles';
9
9
  export {default as Heading} from './Heading/Heading.styles';
10
10
  export {default as Divider} from './Divider/Divider.styles';
11
11
  export {default as Tabs} from './Tabs/styles';
12
- export {default as Select} from './Select/styles';
13
12
  export {default as Checkbox} from './Checkbox/styles';
14
13
  export {default as Switch} from './Switch/styles';
15
14
  export {default as Popover} from './Popover/styles';