UNPKG

@yamada-ui/file-input

Version:

Yamada UI file input component

171 lines (169 loc) 4.95 kB
"use client" // src/file-input.tsx import { forwardRef, omitThemeProps, ui, useComponentMultiStyle } from "@yamada-ui/core"; import { formControlProperties, useFormControlProps } from "@yamada-ui/form-control"; import { useClickable } from "@yamada-ui/use-clickable"; import { useControllableState } from "@yamada-ui/use-controllable-state"; import { assignRef, cx, dataAttr, handlerAll, isNull, mergeRefs, splitObject } from "@yamada-ui/utils"; import { cloneElement, useCallback, useMemo, useRef } from "react"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var defaultFormat = ({ name }) => name; var FileInput = forwardRef( ({ children, ...props }, ref) => { const [styles, mergedProps] = useComponentMultiStyle("FileInput", props); const { id, form, name, className, accept, component, defaultValue, format = defaultFormat, lineClamp = 1, multiple, placeholder, resetRef, separator = ",", value, onChange: onChangeProp, onClick: onClickProp, ...computedProps } = useFormControlProps(omitThemeProps(mergedProps)); const [ { "aria-readonly": ariaReadonly, disabled, readOnly, ...formControlProps }, rest ] = splitObject(computedProps, formControlProperties); const inputRef = useRef(null); const [values, setValues] = useControllableState({ defaultValue, value, onChange: onChangeProp }); const onClick = useCallback(() => { var _a; if (disabled || readOnly) return; (_a = inputRef.current) == null ? void 0 : _a.click(); }, [disabled, readOnly]); const onChange = useCallback( (ev) => { let files = !isNull(ev.currentTarget.files) ? Array.from(ev.currentTarget.files) : void 0; if (!(files == null ? void 0 : files.length)) files = void 0; setValues(files); }, [setValues] ); const onReset = useCallback(() => { if (inputRef.current) inputRef.current.value = ""; setValues(void 0); }, [setValues]); assignRef(resetRef, onReset); const cloneChildren = useMemo(() => { if (!(values == null ? void 0 : values.length)) return /* @__PURE__ */ jsx(ui.span, { lineClamp, children: placeholder }); if (children) return children(values); if (component) { return /* @__PURE__ */ jsx(ui.span, { lineClamp, children: values.map((value2, index) => { const el = component({ index, value: value2 }); const style = { marginBlockEnd: "0.125rem", marginBlockStart: "0.125rem", marginInlineEnd: "0.25rem" }; return el ? cloneElement(el, { key: index, style }) : null; }) }); } else { return /* @__PURE__ */ jsx(ui.span, { lineClamp, children: values.map((value2, index) => { const isLast = values.length === index + 1; return /* @__PURE__ */ jsxs(ui.span, { display: "inline-block", me: "0.25rem", children: [ format(value2, index), !isLast ? separator : null ] }, index); }) }); } }, [children, format, lineClamp, placeholder, separator, component, values]); const clickableProps = useClickable({ ref, ...formControlProps, ...rest, disabled: disabled || readOnly, onClick: handlerAll(onClickProp, onClick) }); const css = { alignItems: "center", cursor: !readOnly ? "pointer" : "auto", display: "flex", ...styles.field }; return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( ui.input, { id, ref: mergeRefs(inputRef, ref), form, type: "file", name, style: { border: "0px", clip: "rect(0px, 0px, 0px, 0px)", height: "1px", margin: "-1px", overflow: "hidden", padding: "0px", position: "absolute", whiteSpace: "nowrap", width: "1px" }, "aria-hidden": true, "aria-readonly": ariaReadonly, accept, disabled, multiple, readOnly, tabIndex: -1, onChange, ...formControlProps } ), /* @__PURE__ */ jsx( ui.div, { className: cx("ui-file-input", className), "data-placeholder": dataAttr(!(values == null ? void 0 : values.length)), py: (values == null ? void 0 : values.length) && component ? "0.125rem" : void 0, __css: css, ...clickableProps, children: cloneChildren } ) ] }); } ); FileInput.displayName = "FileInput"; FileInput.__ui__ = "FileInput"; export { FileInput }; //# sourceMappingURL=chunk-R5QLB7IM.mjs.map