UNPKG

@wonderflow/react-components

Version:

UI components from Wonderflow's Wanda design system

48 lines (47 loc) 3.86 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import clsx from 'clsx'; import { forwardRef, useCallback, useMemo, useState, } from 'react'; import { useUIDSeed } from 'react-uid'; import { IconButton, Stack, Symbol, Text, } from '../..'; import { BaseField } from './base-field'; import * as styles from './textfield.module.css'; export const Textfield = forwardRef(({ children, className, disabled = false, icon, label, textarea, readOnly, invalid, id, iconPosition = 'right', dimension = 'regular', message, type, style, fullWidth, minRows = 4, maxRows = 6, onChange, ...otherProps }, forwardedRef) => { const [isPasswordVisible, setPasswordVisible] = useState(false); const seedID = useUIDSeed(); const isPassword = type === 'password'; const fieldID = useMemo(() => id ?? seedID('field'), [id, seedID]); const handlePasswordVisibility = useCallback(() => { setPasswordVisible(visibility => !visibility); }, []); const dynamicStyle = { '--textarea-min-height': (minRows > 0) ? `${24 * minRows + 16 + 2}px` : 'unset', '--textarea-max-height': (maxRows > 0) ? `${24 * maxRows + 16 + 2}px` : 'unset', '--textarea-overflow-y': (maxRows > 0) ? 'scroll' : 'unset', }; const iconSizes = { small: 12, regular: 16, big: 24, }; const actionSizes = { small: 'small', regular: 'regular', big: 'big', }; const commonProps = { readOnly, invalid: invalid && !disabled, disabled, onChange, }; return (_jsxs(Stack, { as: "fieldset", rowGap: 4, className: clsx(styles.Textfield, className), "data-testid": "Textfield", "data-textfield-has-icon": isPassword || Boolean(icon), "data-textfield-icon-position": iconPosition, "data-textfield-dimension": dimension, "data-textfield-invalid": invalid && !disabled, "data-textfield-fullwidth": fullWidth, "aria-disabled": disabled, "aria-invalid": invalid && !disabled, hAlign: "stretch", vAlign: "start", tabIndex: disabled ? 0 : undefined, style: style, children: [label && _jsx(Text, { as: "label", "aria-disabled": disabled, className: styles.Label, variant: dimension === 'big' ? 'body-1' : 'body-2', htmlFor: fieldID, children: label }), _jsxs("div", { className: styles.FieldContainer, children: [textarea ? (_jsx(BaseField, { ref: forwardedRef, as: "textarea", className: styles.Textarea, style: { ...dynamicStyle }, id: fieldID, ...commonProps, ...otherProps })) : (_jsx(BaseField, { className: styles.InputField, id: fieldID, ref: forwardedRef, type: isPasswordVisible ? 'text' : type, spellCheck: isPassword ? false : undefined, ...commonProps, ...otherProps })), isPassword && (_jsx(IconButton, { className: styles.IconButton, dimension: actionSizes[dimension], onClick: handlePasswordVisibility, kind: "flat", "aria-label": "Reveal password", "data-testid": "RevealIcon", icon: isPasswordVisible ? 'eye-slash' : 'eye', // eslint-disable-next-line no-nested-ternary iconColor: disabled ? 'var(--global-disabled-foreground)' : invalid ? 'var(--highlight-red-foreground)' : 'var(--global-foreground)', disabled: disabled })), !textarea && icon && !isPassword && (_jsx(Symbol, { className: styles.Icon, source: icon, dimension: iconSizes[dimension], "aria-disabled": disabled, fill: disabled ? 'var(--global-disabled-foreground)' : 'currentcolor' }))] }), message && _jsx(Text, { as: "label", color: (invalid && !disabled) ? 'danger' : undefined, "aria-disabled": disabled, className: styles.Label, variant: dimension === 'big' ? 'body-2' : 'body-3', children: message })] })); }); Textfield.displayName = 'Textfield';