@wonderflow/react-components
Version:
UI components from Wonderflow's Wanda design system
48 lines (47 loc) • 3.86 kB
JavaScript
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';