import type * as React from 'react'; import classNames from 'classnames'; export type TextInputDefaultValue = string | number; export type TextInputRows = number | string; export type TextInputSize = 'small' | 'medium'; export type TextInputValue = string | number; export type OmitProps = 'size' | 'ref'; export type TextInputProps = Omit, OmitProps> & { /** * Apply an `aria-label` to the text field to provide additional * context to assistive devices. */ ariaLabel?: string; /** * Sets the initial value. Use this for an uncontrolled component; otherwise, * use the `value` property. */ defaultValue?: TextInputDefaultValue; disabled?: boolean; /** * Additional classes to be added to the field element */ fieldClassName?: string; /** * A unique `id` to be used on the text field. */ id?: string; /** * Applies the "inverse" UI theme */ inversed?: boolean; /** * Whether or not the text field is a multiline text field */ multiline?: boolean; name?: string; /** * Sets `inputMode`, `type`, and `pattern` to improve accessibility and consistency for number fields. Use this prop instead of `type="number"`, see [here](https://technology.blog.gov.uk/2020/02/24/why-the-gov-uk-design-system-team-changed-the-input-type-for-numbers/) for more information. */ numeric?: boolean; onBlur?: (...args: any[]) => any; onChange?: (...args: any[]) => any; /** * @hide-prop HTML `input` [pattern](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefpattern). */ pattern?: string; /** * Optionally specify the number of visible text lines for the field. Only * applicable if this is a multiline field. */ rows?: TextInputRows; inputRef?: React.Ref | React.MutableRefObject; /** * Set the max-width of the input either to `'small'` or `'medium'`. */ size?: TextInputSize; /** * HTML `input` [type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#_types) attribute. If you are using `type=number` please use the numeric prop instead. */ type: string; /** * Sets the input's `value`. Use this in combination with `onChange` * for a controlled component; otherwise, set `defaultValue`. */ value?: TextInputValue; }; // TODO: We don't want to remove these until a breaking change in case anyone // was referencing these types directly from this file. export type MultilineTextInputProps = TextInputProps; export type SingleLineTextInputProps = TextInputProps; /** * `` is an internal component used by ``, which wraps it and handles shared form UI like labels, error messages, etc * `` is also exported for advanced design system use cases, where the internal component can be leveraged to build custom form components * As an internal component, it's subject to more breaking changes. Exercise caution using `` outside of those special cases */ const TextInput = (props: TextInputProps) => { const { ariaLabel, fieldClassName, inversed, multiline, numeric, onCopyCapture, pattern, rows, inputRef, size, type, ...inputProps } = props; const classes = classNames( 'ds-c-field', { 'ds-c-field--error': props['aria-invalid'], 'ds-c-field--inverse': inversed, }, size && `ds-c-field--${size}`, fieldClassName ); let inputType = type; if (numeric) { inputType = 'text'; } else if (multiline) { inputType = undefined; } const ComponentType = multiline ? 'textarea' : 'input'; const numberRows: number = typeof rows === 'string' ? parseInt(rows) : rows; return ( ); }; export default TextInput;