This commit is contained in:
Nathan Bierema 2020-09-03 15:26:05 -04:00
parent 0dda9e463c
commit fc219a04f9
10 changed files with 66 additions and 388 deletions

View File

@ -1,17 +1,41 @@
import React, { PureComponent, Component } from 'react';
import PropTypes from 'prop-types';
import ReactSelect from 'react-select';
// import createStyledComponent from '../utils/createStyledComponent';
// import styles from './styles';
//
// const SelectContainer = createStyledComponent(styles, ReactSelect);
import createThemedComponent from '../utils/createThemedComponent';
/**
* Wrapper around [React Select](https://github.com/JedWatson/react-select) with themes and new props like `openOuterUp` and `menuMaxHeight`.
* Wrapper around [React Select](https://github.com/JedWatson/react-select).
*/
export default class Select extends (PureComponent || Component) {
class Select extends (PureComponent || Component) {
render() {
return <ReactSelect {...this.props} />;
return (
<ReactSelect
{...this.props}
theme={(theme) => ({
...theme,
borderRadius: this.props.theme.inputBorderRadius,
colors: {
...theme.colors,
primary: this.props.theme.base05,
primary50: this.props.theme.base03,
primary25: this.props.theme.base01,
dangerLight: this.props.theme.base03,
danger: this.props.theme.base07,
neutral0: this.props.theme.base00,
neutral5: this.props.theme.base01,
neutral10: this.props.theme.base02,
neutral20: this.props.theme.base03,
neutral30: this.props.theme.base04,
neutral40: this.props.theme.base05,
neutral60: this.props.theme.base06,
neutral80: this.props.theme.base07,
},
})}
/>
);
}
}
@ -19,9 +43,11 @@ Select.propTypes = {
isClearable: PropTypes.bool, // should it be possible to reset value
isDisabled: PropTypes.bool, // whether the Select is disabled or not
isLoading: PropTypes.bool, // whether the Select is loading externally or not
// menuMaxHeight: PropTypes.number, // maximum css height for the opened menu of options
maxMenuHeight: PropTypes.number, // maximum css height for the opened menu of options
isMulti: PropTypes.bool, // multi-value input
isSearchable: PropTypes.bool, // whether to enable searching feature or not
value: PropTypes.any, // initial field value
menuPlacement: PropTypes.oneOf(['auto', 'bottom', 'top']), // value to control the opening direction
};
export default createThemedComponent(Select);

View File

@ -1,361 +0,0 @@
import { css } from 'styled-components';
import { fadeIn, spinner } from '../../utils/animations';
export default ({ theme, openOuterUp, menuMaxHeight }) => css`
&.Select {
position: relative;
&,
& div,
& input,
& span {
box-sizing: border-box;
}
&.is-disabled > .Select-control {
background-color: ${theme.base02};
&:hover {
box-shadow: none;
}
}
&.is-disabled .Select-arrow-zone {
cursor: default;
pointer-events: none;
}
}
.Select-control {
background-color: ${theme.base00};
border-color: ${theme.inputBorderColor};
border-radius: ${theme.inputBorderRadius}px;
border-style: solid;
border-width: ${theme.inputBorderWidth}px;
color: ${theme.base07};
cursor: default;
display: table;
border-spacing: 0;
border-collapse: separate;
height: ${theme.inputHeight}px;
outline: none;
overflow: hidden;
position: relative;
width: 100%;
&:hover {
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
}
.Select-input:focus {
outline: none;
}
}
&.is-searchable {
&.is-open > .Select-control {
cursor: text;
}
}
&.is-open > .Select-control {
border-radius: ${openOuterUp
? `0 0 ${theme.inputBorderRadius}px ${theme.inputBorderRadius}px`
: `${theme.inputBorderRadius}px ${theme.inputBorderRadius}px 0 0`};
}
&.is-searchable {
&.is-focused:not(.is-open) > .Select-control {
cursor: text;
}
}
&.is-focused > .Select-control {
${theme.inputFocusedStyle}
}
.Select-placeholder,
&.Select--single > .Select-control .Select-value {
bottom: 0;
color: ${theme.base03};
left: 0;
line-height: ${theme.inputInternalHeight}px;
padding: 0 ${theme.inputPadding}px;
position: absolute;
right: 0;
top: 0;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&.has-value.Select--single > .Select-control .Select-value,
&.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value {
.Select-value-label {
color: ${theme.base07};
}
a.Select-value-label {
cursor: pointer;
text-decoration: none;
&:hover,
&:focus {
color: ${theme.base0D};
outline: none;
text-decoration: underline;
}
}
}
.Select-input {
height: ${theme.inputInternalHeight}px;
padding-left: ${theme.inputPadding}px;
padding-right: ${theme.inputPadding}px;
vertical-align: middle;
> input {
color: ${theme.base07};
background: none transparent;
border: 0 none;
box-shadow: none;
width: 100%;
cursor: default;
display: inline-block;
font-family: inherit;
font-size: inherit;
margin: 0;
outline: none;
line-height: 14px;
padding: ${(theme.inputInternalHeight - 14) / 2 - 2}px 0;
-webkit-appearance: none;
.is-focused & {
cursor: text;
}
}
}
&.has-value.is-pseudo-focused .Select-input {
opacity: 0;
}
.Select-control:not(.is-searchable) > .Select-input {
outline: none;
}
.Select-loading-zone {
cursor: pointer;
display: table-cell;
position: relative;
text-align: center;
vertical-align: middle;
width: ${theme.spinnerSize}px;
}
.Select-loading {
${spinner(theme)}
vertical-align: middle;
}
.Select-clear-zone {
animation: ${fadeIn} 200ms;
color: ${theme.base03};
cursor: pointer;
display: table-cell;
position: relative;
text-align: center;
vertical-align: middle;
&:hover {
color: #d0021b;
}
}
.Select-clear {
display: inline-block;
font-size: ${Math.floor(theme.inputHeight / 2)}px;
line-height: 1px;
}
.Select-clear-zone,
.Select--multi .Select-clear-zone {
width: ${theme.inputInternalHeight / 2}px;
}
.Select--multi .Select-multi-value-wrapper {
display: inline-block;
}
&.Select .Select-aria-only {
display: inline-block;
position: absolute;
height: 1px;
width: 1px;
margin: -1px;
clip: rect(0, 0, 0, 0);
overflow: hidden;
}
.Select-arrow-zone {
cursor: pointer;
display: table-cell;
position: relative;
text-align: center;
vertical-align: middle;
width: ${theme.selectArrowWidth * 5}px;
padding-right: ${theme.selectArrowWidth}px;
}
.Select-arrow {
border-color: ${theme.base03} transparent transparent;
border-style: solid;
border-width: ${theme.selectArrowWidth}px ${theme.selectArrowWidth}px
${theme.selectArrowWidth / 2}px;
display: inline-block;
height: 0;
width: 0;
}
.is-open .Select-arrow,
.Select-arrow-zone:hover > .Select-arrow {
border-top-color: ${theme.base04};
}
.Select-menu-outer {
border: 1px solid ${theme.base02};
box-shadow: 0 ${openOuterUp ? '-1px' : '1px'} 0 rgba(0, 0, 0, 0.06);
box-sizing: border-box;
/* stylelint-disable declaration-empty-line-before */
${openOuterUp ? 'margin-bottom' : 'margin-top'}: -1px;
/* stylelint-enable */
max-height: ${menuMaxHeight}px;
position: absolute;
top: auto;
left: 0;
bottom: ${openOuterUp ? '100%' : 'auto'};
width: 100%;
min-width: 70px;
z-index: 1000;
-webkit-overflow-scrolling: touch;
}
.Select-menu {
max-height: ${menuMaxHeight - 2}px;
overflow-y: auto;
}
.Select-option {
box-sizing: border-box;
background-color: ${theme.base00};
color: ${theme.base07};
cursor: pointer;
display: block;
padding: ${theme.inputHeight / 3}px;
line-height: ${theme.inputInternalHeight / 2}px;
&.is-selected {
background-color: ${theme.base01};
color: ${theme.base07};
}
&.is-focused {
background-color: ${theme.base02};
color: ${theme.base07};
}
&.is-disabled {
color: ${theme.base05};
cursor: default;
}
}
.Select-noresults {
box-sizing: border-box;
color: ${theme.base06};
background-color: ${theme.base00};
cursor: default;
display: block;
padding: ${theme.inputPadding}px;
}
&.Select--multi {
.Select-input {
display: inline-block;
vertical-align: middle;
margin-left: ${theme.inputPadding}px;
padding: 0;
}
&.has-value .Select-input {
margin-left: ${theme.selectArrowWidth}px;
}
.Select-value {
background-color: ${theme.base00};
border-radius: ${theme.inputBorderRadius}px;
border: 1px solid ${theme.base02};
color: ${theme.base07};
display: inline-block;
font-size: 0.9em;
margin-left: ${theme.inputPadding / 2}px;
margin-top: 0;
vertical-align: middle;
}
.Select-value-icon,
.Select-value-label {
display: inline-block;
vertical-align: middle;
}
.Select-value-label {
border-bottom-right-radius: ${theme.inputBorderRadius}px;
border-top-right-radius: ${theme.inputBorderRadius}px;
cursor: default;
padding: ${Math.floor(theme.inputPadding / 4)}px
${Math.floor(theme.inputPadding / 2)}px;
}
a.Select-value-label {
color: ${theme.base07};
cursor: pointer;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.Select-value-icon {
cursor: pointer;
border-bottom-left-radius: ${theme.inputBorderRadius}px;
border-top-left-radius: ${theme.inputBorderRadius}px;
border-right: 1px solid ${theme.base02};
padding: 0px ${Math.floor(theme.inputPadding / 2)}px;
&:hover,
&:focus {
background-color: ${theme.base03};
color: ${theme.base00};
}
&:active {
background-color: ${theme.base06};
}
}
}
&.Select--multi.is-disabled {
.Select-value {
background-color: ${theme.base00};
border: 1px solid ${theme.base01};
color: ${theme.base05};
}
.Select-value-icon {
cursor: not-allowed;
}
}
`;

View File

@ -0,0 +1,13 @@
import React from 'react';
import getDefaultTheme from '../themes/default';
import { withTheme } from 'styled-components';
export default (UnthemedComponent) => (props) =>
props.theme.type ? (
withTheme(<UnthemedComponent {...props} />)
) : (
// used outside of container (theme provider)
<UnthemedComponent {...props} theme={getDefaultTheme(props.theme)} />
);
// TODO: memoize it?

View File

@ -2,7 +2,7 @@
exports[`Dialog renders correctly 1`] = `
<div
class="sc-fzoLsD fLVcbf"
class="sc-fzozJi bUabZV"
>
<div />
<div>
@ -45,7 +45,7 @@ exports[`Dialog renders correctly 1`] = `
exports[`Dialog renders modal 1`] = `
<div
class="sc-fzoLsD fLVcbf"
class="sc-fzozJi bUabZV"
>
<div />
<div>
@ -85,7 +85,7 @@ exports[`Dialog renders modal 1`] = `
exports[`Dialog renders with props 1`] = `
<div
class="sc-fzoLsD kdTVQ"
class="sc-fzozJi eNoXNi"
open=""
>
<div />

View File

@ -12,7 +12,7 @@ exports[`Editor renders correctly 1`] = `
>
<styled.div>
<div
className="sc-fzpans kykpM"
className="sc-fzoLsD fnGkfM"
/>
</styled.div>
</Editor>

View File

@ -2,7 +2,7 @@
exports[`Notification renders correctly 1`] = `
<div
class="sc-fznZeY gzHfke"
class="sc-fznKkj ibIwiW"
type="info"
>
<span>
@ -13,7 +13,7 @@ exports[`Notification renders correctly 1`] = `
exports[`Notification renders with props 1`] = `
<div
class="sc-fznZeY gzHfke"
class="sc-fznKkj ibIwiW"
type="error"
>
<svg

View File

@ -2,7 +2,7 @@
exports[`SegmentedControl renders correctly 1`] = `
<div
class="sc-fznKkj jdtBdv"
class="sc-fznyAO jQfpYK"
>
<button
data-selected="true"

View File

@ -2,7 +2,7 @@
exports[`Slider renders correctly 1`] = `
<div
class="sc-Axmtr coPiXj"
class="sc-AxheI ikoHwk"
>
<input
max="100"
@ -15,7 +15,7 @@ exports[`Slider renders correctly 1`] = `
exports[`Slider renders with props 1`] = `
<div
class="sc-Axmtr dRUqiC"
class="sc-AxheI bySZMR"
disabled=""
>
<label>

View File

@ -2,10 +2,10 @@
exports[`Tabs renders correctly 1`] = `
<div
class="sc-fznyAO eEQsxY"
class="sc-fzplWN iQpDbE"
>
<div
class="sc-fzplWN dxFeew"
class="sc-fzpans gRdChJ"
>
<div>
<button
@ -30,10 +30,10 @@ exports[`Tabs renders correctly 1`] = `
exports[`Tabs renders tabs without inner components 1`] = `
<div
class="sc-fznyAO eEQsxY"
class="sc-fzplWN iQpDbE"
>
<div
class="sc-fzplWN dxFeew"
class="sc-fzpans gRdChJ"
>
<div>
<button
@ -94,10 +94,10 @@ exports[`Tabs renders tabs without inner components 1`] = `
exports[`Tabs renders with props 1`] = `
<div
class="sc-fznyAO eEQsxY"
class="sc-fzplWN iQpDbE"
>
<div
class="sc-fzplWN dxFeew"
class="sc-fzpans gRdChJ"
>
<div>
<button

View File

@ -2,7 +2,7 @@
exports[`Toolbar renders correctly 1`] = `
<div
class="sc-fzokOt kWHFmJ"
class="sc-fznZeY bcKxBO"
>
<div
class="sc-AxhUy dkmwYZ"
@ -14,10 +14,10 @@ exports[`Toolbar renders correctly 1`] = `
</button>
</div>
<div
class="sc-fzqBZW bdkKty"
class="sc-fzokOt drZiIn"
/>
<div
class="sc-fzqNJr jGNKLq"
class="sc-fzqBZW kjCEpb"
/>
<div
class="sc-AxhUy dkmwYZ"
@ -33,6 +33,6 @@ exports[`Toolbar renders correctly 1`] = `
exports[`Toolbar renders with props 1`] = `
<div
class="sc-fzokOt hoHbQE"
class="sc-fznZeY csZTMz"
/>
`;