@bsol-oss/react-datatable5 12.0.0-beta.81 → 12.0.0-beta.82

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
@@ -771,6 +771,10 @@ interface FilePickerLabels {
771
771
  noFilesFound?: string;
772
772
  cancel?: string;
773
773
  select?: string;
774
+ uploadTab?: string;
775
+ browseTab?: string;
776
+ uploading?: string;
777
+ uploadFailed?: string;
774
778
  }
775
779
  interface CustomJSONSchema7 extends JSONSchema7 {
776
780
  gridColumn?: string;
@@ -817,6 +821,8 @@ interface FilePickerProps {
817
821
  onFetchFiles?: (search: string) => Promise<FilePickerMediaFile[]>;
818
822
  enableMediaLibrary?: boolean;
819
823
  filterImageOnly?: boolean;
824
+ enableUpload?: boolean;
825
+ onUploadFile?: (file: File) => Promise<string>;
820
826
  }
821
827
 
822
828
  interface FormRootProps<TData extends FieldValues> {
@@ -875,6 +881,27 @@ declare const FormTitle: () => react_jsx_runtime.JSX.Element;
875
881
 
876
882
  declare const FormBody: <TData extends object>() => string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
877
883
 
884
+ type MediaLibraryBrowserPropsBase = {
885
+ onFetchFiles?: (search: string) => Promise<FilePickerMediaFile[]>;
886
+ filterImageOnly?: boolean;
887
+ labels?: FilePickerLabels;
888
+ enabled?: boolean;
889
+ };
890
+ type MediaLibraryBrowserPropsSingle = MediaLibraryBrowserPropsBase & {
891
+ multiple?: false;
892
+ onFileSelect?: (fileId: string) => void;
893
+ selectedFileId?: string;
894
+ onSelectedFileIdChange?: (fileId: string) => void;
895
+ };
896
+ type MediaLibraryBrowserPropsMultiple = MediaLibraryBrowserPropsBase & {
897
+ multiple: true;
898
+ onFileSelect?: (fileId: string[]) => void;
899
+ selectedFileId?: string[];
900
+ onSelectedFileIdChange?: (fileId: string[]) => void;
901
+ };
902
+ type MediaLibraryBrowserProps = MediaLibraryBrowserPropsSingle | MediaLibraryBrowserPropsMultiple;
903
+ declare const MediaLibraryBrowser: ({ onFetchFiles, filterImageOnly, labels, enabled, multiple, onFileSelect, selectedFileId: controlledSelectedFileId, onSelectedFileIdChange, }: MediaLibraryBrowserProps) => react_jsx_runtime.JSX.Element | null;
904
+
878
905
  interface UseFormProps {
879
906
  preLoadedValues?: FieldValues | undefined;
880
907
  keyPrefix?: string;
@@ -1136,4 +1163,4 @@ declare module '@tanstack/react-table' {
1136
1163
  }
1137
1164
  }
1138
1165
 
1139
- export { type CalendarProps, CardHeader, type CardHeaderProps, type CustomJSONSchema7, type CustomJSONSchema7Definition, DataDisplay, type DataDisplayProps, type DataResponse, DataTable, type DataTableDefaultState, type DataTableProps, DataTableServer, type DataTableServerProps, type DatePickerLabels, type DatePickerProps, type DateTimePickerLabels, DefaultCardTitle, DefaultForm, type DefaultFormProps, DefaultTable, type DefaultTableProps, DefaultTableServer, type DefaultTableServerProps, DensityToggleButton, type DensityToggleButtonProps, type EditFilterButtonProps, EditSortingButton, type EditSortingButtonProps, type EditViewButtonProps, EmptyState, type EmptyStateProps, type EnumPickerLabels, ErrorAlert, type ErrorAlertProps, type ErrorMessageConfig, type ErrorMessageResult, type FieldErrorConfig, type FilePickerLabels, type FilePickerMediaFile, type FilePickerProps, FilterDialog, FormBody, FormRoot, type FormRootProps, FormTitle, type GetColumnsConfigs, type GetDateColorProps, type GetMultiDatesProps, type GetRangeDatesProps, type GetStyleProps, type GetVariantProps, GlobalFilter, type IdPickerLabels, PageSizeControl, type PageSizeControlProps, Pagination, type QueryParams, type RangeCalendarProps, type RangeDatePickerProps, RecordDisplay, type RecordDisplayProps, ReloadButton, type ReloadButtonProps, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, type Result, RowCountText, Table, TableBody, type TableBodyProps, TableCardContainer, type TableCardContainerProps, TableCards, type TableCardsProps, TableComponent, TableControls, type TableControlsProps, TableDataDisplay, type TableDataDisplayProps, TableFilter, TableFilterTags, TableFooter, type TableFooterProps, TableHeader, type TableHeaderProps, type TableHeaderTexts, TableLoadingComponent, type TableLoadingComponentProps, type TableProps, type TableRendererProps, type TableRowSelectorProps, TableSelector, TableSorter, TableViewer, type TagPickerProps, TextCell, type TextCellProps, type UseDataTableProps, type UseDataTableReturn, type UseDataTableServerProps, type UseDataTableServerReturn, type UseFormProps, type ValidationErrorType, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
1166
+ export { type CalendarProps, CardHeader, type CardHeaderProps, type CustomJSONSchema7, type CustomJSONSchema7Definition, DataDisplay, type DataDisplayProps, type DataResponse, DataTable, type DataTableDefaultState, type DataTableProps, DataTableServer, type DataTableServerProps, type DatePickerLabels, type DatePickerProps, type DateTimePickerLabels, DefaultCardTitle, DefaultForm, type DefaultFormProps, DefaultTable, type DefaultTableProps, DefaultTableServer, type DefaultTableServerProps, DensityToggleButton, type DensityToggleButtonProps, type EditFilterButtonProps, EditSortingButton, type EditSortingButtonProps, type EditViewButtonProps, EmptyState, type EmptyStateProps, type EnumPickerLabels, ErrorAlert, type ErrorAlertProps, type ErrorMessageConfig, type ErrorMessageResult, type FieldErrorConfig, type FilePickerLabels, type FilePickerMediaFile, type FilePickerProps, FilterDialog, FormBody, FormRoot, type FormRootProps, FormTitle, type GetColumnsConfigs, type GetDateColorProps, type GetMultiDatesProps, type GetRangeDatesProps, type GetStyleProps, type GetVariantProps, GlobalFilter, type IdPickerLabels, MediaLibraryBrowser, type MediaLibraryBrowserProps, PageSizeControl, type PageSizeControlProps, Pagination, type QueryParams, type RangeCalendarProps, type RangeDatePickerProps, RecordDisplay, type RecordDisplayProps, ReloadButton, type ReloadButtonProps, ResetFilteringButton, ResetSelectionButton, ResetSortingButton, type Result, RowCountText, Table, TableBody, type TableBodyProps, TableCardContainer, type TableCardContainerProps, TableCards, type TableCardsProps, TableComponent, TableControls, type TableControlsProps, TableDataDisplay, type TableDataDisplayProps, TableFilter, TableFilterTags, TableFooter, type TableFooterProps, TableHeader, type TableHeaderProps, type TableHeaderTexts, TableLoadingComponent, type TableLoadingComponentProps, type TableProps, type TableRendererProps, type TableRowSelectorProps, TableSelector, TableSorter, TableViewer, type TagPickerProps, TextCell, type TextCellProps, type UseDataTableProps, type UseDataTableReturn, type UseDataTableServerProps, type UseDataTableServerReturn, type UseFormProps, type ValidationErrorType, ViewDialog, buildErrorMessages, buildFieldErrors, buildRequiredErrors, convertToAjvErrorsFormat, createErrorMessage, getColumns, getMultiDates, getRangeDates, idPickerSanityCheck, useDataTable, useDataTableContext, useDataTableServer, useForm, widthSanityCheck };
package/dist/index.js CHANGED
@@ -4644,10 +4644,13 @@ function formatBytes(bytes) {
4644
4644
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
4645
4645
  }
4646
4646
 
4647
- function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, labels, translate, colLabel, }) {
4647
+ const MediaLibraryBrowser = ({ onFetchFiles, filterImageOnly = false, labels, enabled = true, multiple = false, onFileSelect, selectedFileId: controlledSelectedFileId, onSelectedFileIdChange, }) => {
4648
4648
  const [searchTerm, setSearchTerm] = React.useState('');
4649
- const [selectedFileId, setSelectedFileId] = React.useState('');
4649
+ const [internalSelectedFileId, setInternalSelectedFileId] = React.useState(multiple ? [] : '');
4650
4650
  const [failedImageIds, setFailedImageIds] = React.useState(new Set());
4651
+ // Use controlled or internal state for selectedFileId
4652
+ const selectedFileId = controlledSelectedFileId ?? internalSelectedFileId;
4653
+ const setSelectedFileId = onSelectedFileIdChange ?? setInternalSelectedFileId;
4651
4654
  const { data: filesData, isLoading, isError, } = reactQuery.useQuery({
4652
4655
  queryKey: ['file-picker-library', searchTerm],
4653
4656
  queryFn: async () => {
@@ -4656,91 +4659,176 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
4656
4659
  const files = await onFetchFiles(searchTerm.trim() || '');
4657
4660
  return { data: files };
4658
4661
  },
4659
- enabled: open && !!onFetchFiles,
4662
+ enabled: enabled && !!onFetchFiles,
4660
4663
  });
4661
4664
  const files = (filesData?.data || []);
4662
4665
  const filteredFiles = filterImageOnly
4663
4666
  ? files.filter((file) => /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name))
4664
4667
  : files;
4668
+ const handleFileClick = (fileId) => {
4669
+ if (multiple) {
4670
+ const currentSelection = Array.isArray(selectedFileId)
4671
+ ? selectedFileId
4672
+ : [];
4673
+ const newSelection = currentSelection.includes(fileId)
4674
+ ? currentSelection.filter((id) => id !== fileId)
4675
+ : [...currentSelection, fileId];
4676
+ setSelectedFileId(newSelection);
4677
+ if (onFileSelect) {
4678
+ onFileSelect(newSelection);
4679
+ }
4680
+ }
4681
+ else {
4682
+ setSelectedFileId(fileId);
4683
+ if (onFileSelect) {
4684
+ onFileSelect(fileId);
4685
+ }
4686
+ }
4687
+ };
4688
+ const handleImageError = (fileId) => {
4689
+ setFailedImageIds((prev) => new Set(prev).add(fileId));
4690
+ };
4691
+ if (!onFetchFiles)
4692
+ return null;
4693
+ return (jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 4, children: [jsxRuntime.jsxs(react.Box, { position: "relative", children: [jsxRuntime.jsx(react.Input, { placeholder: labels?.searchPlaceholder ?? 'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", colorPalette: "blue", _focus: {
4694
+ borderColor: 'colorPalette.500',
4695
+ _dark: {
4696
+ borderColor: 'colorPalette.400',
4697
+ },
4698
+ boxShadow: {
4699
+ base: '0 0 0 1px var(--chakra-colors-blue-500)',
4700
+ _dark: '0 0 0 1px var(--chakra-colors-blue-400)',
4701
+ },
4702
+ }, 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 ?? 'Loading files...' })] })), isError && (jsxRuntime.jsx(react.Box, { bg: { base: 'colorPalette.50', _dark: 'colorPalette.900/20' }, border: "1px solid", borderColor: {
4703
+ base: 'colorPalette.200',
4704
+ _dark: 'colorPalette.800',
4705
+ }, colorPalette: "red", borderRadius: "md", p: 4, children: jsxRuntime.jsx(react.Text, { color: {
4706
+ base: 'colorPalette.600',
4707
+ _dark: 'colorPalette.300',
4708
+ }, 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
+ const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
4710
+ const isSelected = multiple
4711
+ ? Array.isArray(selectedFileId) &&
4712
+ selectedFileId.includes(file.id)
4713
+ : selectedFileId === file.id;
4714
+ const imageFailed = failedImageIds.has(file.id);
4715
+ return (jsxRuntime.jsx(react.Box, { p: 3, border: "2px solid", borderColor: isSelected
4716
+ ? {
4717
+ base: 'colorPalette.500',
4718
+ _dark: 'colorPalette.400',
4719
+ }
4720
+ : 'border.default', borderRadius: "md", bg: isSelected
4721
+ ? {
4722
+ base: 'colorPalette.50',
4723
+ _dark: 'colorPalette.900/20',
4724
+ }
4725
+ : 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => handleFileClick(file.id), _hover: {
4726
+ borderColor: isSelected
4727
+ ? {
4728
+ base: 'colorPalette.600',
4729
+ _dark: 'colorPalette.400',
4730
+ }
4731
+ : {
4732
+ base: 'colorPalette.300',
4733
+ _dark: 'colorPalette.400',
4734
+ },
4735
+ bg: isSelected
4736
+ ? {
4737
+ base: 'colorPalette.100',
4738
+ _dark: 'colorPalette.800/30',
4739
+ }
4740
+ : 'bg.muted',
4741
+ }, 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'
4742
+ ? formatBytes(file.size)
4743
+ : 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: {
4744
+ base: 'colorPalette.500',
4745
+ _dark: 'colorPalette.400',
4746
+ }, 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));
4747
+ }) })) }))] }));
4748
+ };
4749
+
4750
+ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, onUploadFile, enableUpload = false, labels, translate, colLabel, }) {
4751
+ const [selectedFileId, setSelectedFileId] = React.useState('');
4752
+ const [activeTab, setActiveTab] = React.useState('browse');
4753
+ const [uploadingFiles, setUploadingFiles] = React.useState(new Set());
4754
+ const [uploadErrors, setUploadErrors] = React.useState(new Map());
4665
4755
  const handleSelect = () => {
4666
4756
  if (selectedFileId) {
4667
4757
  onSelect(selectedFileId);
4668
4758
  onClose();
4669
4759
  setSelectedFileId('');
4670
- setSearchTerm('');
4760
+ setActiveTab('browse');
4671
4761
  }
4672
4762
  };
4673
4763
  const handleClose = () => {
4674
4764
  onClose();
4675
4765
  setSelectedFileId('');
4676
- setSearchTerm('');
4677
- setFailedImageIds(new Set());
4766
+ setActiveTab('browse');
4767
+ setUploadingFiles(new Set());
4768
+ setUploadErrors(new Map());
4678
4769
  };
4679
- const handleImageError = (fileId) => {
4680
- setFailedImageIds((prev) => new Set(prev).add(fileId));
4770
+ const handleFileUpload = async (files) => {
4771
+ if (!onUploadFile)
4772
+ return;
4773
+ for (const file of files) {
4774
+ const fileKey = `${file.name}-${file.size}`;
4775
+ setUploadingFiles((prev) => new Set(prev).add(fileKey));
4776
+ setUploadErrors((prev) => {
4777
+ const newMap = new Map(prev);
4778
+ newMap.delete(fileKey);
4779
+ return newMap;
4780
+ });
4781
+ try {
4782
+ const fileId = await onUploadFile(file);
4783
+ setSelectedFileId(fileId);
4784
+ setUploadingFiles((prev) => {
4785
+ const newSet = new Set(prev);
4786
+ newSet.delete(fileKey);
4787
+ return newSet;
4788
+ });
4789
+ // Auto-select and close in single-select mode
4790
+ onSelect(fileId);
4791
+ onClose();
4792
+ setSelectedFileId('');
4793
+ setActiveTab('browse');
4794
+ }
4795
+ catch (error) {
4796
+ setUploadingFiles((prev) => {
4797
+ const newSet = new Set(prev);
4798
+ newSet.delete(fileKey);
4799
+ return newSet;
4800
+ });
4801
+ setUploadErrors((prev) => {
4802
+ const newMap = new Map(prev);
4803
+ newMap.set(fileKey, error instanceof Error ? error.message : 'Upload failed');
4804
+ return newMap;
4805
+ });
4806
+ }
4807
+ }
4681
4808
  };
4682
- if (!onFetchFiles)
4809
+ const showTabs = enableUpload && !!onUploadFile && !!onFetchFiles;
4810
+ if (!onFetchFiles && !onUploadFile)
4683
4811
  return null;
4684
- 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 ??
4685
- translate(removeIndex(`${colLabel}.search_placeholder`)) ??
4686
- 'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", colorPalette: "blue", _focus: {
4687
- borderColor: 'colorPalette.500',
4688
- _dark: {
4689
- borderColor: 'colorPalette.400',
4690
- },
4691
- boxShadow: {
4692
- base: '0 0 0 1px var(--chakra-colors-blue-500)',
4693
- _dark: '0 0 0 1px var(--chakra-colors-blue-400)',
4694
- },
4695
- }, 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 ??
4696
- translate(removeIndex(`${colLabel}.loading`)) ??
4697
- 'Loading files...' })] })), isError && (jsxRuntime.jsx(react.Box, { bg: { base: 'colorPalette.50', _dark: 'colorPalette.900/20' }, border: "1px solid", borderColor: {
4698
- base: 'colorPalette.200',
4699
- _dark: 'colorPalette.800',
4700
- }, colorPalette: "red", borderRadius: "md", p: 4, children: jsxRuntime.jsx(react.Text, { color: {
4701
- base: 'colorPalette.600',
4702
- _dark: 'colorPalette.300',
4703
- }, children: labels?.loadingFailed ??
4704
- translate(removeIndex(`${colLabel}.error.loading_failed`)) ??
4705
- '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 ??
4706
- translate(removeIndex(`${colLabel}.no_files_found`)) ??
4707
- 'No files found' }) })) : (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
4708
- const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
4709
- const isSelected = selectedFileId === file.id;
4710
- const imageFailed = failedImageIds.has(file.id);
4711
- return (jsxRuntime.jsx(react.Box, { p: 3, border: "2px solid", borderColor: isSelected
4712
- ? {
4713
- base: 'colorPalette.500',
4714
- _dark: 'colorPalette.400',
4715
- }
4716
- : 'border.default', borderRadius: "md", bg: isSelected
4717
- ? {
4812
+ 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: showTabs ? (jsxRuntime.jsxs(react.Tabs.Root, { value: activeTab, onValueChange: (e) => setActiveTab(e.value ?? 'browse'), children: [jsxRuntime.jsxs(react.Tabs.List, { children: [jsxRuntime.jsx(react.Tabs.Trigger, { value: "browse", children: labels?.browseTab ??
4813
+ translate(removeIndex(`${colLabel}.browse_tab`)) ??
4814
+ 'Browse Library' }), jsxRuntime.jsx(react.Tabs.Trigger, { value: "upload", children: labels?.uploadTab ??
4815
+ 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', selectedFileId: selectedFileId, onSelectedFileIdChange: setSelectedFileId })) }), 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
+ translate(removeIndex(`${colLabel}.fileDropzone`)) ??
4818
+ '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
+ translate(removeIndex(`${colLabel}.uploading`)) ??
4820
+ 'Uploading...', ' ', fileKey.split('-')[0]] })] }) }, fileKey))) })), uploadErrors.size > 0 && (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: Array.from(uploadErrors.entries()).map(([fileKey, error]) => (jsxRuntime.jsx(react.Box, { bg: {
4718
4821
  base: 'colorPalette.50',
4719
4822
  _dark: 'colorPalette.900/20',
4720
- }
4721
- : 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => setSelectedFileId(file.id), _hover: {
4722
- borderColor: isSelected
4723
- ? {
4823
+ }, border: "1px solid", borderColor: {
4824
+ base: 'colorPalette.200',
4825
+ _dark: 'colorPalette.800',
4826
+ }, colorPalette: "red", borderRadius: "md", p: 3, children: jsxRuntime.jsxs(react.Text, { fontSize: "sm", color: {
4724
4827
  base: 'colorPalette.600',
4725
- _dark: 'colorPalette.400',
4726
- }
4727
- : {
4728
- base: 'colorPalette.300',
4729
- _dark: 'colorPalette.400',
4730
- },
4731
- bg: isSelected
4732
- ? {
4733
- base: 'colorPalette.100',
4734
- _dark: 'colorPalette.800/30',
4735
- }
4736
- : 'bg.muted',
4737
- }, 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'
4738
- ? formatBytes(file.size)
4739
- : 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: {
4740
- base: 'colorPalette.500',
4741
- _dark: 'colorPalette.400',
4742
- }, 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));
4743
- }) })) }))] }) }), 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 ??
4828
+ _dark: 'colorPalette.300',
4829
+ }, children: [fileKey.split('-')[0], ":", ' ', labels?.uploadFailed ??
4830
+ translate(removeIndex(`${colLabel}.upload_failed`)) ??
4831
+ 'Upload failed', error && ` - ${error}`] }) }, fileKey))) }))] }) })] })) : onFetchFiles ? (jsxRuntime.jsx(MediaLibraryBrowser, { onFetchFiles: onFetchFiles, filterImageOnly: filterImageOnly, labels: labels, enabled: open, selectedFileId: selectedFileId, onSelectedFileIdChange: setSelectedFileId })) : 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 ??
4744
4832
  translate(removeIndex(`${colLabel}.cancel`)) ??
