UNPKG

@chayns-components/core

Version:

A set of beautiful React components for developing your own applications with chayns.

142 lines 4.98 kB
import React, { useCallback, useMemo } from 'react'; import { getHumanSize, getIconByMimeType } from '../../../utils/file'; import Icon from '../../icon/Icon'; import ContextMenu from '../../context-menu/ContextMenu'; import ListItem from '../../list/list-item/ListItem'; import { StyledFileItem, StyledFileItemKeyboardWrapper, StyledFileItemIcon } from './FileItem.styles'; import { ttsToITextString, useTextstringValue } from '@chayns-components/textstring'; import textStrings from '../../../constants/textStrings'; import { useKeyboardFocusHighlighting } from '../../../hooks/useKeyboardFocusHighlighting'; const FileItem = ({ mimeType, onRemove, size, name, id, source, shouldAllowDownload }) => { const canDownload = shouldAllowDownload && !!source; const canRemove = typeof onRemove === 'function'; const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(canRemove || !!canDownload); const handleRemove = useCallback(() => { if (canRemove) { onRemove(id); } }, [id, onRemove]); const handleItemKeyDown = useCallback(event => { if (event.key === 'Delete') { event.preventDefault(); handleRemove(); } }, [handleRemove]); const handleRemoveKeyDown = useCallback(event => { if (canRemove && (event.key === 'Enter' || event.key === ' ')) { event.preventDefault(); event.stopPropagation(); handleRemove(); } }, [handleRemove]); const humanFileSize = useMemo(() => { if (typeof size === 'number') { return getHumanSize(size); } return undefined; }, [size]); const icon = useMemo(() => getIconByMimeType(mimeType), [mimeType]); const handleDownload = useCallback(() => { if (!source) return; if (source instanceof File) { const url = URL.createObjectURL(source); const a = document.createElement('a'); a.href = url; a.download = name; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } else { // Try fetching as blob to force download. If CORS blocks it, // fall back to opening the URL directly. fetch(source).then(res => { if (!res.ok) throw new Error('fetch failed'); return res.blob(); }).then(blob => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = name; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }).catch(() => { // CORS or network error: fall back to direct link const a = document.createElement('a'); a.href = source; a.download = name; a.rel = 'noopener noreferrer'; a.target = '_blank'; document.body.appendChild(a); a.click(); document.body.removeChild(a); }); } }, [name, source]); const downloadText = useTextstringValue({ textstring: ttsToITextString(textStrings.components.fileItem.download) }); const removeText = useTextstringValue({ textstring: ttsToITextString(textStrings.components.fileItem.remove) }); const rightElement = useMemo(() => { if (!canDownload && !canRemove) return undefined; // Both actions available → show as ContextMenu if (canDownload && canRemove) { const items = [{ icons: ['fa fa-download'], key: 'download', onClick: handleDownload, text: downloadText }, { icons: ['fa fa-trash'], key: 'remove', onClick: () => onRemove(id), text: removeText }]; return /*#__PURE__*/React.createElement(ContextMenu, { items: items }); } const handleClick = () => { if (canRemove) { onRemove(id); return; } handleDownload(); }; const handleKeyDown = canRemove ? handleRemoveKeyDown : undefined; const fileIcon = canRemove ? 'ts-wrong' : 'fa fa-download'; return /*#__PURE__*/React.createElement(StyledFileItemIcon, { onClick: handleClick, onKeyDown: handleKeyDown, role: "button", tabIndex: 0 }, /*#__PURE__*/React.createElement(Icon, { icons: [fileIcon] })); }, [canDownload, canRemove, downloadText, handleDownload, handleRemoveKeyDown, id, onRemove, removeText]); return useMemo(() => /*#__PURE__*/React.createElement(StyledFileItem, null, /*#__PURE__*/React.createElement(StyledFileItemKeyboardWrapper, { onKeyDown: handleItemKeyDown, tabIndex: -1 }, /*#__PURE__*/React.createElement(ListItem, { title: name, subtitle: humanFileSize, icons: [icon], rightElements: rightElement, shouldEnableKeyboardHighlighting: shouldShowKeyboardHighlighting }))), [handleItemKeyDown, humanFileSize, icon, name, rightElement, shouldShowKeyboardHighlighting]); }; FileItem.displayName = 'FileList'; export default FileItem; //# sourceMappingURL=FileItem.js.map