UNPKG

@amaui/ui-react

Version:
197 lines (195 loc) 8.4 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(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } import React from 'react'; import { is, to } from '@amaui/utils'; import { classNames, style as styleMethod, useAmauiTheme } from '@amaui/style-react'; import IconMaterialClose from '@amaui/icons-material-rounded-react/IconMaterialCloseW100'; import IconMaterialDraft from '@amaui/icons-material-rounded-react/IconMaterialDraftW100'; import IconMaterialCloudUpload from '@amaui/icons-material-rounded-react/IconMaterialCloudUploadW100'; import IconMaterialFolder from '@amaui/icons-material-rounded-react/IconMaterialFolderW100'; import IconMaterialFolderOpen from '@amaui/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: 'amaui-FileChoose' }); const FileChoose = /*#__PURE__*/React.forwardRef((props_, ref) => { const theme = useAmauiTheme(); const props = React.useMemo(() => _objectSpread(_objectSpread(_objectSpread({}, theme?.ui?.elements?.all?.props?.default), theme?.ui?.elements?.amauiFileChoose?.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) && ['amaui-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) && ['amaui-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) && ['amaui-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) && ['amaui-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) && ['amaui-FileChoose-file'], classes.file]) }, item.name), /*#__PURE__*/React.createElement(Type, { version: "b3", priority: "secondary" }, to(item.size, 'size-format'))) }))))); }); FileChoose.displayName = 'amaui-FileChoose'; export default FileChoose;