4745
4833
  'Cancel' }), jsxRuntime.jsx(react.Button, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFileId, children: labels?.select ??
4746
4834
  translate(removeIndex(`${colLabel}.select`)) ??
@@ -4750,84 +4838,71 @@ const FilePicker = ({ column, schema, prefix }) => {
4750
4838
  const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4751
4839
  const { filePickerLabels } = useSchemaContext();
4752
4840
  const formI18n = useFormI18n(column, prefix);
4753
- const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, } = schema;
4841
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', type, } = schema;
4754
4842
  const isRequired = required?.some((columnId) => columnId === column);
4755
- const currentValue = watch(column) ?? [];
4756
- const currentFiles = Array.isArray(currentValue)
4757
- ? currentValue
4758
- : [];
4843
+ const isSingleSelect = type === 'string';
4844
+ const currentValue = watch(column) ?? (isSingleSelect ? '' : []);
4845
+ // Handle File objects only
4846
+ const currentFiles = isSingleSelect
4847
+ ? currentValue && currentValue instanceof File
4848
+ ? [currentValue]
4849
+ : []
4850
+ : Array.isArray(currentValue)
4851
+ ? currentValue.filter((f) => f instanceof File)
4852
+ : [];
4759
4853
  const colLabel = formI18n.colLabel;
4760
- const [dialogOpen, setDialogOpen] = React.useState(false);
4761
4854
  const [failedImageIds, setFailedImageIds] = React.useState(new Set());
4762
- const { onFetchFiles, enableMediaLibrary = false, filterImageOnly = false, } = filePicker || {};
4763
- const showMediaLibrary = enableMediaLibrary && !!onFetchFiles;
4855
+ // FilePicker variant: Only handle File objects, no media library browser
4764
4856
  const handleImageError = (fileIdentifier) => {
4765
4857
  setFailedImageIds((prev) => new Set(prev).add(fileIdentifier));
4766
4858
  };
4767
- const handleMediaLibrarySelect = (fileId) => {
4768
- const newFiles = [...currentFiles, fileId];
4769
- setValue(colLabel, newFiles);
4770
- };
4771
4859
  const handleRemove = (index) => {
4772
- const newFiles = currentFiles.filter((_, i) => i !== index);
4773
- setValue(colLabel, newFiles);
4774
- };
4775
- const isFileObject = (value) => {
4776
- return value instanceof File;
4860
+ if (isSingleSelect) {
4861
+ setValue(colLabel, '');
4862
+ }
4863
+ else {
4864
+ const newFiles = currentFiles.filter((_, i) => i !== index);
4865
+ setValue(colLabel, newFiles);
4866
+ }
4777
4867
  };
4778
4868
  const getFileIdentifier = (file, index) => {
4779
- if (isFileObject(file)) {
4780
- return `${file.name}-${file.size}-${index}`;
4781
- }
4782
- return file;
4869
+ // file-picker: file is a File object, create identifier from name and size
4870
+ return `${file.name}-${file.size}-${index}`;
4783
4871
  };
4784
4872
  const getFileName = (file) => {
4785
- if (isFileObject(file)) {
4786
- return file.name;
4787
- }
4788
- return typeof file === 'string' ? file : 'Unknown file';
4873
+ return file.name;
4789
4874
  };
4790
4875
  const getFileSize = (file) => {
4791
- if (isFileObject(file)) {
4792
- return file.size;
4793
- }
4794
- return undefined;
4876
+ return file.size;
4795
4877
  };
4796
4878
  const isImageFile = (file) => {
4797
- if (isFileObject(file)) {
4798
- return file.type.startsWith('image/');
4799
- }
4800
- if (typeof file === 'string') {
4801
- return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file);
4802
- }
4803
- return false;
4879
+ return file.type.startsWith('image/');
4804
4880
  };
