import { type Meta, type StoryObj } from '@storybook/react-vite' import React, { useRef, useState } from 'react' import moment from 'moment' import { DocsTemplate } from '../../../.storybook' import { toast } from '../Toast/Toast' import TextInputComponent from './TextInput' import { isEmptyOrWhitespace, isValidDateString, trimWhitespace, } from '../DatePicker/DatePickerHelper' const meta: Meta = { title: 'Components/FormComponents/TextInput', component: TextInputComponent, parameters: { design: { type: 'figma', url: 'https://www.figma.com/design/RvhKD82948FMQnh5MyCi0o/Web-Design-System?node-id=181-145&t=9R4mlUY42yEaNlLp-0', }, docs: { page: () => ( The Text Input component is a versatile form element used to collect various types of user input, such as strings, numbers, currency, or percentages. It allows users to enter textual or numeric data in a designated field. The{' '} Text Input component supports a wide range of input types, making it suitable for different data types and form scenarios. } infoBullets={[ Implement the Text Input component in forms or settings sections where users need to enter textual or numeric data. , Indicate the expected data type or format for the input by providing clear labels or placeholder text within the Text Input field. , Make use of the TextInput component's various input types to ensure the correct data type is collected from users. , ]} /> ), }, }, } export default meta type Story = StoryObj const TextInput = (args: React.ComponentProps) => { const [value, setValue] = useState('') return (
setValue(val.toString())} clearCallout={() => setValue('')} />
) } const Template: Story = { render: (args) => { return }, } const DateInputStoryComponent = ( args: React.ComponentProps, ) => { const [selectedDate, setSelectedDate] = useState(undefined) const [inputDate, setInputDate] = useState('') const [isDateValid, setIsDateValid] = useState(true) const isEditingRef = useRef(false) const inputRef = useRef(null) // Always return formatted value unless editing const getFormattedDateValue = () => { if (isEditingRef.current) { return inputDate } else if (selectedDate) { return moment(selectedDate).format('MM/DD/YYYY') } return '' } return (
{ const stringValue = String(value) setInputDate(stringValue) if (isEmptyOrWhitespace(stringValue)) { setIsDateValid(true) setSelectedDate(undefined) isEditingRef.current = false return } const isValidDate = isValidDateString(stringValue) if (isValidDate) { setIsDateValid(true) const newDate = moment( trimWhitespace(stringValue), 'MM/DD/YYYY', ).toDate() setSelectedDate(newDate) isEditingRef.current = false toast({ type: 'info', message: `Date selected: ${moment(newDate).format('MM/DD/YYYY')}`, }) } else { isEditingRef.current = true setIsDateValid(false) setSelectedDate(undefined) } }} clearCallout={() => { setInputDate('') setSelectedDate(undefined) setIsDateValid(true) isEditingRef.current = false }} />
) } const genericProps = { callout: (stateName: string | number | undefined, value: string | number) => toast({ type: 'info', message: `callout stateName: ${stateName}, value: ${value}`, }), debounce: 1000, value: '', } export const Basic: Story = { ...Template, args: { ...genericProps, id: 'text', type: 'text', labelText: 'Basic Text Input', stateName: 'basic_text_state', }, } export const RequiredLabel: Story = { ...Template, args: { ...genericProps, id: 'text', type: 'text', labelText: 'Label With Tooltip', stateName: 'required_state', required: true, }, } export const LabelTooltip: Story = { ...Template, args: { ...genericProps, id: 'text', type: 'text', labelText: 'Label With Tooltip', stateName: 'label_tooltip_state', labelTooltip: { tooltipContent: 'This is a tooltip.', }, }, } export const RightLabel: Story = { ...Template, args: { ...genericProps, id: 'text', type: 'text', labelText: 'Label With Tooltip', labelTooltip: { tooltipContent: 'This is a tooltip.', }, stateName: 'right_label_state', rightLabel: 'Right Label', }, } export const NumericTextInput: Story = { ...Template, args: { ...genericProps, id: 'number', type: 'number', labelText: 'Basic Number Input', stateName: 'basic_number_state', }, } export const EmailInput: Story = { ...Template, args: { ...genericProps, id: 'email', type: 'email', labelText: 'Email Input', stateName: 'email_input_state', }, } export const PasswordInput: Story = { ...Template, args: { ...genericProps, id: 'password', type: 'password', labelText: 'Password Input', stateName: 'password_input_state', }, } export const CurrencyTextInput: Story = { ...Template, args: { ...genericProps, id: 'number', type: 'number', labelText: 'Currency Input', stateName: 'currency_input_state', numberFormat: { type: 'currency', currencySymbol: '$', }, }, } export const PercentageTextInput: Story = { ...Template, args: { ...genericProps, id: 'number', type: 'number', labelText: 'Percentage Input', stateName: 'percentage_input_state', numberFormat: { type: 'percentage', }, inputLabel: '%', }, } export const Textarea: Story = { ...Template, args: { ...genericProps, id: 'textarea', type: 'textarea', labelText: 'Textarea', stateName: 'textarea_input_state', }, } export const TextareaAutoresize: Story = { ...Template, args: { ...genericProps, id: 'textarea', type: 'textarea', labelText: 'Textarea', autoResize: true, stateName: 'textarea_input_state', }, } export const ReturnCallout: Story = { ...Template, args: { ...genericProps, id: 'text', type: 'text', labelText: 'Basic Text Input', stateName: 'basic_text_state', onReturnCallout: () => { toast({ type: 'info', message: 'Return / Enter key pressed!', }) }, }, } export const SymbologyPrefixStripping: Story = { ...Template, args: { ...genericProps, id: 'symbology', type: 'text', labelText: 'Scan input (symbology prefix stripping)', stateName: 'symbology_state', placeholder: 'Try pasting ~ABarcode123 or ]C1Barcode123', shouldStripSymbologyPrefix: true, }, } export const DateInput: Story = { render: (args) => , args: { id: 'date', type: 'date-single', labelText: 'Date Input', stateName: 'date_input_state', placeholder: 'MM/DD/YYYY', clear: true, }, }