@trackunit/react-table 1.3.163 → 1.3.165
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/index.cjs.js +84 -59
- package/index.esm.js +87 -62
- package/package.json +11 -10
- package/src/menus/ColumnFilter.d.ts +3 -2
- package/src/menus/ColumnFilterItem.d.ts +32 -0
package/index.cjs.js
CHANGED
|
@@ -286,6 +286,77 @@ const cvaColumnFilterGrabbable = cssClassVarianceUtilities.cvaMerge(["flex", "it
|
|
|
286
286
|
},
|
|
287
287
|
});
|
|
288
288
|
|
|
289
|
+
const ItemTypes = {
|
|
290
|
+
COLUMN: "column",
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* Component for rendering an individual column filter item with drag-and-drop,
|
|
294
|
+
* toggle, and locking capabilities.
|
|
295
|
+
*
|
|
296
|
+
* @param {object} props - Props for the component.
|
|
297
|
+
* @param {string} props.name - The name of the column.
|
|
298
|
+
* @param {(toggled: boolean, event: ChangeEvent<HTMLInputElement>) => void} props.onToggle - Callback for when a column's toggled state changes.
|
|
299
|
+
* @param {boolean} props.toggled - Whether the column is toggled on or off.
|
|
300
|
+
* @param {boolean} props.disabled - Whether the toggle or drag functionality is disabled.
|
|
301
|
+
* @param {number} props.index - The index of the current column in the list.
|
|
302
|
+
* @param {(dragIndex: number, hoverIndex: number) => void} props.moveColumn - Function to move columns during drag-and-drop.
|
|
303
|
+
* @param {() => void} props.onDrop - Callback when a column is dropped.
|
|
304
|
+
* @param {() => void} props.onCancelDrop - Callback for canceling a drop action.
|
|
305
|
+
* @param {string} props.id - Unique identifier for the column.
|
|
306
|
+
* @param {boolean} [props.isSortDisabled] - Optional flag to disable sorting.
|
|
307
|
+
* @returns {JSX.Element} A React component rendering the column filter item.
|
|
308
|
+
*/
|
|
309
|
+
const ColumnFilterItem = ({ name, onToggle, toggled, disabled, index, moveColumn, onDrop, onCancelDrop, id, isSortDisabled, }) => {
|
|
310
|
+
const ref = react.useRef(null);
|
|
311
|
+
const [, drop] = reactDnd.useDrop({
|
|
312
|
+
accept: ItemTypes.COLUMN,
|
|
313
|
+
hover(item, monitor) {
|
|
314
|
+
if (!ref.current) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const dragIndex = item.index;
|
|
318
|
+
const hoverIndex = index;
|
|
319
|
+
if (dragIndex === hoverIndex) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const hoverBoundingRect = ref.current.getBoundingClientRect();
|
|
323
|
+
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
|
|
324
|
+
const clientOffset = monitor.getClientOffset();
|
|
325
|
+
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
|
|
326
|
+
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
moveColumn(dragIndex, hoverIndex);
|
|
333
|
+
item.index = hoverIndex;
|
|
334
|
+
},
|
|
335
|
+
drop(item, monitor) {
|
|
336
|
+
onDrop();
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
const [{ isDragging }, drag] = reactDnd.useDrag({
|
|
340
|
+
type: ItemTypes.COLUMN,
|
|
341
|
+
item: { type: ItemTypes.COLUMN, id, index },
|
|
342
|
+
canDrag: !isSortDisabled,
|
|
343
|
+
collect: (monitor) => ({
|
|
344
|
+
isDragging: monitor.isDragging(),
|
|
345
|
+
}),
|
|
346
|
+
end(draggedItem, monitor) {
|
|
347
|
+
if (!monitor.didDrop()) {
|
|
348
|
+
onCancelDrop();
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
const opacity = isDragging ? 0 : 1;
|
|
353
|
+
drag(drop(ref));
|
|
354
|
+
return (jsxRuntime.jsxs("div", { className: reactComponents.cvaInteractableItem({
|
|
355
|
+
selected: false,
|
|
356
|
+
className: "grid w-full grid-cols-[min-content,1fr,min-content] items-center gap-2 py-1",
|
|
357
|
+
}), ref: ref, style: { opacity: opacity }, children: [jsxRuntime.jsx("div", { className: cvaColumnFilterGrabbable({ disabled: isSortDisabled }), children: jsxRuntime.jsx(reactComponents.Icon, { color: "secondary", name: "EllipsisDrag", size: "small" }) }), jsxRuntime.jsxs("label", { className: "grid w-full grid-cols-[1fr,min-content] items-center gap-2", htmlFor: id, children: [jsxRuntime.jsxs("div", { className: "grid w-full grid-cols-[1fr,min-content] items-center", children: [jsxRuntime.jsx(reactComponents.Text, { className: reactFormComponents.cvaLabel(), children: name }), disabled ? jsxRuntime.jsx(reactComponents.Icon, { name: "LockClosed", size: "small" }) : null] }), jsxRuntime.jsx(reactFormComponents.ToggleSwitch, { disabled: disabled, id: id, onChange: (isToggled, event) => event && onToggle(isToggled, event), showInputFocus: false, size: "small", toggled: toggled })] })] }));
|
|
358
|
+
};
|
|
359
|
+
|
|
289
360
|
/**
|
|
290
361
|
* ColumnFilter component for managing visibility and order of table columns.
|
|
291
362
|
*
|
|
@@ -294,7 +365,7 @@ const cvaColumnFilterGrabbable = cssClassVarianceUtilities.cvaMerge(["flex", "it
|
|
|
294
365
|
* @param {ColumnFilterProps<TColumnFilter, TColumnFilterValue>} props - The props object containing necessary properties.
|
|
295
366
|
* @returns {ReactElement | null} A React JSX element representing the ColumnFilter component or null if columns are not provided.
|
|
296
367
|
*/
|
|
297
|
-
const ColumnFilter = ({ columns, setColumnOrder, defaultColumnOrder = [], columnOrder, onUserEvent, }) => {
|
|
368
|
+
const ColumnFilter = ({ columns, setColumnOrder, defaultColumnOrder = [], columnOrder, onUserEvent, setColumnSize, }) => {
|
|
298
369
|
const [t] = useTranslation();
|
|
299
370
|
const initialSetupRef = react.useRef(false);
|
|
300
371
|
const [searchText, setSearchText] = react.useState("");
|
|
@@ -304,11 +375,18 @@ const ColumnFilter = ({ columns, setColumnOrder, defaultColumnOrder = [], column
|
|
|
304
375
|
initialSetupRef.current = true;
|
|
305
376
|
}
|
|
306
377
|
}, [columnOrder, defaultColumnOrder, setColumnOrder]);
|
|
307
|
-
const
|
|
308
|
-
|
|
378
|
+
const resetColumnState = react.useCallback(() => {
|
|
379
|
+
const sizes = {};
|
|
380
|
+
columns.forEach(column => {
|
|
381
|
+
if (column.columnDef.size) {
|
|
382
|
+
sizes[column.id] = column.columnDef.size;
|
|
383
|
+
}
|
|
384
|
+
column.toggleVisibility(!column.columnDef.meta?.hiddenByDefault);
|
|
385
|
+
column.pin(column.columnDef.meta?.pinned ?? false);
|
|
386
|
+
});
|
|
309
387
|
setColumnOrder(defaultColumnOrder);
|
|
310
|
-
|
|
311
|
-
}, [columns, defaultColumnOrder, setColumnOrder]);
|
|
388
|
+
setColumnSize(sizes);
|
|
389
|
+
}, [columns, defaultColumnOrder, setColumnOrder, setColumnSize]);
|
|
312
390
|
const sortedColumns = react.useMemo(() => {
|
|
313
391
|
let filteredColumns = columns;
|
|
314
392
|
if (searchText.trim() !== "") {
|
|
@@ -325,7 +403,7 @@ const ColumnFilter = ({ columns, setColumnOrder, defaultColumnOrder = [], column
|
|
|
325
403
|
const visibleColumnsCount = react.useMemo(() => {
|
|
326
404
|
return columns.filter(col => col.getIsVisible()).length;
|
|
327
405
|
}, [columns]);
|
|
328
|
-
return (jsxRuntime.jsx(reactDnd.DndProvider, { backend: reactDndHtml5Backend.HTML5Backend, children: jsxRuntime.jsx(reactComponents.Tooltip, { label: t("table.columnFilters.tooltip"), placement: "bottom", children: jsxRuntime.jsxs(reactComponents.Popover, { placement: "bottom-start", children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx(reactComponents.Button, { prefix: jsxRuntime.jsx(reactComponents.Icon, { name: "ViewColumns", size: "small" }), size: "small", variant: "secondary", children: jsxRuntime.jsx("span", { className: "hidden md:block", children: t("table.columnFilters.columns") }) }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { children: () => (jsxRuntime.jsxs(reactComponents.MenuList, { className: "relative max-h-[55vh] w-72 overflow-y-auto", children: [jsxRuntime.jsxs("div", { className: "mb-2 flex items-center gap-1", children: [jsxRuntime.jsx(reactFormComponents.Search, { autoFocus: true, className: "flex-1", fieldSize: "small", id: "column-search", onChange: e => setSearchText(e.currentTarget.value.toLowerCase()), onClear: () => setSearchText(""), placeholder: "Search", value: searchText }), jsxRuntime.jsx(reactComponents.Button, { onClick:
|
|
406
|
+
return (jsxRuntime.jsx(reactDnd.DndProvider, { backend: reactDndHtml5Backend.HTML5Backend, children: jsxRuntime.jsx(reactComponents.Tooltip, { label: t("table.columnFilters.tooltip"), placement: "bottom", children: jsxRuntime.jsxs(reactComponents.Popover, { placement: "bottom-start", children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx(reactComponents.Button, { prefix: jsxRuntime.jsx(reactComponents.Icon, { name: "ViewColumns", size: "small" }), size: "small", variant: "secondary", children: jsxRuntime.jsx("span", { className: "hidden md:block", children: t("table.columnFilters.columns") }) }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { children: () => (jsxRuntime.jsxs(reactComponents.MenuList, { className: "relative max-h-[55vh] w-72 overflow-y-auto", children: [jsxRuntime.jsxs("div", { className: "mb-2 flex items-center gap-1", children: [jsxRuntime.jsx(reactFormComponents.Search, { autoFocus: true, className: "flex-1", fieldSize: "small", id: "column-search", onChange: e => setSearchText(e.currentTarget.value.toLowerCase()), onClear: () => setSearchText(""), placeholder: "Search", value: searchText }), jsxRuntime.jsx(reactComponents.Button, { dataTestId: "resetColumnState", onClick: resetColumnState, size: "small", variant: "ghost-neutral", children: t("layout.actions.reset") })] }), jsxRuntime.jsx(ColumnFiltersDragAndDrop, { columns: sortedColumns, isSortDisabled: !!searchText, onUserEvent: onUserEvent, setColumnOrder: setColumnOrder, visibleColumnsCount: visibleColumnsCount })] })) })] }) }) }));
|
|
329
407
|
};
|
|
330
408
|
const ColumnFiltersDragAndDrop = ({ columns, setColumnOrder, onUserEvent, isSortDisabled, visibleColumnsCount, }) => {
|
|
331
409
|
const [localColumns, setLocalColumns] = react.useState(columns);
|
|
@@ -369,59 +447,6 @@ const ColumnFiltersDragAndDrop = ({ columns, setColumnOrder, onUserEvent, isSort
|
|
|
369
447
|
}, toggled: isVisible }, column.id));
|
|
370
448
|
}) }));
|
|
371
449
|
};
|
|
372
|
-
const ItemTypes = {
|
|
373
|
-
COLUMN: "column",
|
|
374
|
-
};
|
|
375
|
-
const ColumnFilterItem = ({ name, onToggle, toggled, disabled, index, moveColumn, onDrop, onCancelDrop, id, isSortDisabled, }) => {
|
|
376
|
-
const ref = react.useRef(null);
|
|
377
|
-
const [, drop] = reactDnd.useDrop({
|
|
378
|
-
accept: ItemTypes.COLUMN,
|
|
379
|
-
hover(item, monitor) {
|
|
380
|
-
if (!ref.current) {
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
const dragIndex = item.index;
|
|
384
|
-
const hoverIndex = index;
|
|
385
|
-
if (dragIndex === hoverIndex) {
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
const hoverBoundingRect = ref.current.getBoundingClientRect();
|
|
389
|
-
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
|
|
390
|
-
const clientOffset = monitor.getClientOffset();
|
|
391
|
-
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
|
|
392
|
-
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
moveColumn(dragIndex, hoverIndex);
|
|
399
|
-
item.index = hoverIndex;
|
|
400
|
-
},
|
|
401
|
-
drop(item, monitor) {
|
|
402
|
-
onDrop();
|
|
403
|
-
},
|
|
404
|
-
});
|
|
405
|
-
const [{ isDragging }, drag] = reactDnd.useDrag({
|
|
406
|
-
type: ItemTypes.COLUMN,
|
|
407
|
-
item: { type: ItemTypes.COLUMN, id, index },
|
|
408
|
-
canDrag: !isSortDisabled,
|
|
409
|
-
collect: (monitor) => ({
|
|
410
|
-
isDragging: monitor.isDragging(),
|
|
411
|
-
}),
|
|
412
|
-
end(draggedItem, monitor) {
|
|
413
|
-
if (!monitor.didDrop()) {
|
|
414
|
-
onCancelDrop();
|
|
415
|
-
}
|
|
416
|
-
},
|
|
417
|
-
});
|
|
418
|
-
const opacity = isDragging ? 0 : 1;
|
|
419
|
-
drag(drop(ref));
|
|
420
|
-
return (jsxRuntime.jsxs("div", { className: reactComponents.cvaInteractableItem({
|
|
421
|
-
selected: false,
|
|
422
|
-
className: "grid w-full grid-cols-[min-content,1fr,min-content] items-center gap-2 py-1",
|
|
423
|
-
}), ref: ref, style: { opacity: opacity }, children: [jsxRuntime.jsx("div", { className: cvaColumnFilterGrabbable({ disabled: isSortDisabled }), children: jsxRuntime.jsx(reactComponents.Icon, { color: "secondary", name: "EllipsisDrag", size: "small" }) }), jsxRuntime.jsxs("label", { className: "grid w-full grid-cols-[1fr,min-content] items-center gap-2", htmlFor: id, children: [jsxRuntime.jsxs("div", { className: "grid w-full grid-cols-[1fr,min-content] items-center", children: [jsxRuntime.jsx(reactComponents.Text, { className: reactFormComponents.cvaLabel(), children: name }), disabled ? jsxRuntime.jsx(reactComponents.Icon, { name: "LockClosed", size: "small" }) : null] }), jsxRuntime.jsx(reactFormComponents.ToggleSwitch, { disabled: disabled, id: id, onChange: (isToggled, event) => event && onToggle(isToggled, event), showInputFocus: false, size: "small", toggled: toggled })] })] }));
|
|
424
|
-
};
|
|
425
450
|
|
|
426
451
|
/**
|
|
427
452
|
* RowSpacing component for managing the density of table rows.
|
package/index.esm.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
|
|
3
|
-
import { MenuItem, Icon, Button, useOverflowItems, MoreMenu, MenuList, Spacer, Tooltip, Popover, PopoverTrigger, PopoverContent,
|
|
3
|
+
import { MenuItem, Icon, Button, useOverflowItems, MoreMenu, MenuList, Spacer, cvaInteractableItem, Text, Tooltip, Popover, PopoverTrigger, PopoverContent, IconButton, Card, Spinner, EmptyState } from '@trackunit/react-components';
|
|
4
4
|
import { objectValues, nonNullable, objectKeys, objectEntries } from '@trackunit/shared-utils';
|
|
5
5
|
import { useMemo, Children, cloneElement, useRef, useState, useEffect, useCallback, createElement } from 'react';
|
|
6
6
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
7
7
|
import { Link } from '@tanstack/react-router';
|
|
8
|
-
import {
|
|
8
|
+
import { cvaLabel, ToggleSwitch, Search, RadioGroup, RadioItem, Checkbox } from '@trackunit/react-form-components';
|
|
9
9
|
import update from 'immutability-helper';
|
|
10
|
-
import {
|
|
10
|
+
import { useDrop, useDrag, DndProvider } from 'react-dnd';
|
|
11
11
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
12
12
|
import { flexRender, createColumnHelper, useReactTable, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
|
|
13
13
|
export { createColumnHelper } from '@tanstack/react-table';
|
|
@@ -285,6 +285,77 @@ const cvaColumnFilterGrabbable = cvaMerge(["flex", "items-center", "justify-cent
|
|
|
285
285
|
},
|
|
286
286
|
});
|
|
287
287
|
|
|
288
|
+
const ItemTypes = {
|
|
289
|
+
COLUMN: "column",
|
|
290
|
+
};
|
|
291
|
+
/**
|
|
292
|
+
* Component for rendering an individual column filter item with drag-and-drop,
|
|
293
|
+
* toggle, and locking capabilities.
|
|
294
|
+
*
|
|
295
|
+
* @param {object} props - Props for the component.
|
|
296
|
+
* @param {string} props.name - The name of the column.
|
|
297
|
+
* @param {(toggled: boolean, event: ChangeEvent<HTMLInputElement>) => void} props.onToggle - Callback for when a column's toggled state changes.
|
|
298
|
+
* @param {boolean} props.toggled - Whether the column is toggled on or off.
|
|
299
|
+
* @param {boolean} props.disabled - Whether the toggle or drag functionality is disabled.
|
|
300
|
+
* @param {number} props.index - The index of the current column in the list.
|
|
301
|
+
* @param {(dragIndex: number, hoverIndex: number) => void} props.moveColumn - Function to move columns during drag-and-drop.
|
|
302
|
+
* @param {() => void} props.onDrop - Callback when a column is dropped.
|
|
303
|
+
* @param {() => void} props.onCancelDrop - Callback for canceling a drop action.
|
|
304
|
+
* @param {string} props.id - Unique identifier for the column.
|
|
305
|
+
* @param {boolean} [props.isSortDisabled] - Optional flag to disable sorting.
|
|
306
|
+
* @returns {JSX.Element} A React component rendering the column filter item.
|
|
307
|
+
*/
|
|
308
|
+
const ColumnFilterItem = ({ name, onToggle, toggled, disabled, index, moveColumn, onDrop, onCancelDrop, id, isSortDisabled, }) => {
|
|
309
|
+
const ref = useRef(null);
|
|
310
|
+
const [, drop] = useDrop({
|
|
311
|
+
accept: ItemTypes.COLUMN,
|
|
312
|
+
hover(item, monitor) {
|
|
313
|
+
if (!ref.current) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const dragIndex = item.index;
|
|
317
|
+
const hoverIndex = index;
|
|
318
|
+
if (dragIndex === hoverIndex) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const hoverBoundingRect = ref.current.getBoundingClientRect();
|
|
322
|
+
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
|
|
323
|
+
const clientOffset = monitor.getClientOffset();
|
|
324
|
+
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
|
|
325
|
+
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
moveColumn(dragIndex, hoverIndex);
|
|
332
|
+
item.index = hoverIndex;
|
|
333
|
+
},
|
|
334
|
+
drop(item, monitor) {
|
|
335
|
+
onDrop();
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
const [{ isDragging }, drag] = useDrag({
|
|
339
|
+
type: ItemTypes.COLUMN,
|
|
340
|
+
item: { type: ItemTypes.COLUMN, id, index },
|
|
341
|
+
canDrag: !isSortDisabled,
|
|
342
|
+
collect: (monitor) => ({
|
|
343
|
+
isDragging: monitor.isDragging(),
|
|
344
|
+
}),
|
|
345
|
+
end(draggedItem, monitor) {
|
|
346
|
+
if (!monitor.didDrop()) {
|
|
347
|
+
onCancelDrop();
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
const opacity = isDragging ? 0 : 1;
|
|
352
|
+
drag(drop(ref));
|
|
353
|
+
return (jsxs("div", { className: cvaInteractableItem({
|
|
354
|
+
selected: false,
|
|
355
|
+
className: "grid w-full grid-cols-[min-content,1fr,min-content] items-center gap-2 py-1",
|
|
356
|
+
}), ref: ref, style: { opacity: opacity }, children: [jsx("div", { className: cvaColumnFilterGrabbable({ disabled: isSortDisabled }), children: jsx(Icon, { color: "secondary", name: "EllipsisDrag", size: "small" }) }), jsxs("label", { className: "grid w-full grid-cols-[1fr,min-content] items-center gap-2", htmlFor: id, children: [jsxs("div", { className: "grid w-full grid-cols-[1fr,min-content] items-center", children: [jsx(Text, { className: cvaLabel(), children: name }), disabled ? jsx(Icon, { name: "LockClosed", size: "small" }) : null] }), jsx(ToggleSwitch, { disabled: disabled, id: id, onChange: (isToggled, event) => event && onToggle(isToggled, event), showInputFocus: false, size: "small", toggled: toggled })] })] }));
|
|
357
|
+
};
|
|
358
|
+
|
|
288
359
|
/**
|
|
289
360
|
* ColumnFilter component for managing visibility and order of table columns.
|
|
290
361
|
*
|
|
@@ -293,7 +364,7 @@ const cvaColumnFilterGrabbable = cvaMerge(["flex", "items-center", "justify-cent
|
|
|
293
364
|
* @param {ColumnFilterProps<TColumnFilter, TColumnFilterValue>} props - The props object containing necessary properties.
|
|
294
365
|
* @returns {ReactElement | null} A React JSX element representing the ColumnFilter component or null if columns are not provided.
|
|
295
366
|
*/
|
|
296
|
-
const ColumnFilter = ({ columns, setColumnOrder, defaultColumnOrder = [], columnOrder, onUserEvent, }) => {
|
|
367
|
+
const ColumnFilter = ({ columns, setColumnOrder, defaultColumnOrder = [], columnOrder, onUserEvent, setColumnSize, }) => {
|
|
297
368
|
const [t] = useTranslation();
|
|
298
369
|
const initialSetupRef = useRef(false);
|
|
299
370
|
const [searchText, setSearchText] = useState("");
|
|
@@ -303,11 +374,18 @@ const ColumnFilter = ({ columns, setColumnOrder, defaultColumnOrder = [], column
|
|
|
303
374
|
initialSetupRef.current = true;
|
|
304
375
|
}
|
|
305
376
|
}, [columnOrder, defaultColumnOrder, setColumnOrder]);
|
|
306
|
-
const
|
|
307
|
-
|
|
377
|
+
const resetColumnState = useCallback(() => {
|
|
378
|
+
const sizes = {};
|
|
379
|
+
columns.forEach(column => {
|
|
380
|
+
if (column.columnDef.size) {
|
|
381
|
+
sizes[column.id] = column.columnDef.size;
|
|
382
|
+
}
|
|
383
|
+
column.toggleVisibility(!column.columnDef.meta?.hiddenByDefault);
|
|
384
|
+
column.pin(column.columnDef.meta?.pinned ?? false);
|
|
385
|
+
});
|
|
308
386
|
setColumnOrder(defaultColumnOrder);
|
|
309
|
-
|
|
310
|
-
}, [columns, defaultColumnOrder, setColumnOrder]);
|
|
387
|
+
setColumnSize(sizes);
|
|
388
|
+
}, [columns, defaultColumnOrder, setColumnOrder, setColumnSize]);
|
|
311
389
|
const sortedColumns = useMemo(() => {
|
|
312
390
|
let filteredColumns = columns;
|
|
313
391
|
if (searchText.trim() !== "") {
|
|
@@ -324,7 +402,7 @@ const ColumnFilter = ({ columns, setColumnOrder, defaultColumnOrder = [], column
|
|
|
324
402
|
const visibleColumnsCount = useMemo(() => {
|
|
325
403
|
return columns.filter(col => col.getIsVisible()).length;
|
|
326
404
|
}, [columns]);
|
|
327
|
-
return (jsx(DndProvider, { backend: HTML5Backend, children: jsx(Tooltip, { label: t("table.columnFilters.tooltip"), placement: "bottom", children: jsxs(Popover, { placement: "bottom-start", children: [jsx(PopoverTrigger, { children: jsx(Button, { prefix: jsx(Icon, { name: "ViewColumns", size: "small" }), size: "small", variant: "secondary", children: jsx("span", { className: "hidden md:block", children: t("table.columnFilters.columns") }) }) }), jsx(PopoverContent, { children: () => (jsxs(MenuList, { className: "relative max-h-[55vh] w-72 overflow-y-auto", children: [jsxs("div", { className: "mb-2 flex items-center gap-1", children: [jsx(Search, { autoFocus: true, className: "flex-1", fieldSize: "small", id: "column-search", onChange: e => setSearchText(e.currentTarget.value.toLowerCase()), onClear: () => setSearchText(""), placeholder: "Search", value: searchText }), jsx(Button, { onClick:
|
|
405
|
+
return (jsx(DndProvider, { backend: HTML5Backend, children: jsx(Tooltip, { label: t("table.columnFilters.tooltip"), placement: "bottom", children: jsxs(Popover, { placement: "bottom-start", children: [jsx(PopoverTrigger, { children: jsx(Button, { prefix: jsx(Icon, { name: "ViewColumns", size: "small" }), size: "small", variant: "secondary", children: jsx("span", { className: "hidden md:block", children: t("table.columnFilters.columns") }) }) }), jsx(PopoverContent, { children: () => (jsxs(MenuList, { className: "relative max-h-[55vh] w-72 overflow-y-auto", children: [jsxs("div", { className: "mb-2 flex items-center gap-1", children: [jsx(Search, { autoFocus: true, className: "flex-1", fieldSize: "small", id: "column-search", onChange: e => setSearchText(e.currentTarget.value.toLowerCase()), onClear: () => setSearchText(""), placeholder: "Search", value: searchText }), jsx(Button, { dataTestId: "resetColumnState", onClick: resetColumnState, size: "small", variant: "ghost-neutral", children: t("layout.actions.reset") })] }), jsx(ColumnFiltersDragAndDrop, { columns: sortedColumns, isSortDisabled: !!searchText, onUserEvent: onUserEvent, setColumnOrder: setColumnOrder, visibleColumnsCount: visibleColumnsCount })] })) })] }) }) }));
|
|
328
406
|
};
|
|
329
407
|
const ColumnFiltersDragAndDrop = ({ columns, setColumnOrder, onUserEvent, isSortDisabled, visibleColumnsCount, }) => {
|
|
330
408
|
const [localColumns, setLocalColumns] = useState(columns);
|
|
@@ -368,59 +446,6 @@ const ColumnFiltersDragAndDrop = ({ columns, setColumnOrder, onUserEvent, isSort
|
|
|
368
446
|
}, toggled: isVisible }, column.id));
|
|
369
447
|
}) }));
|
|
370
448
|
};
|
|
371
|
-
const ItemTypes = {
|
|
372
|
-
COLUMN: "column",
|
|
373
|
-
};
|
|
374
|
-
const ColumnFilterItem = ({ name, onToggle, toggled, disabled, index, moveColumn, onDrop, onCancelDrop, id, isSortDisabled, }) => {
|
|
375
|
-
const ref = useRef(null);
|
|
376
|
-
const [, drop] = useDrop({
|
|
377
|
-
accept: ItemTypes.COLUMN,
|
|
378
|
-
hover(item, monitor) {
|
|
379
|
-
if (!ref.current) {
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
const dragIndex = item.index;
|
|
383
|
-
const hoverIndex = index;
|
|
384
|
-
if (dragIndex === hoverIndex) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
const hoverBoundingRect = ref.current.getBoundingClientRect();
|
|
388
|
-
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
|
|
389
|
-
const clientOffset = monitor.getClientOffset();
|
|
390
|
-
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
|
|
391
|
-
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
moveColumn(dragIndex, hoverIndex);
|
|
398
|
-
item.index = hoverIndex;
|
|
399
|
-
},
|
|
400
|
-
drop(item, monitor) {
|
|
401
|
-
onDrop();
|
|
402
|
-
},
|
|
403
|
-
});
|
|
404
|
-
const [{ isDragging }, drag] = useDrag({
|
|
405
|
-
type: ItemTypes.COLUMN,
|
|
406
|
-
item: { type: ItemTypes.COLUMN, id, index },
|
|
407
|
-
canDrag: !isSortDisabled,
|
|
408
|
-
collect: (monitor) => ({
|
|
409
|
-
isDragging: monitor.isDragging(),
|
|
410
|
-
}),
|
|
411
|
-
end(draggedItem, monitor) {
|
|
412
|
-
if (!monitor.didDrop()) {
|
|
413
|
-
onCancelDrop();
|
|
414
|
-
}
|
|
415
|
-
},
|
|
416
|
-
});
|
|
417
|
-
const opacity = isDragging ? 0 : 1;
|
|
418
|
-
drag(drop(ref));
|
|
419
|
-
return (jsxs("div", { className: cvaInteractableItem({
|
|
420
|
-
selected: false,
|
|
421
|
-
className: "grid w-full grid-cols-[min-content,1fr,min-content] items-center gap-2 py-1",
|
|
422
|
-
}), ref: ref, style: { opacity: opacity }, children: [jsx("div", { className: cvaColumnFilterGrabbable({ disabled: isSortDisabled }), children: jsx(Icon, { color: "secondary", name: "EllipsisDrag", size: "small" }) }), jsxs("label", { className: "grid w-full grid-cols-[1fr,min-content] items-center gap-2", htmlFor: id, children: [jsxs("div", { className: "grid w-full grid-cols-[1fr,min-content] items-center", children: [jsx(Text, { className: cvaLabel(), children: name }), disabled ? jsx(Icon, { name: "LockClosed", size: "small" }) : null] }), jsx(ToggleSwitch, { disabled: disabled, id: id, onChange: (isToggled, event) => event && onToggle(isToggled, event), showInputFocus: false, size: "small", toggled: toggled })] })] }));
|
|
423
|
-
};
|
|
424
449
|
|
|
425
450
|
/**
|
|
426
451
|
* RowSpacing component for managing the density of table rows.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-table",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.165",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -15,15 +15,16 @@
|
|
|
15
15
|
"jest-fetch-mock": "^3.0.3",
|
|
16
16
|
"@tanstack/react-router": "1.114.29",
|
|
17
17
|
"tailwind-merge": "^2.0.0",
|
|
18
|
-
"@trackunit/react-components": "1.4.
|
|
19
|
-
"@trackunit/shared-utils": "1.5.
|
|
20
|
-
"@trackunit/css-class-variance-utilities": "1.3.
|
|
21
|
-
"@trackunit/ui-icons": "1.3.
|
|
22
|
-
"@trackunit/react-table-base-components": "1.3.
|
|
23
|
-
"@trackunit/react-table-pagination": "1.3.
|
|
24
|
-
"@trackunit/react-form-components": "1.3.
|
|
25
|
-
"@trackunit/i18n-library-translation": "1.3.
|
|
26
|
-
"@trackunit/react-core-contexts-api": "1.4.
|
|
18
|
+
"@trackunit/react-components": "1.4.133",
|
|
19
|
+
"@trackunit/shared-utils": "1.5.110",
|
|
20
|
+
"@trackunit/css-class-variance-utilities": "1.3.110",
|
|
21
|
+
"@trackunit/ui-icons": "1.3.112",
|
|
22
|
+
"@trackunit/react-table-base-components": "1.3.151",
|
|
23
|
+
"@trackunit/react-table-pagination": "1.3.111",
|
|
24
|
+
"@trackunit/react-form-components": "1.3.151",
|
|
25
|
+
"@trackunit/i18n-library-translation": "1.3.124",
|
|
26
|
+
"@trackunit/react-core-contexts-api": "1.4.116",
|
|
27
|
+
"@trackunit/react-test-setup": "1.0.0"
|
|
27
28
|
},
|
|
28
29
|
"module": "./index.esm.js",
|
|
29
30
|
"main": "./index.cjs.js",
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Column, ColumnOrderState, Updater } from "@tanstack/react-table";
|
|
1
|
+
import { Column, ColumnOrderState, ColumnSizingState, Updater } from "@tanstack/react-table";
|
|
2
2
|
export interface ColumnFilterProps<TColumnFilter extends object, TColumnFilterValue> {
|
|
3
3
|
columns: Column<TColumnFilter, TColumnFilterValue>[];
|
|
4
4
|
defaultColumnOrder: ColumnOrderState;
|
|
5
5
|
columnOrder?: ColumnOrderState;
|
|
6
6
|
setColumnOrder: (updater: Updater<ColumnOrderState>) => void;
|
|
7
7
|
onUserEvent?: (event: "Column Reordering" | "Column Filter", payload: Record<string, unknown>) => void;
|
|
8
|
+
setColumnSize: (updater: Updater<ColumnSizingState>) => void;
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* ColumnFilter component for managing visibility and order of table columns.
|
|
@@ -14,7 +15,7 @@ export interface ColumnFilterProps<TColumnFilter extends object, TColumnFilterVa
|
|
|
14
15
|
* @param {ColumnFilterProps<TColumnFilter, TColumnFilterValue>} props - The props object containing necessary properties.
|
|
15
16
|
* @returns {ReactElement | null} A React JSX element representing the ColumnFilter component or null if columns are not provided.
|
|
16
17
|
*/
|
|
17
|
-
export declare const ColumnFilter: <TColumnFilter extends object, TColumnFilterValue>({ columns, setColumnOrder, defaultColumnOrder, columnOrder, onUserEvent, }: ColumnFilterProps<TColumnFilter, TColumnFilterValue>) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare const ColumnFilter: <TColumnFilter extends object, TColumnFilterValue>({ columns, setColumnOrder, defaultColumnOrder, columnOrder, onUserEvent, setColumnSize, }: ColumnFilterProps<TColumnFilter, TColumnFilterValue>) => import("react/jsx-runtime").JSX.Element;
|
|
18
19
|
export interface ColumnFiltersDragAndDropProps<TColumnFiltersDragAndDrop extends object, TColumnFiltersDragAndDropValue> {
|
|
19
20
|
columns: Column<TColumnFiltersDragAndDrop, TColumnFiltersDragAndDropValue>[];
|
|
20
21
|
setColumnOrder: (updater: Updater<ColumnOrderState>) => void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ChangeEvent } from "react";
|
|
2
|
+
interface ColumnFilterItemProps {
|
|
3
|
+
name: string;
|
|
4
|
+
onToggle: (toggled: boolean, event: ChangeEvent<HTMLInputElement>) => void;
|
|
5
|
+
toggled: boolean;
|
|
6
|
+
disabled: boolean;
|
|
7
|
+
onDrop: () => void;
|
|
8
|
+
onCancelDrop: () => void;
|
|
9
|
+
moveColumn: (dragIndex: number, hoverIndex: number) => void;
|
|
10
|
+
index: number;
|
|
11
|
+
id: string;
|
|
12
|
+
isSortDisabled?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Component for rendering an individual column filter item with drag-and-drop,
|
|
16
|
+
* toggle, and locking capabilities.
|
|
17
|
+
*
|
|
18
|
+
* @param {object} props - Props for the component.
|
|
19
|
+
* @param {string} props.name - The name of the column.
|
|
20
|
+
* @param {(toggled: boolean, event: ChangeEvent<HTMLInputElement>) => void} props.onToggle - Callback for when a column's toggled state changes.
|
|
21
|
+
* @param {boolean} props.toggled - Whether the column is toggled on or off.
|
|
22
|
+
* @param {boolean} props.disabled - Whether the toggle or drag functionality is disabled.
|
|
23
|
+
* @param {number} props.index - The index of the current column in the list.
|
|
24
|
+
* @param {(dragIndex: number, hoverIndex: number) => void} props.moveColumn - Function to move columns during drag-and-drop.
|
|
25
|
+
* @param {() => void} props.onDrop - Callback when a column is dropped.
|
|
26
|
+
* @param {() => void} props.onCancelDrop - Callback for canceling a drop action.
|
|
27
|
+
* @param {string} props.id - Unique identifier for the column.
|
|
28
|
+
* @param {boolean} [props.isSortDisabled] - Optional flag to disable sorting.
|
|
29
|
+
* @returns {JSX.Element} A React component rendering the column filter item.
|
|
30
|
+
*/
|
|
31
|
+
export declare const ColumnFilterItem: ({ name, onToggle, toggled, disabled, index, moveColumn, onDrop, onCancelDrop, id, isSortDisabled, }: ColumnFilterItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
export {};
|