UNPKG

vcc-ui

Version:

VCC UI is a collection of React UI Components that can be used for developing front-end applications at Volvo Car Corporation.

181 lines (172 loc) 4.59 kB
import React from 'react'; import { useFela } from 'react-fela'; import { func, string, array, bool, node, object, oneOfType } from 'prop-types'; import { Block } from '../block'; import { Spinner } from '../spinner'; import { getThemeStyle } from '../../get-theme-style'; import { deprecate } from '../../deprecate'; const arrowColor = ({ theme, disabled }) => disabled ? theme.tokens.inputDisabledControl : theme.tokens.inputControl; const styles = ({ loading, disabled, theme, isValid }) => ({ appearance: 'none', color: '#333', backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 13 6' fill='${encodeURIComponent( arrowColor({ theme, disabled }) )}' %3E %3Cpath d='M6.49987275 4.13397441L11.78483479.5 12.5 1.37426775 6.49986464 5.5.5 1.3743604l.7151756-.87426061z'%3E %3C/path%3E %3C/svg%3E")`, backgroundSize: '15px 15px', backgroundColor: theme.tokens.inputBackground, backgroundPosition: 'right 18px center', backgroundRepeat: 'no-repeat', userSelect: 'none', overflow: 'hidden', margin: '0', padding: `${theme.tokens.inputPaddingVertical}px ${theme.tokens.inputPaddingHorizontal}px`, textOverflow: 'ellipsis', whiteSpace: 'nowrap', width: '100%', boxSizing: 'border-box', borderRadius: 0, borderWidth: '1px', borderStyle: 'solid', borderColor: isValid ? theme.tokens.inputBorder : theme.color.foreground.alert, display: 'block', ':disabled': { color: theme.tokens.inputDisabledForeground, }, '& option:disabled': { color: theme.tokens.inputDisabledForeground, }, ':invalid': { color: theme.tokens.inputPlaceholder, }, ':focus:invalid': { color: theme.tokens.inputPlaceholder, }, '::-ms-expand': { display: 'none', }, '::-ms-value': { background: 'none', color: theme.tokens.inputForeground, }, ':valid': { color: theme.tokens.inputForeground, }, '& option': { color: theme.tokens.inputForeground, }, ':-moz-focusring': { color: 'transparent', textShadow: '0 0 0 #000', }, outline: 0, cursor: disabled ? 'not-allowed' : 'pointer', ':focus': { borderColor: theme.tokens.inputBorderFocus, }, extend: [ { condition: loading, style: { backgroundImage: 'none', display: 'flex', justifyContent: 'center', width: '100%', }, }, ], }); export const SelectInput = React.forwardRef( ( { children, value, placeholder, disabled, options, isValid = true, loading = false, ...props }, ref ) => { const { theme } = useFela(); const renderOptions = options => options.map(option => ( <option key={option.value} value={option.value} disabled={option.disabled} > {option.label} </option> )); const renderOptGroups = options => { return Object.keys(options).map(name => ( <optgroup label={name} key={name}> {renderOptions(options[name])} </optgroup> )); }; // TODO: remove in 2.0.0 deprecate( 'The `options` prop on has been deprecated in favor of passing children. It will be removed with version 2.0.0.', !!options ); if (loading) { return ( <Block ref={ref} extend={[ styles({ loading, disabled, theme, isValid }), getThemeStyle('selectInput', theme, { disabled, }), ]} > <Spinner color={theme.tokens.inputForeground} size={27} /> </Block> ); } return ( <Block ref={ref} as="select" extend={[ styles({ loading, disabled, theme, isValid }), getThemeStyle('selectInput', theme, { disabled, }), ]} value={value || (placeholder && '')} required={true} disabled={disabled} {...props} > {placeholder && ( <Block as="option" value={''} disabled hidden> {placeholder} </Block> )} {children ? children : Array.isArray(options) ? renderOptions(options) : renderOptGroups(options)} </Block> ); } ); SelectInput.propTypes = { onChange: func.isRequired, options: oneOfType([array, object]), placeholder: string, value: string, disabled: bool, loading: bool, children: node, isValid: bool, }; SelectInput.displayName = 'SelectInput';