4805
4881
  const getImageUrl = (file) => {
4806
- if (isFileObject(file)) {
4807
- return URL.createObjectURL(file);
4808
- }
4809
- return undefined;
4882
+ return URL.createObjectURL(file);
4810
4883
  };
4811
4884
  return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4812
- gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsxRuntime.jsxs(react.VStack, { align: "stretch", gap: 2, children: [jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4813
- const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => {
4814
- if (isFileObject(cur)) {
4815
- return cur.name === name;
4816
- }
4817
- return false;
4818
- }));
4885
+ gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: jsxRuntime.jsx(FileDropzone, { onDrop: ({ files }) => {
4886
+ // file-picker variant: Store File objects directly (no ID conversion)
4887
+ if (isSingleSelect) {
4888
+ // In single-select mode, use the first file and replace any existing file
4889
+ if (files.length > 0) {
4890
+ setValue(colLabel, files[0]);
4891
+ }
4892
+ }
4893
+ else {
4894
+ // In multi-select mode, filter duplicates and append
4895
+ const newFiles = files.filter(({ name }) => !currentFiles.some((cur) => cur.name === name));
4819
4896
  setValue(colLabel, [...currentFiles, ...newFiles]);
4820
- }, placeholder: filePickerLabels?.fileDropzone ?? formI18n.t('fileDropzone') }), showMediaLibrary && (jsxRuntime.jsx(react.Button, { variant: "outline", onClick: () => setDialogOpen(true), borderColor: "border.default", bg: "bg.panel", _hover: { bg: 'bg.muted' }, children: filePickerLabels?.browseLibrary ??
4821
- formI18n.t('browse_library') ??
4822
- 'Browse from Library' }))] }), showMediaLibrary && (jsxRuntime.jsx(FilePickerDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
4823
- formI18n.t('dialog_title') ??
4824
- 'Select File', filterImageOnly: filterImageOnly, onFetchFiles: onFetchFiles, labels: filePickerLabels, translate: formI18n.t, colLabel: colLabel })), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file, index) => {
4897
+ }
4898
+ }, placeholder: filePickerLabels?.fileDropzone ?? formI18n.t('fileDropzone') }) }), jsxRuntime.jsx(react.Flex, { flexFlow: 'column', gap: 1, children: currentFiles.map((file, index) => {
4825
4899
  const fileIdentifier = getFileIdentifier(file, index);
4826
4900
  const fileName = getFileName(file);
4827
4901
  const fileSize = getFileSize(file);
4828
4902
  const isImage = isImageFile(file);
4829
4903
  const imageUrl = getImageUrl(file);
4830
4904
  const imageFailed = failedImageIds.has(fileIdentifier);
4905
+ // File Viewer
4831
4906
  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: {
4832
4907
  borderColor: 'colorPalette.300',
4833
4908
  bg: 'bg.muted',
@@ -4835,6 +4910,66 @@ const FilePicker = ({ column, schema, prefix }) => {
4835
4910
  }) })] }));
