@bsol-oss/react-datatable5 12.0.0-beta.76 → 12.0.0-beta.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -4869,7 +4869,7 @@ function getText(_ref2) {
|
|
|
4869
4869
|
return source.getStringData(textMediaType);
|
|
4870
4870
|
}
|
|
4871
4871
|
|
|
4872
|
-
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder =
|
|
4872
|
+
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder = 'Drop files here or click to upload', }) => {
|
|
4873
4873
|
const ref = React.useRef(null);
|
|
4874
4874
|
const [isDraggedOver, setIsDraggedOver] = React.useState(false);
|
|
4875
4875
|
React.useEffect(() => {
|
|
@@ -4883,7 +4883,7 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4883
4883
|
onDrop: ({ source }) => {
|
|
4884
4884
|
const files = getFiles({ source });
|
|
4885
4885
|
const text = getText({ source });
|
|
4886
|
-
console.log(files, text,
|
|
4886
|
+
console.log(files, text, 'dfposa');
|
|
4887
4887
|
onDrop({ files, text });
|
|
4888
4888
|
},
|
|
4889
4889
|
});
|
|
@@ -4892,9 +4892,9 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4892
4892
|
function getColor(isDraggedOver) {
|
|
4893
4893
|
if (isDraggedOver) {
|
|
4894
4894
|
return {
|
|
4895
|
-
backgroundColor:
|
|
4895
|
+
backgroundColor: 'blue.400',
|
|
4896
4896
|
_dark: {
|
|
4897
|
-
backgroundColor:
|
|
4897
|
+
backgroundColor: 'blue.400',
|
|
4898
4898
|
},
|
|
4899
4899
|
};
|
|
4900
4900
|
}
|
|
@@ -4915,7 +4915,7 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4915
4915
|
const filesArray = [...event.target.files];
|
|
4916
4916
|
onDrop({ files: filesArray });
|
|
4917
4917
|
};
|
|
4918
|
-
return (jsxRuntime.jsxs(react.Grid, { ...getColor(isDraggedOver), ref: ref, cursor:
|
|
4918
|
+
return (jsxRuntime.jsxs(react.Grid, { ...getColor(isDraggedOver), ref: ref, cursor: 'pointer', onClick: handleClick, borderStyle: 'dashed', borderColor: 'colorPalette.400', alignContent: 'center', justifyContent: 'center', borderWidth: 1, borderRadius: 4, minH: "120px", ...gridProps, children: [children, !!children === false && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(react.Flex, { children: placeholder }), jsxRuntime.jsx(react.Input, { type: "file", multiple: true, style: { display: 'none' }, ref: fileInput, onChange: handleChange })] }))] }));
|
|
4919
4919
|
};
|
|
4920
4920
|
|
|
4921
4921
|
/**
|
|
@@ -4935,6 +4935,7 @@ function formatBytes(bytes) {
|
|
|
4935
4935
|
function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, labels, translate, colLabel, }) {
|
|
4936
4936
|
const [searchTerm, setSearchTerm] = React.useState('');
|
|
4937
4937
|
const [selectedFileId, setSelectedFileId] = React.useState('');
|
|
4938
|
+
const [failedImageIds, setFailedImageIds] = React.useState(new Set());
|
|
4938
4939
|
const { data: filesData, isLoading, isError, } = reactQuery.useQuery({
|
|
4939
4940
|
queryKey: ['file-picker-library', searchTerm],
|
|
4940
4941
|
queryFn: async () => {
|
|
@@ -4961,31 +4962,72 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4961
4962
|
onClose();
|
|
4962
4963
|
setSelectedFileId('');
|
|
4963
4964
|
setSearchTerm('');
|
|
4965
|
+
setFailedImageIds(new Set());
|
|
4966
|
+
};
|
|
4967
|
+
const handleImageError = (fileId) => {
|
|
4968
|
+
setFailedImageIds((prev) => new Set(prev).add(fileId));
|
|
4964
4969
|
};
|
|
4965
4970
|
if (!onFetchFiles)
|
|
4966
4971
|
return null;
|
|
4967
4972
|
return (jsxRuntime.jsx(DialogRoot, { open: open, onOpenChange: (e) => !e.open && handleClose(), children: jsxRuntime.jsxs(DialogContent, { maxWidth: "800px", maxHeight: "90vh", children: [jsxRuntime.jsxs(DialogHeader, { children: [jsxRuntime.jsx(DialogTitle, { fontSize: "lg", fontWeight: "bold", children: title }), jsxRuntime.jsx(DialogCloseTrigger, {})] }), jsxRuntime.jsx(DialogBody, { children: jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 4, children: [jsxRuntime.jsxs(react.Box, { position: "relative", children: [jsxRuntime.jsx(react.Input, { placeholder: labels?.searchPlaceholder ??
|
|
4968
4973
|
translate(removeIndex(`${colLabel}.search_placeholder`)) ??
|
|
4969
|
-
'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", _focus: {
|
|
4970
|
-
borderColor: '
|
|
4971
|
-
|
|
4974
|
+
'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", colorPalette: "blue", _focus: {
|
|
4975
|
+
borderColor: 'colorPalette.500',
|
|
4976
|
+
_dark: {
|
|
4977
|
+
borderColor: 'colorPalette.400',
|
|
4978
|
+
},
|
|
4979
|
+
boxShadow: {
|
|
4980
|
+
base: '0 0 0 1px var(--chakra-colors-blue-500)',
|
|
4981
|
+
_dark: '0 0 0 1px var(--chakra-colors-blue-400)',
|
|
4982
|
+
},
|
|
4972
4983
|
}, pl: 10 }), jsxRuntime.jsx(react.Icon, { as: lu.LuSearch, position: "absolute", left: 3, top: "50%", transform: "translateY(-50%)", color: "fg.muted", boxSize: 4 })] }), isLoading && (jsxRuntime.jsxs(react.Box, { textAlign: "center", py: 8, children: [jsxRuntime.jsx(react.Spinner, { size: "lg", colorPalette: "blue" }), jsxRuntime.jsx(react.Text, { mt: 4, color: "fg.muted", children: labels?.loading ??
|
|
4973
4984
|
translate(removeIndex(`${colLabel}.loading`)) ??
|
|
4974
|
-
'Loading files...' })] })), isError && (jsxRuntime.jsx(react.Box, { bg:
|
|
4985
|
+
'Loading files...' })] })), isError && (jsxRuntime.jsx(react.Box, { bg: { base: 'colorPalette.50', _dark: 'colorPalette.900/20' }, border: "1px solid", borderColor: {
|
|
4986
|
+
base: 'colorPalette.200',
|
|
4987
|
+
_dark: 'colorPalette.800',
|
|
4988
|
+
}, colorPalette: "red", borderRadius: "md", p: 4, children: jsxRuntime.jsx(react.Text, { color: {
|
|
4989
|
+
base: 'colorPalette.600',
|
|
4990
|
+
_dark: 'colorPalette.300',
|
|
4991
|
+
}, children: labels?.loadingFailed ??
|
|
4975
4992
|
translate(removeIndex(`${colLabel}.error.loading_failed`)) ??
|
|
4976
4993
|
'Failed to load files' }) })), !isLoading && !isError && (jsxRuntime.jsx(react.Box, { maxHeight: "400px", overflowY: "auto", children: filteredFiles.length === 0 ? (jsxRuntime.jsx(react.Box, { textAlign: "center", py: 8, children: jsxRuntime.jsx(react.Text, { color: "fg.muted", children: labels?.noFilesFound ??
|
|
4977
4994
|
translate(removeIndex(`${colLabel}.no_files_found`)) ??
|
|
4978
4995
|
'No files found' }) })) : (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
|
|
4979
4996
|
const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
|
|
4980
4997
|
const isSelected = selectedFileId === file.id;
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4998
|
+
const imageFailed = failedImageIds.has(file.id);
|
|
4999
|
+
return (jsxRuntime.jsx(react.Box, { p: 3, border: "2px solid", borderColor: isSelected
|
|
5000
|
+
? {
|
|
5001
|
+
base: 'colorPalette.500',
|
|
5002
|
+
_dark: 'colorPalette.400',
|
|
5003
|
+
}
|
|
5004
|
+
: 'border.default', borderRadius: "md", bg: isSelected
|
|
5005
|
+
? {
|
|
5006
|
+
base: 'colorPalette.50',
|
|
5007
|
+
_dark: 'colorPalette.900/20',
|
|
5008
|
+
}
|
|
5009
|
+
: 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => setSelectedFileId(file.id), _hover: {
|
|
5010
|
+
borderColor: isSelected
|
|
5011
|
+
? {
|
|
5012
|
+
base: 'colorPalette.600',
|
|
5013
|
+
_dark: 'colorPalette.400',
|
|
5014
|
+
}
|
|
5015
|
+
: {
|
|
5016
|
+
base: 'colorPalette.300',
|
|
5017
|
+
_dark: 'colorPalette.400',
|
|
5018
|
+
},
|
|
5019
|
+
bg: isSelected
|
|
5020
|
+
? {
|
|
5021
|
+
base: 'colorPalette.100',
|
|
5022
|
+
_dark: 'colorPalette.800/30',
|
|
5023
|
+
}
|
|
5024
|
+
: 'bg.muted',
|
|
5025
|
+
}, transition: "all 0.2s", children: jsxRuntime.jsxs(react.HStack, { gap: 3, children: [jsxRuntime.jsx(react.Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, children: isImage && file.url && !imageFailed ? (jsxRuntime.jsx(react.Image, { src: file.url, alt: file.name, boxSize: "60px", objectFit: "cover", borderRadius: "md", onError: () => handleImageError(file.id) })) : isImage && (imageFailed || !file.url) ? (jsxRuntime.jsx(react.Icon, { as: lu.LuImage, boxSize: 6, color: "fg.muted" })) : (jsxRuntime.jsx(react.Icon, { as: lu.LuFile, boxSize: 6, color: "fg.muted" })) }), jsxRuntime.jsxs(react.VStack, { align: "start", flex: 1, gap: 1, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.name }), jsxRuntime.jsxs(react.HStack, { gap: 2, children: [file.size && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: typeof file.size === 'number'
|
|
4987
5026
|
? formatBytes(file.size)
|
|
4988
|
-
: file.size }) })), file.comment && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [file.size && (jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: "\u2022" })), jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.comment })] }))] })] }), isSelected && (jsxRuntime.jsx(react.Box, { width: "24px", height: "24px", borderRadius: "full", bg:
|
|
5027
|
+
: file.size }) })), file.comment && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [file.size && (jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: "\u2022" })), jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.comment })] }))] })] }), isSelected && (jsxRuntime.jsx(react.Box, { width: "24px", height: "24px", borderRadius: "full", bg: {
|
|
5028
|
+
base: 'colorPalette.500',
|
|
5029
|
+
_dark: 'colorPalette.400',
|
|
5030
|
+
}, colorPalette: "blue", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: jsxRuntime.jsx(react.Text, { color: "white", fontSize: "xs", fontWeight: "bold", children: "\u2713" }) }))] }) }, file.id));
|
|
4989
5031
|
}) })) }))] }) }), jsxRuntime.jsx(DialogFooter, { children: jsxRuntime.jsxs(react.HStack, { gap: 3, justify: "end", children: [jsxRuntime.jsx(react.Button, { variant: "outline", onClick: handleClose, borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: labels?.cancel ??
|
|
4990
5032
|
translate(removeIndex(`${colLabel}.cancel`)) ??
|
|
4991
5033
|
'Cancel' }), jsxRuntime.jsx(react.Button, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFileId, children: labels?.select ??
|
|
@@ -5004,8 +5046,12 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
5004
5046
|
: [];
|
|
5005
5047
|
const colLabel = formI18n.colLabel;
|
|
5006
5048
|
const [dialogOpen, setDialogOpen] = React.useState(false);
|
|
5049
|
+
const [failedImageIds, setFailedImageIds] = React.useState(new Set());
|
|
5007
5050
|
const { onFetchFiles, enableMediaLibrary = false, filterImageOnly = false, } = filePicker || {};
|
|
5008
5051
|
const showMediaLibrary = enableMediaLibrary && !!onFetchFiles;
|
|
5052
|
+
const handleImageError = (fileIdentifier) => {
|
|
5053
|
+
setFailedImageIds((prev) => new Set(prev).add(fileIdentifier));
|
|
5054
|
+
};
|
|
5009
5055
|
const handleMediaLibrarySelect = (fileId) => {
|
|
5010
5056
|
const newFiles = [...currentFiles, fileId];
|
|
5011
5057
|
setValue(colLabel, newFiles);
|
|
@@ -5069,10 +5115,11 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
5069
5115
|
const fileSize = getFileSize(file);
|
|
5070
5116
|
const isImage = isImageFile(file);
|
|
5071
5117
|
const imageUrl = getImageUrl(file);
|
|
5072
|
-
|
|
5073
|
-
|
|
5118
|
+
const imageFailed = failedImageIds.has(fileIdentifier);
|
|
5119
|
+
return (jsxRuntime.jsx(react.Card.Root, { variant: 'subtle', colorPalette: "blue", children: jsxRuntime.jsxs(react.Card.Body, { gap: "2", cursor: 'pointer', onClick: () => handleRemove(index), display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', border: "2px solid", borderColor: "border.default", borderRadius: "md", _hover: {
|
|
5120
|
+
borderColor: 'colorPalette.300',
|
|
5074
5121
|
bg: 'bg.muted',
|
|
5075
|
-
}, transition: "all 0.2s", children: [jsxRuntime.jsx(react.Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, marginRight: "2", children: isImage && imageUrl ? (jsxRuntime.jsx(react.Image, { src: imageUrl, alt: fileName, boxSize: "60px", objectFit: "cover", borderRadius: "md" })) : (jsxRuntime.jsx(react.Icon, { as: lu.LuFile, boxSize: 6, color: "fg.muted" })) }), jsxRuntime.jsxs(react.VStack, { align: "start", flex: 1, gap: 1, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: fileName }), fileSize !== undefined && (jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: formatBytes(fileSize) }))] }), jsxRuntime.jsx(react.Icon, { as: ti.TiDeleteOutline, boxSize: 5, color: "fg.muted" })] }) }, fileIdentifier));
|
|
5122
|
+
}, transition: "all 0.2s", children: [jsxRuntime.jsx(react.Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, marginRight: "2", children: isImage && imageUrl && !imageFailed ? (jsxRuntime.jsx(react.Image, { src: imageUrl, alt: fileName, boxSize: "60px", objectFit: "cover", borderRadius: "md", onError: () => handleImageError(fileIdentifier) })) : isImage && (imageFailed || !imageUrl) ? (jsxRuntime.jsx(react.Icon, { as: lu.LuImage, boxSize: 6, color: "fg.muted" })) : (jsxRuntime.jsx(react.Icon, { as: lu.LuFile, boxSize: 6, color: "fg.muted" })) }), jsxRuntime.jsxs(react.VStack, { align: "start", flex: 1, gap: 1, children: [jsxRuntime.jsx(react.Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: fileName }), fileSize !== undefined && (jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: formatBytes(fileSize) }))] }), jsxRuntime.jsx(react.Icon, { as: ti.TiDeleteOutline, boxSize: 5, color: "fg.muted" })] }) }, fileIdentifier));
|
|
5076
5123
|
}) })] }));
|
|
5077
5124
|
};
|
|
5078
5125
|
|
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal,
|
|
|
3
3
|
import { AiOutlineColumnWidth } from 'react-icons/ai';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import React__default, { createContext, useContext, useState, useEffect, useRef, forwardRef } from 'react';
|
|
6
|
-
import { LuX, LuCheck, LuChevronRight, LuFile, LuSearch } from 'react-icons/lu';
|
|
6
|
+
import { LuX, LuCheck, LuChevronRight, LuImage, LuFile, LuSearch } from 'react-icons/lu';
|
|
7
7
|
import { MdOutlineSort, MdFilterAlt, MdSearch, MdOutlineViewColumn, MdFilterListAlt, MdPushPin, MdCancel, MdClear, MdOutlineChecklist, MdDateRange } from 'react-icons/md';
|
|
8
8
|
import { FaUpDown, FaGripLinesVertical, FaTrash } from 'react-icons/fa6';
|
|
9
9
|
import { BiDownArrow, BiUpArrow, BiError } from 'react-icons/bi';
|
|
@@ -4849,7 +4849,7 @@ function getText(_ref2) {
|
|
|
4849
4849
|
return source.getStringData(textMediaType);
|
|
4850
4850
|
}
|
|
4851
4851
|
|
|
4852
|
-
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder =
|
|
4852
|
+
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder = 'Drop files here or click to upload', }) => {
|
|
4853
4853
|
const ref = useRef(null);
|
|
4854
4854
|
const [isDraggedOver, setIsDraggedOver] = useState(false);
|
|
4855
4855
|
useEffect(() => {
|
|
@@ -4863,7 +4863,7 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4863
4863
|
onDrop: ({ source }) => {
|
|
4864
4864
|
const files = getFiles({ source });
|
|
4865
4865
|
const text = getText({ source });
|
|
4866
|
-
console.log(files, text,
|
|
4866
|
+
console.log(files, text, 'dfposa');
|
|
4867
4867
|
onDrop({ files, text });
|
|
4868
4868
|
},
|
|
4869
4869
|
});
|
|
@@ -4872,9 +4872,9 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4872
4872
|
function getColor(isDraggedOver) {
|
|
4873
4873
|
if (isDraggedOver) {
|
|
4874
4874
|
return {
|
|
4875
|
-
backgroundColor:
|
|
4875
|
+
backgroundColor: 'blue.400',
|
|
4876
4876
|
_dark: {
|
|
4877
|
-
backgroundColor:
|
|
4877
|
+
backgroundColor: 'blue.400',
|
|
4878
4878
|
},
|
|
4879
4879
|
};
|
|
4880
4880
|
}
|
|
@@ -4895,7 +4895,7 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4895
4895
|
const filesArray = [...event.target.files];
|
|
4896
4896
|
onDrop({ files: filesArray });
|
|
4897
4897
|
};
|
|
4898
|
-
return (jsxs(Grid, { ...getColor(isDraggedOver), ref: ref, cursor:
|
|
4898
|
+
return (jsxs(Grid, { ...getColor(isDraggedOver), ref: ref, cursor: 'pointer', onClick: handleClick, borderStyle: 'dashed', borderColor: 'colorPalette.400', alignContent: 'center', justifyContent: 'center', borderWidth: 1, borderRadius: 4, minH: "120px", ...gridProps, children: [children, !!children === false && (jsxs(Fragment, { children: [jsx(Flex, { children: placeholder }), jsx(Input, { type: "file", multiple: true, style: { display: 'none' }, ref: fileInput, onChange: handleChange })] }))] }));
|
|
4899
4899
|
};
|
|
4900
4900
|
|
|
4901
4901
|
/**
|
|
@@ -4915,6 +4915,7 @@ function formatBytes(bytes) {
|
|
|
4915
4915
|
function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, labels, translate, colLabel, }) {
|
|
4916
4916
|
const [searchTerm, setSearchTerm] = useState('');
|
|
4917
4917
|
const [selectedFileId, setSelectedFileId] = useState('');
|
|
4918
|
+
const [failedImageIds, setFailedImageIds] = useState(new Set());
|
|
4918
4919
|
const { data: filesData, isLoading, isError, } = useQuery({
|
|
4919
4920
|
queryKey: ['file-picker-library', searchTerm],
|
|
4920
4921
|
queryFn: async () => {
|
|
@@ -4941,31 +4942,72 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4941
4942
|
onClose();
|
|
4942
4943
|
setSelectedFileId('');
|
|
4943
4944
|
setSearchTerm('');
|
|
4945
|
+
setFailedImageIds(new Set());
|
|
4946
|
+
};
|
|
4947
|
+
const handleImageError = (fileId) => {
|
|
4948
|
+
setFailedImageIds((prev) => new Set(prev).add(fileId));
|
|
4944
4949
|
};
|
|
4945
4950
|
if (!onFetchFiles)
|
|
4946
4951
|
return null;
|
|
4947
4952
|
return (jsx(DialogRoot, { open: open, onOpenChange: (e) => !e.open && handleClose(), children: jsxs(DialogContent, { maxWidth: "800px", maxHeight: "90vh", children: [jsxs(DialogHeader, { children: [jsx(DialogTitle, { fontSize: "lg", fontWeight: "bold", children: title }), jsx(DialogCloseTrigger, {})] }), jsx(DialogBody, { children: jsxs(VStack, { align: "stretch", gap: 4, children: [jsxs(Box, { position: "relative", children: [jsx(Input, { placeholder: labels?.searchPlaceholder ??
|
|
4948
4953
|
translate(removeIndex(`${colLabel}.search_placeholder`)) ??
|
|
4949
|
-
'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", _focus: {
|
|
4950
|
-
borderColor: '
|
|
4951
|
-
|
|
4954
|
+
'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", colorPalette: "blue", _focus: {
|
|
4955
|
+
borderColor: 'colorPalette.500',
|
|
4956
|
+
_dark: {
|
|
4957
|
+
borderColor: 'colorPalette.400',
|
|
4958
|
+
},
|
|
4959
|
+
boxShadow: {
|
|
4960
|
+
base: '0 0 0 1px var(--chakra-colors-blue-500)',
|
|
4961
|
+
_dark: '0 0 0 1px var(--chakra-colors-blue-400)',
|
|
4962
|
+
},
|
|
4952
4963
|
}, pl: 10 }), jsx(Icon, { as: LuSearch, position: "absolute", left: 3, top: "50%", transform: "translateY(-50%)", color: "fg.muted", boxSize: 4 })] }), isLoading && (jsxs(Box, { textAlign: "center", py: 8, children: [jsx(Spinner, { size: "lg", colorPalette: "blue" }), jsx(Text, { mt: 4, color: "fg.muted", children: labels?.loading ??
|
|
4953
4964
|
translate(removeIndex(`${colLabel}.loading`)) ??
|
|
4954
|
-
'Loading files...' })] })), isError && (jsx(Box, { bg:
|
|
4965
|
+
'Loading files...' })] })), isError && (jsx(Box, { bg: { base: 'colorPalette.50', _dark: 'colorPalette.900/20' }, border: "1px solid", borderColor: {
|
|
4966
|
+
base: 'colorPalette.200',
|
|
4967
|
+
_dark: 'colorPalette.800',
|
|
4968
|
+
}, colorPalette: "red", borderRadius: "md", p: 4, children: jsx(Text, { color: {
|
|
4969
|
+
base: 'colorPalette.600',
|
|
4970
|
+
_dark: 'colorPalette.300',
|
|
4971
|
+
}, children: labels?.loadingFailed ??
|
|
4955
4972
|
translate(removeIndex(`${colLabel}.error.loading_failed`)) ??
|
|
4956
4973
|
'Failed to load files' }) })), !isLoading && !isError && (jsx(Box, { maxHeight: "400px", overflowY: "auto", children: filteredFiles.length === 0 ? (jsx(Box, { textAlign: "center", py: 8, children: jsx(Text, { color: "fg.muted", children: labels?.noFilesFound ??
|
|
4957
4974
|
translate(removeIndex(`${colLabel}.no_files_found`)) ??
|
|
4958
4975
|
'No files found' }) })) : (jsx(VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
|
|
4959
4976
|
const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
|
|
4960
4977
|
const isSelected = selectedFileId === file.id;
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4978
|
+
const imageFailed = failedImageIds.has(file.id);
|
|
4979
|
+
return (jsx(Box, { p: 3, border: "2px solid", borderColor: isSelected
|
|
4980
|
+
? {
|
|
4981
|
+
base: 'colorPalette.500',
|
|
4982
|
+
_dark: 'colorPalette.400',
|
|
4983
|
+
}
|
|
4984
|
+
: 'border.default', borderRadius: "md", bg: isSelected
|
|
4985
|
+
? {
|
|
4986
|
+
base: 'colorPalette.50',
|
|
4987
|
+
_dark: 'colorPalette.900/20',
|
|
4988
|
+
}
|
|
4989
|
+
: 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => setSelectedFileId(file.id), _hover: {
|
|
4990
|
+
borderColor: isSelected
|
|
4991
|
+
? {
|
|
4992
|
+
base: 'colorPalette.600',
|
|
4993
|
+
_dark: 'colorPalette.400',
|
|
4994
|
+
}
|
|
4995
|
+
: {
|
|
4996
|
+
base: 'colorPalette.300',
|
|
4997
|
+
_dark: 'colorPalette.400',
|
|
4998
|
+
},
|
|
4999
|
+
bg: isSelected
|
|
5000
|
+
? {
|
|
5001
|
+
base: 'colorPalette.100',
|
|
5002
|
+
_dark: 'colorPalette.800/30',
|
|
5003
|
+
}
|
|
5004
|
+
: 'bg.muted',
|
|
5005
|
+
}, transition: "all 0.2s", children: jsxs(HStack, { gap: 3, children: [jsx(Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, children: isImage && file.url && !imageFailed ? (jsx(Image, { src: file.url, alt: file.name, boxSize: "60px", objectFit: "cover", borderRadius: "md", onError: () => handleImageError(file.id) })) : isImage && (imageFailed || !file.url) ? (jsx(Icon, { as: LuImage, boxSize: 6, color: "fg.muted" })) : (jsx(Icon, { as: LuFile, boxSize: 6, color: "fg.muted" })) }), jsxs(VStack, { align: "start", flex: 1, gap: 1, children: [jsx(Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.name }), jsxs(HStack, { gap: 2, children: [file.size && (jsx(Fragment, { children: jsx(Text, { fontSize: "xs", color: "fg.muted", children: typeof file.size === 'number'
|
|
4967
5006
|
? formatBytes(file.size)
|
|
4968
|
-
: file.size }) })), file.comment && (jsxs(Fragment, { children: [file.size && (jsx(Text, { fontSize: "xs", color: "fg.muted", children: "\u2022" })), jsx(Text, { fontSize: "xs", color: "fg.muted", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.comment })] }))] })] }), isSelected && (jsx(Box, { width: "24px", height: "24px", borderRadius: "full", bg:
|
|
5007
|
+
: file.size }) })), file.comment && (jsxs(Fragment, { children: [file.size && (jsx(Text, { fontSize: "xs", color: "fg.muted", children: "\u2022" })), jsx(Text, { fontSize: "xs", color: "fg.muted", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: file.comment })] }))] })] }), isSelected && (jsx(Box, { width: "24px", height: "24px", borderRadius: "full", bg: {
|
|
5008
|
+
base: 'colorPalette.500',
|
|
5009
|
+
_dark: 'colorPalette.400',
|
|
5010
|
+
}, colorPalette: "blue", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: jsx(Text, { color: "white", fontSize: "xs", fontWeight: "bold", children: "\u2713" }) }))] }) }, file.id));
|
|
4969
5011
|
}) })) }))] }) }), jsx(DialogFooter, { children: jsxs(HStack, { gap: 3, justify: "end", children: [jsx(Button$1, { variant: "outline", onClick: handleClose, borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: labels?.cancel ??
|
|
4970
5012
|
translate(removeIndex(`${colLabel}.cancel`)) ??
|
|
4971
5013
|
'Cancel' }), jsx(Button$1, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFileId, children: labels?.select ??
|
|
@@ -4984,8 +5026,12 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
4984
5026
|
: [];
|
|
4985
5027
|
const colLabel = formI18n.colLabel;
|
|
4986
5028
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
5029
|
+
const [failedImageIds, setFailedImageIds] = useState(new Set());
|
|
4987
5030
|
const { onFetchFiles, enableMediaLibrary = false, filterImageOnly = false, } = filePicker || {};
|
|
4988
5031
|
const showMediaLibrary = enableMediaLibrary && !!onFetchFiles;
|
|
5032
|
+
const handleImageError = (fileIdentifier) => {
|
|
5033
|
+
setFailedImageIds((prev) => new Set(prev).add(fileIdentifier));
|
|
5034
|
+
};
|
|
4989
5035
|
const handleMediaLibrarySelect = (fileId) => {
|
|
4990
5036
|
const newFiles = [...currentFiles, fileId];
|
|
4991
5037
|
setValue(colLabel, newFiles);
|
|
@@ -5049,10 +5095,11 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
5049
5095
|
const fileSize = getFileSize(file);
|
|
5050
5096
|
const isImage = isImageFile(file);
|
|
5051
5097
|
const imageUrl = getImageUrl(file);
|
|
5052
|
-
|
|
5053
|
-
|
|
5098
|
+
const imageFailed = failedImageIds.has(fileIdentifier);
|
|
5099
|
+
return (jsx(Card.Root, { variant: 'subtle', colorPalette: "blue", children: jsxs(Card.Body, { gap: "2", cursor: 'pointer', onClick: () => handleRemove(index), display: 'flex', flexFlow: 'row', alignItems: 'center', padding: '2', border: "2px solid", borderColor: "border.default", borderRadius: "md", _hover: {
|
|
5100
|
+
borderColor: 'colorPalette.300',
|
|
5054
5101
|
bg: 'bg.muted',
|
|
5055
|
-
}, transition: "all 0.2s", children: [jsx(Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, marginRight: "2", children: isImage && imageUrl ? (jsx(Image, { src: imageUrl, alt: fileName, boxSize: "60px", objectFit: "cover", borderRadius: "md" })) : (jsx(Icon, { as: LuFile, boxSize: 6, color: "fg.muted" })) }), jsxs(VStack, { align: "start", flex: 1, gap: 1, children: [jsx(Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: fileName }), fileSize !== undefined && (jsx(Text, { fontSize: "xs", color: "fg.muted", children: formatBytes(fileSize) }))] }), jsx(Icon, { as: TiDeleteOutline, boxSize: 5, color: "fg.muted" })] }) }, fileIdentifier));
|
|
5102
|
+
}, transition: "all 0.2s", children: [jsx(Box, { width: "60px", height: "60px", display: "flex", alignItems: "center", justifyContent: "center", bg: "bg.muted", borderRadius: "md", flexShrink: 0, marginRight: "2", children: isImage && imageUrl && !imageFailed ? (jsx(Image, { src: imageUrl, alt: fileName, boxSize: "60px", objectFit: "cover", borderRadius: "md", onError: () => handleImageError(fileIdentifier) })) : isImage && (imageFailed || !imageUrl) ? (jsx(Icon, { as: LuImage, boxSize: 6, color: "fg.muted" })) : (jsx(Icon, { as: LuFile, boxSize: 6, color: "fg.muted" })) }), jsxs(VStack, { align: "start", flex: 1, gap: 1, children: [jsx(Text, { fontSize: "sm", fontWeight: "medium", color: "fg.default", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: fileName }), fileSize !== undefined && (jsx(Text, { fontSize: "xs", color: "fg.muted", children: formatBytes(fileSize) }))] }), jsx(Icon, { as: TiDeleteOutline, boxSize: 5, color: "fg.muted" })] }) }, fileIdentifier));
|
|
5056
5103
|
}) })] }));
|
|
5057
5104
|
};
|
|
5058
5105
|
|