diff --git a/.all-contributorsrc b/.all-contributorsrc index 076156741b7e..0c263b6a4675 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1067,6 +1067,15 @@ "contributions": [ "code" ] + }, + { + "login": "bianca-sparxs", + "name": "Bianca Sparxs", + "avatar_url": "https://avatars.githubusercontent.com/u/33003148?v=4", + "profile": "https://github.com/bianca-sparxs", + "contributions": [ + "code" + ] } ], "commitConvention": "none" diff --git a/README.md b/README.md index a825390d5bb9..508c4c7ff635 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,7 @@ check out our [Contributing Guide](/.github/CONTRIBUTING.md) and our
Jesse Hull

💻
Ashvin Warrier

💻
GalvinGao

💻 +
Bianca Sparxs

💻 diff --git a/packages/react/src/components/TextInput/TextInput.js b/packages/react/src/components/TextInput/TextInput.tsx similarity index 73% rename from packages/react/src/components/TextInput/TextInput.js rename to packages/react/src/components/TextInput/TextInput.tsx index 0c662291d1c4..77b185bcae4f 100644 --- a/packages/react/src/components/TextInput/TextInput.js +++ b/packages/react/src/components/TextInput/TextInput.tsx @@ -6,7 +6,7 @@ */ import PropTypes from 'prop-types'; -import React, { useContext, useState } from 'react'; +import React, { ReactNode, useContext, useState } from 'react'; import classNames from 'classnames'; import { useNormalizedInputProps } from '../../internal/useNormalizedInputProps'; import PasswordInput from './PasswordInput'; @@ -19,6 +19,132 @@ import * as FeatureFlags from '@carbon/feature-flags'; import { usePrefix } from '../../internal/usePrefix'; import { useAnnouncer } from '../../internal/useAnnouncer'; +type ExcludedAttributes = 'defaultValue' | 'id' | 'size' | 'value'; + +export interface TextInputProps + extends Omit< + React.InputHTMLAttributes, + ExcludedAttributes + > { + /** + * Specify an optional className to be applied to the `` node + */ + className?: string; + + /** + * Optionally provide the default value of the `` + */ + defaultValue?: string | number; + + /** + * Specify whether the `` should be disabled + */ + disabled?: boolean; + + /** + * Specify whether to display the character counter + */ + enableCounter?: boolean; + + /** + * Provide text that is used alongside the control label for additional help + */ + helperText?: ReactNode; + + /** + * Specify whether you want the underlying label to be visually hidden + */ + hideLabel?: boolean; + + /** + * Specify a custom `id` for the `` + */ + id: string; + + /** + * `true` to use the inline version. + */ + inline?: boolean; + + /** + * Specify whether the control is currently invalid + */ + invalid?: boolean; + + /** + * Provide the text that is displayed when the control is in an invalid state + */ + invalidText?: ReactNode; + + /** + * Provide the text that will be read by a screen reader when visiting this + * control + */ + labelText: ReactNode; + + /** + * `true` to use the light version. For use on $ui-01 backgrounds only. + * Don't use this to make tile background color same as container background color. + * 'The `light` prop for `TextInput` has ' + + 'been deprecated in favor of the new `Layer` component. It will be removed in the next major release.' + */ + light?: boolean; + + /** + * Max character count allowed for the input. This is needed in order for enableCounter to display + */ + maxCount?: number; + + /** + * Optionally provide an `onChange` handler that is called whenever `` + * is updated + */ + onChange?: ( + event: React.ChangeEvent + ) => void; + + /** + * Optionally provide an `onClick` handler that is called whenever the + * `` is clicked + */ + onClick?: (event: React.MouseEvent) => void; + + /** + * Specify the placeholder attribute for the `` + */ + placeholder?: string; + + /** + * Whether the input should be read-only + */ + readOnly?: boolean; + + /** + * Specify the size of the Text Input. Currently supports the following: + */ + size?: 'sm' | 'md' | 'lg' | 'xl'; + + /** + * Specify the type of the `` + */ + type?: string; + + /** + * Specify the value of the `` + */ + value?: string | number | undefined; + + /** + * Specify whether the control is currently in warning state + */ + warn?: boolean; + + /** + * Provide the text that is displayed when the control is in warning state + */ + warnText?: ReactNode; +} + const TextInput = React.forwardRef(function TextInput( { className, @@ -42,7 +168,7 @@ const TextInput = React.forwardRef(function TextInput( enableCounter = false, maxCount, ...rest - }, + }: TextInputProps, ref ) { const prefix = usePrefix(); @@ -51,7 +177,7 @@ const TextInput = React.forwardRef(function TextInput( const { defaultValue, value } = rest; const [textCount, setTextCount] = useState( - defaultValue?.length || value?.length || 0 + defaultValue?.toString().length || value?.toString().length || 0 ); const normalizedProps = useNormalizedInputProps({ @@ -187,7 +313,8 @@ const TextInput = React.forwardRef(function TextInput( ); const { isFluid } = useContext(FormContext); - let ariaAnnouncement = useAnnouncer(textCount, maxCount); + const ariaAnnouncement = useAnnouncer(textCount, maxCount); + const Icon = normalizedProps.icon as any; return (
@@ -203,9 +330,7 @@ const TextInput = React.forwardRef(function TextInput(
- {normalizedProps.icon && ( - - )} + {Icon && } {input} {ariaAnnouncement} @@ -220,8 +345,8 @@ const TextInput = React.forwardRef(function TextInput( }); TextInput.displayName = 'TextInput'; -TextInput.PasswordInput = PasswordInput; -TextInput.ControlledPasswordInput = ControlledPasswordInput; +(TextInput as any).PasswordInput = PasswordInput; +(TextInput as any).ControlledPasswordInput = ControlledPasswordInput; TextInput.propTypes = { /** * Specify an optional className to be applied to the `` node diff --git a/packages/react/src/internal/useNormalizedInputProps.js b/packages/react/src/internal/useNormalizedInputProps.js index 84e4dab226ec..1c75aee07242 100644 --- a/packages/react/src/internal/useNormalizedInputProps.js +++ b/packages/react/src/internal/useNormalizedInputProps.js @@ -25,6 +25,7 @@ import { usePrefix } from './usePrefix'; * @property {boolean} disabled - Whether the input is disabled * @property {boolean} invalid - Whether the input is invalid (takes precedence over warn) * @property {string} invalidId - The invalid message's id + * @property {string} helperId - id used for helper text * @property {boolean} warn - Whether the input is in warning state * @property {string} warnId - The warning message's id * @property {React.ReactNode | null} validation – React node rendering the appropriate validation message (if any)