/** * WordPress dependencies */ /** * External dependencies */ import Select from 'react-select'; import { isArray } from 'lodash'; import type { Props as SelectProps, StylesConfig } from 'react-select'; const WORDPRESS_TEXT_COLOR = 'var(--wp-components-color-foreground, #1e1e1e)'; const WORDPRESS_TEXT_DISABLED_COLOR = '#dddddd'; const WORDPRESS_ACCENT_COLOR = 'var(--wp-components-color-accent, var(--wp-admin-theme-color, #3858e9))'; /** * Internal dependencies */ import './style.scss'; export const DEFAULT_STYLE: StylesConfig< unknown, boolean > = { control: ( _, state ) => ( { ...getControlBorder( state ), background: state.isDisabled ? '#f7f7f7' : '#fff', boxShadow: undefined, display: 'flex', flexDirection: 'row', fontSize: '13px', height: ! state.isMulti ? '40px' : undefined, margin: '0', padding: '0 6px 0 12px', paddingLeft: state.isMulti ? '0' : undefined, } ), singleValue: ( style, state ) => ( { ...style, color: state.isDisabled ? WORDPRESS_TEXT_DISABLED_COLOR : WORDPRESS_TEXT_COLOR, } ), input: ( style ) => ( { ...style, marginTop: '-3px', } ), groupHeading: ( style ) => ( { ...style, padding: '1em', } ), loadingIndicator: () => ( { display: 'none', } ), indicatorSeparator: () => ( { display: 'none', } ), dropdownIndicator: () => ( { display: 'flex', color: 'transparent', width: '1.5em', height: '100%', background: 'url(\'data:image/svg+xml,\') center no-repeat', } ), menuPortal: ( style ) => { const margin = 14; const width = Math.min( document.body.clientWidth - 2 * margin, 300 ); const sl: unknown = isArray( style.left ) ? style.left[ 0 ] : style.left; const styleLeft = numberify( sl ); const overflowX = Math.abs( Math.min( 0, document.body.clientWidth - ( styleLeft + width + 14 ) ) ); const left = styleLeft - overflowX; return { ...style, zIndex: '999999', width, left, right: left + width - margin, }; }, menu: ( style ) => ( { ...style, borderRadius: 0, } ), option: ( style, state ) => ( { ...style, ...getOptionColor( state ), padding: '0.5em 1em', } ), }; export type StylizedSelectControlProps< OptionType, IsMulti extends boolean, > = { readonly className?: string; readonly isMandatory?: boolean; } & SelectProps< OptionType, IsMulti >; export function StylizedSelectControl< OptionType, IsMulti extends boolean >( { className = '', styles = {}, // eslint-disable-next-line @typescript-eslint/no-unused-vars menuPortalTarget, isMandatory, value, isMulti, ...props }: StylizedSelectControlProps< OptionType, IsMulti > ): JSX.Element { const isClearable = isMandatory && isMultiValue( value, isMulti ) ? value.length > 1 : true; return ( ); } // ======= // HELPERS // ======= const getControlBorder = ( { isDisabled, isFocused, }: Partial< { isDisabled: boolean; isFocused: boolean; } > = {} ) => { let color = 'var(--wp-components-color-gray-600, #949494)'; if ( isFocused ) { color = WORDPRESS_ACCENT_COLOR; } if ( isDisabled ) { color = WORDPRESS_TEXT_DISABLED_COLOR; } return { border: `1px solid ${ color }`, borderRadius: '2px', }; }; const getOptionColor = ( { isSelected, isFocused, }: Partial< { isSelected: boolean; isFocused: boolean; } > = {} ) => { let color = WORDPRESS_TEXT_COLOR; let background = '#fff'; if ( isSelected ) { background = '#f1f1f1'; } if ( isFocused ) { color = '#fff'; background = WORDPRESS_ACCENT_COLOR; } return { background, color }; }; const numberify = ( x: unknown ): number => { if ( 'number' === typeof x ) { return x; } return 'string' === typeof x ? Number.parseInt( x ) || 0 : 0; }; const isMultiValue = ( x: unknown, isMulti?: boolean ): x is unknown[] => !! isMulti && !! x && Array.isArray( x );