@bsol-oss/react-datatable5 12.0.0-beta.76 → 12.0.0-beta.78
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 +8 -4
- package/dist/index.js +148 -47
- package/dist/index.mjs +150 -49
- package/dist/types/components/DataTable/DataTable.d.ts +3 -0
- package/dist/types/components/DataTable/DefaultTable.d.ts +9 -8
- package/dist/types/components/DataTable/DefaultTableServer.d.ts +23 -0
- package/dist/types/components/DataTable/display/Table.d.ts +1 -1
- package/dist/types/components/DataTable/display/TableBodySkeleton.d.ts +5 -0
- package/dist/types/components/Form/components/FileDropzone.d.ts +2 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -112,6 +112,9 @@ interface DataTableProps<TData = unknown> {
|
|
|
112
112
|
* Data array for the table.
|
|
113
113
|
*
|
|
114
114
|
* It will pass into as the data in `@tanstack/react-table`
|
|
115
|
+
* Do not toggle the data array, it will cause the table to re-render in infinite loop.
|
|
116
|
+
*
|
|
117
|
+
* @default []
|
|
115
118
|
*
|
|
116
119
|
*/
|
|
117
120
|
data: TData[];
|
|
@@ -386,7 +389,7 @@ interface TableProps extends TableRootProps {
|
|
|
386
389
|
canResize?: boolean;
|
|
387
390
|
children: ReactNode;
|
|
388
391
|
}
|
|
389
|
-
declare const Table: ({ children, emptyComponent, canResize, ...props }: TableProps) => string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null;
|
|
392
|
+
declare const Table: ({ children, emptyComponent, canResize, showLoading, ...props }: TableProps) => string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null;
|
|
390
393
|
|
|
391
394
|
interface TableBodyProps {
|
|
392
395
|
pinnedBgColor?: {
|
|
@@ -467,14 +470,15 @@ declare const TableHeader: ({ canResize, showSelector, isSticky, tableHeaderProp
|
|
|
467
470
|
|
|
468
471
|
interface DefaultTableProps {
|
|
469
472
|
showFooter?: boolean;
|
|
470
|
-
tableProps?: Omit<TableProps,
|
|
473
|
+
tableProps?: Omit<TableProps, 'children'>;
|
|
471
474
|
tableHeaderProps?: TableHeaderProps;
|
|
472
475
|
tableBodyProps?: TableBodyProps;
|
|
473
476
|
tableFooterProps?: TableFooterProps;
|
|
474
477
|
controlProps?: TableControlsProps;
|
|
475
|
-
variant?:
|
|
478
|
+
variant?: '' | 'greedy';
|
|
479
|
+
isLoading?: boolean;
|
|
476
480
|
}
|
|
477
|
-
declare const DefaultTable: ({ showFooter, tableProps, tableHeaderProps, tableBodyProps, tableFooterProps, controlProps, variant, }: DefaultTableProps) => react_jsx_runtime.JSX.Element;
|
|
481
|
+
declare const DefaultTable: ({ showFooter, tableProps, tableHeaderProps, tableBodyProps, tableFooterProps, controlProps, variant, isLoading, }: DefaultTableProps) => react_jsx_runtime.JSX.Element;
|
|
478
482
|
|
|
479
483
|
interface ReloadButtonProps {
|
|
480
484
|
variant?: string;
|
package/dist/index.js
CHANGED
|
@@ -3114,9 +3114,10 @@ const EmptyState = React__namespace.forwardRef(function EmptyState(props, ref) {
|
|
|
3114
3114
|
});
|
|
3115
3115
|
|
|
3116
3116
|
const EmptyResult = (jsxRuntime.jsx(EmptyState, { icon: jsxRuntime.jsx(hi.HiColorSwatch, {}), title: "No results found", description: "Try adjusting your search", children: jsxRuntime.jsxs(react.List.Root, { variant: "marker", children: [jsxRuntime.jsx(react.List.Item, { children: "Try removing filters" }), jsxRuntime.jsx(react.List.Item, { children: "Try different keywords" })] }) }));
|
|
3117
|
-
const Table = ({ children, emptyComponent = EmptyResult, canResize = true, ...props }) => {
|
|
3117
|
+
const Table = ({ children, emptyComponent = EmptyResult, canResize = true, showLoading = false, ...props }) => {
|
|
3118
3118
|
const { table } = useDataTableContext();
|
|
3119
|
-
|
|
3119
|
+
// Skip empty check when loading to allow skeleton to render
|
|
3120
|
+
if (!showLoading && table.getRowModel().rows.length <= 0) {
|
|
3120
3121
|
return emptyComponent;
|
|
3121
3122
|
}
|
|
3122
3123
|
return (jsxRuntime.jsx(react.Table.Root, { stickyHeader: true, variant: "outline", width: canResize ? table.getCenterTotalSize() : undefined, display: "grid", alignContent: "start", overflowY: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...props, children: children }));
|
|
@@ -3185,6 +3186,65 @@ const TableRowSelector = ({ row, }) => {
|
|
|
3185
3186
|
onCheckedChange: row.getToggleSelectedHandler() }) }));
|
|
3186
3187
|
};
|
|
3187
3188
|
|
|
3189
|
+
const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
|
|
3190
|
+
"use no memo";
|
|
3191
|
+
const { table } = useDataTableContext();
|
|
3192
|
+
const SELECTION_BOX_WIDTH = 20;
|
|
3193
|
+
const [hoveredRow, setHoveredRow] = React.useState(-1);
|
|
3194
|
+
const handleRowHover = (index) => {
|
|
3195
|
+
setHoveredRow(index);
|
|
3196
|
+
};
|
|
3197
|
+
const getTdProps = (column) => {
|
|
3198
|
+
const tdProps = column.getIsPinned()
|
|
3199
|
+
? {
|
|
3200
|
+
left: showSelector
|
|
3201
|
+
? `${column.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
|
|
3202
|
+
: `${column.getStart("left")}px`,
|
|
3203
|
+
position: "relative",
|
|
3204
|
+
}
|
|
3205
|
+
: {};
|
|
3206
|
+
return tdProps;
|
|
3207
|
+
};
|
|
3208
|
+
const getTrProps = ({ hoveredRow, index, }) => {
|
|
3209
|
+
if (hoveredRow === -1) {
|
|
3210
|
+
return {};
|
|
3211
|
+
}
|
|
3212
|
+
if (hoveredRow === index) {
|
|
3213
|
+
return {
|
|
3214
|
+
opacity: "1",
|
|
3215
|
+
};
|
|
3216
|
+
}
|
|
3217
|
+
return {
|
|
3218
|
+
opacity: "0.8",
|
|
3219
|
+
};
|
|
3220
|
+
};
|
|
3221
|
+
// Get the number of skeleton rows based on current pageSize
|
|
3222
|
+
const pageSize = table.getState().pagination.pageSize;
|
|
3223
|
+
const visibleColumns = table.getVisibleLeafColumns();
|
|
3224
|
+
return (jsxRuntime.jsx(react.Table.Body, { children: Array.from({ length: pageSize }).map((_, rowIndex) => {
|
|
3225
|
+
return (jsxRuntime.jsxs(react.Table.Row, { display: "flex", zIndex: 1, onMouseEnter: () => handleRowHover(rowIndex), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index: rowIndex }), children: [showSelector && (jsxRuntime.jsx(TableRowSelectorSkeleton, {})), visibleColumns.map((column, colIndex) => {
|
|
3226
|
+
return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`,
|
|
3227
|
+
// styling resize and pinning start
|
|
3228
|
+
flex: `${canResize ? "0" : "1"} 0 ${column.getSize()}px`,
|
|
3229
|
+
// this is to avoid the cell from being too wide
|
|
3230
|
+
minWidth: `0`, color: {
|
|
3231
|
+
base: "colorPalette.900",
|
|
3232
|
+
_dark: "colorPalette.100",
|
|
3233
|
+
},
|
|
3234
|
+
bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...getTdProps(column), children: jsxRuntime.jsx(react.Skeleton, { height: "20px", width: "80%" }) }, `chakra-table-skeleton-cell-${rowIndex}-${colIndex}`));
|
|
3235
|
+
})] }, `chakra-table-skeleton-row-${rowIndex}`));
|
|
3236
|
+
}) }));
|
|
3237
|
+
};
|
|
3238
|
+
const TableRowSelectorSkeleton = () => {
|
|
3239
|
+
const { table } = useDataTableContext();
|
|
3240
|
+
const SELECTION_BOX_WIDTH = 20;
|
|
3241
|
+
return (jsxRuntime.jsx(react.Table.Cell, { padding: `${table.getDensityValue()}px`, display: "grid", color: {
|
|
3242
|
+
base: "colorPalette.900",
|
|
3243
|
+
_dark: "colorPalette.100",
|
|
3244
|
+
},
|
|
3245
|
+
bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, justifyItems: "center", alignItems: "center", children: jsxRuntime.jsx(react.Skeleton, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }) }));
|
|
3246
|
+
};
|
|
3247
|
+
|
|
3188
3248
|
const TableFooter = ({ showSelector = false, alwaysShowSelector = true, }) => {
|
|
3189
3249
|
const table = useDataTableContext().table;
|
|
3190
3250
|
const SELECTION_BOX_WIDTH = 20;
|
|
@@ -3346,11 +3406,12 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
|
|
|
3346
3406
|
})] }, `chakra-table-headergroup-${headerGroup.id}`))) }));
|
|
3347
3407
|
};
|
|
3348
3408
|
|
|
3349
|
-
const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant =
|
|
3350
|
-
|
|
3351
|
-
|
|
3409
|
+
const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = '', isLoading = false, }) => {
|
|
3410
|
+
const bodyComponent = isLoading ? (jsxRuntime.jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: tableBodyProps.canResize })) : (jsxRuntime.jsx(TableBody, { ...tableBodyProps }));
|
|
3411
|
+
if (variant === 'greedy') {
|
|
3412
|
+
return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { canResize: false, showLoading: isLoading, ...tableProps, children: [jsxRuntime.jsx(TableHeader, { canResize: false, ...tableHeaderProps }), bodyComponent, showFooter && (jsxRuntime.jsx(TableFooter, { canResize: false, ...tableFooterProps }))] }) }));
|
|
3352
3413
|
}
|
|
3353
|
-
return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { ...tableProps, children: [jsxRuntime.jsx(TableHeader, { ...tableHeaderProps }),
|
|
3414
|
+
return (jsxRuntime.jsx(TableControls, { ...controlProps, children: jsxRuntime.jsxs(Table, { showLoading: isLoading, ...tableProps, children: [jsxRuntime.jsx(TableHeader, { ...tableHeaderProps }), bodyComponent, showFooter && jsxRuntime.jsx(TableFooter, { ...tableFooterProps })] }) }));
|
|
3354
3415
|
};
|
|
3355
3416
|
|
|
3356
3417
|
const TableCardContainer = ({ children, variant = "", gap = "1rem", gridTemplateColumns = "repeat(auto-fit, minmax(20rem, 1fr))", direction = "row", ...props }) => {
|
|
@@ -4469,7 +4530,8 @@ function filterArray(array, searchTerm) {
|
|
|
4469
4530
|
|
|
4470
4531
|
const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
|
|
4471
4532
|
const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
|
|
4472
|
-
const {
|
|
4533
|
+
const { enumPickerLabels } = useSchemaContext();
|
|
4534
|
+
const formI18n = useFormI18n(column, prefix);
|
|
4473
4535
|
const { required, variant } = schema;
|
|
4474
4536
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4475
4537
|
const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
|
|
@@ -4477,7 +4539,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4477
4539
|
const [limit, setLimit] = React.useState(10);
|
|
4478
4540
|
const [openSearchResult, setOpenSearchResult] = React.useState();
|
|
4479
4541
|
const ref = React.useRef(null);
|
|
4480
|
-
const colLabel =
|
|
4542
|
+
const colLabel = formI18n.colLabel;
|
|
4481
4543
|
const watchEnum = watch(colLabel);
|
|
4482
4544
|
const watchEnums = (watch(colLabel) ?? []);
|
|
4483
4545
|
const dataList = schema.enum ?? [];
|
|
@@ -4488,10 +4550,8 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4488
4550
|
setLimit(10);
|
|
4489
4551
|
};
|
|
4490
4552
|
if (variant === 'radio') {
|
|
4491
|
-
return (jsxRuntime.jsx(Field, { label:
|
|
4492
|
-
gridRow, errorText: errors[`${colLabel}`]
|
|
4493
|
-
? translate.t(removeIndex(`${colLabel}.field_required`))
|
|
4494
|
-
: undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
|
|
4553
|
+
return (jsxRuntime.jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4554
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsxRuntime.jsx(react.RadioGroup.Root, { defaultValue: "1", children: jsxRuntime.jsx(react.HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
|
|
4495
4555
|
return (jsxRuntime.jsxs(react.RadioGroup.Item, { onClick: () => {
|
|
4496
4556
|
if (!isMultiple) {
|
|
4497
4557
|
setOpenSearchResult(false);
|
|
@@ -4502,13 +4562,11 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4502
4562
|
setValue(colLabel, [...newSet]);
|
|
4503
4563
|
}, value: item, children: [jsxRuntime.jsx(react.RadioGroup.ItemHiddenInput, {}), jsxRuntime.jsx(react.RadioGroup.ItemIndicator, {}), jsxRuntime.jsx(react.RadioGroup.ItemText, { children: !!renderDisplay === true
|
|
4504
4564
|
? renderDisplay(item)
|
|
4505
|
-
:
|
|
4565
|
+
: formI18n.t(item) })] }, `${colLabel}-${item}`));
|
|
4506
4566
|
}) }) }) }));
|
|
4507
4567
|
}
|
|
4508
|
-
return (jsxRuntime.jsxs(Field, { label:
|
|
4509
|
-
gridRow, errorText: errors[`${colLabel}`]
|
|
4510
|
-
? translate.t(removeIndex(`${colLabel}.field_required`))
|
|
4511
|
-
: undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
|
|
4568
|
+
return (jsxRuntime.jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4569
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxRuntime.jsxs(react.Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
|
|
4512
4570
|
const item = enumValue;
|
|
4513
4571
|
if (!!item === false) {
|
|
4514
4572
|
return jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
@@ -4517,19 +4575,15 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4517
4575
|
setValue(column, watchEnums.filter((id) => id != item));
|
|
4518
4576
|
}, children: !!renderDisplay === true
|
|
4519
4577
|
? renderDisplay(item)
|
|
4520
|
-
:
|
|
4578
|
+
: formI18n.t(item) }, item));
|
|
4521
4579
|
}), jsxRuntime.jsx(Tag, { size: "lg", cursor: 'pointer', onClick: () => {
|
|
4522
4580
|
setOpenSearchResult(true);
|
|
4523
|
-
}, children: enumPickerLabels?.addMore ??
|
|
4524
|
-
translate.t(removeIndex(`${colLabel}.add_more`)) }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: 'outline', onClick: () => {
|
|
4581
|
+
}, children: enumPickerLabels?.addMore ?? formI18n.t('add_more') }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: 'outline', onClick: () => {
|
|
4525
4582
|
setOpenSearchResult(true);
|
|
4526
|
-
}, justifyContent: 'start', children: !!watchEnum === false
|
|
4527
|
-
? ''
|
|
4528
|
-
: translate.t(removeIndex(`${colLabel}.${watchEnum ?? 'null'}`)) })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: 'bottom-start' }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: 'grid', gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: enumPickerLabels?.typeToSearch ??
|
|
4529
|
-
translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
|
|
4583
|
+
}, justifyContent: 'start', children: !!watchEnum === false ? '' : formI18n.t(watchEnum ?? 'null') })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: 'bottom-start' }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { portalled: false, children: jsxRuntime.jsxs(PopoverBody, { display: 'grid', gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: enumPickerLabels?.typeToSearch ?? formI18n.t('type_to_search'), onChange: (event) => {
|
|
4530
4584
|
onSearchChange(event);
|
|
4531
4585
|
setOpenSearchResult(true);
|
|
4532
|
-
}, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), showTotalAndLimit && (jsxRuntime.jsx(react.Text, { children: `${enumPickerLabels?.total ??
|
|
4586
|
+
}, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), showTotalAndLimit && (jsxRuntime.jsx(react.Text, { children: `${enumPickerLabels?.total ?? formI18n.t('total')}: ${count}, ${enumPickerLabels?.showing ?? formI18n.t('showing')} ${limit}` })), jsxRuntime.jsxs(react.Grid, { overflow: 'auto', maxHeight: '20rem', children: [jsxRuntime.jsx(react.Flex, { flexFlow: 'column wrap', children: dataList
|
|
4533
4587
|
.filter((item) => {
|
|
4534
4588
|
const searchTerm = (searchText || '').toLowerCase();
|
|
4535
4589
|
if (!searchTerm)
|
|
@@ -4541,7 +4595,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4541
4595
|
// Check if the display value (translation) contains the search text
|
|
4542
4596
|
const displayValue = !!renderDisplay === true
|
|
4543
4597
|
? renderDisplay(item)
|
|
4544
|
-
:
|
|
4598
|
+
: formI18n.t(item);
|
|
4545
4599
|
// Convert to string and check if it includes the search term
|
|
4546
4600
|
const displayValueString = String(displayValue).toLowerCase();
|
|
4547
4601
|
const displayValueMatch = displayValueString.includes(searchTerm);
|
|
@@ -4561,9 +4615,9 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4561
4615
|
setValue(colLabel, [...newSet]);
|
|
4562
4616
|
}, ...(selected ? { color: 'colorPalette.400/50' } : {}), children: !!renderDisplay === true
|
|
4563
4617
|
? renderDisplay(item)
|
|
4564
|
-
:
|
|
4618
|
+
: formI18n.t(item) }, `${colLabel}-${item}`));
|
|
4565
4619
|
}) }), isDirty && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: dataList.length <= 0 && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: enumPickerLabels?.emptySearchResult ??
|
|
4566
|
-
|
|
4620
|
+
formI18n.t('empty_search_result') })) }))] })] }) })] })] }));
|
|
4567
4621
|
};
|
|
4568
4622
|
|
|
4569
4623
|
function isEnteringWindow(_ref) {
|
|
@@ -4869,7 +4923,7 @@ function getText(_ref2) {
|
|
|
4869
4923
|
return source.getStringData(textMediaType);
|
|
4870
4924
|
}
|
|
4871
4925
|
|
|
4872
|
-
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder =
|
|
4926
|
+
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder = 'Drop files here or click to upload', }) => {
|
|
4873
4927
|
const ref = React.useRef(null);
|
|
4874
4928
|
const [isDraggedOver, setIsDraggedOver] = React.useState(false);
|
|
4875
4929
|
React.useEffect(() => {
|
|
@@ -4883,7 +4937,7 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4883
4937
|
onDrop: ({ source }) => {
|
|
4884
4938
|
const files = getFiles({ source });
|
|
4885
4939
|
const text = getText({ source });
|
|
4886
|
-
console.log(files, text,
|
|
4940
|
+
console.log(files, text, 'dfposa');
|
|
4887
4941
|
onDrop({ files, text });
|
|
4888
4942
|
},
|
|
4889
4943
|
});
|
|
@@ -4892,9 +4946,9 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4892
4946
|
function getColor(isDraggedOver) {
|
|
4893
4947
|
if (isDraggedOver) {
|
|
4894
4948
|
return {
|
|
4895
|
-
backgroundColor:
|
|
4949
|
+
backgroundColor: 'blue.400',
|
|
4896
4950
|
_dark: {
|
|
4897
|
-
backgroundColor:
|
|
4951
|
+
backgroundColor: 'blue.400',
|
|
4898
4952
|
},
|
|
4899
4953
|
};
|
|
4900
4954
|
}
|
|
@@ -4915,7 +4969,7 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4915
4969
|
const filesArray = [...event.target.files];
|
|
4916
4970
|
onDrop({ files: filesArray });
|
|
4917
4971
|
};
|
|
4918
|
-
return (jsxRuntime.jsxs(react.Grid, { ...getColor(isDraggedOver), ref: ref, cursor:
|
|
4972
|
+
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
4973
|
};
|
|
4920
4974
|
|
|
4921
4975
|
/**
|
|
@@ -4935,6 +4989,7 @@ function formatBytes(bytes) {
|
|
|
4935
4989
|
function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, labels, translate, colLabel, }) {
|
|
4936
4990
|
const [searchTerm, setSearchTerm] = React.useState('');
|
|
4937
4991
|
const [selectedFileId, setSelectedFileId] = React.useState('');
|
|
4992
|
+
const [failedImageIds, setFailedImageIds] = React.useState(new Set());
|
|
4938
4993
|
const { data: filesData, isLoading, isError, } = reactQuery.useQuery({
|
|
4939
4994
|
queryKey: ['file-picker-library', searchTerm],
|
|
4940
4995
|
queryFn: async () => {
|
|
@@ -4961,31 +5016,72 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4961
5016
|
onClose();
|
|
4962
5017
|
setSelectedFileId('');
|
|
4963
5018
|
setSearchTerm('');
|
|
5019
|
+
setFailedImageIds(new Set());
|
|
5020
|
+
};
|
|
5021
|
+
const handleImageError = (fileId) => {
|
|
5022
|
+
setFailedImageIds((prev) => new Set(prev).add(fileId));
|
|
4964
5023
|
};
|
|
4965
5024
|
if (!onFetchFiles)
|
|
4966
5025
|
return null;
|
|
4967
5026
|
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
5027
|
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
|
-
|
|
5028
|
+
'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", colorPalette: "blue", _focus: {
|
|
5029
|
+
borderColor: 'colorPalette.500',
|
|
5030
|
+
_dark: {
|
|
5031
|
+
borderColor: 'colorPalette.400',
|
|
5032
|
+
},
|
|
5033
|
+
boxShadow: {
|
|
5034
|
+
base: '0 0 0 1px var(--chakra-colors-blue-500)',
|
|
5035
|
+
_dark: '0 0 0 1px var(--chakra-colors-blue-400)',
|
|
5036
|
+
},
|
|
4972
5037
|
}, 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
5038
|
translate(removeIndex(`${colLabel}.loading`)) ??
|
|
4974
|
-
'Loading files...' })] })), isError && (jsxRuntime.jsx(react.Box, { bg:
|
|
5039
|
+
'Loading files...' })] })), isError && (jsxRuntime.jsx(react.Box, { bg: { base: 'colorPalette.50', _dark: 'colorPalette.900/20' }, border: "1px solid", borderColor: {
|
|
5040
|
+
base: 'colorPalette.200',
|
|
5041
|
+
_dark: 'colorPalette.800',
|
|
5042
|
+
}, colorPalette: "red", borderRadius: "md", p: 4, children: jsxRuntime.jsx(react.Text, { color: {
|
|
5043
|
+
base: 'colorPalette.600',
|
|
5044
|
+
_dark: 'colorPalette.300',
|
|
5045
|
+
}, children: labels?.loadingFailed ??
|
|
4975
5046
|
translate(removeIndex(`${colLabel}.error.loading_failed`)) ??
|
|
4976
5047
|
'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
5048
|
translate(removeIndex(`${colLabel}.no_files_found`)) ??
|
|
4978
5049
|
'No files found' }) })) : (jsxRuntime.jsx(react.VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
|
|
4979
5050
|
const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
|
|
4980
5051
|
const isSelected = selectedFileId === file.id;
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
5052
|
+
const imageFailed = failedImageIds.has(file.id);
|
|
5053
|
+
return (jsxRuntime.jsx(react.Box, { p: 3, border: "2px solid", borderColor: isSelected
|
|
5054
|
+
? {
|
|
5055
|
+
base: 'colorPalette.500',
|
|
5056
|
+
_dark: 'colorPalette.400',
|
|
5057
|
+
}
|
|
5058
|
+
: 'border.default', borderRadius: "md", bg: isSelected
|
|
5059
|
+
? {
|
|
5060
|
+
base: 'colorPalette.50',
|
|
5061
|
+
_dark: 'colorPalette.900/20',
|
|
5062
|
+
}
|
|
5063
|
+
: 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => setSelectedFileId(file.id), _hover: {
|
|
5064
|
+
borderColor: isSelected
|
|
5065
|
+
? {
|
|
5066
|
+
base: 'colorPalette.600',
|
|
5067
|
+
_dark: 'colorPalette.400',
|
|
5068
|
+
}
|
|
5069
|
+
: {
|
|
5070
|
+
base: 'colorPalette.300',
|
|
5071
|
+
_dark: 'colorPalette.400',
|
|
5072
|
+
},
|
|
5073
|
+
bg: isSelected
|
|
5074
|
+
? {
|
|
5075
|
+
base: 'colorPalette.100',
|
|
5076
|
+
_dark: 'colorPalette.800/30',
|
|
5077
|
+
}
|
|
5078
|
+
: 'bg.muted',
|
|
5079
|
+
}, 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
5080
|
? 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:
|
|
5081
|
+
: 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: {
|
|
5082
|
+
base: 'colorPalette.500',
|
|
5083
|
+
_dark: 'colorPalette.400',
|
|
5084
|
+
}, 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
5085
|
}) })) }))] }) }), 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
5086
|
translate(removeIndex(`${colLabel}.cancel`)) ??
|
|
4991
5087
|
'Cancel' }), jsxRuntime.jsx(react.Button, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFileId, children: labels?.select ??
|
|
@@ -5004,8 +5100,12 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
5004
5100
|
: [];
|
|
5005
5101
|
const colLabel = formI18n.colLabel;
|
|
5006
5102
|
const [dialogOpen, setDialogOpen] = React.useState(false);
|
|
5103
|
+
const [failedImageIds, setFailedImageIds] = React.useState(new Set());
|
|
5007
5104
|
const { onFetchFiles, enableMediaLibrary = false, filterImageOnly = false, } = filePicker || {};
|
|
5008
5105
|
const showMediaLibrary = enableMediaLibrary && !!onFetchFiles;
|
|
5106
|
+
const handleImageError = (fileIdentifier) => {
|
|
5107
|
+
setFailedImageIds((prev) => new Set(prev).add(fileIdentifier));
|
|
5108
|
+
};
|
|
5009
5109
|
const handleMediaLibrarySelect = (fileId) => {
|
|
5010
5110
|
const newFiles = [...currentFiles, fileId];
|
|
5011
5111
|
setValue(colLabel, newFiles);
|
|
@@ -5069,10 +5169,11 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
5069
5169
|
const fileSize = getFileSize(file);
|
|
5070
5170
|
const isImage = isImageFile(file);
|
|
5071
5171
|
const imageUrl = getImageUrl(file);
|
|
5072
|
-
|
|
5073
|
-
|
|
5172
|
+
const imageFailed = failedImageIds.has(fileIdentifier);
|
|
5173
|
+
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: {
|
|
5174
|
+
borderColor: 'colorPalette.300',
|
|
5074
5175
|
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));
|
|
5176
|
+
}, 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
5177
|
}) })] }));
|
|
5077
5178
|
};
|
|
5078
5179
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading } from '@chakra-ui/react';
|
|
2
|
+
import { Button as Button$1, AbsoluteCenter, Spinner, Span, IconButton, Portal, Dialog, Flex, Text, useDisclosure, DialogBackdrop, RadioGroup as RadioGroup$1, Grid, Box, Slider as Slider$1, HStack, For, Tag as Tag$1, Input, Menu, createRecipeContext, createContext as createContext$1, Pagination as Pagination$1, usePaginationContext, CheckboxCard as CheckboxCard$1, Image, EmptyState as EmptyState$2, VStack, Alert, Card, Group, InputElement, Tooltip as Tooltip$1, Icon, List, Table as Table$1, Checkbox as Checkbox$1, Skeleton, MenuRoot as MenuRoot$1, MenuTrigger as MenuTrigger$1, Field as Field$1, Popover, NumberInput, Show, RadioCard, CheckboxGroup, Center, Heading } from '@chakra-ui/react';
|
|
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';
|
|
@@ -3094,9 +3094,10 @@ const EmptyState = React.forwardRef(function EmptyState(props, ref) {
|
|
|
3094
3094
|
});
|
|
3095
3095
|
|
|
3096
3096
|
const EmptyResult = (jsx(EmptyState, { icon: jsx(HiColorSwatch, {}), title: "No results found", description: "Try adjusting your search", children: jsxs(List.Root, { variant: "marker", children: [jsx(List.Item, { children: "Try removing filters" }), jsx(List.Item, { children: "Try different keywords" })] }) }));
|
|
3097
|
-
const Table = ({ children, emptyComponent = EmptyResult, canResize = true, ...props }) => {
|
|
3097
|
+
const Table = ({ children, emptyComponent = EmptyResult, canResize = true, showLoading = false, ...props }) => {
|
|
3098
3098
|
const { table } = useDataTableContext();
|
|
3099
|
-
|
|
3099
|
+
// Skip empty check when loading to allow skeleton to render
|
|
3100
|
+
if (!showLoading && table.getRowModel().rows.length <= 0) {
|
|
3100
3101
|
return emptyComponent;
|
|
3101
3102
|
}
|
|
3102
3103
|
return (jsx(Table$1.Root, { stickyHeader: true, variant: "outline", width: canResize ? table.getCenterTotalSize() : undefined, display: "grid", alignContent: "start", overflowY: "auto", bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...props, children: children }));
|
|
@@ -3165,6 +3166,65 @@ const TableRowSelector = ({ row, }) => {
|
|
|
3165
3166
|
onCheckedChange: row.getToggleSelectedHandler() }) }));
|
|
3166
3167
|
};
|
|
3167
3168
|
|
|
3169
|
+
const TableBodySkeleton = ({ showSelector = false, canResize = true, }) => {
|
|
3170
|
+
"use no memo";
|
|
3171
|
+
const { table } = useDataTableContext();
|
|
3172
|
+
const SELECTION_BOX_WIDTH = 20;
|
|
3173
|
+
const [hoveredRow, setHoveredRow] = useState(-1);
|
|
3174
|
+
const handleRowHover = (index) => {
|
|
3175
|
+
setHoveredRow(index);
|
|
3176
|
+
};
|
|
3177
|
+
const getTdProps = (column) => {
|
|
3178
|
+
const tdProps = column.getIsPinned()
|
|
3179
|
+
? {
|
|
3180
|
+
left: showSelector
|
|
3181
|
+
? `${column.getStart("left") + SELECTION_BOX_WIDTH + table.getDensityValue() * 2}px`
|
|
3182
|
+
: `${column.getStart("left")}px`,
|
|
3183
|
+
position: "relative",
|
|
3184
|
+
}
|
|
3185
|
+
: {};
|
|
3186
|
+
return tdProps;
|
|
3187
|
+
};
|
|
3188
|
+
const getTrProps = ({ hoveredRow, index, }) => {
|
|
3189
|
+
if (hoveredRow === -1) {
|
|
3190
|
+
return {};
|
|
3191
|
+
}
|
|
3192
|
+
if (hoveredRow === index) {
|
|
3193
|
+
return {
|
|
3194
|
+
opacity: "1",
|
|
3195
|
+
};
|
|
3196
|
+
}
|
|
3197
|
+
return {
|
|
3198
|
+
opacity: "0.8",
|
|
3199
|
+
};
|
|
3200
|
+
};
|
|
3201
|
+
// Get the number of skeleton rows based on current pageSize
|
|
3202
|
+
const pageSize = table.getState().pagination.pageSize;
|
|
3203
|
+
const visibleColumns = table.getVisibleLeafColumns();
|
|
3204
|
+
return (jsx(Table$1.Body, { children: Array.from({ length: pageSize }).map((_, rowIndex) => {
|
|
3205
|
+
return (jsxs(Table$1.Row, { display: "flex", zIndex: 1, onMouseEnter: () => handleRowHover(rowIndex), onMouseLeave: () => handleRowHover(-1), ...getTrProps({ hoveredRow, index: rowIndex }), children: [showSelector && (jsx(TableRowSelectorSkeleton, {})), visibleColumns.map((column, colIndex) => {
|
|
3206
|
+
return (jsx(Table$1.Cell, { padding: `${table.getDensityValue()}px`,
|
|
3207
|
+
// styling resize and pinning start
|
|
3208
|
+
flex: `${canResize ? "0" : "1"} 0 ${column.getSize()}px`,
|
|
3209
|
+
// this is to avoid the cell from being too wide
|
|
3210
|
+
minWidth: `0`, color: {
|
|
3211
|
+
base: "colorPalette.900",
|
|
3212
|
+
_dark: "colorPalette.100",
|
|
3213
|
+
},
|
|
3214
|
+
bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, ...getTdProps(column), children: jsx(Skeleton, { height: "20px", width: "80%" }) }, `chakra-table-skeleton-cell-${rowIndex}-${colIndex}`));
|
|
3215
|
+
})] }, `chakra-table-skeleton-row-${rowIndex}`));
|
|
3216
|
+
}) }));
|
|
3217
|
+
};
|
|
3218
|
+
const TableRowSelectorSkeleton = () => {
|
|
3219
|
+
const { table } = useDataTableContext();
|
|
3220
|
+
const SELECTION_BOX_WIDTH = 20;
|
|
3221
|
+
return (jsx(Table$1.Cell, { padding: `${table.getDensityValue()}px`, display: "grid", color: {
|
|
3222
|
+
base: "colorPalette.900",
|
|
3223
|
+
_dark: "colorPalette.100",
|
|
3224
|
+
},
|
|
3225
|
+
bg: { base: "colorPalette.50", _dark: "colorPalette.950" }, justifyItems: "center", alignItems: "center", children: jsx(Skeleton, { width: `${SELECTION_BOX_WIDTH}px`, height: `${SELECTION_BOX_WIDTH}px` }) }));
|
|
3226
|
+
};
|
|
3227
|
+
|
|
3168
3228
|
const TableFooter = ({ showSelector = false, alwaysShowSelector = true, }) => {
|
|
3169
3229
|
const table = useDataTableContext().table;
|
|
3170
3230
|
const SELECTION_BOX_WIDTH = 20;
|
|
@@ -3326,11 +3386,12 @@ const TableHeader = ({ canResize = true, showSelector = false, isSticky = true,
|
|
|
3326
3386
|
})] }, `chakra-table-headergroup-${headerGroup.id}`))) }));
|
|
3327
3387
|
};
|
|
3328
3388
|
|
|
3329
|
-
const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant =
|
|
3330
|
-
|
|
3331
|
-
|
|
3389
|
+
const DefaultTable = ({ showFooter = false, tableProps = {}, tableHeaderProps = {}, tableBodyProps = {}, tableFooterProps = {}, controlProps = {}, variant = '', isLoading = false, }) => {
|
|
3390
|
+
const bodyComponent = isLoading ? (jsx(TableBodySkeleton, { showSelector: tableBodyProps.showSelector, canResize: tableBodyProps.canResize })) : (jsx(TableBody, { ...tableBodyProps }));
|
|
3391
|
+
if (variant === 'greedy') {
|
|
3392
|
+
return (jsx(TableControls, { ...controlProps, children: jsxs(Table, { canResize: false, showLoading: isLoading, ...tableProps, children: [jsx(TableHeader, { canResize: false, ...tableHeaderProps }), bodyComponent, showFooter && (jsx(TableFooter, { canResize: false, ...tableFooterProps }))] }) }));
|
|
3332
3393
|
}
|
|
3333
|
-
return (jsx(TableControls, { ...controlProps, children: jsxs(Table, { ...tableProps, children: [jsx(TableHeader, { ...tableHeaderProps }),
|
|
3394
|
+
return (jsx(TableControls, { ...controlProps, children: jsxs(Table, { showLoading: isLoading, ...tableProps, children: [jsx(TableHeader, { ...tableHeaderProps }), bodyComponent, showFooter && jsx(TableFooter, { ...tableFooterProps })] }) }));
|
|
3334
3395
|
};
|
|
3335
3396
|
|
|
3336
3397
|
const TableCardContainer = ({ children, variant = "", gap = "1rem", gridTemplateColumns = "repeat(auto-fit, minmax(20rem, 1fr))", direction = "row", ...props }) => {
|
|
@@ -4449,7 +4510,8 @@ function filterArray(array, searchTerm) {
|
|
|
4449
4510
|
|
|
4450
4511
|
const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLimit = false, }) => {
|
|
4451
4512
|
const { watch, formState: { errors }, setValue, } = useFormContext();
|
|
4452
|
-
const {
|
|
4513
|
+
const { enumPickerLabels } = useSchemaContext();
|
|
4514
|
+
const formI18n = useFormI18n(column, prefix);
|
|
4453
4515
|
const { required, variant } = schema;
|
|
4454
4516
|
const isRequired = required?.some((columnId) => columnId === column);
|
|
4455
4517
|
const { gridColumn = 'span 12', gridRow = 'span 1', renderDisplay } = schema;
|
|
@@ -4457,7 +4519,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4457
4519
|
const [limit, setLimit] = useState(10);
|
|
4458
4520
|
const [openSearchResult, setOpenSearchResult] = useState();
|
|
4459
4521
|
const ref = useRef(null);
|
|
4460
|
-
const colLabel =
|
|
4522
|
+
const colLabel = formI18n.colLabel;
|
|
4461
4523
|
const watchEnum = watch(colLabel);
|
|
4462
4524
|
const watchEnums = (watch(colLabel) ?? []);
|
|
4463
4525
|
const dataList = schema.enum ?? [];
|
|
@@ -4468,10 +4530,8 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4468
4530
|
setLimit(10);
|
|
4469
4531
|
};
|
|
4470
4532
|
if (variant === 'radio') {
|
|
4471
|
-
return (jsx(Field, { label:
|
|
4472
|
-
gridRow, errorText: errors[`${colLabel}`]
|
|
4473
|
-
? translate.t(removeIndex(`${colLabel}.field_required`))
|
|
4474
|
-
: undefined, invalid: !!errors[colLabel], children: jsx(RadioGroup$1.Root, { defaultValue: "1", children: jsx(HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
|
|
4533
|
+
return (jsx(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4534
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: jsx(RadioGroup$1.Root, { defaultValue: "1", children: jsx(HStack, { gap: "6", children: filterArray(dataList, searchText ?? '').map((item) => {
|
|
4475
4535
|
return (jsxs(RadioGroup$1.Item, { onClick: () => {
|
|
4476
4536
|
if (!isMultiple) {
|
|
4477
4537
|
setOpenSearchResult(false);
|
|
@@ -4482,13 +4542,11 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4482
4542
|
setValue(colLabel, [...newSet]);
|
|
4483
4543
|
}, value: item, children: [jsx(RadioGroup$1.ItemHiddenInput, {}), jsx(RadioGroup$1.ItemIndicator, {}), jsx(RadioGroup$1.ItemText, { children: !!renderDisplay === true
|
|
4484
4544
|
? renderDisplay(item)
|
|
4485
|
-
:
|
|
4545
|
+
: formI18n.t(item) })] }, `${colLabel}-${item}`));
|
|
4486
4546
|
}) }) }) }));
|
|
4487
4547
|
}
|
|
4488
|
-
return (jsxs(Field, { label:
|
|
4489
|
-
gridRow, errorText: errors[`${colLabel}`]
|
|
4490
|
-
? translate.t(removeIndex(`${colLabel}.field_required`))
|
|
4491
|
-
: undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxs(Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
|
|
4548
|
+
return (jsxs(Field, { label: formI18n.label(), required: isRequired, alignItems: 'stretch', gridColumn,
|
|
4549
|
+
gridRow, errorText: errors[`${colLabel}`] ? formI18n.required() : undefined, invalid: !!errors[colLabel], children: [isMultiple && (jsxs(Flex, { flexFlow: 'wrap', gap: 1, children: [watchEnums.map((enumValue) => {
|
|
4492
4550
|
const item = enumValue;
|
|
4493
4551
|
if (!!item === false) {
|
|
4494
4552
|
return jsx(Fragment, {});
|
|
@@ -4497,19 +4555,15 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4497
4555
|
setValue(column, watchEnums.filter((id) => id != item));
|
|
4498
4556
|
}, children: !!renderDisplay === true
|
|
4499
4557
|
? renderDisplay(item)
|
|
4500
|
-
:
|
|
4558
|
+
: formI18n.t(item) }, item));
|
|
4501
4559
|
}), jsx(Tag, { size: "lg", cursor: 'pointer', onClick: () => {
|
|
4502
4560
|
setOpenSearchResult(true);
|
|
4503
|
-
}, children: enumPickerLabels?.addMore ??
|
|
4504
|
-
translate.t(removeIndex(`${colLabel}.add_more`)) }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsx(Button, { variant: 'outline', onClick: () => {
|
|
4561
|
+
}, children: enumPickerLabels?.addMore ?? formI18n.t('add_more') }, `${colLabel}-add-more-tag`)] })), !isMultiple && (jsx(Button, { variant: 'outline', onClick: () => {
|
|
4505
4562
|
setOpenSearchResult(true);
|
|
4506
|
-
}, justifyContent: 'start', children: !!watchEnum === false
|
|
4507
|
-
? ''
|
|
4508
|
-
: translate.t(removeIndex(`${colLabel}.${watchEnum ?? 'null'}`)) })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: 'bottom-start' }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { portalled: false, children: jsxs(PopoverBody, { display: 'grid', gap: 1, children: [jsx(Input, { placeholder: enumPickerLabels?.typeToSearch ??
|
|
4509
|
-
translate.t(`${colLabel}.type_to_search`), onChange: (event) => {
|
|
4563
|
+
}, justifyContent: 'start', children: !!watchEnum === false ? '' : formI18n.t(watchEnum ?? 'null') })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: 'bottom-start' }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { portalled: false, children: jsxs(PopoverBody, { display: 'grid', gap: 1, children: [jsx(Input, { placeholder: enumPickerLabels?.typeToSearch ?? formI18n.t('type_to_search'), onChange: (event) => {
|
|
4510
4564
|
onSearchChange(event);
|
|
4511
4565
|
setOpenSearchResult(true);
|
|
4512
|
-
}, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), showTotalAndLimit && (jsx(Text, { children: `${enumPickerLabels?.total ??
|
|
4566
|
+
}, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), showTotalAndLimit && (jsx(Text, { children: `${enumPickerLabels?.total ?? formI18n.t('total')}: ${count}, ${enumPickerLabels?.showing ?? formI18n.t('showing')} ${limit}` })), jsxs(Grid, { overflow: 'auto', maxHeight: '20rem', children: [jsx(Flex, { flexFlow: 'column wrap', children: dataList
|
|
4513
4567
|
.filter((item) => {
|
|
4514
4568
|
const searchTerm = (searchText || '').toLowerCase();
|
|
4515
4569
|
if (!searchTerm)
|
|
@@ -4521,7 +4575,7 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4521
4575
|
// Check if the display value (translation) contains the search text
|
|
4522
4576
|
const displayValue = !!renderDisplay === true
|
|
4523
4577
|
? renderDisplay(item)
|
|
4524
|
-
:
|
|
4578
|
+
: formI18n.t(item);
|
|
4525
4579
|
// Convert to string and check if it includes the search term
|
|
4526
4580
|
const displayValueString = String(displayValue).toLowerCase();
|
|
4527
4581
|
const displayValueMatch = displayValueString.includes(searchTerm);
|
|
@@ -4541,9 +4595,9 @@ const EnumPicker = ({ column, isMultiple = false, schema, prefix, showTotalAndLi
|
|
|
4541
4595
|
setValue(colLabel, [...newSet]);
|
|
4542
4596
|
}, ...(selected ? { color: 'colorPalette.400/50' } : {}), children: !!renderDisplay === true
|
|
4543
4597
|
? renderDisplay(item)
|
|
4544
|
-
:
|
|
4598
|
+
: formI18n.t(item) }, `${colLabel}-${item}`));
|
|
4545
4599
|
}) }), isDirty && (jsx(Fragment, { children: dataList.length <= 0 && (jsx(Fragment, { children: enumPickerLabels?.emptySearchResult ??
|
|
4546
|
-
|
|
4600
|
+
formI18n.t('empty_search_result') })) }))] })] }) })] })] }));
|
|
4547
4601
|
};
|
|
4548
4602
|
|
|
4549
4603
|
function isEnteringWindow(_ref) {
|
|
@@ -4849,7 +4903,7 @@ function getText(_ref2) {
|
|
|
4849
4903
|
return source.getStringData(textMediaType);
|
|
4850
4904
|
}
|
|
4851
4905
|
|
|
4852
|
-
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder =
|
|
4906
|
+
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder = 'Drop files here or click to upload', }) => {
|
|
4853
4907
|
const ref = useRef(null);
|
|
4854
4908
|
const [isDraggedOver, setIsDraggedOver] = useState(false);
|
|
4855
4909
|
useEffect(() => {
|
|
@@ -4863,7 +4917,7 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4863
4917
|
onDrop: ({ source }) => {
|
|
4864
4918
|
const files = getFiles({ source });
|
|
4865
4919
|
const text = getText({ source });
|
|
4866
|
-
console.log(files, text,
|
|
4920
|
+
console.log(files, text, 'dfposa');
|
|
4867
4921
|
onDrop({ files, text });
|
|
4868
4922
|
},
|
|
4869
4923
|
});
|
|
@@ -4872,9 +4926,9 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4872
4926
|
function getColor(isDraggedOver) {
|
|
4873
4927
|
if (isDraggedOver) {
|
|
4874
4928
|
return {
|
|
4875
|
-
backgroundColor:
|
|
4929
|
+
backgroundColor: 'blue.400',
|
|
4876
4930
|
_dark: {
|
|
4877
|
-
backgroundColor:
|
|
4931
|
+
backgroundColor: 'blue.400',
|
|
4878
4932
|
},
|
|
4879
4933
|
};
|
|
4880
4934
|
}
|
|
@@ -4895,7 +4949,7 @@ const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }
|
|
|
4895
4949
|
const filesArray = [...event.target.files];
|
|
4896
4950
|
onDrop({ files: filesArray });
|
|
4897
4951
|
};
|
|
4898
|
-
return (jsxs(Grid, { ...getColor(isDraggedOver), ref: ref, cursor:
|
|
4952
|
+
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
4953
|
};
|
|
4900
4954
|
|
|
4901
4955
|
/**
|
|
@@ -4915,6 +4969,7 @@ function formatBytes(bytes) {
|
|
|
4915
4969
|
function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = false, onFetchFiles, labels, translate, colLabel, }) {
|
|
4916
4970
|
const [searchTerm, setSearchTerm] = useState('');
|
|
4917
4971
|
const [selectedFileId, setSelectedFileId] = useState('');
|
|
4972
|
+
const [failedImageIds, setFailedImageIds] = useState(new Set());
|
|
4918
4973
|
const { data: filesData, isLoading, isError, } = useQuery({
|
|
4919
4974
|
queryKey: ['file-picker-library', searchTerm],
|
|
4920
4975
|
queryFn: async () => {
|
|
@@ -4941,31 +4996,72 @@ function FilePickerDialog({ open, onClose, onSelect, title, filterImageOnly = fa
|
|
|
4941
4996
|
onClose();
|
|
4942
4997
|
setSelectedFileId('');
|
|
4943
4998
|
setSearchTerm('');
|
|
4999
|
+
setFailedImageIds(new Set());
|
|
5000
|
+
};
|
|
5001
|
+
const handleImageError = (fileId) => {
|
|
5002
|
+
setFailedImageIds((prev) => new Set(prev).add(fileId));
|
|
4944
5003
|
};
|
|
4945
5004
|
if (!onFetchFiles)
|
|
4946
5005
|
return null;
|
|
4947
5006
|
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
5007
|
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
|
-
|
|
5008
|
+
'Search files...', value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), bg: "bg.panel", border: "1px solid", borderColor: "border.default", colorPalette: "blue", _focus: {
|
|
5009
|
+
borderColor: 'colorPalette.500',
|
|
5010
|
+
_dark: {
|
|
5011
|
+
borderColor: 'colorPalette.400',
|
|
5012
|
+
},
|
|
5013
|
+
boxShadow: {
|
|
5014
|
+
base: '0 0 0 1px var(--chakra-colors-blue-500)',
|
|
5015
|
+
_dark: '0 0 0 1px var(--chakra-colors-blue-400)',
|
|
5016
|
+
},
|
|
4952
5017
|
}, 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
5018
|
translate(removeIndex(`${colLabel}.loading`)) ??
|
|
4954
|
-
'Loading files...' })] })), isError && (jsx(Box, { bg:
|
|
5019
|
+
'Loading files...' })] })), isError && (jsx(Box, { bg: { base: 'colorPalette.50', _dark: 'colorPalette.900/20' }, border: "1px solid", borderColor: {
|
|
5020
|
+
base: 'colorPalette.200',
|
|
5021
|
+
_dark: 'colorPalette.800',
|
|
5022
|
+
}, colorPalette: "red", borderRadius: "md", p: 4, children: jsx(Text, { color: {
|
|
5023
|
+
base: 'colorPalette.600',
|
|
5024
|
+
_dark: 'colorPalette.300',
|
|
5025
|
+
}, children: labels?.loadingFailed ??
|
|
4955
5026
|
translate(removeIndex(`${colLabel}.error.loading_failed`)) ??
|
|
4956
5027
|
'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
5028
|
translate(removeIndex(`${colLabel}.no_files_found`)) ??
|
|
4958
5029
|
'No files found' }) })) : (jsx(VStack, { align: "stretch", gap: 2, children: filteredFiles.map((file) => {
|
|
4959
5030
|
const isImage = /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(file.name);
|
|
4960
5031
|
const isSelected = selectedFileId === file.id;
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
5032
|
+
const imageFailed = failedImageIds.has(file.id);
|
|
5033
|
+
return (jsx(Box, { p: 3, border: "2px solid", borderColor: isSelected
|
|
5034
|
+
? {
|
|
5035
|
+
base: 'colorPalette.500',
|
|
5036
|
+
_dark: 'colorPalette.400',
|
|
5037
|
+
}
|
|
5038
|
+
: 'border.default', borderRadius: "md", bg: isSelected
|
|
5039
|
+
? {
|
|
5040
|
+
base: 'colorPalette.50',
|
|
5041
|
+
_dark: 'colorPalette.900/20',
|
|
5042
|
+
}
|
|
5043
|
+
: 'bg.panel', colorPalette: "blue", cursor: "pointer", onClick: () => setSelectedFileId(file.id), _hover: {
|
|
5044
|
+
borderColor: isSelected
|
|
5045
|
+
? {
|
|
5046
|
+
base: 'colorPalette.600',
|
|
5047
|
+
_dark: 'colorPalette.400',
|
|
5048
|
+
}
|
|
5049
|
+
: {
|
|
5050
|
+
base: 'colorPalette.300',
|
|
5051
|
+
_dark: 'colorPalette.400',
|
|
5052
|
+
},
|
|
5053
|
+
bg: isSelected
|
|
5054
|
+
? {
|
|
5055
|
+
base: 'colorPalette.100',
|
|
5056
|
+
_dark: 'colorPalette.800/30',
|
|
5057
|
+
}
|
|
5058
|
+
: 'bg.muted',
|
|
5059
|
+
}, 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
5060
|
? 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:
|
|
5061
|
+
: 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: {
|
|
5062
|
+
base: 'colorPalette.500',
|
|
5063
|
+
_dark: 'colorPalette.400',
|
|
5064
|
+
}, colorPalette: "blue", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: jsx(Text, { color: "white", fontSize: "xs", fontWeight: "bold", children: "\u2713" }) }))] }) }, file.id));
|
|
4969
5065
|
}) })) }))] }) }), 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
5066
|
translate(removeIndex(`${colLabel}.cancel`)) ??
|
|
4971
5067
|
'Cancel' }), jsx(Button$1, { colorPalette: "blue", onClick: handleSelect, disabled: !selectedFileId, children: labels?.select ??
|
|
@@ -4984,8 +5080,12 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
4984
5080
|
: [];
|
|
4985
5081
|
const colLabel = formI18n.colLabel;
|
|
4986
5082
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
5083
|
+
const [failedImageIds, setFailedImageIds] = useState(new Set());
|
|
4987
5084
|
const { onFetchFiles, enableMediaLibrary = false, filterImageOnly = false, } = filePicker || {};
|
|
4988
5085
|
const showMediaLibrary = enableMediaLibrary && !!onFetchFiles;
|
|
5086
|
+
const handleImageError = (fileIdentifier) => {
|
|
5087
|
+
setFailedImageIds((prev) => new Set(prev).add(fileIdentifier));
|
|
5088
|
+
};
|
|
4989
5089
|
const handleMediaLibrarySelect = (fileId) => {
|
|
4990
5090
|
const newFiles = [...currentFiles, fileId];
|
|
4991
5091
|
setValue(colLabel, newFiles);
|
|
@@ -5049,10 +5149,11 @@ const FilePicker = ({ column, schema, prefix }) => {
|
|
|
5049
5149
|
const fileSize = getFileSize(file);
|
|
5050
5150
|
const isImage = isImageFile(file);
|
|
5051
5151
|
const imageUrl = getImageUrl(file);
|
|
5052
|
-
|
|
5053
|
-
|
|
5152
|
+
const imageFailed = failedImageIds.has(fileIdentifier);
|
|
5153
|
+
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: {
|
|
5154
|
+
borderColor: 'colorPalette.300',
|
|
5054
5155
|
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));
|
|
5156
|
+
}, 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
5157
|
}) })] }));
|
|
5057
5158
|
};
|
|
5058
5159
|
|
|
@@ -18,6 +18,9 @@ export interface DataTableProps<TData = unknown> {
|
|
|
18
18
|
* Data array for the table.
|
|
19
19
|
*
|
|
20
20
|
* It will pass into as the data in `@tanstack/react-table`
|
|
21
|
+
* Do not toggle the data array, it will cause the table to re-render in infinite loop.
|
|
22
|
+
*
|
|
23
|
+
* @default []
|
|
21
24
|
*
|
|
22
25
|
*/
|
|
23
26
|
data: TData[];
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { TableControlsProps } from
|
|
2
|
-
import { TableProps } from
|
|
3
|
-
import { TableBodyProps } from
|
|
4
|
-
import { TableFooterProps } from
|
|
5
|
-
import { TableHeaderProps } from
|
|
1
|
+
import { TableControlsProps } from './controls/TableControls';
|
|
2
|
+
import { TableProps } from './display/Table';
|
|
3
|
+
import { TableBodyProps } from './display/TableBody';
|
|
4
|
+
import { TableFooterProps } from './display/TableFooter';
|
|
5
|
+
import { TableHeaderProps } from './display/TableHeader';
|
|
6
6
|
export interface DefaultTableProps {
|
|
7
7
|
showFooter?: boolean;
|
|
8
|
-
tableProps?: Omit<TableProps,
|
|
8
|
+
tableProps?: Omit<TableProps, 'children'>;
|
|
9
9
|
tableHeaderProps?: TableHeaderProps;
|
|
10
10
|
tableBodyProps?: TableBodyProps;
|
|
11
11
|
tableFooterProps?: TableFooterProps;
|
|
12
12
|
controlProps?: TableControlsProps;
|
|
13
|
-
variant?:
|
|
13
|
+
variant?: '' | 'greedy';
|
|
14
|
+
isLoading?: boolean;
|
|
14
15
|
}
|
|
15
|
-
export declare const DefaultTable: ({ showFooter, tableProps, tableHeaderProps, tableBodyProps, tableFooterProps, controlProps, variant, }: DefaultTableProps) => import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare const DefaultTable: ({ showFooter, tableProps, tableHeaderProps, tableBodyProps, tableFooterProps, controlProps, variant, isLoading, }: DefaultTableProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DefaultTableProps } from './DefaultTable';
|
|
2
|
+
export interface DefaultTableServerProps extends DefaultTableProps {
|
|
3
|
+
/**
|
|
4
|
+
* Optional isLoading prop to override auto-detected loading state.
|
|
5
|
+
* If not provided, will automatically detect from DataTableServerContext.
|
|
6
|
+
*/
|
|
7
|
+
isLoading?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* DefaultTableServer is a wrapper around DefaultTable that automatically
|
|
11
|
+
* detects server-side loading state from DataTableServerContext.
|
|
12
|
+
*
|
|
13
|
+
* Use this component when working with DataTableServer to automatically
|
|
14
|
+
* show skeleton loading state during data fetching.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <DataTableServer columns={columns} {...datatableServer}>
|
|
19
|
+
* <DefaultTableServer />
|
|
20
|
+
* </DataTableServer>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const DefaultTableServer: ({ isLoading: isLoadingOverride, ...props }: DefaultTableServerProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -7,4 +7,4 @@ export interface TableProps extends TableRootProps {
|
|
|
7
7
|
canResize?: boolean;
|
|
8
8
|
children: ReactNode;
|
|
9
9
|
}
|
|
10
|
-
export declare const Table: ({ children, emptyComponent, canResize, ...props }: TableProps) => string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
export declare const Table: ({ children, emptyComponent, canResize, showLoading, ...props }: TableProps) => string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null;
|