diff --git a/apps/storybook-react/stories/TextField.stories.jsx b/apps/storybook-react/stories/TextField.stories.jsx index 43015ad813..6027bbd0e6 100644 --- a/apps/storybook-react/stories/TextField.stories.jsx +++ b/apps/storybook-react/stories/TextField.stories.jsx @@ -150,13 +150,13 @@ export const knobs = () => ( id="storybook-knobs" variant={select( 'Variant', - [...Object.values(TextField.constants.variants)], - TextField.constants.variants[0], + ['error', 'warning', 'success', 'default'], + 'default', )} type={select( 'Type', - [...Object.values(TextField.constants.types)], - TextField.constants.types[0], + ['text', 'search', 'password', 'email', 'number'], + 'text', )} label={text('Label', 'label')} meta={text('Meta', 'meta')} diff --git a/libraries/core-react/src/TextField/HelperText/HelperText.jsx b/libraries/core-react/src/TextField/HelperText/HelperText.jsx deleted file mode 100644 index 594986a4d6..0000000000 --- a/libraries/core-react/src/TextField/HelperText/HelperText.jsx +++ /dev/null @@ -1,97 +0,0 @@ -// @ts-nocheck -import React from 'react' -import PropTypes from 'prop-types' -import styled from 'styled-components' -import { typographyTemplate } from '../../_common/templates' -import { helperText as tokens } from './HelperText.token' -import { propsFor, useTextField } from '../context' -import { Icon } from '../Icon' - -const Variation = ({ variant, isFocused, isDisabled }) => { - if (!variant) { - return `` - } - - const { focus, color, disabledColor } = variant - - if (isDisabled) { - return `color: ${disabledColor};` - } - - if (isFocused) { - return ` color: ${focus.color};` - } - - return `color: ${color};` -} - -const Container = styled.div` - display: flex; - align-items: flex-end; - - margin-left: ${({ spacings }) => spacings.left}; - margin-top: ${({ spacings }) => spacings.top}; -` -const Text = styled.p` - margin: 0; - ${typographyTemplate(tokens.typography)} - ${Variation} -` - -const StyledIcon = styled(Icon)` - margin-right: ${({ spacings }) => spacings.left}; -` - -const HelperText = React.forwardRef(function TextFieldHelperText(props, ref) { - const { helperText, icon, variant, disabled: isDisabled } = props - const helperVariant = tokens[variant] - const spacings = tokens.spacings.comfortable - - const { isFocused } = useTextField() - - const iconProps = { - spacings, - isDisabled, - color: helperVariant.color, - disabledColor: helperVariant.disabledColor, - focusColor: helperVariant.focus.color, - } - - return ( - - {icon && {icon}} - - {helperText} - - - ) -}) - -HelperText.propTypes = { - /** @ignore */ - className: PropTypes.string, - /** Helper text */ - helperText: PropTypes.string, - /** Icon */ - icon: PropTypes.node, - /** Disabled */ - disabled: PropTypes.bool, - /** Variant */ - variant: PropTypes.oneOf(propsFor.variants), -} - -HelperText.defaultProps = { - className: '', - helperText: '', - icon: null, - disabled: false, - variant: 'default', -} - -HelperText.displayName = 'eds-text-field-helperText' - -export { HelperText } diff --git a/libraries/core-react/src/TextField/HelperText/HelperText.token.js b/libraries/core-react/src/TextField/HelperText/HelperText.token.ts similarity index 65% rename from libraries/core-react/src/TextField/HelperText/HelperText.token.js rename to libraries/core-react/src/TextField/HelperText/HelperText.token.ts index 3fec527bf8..346ba3e86e 100644 --- a/libraries/core-react/src/TextField/HelperText/HelperText.token.js +++ b/libraries/core-react/src/TextField/HelperText/HelperText.token.ts @@ -1,4 +1,3 @@ -// @ts-nocheck import { tokens } from '@equinor/eds-tokens' const { @@ -21,6 +20,12 @@ const spacings = { bottom: '6px', }, } +export type HelperTextVariantProps = { + color: string + disabledColor: string + focusColor: string +} + export const helperText = { background: colors.ui.background__light.hex, typography: typography.input.helper, @@ -28,29 +33,21 @@ export const helperText = { default: { color: colors.text.static_icons__tertiary.hex, disabledColor: colors.interactive.disabled__text.hex, - focus: { - color: colors.text.static_icons__tertiary.hex, - }, + focusColor: colors.text.static_icons__tertiary.hex, }, error: { - color: colors.interactive.danger__resting.hex, + color: colors.interactive.danger__text.hex, disabledColor: colors.interactive.disabled__text.hex, - focus: { - color: colors.interactive.danger__hover.hex, - }, + focusColor: colors.interactive.danger__hover.hex, }, warning: { - color: colors.interactive.warning__resting.hex, + color: colors.interactive.warning__text.hex, disabledColor: colors.interactive.disabled__text.hex, - focus: { - color: colors.interactive.warning__hover.hex, - }, + focusColor: colors.interactive.warning__hover.hex, }, success: { - color: colors.interactive.success__resting.hex, + color: colors.interactive.success__text.hex, disabledColor: colors.interactive.disabled__text.hex, - focus: { - color: colors.interactive.success__hover.hex, - }, + focusColor: colors.interactive.success__hover.hex, }, } diff --git a/libraries/core-react/src/TextField/HelperText/HelperText.tsx b/libraries/core-react/src/TextField/HelperText/HelperText.tsx new file mode 100644 index 0000000000..ec332698ac --- /dev/null +++ b/libraries/core-react/src/TextField/HelperText/HelperText.tsx @@ -0,0 +1,112 @@ +import React, { ReactNode } from 'react' +import styled, { css } from 'styled-components' +import { Spacing, typographyTemplate } from '../../_common/templates' +import { + HelperTextVariantProps, + helperText as tokens, +} from './HelperText.token' +import { useTextField } from '../context' +import { Icon } from '../Icon' +import type { Variants } from '../types' + +type VariantionProps = { + variant: HelperTextVariantProps + isFocused: boolean + isDisabled: boolean +} + +const Variation = ({ variant, isFocused, isDisabled }: VariantionProps) => { + if (!variant) { + return `` + } + + const { focusColor, color, disabledColor } = variant + + if (isDisabled) { + return css` + color: ${disabledColor}; + ` + } + + if (isFocused) { + return css` + color: ${focusColor}; + ` + } + + return css` + color: ${color}; + ` +} + +type StyledProps = { + spacings: Spacing +} + +const Container = styled.div` + display: flex; + align-items: flex-end; + + margin-left: ${({ spacings }) => spacings.left}; + margin-top: ${({ spacings }) => spacings.top}; +` +const Text = styled.p` + margin: 0; + ${typographyTemplate(tokens.typography)} + ${Variation} +` + +const StyledIcon = styled(Icon)` + margin-right: ${({ spacings }) => spacings.left}; +` + +type Props = { + /** Helper text */ + helperText?: string + /** Icon */ + icon?: ReactNode + /** Disabled */ + disabled?: boolean + /** Variant */ + variant: Variants +} + +const HelperText = React.forwardRef( + function TextFieldHelperText(props, ref) { + const { + helperText, + icon, + variant = 'default', + disabled: isDisabled, + } = props + const helperVariant = tokens[variant] + const spacings = tokens.spacings.comfortable + + const { isFocused } = useTextField() + + const iconProps = { + spacings, + isDisabled, + color: helperVariant.color, + disabledColor: helperVariant.disabledColor, + focusColor: helperVariant.focusColor, + } + + return ( + + {icon && {icon}} + + {helperText} + + + ) + }, +) + +HelperText.displayName = 'eds-text-field-helperText' + +export { HelperText } diff --git a/libraries/core-react/src/TextField/HelperText/index.js b/libraries/core-react/src/TextField/HelperText/index.ts similarity index 73% rename from libraries/core-react/src/TextField/HelperText/index.js rename to libraries/core-react/src/TextField/HelperText/index.ts index 72c8468832..23c77d008a 100644 --- a/libraries/core-react/src/TextField/HelperText/index.js +++ b/libraries/core-react/src/TextField/HelperText/index.ts @@ -1,2 +1 @@ -// @ts-nocheck export { HelperText } from './HelperText' diff --git a/libraries/core-react/src/TextField/Icon/Icon.jsx b/libraries/core-react/src/TextField/Icon/Icon.jsx deleted file mode 100644 index ce164fabed..0000000000 --- a/libraries/core-react/src/TextField/Icon/Icon.jsx +++ /dev/null @@ -1,67 +0,0 @@ -// @ts-nocheck -import React from 'react' -import PropTypes from 'prop-types' -import styled from 'styled-components' -import { propsFor, useTextField } from '../context' - -const IconVariation = ({ - color, - focusColor, - disabledColor, - isDisabled, - isFocused, -}) => { - let color_ = color - if (isDisabled) { - color_ = disabledColor - } - if (isFocused) { - color_ = focusColor - } - return `fill: ${color_};` -} - -const StyledIcon = styled.div` - width: 16px; - height: 16px; - ${IconVariation} -` - -const Icon = React.forwardRef(function TextFieldIcon(props, ref) { - const { children, ...other } = props - const { isFocused } = useTextField() - - return ( - - {children} - - ) -}) - -Icon.propTypes = { - /** @ignore */ - children: PropTypes.node, - /** @ignore */ - className: PropTypes.string, - /** Variant */ - variant: PropTypes.oneOf(propsFor.variants), - /** Disabled color */ - disabledColor: PropTypes.string, - /** Focus color */ - focusColor: PropTypes.string, - /** Color */ - color: PropTypes.string, -} - -Icon.defaultProps = { - children: null, - className: '', - variant: 'default', - disabledColor: '', - focusColor: '', - color: '', -} - -Icon.displayName = 'eds-text-field-icon' - -export { Icon } diff --git a/libraries/core-react/src/TextField/Icon/Icon.tsx b/libraries/core-react/src/TextField/Icon/Icon.tsx new file mode 100644 index 0000000000..cef5c8bd8d --- /dev/null +++ b/libraries/core-react/src/TextField/Icon/Icon.tsx @@ -0,0 +1,68 @@ +import React from 'react' +import styled, { css } from 'styled-components' +import { useTextField } from '../context' + +type VariationProps = { + color: string + focusColor: string + disabledColor: string + isDisabled?: boolean + isFocused?: boolean +} + +const Variation = ({ + color, + focusColor, + disabledColor, + isDisabled, + isFocused, +}: VariationProps) => { + if (isDisabled) { + return css` + fill: ${disabledColor}; + ` + } + if (isFocused) { + return css` + fill: ${focusColor}; + ` + } + return css` + fill: ${color}; + ` +} + +const StyledIcon = styled.div` + width: 16px; + height: 16px; + ${Variation} +` + +type Props = { + /** Disabled color */ + disabledColor: string + /** Focus color */ + focusColor: string + /** Color */ + color: string + /** isDisabled */ + isDisabled?: boolean +} + +const Icon = React.forwardRef(function TextFieldIcon( + props, + ref, +) { + const { children, ...other } = props + const { isFocused } = useTextField() + + return ( + + {children} + + ) +}) + +Icon.displayName = 'eds-text-field-icon' + +export { Icon } diff --git a/libraries/core-react/src/TextField/Icon/index.js b/libraries/core-react/src/TextField/Icon/index.ts similarity index 66% rename from libraries/core-react/src/TextField/Icon/index.js rename to libraries/core-react/src/TextField/Icon/index.ts index d7cac994d4..d78603a27e 100644 --- a/libraries/core-react/src/TextField/Icon/index.js +++ b/libraries/core-react/src/TextField/Icon/index.ts @@ -1,2 +1 @@ -// @ts-nocheck export { Icon } from './Icon' diff --git a/libraries/core-react/src/TextField/Input/Input.jsx b/libraries/core-react/src/TextField/Input/Input.jsx deleted file mode 100644 index 781d29a60c..0000000000 --- a/libraries/core-react/src/TextField/Input/Input.jsx +++ /dev/null @@ -1,157 +0,0 @@ -// @ts-nocheck -import React from 'react' -import PropTypes from 'prop-types' -import styled from 'styled-components' -import { input as tokens } from './Input.tokens' -import { typographyTemplate } from '../../_common/templates' -import { propsFor, useTextField } from '../context' -import { Icon } from '../Icon' - -const typeProps = ['text', 'search', 'password', 'email', 'number'] - -const Variation = ({ variant }) => { - if (!variant) { - return `` - } - - const { - focus: { border: focusBorderOutline }, - border: { outline: borderOutline, bottom: borderBottom }, - } = variant - - return ` - border-bottom: ${borderBottom.width} solid ${borderBottom.color}; - outline: ${borderOutline.width} solid ${borderOutline.color}; - - &:active, - &:focus { - outline-offset:0; - border-bottom: 1px solid transparent; - outline: ${focusBorderOutline.width} solid ${focusBorderOutline.color}; - - } - - &:disabled { - cursor: not-allowed; - border-bottom: 1px solid transparent; - outline: none; - - &:focus, - &:active { - outline: none; - } - } -` -} - -const StyledInput = styled.input` - width: 100%; - box-sizing: border-box; - margin: 0; - border: none; - appearance: none; - - background: ${tokens.background}; - padding-left: ${({ spacings }) => spacings.left}; - padding-right: ${({ spacings }) => spacings.right}; - padding-top: ${({ spacings }) => spacings.top}; - padding-bottom: ${({ spacings }) => spacings.bottom}; - - ${typographyTemplate(tokens.typography)} - color: ${tokens.color}; - - ${Variation} -` - -const Container = styled.div` - position: relative; -` - -const StyledIcon = styled(Icon)` - position: absolute; - right: ${({ spacings }) => spacings.right}; - top: ${({ spacings }) => spacings.top}; - bottom: ${({ spacings }) => spacings.bottom}; -` - -const Input = React.forwardRef(function TextFieldInput(props, ref) { - const { multiline, variant, inputIcon, disabled, ...other } = props - - const { handleFocus, handleBlur } = useTextField() - - const as = multiline ? 'textarea' : 'input' - const inputVariant = tokens[variant] - let spacings = tokens.spacings.comfortable - - if (inputIcon) { - spacings = { - ...spacings, - input: { - ...spacings.input, - right: '32px', - }, - } - } - - const iconProps = { - spacings: spacings.icon, - isDisabled: disabled, - color: inputVariant.icon.color, - disabledColor: inputVariant.icon.disabledColor, - focusColor: inputVariant.focus.icon.color, - } - - return ( - - - {inputIcon && {inputIcon}} - - ) -}) - -Input.propTypes = { - /** @ignore */ - className: PropTypes.string, - /** Specifies if text should be bold */ - multiline: PropTypes.bool, - /** Input label */ - label: PropTypes.string, - /** Placeholder */ - placeholder: PropTypes.string, - /** Specifiec which type input is */ - type: PropTypes.oneOf(typeProps), - /** Variant */ - variant: PropTypes.oneOf(propsFor.variants), - /** Icon to be embeded in input field */ - inputIcon: PropTypes.element, - /** Disabled state */ - disabled: PropTypes.bool, -} - -Input.defaultProps = { - className: '', - multiline: false, - label: '', - placeholder: '', - type: 'text', - variant: 'default', - inputIcon: null, - disabled: false, -} - -Input.displayName = 'eds-text-field-input' - -Input.constants = { - types: typeProps, -} - -export { Input } diff --git a/libraries/core-react/src/TextField/Input/Input.tokens.js b/libraries/core-react/src/TextField/Input/Input.tokens.ts similarity index 90% rename from libraries/core-react/src/TextField/Input/Input.tokens.js rename to libraries/core-react/src/TextField/Input/Input.tokens.ts index f69058cfd7..a2060f5e90 100644 --- a/libraries/core-react/src/TextField/Input/Input.tokens.js +++ b/libraries/core-react/src/TextField/Input/Input.tokens.ts @@ -1,4 +1,3 @@ -// @ts-nocheck import { tokens } from '@equinor/eds-tokens' const { @@ -38,6 +37,26 @@ const spacings = { }, } +export type InputVariantProps = { + icon: { + color: string + disabledColor: string + } + border: { + outline: { color: string; width: string } + bottom: { color: string; width: string } + } + focus: { + icon: { + color: string + } + border: { + width: string + color: string + } + } +} + export const input = { background: colors.ui.background__light.hex, typography: typography.input.text, diff --git a/libraries/core-react/src/TextField/Input/Input.tsx b/libraries/core-react/src/TextField/Input/Input.tsx new file mode 100644 index 0000000000..562d03ca86 --- /dev/null +++ b/libraries/core-react/src/TextField/Input/Input.tsx @@ -0,0 +1,157 @@ +import React, { ReactNode, ElementType } from 'react' +import styled, { css } from 'styled-components' +import { InputVariantProps, input as tokens } from './Input.tokens' +import { + Spacing, + typographyTemplate, + spacingsTemplate, +} from '../../_common/templates' +import { useTextField } from '../context' +import { Icon } from '../Icon' +import type { Variants } from '../types' + +const Variation = ({ variant }: { variant: InputVariantProps }) => { + if (!variant) { + return `` + } + + const { + focus: { border: focusBorderOutline }, + border: { outline: borderOutline, bottom: borderBottom }, + } = variant + + return css` + border-bottom: ${borderBottom.width} solid ${borderBottom.color}; + outline: ${borderOutline.width} solid ${borderOutline.color}; + + &:active, + &:focus { + outline-offset: 0; + border-bottom: 1px solid transparent; + outline: ${focusBorderOutline.width} solid ${focusBorderOutline.color}; + } + + &:disabled { + cursor: not-allowed; + border-bottom: 1px solid transparent; + outline: none; + + &:focus, + &:active { + outline: none; + } + } + ` +} + +type StyledProps = { + spacings: Spacing + variant: InputVariantProps +} + +const StyledInput = styled.input` + width: 100%; + box-sizing: border-box; + margin: 0; + border: none; + appearance: none; + + background: ${tokens.background}; + + ${({ spacings }) => spacingsTemplate(spacings)} + ${typographyTemplate(tokens.typography)} + color: ${tokens.color}; + + ${Variation} +` + +const Container = styled.div` + position: relative; +` + +type StyledIconProps = { + spacings: Spacing +} + +const StyledIcon = styled(Icon)` + position: absolute; + right: ${({ spacings }) => spacings.right}; + top: ${({ spacings }) => spacings.top}; + bottom: ${({ spacings }) => spacings.bottom}; +` + +type Props = { + /** Specifies if text should be bold */ + multiline?: boolean + /** Placeholder */ + placeholder?: string + /** Variant */ + variant?: Variants + /** Icon to be embeded in input field */ + inputIcon?: ReactNode + /** Disabled state */ + disabled?: boolean + /** Type */ + type?: string + /** Read Only */ + readonly?: boolean +} + +const Input = React.forwardRef(function TextFieldInput( + props, + ref, +) { + const { + multiline = false, + variant = 'default', + inputIcon, + disabled = false, + type = 'text', + ...other + } = props + + const { handleFocus, handleBlur } = useTextField() + + const as: ElementType = multiline ? 'textarea' : 'input' + const inputVariant = tokens[variant] + let spacings = tokens.spacings.comfortable + + if (inputIcon) { + spacings = { + ...spacings, + input: { + ...spacings.input, + right: '32px', + }, + } + } + + const iconProps = { + spacings: spacings.icon, + isDisabled: disabled, + color: inputVariant.icon.color, + disabledColor: inputVariant.icon.disabledColor, + focusColor: inputVariant.focus.icon.color, + } + + const inputProps = { + as, + ref, + type, + disabled, + variant: inputVariant, + spacings: spacings.input, + ...other, + } + + return ( + + + {inputIcon && {inputIcon}} + + ) +}) + +Input.displayName = 'eds-text-field-input' + +export { Input } diff --git a/libraries/core-react/src/TextField/Input/index.js b/libraries/core-react/src/TextField/Input/index.ts similarity index 68% rename from libraries/core-react/src/TextField/Input/index.js rename to libraries/core-react/src/TextField/Input/index.ts index 0f4d41c96d..3188ccc6a9 100644 --- a/libraries/core-react/src/TextField/Input/index.js +++ b/libraries/core-react/src/TextField/Input/index.ts @@ -1,2 +1 @@ -// @ts-nocheck export { Input } from './Input' diff --git a/libraries/core-react/src/TextField/Label/Label.tokens.js b/libraries/core-react/src/TextField/Label/Label.tokens.ts similarity index 96% rename from libraries/core-react/src/TextField/Label/Label.tokens.js rename to libraries/core-react/src/TextField/Label/Label.tokens.ts index b048bc987b..9856dd6b03 100644 --- a/libraries/core-react/src/TextField/Label/Label.tokens.js +++ b/libraries/core-react/src/TextField/Label/Label.tokens.ts @@ -1,4 +1,3 @@ -// @ts-nocheck import { tokens } from '@equinor/eds-tokens' const { diff --git a/libraries/core-react/src/TextField/Label/Label.jsx b/libraries/core-react/src/TextField/Label/Label.tsx similarity index 62% rename from libraries/core-react/src/TextField/Label/Label.jsx rename to libraries/core-react/src/TextField/Label/Label.tsx index 59731f8dc3..0abd9c2646 100644 --- a/libraries/core-react/src/TextField/Label/Label.jsx +++ b/libraries/core-react/src/TextField/Label/Label.tsx @@ -1,6 +1,4 @@ -// @ts-nocheck import React from 'react' -import PropTypes from 'prop-types' import styled from 'styled-components' import { typographyTemplate } from '../../_common/templates' import { label as tokens } from './Label.tokens' @@ -10,20 +8,27 @@ const LabelBase = styled.label` justify-content: space-between; position: relative; + ${typographyTemplate(tokens.typography)} margin-left: ${tokens.spacings.left}; margin-right: ${tokens.spacings.right}; - - ${typographyTemplate(tokens.typography)} color: ${tokens.color}; - ` const Text = styled.p` margin: 0; ` -const Label = React.forwardRef(function TextFieldLabel(props, ref) { - const { label, meta, inputId } = props +type Props = { + label: string + meta: string + inputId: string +} + +const Label = React.forwardRef(function TextFieldLabel( + props, + ref, +) { + const { label = '', meta = '', inputId } = props return ( @@ -33,20 +38,6 @@ const Label = React.forwardRef(function TextFieldLabel(props, ref) { ) }) -Label.propTypes = { - /** Label text */ - label: PropTypes.string, - /** Meta text */ - meta: PropTypes.string, - /** Id of input for `for` */ - inputId: PropTypes.string.isRequired, -} - -Label.defaultProps = { - label: '', - meta: '', -} - Label.displayName = 'eds-text-field-label' export { Label } diff --git a/libraries/core-react/src/TextField/Label/index.js b/libraries/core-react/src/TextField/Label/index.ts similarity index 68% rename from libraries/core-react/src/TextField/Label/index.js rename to libraries/core-react/src/TextField/Label/index.ts index 74d1321401..717144f332 100644 --- a/libraries/core-react/src/TextField/Label/index.js +++ b/libraries/core-react/src/TextField/Label/index.ts @@ -1,2 +1 @@ -// @ts-nocheck export { Label } from './Label' diff --git a/libraries/core-react/src/TextField/TextField.test.jsx b/libraries/core-react/src/TextField/TextField.test.tsx similarity index 95% rename from libraries/core-react/src/TextField/TextField.test.jsx rename to libraries/core-react/src/TextField/TextField.test.tsx index aa60933209..cd062b9171 100644 --- a/libraries/core-react/src/TextField/TextField.test.jsx +++ b/libraries/core-react/src/TextField/TextField.test.tsx @@ -29,15 +29,16 @@ describe('TextField', () => { const { queryByDisplayValue } = render( , ) + const inputElement = queryByDisplayValue(value) as HTMLInputElement - expect(queryByDisplayValue(value).value).toBe(value) + expect(inputElement.value).toBe(value) }) it('Has correct updated value when changed', () => { let value = 'Initial value' const newValue = 'Updated value' const onChangeHandler = (ele) => { - // eslint-disable-next-line prefer-destructuring + // eslint-disable-next-line value = ele.target.value } diff --git a/libraries/core-react/src/TextField/TextField.jsx b/libraries/core-react/src/TextField/TextField.tsx similarity index 58% rename from libraries/core-react/src/TextField/TextField.jsx rename to libraries/core-react/src/TextField/TextField.tsx index 926571b1b0..99d09291cf 100644 --- a/libraries/core-react/src/TextField/TextField.jsx +++ b/libraries/core-react/src/TextField/TextField.tsx @@ -1,18 +1,51 @@ -// @ts-nocheck -import React from 'react' -import PropTypes from 'prop-types' +import React, { ReactNode } from 'react' import styled from 'styled-components' import { Input } from './Input' import { Label } from './Label' import { HelperText } from './HelperText' -import { propsFor, TextFieldProvider } from './context' +import { TextFieldProvider } from './context' +import type { Variants } from './types' const Container = styled.div` min-width: 100px; width: 100%; ` -const TextField = React.forwardRef(function TextField(props, ref) { +type Props = { + /** @ignore */ + className?: string + /** Variants */ + variant?: Variants + /** Input unique id */ + id: string + /** Label text */ + label?: string + /** Meta text */ + meta?: string + /** Helper text */ + helperText?: string + /** Placeholder text */ + placeholder?: string + /** Disabled */ + disabled?: boolean + /** Multiline input */ + multiline?: boolean + /** Input ref */ + inputRef?: React.Ref + /** InputIcon */ + inputIcon?: ReactNode + /** HelperIcon */ + helperIcon?: ReactNode + /** Value */ + value?: string + /** Read Only */ + readOnly?: boolean +} & React.HTMLAttributes + +const TextField = React.forwardRef(function TextField( + props, + ref, +) { const { id, label, @@ -22,7 +55,7 @@ const TextField = React.forwardRef(function TextField(props, ref) { disabled, multiline, className, - variant, + variant = 'default', inputRef, inputIcon, helperIcon, @@ -72,51 +105,6 @@ const TextField = React.forwardRef(function TextField(props, ref) { ) }) -TextField.propTypes = { - /** @ignore */ - className: PropTypes.string, - /** Variant */ - variant: PropTypes.oneOf(propsFor.variants), - /** Input unique id */ - id: PropTypes.string.isRequired, - /** Label text */ - label: PropTypes.string, - /** Meta text */ - meta: PropTypes.string, - /** Helper text */ - helperText: PropTypes.string, - /** Placeholder text */ - placeholder: PropTypes.string, - /** Disabled */ - disabled: PropTypes.bool, - /** Multiline input */ - multiline: PropTypes.bool, - /** Input ref */ - inputRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), - /** InputIcon */ - inputIcon: PropTypes.element, - /** HelperIcon */ - helperIcon: PropTypes.element, -} - -TextField.defaultProps = { - className: '', - placeholder: '', - helperText: '', - label: '', - meta: '', - disabled: false, - variant: 'default', - multiline: false, - inputRef: null, - inputIcon: null, - helperIcon: null, -} TextField.displayName = 'eds-text-field' -TextField.constants = { - variants: propsFor.variants, - types: Input.constants.types, -} - export { TextField } diff --git a/libraries/core-react/src/TextField/context.jsx b/libraries/core-react/src/TextField/context.jsx deleted file mode 100644 index efde976c84..0000000000 --- a/libraries/core-react/src/TextField/context.jsx +++ /dev/null @@ -1,50 +0,0 @@ -// @ts-nocheck -import React, { useState, useContext } from 'react' -import PropTypes from 'prop-types' - -export const propsFor = { - variants: ['error', 'warning', 'success', 'default'], -} - -const initalState = { - isFocused: false, -} - -const TextFieldContext = React.createContext(initalState) - -export const TextFieldProvider = ({ children }) => { - const [state, setState] = useState(initalState) - return ( - - {children} - - ) -} - -TextFieldProvider.propTypes = { - /** @ignore */ - children: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.node), - PropTypes.node, - ]).isRequired, -} - -TextFieldProvider.defaultProps = {} - -export const useTextField = () => { - const [state, setState] = useContext(TextFieldContext) - - const handleFocus = () => { - setState({ ...state, isFocused: true }) - } - const handleBlur = () => { - setState({ ...state, isFocused: false }) - } - - return { - handleFocus, - handleBlur, - isFocused: state.isFocused, - isDisabled: state.isDisabled, - } -} diff --git a/libraries/core-react/src/TextField/context.tsx b/libraries/core-react/src/TextField/context.tsx new file mode 100644 index 0000000000..5b61b78249 --- /dev/null +++ b/libraries/core-react/src/TextField/context.tsx @@ -0,0 +1,46 @@ +import React, { useState, useContext, ReactNode } from 'react' + +export const propsFor = { + variants: ['error', 'warning', 'success', 'default'], +} + +type State = { + isFocused: boolean +} + +type UseTextFieldProps = { + handleFocus: () => void + handleBlur: () => void +} & T + +const initalState: State = { + isFocused: false, +} + +const TextFieldContext = React.createContext(initalState) + +type ProviderProps = { children: ReactNode } + +export const TextFieldProvider = ({ children }: ProviderProps): JSX.Element => { + const [state, setState] = useState(initalState) + + const handleFocus = () => { + setState({ ...state, isFocused: true }) + } + const handleBlur = () => { + setState({ ...state, isFocused: false }) + } + const value = { + handleFocus, + handleBlur, + isFocused: state.isFocused, + } + return ( + + {children} + + ) +} + +export const useTextField = (): UseTextFieldProps => + useContext(TextFieldContext) as UseTextFieldProps diff --git a/libraries/core-react/src/TextField/index.js b/libraries/core-react/src/TextField/index.ts similarity index 72% rename from libraries/core-react/src/TextField/index.js rename to libraries/core-react/src/TextField/index.ts index 12fd880a53..dea5f2d477 100644 --- a/libraries/core-react/src/TextField/index.js +++ b/libraries/core-react/src/TextField/index.ts @@ -1,2 +1 @@ -// @ts-nocheck export { TextField } from './TextField' diff --git a/libraries/core-react/src/TextField/types.ts b/libraries/core-react/src/TextField/types.ts new file mode 100644 index 0000000000..008ce83d7d --- /dev/null +++ b/libraries/core-react/src/TextField/types.ts @@ -0,0 +1 @@ +export type Variants = 'error' | 'warning' | 'success' | 'default' diff --git a/libraries/core-react/src/_common/templates.ts b/libraries/core-react/src/_common/templates.ts index bcf94dc2a6..2ff91c8c38 100644 --- a/libraries/core-react/src/_common/templates.ts +++ b/libraries/core-react/src/_common/templates.ts @@ -3,12 +3,12 @@ import type { FlattenSimpleInterpolation } from 'styled-components' type StyledCSS = FlattenSimpleInterpolation -type Typography = { +export type Typography = { color: string fontFamily: string fontSize: string fontWeight: number - letterSpacing: string + letterSpacing?: string lineHeight: string textAlign?: string fontStyle?: string @@ -17,13 +17,13 @@ type Typography = { fontFeature?: string } -type Border = { +export type Border = { radius: string color: string width: string } -type Spacing = { +export type Spacing = { left: string right: string top: string