import { ChangeEvent, FocusEvent, Fragment, KeyboardEvent, MouseEvent, useMemo, useRef, useState, } from 'react'; import { RtFormFieldBaseProps, RtFormFieldSize, RtFormFieldUI, } from '../types/rt-form-field-text.types'; import { RtSymbolActionOriginProps } from '@dpa/react-symbol-action'; import { useGridChild, RtGrid, RtGridProps } from '@dpa/react-grid'; import { createSyntheticEvent } from '../utils/create-synthetic-event'; export function useFormField({ onChange, onBlur, onClear, onFocus, onKeyUp, onKeyDown, onPressEnter, isClearable, disabled, readonly, value, clearable, size, ui, onTrailingActionClick, phDisplay, suffix, prefix, hint, detailsSlot, isDetailsSlotGridChild, label, required, }: RtFormFieldBaseProps & { ui: RtFormFieldUI; size: RtFormFieldSize; }) { const localInputRef = useRef(null); const [focus, setFocus] = useState(false); const [hover, setHover] = useState(false); const isValue = !!value || (value as any) === 0; const canClear = !!isClearable && !disabled && isValue && (clearable === 'persistent' || hover || focus); const symbolActionSize = useMemo<{ width: RtSymbolActionOriginProps['width']; height: RtSymbolActionOriginProps['height']; }>(() => { if (ui === 'ambulant-label') { return { width: 'md', height: 'lg' }; } else if (ui === 'space') { return { width: 'sm', height: 'lg' }; } else { return size === 'lg' ? { width: 'sm', height: 'md' } : { width: 'sm', height: 'sm' }; } }, [size, ui]); const { gridChildClassname, gridAttributes } = useGridChild({ size: size, radius: 'primary', }); const showPrefixSuffix = phDisplay === 'persistent' || ui !== 'ambulant-label' || focus || isValue; const isAmbulantLabelFloating = isValue || focus || ((!!suffix || !!prefix) && showPrefixSuffix); const isInnerGrid = !!hint || (!!detailsSlot && isDetailsSlotGridChild); const GridWrapper = RtGrid; const gridProps: Partial> = { direction: 'vertical', width: 'fill', }; const formFieldDataContentRef = useRef(null); const formatLabel = label + (required ? '*' : ''); const handleChange = (e: ChangeEvent) => { if (onChange) onChange({ value: (e.target as HTMLInputElement).value, event: e }); }; function handleClick() { setTimeout(() => { localInputRef.current?.focus(); }, 0); } function handleFocus(e: FocusEvent) { setFocus(true); if (onFocus) onFocus(e); } function handleBlur(e: FocusEvent) { setFocus(false); if (onBlur) onBlur(e); } function handleClear(e: MouseEvent) { if (!canClear) return; e.stopPropagation(); e.preventDefault(); if (!readonly && localInputRef.current) localInputRef.current.value = ''; if (onChange) { const event = createSyntheticEvent({ type: 'change', event: e, target: localInputRef.current!, }) as ChangeEvent; onChange({ value: localInputRef.current!.value, event }); } if (onClear) onClear(e); } function handleMouseEnter(e: MouseEvent) { setHover(true); } function handleMouseLeave(e: MouseEvent) { setHover(false); } function handleKeyUp(e: KeyboardEvent) { if (onKeyUp) onKeyUp(e); if (onPressEnter && e.key === 'Enter') onPressEnter(e); } function handleKeyDown(e: KeyboardEvent) { if (onKeyDown) onKeyDown(e); } function handleTrailingActionClick(e: MouseEvent) { if (onTrailingActionClick) { e.preventDefault(); e.stopPropagation(); onTrailingActionClick(e); } } return { symbolActionSize, localInputRef, hover, focus, canClear, gridChildClassname, gridAttributes, isAmbulantLabelFloating, GridWrapper, isInnerGrid, gridProps, formFieldDataContentRef, showPrefixSuffix, formatLabel, handleChange, handleClick, handleFocus, handleBlur, handleClear, handleMouseEnter, handleMouseLeave, handleKeyUp, handleKeyDown, handleTrailingActionClick, }; }