"use client" import * as React from "react" import { XIcon } from "lucide-react" import { InputDecorator } from "./decorator" import { createInputChangeHandler, getInputValue } from "./value" import { stopInteractivePropagation } from "@/lib/utils" export type ClearableInputProps = Omit< React.ComponentProps, "value" | "onChange" > & { value?: string | number | null onChange?: React.ChangeEventHandler onValueChange?: (value: string) => void onClear?: () => void clearable?: boolean clearLabel?: string clearOnEscape?: boolean focusAfterClear?: boolean replaceTrailingWhenClear?: boolean leadingIcon?: React.ReactNode trailing?: React.ReactNode trailingAction?: React.ReactNode wrapperClassName?: string inputClassName?: string } const ClearableInput = React.forwardRef( ( { value, onChange, onValueChange, onClear, clearable = true, clearLabel = "Clear", clearOnEscape = true, focusAfterClear = true, replaceTrailingWhenClear = true, leadingIcon, trailing, trailingAction, disabled, onKeyDown, ...props }, ref ) => { const inputRef = React.useRef(null) const stringValue = getInputValue(value) const canClear = clearable && stringValue.length > 0 && !disabled && !props.readOnly const handleChange = createInputChangeHandler({ onChange, onValueChange }) React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement) const clearValue = () => { if (!canClear) return onValueChange?.("") onClear?.() if (focusAfterClear) inputRef.current?.focus() } const handleClearClick: React.MouseEventHandler = (event) => { stopInteractivePropagation(event) clearValue() } const handleClearMouseDown: React.MouseEventHandler = (event) => { stopInteractivePropagation(event) } const handleKeyDown: React.KeyboardEventHandler = (event) => { onKeyDown?.(event) if (event.defaultPrevented) return if (clearOnEscape && event.key === "Escape" && canClear) { event.preventDefault() clearValue() } } return ( {trailingAction} {canClear && ( )} } {...props} /> ) } ) ClearableInput.displayName = "ClearableInput" export { ClearableInput }