@spark-web/select 0.0.0-snapshot-release-20220907020533
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/README.md +140 -0
- package/dist/declarations/src/Select.d.ts +34 -0
- package/dist/declarations/src/index.d.ts +2 -0
- package/dist/spark-web-select.cjs.d.ts +1 -0
- package/dist/spark-web-select.cjs.dev.js +118 -0
- package/dist/spark-web-select.cjs.js +7 -0
- package/dist/spark-web-select.cjs.prod.js +118 -0
- package/dist/spark-web-select.esm.js +114 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Select
|
|
3
|
+
storybookPath: forms-select--default
|
|
4
|
+
isExperimentalPackage: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Allows the user to make a single selection from a list of values — usually in a
|
|
8
|
+
form. If only a few options are provided, consider using a `RadioButton`
|
|
9
|
+
instead.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Field
|
|
14
|
+
|
|
15
|
+
Each select input must be accompanied by a Field with a label. Effective form
|
|
16
|
+
labeling helps inform users which selection to make.
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### Controlled
|
|
21
|
+
|
|
22
|
+
A `<Select>` can be both controlled and uncontrolled. To control a `<Select>`
|
|
23
|
+
provide a `value`, as well as an `onChange` function to set the new value when
|
|
24
|
+
the select is updated.
|
|
25
|
+
|
|
26
|
+
```jsx live
|
|
27
|
+
const [selectedOption, setSelectedOption] = React.useState('');
|
|
28
|
+
|
|
29
|
+
const options = [
|
|
30
|
+
{ label: 'NSW', value: 'nsw' },
|
|
31
|
+
{ label: 'VIC', value: 'vic' },
|
|
32
|
+
{ label: 'QLD', value: 'qld' },
|
|
33
|
+
{ label: 'SA', value: 'sa' },
|
|
34
|
+
{ label: 'WA', value: 'wa' },
|
|
35
|
+
{ label: 'TAS', value: 'tas' },
|
|
36
|
+
{ label: 'NT', value: 'nt' },
|
|
37
|
+
{ label: 'ACT', value: 'act' },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Stack gap="large">
|
|
42
|
+
<Field label="State">
|
|
43
|
+
<Select
|
|
44
|
+
placeholder="Choose a state..."
|
|
45
|
+
value={selectedOption}
|
|
46
|
+
onChange={event => setSelectedOption(event.target.value)}
|
|
47
|
+
options={options}
|
|
48
|
+
required
|
|
49
|
+
/>
|
|
50
|
+
</Field>
|
|
51
|
+
{selectedOption && (
|
|
52
|
+
<Text>
|
|
53
|
+
You have selected{' '}
|
|
54
|
+
{options.find(option => option.value === selectedOption).label}
|
|
55
|
+
</Text>
|
|
56
|
+
)}
|
|
57
|
+
</Stack>
|
|
58
|
+
);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Uncontrolled
|
|
62
|
+
|
|
63
|
+
The `<Select>`, by default, is an uncontrolled component, meaning that the form
|
|
64
|
+
data is controlled directly by the DOM itself. To access the value, instead of
|
|
65
|
+
writing an `onChange` handler, you would use a `ref` to get form values from the
|
|
66
|
+
DOM.
|
|
67
|
+
|
|
68
|
+
```jsx live
|
|
69
|
+
<Field label="Breaking Bad Characters">
|
|
70
|
+
<Select
|
|
71
|
+
options={[
|
|
72
|
+
{ label: 'Walter White', value: 'walter-white' },
|
|
73
|
+
{ label: 'Jesse Pinkman', value: 'jesse-pinkman' },
|
|
74
|
+
{ label: 'Saul Goodman', value: 'saul-goodman' },
|
|
75
|
+
{ label: 'Gus Fring', value: 'gus-fring' },
|
|
76
|
+
{ label: 'Hank Schrader', value: 'hank-schrader' },
|
|
77
|
+
{ label: 'Mike Ehrmantraut', value: 'mike-ehrmantraut' },
|
|
78
|
+
]}
|
|
79
|
+
/>
|
|
80
|
+
</Field>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Groups
|
|
84
|
+
|
|
85
|
+
Related options can be grouped by passing in an array of objects with a label
|
|
86
|
+
and option key — where each option is an array of objects with label, value and
|
|
87
|
+
(optionally) disabled keys. Internally this uses the
|
|
88
|
+
[`<optgroup>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup).
|
|
89
|
+
|
|
90
|
+
```jsx live
|
|
91
|
+
const [selectedOption, setSelectedOption] = React.useState('');
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Field label="Select">
|
|
95
|
+
<Select
|
|
96
|
+
placeholder="TV Characters"
|
|
97
|
+
options={[
|
|
98
|
+
{
|
|
99
|
+
label: 'Mad Men',
|
|
100
|
+
options: [
|
|
101
|
+
{ label: 'Don Draper', value: 'don-draper' },
|
|
102
|
+
{ label: 'Peggy Olson', value: 'peggy-olson' },
|
|
103
|
+
{ label: 'Joan Harris', value: 'joan-harris' },
|
|
104
|
+
{ label: 'Roger Sterling', value: 'roger-sterling' },
|
|
105
|
+
{ label: 'Pete Campbell', value: 'pete-campbell' },
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
label: 'Breaking Bad',
|
|
110
|
+
options: [
|
|
111
|
+
{ label: 'Walter White', value: 'walter-white' },
|
|
112
|
+
{ label: 'Jesse Pinkman', value: 'jesse-pinkman' },
|
|
113
|
+
{ label: 'Saul Goodman', value: 'saul-goodman' },
|
|
114
|
+
{ label: 'Gus Fring', value: 'gus-fring' },
|
|
115
|
+
{ label: 'Hank Schrader', value: 'hank-schrader' },
|
|
116
|
+
{ label: 'Mike Ehrmantraut', value: 'mike-ehrmantraut' },
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
]}
|
|
120
|
+
/>
|
|
121
|
+
</Field>
|
|
122
|
+
);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Props
|
|
126
|
+
|
|
127
|
+
| Prop | Type | Default | Description |
|
|
128
|
+
| ------------- | -------------------------------------------- | ------- | -------------------------------------------------------------------------------------- |
|
|
129
|
+
| data? | [DataAttributeMap][data-attribute-map] | | Sets data attributes on the component. |
|
|
130
|
+
| options | Readonly\<Array\<Option \| Group>> | | The values that can be selected by the input. |
|
|
131
|
+
| placeholder? | string | | Placeholder text for when the input does not have an initial value. |
|
|
132
|
+
| defaultValue? | string \| number \| readonly string[] | | Default value of the select. |
|
|
133
|
+
| name? | string | | This attribute is used to specify the name of the control. |
|
|
134
|
+
| onBlur? | React.FocusEventHandler\<HTMLSelectElement> | | Function for handling change events. |
|
|
135
|
+
| onChange? | React.ChangeEventHandler\<HTMLSelectElement> | | Function for handling blur events. |
|
|
136
|
+
| required? | boolean | | Boolean that indicating that an option with a non-empty string value must be selected. |
|
|
137
|
+
| value | string \| number \| readonly string[] | | Value of the select. |
|
|
138
|
+
|
|
139
|
+
[data-attribute-map]:
|
|
140
|
+
https://github.com/brighte-labs/spark-web/blob/e7f6f4285b4cfd876312cc89fbdd094039aa239a/packages/utils/src/internal/buildDataAttributes.ts#L1
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { DataAttributeMap } from '@spark-web/utils/internal';
|
|
2
|
+
import type { SelectHTMLAttributes } from 'react';
|
|
3
|
+
export declare type Option = {
|
|
4
|
+
/** Whether or not the option is disabled. */
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
/** Label for the option. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Value of the option. */
|
|
9
|
+
value: string | number;
|
|
10
|
+
};
|
|
11
|
+
export declare type Group = {
|
|
12
|
+
/** List of options for the group. */
|
|
13
|
+
options: Array<Option>;
|
|
14
|
+
/** Label for the group. */
|
|
15
|
+
label: string;
|
|
16
|
+
};
|
|
17
|
+
export declare type OptionsOrGroups = Array<Option | Group>;
|
|
18
|
+
export declare type NativeSelectProps = Pick<SelectHTMLAttributes<HTMLSelectElement>, 'defaultValue' | 'name' | 'onBlur' | 'onChange' | 'required' | 'value'>;
|
|
19
|
+
export declare type SelectProps = NativeSelectProps & {
|
|
20
|
+
/** Allows setting of data attributes on the underlying element. */
|
|
21
|
+
data?: DataAttributeMap;
|
|
22
|
+
/** The values that can be selected by the input. */
|
|
23
|
+
options: OptionsOrGroups;
|
|
24
|
+
/** Placeholder text for when the input does not have an initial value. */
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
};
|
|
27
|
+
export declare const Select: import("react").ForwardRefExoticComponent<NativeSelectProps & {
|
|
28
|
+
/** Allows setting of data attributes on the underlying element. */
|
|
29
|
+
data?: DataAttributeMap | undefined;
|
|
30
|
+
/** The values that can be selected by the input. */
|
|
31
|
+
options: OptionsOrGroups;
|
|
32
|
+
/** Placeholder text for when the input does not have an initial value. */
|
|
33
|
+
placeholder?: string | undefined;
|
|
34
|
+
} & import("react").RefAttributes<HTMLSelectElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./declarations/src/index";
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
6
|
+
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
|
|
7
|
+
var css = require('@emotion/css');
|
|
8
|
+
var box = require('@spark-web/box');
|
|
9
|
+
var field = require('@spark-web/field');
|
|
10
|
+
var icon = require('@spark-web/icon');
|
|
11
|
+
var textInput = require('@spark-web/text-input');
|
|
12
|
+
var theme = require('@spark-web/theme');
|
|
13
|
+
var react = require('react');
|
|
14
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
15
|
+
|
|
16
|
+
var Select = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
17
|
+
var data = _ref.data,
|
|
18
|
+
defaultValue = _ref.defaultValue,
|
|
19
|
+
name = _ref.name,
|
|
20
|
+
onBlur = _ref.onBlur,
|
|
21
|
+
onChange = _ref.onChange,
|
|
22
|
+
optionsOrGroups = _ref.options,
|
|
23
|
+
placeholder = _ref.placeholder,
|
|
24
|
+
required = _ref.required,
|
|
25
|
+
value = _ref.value;
|
|
26
|
+
|
|
27
|
+
var _useFieldContext = field.useFieldContext(),
|
|
28
|
+
_useFieldContext2 = _slicedToArray(_useFieldContext, 2),
|
|
29
|
+
_useFieldContext2$ = _useFieldContext2[0],
|
|
30
|
+
disabled = _useFieldContext2$.disabled,
|
|
31
|
+
invalid = _useFieldContext2$.invalid,
|
|
32
|
+
a11yProps = _useFieldContext2[1];
|
|
33
|
+
|
|
34
|
+
var _useSelectStyles = useSelectStyles({
|
|
35
|
+
disabled: disabled,
|
|
36
|
+
invalid: invalid
|
|
37
|
+
}),
|
|
38
|
+
_useSelectStyles2 = _slicedToArray(_useSelectStyles, 2),
|
|
39
|
+
boxProps = _useSelectStyles2[0],
|
|
40
|
+
inputStyles = _useSelectStyles2[1];
|
|
41
|
+
|
|
42
|
+
var mapOptions = react.useCallback(function (opt) {
|
|
43
|
+
return /*#__PURE__*/jsxRuntime.jsx("option", {
|
|
44
|
+
value: opt.value,
|
|
45
|
+
disabled: opt.disabled,
|
|
46
|
+
children: opt.label
|
|
47
|
+
}, opt.value);
|
|
48
|
+
}, []);
|
|
49
|
+
return /*#__PURE__*/jsxRuntime.jsxs(textInput.InputContainer, {
|
|
50
|
+
children: [/*#__PURE__*/jsxRuntime.jsx(Indicator, {}), /*#__PURE__*/jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread(_objectSpread({}, boxProps), a11yProps), {}, {
|
|
51
|
+
as: "select",
|
|
52
|
+
className: css.css(inputStyles),
|
|
53
|
+
data: data,
|
|
54
|
+
defaultValue: (defaultValue !== null && defaultValue !== void 0 ? defaultValue : placeholder) ? '' : undefined,
|
|
55
|
+
disabled: disabled,
|
|
56
|
+
name: name,
|
|
57
|
+
onBlur: onBlur,
|
|
58
|
+
onChange: onChange,
|
|
59
|
+
ref: forwardedRef,
|
|
60
|
+
required: required,
|
|
61
|
+
value: value,
|
|
62
|
+
width: "full",
|
|
63
|
+
children: [!value || placeholder ? /*#__PURE__*/jsxRuntime.jsx("option", {
|
|
64
|
+
value: "",
|
|
65
|
+
disabled: true,
|
|
66
|
+
children: placeholder
|
|
67
|
+
}) : null, optionsOrGroups.map(function (optionOrGroup) {
|
|
68
|
+
if ('options' in optionOrGroup) {
|
|
69
|
+
return /*#__PURE__*/jsxRuntime.jsx("optgroup", {
|
|
70
|
+
label: optionOrGroup.label,
|
|
71
|
+
children: optionOrGroup.options.map(function (option) {
|
|
72
|
+
return mapOptions(option);
|
|
73
|
+
})
|
|
74
|
+
}, optionOrGroup.label);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return mapOptions(optionOrGroup);
|
|
78
|
+
})]
|
|
79
|
+
}))]
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
Select.displayName = 'Select';
|
|
83
|
+
|
|
84
|
+
var Indicator = function Indicator() {
|
|
85
|
+
return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
|
|
86
|
+
position: "absolute",
|
|
87
|
+
top: 0,
|
|
88
|
+
bottom: 0,
|
|
89
|
+
right: 0,
|
|
90
|
+
display: "flex",
|
|
91
|
+
alignItems: "center",
|
|
92
|
+
padding: "medium",
|
|
93
|
+
className: css.css({
|
|
94
|
+
pointerEvents: 'none'
|
|
95
|
+
}),
|
|
96
|
+
children: /*#__PURE__*/jsxRuntime.jsx(icon.ChevronDownIcon, {
|
|
97
|
+
size: "xxsmall",
|
|
98
|
+
tone: "placeholder"
|
|
99
|
+
})
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
function useSelectStyles(props) {
|
|
104
|
+
var _useInputStyles = textInput.useInputStyles(props),
|
|
105
|
+
_useInputStyles2 = _slicedToArray(_useInputStyles, 2),
|
|
106
|
+
boxProps = _useInputStyles2[0],
|
|
107
|
+
inputStyles = _useInputStyles2[1];
|
|
108
|
+
|
|
109
|
+
var theme$1 = theme.useTheme();
|
|
110
|
+
return [boxProps, _objectSpread(_objectSpread({}, inputStyles), {}, {
|
|
111
|
+
// Prevent text going underneath the chevron icon
|
|
112
|
+
paddingRight: theme$1.sizing.xxsmall + // size of chevron icon
|
|
113
|
+
theme$1.spacing.medium * 2 // paddingX value
|
|
114
|
+
|
|
115
|
+
})];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
exports.Select = Select;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
6
|
+
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
|
|
7
|
+
var css = require('@emotion/css');
|
|
8
|
+
var box = require('@spark-web/box');
|
|
9
|
+
var field = require('@spark-web/field');
|
|
10
|
+
var icon = require('@spark-web/icon');
|
|
11
|
+
var textInput = require('@spark-web/text-input');
|
|
12
|
+
var theme = require('@spark-web/theme');
|
|
13
|
+
var react = require('react');
|
|
14
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
15
|
+
|
|
16
|
+
var Select = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
|
|
17
|
+
var data = _ref.data,
|
|
18
|
+
defaultValue = _ref.defaultValue,
|
|
19
|
+
name = _ref.name,
|
|
20
|
+
onBlur = _ref.onBlur,
|
|
21
|
+
onChange = _ref.onChange,
|
|
22
|
+
optionsOrGroups = _ref.options,
|
|
23
|
+
placeholder = _ref.placeholder,
|
|
24
|
+
required = _ref.required,
|
|
25
|
+
value = _ref.value;
|
|
26
|
+
|
|
27
|
+
var _useFieldContext = field.useFieldContext(),
|
|
28
|
+
_useFieldContext2 = _slicedToArray(_useFieldContext, 2),
|
|
29
|
+
_useFieldContext2$ = _useFieldContext2[0],
|
|
30
|
+
disabled = _useFieldContext2$.disabled,
|
|
31
|
+
invalid = _useFieldContext2$.invalid,
|
|
32
|
+
a11yProps = _useFieldContext2[1];
|
|
33
|
+
|
|
34
|
+
var _useSelectStyles = useSelectStyles({
|
|
35
|
+
disabled: disabled,
|
|
36
|
+
invalid: invalid
|
|
37
|
+
}),
|
|
38
|
+
_useSelectStyles2 = _slicedToArray(_useSelectStyles, 2),
|
|
39
|
+
boxProps = _useSelectStyles2[0],
|
|
40
|
+
inputStyles = _useSelectStyles2[1];
|
|
41
|
+
|
|
42
|
+
var mapOptions = react.useCallback(function (opt) {
|
|
43
|
+
return /*#__PURE__*/jsxRuntime.jsx("option", {
|
|
44
|
+
value: opt.value,
|
|
45
|
+
disabled: opt.disabled,
|
|
46
|
+
children: opt.label
|
|
47
|
+
}, opt.value);
|
|
48
|
+
}, []);
|
|
49
|
+
return /*#__PURE__*/jsxRuntime.jsxs(textInput.InputContainer, {
|
|
50
|
+
children: [/*#__PURE__*/jsxRuntime.jsx(Indicator, {}), /*#__PURE__*/jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread(_objectSpread({}, boxProps), a11yProps), {}, {
|
|
51
|
+
as: "select",
|
|
52
|
+
className: css.css(inputStyles),
|
|
53
|
+
data: data,
|
|
54
|
+
defaultValue: (defaultValue !== null && defaultValue !== void 0 ? defaultValue : placeholder) ? '' : undefined,
|
|
55
|
+
disabled: disabled,
|
|
56
|
+
name: name,
|
|
57
|
+
onBlur: onBlur,
|
|
58
|
+
onChange: onChange,
|
|
59
|
+
ref: forwardedRef,
|
|
60
|
+
required: required,
|
|
61
|
+
value: value,
|
|
62
|
+
width: "full",
|
|
63
|
+
children: [!value || placeholder ? /*#__PURE__*/jsxRuntime.jsx("option", {
|
|
64
|
+
value: "",
|
|
65
|
+
disabled: true,
|
|
66
|
+
children: placeholder
|
|
67
|
+
}) : null, optionsOrGroups.map(function (optionOrGroup) {
|
|
68
|
+
if ('options' in optionOrGroup) {
|
|
69
|
+
return /*#__PURE__*/jsxRuntime.jsx("optgroup", {
|
|
70
|
+
label: optionOrGroup.label,
|
|
71
|
+
children: optionOrGroup.options.map(function (option) {
|
|
72
|
+
return mapOptions(option);
|
|
73
|
+
})
|
|
74
|
+
}, optionOrGroup.label);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return mapOptions(optionOrGroup);
|
|
78
|
+
})]
|
|
79
|
+
}))]
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
Select.displayName = 'Select';
|
|
83
|
+
|
|
84
|
+
var Indicator = function Indicator() {
|
|
85
|
+
return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
|
|
86
|
+
position: "absolute",
|
|
87
|
+
top: 0,
|
|
88
|
+
bottom: 0,
|
|
89
|
+
right: 0,
|
|
90
|
+
display: "flex",
|
|
91
|
+
alignItems: "center",
|
|
92
|
+
padding: "medium",
|
|
93
|
+
className: css.css({
|
|
94
|
+
pointerEvents: 'none'
|
|
95
|
+
}),
|
|
96
|
+
children: /*#__PURE__*/jsxRuntime.jsx(icon.ChevronDownIcon, {
|
|
97
|
+
size: "xxsmall",
|
|
98
|
+
tone: "placeholder"
|
|
99
|
+
})
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
function useSelectStyles(props) {
|
|
104
|
+
var _useInputStyles = textInput.useInputStyles(props),
|
|
105
|
+
_useInputStyles2 = _slicedToArray(_useInputStyles, 2),
|
|
106
|
+
boxProps = _useInputStyles2[0],
|
|
107
|
+
inputStyles = _useInputStyles2[1];
|
|
108
|
+
|
|
109
|
+
var theme$1 = theme.useTheme();
|
|
110
|
+
return [boxProps, _objectSpread(_objectSpread({}, inputStyles), {}, {
|
|
111
|
+
// Prevent text going underneath the chevron icon
|
|
112
|
+
paddingRight: theme$1.sizing.xxsmall + // size of chevron icon
|
|
113
|
+
theme$1.spacing.medium * 2 // paddingX value
|
|
114
|
+
|
|
115
|
+
})];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
exports.Select = Select;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
|
|
2
|
+
import _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';
|
|
3
|
+
import { css } from '@emotion/css';
|
|
4
|
+
import { Box } from '@spark-web/box';
|
|
5
|
+
import { useFieldContext } from '@spark-web/field';
|
|
6
|
+
import { ChevronDownIcon } from '@spark-web/icon';
|
|
7
|
+
import { InputContainer, useInputStyles } from '@spark-web/text-input';
|
|
8
|
+
import { useTheme } from '@spark-web/theme';
|
|
9
|
+
import { forwardRef, useCallback } from 'react';
|
|
10
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
11
|
+
|
|
12
|
+
var Select = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
|
|
13
|
+
var data = _ref.data,
|
|
14
|
+
defaultValue = _ref.defaultValue,
|
|
15
|
+
name = _ref.name,
|
|
16
|
+
onBlur = _ref.onBlur,
|
|
17
|
+
onChange = _ref.onChange,
|
|
18
|
+
optionsOrGroups = _ref.options,
|
|
19
|
+
placeholder = _ref.placeholder,
|
|
20
|
+
required = _ref.required,
|
|
21
|
+
value = _ref.value;
|
|
22
|
+
|
|
23
|
+
var _useFieldContext = useFieldContext(),
|
|
24
|
+
_useFieldContext2 = _slicedToArray(_useFieldContext, 2),
|
|
25
|
+
_useFieldContext2$ = _useFieldContext2[0],
|
|
26
|
+
disabled = _useFieldContext2$.disabled,
|
|
27
|
+
invalid = _useFieldContext2$.invalid,
|
|
28
|
+
a11yProps = _useFieldContext2[1];
|
|
29
|
+
|
|
30
|
+
var _useSelectStyles = useSelectStyles({
|
|
31
|
+
disabled: disabled,
|
|
32
|
+
invalid: invalid
|
|
33
|
+
}),
|
|
34
|
+
_useSelectStyles2 = _slicedToArray(_useSelectStyles, 2),
|
|
35
|
+
boxProps = _useSelectStyles2[0],
|
|
36
|
+
inputStyles = _useSelectStyles2[1];
|
|
37
|
+
|
|
38
|
+
var mapOptions = useCallback(function (opt) {
|
|
39
|
+
return /*#__PURE__*/jsx("option", {
|
|
40
|
+
value: opt.value,
|
|
41
|
+
disabled: opt.disabled,
|
|
42
|
+
children: opt.label
|
|
43
|
+
}, opt.value);
|
|
44
|
+
}, []);
|
|
45
|
+
return /*#__PURE__*/jsxs(InputContainer, {
|
|
46
|
+
children: [/*#__PURE__*/jsx(Indicator, {}), /*#__PURE__*/jsxs(Box, _objectSpread(_objectSpread(_objectSpread({}, boxProps), a11yProps), {}, {
|
|
47
|
+
as: "select",
|
|
48
|
+
className: css(inputStyles),
|
|
49
|
+
data: data,
|
|
50
|
+
defaultValue: (defaultValue !== null && defaultValue !== void 0 ? defaultValue : placeholder) ? '' : undefined,
|
|
51
|
+
disabled: disabled,
|
|
52
|
+
name: name,
|
|
53
|
+
onBlur: onBlur,
|
|
54
|
+
onChange: onChange,
|
|
55
|
+
ref: forwardedRef,
|
|
56
|
+
required: required,
|
|
57
|
+
value: value,
|
|
58
|
+
width: "full",
|
|
59
|
+
children: [!value || placeholder ? /*#__PURE__*/jsx("option", {
|
|
60
|
+
value: "",
|
|
61
|
+
disabled: true,
|
|
62
|
+
children: placeholder
|
|
63
|
+
}) : null, optionsOrGroups.map(function (optionOrGroup) {
|
|
64
|
+
if ('options' in optionOrGroup) {
|
|
65
|
+
return /*#__PURE__*/jsx("optgroup", {
|
|
66
|
+
label: optionOrGroup.label,
|
|
67
|
+
children: optionOrGroup.options.map(function (option) {
|
|
68
|
+
return mapOptions(option);
|
|
69
|
+
})
|
|
70
|
+
}, optionOrGroup.label);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return mapOptions(optionOrGroup);
|
|
74
|
+
})]
|
|
75
|
+
}))]
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
Select.displayName = 'Select';
|
|
79
|
+
|
|
80
|
+
var Indicator = function Indicator() {
|
|
81
|
+
return /*#__PURE__*/jsx(Box, {
|
|
82
|
+
position: "absolute",
|
|
83
|
+
top: 0,
|
|
84
|
+
bottom: 0,
|
|
85
|
+
right: 0,
|
|
86
|
+
display: "flex",
|
|
87
|
+
alignItems: "center",
|
|
88
|
+
padding: "medium",
|
|
89
|
+
className: css({
|
|
90
|
+
pointerEvents: 'none'
|
|
91
|
+
}),
|
|
92
|
+
children: /*#__PURE__*/jsx(ChevronDownIcon, {
|
|
93
|
+
size: "xxsmall",
|
|
94
|
+
tone: "placeholder"
|
|
95
|
+
})
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
function useSelectStyles(props) {
|
|
100
|
+
var _useInputStyles = useInputStyles(props),
|
|
101
|
+
_useInputStyles2 = _slicedToArray(_useInputStyles, 2),
|
|
102
|
+
boxProps = _useInputStyles2[0],
|
|
103
|
+
inputStyles = _useInputStyles2[1];
|
|
104
|
+
|
|
105
|
+
var theme = useTheme();
|
|
106
|
+
return [boxProps, _objectSpread(_objectSpread({}, inputStyles), {}, {
|
|
107
|
+
// Prevent text going underneath the chevron icon
|
|
108
|
+
paddingRight: theme.sizing.xxsmall + // size of chevron icon
|
|
109
|
+
theme.spacing.medium * 2 // paddingX value
|
|
110
|
+
|
|
111
|
+
})];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export { Select };
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spark-web/select",
|
|
3
|
+
"version": "0.0.0-snapshot-release-20220907020533",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "dist/spark-web-select.cjs.js",
|
|
6
|
+
"module": "dist/spark-web-select.esm.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@babel/runtime": "^7.18.9",
|
|
12
|
+
"@emotion/css": "^11.9.0",
|
|
13
|
+
"@spark-web/box": "^1.0.7",
|
|
14
|
+
"@spark-web/icon": "^1.1.5",
|
|
15
|
+
"@spark-web/text-input": "^2.0.1",
|
|
16
|
+
"@spark-web/theme": "0.0.0-snapshot-release-20220907020533"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@spark-web/field": "^3.0.3",
|
|
20
|
+
"@spark-web/utils": "^1.2.0",
|
|
21
|
+
"@types/react": "^17.0.12",
|
|
22
|
+
"react": "^17.0.2"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@spark-web/field": "^3.0.3",
|
|
26
|
+
"react": ">=17.0.2"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">= 14.13"
|
|
30
|
+
}
|
|
31
|
+
}
|