104 lines
2.5 KiB
TypeScript
104 lines
2.5 KiB
TypeScript
// Copyright 2019-2023 @polkadot/extension-ui authors & contributors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
import type { ThemeProps } from '../types.js';
|
|
|
|
import React, { useCallback } from 'react';
|
|
|
|
import arrow from '../assets/arrow-down.svg';
|
|
import { styled } from '../styled.js';
|
|
import Label from './Label.js';
|
|
|
|
interface DropdownOption {
|
|
text: string;
|
|
value: string;
|
|
}
|
|
|
|
interface Props extends ThemeProps {
|
|
className?: string;
|
|
defaultValue?: string | null;
|
|
isDisabled?: boolean
|
|
isError?: boolean;
|
|
isFocussed?: boolean;
|
|
label: string;
|
|
onBlur?: () => void;
|
|
onChange?: (value: string) => void;
|
|
options: DropdownOption[];
|
|
value?: string;
|
|
}
|
|
|
|
function Dropdown ({ className, defaultValue, isDisabled, isFocussed, label, onBlur, onChange, options, value }: Props): React.ReactElement<Props> {
|
|
const _onChange = useCallback(
|
|
({ target: { value } }: React.ChangeEvent<HTMLSelectElement>) =>
|
|
onChange && onChange(value.trim()),
|
|
[onChange]
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<Label
|
|
className={className}
|
|
label={label}
|
|
>
|
|
<select
|
|
autoFocus={isFocussed}
|
|
defaultValue={defaultValue || undefined}
|
|
disabled={isDisabled}
|
|
onBlur={onBlur}
|
|
onChange={_onChange}
|
|
value={value}
|
|
>
|
|
{options.map(({ text, value }): React.ReactNode => (
|
|
<option
|
|
key={value}
|
|
value={value}
|
|
>
|
|
{text}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</Label>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default React.memo(styled(Dropdown)(({ isError, label, theme }: Props) => `
|
|
position: relative;
|
|
|
|
select {
|
|
-webkit-appearance: none;
|
|
-moz-appearance: none;
|
|
appearance: none;
|
|
background: ${theme.readonlyInputBackground};
|
|
border-color: ${isError ? theme.errorBorderColor : theme.inputBorderColor};
|
|
border-radius: ${theme.borderRadius};
|
|
border-style: solid;
|
|
border-width: 1px;
|
|
box-sizing: border-box;
|
|
color: ${isError ? theme.errorBorderColor : theme.textColor};
|
|
display: block;
|
|
font-family: ${theme.fontFamily};
|
|
font-size: ${theme.fontSize};
|
|
padding: 0.5rem 0.75rem;
|
|
width: 100%;
|
|
cursor: pointer;
|
|
|
|
&:read-only {
|
|
box-shadow: none;
|
|
outline: none;
|
|
}
|
|
}
|
|
|
|
label::after {
|
|
content: '';
|
|
position: absolute;
|
|
top: ${label ? 'calc(50% + 14px)' : '50%'};
|
|
transform: translateY(-50%);
|
|
right: 12px;
|
|
width: 8px;
|
|
height: 6px;
|
|
background: url(${arrow}) center no-repeat;
|
|
pointer-events: none;
|
|
}
|
|
`));
|