@bsol-oss/react-datatable5 12.0.0-beta.82 → 12.0.0-beta.84
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.d.ts
CHANGED
|
@@ -889,18 +889,18 @@ type MediaLibraryBrowserPropsBase = {
|
|
|
889
889
|
};
|
|
890
890
|
type MediaLibraryBrowserPropsSingle = MediaLibraryBrowserPropsBase & {
|
|
891
891
|
multiple?: false;
|
|
892
|
-
onFileSelect?: (
|
|
893
|
-
|
|
894
|
-
|
|
892
|
+
onFileSelect?: (file: FilePickerMediaFile) => void;
|
|
893
|
+
selectedFile?: FilePickerMediaFile;
|
|
894
|
+
onSelectedFileChange?: (file: FilePickerMediaFile | undefined) => void;
|
|
895
895
|
};
|
|
896
896
|
type MediaLibraryBrowserPropsMultiple = MediaLibraryBrowserPropsBase & {
|
|
897
897
|
multiple: true;
|
|
898
|
-
onFileSelect?: (
|
|
899
|
-
|
|
900
|
-
|
|
898
|
+
onFileSelect?: (files: FilePickerMediaFile[]) => void;
|
|
899
|
+
selectedFile?: FilePickerMediaFile[];
|
|
900
|
+
onSelectedFileChange?: (files: FilePickerMediaFile[]) => void;
|
|
901
901
|
};
|
|
902
902
|
type MediaLibraryBrowserProps = MediaLibraryBrowserPropsSingle | MediaLibraryBrowserPropsMultiple;
|
|
903
|
-
declare const MediaLibraryBrowser: ({ onFetchFiles, filterImageOnly, labels, enabled, multiple, onFileSelect,
|
|
903
|
+
declare const MediaLibraryBrowser: ({ onFetchFiles, filterImageOnly, labels, enabled, multiple, onFileSelect, selectedFile: controlledSelectedFile, onSelectedFileChange, }: MediaLibraryBrowserProps) => react_jsx_runtime.JSX.Element | null;
|
|
904
904
|
|
|
905
905
|
interface UseFormProps {
|
|
906
906
|
preLoadedValues?: FieldValues | undefined;
|
package/dist/index.js
CHANGED
|
@@ -4644,13 +4644,13 @@ function formatBytes(bytes) {
|
|
|
4644
4644
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
4645
4645
|
}
|
|
4646
4646
|
|
|
4647
|
-
const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, enabled = true, multiple = false, onFileSelect,
|
|
4647
|
+
const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, enabled = true, multiple = false, onFileSelect, selectedFile: controlledSelectedFile, onSelectedFileChange, }) => {
|
|
4648
4648
|
const [searchTerm, setSearchTerm] = React.useState('');
|
|
4649
|
-
const [
|
|
4649
|
+
const [internalSelectedFile, setInternalSelectedFile] = React.useState(multiple ? [] : undefined);
|
|
4650
4650
|
const [failedImageIds, setFailedImageIds] = React.useState(new Set());
|
|
4651
|
-
// Use controlled or internal state for
|
|
4652
|
-
const
|
|
4653
|
-
const
|
|
4651
|
+
// Use controlled or internal state for selectedFile
|
|
4652
|
+
const selectedFile = controlledSelectedFile ?? internalSelectedFile;
|
|
4653
|
+
const setSelectedFile = onSelectedFileChange ?? setInternalSelectedFile;
|
|
4654
4654
|
const { data: filesData, isLoading, isError, } = reactQuery.useQuery({
|
|
4655
4655
|
queryKey: ['file-picker-library', searchTerm],
|
|
4656
4656
|
queryFn: async () => {
|
|
@@ -4665,23 +4665,25 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4665
4665
|
const filteredFiles = filterImageOnly
|
|
4666
4666
|
? files.filter((file) => /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name))
|
|
4667
4667
|
: files;
|
|
4668
|
-
const handleFileClick = (
|
|
4668
|
+
const handleFileClick = (file) => {
|
|
4669
4669
|
if (multiple) {
|
|
4670
|
-
const currentSelection = Array.isArray(
|
|
4671
|
-
?
|
|
4670
|
+
const currentSelection = Array.isArray(selectedFile)
|
|
4671
|
+
? selectedFile
|
|
4672
4672
|
: [];
|
|
4673
|
-
const
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4673
|
+
const isAlreadySelected = currentSelection.some((f) => f.id === file.id);
|
|
4674
|
+
const newSelection = isAlreadySelected
|
|
4675
|
+
? currentSelection.filter((f) => f.id !== file.id)
|
|
4676
|
+
: [...currentSelection, file];
|
|
4677
|
+
setSelectedFile(newSelection);
|
|
4677
4678
|
if (onFileSelect) {
|
|
4678
4679
|
onFileSelect(newSelection);
|
|
4679
4680
|
}
|
|
4680
4681
|
}
|
|
4681
4682
|
else {
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4683
|
+
const newFile = selectedFile === file ? undefined : file;
|
|
4684
|
+
setSelectedFile(newFile);
|
|
4685
|
+
if (onFileSelect && newFile) {
|
|
4686
|
+
onFileSelect(newFile);
|
|
4685
4687
|
}
|
|
4686
4688
|
}
|
|
4687
4689
|
};
|
|
@@ -4708,9 +4710,10 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4708
4710
|
}, children: labels?.loadingFailed ?? '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 ?? 'No files found' }) })) : (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
|
|
4709
4711
|
const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
|
|
4710
4712
|
const isSelected = multiple
|
|
4711
|
-
? Array.isArray(
|
|
4712
|
-
|
|
4713
|
-
:
|
|
4713
|
+
? Array.isArray(selectedFile) &&
|
|
4714
|
+
selectedFile.some((f) => f.id === file.id)
|
|
4715
|
+
: selectedFile?.id ===
|
|
4716
|
+
file.id;
|
|
4714
4717
|
const imageFailed = failedImageIds.has(file.id);
|
|
4715
4718
|
return (jsxRuntime.jsx(react.Box, { p: 3, border: "2px solid", borderColor: isSelected
|
|
4716
4719
|
? {
|
|
@@ -4722,7 +4725,7 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4722
4725
|
base: 'colorPalette.50',
|
|
4723
4726
|
_dark: 'colorPalette.900/20',
|
|
4724
4727
|
}
|
|
4725
|
-
: 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => handleFileClick(file
|
|
4728
|
+
: 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => handleFileClick(file), _hover: {
|
|
4726
4729
|
borderColor: isSelected
|
|
4727
4730
|
? {
|
|
4728
4731
|
base: 'colorPalette.600',
|
|
@@ -4747,22 +4750,22 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4747
4750
|
}) })) }))] }));
|
|
4748
4751
|
};
|
|
4749
4752
|
|
|
4750
|
-
function
|
|
4751
|
-
const [
|
|
4753
|
+
function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, onUploadFile, enableUpload = false, labels, translate, colLabel, }) {
|
|
4754
|
+
const [selectedFile, setSelectedFile] = React.useState(undefined);
|
|
4752
4755
|
const [activeTab, setActiveTab] = React.useState('browse');
|
|
4753
4756
|
const [uploadingFiles, setUploadingFiles] = React.useState(new Set());
|
|
4754
4757
|
const [uploadErrors, setUploadErrors] = React.useState(new Map());
|
|
4755
4758
|
const handleSelect = () => {
|
|
4756
|
-
if (
|
|
4757
|
-
onSelect(
|
|
4759
|
+
if (selectedFile) {
|
|
4760
|
+
onSelect(selectedFile);
|
|
4758
4761
|
onClose();
|
|
4759
|
-
|
|
4762
|
+
setSelectedFile(undefined);
|
|
4760
4763
|
setActiveTab('browse');
|
|
4761
4764
|
}
|
|
4762
4765
|
};
|
|
4763
4766
|
const handleClose = () => {
|
|
4764
4767
|
onClose();
|
|
4765
|
-
|
|
4768
|
+
setSelectedFile(undefined);
|
|
4766
4769
|
setActiveTab('browse');
|
|
4767
4770
|
setUploadingFiles(new Set());
|
|
4768
4771
|
setUploadErrors(new Map());
|
|
@@ -4780,16 +4783,23 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4780
4783
|
});
|
|
4781
4784
|
try {
|
|
4782
4785
|
const fileId = await onUploadFile(file);
|
|
4783
|
-
|
|
4786
|
+
// Create a minimal FilePickerMediaFile object from the uploaded file
|
|
4787
|
+
const uploadedFile = {
|
|
4788
|
+
id: fileId,
|
|
4789
|
+
name: file.name,
|
|
4790
|
+
size: file.size,
|
|
4791
|
+
type: file.type,
|
|
4792
|
+
};
|
|
4793
|
+
setSelectedFile(uploadedFile);
|
|
4784
4794
|
setUploadingFiles((prev) => {
|
|
4785
4795
|
const newSet = new Set(prev);
|
|
4786
4796
|
newSet.delete(fileKey);
|
|
4787
4797
|
return newSet;
|
|
4788
4798
|
});
|
|
4789
4799
|
// Auto-select and close in single-select mode
|
|
4790
|
-
onSelect(
|
|
4800
|
+
onSelect(uploadedFile);
|
|
4791
4801
|
onClose();
|
|
4792
|
-
|
|
4802
|
+
setSelectedFile(undefined);
|
|
4793
4803
|
setActiveTab('browse');
|
|
4794
4804
|
}
|
|
4795
4805
|
catch (error) {
|
|
@@ -4813,7 +4823,7 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4813
4823
|
translate(removeIndex(`${colLabel}.browse_tab`)) ??
|
|
4814
4824
|
'Browse Library' }), jsxRuntime.jsx(react.Tabs.Trigger, { value: "upload", children: labels?.uploadTab ??
|
|
4815
4825
|
translate(removeIndex(`${colLabel}.upload_tab`)) ??
|
|
4816
|
-
'Upload Files' })] }), jsxRuntime.jsx(react.Tabs.Content, { value: "browse", children: onFetchFiles && (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse',
|
|
4826
|
+
'Upload Files' })] }), jsxRuntime.jsx(react.Tabs.Content, { value: "browse", children: onFetchFiles && (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse', selectedFile: selectedFile, onFileSelect: setSelectedFile })) }), jsxRuntime.jsx(react.Tabs.Content, { value: "upload", children: jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 4, children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => handleFileUpload(files), placeholder: labels?.fileDropzone ??
|
|
4817
4827
|
translate(removeIndex(`${colLabel}.fileDropzone`)) ??
|
|
4818
4828
|
'Drop files here or click to upload' }), uploadingFiles.size > 0 && (jsxRuntime.jsx(react.Box, { children: Array.from(uploadingFiles).map((fileKey) => (jsxRuntime.jsx(react.Box, { py: 2, children: jsxRuntime.jsxs(react.HStack, { gap: 2, children: [jsxRuntime.jsx(react.Spinner, { size: "sm", colorPalette: "blue" }), jsxRuntime.jsxs(react.Text, { fontSize: "sm", color: "fg.muted", children: [labels?.uploading ??
|
|
4819
4829
|
translate(removeIndex(`${colLabel}.uploading`)) ??
|
|
@@ -4828,9 +4838,9 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4828
4838
|
_dark: 'colorPalette.300',
|
|
4829
4839
|
}, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ??
|
|
4830
4840
|
translate(removeIndex(`${colLabel}.upload_failed`)) ??
|
|
4831
|
-
'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open,
|
|
4841
|
+
'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open, selectedFile: selectedFile, onFileSelect: setSelectedFile })) : null }), 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 ??
|
|
4832
4842
|
translate(removeIndex(`${colLabel}.cancel`)) ??
|
|
4833
|
-
'Cancel' }), jsxRuntime.jsx(react.Button, { colorPalette: "blue", onClick: handleSelect, disabled: !
|
|
4843
|
+
'Cancel' }), jsxRuntime.jsx(react.Button, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFile, children: labels?.select ??
|
|
4834
4844
|
translate(removeIndex(`${colLabel}.select`)) ??
|
|
4835
4845
|
'Select' })] }) })] }) }));
|
|
4836
4846
|
}
|
|
@@ -4929,17 +4939,70 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
4929
4939
|
const colLabel = formI18n.colLabel;
|
|
4930
4940
|
const [dialogOpen, setDialogOpen] = React.useState(false);
|
|
4931
4941
|
const [failedImageIds, setFailedImageIds] = React.useState(new Set());
|
|
4942
|
+
// Map of file ID to FilePickerMediaFile for display
|
|
4943
|
+
const [fileMap, setFileMap] = React.useState(new Map());
|
|
4932
4944
|
const { onFetchFiles, filterImageOnly = false, enableUpload = false, onUploadFile, } = filePicker || {};
|
|
4945
|
+
// Fetch file details for existing file IDs
|
|
4946
|
+
React.useEffect(() => {
|
|
4947
|
+
if (!onFetchFiles || currentFileIds.length === 0)
|
|
4948
|
+
return;
|
|
4949
|
+
const fetchFileDetails = async () => {
|
|
4950
|
+
setFileMap((prevMap) => {
|
|
4951
|
+
const filesToFetch = currentFileIds.filter((id) => !prevMap.has(id));
|
|
4952
|
+
if (filesToFetch.length === 0)
|
|
4953
|
+
return prevMap;
|
|
4954
|
+
// Fetch all files and filter for the ones we need
|
|
4955
|
+
onFetchFiles('')
|
|
4956
|
+
.then((allFiles) => {
|
|
4957
|
+
setFileMap((currentMap) => {
|
|
4958
|
+
const newFileMap = new Map(currentMap);
|
|
4959
|
+
filesToFetch.forEach((id) => {
|
|
4960
|
+
const file = allFiles.find((f) => f.id === id);
|
|
4961
|
+
if (file) {
|
|
4962
|
+
newFileMap.set(id, file);
|
|
4963
|
+
}
|
|
4964
|
+
});
|
|
4965
|
+
return newFileMap;
|
|
4966
|
+
});
|
|
4967
|
+
})
|
|
4968
|
+
.catch((error) => {
|
|
4969
|
+
console.error('Failed to fetch file details:', error);
|
|
4970
|
+
});
|
|
4971
|
+
return prevMap;
|
|
4972
|
+
});
|
|
4973
|
+
};
|
|
4974
|
+
fetchFileDetails();
|
|
4975
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4976
|
+
}, [currentFileIds.join(','), onFetchFiles]);
|
|
4977
|
+
// Clean up fileMap when files are removed
|
|
4978
|
+
React.useEffect(() => {
|
|
4979
|
+
setFileMap((prevMap) => {
|
|
4980
|
+
const currentIds = new Set(currentFileIds);
|
|
4981
|
+
const newFileMap = new Map();
|
|
4982
|
+
prevMap.forEach((file, id) => {
|
|
4983
|
+
if (currentIds.has(id)) {
|
|
4984
|
+
newFileMap.set(id, file);
|
|
4985
|
+
}
|
|
4986
|
+
});
|
|
4987
|
+
return newFileMap.size !== prevMap.size ? newFileMap : prevMap;
|
|
4988
|
+
});
|
|
4989
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4990
|
+
}, [currentFileIds.join(',')]);
|
|
4933
4991
|
if (!onFetchFiles) {
|
|
4934
4992
|
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4935
4993
|
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(react.Text, { color: "fg.muted", children: "Media library browser requires onFetchFiles" }) }));
|
|
4936
4994
|
}
|
|
4937
|
-
const
|
|
4995
|
+
const handleImageError = (fileIdentifier) => {
|
|
4996
|
+
setFailedImageIds((prev) => new Set(prev).add(fileIdentifier));
|
|
4997
|
+
};
|
|
4998
|
+
const handleMediaLibrarySelect = (file) => {
|
|
4999
|
+
// Store the file in the map for display
|
|
5000
|
+
setFileMap((prev) => new Map(prev).set(file.id, file));
|
|
4938
5001
|
if (isSingleSelect) {
|
|
4939
|
-
setValue(colLabel,
|
|
5002
|
+
setValue(colLabel, file.id);
|
|
4940
5003
|
}
|
|
4941
5004
|
else {
|
|
4942
|
-
const newFileIds = [...currentFileIds,
|
|
5005
|
+
const newFileIds = [...currentFileIds, file.id];
|
|
4943
5006
|
setValue(colLabel, newFileIds);
|
|
4944
5007
|
}
|
|
4945
5008
|
};
|
|
@@ -4952,21 +5015,24 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
4952
5015
|
setValue(colLabel, newFileIds);
|
|
4953
5016
|
}
|
|
4954
5017
|
};
|
|
4955
|
-
const isImageId = (fileId) => {
|
|
4956
|
-
return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(fileId);
|
|
4957
|
-
};
|
|
4958
5018
|
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4959
5019
|
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: jsxRuntime.jsx(react.Button, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ??
|
|
4960
5020
|
formI18n.t('browse_library') ??
|
|
4961
|
-
'Browse from Library' }) }), jsxRuntime.jsx(
|
|
5021
|
+
'Browse from Library' }) }), jsxRuntime.jsx(MediaBrowserDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
|
|
4962
5022
|
formI18n.t('dialog_title') ??
|
|
4963
5023
|
'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, translate: formI18n.t, colLabel: colLabel }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
|
|
4964
|
-
const
|
|
5024
|
+
const file = fileMap.get(fileId);
|
|
5025
|
+
const isImage = file
|
|
5026
|
+
? /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name)
|
|
5027
|
+
: /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(fileId);
|
|
4965
5028
|
const imageFailed = failedImageIds.has(fileId);
|
|
5029
|
+
const displayName = file?.name ?? fileId;
|
|
4966
5030
|
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: {
|
|
4967
5031
|
borderColor: 'colorPalette.300',
|
|
4968
5032
|
bg: 'bg.muted',
|
|
4969
|
-
}, 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 && !imageFailed ? (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.
|
|
5033
|
+
}, 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", overflow: "hidden", children: isImage && file?.url && !imageFailed ? (jsxRuntime.jsx(react.Image, { src: file.url, alt: displayName, boxSize: "60px", objectFit: "cover", onError: () => handleImageError(fileId) })) : isImage && !imageFailed ? (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: displayName }), file?.size && (jsxRuntime.jsx(react.Text, { fontSize: "xs", color: "fg.muted", children: typeof file.size === 'number'
|
|
5034
|
+
? `${(file.size / 1024).toFixed(1)} KB`
|
|
5035
|
+
: file.size }))] }), jsxRuntime.jsx(react.Icon, { as: ti.TiDeleteOutline, boxSize: 5, color: "fg.muted" })] }) }, `${fileId}-${index}`));
|
|
4970
5036
|
}) })] }));
|
|
4971
5037
|
};
|
|
4972
5038
|
|
|
@@ -6135,6 +6201,9 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
|
6135
6201
|
if (variant === 'text-area') {
|
|
6136
6202
|
return jsxRuntime.jsx(TextAreaInput, { schema: colSchema, prefix, column });
|
|
6137
6203
|
}
|
|
6204
|
+
if (variant === 'media-library-browser') {
|
|
6205
|
+
return (jsxRuntime.jsx(FormMediaLibraryBrowser, { schema: colSchema, prefix, column }));
|
|
6206
|
+
}
|
|
6138
6207
|
return jsxRuntime.jsx(StringInputField, { schema: colSchema, prefix, column });
|
|
6139
6208
|
}
|
|
6140
6209
|
if (type === 'number' || type === 'integer') {
|
package/dist/index.mjs
CHANGED
|
@@ -4624,13 +4624,13 @@ function formatBytes(bytes) {
|
|
|
4624
4624
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
4625
4625
|
}
|
|
4626
4626
|
|
|
4627
|
-
const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, enabled = true, multiple = false, onFileSelect,
|
|
4627
|
+
const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, enabled = true, multiple = false, onFileSelect, selectedFile: controlledSelectedFile, onSelectedFileChange, }) => {
|
|
4628
4628
|
const [searchTerm, setSearchTerm] = useState('');
|
|
4629
|
-
const [
|
|
4629
|
+
const [internalSelectedFile, setInternalSelectedFile] = useState(multiple ? [] : undefined);
|
|
4630
4630
|
const [failedImageIds, setFailedImageIds] = useState(new Set());
|
|
4631
|
-
// Use controlled or internal state for
|
|
4632
|
-
const
|
|
4633
|
-
const
|
|
4631
|
+
// Use controlled or internal state for selectedFile
|
|
4632
|
+
const selectedFile = controlledSelectedFile ?? internalSelectedFile;
|
|
4633
|
+
const setSelectedFile = onSelectedFileChange ?? setInternalSelectedFile;
|
|
4634
4634
|
const { data: filesData, isLoading, isError, } = useQuery({
|
|
4635
4635
|
queryKey: ['file-picker-library', searchTerm],
|
|
4636
4636
|
queryFn: async () => {
|
|
@@ -4645,23 +4645,25 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4645
4645
|
const filteredFiles = filterImageOnly
|
|
4646
4646
|
? files.filter((file) => /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name))
|
|
4647
4647
|
: files;
|
|
4648
|
-
const handleFileClick = (
|
|
4648
|
+
const handleFileClick = (file) => {
|
|
4649
4649
|
if (multiple) {
|
|
4650
|
-
const currentSelection = Array.isArray(
|
|
4651
|
-
?
|
|
4650
|
+
const currentSelection = Array.isArray(selectedFile)
|
|
4651
|
+
? selectedFile
|
|
4652
4652
|
: [];
|
|
4653
|
-
const
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4653
|
+
const isAlreadySelected = currentSelection.some((f) => f.id === file.id);
|
|
4654
|
+
const newSelection = isAlreadySelected
|
|
4655
|
+
? currentSelection.filter((f) => f.id !== file.id)
|
|
4656
|
+
: [...currentSelection, file];
|
|
4657
|
+
setSelectedFile(newSelection);
|
|
4657
4658
|
if (onFileSelect) {
|
|
4658
4659
|
onFileSelect(newSelection);
|
|
4659
4660
|
}
|
|
4660
4661
|
}
|
|
4661
4662
|
else {
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4663
|
+
const newFile = selectedFile === file ? undefined : file;
|
|
4664
|
+
setSelectedFile(newFile);
|
|
4665
|
+
if (onFileSelect && newFile) {
|
|
4666
|
+
onFileSelect(newFile);
|
|
4665
4667
|
}
|
|
4666
4668
|
}
|
|
4667
4669
|
};
|
|
@@ -4688,9 +4690,10 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4688
4690
|
}, children: labels?.loadingFailed ?? '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 ?? 'No files found' }) })) : (jsx(VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
|
|
4689
4691
|
const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
|
|
4690
4692
|
const isSelected = multiple
|
|
4691
|
-
? Array.isArray(
|
|
4692
|
-
|
|
4693
|
-
:
|
|
4693
|
+
? Array.isArray(selectedFile) &&
|
|
4694
|
+
selectedFile.some((f) => f.id === file.id)
|
|
4695
|
+
: selectedFile?.id ===
|
|
4696
|
+
file.id;
|
|
4694
4697
|
const imageFailed = failedImageIds.has(file.id);
|
|
4695
4698
|
return (jsx(Box, { p: 3, border: "2px solid", borderColor: isSelected
|
|
4696
4699
|
? {
|
|
@@ -4702,7 +4705,7 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4702
4705
|
base: 'colorPalette.50',
|
|
4703
4706
|
_dark: 'colorPalette.900/20',
|
|
4704
4707
|
}
|
|
4705
|
-
: 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => handleFileClick(file
|
|
4708
|
+
: 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => handleFileClick(file), _hover: {
|
|
4706
4709
|
borderColor: isSelected
|
|
4707
4710
|
? {
|
|
4708
4711
|
base: 'colorPalette.600',
|
|
@@ -4727,22 +4730,22 @@ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, en
|
|
|
4727
4730
|
}) })) }))] }));
|
|
4728
4731
|
};
|
|
4729
4732
|
|
|
4730
|
-
function
|
|
4731
|
-
const [
|
|
4733
|
+
function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, onUploadFile, enableUpload = false, labels, translate, colLabel, }) {
|
|
4734
|
+
const [selectedFile, setSelectedFile] = useState(undefined);
|
|
4732
4735
|
const [activeTab, setActiveTab] = useState('browse');
|
|
4733
4736
|
const [uploadingFiles, setUploadingFiles] = useState(new Set());
|
|
4734
4737
|
const [uploadErrors, setUploadErrors] = useState(new Map());
|
|
4735
4738
|
const handleSelect = () => {
|
|
4736
|
-
if (
|
|
4737
|
-
onSelect(
|
|
4739
|
+
if (selectedFile) {
|
|
4740
|
+
onSelect(selectedFile);
|
|
4738
4741
|
onClose();
|
|
4739
|
-
|
|
4742
|
+
setSelectedFile(undefined);
|
|
4740
4743
|
setActiveTab('browse');
|
|
4741
4744
|
}
|
|
4742
4745
|
};
|
|
4743
4746
|
const handleClose = () => {
|
|
4744
4747
|
onClose();
|
|
4745
|
-
|
|
4748
|
+
setSelectedFile(undefined);
|
|
4746
4749
|
setActiveTab('browse');
|
|
4747
4750
|
setUploadingFiles(new Set());
|
|
4748
4751
|
setUploadErrors(new Map());
|
|
@@ -4760,16 +4763,23 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4760
4763
|
});
|
|
4761
4764
|
try {
|
|
4762
4765
|
const fileId = await onUploadFile(file);
|
|
4763
|
-
|
|
4766
|
+
// Create a minimal FilePickerMediaFile object from the uploaded file
|
|
4767
|
+
const uploadedFile = {
|
|
4768
|
+
id: fileId,
|
|
4769
|
+
name: file.name,
|
|
4770
|
+
size: file.size,
|
|
4771
|
+
type: file.type,
|
|
4772
|
+
};
|
|
4773
|
+
setSelectedFile(uploadedFile);
|
|
4764
4774
|
setUploadingFiles((prev) => {
|
|
4765
4775
|
const newSet = new Set(prev);
|
|
4766
4776
|
newSet.delete(fileKey);
|
|
4767
4777
|
return newSet;
|
|
4768
4778
|
});
|
|
4769
4779
|
// Auto-select and close in single-select mode
|
|
4770
|
-
onSelect(
|
|
4780
|
+
onSelect(uploadedFile);
|
|
4771
4781
|
onClose();
|
|
4772
|
-
|
|
4782
|
+
setSelectedFile(undefined);
|
|
4773
4783
|
setActiveTab('browse');
|
|
4774
4784
|
}
|
|
4775
4785
|
catch (error) {
|
|
@@ -4793,7 +4803,7 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4793
4803
|
translate(removeIndex(`${colLabel}.browse_tab`)) ??
|
|
4794
4804
|
'Browse Library' }), jsx(Tabs.Trigger, { value: "upload", children: labels?.uploadTab ??
|
|
4795
4805
|
translate(removeIndex(`${colLabel}.upload_tab`)) ??
|
|
4796
|
-
'Upload Files' })] }), jsx(Tabs.Content, { value: "browse", children: onFetchFiles && (jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse',
|
|
4806
|
+
'Upload Files' })] }), jsx(Tabs.Content, { value: "browse", children: onFetchFiles && (jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open && activeTab === 'browse', selectedFile: selectedFile, onFileSelect: setSelectedFile })) }), jsx(Tabs.Content, { value: "upload", children: jsxs(VStack, { align: "stretch", gap: 4, children: [jsx(FileDropzone, { onDrop: ({ files }) => handleFileUpload(files), placeholder: labels?.fileDropzone ??
|
|
4797
4807
|
translate(removeIndex(`${colLabel}.fileDropzone`)) ??
|
|
4798
4808
|
'Drop files here or click to upload' }), uploadingFiles.size > 0 && (jsx(Box, { children: Array.from(uploadingFiles).map((fileKey) => (jsx(Box, { py: 2, children: jsxs(HStack, { gap: 2, children: [jsx(Spinner, { size: "sm", colorPalette: "blue" }), jsxs(Text, { fontSize: "sm", color: "fg.muted", children: [labels?.uploading ??
|
|
4799
4809
|
translate(removeIndex(`${colLabel}.uploading`)) ??
|
|
@@ -4808,9 +4818,9 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4808
4818
|
_dark: 'colorPalette.300',
|
|
4809
4819
|
}, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ??
|
|
4810
4820
|
translate(removeIndex(`${colLabel}.upload_failed`)) ??
|
|
4811
|
-
'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open,
|
|
4821
|
+
'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open, selectedFile: selectedFile, onFileSelect: setSelectedFile })) : null }), 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 ??
|
|
4812
4822
|
translate(removeIndex(`${colLabel}.cancel`)) ??
|
|
4813
|
-
'Cancel' }), jsx(Button$1, { colorPalette: "blue", onClick: handleSelect, disabled: !
|
|
4823
|
+
'Cancel' }), jsx(Button$1, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFile, children: labels?.select ??
|
|
4814
4824
|
translate(removeIndex(`${colLabel}.select`)) ??
|
|
4815
4825
|
'Select' })] }) })] }) }));
|
|
4816
4826
|
}
|
|
@@ -4909,17 +4919,70 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
4909
4919
|
const colLabel = formI18n.colLabel;
|
|
4910
4920
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
4911
4921
|
const [failedImageIds, setFailedImageIds] = useState(new Set());
|
|
4922
|
+
// Map of file ID to FilePickerMediaFile for display
|
|
4923
|
+
const [fileMap, setFileMap] = useState(new Map());
|
|
4912
4924
|
const { onFetchFiles, filterImageOnly = false, enableUpload = false, onUploadFile, } = filePicker || {};
|
|
4925
|
+
// Fetch file details for existing file IDs
|
|
4926
|
+
useEffect(() => {
|
|
4927
|
+
if (!onFetchFiles || currentFileIds.length === 0)
|
|
4928
|
+
return;
|
|
4929
|
+
const fetchFileDetails = async () => {
|
|
4930
|
+
setFileMap((prevMap) => {
|
|
4931
|
+
const filesToFetch = currentFileIds.filter((id) => !prevMap.has(id));
|
|
4932
|
+
if (filesToFetch.length === 0)
|
|
4933
|
+
return prevMap;
|
|
4934
|
+
// Fetch all files and filter for the ones we need
|
|
4935
|
+
onFetchFiles('')
|
|
4936
|
+
.then((allFiles) => {
|
|
4937
|
+
setFileMap((currentMap) => {
|
|
4938
|
+
const newFileMap = new Map(currentMap);
|
|
4939
|
+
filesToFetch.forEach((id) => {
|
|
4940
|
+
const file = allFiles.find((f) => f.id === id);
|
|
4941
|
+
if (file) {
|
|
4942
|
+
newFileMap.set(id, file);
|
|
4943
|
+
}
|
|
4944
|
+
});
|
|
4945
|
+
return newFileMap;
|
|
4946
|
+
});
|
|
4947
|
+
})
|
|
4948
|
+
.catch((error) => {
|
|
4949
|
+
console.error('Failed to fetch file details:', error);
|
|
4950
|
+
});
|
|
4951
|
+
return prevMap;
|
|
4952
|
+
});
|
|
4953
|
+
};
|
|
4954
|
+
fetchFileDetails();
|
|
4955
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4956
|
+
}, [currentFileIds.join(','), onFetchFiles]);
|
|
4957
|
+
// Clean up fileMap when files are removed
|
|
4958
|
+
useEffect(() => {
|
|
4959
|
+
setFileMap((prevMap) => {
|
|
4960
|
+
const currentIds = new Set(currentFileIds);
|
|
4961
|
+
const newFileMap = new Map();
|
|
4962
|
+
prevMap.forEach((file, id) => {
|
|
4963
|
+
if (currentIds.has(id)) {
|
|
4964
|
+
newFileMap.set(id, file);
|
|
4965
|
+
}
|
|
4966
|
+
});
|
|
4967
|
+
return newFileMap.size !== prevMap.size ? newFileMap : prevMap;
|
|
4968
|
+
});
|
|
4969
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4970
|
+
}, [currentFileIds.join(',')]);
|
|
4913
4971
|
if (!onFetchFiles) {
|
|
4914
4972
|
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4915
4973
|
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsx(Text, { color: "fg.muted", children: "Media library browser requires onFetchFiles" }) }));
|
|
4916
4974
|
}
|
|
4917
|
-
const
|
|
4975
|
+
const handleImageError = (fileIdentifier) => {
|
|
4976
|
+
setFailedImageIds((prev) => new Set(prev).add(fileIdentifier));
|
|
4977
|
+
};
|
|
4978
|
+
const handleMediaLibrarySelect = (file) => {
|
|
4979
|
+
// Store the file in the map for display
|
|
4980
|
+
setFileMap((prev) => new Map(prev).set(file.id, file));
|
|
4918
4981
|
if (isSingleSelect) {
|
|
4919
|
-
setValue(colLabel,
|
|
4982
|
+
setValue(colLabel, file.id);
|
|
4920
4983
|
}
|
|
4921
4984
|
else {
|
|
4922
|
-
const newFileIds = [...currentFileIds,
|
|
4985
|
+
const newFileIds = [...currentFileIds, file.id];
|
|
4923
4986
|
setValue(colLabel, newFileIds);
|
|
4924
4987
|
}
|
|
4925
4988
|
};
|
|
@@ -4932,21 +4995,24 @@ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
|
|
|
4932
4995
|
setValue(colLabel, newFileIds);
|
|
4933
4996
|
}
|
|
4934
4997
|
};
|
|
4935
|
-
const isImageId = (fileId) => {
|
|
4936
|
-
return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(fileId);
|
|
4937
|
-
};
|
|
4938
4998
|
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4939
4999
|
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsx(VStack, { align: "stretch", gap: 2, children: jsx(Button$1, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ??
|
|
4940
5000
|
formI18n.t('browse_library') ??
|
|
4941
|
-
'Browse from Library' }) }), jsx(
|
|
5001
|
+
'Browse from Library' }) }), jsx(MediaBrowserDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
|
|
4942
5002
|
formI18n.t('dialog_title') ??
|
|
4943
5003
|
'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, onUploadFile: onUploadFile, enableUpload: enableUpload, labels: filePickerLabels, translate: formI18n.t, colLabel: colLabel }), jsx(Flex, { flexFlow: 'column', gap: 1, children: currentFileIds.map((fileId, index) => {
|
|
4944
|
-
const
|
|
5004
|
+
const file = fileMap.get(fileId);
|
|
5005
|
+
const isImage = file
|
|
5006
|
+
? /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name)
|
|
5007
|
+
: /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(fileId);
|
|
4945
5008
|
const imageFailed = failedImageIds.has(fileId);
|
|
5009
|
+
const displayName = file?.name ?? fileId;
|
|
4946
5010
|
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: {
|
|
4947
5011
|
borderColor: 'colorPalette.300',
|
|
4948
5012
|
bg: 'bg.muted',
|
|
4949
|
-
}, 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 && !imageFailed ? (jsx(Icon, { as: LuImage, boxSize: 6, color: "fg.muted" })) : (jsx(Icon, { as: LuFile, boxSize: 6, color: "fg.muted" })) }),
|
|
5013
|
+
}, 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", overflow: "hidden", children: isImage && file?.url && !imageFailed ? (jsx(Image, { src: file.url, alt: displayName, boxSize: "60px", objectFit: "cover", onError: () => handleImageError(fileId) })) : isImage && !imageFailed ? (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: displayName }), file?.size && (jsx(Text, { fontSize: "xs", color: "fg.muted", children: typeof file.size === 'number'
|
|
5014
|
+
? `${(file.size / 1024).toFixed(1)} KB`
|
|
5015
|
+
: file.size }))] }), jsx(Icon, { as: TiDeleteOutline, boxSize: 5, color: "fg.muted" })] }) }, `${fileId}-${index}`));
|
|
4950
5016
|
}) })] }));
|
|
4951
5017
|
};
|
|
4952
5018
|
|
|
@@ -6115,6 +6181,9 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
|
|
|
6115
6181
|
if (variant === 'text-area') {
|
|
6116
6182
|
return jsx(TextAreaInput, { schema: colSchema, prefix, column });
|
|
6117
6183
|
}
|
|
6184
|
+
if (variant === 'media-library-browser') {
|
|
6185
|
+
return (jsx(FormMediaLibraryBrowser, { schema: colSchema, prefix, column }));
|
|
6186
|
+
}
|
|
6118
6187
|
return jsx(StringInputField, { schema: colSchema, prefix, column });
|
|
6119
6188
|
}
|
|
6120
6189
|
if (type === 'number' || type === 'integer') {
|
|
@@ -7,16 +7,16 @@ type MediaLibraryBrowserPropsBase = {
|
|
|
7
7
|
};
|
|
8
8
|
type MediaLibraryBrowserPropsSingle = MediaLibraryBrowserPropsBase & {
|
|
9
9
|
multiple?: false;
|
|
10
|
-
onFileSelect?: (
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
onFileSelect?: (file: FilePickerMediaFile) => void;
|
|
11
|
+
selectedFile?: FilePickerMediaFile;
|
|
12
|
+
onSelectedFileChange?: (file: FilePickerMediaFile | undefined) => void;
|
|
13
13
|
};
|
|
14
14
|
type MediaLibraryBrowserPropsMultiple = MediaLibraryBrowserPropsBase & {
|
|
15
15
|
multiple: true;
|
|
16
|
-
onFileSelect?: (
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
onFileSelect?: (files: FilePickerMediaFile[]) => void;
|
|
17
|
+
selectedFile?: FilePickerMediaFile[];
|
|
18
|
+
onSelectedFileChange?: (files: FilePickerMediaFile[]) => void;
|
|
19
19
|
};
|
|
20
20
|
export type MediaLibraryBrowserProps = MediaLibraryBrowserPropsSingle | MediaLibraryBrowserPropsMultiple;
|
|
21
|
-
export declare const MediaLibraryBrowser: ({ onFetchFiles, filterImageOnly, labels, enabled, multiple, onFileSelect,
|
|
21
|
+
export declare const MediaLibraryBrowser: ({ onFetchFiles, filterImageOnly, labels, enabled, multiple, onFileSelect, selectedFile: controlledSelectedFile, onSelectedFileChange, }: MediaLibraryBrowserProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
22
22
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FilePickerMediaFile, FilePickerLabels } from '../types/CustomJSONSchema7';
|
|
2
2
|
import { InputDefaultProps } from './types';
|
|
3
|
-
interface
|
|
3
|
+
interface MediaBrowserDialogProps {
|
|
4
4
|
open: boolean;
|
|
5
5
|
onClose: () => void;
|
|
6
|
-
onSelect: (
|
|
6
|
+
onSelect: (file: FilePickerMediaFile) => void;
|
|
7
7
|
title: string;
|
|
8
8
|
filterImageOnly?: boolean;
|
|
9
9
|
onFetchFiles?: (search: string) => Promise<FilePickerMediaFile[]>;
|
|
@@ -13,6 +13,6 @@ interface FilePickerDialogProps {
|
|
|
13
13
|
translate: (key: string) => string;
|
|
14
14
|
colLabel: string;
|
|
15
15
|
}
|
|
16
|
-
export declare function
|
|
16
|
+
export declare function MediaBrowserDialog({ open, onClose, onSelect, title, filterImageOnly, onFetchFiles, onUploadFile, enableUpload, labels, translate, colLabel, }: MediaBrowserDialogProps): import("react/jsx-runtime").JSX.Element | null;
|
|
17
17
|
export declare const FilePicker: ({ column, schema, prefix }: InputDefaultProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
18
|
export {};
|