@yamada-ui/file-input
Version:
Yamada UI file input component
171 lines (169 loc) • 4.95 kB
JavaScript
"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