@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 +1 -1
- package/styles/v2/components/AutoSuggestSelect/AutoSuggestSelect.jsx +5 -1
- package/styles/v2/components/Checkbox/styles/index.js +8 -1
- package/styles/v2/components/Select/Select.jsx +133 -7
- package/styles/v2/components/Select/Select.stories.js +26 -12
- package/styles/v2/components/styles.js +0 -1
- package/v2/index.js +1 -1
- package/v2/index.js.map +1 -1
- package/styles/v2/components/Select/styles/index.js +0 -29
package/package.json
CHANGED
|
@@ -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
|
|
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: {
|
|
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
|
|
4
|
-
|
|
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
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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';
|