4836
4911
  };
4837
4912
 
4913
+ const FormMediaLibraryBrowser = ({ column, schema, prefix, }) => {
4914
+ const { setValue, formState: { errors }, watch, } = reactHookForm.useFormContext();
4915
+ const { filePickerLabels } = useSchemaContext();
4916
+ const formI18n = useFormI18n(column, prefix);
4917
+ const { required, gridColumn = 'span 12', gridRow = 'span 1', filePicker, type, } = schema;
4918
+ const isRequired = required?.some((columnId) => columnId === column);
4919
+ const isSingleSelect = type === 'string';
4920
+ const currentValue = watch(column) ?? (isSingleSelect ? '' : []);
4921
+ // Handle string IDs only
4922
+ const currentFileIds = isSingleSelect
4923
+ ? currentValue
4924
+ ? [currentValue]
4925
+ : []
4926
+ : Array.isArray(currentValue)
4927
+ ? currentValue
4928
+ : [];
4929
+ const colLabel = formI18n.colLabel;
4930
+ const [dialogOpen, setDialogOpen] = React.useState(false);
4931
+ const [failedImageIds, setFailedImageIds] = React.useState(new Set());
4932
+ const { onFetchFiles, filterImageOnly = false, enableUpload = false, onUploadFile, } = filePicker || {};
4933
+ if (!onFetchFiles) {
4934
+ return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4935
+ 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
+ }
4937
+ const handleMediaLibrarySelect = (fileId) => {
4938
+ if (isSingleSelect) {
4939
+ setValue(colLabel, fileId);
4940
+ }
4941
+ else {
4942
+ const newFileIds = [...currentFileIds, fileId];
4943
+ setValue(colLabel, newFileIds);
4944
+ }
4945
+ };
4946
+ const handleRemove = (index) => {
4947
+ if (isSingleSelect) {
4948
+ setValue(colLabel, '');
4949
+ }
4950
+ else {
4951
+ const newFileIds = currentFileIds.filter((_, i) => i !== index);
4952
+ setValue(colLabel, newFileIds);
4953
+ }
4954
+ };
4955
+ const isImageId = (fileId) => {
4956
+ return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(fileId);
4957
+ };
4958
+ return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
4959
+ 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
+ formI18n.t('browse_library') ??
4961
+ 'Browse from Library' }) }), jsxRuntime.jsx(FilePickerDialog, { open: dialogOpen, onClose: () => setDialogOpen(false), onSelect: handleMediaLibrarySelect, title: filePickerLabels?.dialogTitle ??
4962
+ formI18n.t('dialog_title') ??
4963
+ '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 isImage = isImageId(fileId);
4965
+ const imageFailed = failedImageIds.has(fileId);
4966
+ 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
+ borderColor: 'colorPalette.300',
4968
+ 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.jsx(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: fileId }) }), jsxRuntime.jsx(react.Icon, { as: ti.TiDeleteOutline, boxSize: 5, color: "fg.muted" })] }) }, `${fileId}-${index}`));
4970
+ }) })] }));
4971
+ };
4972
+
4838
4973
  const ToggleTip = React__namespace.forwardRef(function ToggleTip(props, ref) {
4839
4974
  const { showArrow, children, portalled = true, content, portalRef, ...rest } = props;
4840
4975
  return (jsxRuntime.jsxs(react.Popover.Root, { ...rest, positioning: { ...rest.positioning, gutter: 4 }, children: [jsxRuntime.jsx(react.Popover.Trigger, { asChild: true, children: children }), jsxRuntime.jsx(react.Portal, { disabled: !portalled, container: portalRef, children: jsxRuntime.jsx(react.Popover.Positioner, { children: jsxRuntime.jsxs(react.Popover.Content, { width: "auto", px: "2", py: "1", textStyle: "xs", rounded: "sm", ref: ref, children: [showArrow && (jsxRuntime.jsx(react.Popover.Arrow, { children: jsxRuntime.jsx(react.Popover.ArrowTip, {}) })), content] }) }) })] }));
@@ -6025,6 +6160,9 @@ const SchemaRenderer = ({ schema, prefix, column, }) => {
6025
6160
  if (variant === 'file-picker') {
6026
6161
  return jsxRuntime.jsx(FilePicker, { schema: colSchema, prefix, column });
6027
6162
  }
6163
+ if (variant === 'media-library-browser') {
6164
+ return (jsxRuntime.jsx(FormMediaLibraryBrowser, { schema: colSchema, prefix, column }));
6165
+ }
6028
6166
  if (variant === 'date-range') {
6029
6167
  return jsxRuntime.jsx(DateRangePicker, { schema: colSchema, prefix, column });
6030
6168
  }
@@ -6416,59 +6554,62 @@ const DateTimeViewer = ({ column, schema, prefix }) => {
6416
6554
  const SchemaViewer = ({ schema, prefix, column, }) => {
6417
6555
  const colSchema = schema;
6418
6556
  const { type, variant, properties: innerProperties, foreign_key, items, format, } = schema;
6419
- if (variant === "custom-input") {
6557
+ if (variant === 'custom-input') {
6420
6558
  return jsxRuntime.jsx(CustomViewer, { schema: colSchema, prefix, column });
6421
6559
  }
6422
- if (type === "string") {
6560
+ if (type === 'string') {
6423
6561
  if ((schema.enum ?? []).length > 0) {
6424
6562
  return jsxRuntime.jsx(EnumViewer, { schema: colSchema, prefix, column });
6425
6563
  }
6426
- if (variant === "id-picker") {
6564
+ if (variant === 'id-picker') {
6427
6565
  idPickerSanityCheck(column, foreign_key);
6428
6566
  return jsxRuntime.jsx(IdViewer, { schema: colSchema, prefix, column });
6429
6567
  }
6430
- if (format === "time") {
6568
+ if (format === 'time') {
6431
6569
  return jsxRuntime.jsx(TimeViewer, { schema: colSchema, prefix, column });
6432
6570
  }
6433
- if (format === "date") {
6571
+ if (format === 'date') {
6434
6572
  return jsxRuntime.jsx(DateViewer, { schema: colSchema, prefix, column });
6435
6573
  }
6436
- if (format === "date-time") {
6574
+ if (format === 'date-time') {
6437
6575
  return jsxRuntime.jsx(DateTimeViewer, { schema: colSchema, prefix, column });
6438
6576
  }
6439
- if (variant === "text-area") {
6577
+ if (variant === 'text-area') {
6440
6578
  return jsxRuntime.jsx(TextAreaViewer, { schema: colSchema, prefix, column });
6441
6579
  }
6442
6580
  return jsxRuntime.jsx(StringViewer, { schema: colSchema, prefix, column });
6443
6581
  }
6444
- if (type === "number" || type === "integer") {
6582
+ if (type === 'number' || type === 'integer') {
6445
6583
  return jsxRuntime.jsx(NumberViewer, { schema: colSchema, prefix, column });
6446
6584
  }
6447
- if (type === "boolean") {
6585
+ if (type === 'boolean') {
6448
6586
  return jsxRuntime.jsx(BooleanViewer, { schema: colSchema, prefix, column });
6449
6587
  }
6450
- if (type === "object") {
6588
+ if (type === 'object') {
6451
6589
  if (innerProperties) {
6452
6590
  return jsxRuntime.jsx(ObjectViewer, { schema: colSchema, prefix, column });
6453
6591
  }
6454
6592
  return jsxRuntime.jsx(RecordInput, { schema: colSchema, prefix, column });
6455
6593
  }
6456
- if (type === "array") {
6457
- if (variant === "id-picker") {
6594
+ if (type === 'array') {
6595
+ if (variant === 'id-picker') {
6458
6596
  idPickerSanityCheck(column, foreign_key);
6459
6597
  return (jsxRuntime.jsx(IdViewer, { schema: colSchema, prefix, column, isMultiple: true }));
6460
6598
  }
6461
- if (variant === "tag-picker") {
6599
+ if (variant === 'tag-picker') {
6462
6600
  return jsxRuntime.jsx(TagViewer, { schema: colSchema, prefix, column });
6463
6601
  }
6464
- if (variant === "file-picker") {
6602
+ if (variant === 'file-picker') {
6603
+ return jsxRuntime.jsx(FileViewer, { schema: colSchema, prefix, column });
6604
+ }
6605
+ if (variant === 'media-library-browser') {
6465
6606
  return jsxRuntime.jsx(FileViewer, { schema: colSchema, prefix, column });
6466
6607
  }
6467
- if (variant === "enum-picker") {
6608
+ if (variant === 'enum-picker') {
6468
6609
  const { items } = schema;
6469
6610
  const { enum: enumItems } = items;
6470
6611
  const enumSchema = {
6471
- type: "string",
6612
+ type: 'string',
6472
6613
  enum: enumItems,
6473
6614
  };
6474
6615
  return (jsxRuntime.jsx(EnumViewer, { isMultiple: true, schema: enumSchema, prefix, column }));
@@ -6478,7 +6619,7 @@ const SchemaViewer = ({ schema, prefix, column, }) => {
6478
6619
  }
6479
6620
  return jsxRuntime.jsx(react.Text, { children: `array ${column}` });
6480
6621
  }
6481
- if (type === "null") {
6622
+ if (type === 'null') {
6482
6623
  return jsxRuntime.jsx(react.Text, { children: `null ${column}` });
6483
6624
  }
6484
6625
  return jsxRuntime.jsx(react.Text, { children: "missing type" });
@@ -7409,6 +7550,7 @@ exports.FormBody = FormBody;
7409
7550
  exports.FormRoot = FormRoot;
7410
7551
  exports.FormTitle = FormTitle;
7411
7552
  exports.GlobalFilter = GlobalFilter;
7553
+ exports.MediaLibraryBrowser = MediaLibraryBrowser;
7412
7554
  exports.PageSizeControl = PageSizeControl;
7413
7555
  exports.Pagination = Pagination;
7414
7556
  exports.RecordDisplay = RecordDisplay;