UNPKG

@onesy/ui-react

Version:
197 lines (195 loc) 8.25 kB
import _extends from "@babel/runtime/helpers/extends"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; const _excluded = ["tonal", "color", "inputRef", "size", "max", "allowedTypes", "files", "valueDefault", "value", "multiple", "accept", "capture", "remove", "renderFiles", "onClick", "onChange", "IconStart", "inputProps", "WrapperProps", "ComponentProps", "Component", "className", "style", "children"]; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import React from 'react'; import { is, to } from '@onesy/utils'; import { classNames, style as styleMethod, useOnesyTheme } from '@onesy/style-react'; import IconMaterialClose from '@onesy/icons-material-rounded-react/IconMaterialCloseW100'; import IconMaterialDraft from '@onesy/icons-material-rounded-react/IconMaterialDraftW100'; import IconMaterialCloudUpload from '@onesy/icons-material-rounded-react/IconMaterialCloudUploadW100'; import IconMaterialFolder from '@onesy/icons-material-rounded-react/IconMaterialFolderW100'; import IconMaterialFolderOpen from '@onesy/icons-material-rounded-react/IconMaterialFolderOpenW100'; import TypeElement from '../Type'; import ButtonElement from '../Button'; import IconButtonElement from '../IconButton'; import TreeElement from '../Tree'; import LineElement from '../Line'; import { iconFontSize, staticClassName } from '../utils'; const useStyle = styleMethod(theme => ({ root: { position: 'relative' }, input: { position: 'absolute', width: '0px', height: '0px', visibility: 'hidden' }, files: { width: '340px', maxWidth: '100%' }, file: { maxWidth: '174px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }), { name: 'onesy-FileChoose' }); const FileChoose = /*#__PURE__*/React.forwardRef((props_, ref) => { const theme = useOnesyTheme(); const props = React.useMemo(() => _objectSpread(_objectSpread(_objectSpread({}, theme?.ui?.elements?.all?.props?.default), theme?.ui?.elements?.onesyFileChoose?.props?.default), props_), [props_]); const Line = React.useMemo(() => theme?.elements?.Line || LineElement, [theme]); const Type = React.useMemo(() => theme?.elements?.Type || TypeElement, [theme]); const Button = React.useMemo(() => theme?.elements?.Button || ButtonElement, [theme]); const IconButton = React.useMemo(() => theme?.elements?.IconButton || IconButtonElement, [theme]); const Tree = React.useMemo(() => theme?.elements?.Tree || TreeElement, [theme]); const { tonal = true, color = 'default', inputRef, size = 'regular', max, allowedTypes, files, valueDefault, value: value_, multiple, accept, capture, remove = true, renderFiles, onClick, onChange: onChange_, IconStart = IconMaterialCloudUpload, inputProps, WrapperProps: WrapperProps_, ComponentProps: ComponentProps_, Component = Button, className, style, children = 'Choose file' } = props, other = _objectWithoutProperties(props, _excluded); const { classes } = useStyle(); const [init, setInit] = React.useState(false); const [value, setValue] = React.useState(valueDefault !== undefined ? valueDefault : value_); const refs = { value: React.useRef(undefined), input: React.useRef(undefined), allowedTypes: React.useRef(undefined), max: React.useRef(undefined) }; refs.value.current = value; refs.max.current = max; refs.allowedTypes.current = allowedTypes; React.useEffect(() => { setInit(true); }, []); React.useEffect(() => { if (init) { if (value_ !== refs.value.current) setValue(value_); } }, [value_]); const onChange = React.useCallback(valueNew_ => { let valueNew = valueNew_; // Allowed types if (is('array', refs.allowedTypes.current)) valueNew = valueNew.map(item => refs.allowedTypes.current.includes(item.name)); // Max if (refs.max.current) valueNew = valueNew.slice(0, refs.max.current); if (!props.hasOwnProperty('value')) setValue(valueNew); if (is('function', onChange_)) onChange_(valueNew); }, []); const onChangeMethod = React.useCallback(event => { const valueNew = Array.from(refs.input.current.files); onChange(valueNew); }, []); const onRemove = index => { const valueNew = [...value]; valueNew.splice(index, 1); onChange(valueNew); }; const onReset = event => { if (refs.input.current) refs.input.current.value = ''; if (is('function', onClick)) onClick(event); }; const Wrapper = files ? Line : React.Fragment; const WrapperProps = files ? _objectSpread(_objectSpread({ ref, direction: 'column' }, WrapperProps_), {}, { className: classNames([staticClassName('FileChoose', theme) && ['onesy-FileChoose-root'], WrapperProps_?.className, className, classes.root]) }, other) : undefined; let ComponentProps = _objectSpread({}, ComponentProps_); if (!files) { ComponentProps = _objectSpread(_objectSpread({}, ComponentProps), {}, { ref, className: classNames([staticClassName('FileChoose', theme) && ['onesy-FileChoose-root'], ComponentProps_?.className, className, classes.root]) }, other); } return /*#__PURE__*/React.createElement(Wrapper, WrapperProps, /*#__PURE__*/React.createElement(Component, _extends({ Component: "label", tonal: tonal, color: color, version: "outlined", start: /*#__PURE__*/React.createElement(IconStart, null), onClick: onReset, size: size }, ComponentProps), /*#__PURE__*/React.createElement("input", _extends({ ref: item => { if (inputRef) inputRef.current = item; refs.input.current = item; }, type: "file", accept: accept, multiple: multiple, capture: capture, onChange: onChangeMethod }, inputProps, { className: classNames([staticClassName('FileChoose', theme) && ['onesy-FileChoose-input'], inputProps?.className, classes.input]) })), children), files && !!value?.length && (is('function', renderFiles) ? renderFiles(value, onRemove) : /*#__PURE__*/React.createElement(Tree, { openDefault: true, icon: /*#__PURE__*/React.createElement(IconMaterialFolder, { size: "small" }), iconOpen: /*#__PURE__*/React.createElement(IconMaterialFolderOpen, { size: "small" }), middle: "Files", indicator: true, indicatorPosition: "end", className: classNames([staticClassName('FileChoose', theme) && ['onesy-FileChoose-files'], classes.files]) }, value.map((item, index) => /*#__PURE__*/React.createElement(Tree, { key: index, icon: /*#__PURE__*/React.createElement(IconMaterialDraft, { size: "small" }), end: remove && /*#__PURE__*/React.createElement(IconButton, { tonal: true, color: "default", size: 20, fontSize: iconFontSize, onClick: () => onRemove(index) }, /*#__PURE__*/React.createElement(IconMaterialClose, null)), middle: /*#__PURE__*/React.createElement(Line, { gap: 1, direction: "row", align: "center" }, /*#__PURE__*/React.createElement(Type, { version: "b2", className: classNames([staticClassName('FileChoose', theme) && ['onesy-FileChoose-file'], classes.file]) }, item.name), /*#__PURE__*/React.createElement(Type, { version: "b3", priority: "secondary" }, to(item.size, 'size-format'))) }))))); }); FileChoose.displayName = 'onesy-FileChoose'; export default FileChoose;