@sproutsocial/seeds-react-select 1.0.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/.eslintignore +6 -0
- package/.eslintrc.js +4 -0
- package/.turbo/turbo-build.log +21 -0
- package/CHANGELOG.md +7 -0
- package/dist/esm/index.js +188 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +225 -0
- package/dist/index.js.map +1 -0
- package/jest.config.js +9 -0
- package/package.json +44 -0
- package/src/Select.stories.tsx +53 -0
- package/src/Select.tsx +65 -0
- package/src/SelectTypes.ts +35 -0
- package/src/__tests__/Select.test.tsx +67 -0
- package/src/index.ts +5 -0
- package/src/styled.d.ts +7 -0
- package/src/styles.ts +129 -0
- package/tsconfig.json +9 -0
- package/tsup.config.ts +12 -0
package/.eslintignore
ADDED
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
yarn run v1.22.22
|
|
2
|
+
$ tsup --dts
|
|
3
|
+
CLI Building entry: src/index.ts
|
|
4
|
+
CLI Using tsconfig: tsconfig.json
|
|
5
|
+
CLI tsup v8.0.2
|
|
6
|
+
CLI Using tsup config: /home/runner/work/seeds/seeds/seeds-react/seeds-react-select/tsup.config.ts
|
|
7
|
+
CLI Target: es2022
|
|
8
|
+
CLI Cleaning output folder
|
|
9
|
+
CJS Build start
|
|
10
|
+
ESM Build start
|
|
11
|
+
CJS dist/index.js 6.66 KB
|
|
12
|
+
CJS dist/index.js.map 9.82 KB
|
|
13
|
+
CJS ⚡️ Build success in 163ms
|
|
14
|
+
ESM dist/esm/index.js 4.70 KB
|
|
15
|
+
ESM dist/esm/index.js.map 9.74 KB
|
|
16
|
+
ESM ⚡️ Build success in 168ms
|
|
17
|
+
DTS Build start
|
|
18
|
+
DTS ⚡️ Build success in 37165ms
|
|
19
|
+
DTS dist/index.d.ts 1.52 KB
|
|
20
|
+
DTS dist/index.d.mts 1.52 KB
|
|
21
|
+
Done in 43.16s.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// src/Select.tsx
|
|
2
|
+
import "react";
|
|
3
|
+
import Icon from "@sproutsocial/seeds-react-icon";
|
|
4
|
+
|
|
5
|
+
// src/styles.ts
|
|
6
|
+
import styled, { css } from "styled-components";
|
|
7
|
+
import { focusRing } from "@sproutsocial/seeds-react-mixins";
|
|
8
|
+
import { COMMON } from "@sproutsocial/seeds-react-system-props";
|
|
9
|
+
var Container = styled.div`
|
|
10
|
+
position: relative;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
|
|
13
|
+
select {
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
width: 100%;
|
|
16
|
+
border: 1px solid ${(props) => props.theme.colors.form.border.base};
|
|
17
|
+
border-radius: ${(props) => props.theme.radii[500]};
|
|
18
|
+
background-color: ${(props) => props.theme.colors.form.background.base};
|
|
19
|
+
color: ${(props) => props.theme.colors.text.body};
|
|
20
|
+
cursor: ${(props) => props.disabled ? "not-allowed" : "pointer"};
|
|
21
|
+
outline: none;
|
|
22
|
+
appearance: none;
|
|
23
|
+
transition: border-color ${(props) => props.theme.duration.fast}
|
|
24
|
+
${(props) => props.theme.easing.ease_in},
|
|
25
|
+
box-shadow ${(props) => props.theme.duration.fast}
|
|
26
|
+
${(props) => props.theme.easing.ease_in};
|
|
27
|
+
font-family: ${(props) => props.theme.fontFamily};
|
|
28
|
+
font-weight: ${(props) => props.theme.fontWeights.normal};
|
|
29
|
+
margin: 0;
|
|
30
|
+
/* We do this because the Sprout app sets it to hidden in Classic mode. We can delete after Nectar launches. */
|
|
31
|
+
visibility: visible;
|
|
32
|
+
|
|
33
|
+
padding: ${(props) => {
|
|
34
|
+
switch (props.size) {
|
|
35
|
+
case "large":
|
|
36
|
+
return `${props.theme.space[350]} ${props.theme.space[600]} ${props.theme.space[350]} ${props.theme.space[400]}`;
|
|
37
|
+
case "small":
|
|
38
|
+
return `${props.theme.space[200]} ${props.theme.space[500]} ${props.theme.space[200]} ${props.theme.space[200]}`;
|
|
39
|
+
case "default":
|
|
40
|
+
default:
|
|
41
|
+
return `${props.theme.space[300]} ${props.theme.space[500]} ${props.theme.space[300]} ${props.theme.space[300]}`;
|
|
42
|
+
}
|
|
43
|
+
}};
|
|
44
|
+
font-size: ${(props) => {
|
|
45
|
+
switch (props.size) {
|
|
46
|
+
case "large":
|
|
47
|
+
return props.theme.typography[300].fontSize;
|
|
48
|
+
case "small":
|
|
49
|
+
case "default":
|
|
50
|
+
default:
|
|
51
|
+
return props.theme.typography[200].fontSize;
|
|
52
|
+
}
|
|
53
|
+
}};
|
|
54
|
+
|
|
55
|
+
line-height: ${(props) => {
|
|
56
|
+
switch (props.size) {
|
|
57
|
+
case "large":
|
|
58
|
+
return props.theme.typography[300].lineHeight;
|
|
59
|
+
case "small":
|
|
60
|
+
case "default":
|
|
61
|
+
default:
|
|
62
|
+
return "normal";
|
|
63
|
+
}
|
|
64
|
+
}};
|
|
65
|
+
|
|
66
|
+
/* kill the dropdown arrow on IE 11 */
|
|
67
|
+
&::-ms-expand {
|
|
68
|
+
display: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&:focus {
|
|
72
|
+
${focusRing}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Fix for red ring when input is marked required in Firefox */
|
|
76
|
+
&:not(output):not(:focus):-moz-ui-invalid {
|
|
77
|
+
box-shadow: none;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
${(props) => props.disabled && css`
|
|
82
|
+
opacity: 0.4;
|
|
83
|
+
`}
|
|
84
|
+
|
|
85
|
+
${(props) => props.invalid && css`
|
|
86
|
+
select {
|
|
87
|
+
border-color: ${(props2) => props2.theme.colors.form.border.error};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
${Arrow} {
|
|
91
|
+
color: ${(props2) => props2.theme.colors.icon.error};
|
|
92
|
+
}
|
|
93
|
+
`}
|
|
94
|
+
|
|
95
|
+
${COMMON}
|
|
96
|
+
`;
|
|
97
|
+
var Arrow = styled.span`
|
|
98
|
+
position: absolute;
|
|
99
|
+
top: 50%;
|
|
100
|
+
right: ${(props) => {
|
|
101
|
+
switch (props.size) {
|
|
102
|
+
case "large":
|
|
103
|
+
return props.theme.space[350];
|
|
104
|
+
case "small":
|
|
105
|
+
case "default":
|
|
106
|
+
default:
|
|
107
|
+
return props.theme.space[300];
|
|
108
|
+
}
|
|
109
|
+
}};
|
|
110
|
+
transform: translateY(-50%);
|
|
111
|
+
color: ${(props) => props.theme.colors.icon.base};
|
|
112
|
+
pointer-events: none;
|
|
113
|
+
`;
|
|
114
|
+
Container.displayName = "SelectContainer";
|
|
115
|
+
Arrow.displayName = "Select Arrow";
|
|
116
|
+
var styles_default = Container;
|
|
117
|
+
|
|
118
|
+
// src/Select.tsx
|
|
119
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
120
|
+
var Select = ({
|
|
121
|
+
id,
|
|
122
|
+
name,
|
|
123
|
+
children,
|
|
124
|
+
defaultValue,
|
|
125
|
+
value,
|
|
126
|
+
required,
|
|
127
|
+
isInvalid,
|
|
128
|
+
onChange,
|
|
129
|
+
autoFocus,
|
|
130
|
+
disabled,
|
|
131
|
+
ariaLabel,
|
|
132
|
+
ariaDescribedby,
|
|
133
|
+
size = "default",
|
|
134
|
+
qa = {},
|
|
135
|
+
inputProps = {},
|
|
136
|
+
...rest
|
|
137
|
+
}) => {
|
|
138
|
+
const handleChange = (e) => {
|
|
139
|
+
if (onChange) {
|
|
140
|
+
onChange(e);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
return /* @__PURE__ */ jsxs(styles_default, { invalid: isInvalid, disabled, size, ...rest, children: [
|
|
144
|
+
/* @__PURE__ */ jsx(
|
|
145
|
+
"select",
|
|
146
|
+
{
|
|
147
|
+
id,
|
|
148
|
+
name,
|
|
149
|
+
"aria-label": ariaLabel,
|
|
150
|
+
"aria-describedby": ariaDescribedby,
|
|
151
|
+
defaultValue,
|
|
152
|
+
value,
|
|
153
|
+
required,
|
|
154
|
+
autoFocus,
|
|
155
|
+
disabled,
|
|
156
|
+
onChange: handleChange,
|
|
157
|
+
"data-qa-select": name || "",
|
|
158
|
+
"data-qa-select-value": value || "unselected",
|
|
159
|
+
"data-qa-select-isrequired": required === true,
|
|
160
|
+
"data-qa-select-isdisabled": disabled === true,
|
|
161
|
+
...qa,
|
|
162
|
+
...inputProps,
|
|
163
|
+
children
|
|
164
|
+
}
|
|
165
|
+
),
|
|
166
|
+
/* @__PURE__ */ jsx(Arrow, { size, children: /* @__PURE__ */ jsx(
|
|
167
|
+
Icon,
|
|
168
|
+
{
|
|
169
|
+
name: "chevron-down-outline",
|
|
170
|
+
fixedWidth: true,
|
|
171
|
+
size: size === "small" ? "small" : "medium",
|
|
172
|
+
"aria-hidden": true
|
|
173
|
+
}
|
|
174
|
+
) })
|
|
175
|
+
] });
|
|
176
|
+
};
|
|
177
|
+
var Select_default = Select;
|
|
178
|
+
|
|
179
|
+
// src/SelectTypes.ts
|
|
180
|
+
import "react";
|
|
181
|
+
|
|
182
|
+
// src/index.ts
|
|
183
|
+
var src_default = Select_default;
|
|
184
|
+
export {
|
|
185
|
+
Select_default as Select,
|
|
186
|
+
src_default as default
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/Select.tsx","../../src/styles.ts","../../src/SelectTypes.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport Container, { Arrow } from \"./styles\";\nimport type { TypeSelectProps } from \"./SelectTypes\";\n\nconst Select = ({\n id,\n name,\n children,\n defaultValue,\n value,\n required,\n isInvalid,\n onChange,\n autoFocus,\n disabled,\n ariaLabel,\n ariaDescribedby,\n size = \"default\",\n qa = {},\n inputProps = {},\n ...rest\n}: TypeSelectProps) => {\n const handleChange = (e: React.SyntheticEvent<HTMLSelectElement>) => {\n if (onChange) {\n onChange(e);\n }\n };\n\n return (\n <Container invalid={isInvalid} disabled={disabled} size={size} {...rest}>\n <select\n id={id}\n name={name}\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedby}\n defaultValue={defaultValue}\n value={value}\n required={required}\n autoFocus={autoFocus}\n disabled={disabled}\n onChange={handleChange}\n data-qa-select={name || \"\"}\n data-qa-select-value={value || \"unselected\"}\n data-qa-select-isrequired={required === true}\n data-qa-select-isdisabled={disabled === true}\n {...qa}\n {...inputProps}\n >\n {children}\n </select>\n\n <Arrow size={size}>\n <Icon\n name=\"chevron-down-outline\"\n fixedWidth\n size={size === \"small\" ? \"small\" : \"medium\"}\n aria-hidden\n />\n </Arrow>\n </Container>\n );\n};\n\nexport default Select;\n","import styled, { css } from \"styled-components\";\nimport { focusRing } from \"@sproutsocial/seeds-react-mixins\";\nimport { COMMON } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeSelectProps } from \"./SelectTypes\";\n\ninterface TypeSelectContainer extends Omit<TypeSelectProps, \"isInvalid\"> {\n invalid?: boolean;\n}\n\nconst Container = styled.div<TypeSelectContainer>`\n position: relative;\n box-sizing: border-box;\n\n select {\n box-sizing: border-box;\n width: 100%;\n border: 1px solid ${(props) => props.theme.colors.form.border.base};\n border-radius: ${(props) => props.theme.radii[500]};\n background-color: ${(props) => props.theme.colors.form.background.base};\n color: ${(props) => props.theme.colors.text.body};\n cursor: ${(props) => (props.disabled ? \"not-allowed\" : \"pointer\")};\n outline: none;\n appearance: none;\n transition: border-color ${(props) => props.theme.duration.fast}\n ${(props) => props.theme.easing.ease_in},\n box-shadow ${(props) => props.theme.duration.fast}\n ${(props) => props.theme.easing.ease_in};\n font-family: ${(props) => props.theme.fontFamily};\n font-weight: ${(props) => props.theme.fontWeights.normal};\n margin: 0;\n /* We do this because the Sprout app sets it to hidden in Classic mode. We can delete after Nectar launches. */\n visibility: visible;\n\n padding: ${(props) => {\n switch (props.size) {\n case \"large\":\n return `${props.theme.space[350]} ${props.theme.space[600]} ${props.theme.space[350]} ${props.theme.space[400]}`;\n\n case \"small\":\n return `${props.theme.space[200]} ${props.theme.space[500]} ${props.theme.space[200]} ${props.theme.space[200]}`;\n\n case \"default\":\n default:\n return `${props.theme.space[300]} ${props.theme.space[500]} ${props.theme.space[300]} ${props.theme.space[300]}`;\n }\n }};\n font-size: ${(props) => {\n switch (props.size) {\n case \"large\":\n return props.theme.typography[300].fontSize;\n\n case \"small\":\n case \"default\":\n default:\n return props.theme.typography[200].fontSize;\n }\n }};\n\n line-height: ${(props) => {\n switch (props.size) {\n case \"large\":\n return props.theme.typography[300].lineHeight;\n\n /* hardcoded to 'normal' so the large change doesn't impact small/default */\n case \"small\":\n case \"default\":\n default:\n return \"normal\";\n }\n }};\n\n /* kill the dropdown arrow on IE 11 */\n &::-ms-expand {\n display: none;\n }\n\n &:focus {\n ${focusRing}\n }\n\n /* Fix for red ring when input is marked required in Firefox */\n &:not(output):not(:focus):-moz-ui-invalid {\n box-shadow: none;\n }\n }\n\n ${(props) =>\n props.disabled &&\n css`\n opacity: 0.4;\n `}\n\n ${(props) =>\n props.invalid &&\n css`\n select {\n border-color: ${(props) => props.theme.colors.form.border.error};\n }\n\n ${Arrow} {\n color: ${(props) => props.theme.colors.icon.error};\n }\n `}\n\n ${COMMON}\n`;\n\nexport const Arrow = styled.span<Pick<TypeSelectProps, \"size\">>`\n position: absolute;\n top: 50%;\n right: ${(props) => {\n switch (props.size) {\n case \"large\":\n return props.theme.space[350];\n case \"small\":\n case \"default\":\n default:\n return props.theme.space[300];\n }\n }};\n transform: translateY(-50%);\n color: ${(props) => props.theme.colors.icon.base};\n pointer-events: none;\n`;\n\nContainer.displayName = \"SelectContainer\";\nArrow.displayName = \"Select Arrow\";\n\nexport default Container;\n","import * as React from \"react\";\nimport type {\n TypeSystemCommonProps,\n TypeStyledComponentsCommonProps,\n} from \"@sproutsocial/seeds-react-system-props\";\n\nexport interface TypeSelectProps\n extends TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n Omit<React.ComponentPropsWithoutRef<\"div\">, \"color\" | \"onChange\"> {\n /** ID of the form element, should match the \"for\" value of the associated label */\n id: string;\n name: string;\n\n /** Label used to describe the select if not used with an accompanying visual label */\n ariaLabel?: string;\n\n /** Attribute used to associate other elements that describe the Select, like an error */\n ariaDescribedby?: string;\n children: React.ReactNode;\n defaultValue?: React.ComponentPropsWithoutRef<\"select\">[\"value\"];\n\n /** Current value of the input */\n value?: React.ComponentPropsWithoutRef<\"select\">[\"value\"];\n required?: boolean;\n isInvalid?: boolean;\n autoFocus?: boolean;\n disabled?: boolean;\n\n /** Props to spread onto the underlying input element */\n inputProps?: React.ComponentPropsWithRef<\"select\">;\n qa?: object;\n onChange?: (e: React.SyntheticEvent<HTMLSelectElement>) => void;\n size?: \"large\" | \"small\" | \"default\";\n}\n","import Select from \"./Select\";\n\nexport default Select;\nexport { Select };\nexport * from \"./SelectTypes\";\n"],"mappings":"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","names":["props"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { TypeStyledComponentsCommonProps, TypeSystemCommonProps } from '@sproutsocial/seeds-react-system-props';
|
|
4
|
+
|
|
5
|
+
interface TypeSelectProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"div">, "color" | "onChange"> {
|
|
6
|
+
/** ID of the form element, should match the "for" value of the associated label */
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
/** Label used to describe the select if not used with an accompanying visual label */
|
|
10
|
+
ariaLabel?: string;
|
|
11
|
+
/** Attribute used to associate other elements that describe the Select, like an error */
|
|
12
|
+
ariaDescribedby?: string;
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
defaultValue?: React.ComponentPropsWithoutRef<"select">["value"];
|
|
15
|
+
/** Current value of the input */
|
|
16
|
+
value?: React.ComponentPropsWithoutRef<"select">["value"];
|
|
17
|
+
required?: boolean;
|
|
18
|
+
isInvalid?: boolean;
|
|
19
|
+
autoFocus?: boolean;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/** Props to spread onto the underlying input element */
|
|
22
|
+
inputProps?: React.ComponentPropsWithRef<"select">;
|
|
23
|
+
qa?: object;
|
|
24
|
+
onChange?: (e: React.SyntheticEvent<HTMLSelectElement>) => void;
|
|
25
|
+
size?: "large" | "small" | "default";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare const Select: ({ id, name, children, defaultValue, value, required, isInvalid, onChange, autoFocus, disabled, ariaLabel, ariaDescribedby, size, qa, inputProps, ...rest }: TypeSelectProps) => react_jsx_runtime.JSX.Element;
|
|
29
|
+
|
|
30
|
+
export { Select, type TypeSelectProps, Select as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { TypeStyledComponentsCommonProps, TypeSystemCommonProps } from '@sproutsocial/seeds-react-system-props';
|
|
4
|
+
|
|
5
|
+
interface TypeSelectProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"div">, "color" | "onChange"> {
|
|
6
|
+
/** ID of the form element, should match the "for" value of the associated label */
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
/** Label used to describe the select if not used with an accompanying visual label */
|
|
10
|
+
ariaLabel?: string;
|
|
11
|
+
/** Attribute used to associate other elements that describe the Select, like an error */
|
|
12
|
+
ariaDescribedby?: string;
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
defaultValue?: React.ComponentPropsWithoutRef<"select">["value"];
|
|
15
|
+
/** Current value of the input */
|
|
16
|
+
value?: React.ComponentPropsWithoutRef<"select">["value"];
|
|
17
|
+
required?: boolean;
|
|
18
|
+
isInvalid?: boolean;
|
|
19
|
+
autoFocus?: boolean;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/** Props to spread onto the underlying input element */
|
|
22
|
+
inputProps?: React.ComponentPropsWithRef<"select">;
|
|
23
|
+
qa?: object;
|
|
24
|
+
onChange?: (e: React.SyntheticEvent<HTMLSelectElement>) => void;
|
|
25
|
+
size?: "large" | "small" | "default";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare const Select: ({ id, name, children, defaultValue, value, required, isInvalid, onChange, autoFocus, disabled, ariaLabel, ariaDescribedby, size, qa, inputProps, ...rest }: TypeSelectProps) => react_jsx_runtime.JSX.Element;
|
|
29
|
+
|
|
30
|
+
export { Select, type TypeSelectProps, Select as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
Select: () => Select_default,
|
|
34
|
+
default: () => src_default
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(src_exports);
|
|
37
|
+
|
|
38
|
+
// src/Select.tsx
|
|
39
|
+
var React = require("react");
|
|
40
|
+
var import_seeds_react_icon = __toESM(require("@sproutsocial/seeds-react-icon"));
|
|
41
|
+
|
|
42
|
+
// src/styles.ts
|
|
43
|
+
var import_styled_components = __toESM(require("styled-components"));
|
|
44
|
+
var import_seeds_react_mixins = require("@sproutsocial/seeds-react-mixins");
|
|
45
|
+
var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
|
|
46
|
+
var Container = import_styled_components.default.div`
|
|
47
|
+
position: relative;
|
|
48
|
+
box-sizing: border-box;
|
|
49
|
+
|
|
50
|
+
select {
|
|
51
|
+
box-sizing: border-box;
|
|
52
|
+
width: 100%;
|
|
53
|
+
border: 1px solid ${(props) => props.theme.colors.form.border.base};
|
|
54
|
+
border-radius: ${(props) => props.theme.radii[500]};
|
|
55
|
+
background-color: ${(props) => props.theme.colors.form.background.base};
|
|
56
|
+
color: ${(props) => props.theme.colors.text.body};
|
|
57
|
+
cursor: ${(props) => props.disabled ? "not-allowed" : "pointer"};
|
|
58
|
+
outline: none;
|
|
59
|
+
appearance: none;
|
|
60
|
+
transition: border-color ${(props) => props.theme.duration.fast}
|
|
61
|
+
${(props) => props.theme.easing.ease_in},
|
|
62
|
+
box-shadow ${(props) => props.theme.duration.fast}
|
|
63
|
+
${(props) => props.theme.easing.ease_in};
|
|
64
|
+
font-family: ${(props) => props.theme.fontFamily};
|
|
65
|
+
font-weight: ${(props) => props.theme.fontWeights.normal};
|
|
66
|
+
margin: 0;
|
|
67
|
+
/* We do this because the Sprout app sets it to hidden in Classic mode. We can delete after Nectar launches. */
|
|
68
|
+
visibility: visible;
|
|
69
|
+
|
|
70
|
+
padding: ${(props) => {
|
|
71
|
+
switch (props.size) {
|
|
72
|
+
case "large":
|
|
73
|
+
return `${props.theme.space[350]} ${props.theme.space[600]} ${props.theme.space[350]} ${props.theme.space[400]}`;
|
|
74
|
+
case "small":
|
|
75
|
+
return `${props.theme.space[200]} ${props.theme.space[500]} ${props.theme.space[200]} ${props.theme.space[200]}`;
|
|
76
|
+
case "default":
|
|
77
|
+
default:
|
|
78
|
+
return `${props.theme.space[300]} ${props.theme.space[500]} ${props.theme.space[300]} ${props.theme.space[300]}`;
|
|
79
|
+
}
|
|
80
|
+
}};
|
|
81
|
+
font-size: ${(props) => {
|
|
82
|
+
switch (props.size) {
|
|
83
|
+
case "large":
|
|
84
|
+
return props.theme.typography[300].fontSize;
|
|
85
|
+
case "small":
|
|
86
|
+
case "default":
|
|
87
|
+
default:
|
|
88
|
+
return props.theme.typography[200].fontSize;
|
|
89
|
+
}
|
|
90
|
+
}};
|
|
91
|
+
|
|
92
|
+
line-height: ${(props) => {
|
|
93
|
+
switch (props.size) {
|
|
94
|
+
case "large":
|
|
95
|
+
return props.theme.typography[300].lineHeight;
|
|
96
|
+
case "small":
|
|
97
|
+
case "default":
|
|
98
|
+
default:
|
|
99
|
+
return "normal";
|
|
100
|
+
}
|
|
101
|
+
}};
|
|
102
|
+
|
|
103
|
+
/* kill the dropdown arrow on IE 11 */
|
|
104
|
+
&::-ms-expand {
|
|
105
|
+
display: none;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&:focus {
|
|
109
|
+
${import_seeds_react_mixins.focusRing}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Fix for red ring when input is marked required in Firefox */
|
|
113
|
+
&:not(output):not(:focus):-moz-ui-invalid {
|
|
114
|
+
box-shadow: none;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
${(props) => props.disabled && import_styled_components.css`
|
|
119
|
+
opacity: 0.4;
|
|
120
|
+
`}
|
|
121
|
+
|
|
122
|
+
${(props) => props.invalid && import_styled_components.css`
|
|
123
|
+
select {
|
|
124
|
+
border-color: ${(props2) => props2.theme.colors.form.border.error};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
${Arrow} {
|
|
128
|
+
color: ${(props2) => props2.theme.colors.icon.error};
|
|
129
|
+
}
|
|
130
|
+
`}
|
|
131
|
+
|
|
132
|
+
${import_seeds_react_system_props.COMMON}
|
|
133
|
+
`;
|
|
134
|
+
var Arrow = import_styled_components.default.span`
|
|
135
|
+
position: absolute;
|
|
136
|
+
top: 50%;
|
|
137
|
+
right: ${(props) => {
|
|
138
|
+
switch (props.size) {
|
|
139
|
+
case "large":
|
|
140
|
+
return props.theme.space[350];
|
|
141
|
+
case "small":
|
|
142
|
+
case "default":
|
|
143
|
+
default:
|
|
144
|
+
return props.theme.space[300];
|
|
145
|
+
}
|
|
146
|
+
}};
|
|
147
|
+
transform: translateY(-50%);
|
|
148
|
+
color: ${(props) => props.theme.colors.icon.base};
|
|
149
|
+
pointer-events: none;
|
|
150
|
+
`;
|
|
151
|
+
Container.displayName = "SelectContainer";
|
|
152
|
+
Arrow.displayName = "Select Arrow";
|
|
153
|
+
var styles_default = Container;
|
|
154
|
+
|
|
155
|
+
// src/Select.tsx
|
|
156
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
157
|
+
var Select = ({
|
|
158
|
+
id,
|
|
159
|
+
name,
|
|
160
|
+
children,
|
|
161
|
+
defaultValue,
|
|
162
|
+
value,
|
|
163
|
+
required,
|
|
164
|
+
isInvalid,
|
|
165
|
+
onChange,
|
|
166
|
+
autoFocus,
|
|
167
|
+
disabled,
|
|
168
|
+
ariaLabel,
|
|
169
|
+
ariaDescribedby,
|
|
170
|
+
size = "default",
|
|
171
|
+
qa = {},
|
|
172
|
+
inputProps = {},
|
|
173
|
+
...rest
|
|
174
|
+
}) => {
|
|
175
|
+
const handleChange = (e) => {
|
|
176
|
+
if (onChange) {
|
|
177
|
+
onChange(e);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(styles_default, { invalid: isInvalid, disabled, size, ...rest, children: [
|
|
181
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
182
|
+
"select",
|
|
183
|
+
{
|
|
184
|
+
id,
|
|
185
|
+
name,
|
|
186
|
+
"aria-label": ariaLabel,
|
|
187
|
+
"aria-describedby": ariaDescribedby,
|
|
188
|
+
defaultValue,
|
|
189
|
+
value,
|
|
190
|
+
required,
|
|
191
|
+
autoFocus,
|
|
192
|
+
disabled,
|
|
193
|
+
onChange: handleChange,
|
|
194
|
+
"data-qa-select": name || "",
|
|
195
|
+
"data-qa-select-value": value || "unselected",
|
|
196
|
+
"data-qa-select-isrequired": required === true,
|
|
197
|
+
"data-qa-select-isdisabled": disabled === true,
|
|
198
|
+
...qa,
|
|
199
|
+
...inputProps,
|
|
200
|
+
children
|
|
201
|
+
}
|
|
202
|
+
),
|
|
203
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Arrow, { size, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
204
|
+
import_seeds_react_icon.default,
|
|
205
|
+
{
|
|
206
|
+
name: "chevron-down-outline",
|
|
207
|
+
fixedWidth: true,
|
|
208
|
+
size: size === "small" ? "small" : "medium",
|
|
209
|
+
"aria-hidden": true
|
|
210
|
+
}
|
|
211
|
+
) })
|
|
212
|
+
] });
|
|
213
|
+
};
|
|
214
|
+
var Select_default = Select;
|
|
215
|
+
|
|
216
|
+
// src/SelectTypes.ts
|
|
217
|
+
var React2 = require("react");
|
|
218
|
+
|
|
219
|
+
// src/index.ts
|
|
220
|
+
var src_default = Select_default;
|
|
221
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
222
|
+
0 && (module.exports = {
|
|
223
|
+
Select
|
|
224
|
+
});
|
|
225
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Select.tsx","../src/styles.ts","../src/SelectTypes.ts"],"sourcesContent":["import Select from \"./Select\";\n\nexport default Select;\nexport { Select };\nexport * from \"./SelectTypes\";\n","import * as React from \"react\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport Container, { Arrow } from \"./styles\";\nimport type { TypeSelectProps } from \"./SelectTypes\";\n\nconst Select = ({\n id,\n name,\n children,\n defaultValue,\n value,\n required,\n isInvalid,\n onChange,\n autoFocus,\n disabled,\n ariaLabel,\n ariaDescribedby,\n size = \"default\",\n qa = {},\n inputProps = {},\n ...rest\n}: TypeSelectProps) => {\n const handleChange = (e: React.SyntheticEvent<HTMLSelectElement>) => {\n if (onChange) {\n onChange(e);\n }\n };\n\n return (\n <Container invalid={isInvalid} disabled={disabled} size={size} {...rest}>\n <select\n id={id}\n name={name}\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedby}\n defaultValue={defaultValue}\n value={value}\n required={required}\n autoFocus={autoFocus}\n disabled={disabled}\n onChange={handleChange}\n data-qa-select={name || \"\"}\n data-qa-select-value={value || \"unselected\"}\n data-qa-select-isrequired={required === true}\n data-qa-select-isdisabled={disabled === true}\n {...qa}\n {...inputProps}\n >\n {children}\n </select>\n\n <Arrow size={size}>\n <Icon\n name=\"chevron-down-outline\"\n fixedWidth\n size={size === \"small\" ? \"small\" : \"medium\"}\n aria-hidden\n />\n </Arrow>\n </Container>\n );\n};\n\nexport default Select;\n","import styled, { css } from \"styled-components\";\nimport { focusRing } from \"@sproutsocial/seeds-react-mixins\";\nimport { COMMON } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeSelectProps } from \"./SelectTypes\";\n\ninterface TypeSelectContainer extends Omit<TypeSelectProps, \"isInvalid\"> {\n invalid?: boolean;\n}\n\nconst Container = styled.div<TypeSelectContainer>`\n position: relative;\n box-sizing: border-box;\n\n select {\n box-sizing: border-box;\n width: 100%;\n border: 1px solid ${(props) => props.theme.colors.form.border.base};\n border-radius: ${(props) => props.theme.radii[500]};\n background-color: ${(props) => props.theme.colors.form.background.base};\n color: ${(props) => props.theme.colors.text.body};\n cursor: ${(props) => (props.disabled ? \"not-allowed\" : \"pointer\")};\n outline: none;\n appearance: none;\n transition: border-color ${(props) => props.theme.duration.fast}\n ${(props) => props.theme.easing.ease_in},\n box-shadow ${(props) => props.theme.duration.fast}\n ${(props) => props.theme.easing.ease_in};\n font-family: ${(props) => props.theme.fontFamily};\n font-weight: ${(props) => props.theme.fontWeights.normal};\n margin: 0;\n /* We do this because the Sprout app sets it to hidden in Classic mode. We can delete after Nectar launches. */\n visibility: visible;\n\n padding: ${(props) => {\n switch (props.size) {\n case \"large\":\n return `${props.theme.space[350]} ${props.theme.space[600]} ${props.theme.space[350]} ${props.theme.space[400]}`;\n\n case \"small\":\n return `${props.theme.space[200]} ${props.theme.space[500]} ${props.theme.space[200]} ${props.theme.space[200]}`;\n\n case \"default\":\n default:\n return `${props.theme.space[300]} ${props.theme.space[500]} ${props.theme.space[300]} ${props.theme.space[300]}`;\n }\n }};\n font-size: ${(props) => {\n switch (props.size) {\n case \"large\":\n return props.theme.typography[300].fontSize;\n\n case \"small\":\n case \"default\":\n default:\n return props.theme.typography[200].fontSize;\n }\n }};\n\n line-height: ${(props) => {\n switch (props.size) {\n case \"large\":\n return props.theme.typography[300].lineHeight;\n\n /* hardcoded to 'normal' so the large change doesn't impact small/default */\n case \"small\":\n case \"default\":\n default:\n return \"normal\";\n }\n }};\n\n /* kill the dropdown arrow on IE 11 */\n &::-ms-expand {\n display: none;\n }\n\n &:focus {\n ${focusRing}\n }\n\n /* Fix for red ring when input is marked required in Firefox */\n &:not(output):not(:focus):-moz-ui-invalid {\n box-shadow: none;\n }\n }\n\n ${(props) =>\n props.disabled &&\n css`\n opacity: 0.4;\n `}\n\n ${(props) =>\n props.invalid &&\n css`\n select {\n border-color: ${(props) => props.theme.colors.form.border.error};\n }\n\n ${Arrow} {\n color: ${(props) => props.theme.colors.icon.error};\n }\n `}\n\n ${COMMON}\n`;\n\nexport const Arrow = styled.span<Pick<TypeSelectProps, \"size\">>`\n position: absolute;\n top: 50%;\n right: ${(props) => {\n switch (props.size) {\n case \"large\":\n return props.theme.space[350];\n case \"small\":\n case \"default\":\n default:\n return props.theme.space[300];\n }\n }};\n transform: translateY(-50%);\n color: ${(props) => props.theme.colors.icon.base};\n pointer-events: none;\n`;\n\nContainer.displayName = \"SelectContainer\";\nArrow.displayName = \"Select Arrow\";\n\nexport default Container;\n","import * as React from \"react\";\nimport type {\n TypeSystemCommonProps,\n TypeStyledComponentsCommonProps,\n} from \"@sproutsocial/seeds-react-system-props\";\n\nexport interface TypeSelectProps\n extends TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n Omit<React.ComponentPropsWithoutRef<\"div\">, \"color\" | \"onChange\"> {\n /** ID of the form element, should match the \"for\" value of the associated label */\n id: string;\n name: string;\n\n /** Label used to describe the select if not used with an accompanying visual label */\n ariaLabel?: string;\n\n /** Attribute used to associate other elements that describe the Select, like an error */\n ariaDescribedby?: string;\n children: React.ReactNode;\n defaultValue?: React.ComponentPropsWithoutRef<\"select\">[\"value\"];\n\n /** Current value of the input */\n value?: React.ComponentPropsWithoutRef<\"select\">[\"value\"];\n required?: boolean;\n isInvalid?: boolean;\n autoFocus?: boolean;\n disabled?: boolean;\n\n /** Props to spread onto the underlying input element */\n inputProps?: React.ComponentPropsWithRef<\"select\">;\n qa?: object;\n onChange?: (e: React.SyntheticEvent<HTMLSelectElement>) => void;\n size?: \"large\" | \"small\" | \"default\";\n}\n"],"mappings":"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","names":["styled","props","Icon","React"]}
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sproutsocial/seeds-react-select",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Seeds React Select",
|
|
5
|
+
"author": "Sprout Social, Inc.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/esm/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsup --dts",
|
|
12
|
+
"build:debug": "tsup --dts --metafile",
|
|
13
|
+
"dev": "tsup --watch --dts",
|
|
14
|
+
"clean": "rm -rf .turbo dist",
|
|
15
|
+
"clean:modules": "rm -rf node_modules",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"test": "jest",
|
|
18
|
+
"test:watch": "jest --watch --coverage=false"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@sproutsocial/seeds-react-theme": "*",
|
|
22
|
+
"@sproutsocial/seeds-react-system-props": "*",
|
|
23
|
+
"@sproutsocial/seeds-react-icon": "*",
|
|
24
|
+
"@sproutsocial/seeds-react-mixins": "*"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/react": "^18.0.0",
|
|
28
|
+
"@types/styled-components": "^5.1.26",
|
|
29
|
+
"@sproutsocial/eslint-config-seeds": "*",
|
|
30
|
+
"react": "^18.0.0",
|
|
31
|
+
"styled-components": "^5.2.3",
|
|
32
|
+
"tsup": "^8.0.2",
|
|
33
|
+
"typescript": "^5.6.2",
|
|
34
|
+
"@sproutsocial/seeds-tsconfig": "*",
|
|
35
|
+
"@sproutsocial/seeds-testing": "*",
|
|
36
|
+
"@sproutsocial/seeds-react-testing-library": "*"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"styled-components": "^5.2.3"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import Select from "./Select";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Select> = {
|
|
6
|
+
title: "Components/Form Elements/Select",
|
|
7
|
+
component: Select,
|
|
8
|
+
argTypes: {
|
|
9
|
+
size: {
|
|
10
|
+
options: ["small", "large", undefined],
|
|
11
|
+
control: {
|
|
12
|
+
type: "select",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
children: {
|
|
16
|
+
control: "object",
|
|
17
|
+
},
|
|
18
|
+
disabled: {
|
|
19
|
+
control: "boolean",
|
|
20
|
+
},
|
|
21
|
+
required: {
|
|
22
|
+
control: "boolean",
|
|
23
|
+
},
|
|
24
|
+
isInvalid: {
|
|
25
|
+
control: "boolean",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
args: {
|
|
29
|
+
size: undefined,
|
|
30
|
+
disabled: false,
|
|
31
|
+
required: false,
|
|
32
|
+
isInvalid: false,
|
|
33
|
+
children: [
|
|
34
|
+
<option value="" disabled selected>
|
|
35
|
+
Select One
|
|
36
|
+
</option>,
|
|
37
|
+
<option value="apple">Apple</option>,
|
|
38
|
+
<option value="orange">Orange</option>,
|
|
39
|
+
<option value="banana">Banana</option>,
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export default meta;
|
|
44
|
+
|
|
45
|
+
type Story = StoryObj<typeof Select>;
|
|
46
|
+
|
|
47
|
+
export const Default: Story = {};
|
|
48
|
+
|
|
49
|
+
export const Large: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
size: "large",
|
|
52
|
+
},
|
|
53
|
+
};
|
package/src/Select.tsx
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import Icon from "@sproutsocial/seeds-react-icon";
|
|
3
|
+
import Container, { Arrow } from "./styles";
|
|
4
|
+
import type { TypeSelectProps } from "./SelectTypes";
|
|
5
|
+
|
|
6
|
+
const Select = ({
|
|
7
|
+
id,
|
|
8
|
+
name,
|
|
9
|
+
children,
|
|
10
|
+
defaultValue,
|
|
11
|
+
value,
|
|
12
|
+
required,
|
|
13
|
+
isInvalid,
|
|
14
|
+
onChange,
|
|
15
|
+
autoFocus,
|
|
16
|
+
disabled,
|
|
17
|
+
ariaLabel,
|
|
18
|
+
ariaDescribedby,
|
|
19
|
+
size = "default",
|
|
20
|
+
qa = {},
|
|
21
|
+
inputProps = {},
|
|
22
|
+
...rest
|
|
23
|
+
}: TypeSelectProps) => {
|
|
24
|
+
const handleChange = (e: React.SyntheticEvent<HTMLSelectElement>) => {
|
|
25
|
+
if (onChange) {
|
|
26
|
+
onChange(e);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Container invalid={isInvalid} disabled={disabled} size={size} {...rest}>
|
|
32
|
+
<select
|
|
33
|
+
id={id}
|
|
34
|
+
name={name}
|
|
35
|
+
aria-label={ariaLabel}
|
|
36
|
+
aria-describedby={ariaDescribedby}
|
|
37
|
+
defaultValue={defaultValue}
|
|
38
|
+
value={value}
|
|
39
|
+
required={required}
|
|
40
|
+
autoFocus={autoFocus}
|
|
41
|
+
disabled={disabled}
|
|
42
|
+
onChange={handleChange}
|
|
43
|
+
data-qa-select={name || ""}
|
|
44
|
+
data-qa-select-value={value || "unselected"}
|
|
45
|
+
data-qa-select-isrequired={required === true}
|
|
46
|
+
data-qa-select-isdisabled={disabled === true}
|
|
47
|
+
{...qa}
|
|
48
|
+
{...inputProps}
|
|
49
|
+
>
|
|
50
|
+
{children}
|
|
51
|
+
</select>
|
|
52
|
+
|
|
53
|
+
<Arrow size={size}>
|
|
54
|
+
<Icon
|
|
55
|
+
name="chevron-down-outline"
|
|
56
|
+
fixedWidth
|
|
57
|
+
size={size === "small" ? "small" : "medium"}
|
|
58
|
+
aria-hidden
|
|
59
|
+
/>
|
|
60
|
+
</Arrow>
|
|
61
|
+
</Container>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default Select;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type {
|
|
3
|
+
TypeSystemCommonProps,
|
|
4
|
+
TypeStyledComponentsCommonProps,
|
|
5
|
+
} from "@sproutsocial/seeds-react-system-props";
|
|
6
|
+
|
|
7
|
+
export interface TypeSelectProps
|
|
8
|
+
extends TypeStyledComponentsCommonProps,
|
|
9
|
+
TypeSystemCommonProps,
|
|
10
|
+
Omit<React.ComponentPropsWithoutRef<"div">, "color" | "onChange"> {
|
|
11
|
+
/** ID of the form element, should match the "for" value of the associated label */
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
|
|
15
|
+
/** Label used to describe the select if not used with an accompanying visual label */
|
|
16
|
+
ariaLabel?: string;
|
|
17
|
+
|
|
18
|
+
/** Attribute used to associate other elements that describe the Select, like an error */
|
|
19
|
+
ariaDescribedby?: string;
|
|
20
|
+
children: React.ReactNode;
|
|
21
|
+
defaultValue?: React.ComponentPropsWithoutRef<"select">["value"];
|
|
22
|
+
|
|
23
|
+
/** Current value of the input */
|
|
24
|
+
value?: React.ComponentPropsWithoutRef<"select">["value"];
|
|
25
|
+
required?: boolean;
|
|
26
|
+
isInvalid?: boolean;
|
|
27
|
+
autoFocus?: boolean;
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
|
|
30
|
+
/** Props to spread onto the underlying input element */
|
|
31
|
+
inputProps?: React.ComponentPropsWithRef<"select">;
|
|
32
|
+
qa?: object;
|
|
33
|
+
onChange?: (e: React.SyntheticEvent<HTMLSelectElement>) => void;
|
|
34
|
+
size?: "large" | "small" | "default";
|
|
35
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
render,
|
|
4
|
+
fireEvent,
|
|
5
|
+
screen,
|
|
6
|
+
} from "@sproutsocial/seeds-react-testing-library";
|
|
7
|
+
import Select from "../Select";
|
|
8
|
+
|
|
9
|
+
describe("Select", () => {
|
|
10
|
+
it("should notify on changes", () => {
|
|
11
|
+
const mockOnChange = jest.fn();
|
|
12
|
+
render(
|
|
13
|
+
<Select id="select" name="select" onChange={mockOnChange}>
|
|
14
|
+
<option value="v">option1</option>
|
|
15
|
+
</Select>
|
|
16
|
+
);
|
|
17
|
+
fireEvent.change(
|
|
18
|
+
screen.getByDataQaLabel({
|
|
19
|
+
select: "select",
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
23
|
+
});
|
|
24
|
+
it("should render statuses correctly", () => {
|
|
25
|
+
const { rerender } = render(
|
|
26
|
+
<Select id="select" name="select" disabled>
|
|
27
|
+
<option value="v">option1</option>
|
|
28
|
+
</Select>
|
|
29
|
+
);
|
|
30
|
+
expect(
|
|
31
|
+
screen.getByDataQaLabel({
|
|
32
|
+
"select-isdisabled": "true",
|
|
33
|
+
})
|
|
34
|
+
).toBeTruthy();
|
|
35
|
+
rerender(
|
|
36
|
+
<Select id="select" name="select" disabled={false} isInvalid>
|
|
37
|
+
<option value="v">option1</option>
|
|
38
|
+
</Select>
|
|
39
|
+
);
|
|
40
|
+
expect(
|
|
41
|
+
screen.getByDataQaLabel({
|
|
42
|
+
"select-isdisabled": "false",
|
|
43
|
+
})
|
|
44
|
+
).toBeTruthy();
|
|
45
|
+
});
|
|
46
|
+
it("should render with chevron-down", () => {
|
|
47
|
+
render(
|
|
48
|
+
<Select
|
|
49
|
+
id="select"
|
|
50
|
+
name="select"
|
|
51
|
+
inputProps={{
|
|
52
|
+
style: {
|
|
53
|
+
display: "block",
|
|
54
|
+
margin: "200",
|
|
55
|
+
},
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
<option value="v">option1</option>
|
|
59
|
+
</Select>
|
|
60
|
+
);
|
|
61
|
+
expect(
|
|
62
|
+
screen.getByDataQaLabel({
|
|
63
|
+
icon: "chevron-down-outline",
|
|
64
|
+
})
|
|
65
|
+
).toBeTruthy();
|
|
66
|
+
});
|
|
67
|
+
});
|
package/src/index.ts
ADDED
package/src/styled.d.ts
ADDED
package/src/styles.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import styled, { css } from "styled-components";
|
|
2
|
+
import { focusRing } from "@sproutsocial/seeds-react-mixins";
|
|
3
|
+
import { COMMON } from "@sproutsocial/seeds-react-system-props";
|
|
4
|
+
import type { TypeSelectProps } from "./SelectTypes";
|
|
5
|
+
|
|
6
|
+
interface TypeSelectContainer extends Omit<TypeSelectProps, "isInvalid"> {
|
|
7
|
+
invalid?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Container = styled.div<TypeSelectContainer>`
|
|
11
|
+
position: relative;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
|
|
14
|
+
select {
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
width: 100%;
|
|
17
|
+
border: 1px solid ${(props) => props.theme.colors.form.border.base};
|
|
18
|
+
border-radius: ${(props) => props.theme.radii[500]};
|
|
19
|
+
background-color: ${(props) => props.theme.colors.form.background.base};
|
|
20
|
+
color: ${(props) => props.theme.colors.text.body};
|
|
21
|
+
cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};
|
|
22
|
+
outline: none;
|
|
23
|
+
appearance: none;
|
|
24
|
+
transition: border-color ${(props) => props.theme.duration.fast}
|
|
25
|
+
${(props) => props.theme.easing.ease_in},
|
|
26
|
+
box-shadow ${(props) => props.theme.duration.fast}
|
|
27
|
+
${(props) => props.theme.easing.ease_in};
|
|
28
|
+
font-family: ${(props) => props.theme.fontFamily};
|
|
29
|
+
font-weight: ${(props) => props.theme.fontWeights.normal};
|
|
30
|
+
margin: 0;
|
|
31
|
+
/* We do this because the Sprout app sets it to hidden in Classic mode. We can delete after Nectar launches. */
|
|
32
|
+
visibility: visible;
|
|
33
|
+
|
|
34
|
+
padding: ${(props) => {
|
|
35
|
+
switch (props.size) {
|
|
36
|
+
case "large":
|
|
37
|
+
return `${props.theme.space[350]} ${props.theme.space[600]} ${props.theme.space[350]} ${props.theme.space[400]}`;
|
|
38
|
+
|
|
39
|
+
case "small":
|
|
40
|
+
return `${props.theme.space[200]} ${props.theme.space[500]} ${props.theme.space[200]} ${props.theme.space[200]}`;
|
|
41
|
+
|
|
42
|
+
case "default":
|
|
43
|
+
default:
|
|
44
|
+
return `${props.theme.space[300]} ${props.theme.space[500]} ${props.theme.space[300]} ${props.theme.space[300]}`;
|
|
45
|
+
}
|
|
46
|
+
}};
|
|
47
|
+
font-size: ${(props) => {
|
|
48
|
+
switch (props.size) {
|
|
49
|
+
case "large":
|
|
50
|
+
return props.theme.typography[300].fontSize;
|
|
51
|
+
|
|
52
|
+
case "small":
|
|
53
|
+
case "default":
|
|
54
|
+
default:
|
|
55
|
+
return props.theme.typography[200].fontSize;
|
|
56
|
+
}
|
|
57
|
+
}};
|
|
58
|
+
|
|
59
|
+
line-height: ${(props) => {
|
|
60
|
+
switch (props.size) {
|
|
61
|
+
case "large":
|
|
62
|
+
return props.theme.typography[300].lineHeight;
|
|
63
|
+
|
|
64
|
+
/* hardcoded to 'normal' so the large change doesn't impact small/default */
|
|
65
|
+
case "small":
|
|
66
|
+
case "default":
|
|
67
|
+
default:
|
|
68
|
+
return "normal";
|
|
69
|
+
}
|
|
70
|
+
}};
|
|
71
|
+
|
|
72
|
+
/* kill the dropdown arrow on IE 11 */
|
|
73
|
+
&::-ms-expand {
|
|
74
|
+
display: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&:focus {
|
|
78
|
+
${focusRing}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Fix for red ring when input is marked required in Firefox */
|
|
82
|
+
&:not(output):not(:focus):-moz-ui-invalid {
|
|
83
|
+
box-shadow: none;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
${(props) =>
|
|
88
|
+
props.disabled &&
|
|
89
|
+
css`
|
|
90
|
+
opacity: 0.4;
|
|
91
|
+
`}
|
|
92
|
+
|
|
93
|
+
${(props) =>
|
|
94
|
+
props.invalid &&
|
|
95
|
+
css`
|
|
96
|
+
select {
|
|
97
|
+
border-color: ${(props) => props.theme.colors.form.border.error};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
${Arrow} {
|
|
101
|
+
color: ${(props) => props.theme.colors.icon.error};
|
|
102
|
+
}
|
|
103
|
+
`}
|
|
104
|
+
|
|
105
|
+
${COMMON}
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
export const Arrow = styled.span<Pick<TypeSelectProps, "size">>`
|
|
109
|
+
position: absolute;
|
|
110
|
+
top: 50%;
|
|
111
|
+
right: ${(props) => {
|
|
112
|
+
switch (props.size) {
|
|
113
|
+
case "large":
|
|
114
|
+
return props.theme.space[350];
|
|
115
|
+
case "small":
|
|
116
|
+
case "default":
|
|
117
|
+
default:
|
|
118
|
+
return props.theme.space[300];
|
|
119
|
+
}
|
|
120
|
+
}};
|
|
121
|
+
transform: translateY(-50%);
|
|
122
|
+
color: ${(props) => props.theme.colors.icon.base};
|
|
123
|
+
pointer-events: none;
|
|
124
|
+
`;
|
|
125
|
+
|
|
126
|
+
Container.displayName = "SelectContainer";
|
|
127
|
+
Arrow.displayName = "Select Arrow";
|
|
128
|
+
|
|
129
|
+
export default Container;
|
package/tsconfig.json
ADDED
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from "tsup";
|
|
2
|
+
|
|
3
|
+
export default defineConfig((options) => ({
|
|
4
|
+
entry: ["src/index.ts"],
|
|
5
|
+
format: ["cjs", "esm"],
|
|
6
|
+
clean: true,
|
|
7
|
+
legacyOutput: true,
|
|
8
|
+
dts: options.dts,
|
|
9
|
+
external: ["react"],
|
|
10
|
+
sourcemap: true,
|
|
11
|
+
metafile: options.metafile,
|
|
12
|
+
}));
|