import React, { useState, useRef } from 'react'; import { useArgs } from '@storybook/client-api'; import PropTypes from 'prop-types'; import { DISPLAY, FLEX_DIRECTION, AlignItems, TextVariant, IconColor, BackgroundColor, TextColor, Size, } from '../../../helpers/constants/design-system'; import Box from '../../ui/box/box'; import { AvatarAccount, AvatarToken, Button, ButtonIcon, ICON_NAMES, Icon, Text, } from '..'; import { TEXT_FIELD_SIZES, TEXT_FIELD_TYPES } from './text-field.constants'; import { TextField } from './text-field'; import README from './README.mdx'; const marginSizeControlOptions = [ undefined, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'auto', ]; export default { title: 'Components/ComponentLibrary/TextField', component: TextField, parameters: { docs: { page: README, }, }, argTypes: { autoComplete: { control: 'boolean', }, autoFocus: { control: 'boolean', }, className: { control: 'text', }, defaultValue: { control: 'text', }, disabled: { control: 'boolean', }, error: { control: 'boolean', }, id: { control: 'text', }, inputProps: { control: 'object', }, startAccessory: { control: 'text', }, maxLength: { control: 'number', }, name: { control: 'text', }, onBlur: { action: 'onBlur', }, onChange: { action: 'onChange', }, onClick: { action: 'onClick', }, onFocus: { action: 'onFocus', }, placeholder: { control: 'text', }, readOnly: { control: 'boolean', }, required: { control: 'boolean', }, endAccessory: { control: 'text', }, size: { control: 'select', options: Object.values(TEXT_FIELD_SIZES), }, type: { control: 'select', options: Object.values(TEXT_FIELD_TYPES), }, value: { control: 'text', }, marginTop: { options: marginSizeControlOptions, control: 'select', table: { category: 'box props' }, }, marginRight: { options: marginSizeControlOptions, control: 'select', table: { category: 'box props' }, }, marginBottom: { options: marginSizeControlOptions, control: 'select', table: { category: 'box props' }, }, marginLeft: { options: marginSizeControlOptions, control: 'select', table: { category: 'box props' }, }, }, args: { placeholder: 'Placeholder...', }, }; const Template = (args) => { const [{ value }, updateArgs] = useArgs(); const handleOnChange = (e) => { updateArgs({ value: e.target.value }); }; return ; }; export const DefaultStory = Template.bind({}); DefaultStory.storyName = 'Default'; export const SizeStory = (args) => { return ( ); }; SizeStory.storyName = 'Size'; export const Type = (args) => ( ); export const Truncate = Template.bind({}); Truncate.args = { placeholder: 'Truncate', value: 'Truncated text when truncate and width is set', truncate: true, style: { width: 240 }, }; export const StartAccessoryEndAccessory = (args) => { const [value, setValue] = useState({ search: '', address: '', amount: 1, accountAddress: '0x514910771af9ca656af840dff83e8264ecf986ca', }); const handleOnChange = (e) => { setValue({ ...value, [e.target.name]: e.target.value }); }; const handleTokenPrice = (tokenAmount, priceUSD) => { return tokenAmount * priceUSD; }; return ( } /> } /> ETH } endAccessory={ = ${handleTokenPrice(value.amount, 1173.58)} } /> ) } endAccessory={ value.accountAddress.length === 42 && ( ) } /> ); }; export const InputRef = (args) => { const inputRef = useRef(null); const [value, setValue] = useState(''); const handleOnClick = () => { inputRef.current.focus(); }; const handleOnChange = (e) => { setValue(e.target.value); }; return ( ); }; const CustomInputComponent = React.forwardRef( ( { as, autoComplete, autoFocus, defaultValue, disabled, focused, id, inputProps, inputRef, maxLength, name, onBlur, onChange, onFocus, padding, paddingLeft, paddingRight, placeholder, readOnly, required, value, variant, type, className, 'aria-invalid': ariaInvalid, ...props }, ref, ) => ( GoerliETH No conversion rate available ), ); CustomInputComponent.propTypes = { /** * The custom input component should accepts all props that the * InputComponent accepts in ./text-field.js */ autoFocus: PropTypes.bool, className: PropTypes.string, defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), disabled: PropTypes.bool, id: PropTypes.string, inputProps: PropTypes.object, inputRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), maxLength: PropTypes.number, name: PropTypes.string, onBlur: PropTypes.func, onChange: PropTypes.func, onFocus: PropTypes.func, placeholder: PropTypes.string, readOnly: PropTypes.bool, required: PropTypes.bool, type: PropTypes.oneOf(Object.values(TEXT_FIELD_TYPES)), /** * Because we manipulate the type in TextField so the html element * receives the correct attribute we need to change the autoComplete * propType to a string */ autoComplete: PropTypes.string, /** * The custom input component should also accept all the props from Box */ ...Box.propTypes, }; CustomInputComponent.displayName = 'CustomInputComponent'; export const InputComponent = (args) => ( } /> ); InputComponent.args = { autoComplete: true }; export const AutoComplete = Template.bind({}); AutoComplete.args = { autoComplete: true, type: 'password', placeholder: 'Enter password', }; export const AutoFocus = Template.bind({}); AutoFocus.args = { autoFocus: true }; export const DefaultValue = Template.bind({}); DefaultValue.args = { defaultValue: 'Default value' }; export const Disabled = Template.bind({}); Disabled.args = { disabled: true }; export const ErrorStory = Template.bind({}); ErrorStory.args = { error: true }; ErrorStory.storyName = 'Error'; export const MaxLength = Template.bind({}); MaxLength.args = { maxLength: 10, placeholder: 'Max length 10' }; export const ReadOnly = Template.bind({}); ReadOnly.args = { readOnly: true, value: 'Read only' }; export const Required = Template.bind({}); Required.args = { required: true, placeholder: 'Required' };