UNPKG

@itwin/itwinui-react

Version:

A react component library for iTwinUI

201 lines (200 loc) 6.36 kB
import * as React from 'react'; import { getWindow, SvgDocument, useMergedRefs, useSafeContext, useId, mergeEventHandlers, polymorphic, Box, } from '../../utils/index.js'; import cx from 'classnames'; import { FileEmptyCard } from './FileEmptyCard.js'; import { Anchor } from '../Typography/Anchor.js'; import { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden.js'; let toBytes = (bytes) => { let units = [' bytes', 'KB', 'MB', 'GB', 'TB']; let i = 0; while (bytes >= 1024 && ++i) bytes /= 1024; return bytes.toFixed(bytes < 10 && i > 0 ? 2 : 0) + units[i]; }; let toDate = (dateNumber) => { let date = new Date(dateNumber); return date.toDateString() + ' ' + date.toLocaleTimeString(); }; let FileUploadCardIcon = polymorphic.span('iui-file-card-icon', { children: React.createElement(SvgDocument, null), }); if ('development' === process.env.NODE_ENV) FileUploadCardIcon.displayName = 'FileUploadCard.Icon'; let FileUploadCardInfo = polymorphic.span('iui-file-card-text'); if ('development' === process.env.NODE_ENV) FileUploadCardInfo.displayName = 'FileUploadCard.Info'; let FileUploadCardTitle = React.forwardRef((props, ref) => { let { children, className, ...rest } = props; let { files } = useSafeContext(FileUploadCardContext); let title = files.length > 1 ? files.length + ' files selected' : files[0].name; return React.createElement( Box, { as: 'span', className: cx('iui-file-card-title', className), ref: ref, ...rest, }, children ?? title, ); }); if ('development' === process.env.NODE_ENV) FileUploadCardTitle.displayName = 'FileUploadCard.Title'; let FileUploadCardDescription = React.forwardRef((props, ref) => { let { children, className, ...rest } = props; let { files } = useSafeContext(FileUploadCardContext); let description = files.length > 1 ? files[0].name + ', ' + files[1].name : toBytes(files[0].size) + ' ' + toDate(files[0].lastModified); if (files.length > 2) description += ', and ' + (files.length - 2) + ' others'; return React.createElement( Box, { as: 'span', className: cx('iui-file-card-description', className), ref: ref, ...rest, }, children ?? description, ); }); if ('development' === process.env.NODE_ENV) FileUploadCardDescription.displayName = 'FileUploadCard.Description'; let FileUploadCardAction = polymorphic.div('iui-file-card-action'); if ('development' === process.env.NODE_ENV) FileUploadCardAction.displayName = 'FileUploadCard.Action'; let FileUploadCardInputLabel = React.forwardRef((props, ref) => { let { children, ...rest } = props; let { inputId } = useSafeContext(FileUploadCardContext); return React.createElement( Anchor, { as: 'label', ref: ref, htmlFor: inputId, ...rest, }, children, ); }); if ('development' === process.env.NODE_ENV) FileUploadCardInputLabel.displayName = 'FileUploadCard.InputLabel'; let FileUploadCardInput = React.forwardRef((props, ref) => { let { children, onChange, id, ...rest } = props; let { files, onFilesChange, setInternalFiles, inputId, setInputId } = useSafeContext(FileUploadCardContext); let setNativeFilesRef = React.useCallback( (node) => { if (!node || !getWindow()?.DataTransfer) return; let dataTransfer = new DataTransfer(); dataTransfer.items.clear(); Array.from(files).forEach((file) => dataTransfer.items.add(file)); node.files = dataTransfer.files; }, [files], ); let refs = useMergedRefs(ref, setNativeFilesRef); React.useEffect(() => { if (id && id !== inputId) setInputId(id); }, [id, inputId, setInputId]); return React.createElement( React.Fragment, null, React.createElement(VisuallyHidden, { as: 'input', type: 'file', unhideOnFocus: false, onChange: mergeEventHandlers(onChange, (e) => { let _files = Array.from(e.currentTarget.files || []); onFilesChange?.(_files); setInternalFiles(_files); }), ref: refs, id: id ?? inputId, ...rest, }), children, ); }); if ('development' === process.env.NODE_ENV) FileUploadCardInput.displayName = 'FileUploadCard.Input'; let FileUploadCardComponent = React.forwardRef((props, ref) => { let { className, children, files: filesProp, onFilesChange, emptyCard = React.createElement(FileEmptyCard, null), input, ...rest } = props; let [internalFiles, setInternalFiles] = React.useState(); let uid = useId(); let [inputId, setInputId] = React.useState(uid); let files = filesProp ?? internalFiles ?? []; return React.createElement( FileUploadCardContext.Provider, { value: { files, onFilesChange, setInternalFiles, inputId, setInputId, }, }, files?.length ? React.createElement( Box, { className: cx('iui-file-card', className), ref: ref, ...rest, }, children ?? React.createElement( React.Fragment, null, React.createElement(FileUploadCard.Icon, null), React.createElement( FileUploadCard.Info, null, React.createElement(FileUploadCard.Title, null), React.createElement(FileUploadCard.Description, null), ), React.createElement( FileUploadCard.Action, null, React.createElement(FileUploadCard.InputLabel, null, 'Replace'), ), ), ) : emptyCard, input ?? React.createElement(FileUploadCard.Input, null), ); }); export const FileUploadCard = Object.assign(FileUploadCardComponent, { Icon: FileUploadCardIcon, Info: FileUploadCardInfo, Title: FileUploadCardTitle, Description: FileUploadCardDescription, Action: FileUploadCardAction, InputLabel: FileUploadCardInputLabel, Input: FileUploadCardInput, }); if ('development' === process.env.NODE_ENV) FileUploadCard.displayName = 'FileUploadCard'; export const FileUploadCardContext = React.createContext(void 0); if ('development' === process.env.NODE_ENV) FileUploadCardContext.displayName = 'FileUploadCardContext';