mantine-react-table
Version:
A fully featured Mantine implementation of TanStack React Table V8, written from the ground up in TypeScript.
899 lines (876 loc) • 178 kB
JavaScript
import React, { useMemo, Fragment, useState, useEffect, useRef, memo, useCallback, useLayoutEffect } from 'react';
import { aggregationFns, filterFns, sortingFns, useReactTable, getCoreRowModel, getExpandedRowModel, getFacetedRowModel, getFilteredRowModel, getGroupedRowModel, getPaginationRowModel, getSortedRowModel } from '@tanstack/react-table';
import { rankItem, rankings, compareItems } from '@tanstack/match-sorter-utils';
import { IconArrowAutofitContent, IconArrowDown, IconArrowsSort, IconBoxMultiple, IconChevronDown, IconChevronLeft, IconChevronRight, IconChevronUp, IconChevronsDown, IconCircleOff, IconCircleX, IconClearAll, IconColumns, IconDeviceFloppy, IconDots, IconDotsVertical, IconEdit, IconEyeOff, IconFilter, IconFilterOff, IconGripHorizontal, IconMaximize, IconMinimize, IconPinned, IconPinnedOff, IconSearch, IconSortAscending, IconSortDescending, IconTallymark1, IconTallymark2, IconTallymark3, IconTallymark4, IconTallymarks, IconX } from '@tabler/icons';
import { Tooltip, ActionIcon, Menu, Box, Button, Radio, Checkbox, Flex, Collapse, TextInput, Progress, Select, Text, Chip, Alert, Switch, Divider, Transition, MultiSelect, packSx, useMantineTheme, CopyButton, UnstyledButton, Skeleton, Table, Paper, Modal, Stack } from '@mantine/core';
import { useDebouncedValue, useMediaQuery } from '@mantine/hooks';
import { useVirtualizer, defaultRangeExtractor } from '@tanstack/react-virtual';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
}
const MRT_AggregationFns = Object.assign({}, aggregationFns);
const getColumnId = (columnDef) => { var _a, _b, _c, _d; return (_d = (_a = columnDef.id) !== null && _a !== void 0 ? _a : (_c = (_b = columnDef.accessorKey) === null || _b === void 0 ? void 0 : _b.toString) === null || _c === void 0 ? void 0 : _c.call(_b)) !== null && _d !== void 0 ? _d : columnDef.header; };
const getAllLeafColumnDefs = (columns) => {
const allLeafColumnDefs = [];
const getLeafColumns = (cols) => {
cols.forEach((col) => {
if (col.columns) {
getLeafColumns(col.columns);
}
else {
allLeafColumnDefs.push(col);
}
});
};
getLeafColumns(columns);
return allLeafColumnDefs;
};
const prepareColumns = ({ aggregationFns, columnDefs, columnFilterFns, defaultDisplayColumn, filterFns, sortingFns, }) => columnDefs.map((columnDef) => {
var _a, _b;
//assign columnId
if (!columnDef.id)
columnDef.id = getColumnId(columnDef);
if (process.env.NODE_ENV !== 'production' && !columnDef.id) {
console.error('Column definitions must have a valid `accessorKey` or `id` property');
}
//assign columnDefType
if (!columnDef.columnDefType)
columnDef.columnDefType = 'data';
if ((_a = columnDef.columns) === null || _a === void 0 ? void 0 : _a.length) {
columnDef.columnDefType = 'group';
//recursively prepare columns if this is a group column
columnDef.columns = prepareColumns({
aggregationFns,
columnDefs: columnDef.columns,
columnFilterFns,
defaultDisplayColumn,
filterFns,
sortingFns,
});
}
else if (columnDef.columnDefType === 'data') {
//assign aggregationFns if multiple aggregationFns are provided
if (Array.isArray(columnDef.aggregationFn)) {
const aggFns = columnDef.aggregationFn;
columnDef.aggregationFn = (columnId, leafRows, childRows) => aggFns.map((fn) => { var _a; return (_a = aggregationFns[fn]) === null || _a === void 0 ? void 0 : _a.call(aggregationFns, columnId, leafRows, childRows); });
}
//assign filterFns
if (Object.keys(filterFns).includes(columnFilterFns[columnDef.id])) {
columnDef.filterFn =
(_b = filterFns[columnFilterFns[columnDef.id]]) !== null && _b !== void 0 ? _b : filterFns.fuzzy;
columnDef._filterFn =
columnFilterFns[columnDef.id];
}
//assign sortingFns
if (Object.keys(sortingFns).includes(columnDef.sortingFn)) {
// @ts-ignore
columnDef.sortingFn = sortingFns[columnDef.sortingFn];
}
}
else if (columnDef.columnDefType === 'display') {
columnDef = Object.assign(Object.assign({}, defaultDisplayColumn), columnDef);
}
return columnDef;
});
const reorderColumn = (draggedColumn, targetColumn, columnOrder) => {
if (draggedColumn.getCanPin()) {
draggedColumn.pin(targetColumn.getIsPinned());
}
columnOrder.splice(columnOrder.indexOf(targetColumn.id), 0, columnOrder.splice(columnOrder.indexOf(draggedColumn.id), 1)[0]);
return [...columnOrder];
};
const showExpandColumn = (props, grouping) => !!(props.enableExpanding ||
(props.enableGrouping && (grouping === undefined || (grouping === null || grouping === void 0 ? void 0 : grouping.length))) ||
props.renderDetailPanel);
const getLeadingDisplayColumnIds = (props) => {
var _a;
return [
(props.enableRowDragging || props.enableRowOrdering) && 'mrt-row-drag',
props.positionActionsColumn === 'first' &&
(props.enableRowActions ||
(props.enableEditing &&
['row', 'modal'].includes((_a = props.editingMode) !== null && _a !== void 0 ? _a : ''))) &&
'mrt-row-actions',
props.positionExpandColumn === 'first' &&
showExpandColumn(props) &&
'mrt-row-expand',
props.enableRowSelection && 'mrt-row-select',
props.enableRowNumbers && 'mrt-row-numbers',
].filter(Boolean);
};
const getTrailingDisplayColumnIds = (props) => {
var _a;
return [
props.positionActionsColumn === 'last' &&
(props.enableRowActions ||
(props.enableEditing &&
['row', 'modal'].includes((_a = props.editingMode) !== null && _a !== void 0 ? _a : ''))) &&
'mrt-row-actions',
props.positionExpandColumn === 'last' &&
showExpandColumn(props) &&
'mrt-row-expand',
];
};
const getDefaultColumnOrderIds = (props) => [
...getLeadingDisplayColumnIds(props),
...getAllLeafColumnDefs(props.columns).map((columnDef) => getColumnId(columnDef)),
...getTrailingDisplayColumnIds(props),
].filter(Boolean);
const getDefaultColumnFilterFn = (columnDef) => {
if (columnDef.filterVariant === 'multi-select')
return 'arrIncludesSome';
if (columnDef.filterVariant === 'range')
return 'betweenInclusive';
if (columnDef.filterVariant === 'select' ||
columnDef.filterVariant === 'checkbox')
return 'equals';
return 'fuzzy';
};
const getIsLastLeftPinnedColumn = (table, column) => {
return (column.getIsPinned() === 'left' &&
table.getLeftLeafHeaders().length - 1 === column.getPinnedIndex());
};
const getIsFirstRightPinnedColumn = (column) => {
return column.getIsPinned() === 'right' && column.getPinnedIndex() === 0;
};
const getTotalRight = (table, column) => {
return ((table.getRightLeafHeaders().length - 1 - column.getPinnedIndex()) * 200);
};
const getCommonCellStyles = ({ column, header, table, tableCellProps, theme, }) => {
var _a, _b, _c, _d, _e, _f, _g, _h;
return (Object.assign(Object.assign({ backgroundColor: column.getIsPinned() && column.columnDef.columnDefType !== 'group'
? theme.fn.rgba(theme.colorScheme === 'dark'
? theme.fn.darken(theme.colors.dark[7], 0.02)
: theme.white, 0.97)
: 'inherit', backgroundClip: 'padding-box', boxShadow: getIsLastLeftPinnedColumn(table, column)
? `-4px 0 8px -6px ${theme.fn.rgba(theme.black, 0.2)} inset`
: getIsFirstRightPinnedColumn(column)
? `4px 0 8px -6px ${theme.fn.rgba(theme.black, 0.2)} inset`
: undefined, display: table.options.layoutMode === 'grid' ? 'flex' : 'table-cell', left: column.getIsPinned() === 'left'
? `${column.getStart('left')}px`
: undefined, ml: table.options.enableColumnVirtualization &&
column.getIsPinned() === 'left' &&
column.getPinnedIndex() === 0
? `-${column.getSize() * ((_b = (_a = table.getState().columnPinning.left) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 1)}px`
: undefined, mr: table.options.enableColumnVirtualization &&
column.getIsPinned() === 'right' &&
column.getPinnedIndex() === table.getVisibleLeafColumns().length - 1
? `-${column.getSize() *
((_d = (_c = table.getState().columnPinning.right) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 1) *
1.2}px`
: undefined, opacity: ((_e = table.getState().draggingColumn) === null || _e === void 0 ? void 0 : _e.id) === column.id ||
((_f = table.getState().hoveredColumn) === null || _f === void 0 ? void 0 : _f.id) === column.id
? 0.5
: 1, position: column.getIsPinned() && column.columnDef.columnDefType !== 'group'
? 'sticky'
: 'static', right: column.getIsPinned() === 'right'
? `${getTotalRight(table, column)}px`
: undefined, transition: table.options.enableColumnVirtualization || column.getIsResizing()
? 'none'
: `all 100ms ease-in-out` }, ((tableCellProps === null || tableCellProps === void 0 ? void 0 : tableCellProps.sx) instanceof Function
? tableCellProps.sx(theme)
: tableCellProps === null || tableCellProps === void 0 ? void 0 : tableCellProps.sx)), { flex: table.options.layoutMode === 'grid'
? `${column.getSize()} 0 auto`
: undefined, minWidth: `max(${column.getSize()}px, ${(_g = column.columnDef.minSize) !== null && _g !== void 0 ? _g : 30}px)`, width: (_h = header === null || header === void 0 ? void 0 : header.getSize()) !== null && _h !== void 0 ? _h : column.getSize() }));
};
const MRT_DefaultColumn = {
minSize: 40,
maxSize: 1000,
size: 180,
};
const MRT_DefaultDisplayColumn = {
columnDefType: 'display',
enableClickToCopy: false,
enableColumnActions: false,
enableColumnDragging: false,
enableColumnFilter: false,
enableColumnOrdering: false,
enableEditing: false,
enableGlobalFilter: false,
enableGrouping: false,
enableHiding: false,
enableResizing: false,
enableSorting: false,
};
const getPrimaryShade = (theme) => {
var _a, _b, _c, _d, _e;
return (_e = (theme.colorScheme === 'dark'
? // @ts-ignore
(_b = (_a = theme.primaryShade) === null || _a === void 0 ? void 0 : _a.dark) !== null && _b !== void 0 ? _b : theme.primaryShade
: // @ts-ignore
(_d = (_c = theme.primaryShade) === null || _c === void 0 ? void 0 : _c.light) !== null && _d !== void 0 ? _d : theme.primaryShade)) !== null && _e !== void 0 ? _e : 7;
};
const getPrimaryColor = (theme) => theme.colors[theme.primaryColor][getPrimaryShade(theme)];
const fuzzy$1 = (row, columnId, filterValue, addMeta) => {
const itemRank = rankItem(row.getValue(columnId), filterValue, {
threshold: rankings.MATCHES,
});
addMeta(itemRank);
return itemRank.passed;
};
fuzzy$1.autoRemove = (val) => !val;
const contains = (row, id, filterValue) => row
.getValue(id)
.toString()
.toLowerCase()
.trim()
.includes(filterValue.toString().toLowerCase().trim());
contains.autoRemove = (val) => !val;
const startsWith = (row, id, filterValue) => row
.getValue(id)
.toString()
.toLowerCase()
.trim()
.startsWith(filterValue.toString().toLowerCase().trim());
startsWith.autoRemove = (val) => !val;
const endsWith = (row, id, filterValue) => row
.getValue(id)
.toString()
.toLowerCase()
.trim()
.endsWith(filterValue.toString().toLowerCase().trim());
endsWith.autoRemove = (val) => !val;
const equals = (row, id, filterValue) => row.getValue(id).toString().toLowerCase().trim() ===
filterValue.toString().toLowerCase().trim();
equals.autoRemove = (val) => !val;
const notEquals = (row, id, filterValue) => row.getValue(id).toString().toLowerCase().trim() !==
filterValue.toString().toLowerCase().trim();
notEquals.autoRemove = (val) => !val;
const greaterThan = (row, id, filterValue) => !isNaN(+filterValue) && !isNaN(+row.getValue(id))
? +row.getValue(id) > +filterValue
: row.getValue(id).toString().toLowerCase().trim() >
filterValue.toString().toLowerCase().trim();
greaterThan.autoRemove = (val) => !val;
const greaterThanOrEqualTo = (row, id, filterValue) => equals(row, id, filterValue) || greaterThan(row, id, filterValue);
greaterThanOrEqualTo.autoRemove = (val) => !val;
const lessThan = (row, id, filterValue) => !isNaN(+filterValue) && !isNaN(+row.getValue(id))
? +row.getValue(id) < +filterValue
: row.getValue(id).toString().toLowerCase().trim() <
filterValue.toString().toLowerCase().trim();
lessThan.autoRemove = (val) => !val;
const lessThanOrEqualTo = (row, id, filterValue) => equals(row, id, filterValue) || lessThan(row, id, filterValue);
lessThanOrEqualTo.autoRemove = (val) => !val;
const between = (row, id, filterValues) => (['', undefined].includes(filterValues[0]) ||
greaterThan(row, id, filterValues[0])) &&
((!isNaN(+filterValues[0]) &&
!isNaN(+filterValues[1]) &&
+filterValues[0] > +filterValues[1]) ||
['', undefined].includes(filterValues[1]) ||
lessThan(row, id, filterValues[1]));
between.autoRemove = (val) => !val;
const betweenInclusive = (row, id, filterValues) => (['', undefined].includes(filterValues[0]) ||
greaterThanOrEqualTo(row, id, filterValues[0])) &&
((!isNaN(+filterValues[0]) &&
!isNaN(+filterValues[1]) &&
+filterValues[0] > +filterValues[1]) ||
['', undefined].includes(filterValues[1]) ||
lessThanOrEqualTo(row, id, filterValues[1]));
betweenInclusive.autoRemove = (val) => !val;
const empty = (row, id, _filterValue) => !row.getValue(id).toString().trim();
empty.autoRemove = (val) => !val;
const notEmpty = (row, id, _filterValue) => !!row.getValue(id).toString().trim();
notEmpty.autoRemove = (val) => !val;
const MRT_FilterFns = Object.assign(Object.assign({}, filterFns), { between,
betweenInclusive,
contains,
empty,
endsWith,
equals,
fuzzy: fuzzy$1,
greaterThan,
greaterThanOrEqualTo,
lessThan,
lessThanOrEqualTo,
notEmpty,
notEquals,
startsWith });
const MRT_Default_Icons = {
IconArrowAutofitContent,
IconArrowDown,
IconArrowsSort,
IconBoxMultiple,
IconChevronDown,
IconChevronLeft,
IconChevronRight,
IconChevronUp,
IconChevronsDown,
IconCircleOff,
IconCircleX,
IconClearAll,
IconColumns,
IconDeviceFloppy,
IconDots,
IconDotsVertical,
IconEdit,
IconEyeOff,
IconFilter,
IconFilterOff,
IconGripHorizontal,
IconMaximize,
IconMinimize,
IconPinned,
IconPinnedOff,
IconSearch,
IconSortAscending,
IconSortDescending,
IconTallymark1,
IconTallymark2,
IconTallymark3,
IconTallymark4,
IconTallymarks,
IconX,
};
const fuzzy = (rowA, rowB, columnId) => {
let dir = 0;
if (rowA.columnFiltersMeta[columnId]) {
dir = compareItems(rowA.columnFiltersMeta[columnId], rowB.columnFiltersMeta[columnId]);
}
// Provide a fallback for when the item ranks are equal
return dir === 0
? sortingFns.alphanumeric(rowA, rowB, columnId)
: dir;
};
const MRT_SortingFns = Object.assign(Object.assign({}, sortingFns), { fuzzy });
const rankGlobalFuzzy = (rowA, rowB) => Math.max(...Object.values(rowB.columnFiltersMeta).map((v) => v.rank)) -
Math.max(...Object.values(rowA.columnFiltersMeta).map((v) => v.rank));
const MRT_ExpandAllButton = ({ table }) => {
var _a;
const { getIsAllRowsExpanded, getIsSomeRowsExpanded, getCanSomeRowsExpand, getState, options: { icons: { IconChevronsDown }, localization, mantineExpandAllButtonProps, renderDetailPanel, }, toggleAllRowsExpanded, } = table;
const { density, isLoading } = getState();
const actionIconProps = mantineExpandAllButtonProps instanceof Function
? mantineExpandAllButtonProps({ table })
: mantineExpandAllButtonProps;
const isAllRowsExpanded = getIsAllRowsExpanded();
return (React.createElement(Tooltip, { withinPortal: true, withArrow: true, openDelay: 1000, label: ((_a = actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.title) !== null && _a !== void 0 ? _a : isAllRowsExpanded)
? localization.collapseAll
: localization.expandAll },
React.createElement(ActionIcon, Object.assign({ "aria-label": localization.expandAll, disabled: isLoading || (!renderDetailPanel && !getCanSomeRowsExpand()), onClick: () => toggleAllRowsExpanded(!isAllRowsExpanded) }, actionIconProps, { sx: (theme) => (Object.assign({ marginLeft: density === 'xl'
? '-6px'
: density === 'lg'
? '-3px'
: density === 'md'
? '0'
: density === 'sm'
? '3px'
: '6px', '&:disabled': {
backgroundColor: 'transparent',
border: 'none',
} }, ((actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.sx) instanceof Function
? actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.sx(theme)
: actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.sx))), title: undefined }),
React.createElement(IconChevronsDown, { style: {
transform: `rotate(${isAllRowsExpanded ? -180 : getIsSomeRowsExpanded() ? -90 : 0}deg)`,
transition: 'transform 100ms',
} }))));
};
const MRT_ExpandButton = ({ row, table }) => {
var _a;
const { options: { icons: { IconChevronDown }, localization, mantineExpandButtonProps, renderDetailPanel, }, } = table;
const actionIconProps = mantineExpandButtonProps instanceof Function
? mantineExpandButtonProps({ table, row })
: mantineExpandButtonProps;
const canExpand = row.getCanExpand();
const isExpanded = row.getIsExpanded();
const handleToggleExpand = (event) => {
var _a;
event.stopPropagation();
row.toggleExpanded();
(_a = actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.onClick) === null || _a === void 0 ? void 0 : _a.call(actionIconProps, event);
};
return (React.createElement(Tooltip, { withinPortal: true, withArrow: true, disabled: !canExpand && !renderDetailPanel, openDelay: 1000, label: ((_a = actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.title) !== null && _a !== void 0 ? _a : isExpanded)
? localization.collapse
: localization.expand },
React.createElement(ActionIcon, Object.assign({ "aria-label": localization.expand, disabled: !canExpand && !renderDetailPanel }, actionIconProps, { onClick: handleToggleExpand, sx: (theme) => (Object.assign({ '&:disabled': {
backgroundColor: 'transparent',
border: 'none',
} }, ((actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.sx) instanceof Function
? actionIconProps.sx(theme)
: actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.sx))), title: undefined }),
React.createElement(IconChevronDown, { style: {
transform: `rotate(${!canExpand && !renderDetailPanel ? -90 : isExpanded ? -180 : 0}deg)`,
transition: 'transform 100ms',
} }))));
};
const MRT_RowActionMenu = ({ handleEdit, row, table, }) => {
const { options: { icons: { IconEdit, IconDots }, enableEditing, localization, renderRowActionMenuItems, }, } = table;
return (React.createElement(Menu, { closeOnItemClick: true },
React.createElement(Tooltip, { withinPortal: true, withArrow: true, openDelay: 1000, label: localization.rowActions },
React.createElement(Menu.Target, null,
React.createElement(ActionIcon, { "aria-label": localization.rowActions, size: "sm" },
React.createElement(IconDots, null)))),
React.createElement(Menu.Dropdown, null,
enableEditing && (React.createElement(Menu.Item, { icon: React.createElement(IconEdit, null), onClick: handleEdit }, localization.edit)), renderRowActionMenuItems === null || renderRowActionMenuItems === void 0 ? void 0 :
renderRowActionMenuItems({
row,
table,
}))));
};
const MRT_EditActionButtons = ({ row, table, variant = 'icon', }) => {
const { getState, options: { icons: { IconCircleX, IconDeviceFloppy }, localization, onEditingRowSave, onEditingRowCancel, }, refs: { editInputRefs }, setEditingRow, } = table;
const { editingRow } = getState();
const handleCancel = () => {
onEditingRowCancel === null || onEditingRowCancel === void 0 ? void 0 : onEditingRowCancel({ row, table });
setEditingRow(null);
};
const handleSave = () => {
var _a, _b;
//look for auto-filled input values
(_a = Object.values(editInputRefs === null || editInputRefs === void 0 ? void 0 : editInputRefs.current)) === null || _a === void 0 ? void 0 : _a.forEach((input) => {
if (input.value !== undefined &&
Object.hasOwn(editingRow === null || editingRow === void 0 ? void 0 : editingRow._valuesCache, input.name)) {
// @ts-ignore
editingRow._valuesCache[input.name] = input.value;
}
});
onEditingRowSave === null || onEditingRowSave === void 0 ? void 0 : onEditingRowSave({
exitEditingMode: () => setEditingRow(null),
row: editingRow !== null && editingRow !== void 0 ? editingRow : row,
table,
values: (_b = editingRow === null || editingRow === void 0 ? void 0 : editingRow._valuesCache) !== null && _b !== void 0 ? _b : Object.assign({}, row.original),
});
};
return (React.createElement(Box, { onClick: (e) => e.stopPropagation(), sx: { display: 'flex', gap: '12px' } }, variant === 'icon' ? (React.createElement(React.Fragment, null,
React.createElement(Tooltip, { withinPortal: true, withArrow: true, label: localization.cancel },
React.createElement(ActionIcon, { "aria-label": localization.cancel, onClick: handleCancel },
React.createElement(IconCircleX, null))),
React.createElement(Tooltip, { withinPortal: true, withArrow: true, label: localization.save },
React.createElement(ActionIcon, { "aria-label": localization.save, color: "blue", onClick: handleSave },
React.createElement(IconDeviceFloppy, null))))) : (React.createElement(React.Fragment, null,
React.createElement(Button, { onClick: handleCancel, variant: "subtle" }, localization.cancel),
React.createElement(Button, { onClick: handleSave, variant: "filled" }, localization.save)))));
};
const MRT_ToggleRowActionMenuButton = ({ cell, row, table, }) => {
const { getState, options: { editingMode, enableEditing, icons: { IconEdit }, localization, renderRowActionMenuItems, renderRowActions, }, setEditingRow, } = table;
const { editingRow } = getState();
const handleStartEditMode = (event) => {
event.stopPropagation();
setEditingRow(Object.assign({}, row));
};
return (React.createElement(React.Fragment, null, renderRowActions ? (React.createElement(React.Fragment, null, renderRowActions({ cell, row, table }))) : row.id === (editingRow === null || editingRow === void 0 ? void 0 : editingRow.id) && editingMode === 'row' ? (React.createElement(MRT_EditActionButtons, { row: row, table: table })) : !renderRowActionMenuItems && enableEditing ? (React.createElement(Tooltip, { withinPortal: true, position: "right", withArrow: true, label: localization.edit },
React.createElement(ActionIcon, { "aria-label": localization.edit, onClick: handleStartEditMode },
React.createElement(IconEdit, null)))) : renderRowActionMenuItems ? (React.createElement(MRT_RowActionMenu, { handleEdit: handleStartEditMode, row: row, table: table })) : null));
};
const MRT_SelectCheckbox = ({ row, selectAll, table }) => {
var _a;
const { getState, options: { localization, enableMultiRowSelection, mantineSelectCheckboxProps, mantineSelectAllCheckboxProps, selectAllMode, }, } = table;
const { density, isLoading } = getState();
const checkboxProps = !row
? mantineSelectAllCheckboxProps instanceof Function
? mantineSelectAllCheckboxProps({ table })
: mantineSelectAllCheckboxProps
: mantineSelectCheckboxProps instanceof Function
? mantineSelectCheckboxProps({ row, table })
: mantineSelectCheckboxProps;
const commonProps = Object.assign(Object.assign({ 'aria-label': selectAll
? localization.toggleSelectAll
: localization.toggleSelectRow, checked: selectAll
? selectAllMode === 'page'
? table.getIsAllPageRowsSelected()
: table.getIsAllRowsSelected()
: row === null || row === void 0 ? void 0 : row.getIsSelected(), disabled: isLoading, onChange: row
? row.getToggleSelectedHandler()
: selectAllMode === 'all'
? table.getToggleAllRowsSelectedHandler()
: table.getToggleAllPageRowsSelectedHandler(), size: density === 'xs' ? 'sm' : 'md' }, checkboxProps), { onClick: (e) => {
var _a;
e.stopPropagation();
(_a = checkboxProps === null || checkboxProps === void 0 ? void 0 : checkboxProps.onClick) === null || _a === void 0 ? void 0 : _a.call(checkboxProps, e);
}, title: undefined });
return (React.createElement(Tooltip, { withinPortal: true, withArrow: true, openDelay: 1000, label: (_a = checkboxProps === null || checkboxProps === void 0 ? void 0 : checkboxProps.title) !== null && _a !== void 0 ? _a : (selectAll
? localization.toggleSelectAll
: localization.toggleSelectRow) }, enableMultiRowSelection === false ? (React.createElement(Radio, Object.assign({}, commonProps))) : (React.createElement(Checkbox, Object.assign({ indeterminate: selectAll
? table.getIsSomeRowsSelected() &&
!(selectAllMode === 'page'
? table.getIsAllPageRowsSelected()
: table.getIsAllRowsSelected())
: row === null || row === void 0 ? void 0 : row.getIsSomeSelected() }, commonProps)))));
};
const mrtFilterOptions = (localization) => [
{
option: 'fuzzy',
symbol: '≈',
label: localization.filterFuzzy,
divider: false,
},
{
option: 'contains',
symbol: '*',
label: localization.filterContains,
divider: false,
},
{
option: 'startsWith',
symbol: 'a',
label: localization.filterStartsWith,
divider: false,
},
{
option: 'endsWith',
symbol: 'z',
label: localization.filterEndsWith,
divider: true,
},
{
option: 'equals',
symbol: '=',
label: localization.filterEquals,
divider: false,
},
{
option: 'notEquals',
symbol: '≠',
label: localization.filterNotEquals,
divider: true,
},
{
option: 'between',
symbol: '⇿',
label: localization.filterBetween,
divider: false,
},
{
option: 'betweenInclusive',
symbol: '⬌',
label: localization.filterBetweenInclusive,
divider: true,
},
{
option: 'greaterThan',
symbol: '>',
label: localization.filterGreaterThan,
divider: false,
},
{
option: 'greaterThanOrEqualTo',
symbol: '≥',
label: localization.filterGreaterThanOrEqualTo,
divider: false,
},
{
option: 'lessThan',
symbol: '<',
label: localization.filterLessThan,
divider: false,
},
{
option: 'lessThanOrEqualTo',
symbol: '≤',
label: localization.filterLessThanOrEqualTo,
divider: true,
},
{
option: 'empty',
symbol: '∅',
label: localization.filterEmpty,
divider: false,
},
{
option: 'notEmpty',
symbol: '!∅',
label: localization.filterNotEmpty,
divider: false,
},
];
const MRT_FilterOptionMenu = ({ header, onSelect, setFilterValue, table, }) => {
var _a, _b, _c, _d;
const { getState, options: { columnFilterModeOptions, globalFilterModeOptions, localization, renderColumnFilterModeMenuItems, renderGlobalFilterModeMenuItems, }, setColumnFilterFns, setGlobalFilterFn, } = table;
const { globalFilterFn } = getState();
const { column } = header !== null && header !== void 0 ? header : {};
const { columnDef } = column !== null && column !== void 0 ? column : {};
const allowedColumnFilterOptions = (_a = columnDef === null || columnDef === void 0 ? void 0 : columnDef.columnFilterModeOptions) !== null && _a !== void 0 ? _a : columnFilterModeOptions;
const internalFilterOptions = useMemo(() => mrtFilterOptions(localization).filter((filterOption) => columnDef
? allowedColumnFilterOptions === undefined ||
(allowedColumnFilterOptions === null || allowedColumnFilterOptions === void 0 ? void 0 : allowedColumnFilterOptions.includes(filterOption.option))
: (!globalFilterModeOptions ||
globalFilterModeOptions.includes(filterOption.option)) &&
['fuzzy', 'contains', 'startsWith'].includes(filterOption.option)), []);
const handleSelectFilterMode = (option) => {
if (header && column) {
setColumnFilterFns((prev) => (Object.assign(Object.assign({}, prev), { [header.id]: option })));
if (['empty', 'notEmpty'].includes(option)) {
column.setFilterValue(' ');
}
else if ((columnDef === null || columnDef === void 0 ? void 0 : columnDef.filterVariant) === 'multi-select' ||
['arrIncludesSome', 'arrIncludesAll', 'arrIncludes'].includes(option)) {
column.setFilterValue([]);
setFilterValue === null || setFilterValue === void 0 ? void 0 : setFilterValue([]);
}
else if ((columnDef === null || columnDef === void 0 ? void 0 : columnDef.filterVariant) === 'range' ||
['between', 'betweenInclusive', 'inNumberRange'].includes(option)) {
column.setFilterValue(['', '']);
setFilterValue === null || setFilterValue === void 0 ? void 0 : setFilterValue('');
}
else {
column.setFilterValue('');
setFilterValue === null || setFilterValue === void 0 ? void 0 : setFilterValue('');
}
}
else {
setGlobalFilterFn(option);
}
onSelect === null || onSelect === void 0 ? void 0 : onSelect();
};
const filterOption = !!header && columnDef ? columnDef._filterFn : globalFilterFn;
return (React.createElement(Menu.Dropdown, null, (_d = (header && column && columnDef
? (_c = (_b = columnDef.renderColumnFilterModeMenuItems) === null || _b === void 0 ? void 0 : _b.call(columnDef, {
column: column,
internalFilterOptions,
onSelectFilterMode: handleSelectFilterMode,
table,
})) !== null && _c !== void 0 ? _c : renderColumnFilterModeMenuItems === null || renderColumnFilterModeMenuItems === void 0 ? void 0 : renderColumnFilterModeMenuItems({
column: column,
internalFilterOptions,
onSelectFilterMode: handleSelectFilterMode,
table,
})
: renderGlobalFilterModeMenuItems === null || renderGlobalFilterModeMenuItems === void 0 ? void 0 : renderGlobalFilterModeMenuItems({
internalFilterOptions,
onSelectFilterMode: handleSelectFilterMode,
table,
}))) !== null && _d !== void 0 ? _d : internalFilterOptions.map(({ option, label, divider, symbol }, index) => (React.createElement(Fragment, { key: index },
React.createElement(Menu.Item, { onClick: () => handleSelectFilterMode(option), color: option === filterOption ? 'blue' : undefined, sx: {
'& > .mantine-Menu-itemLabel': {
display: 'flex',
flexWrap: 'nowrap',
gap: '1ch',
},
}, value: option },
React.createElement(Flex, { sx: {
fontSize: '20px',
transform: 'translateY(-2px)',
width: '2ch',
} }, symbol),
React.createElement(Flex, { align: "center" }, label)),
divider && React.createElement(Menu.Divider, null))))));
};
const MRT_GlobalFilterTextInput = ({ table, }) => {
var _a;
const { getState, setGlobalFilter, options: { enableGlobalFilterModes, icons: { IconSearch, IconX }, localization, manualFiltering, mantineSearchTextInputProps, }, refs: { searchInputRef }, } = table;
const { globalFilter, showGlobalFilter } = getState();
const textFieldProps = mantineSearchTextInputProps instanceof Function
? mantineSearchTextInputProps({ table })
: mantineSearchTextInputProps;
const [searchValue, setSearchValue] = useState(globalFilter !== null && globalFilter !== void 0 ? globalFilter : '');
const [debouncedSearchValue] = useDebouncedValue(searchValue, manualFiltering ? 500 : 250);
useEffect(() => {
setGlobalFilter(debouncedSearchValue || undefined);
}, [debouncedSearchValue]);
useEffect(() => {
if (globalFilter === undefined) {
handleClear();
}
}, [globalFilter]);
const handleClear = () => {
setSearchValue('');
setGlobalFilter(undefined);
};
return (React.createElement(Collapse, { in: showGlobalFilter, sx: { '& > div': { display: 'flex' } } },
enableGlobalFilterModes && (React.createElement(Menu, { withinPortal: true },
React.createElement(Menu.Target, null,
React.createElement(ActionIcon, { "aria-label": localization.changeSearchMode, size: "sm" },
React.createElement(IconSearch, null))),
React.createElement(MRT_FilterOptionMenu, { table: table, onSelect: handleClear }))),
React.createElement(TextInput, Object.assign({ placeholder: localization.search, onChange: (event) => setSearchValue(event.target.value), value: searchValue !== null && searchValue !== void 0 ? searchValue : '', variant: "filled", icon: !enableGlobalFilterModes && React.createElement(IconSearch, null), rightSection: React.createElement(Tooltip, { withinPortal: true, withArrow: true, label: (_a = localization.clearSearch) !== null && _a !== void 0 ? _a : '' },
React.createElement(ActionIcon, { "aria-label": localization.clearSearch, disabled: !(searchValue === null || searchValue === void 0 ? void 0 : searchValue.length), onClick: handleClear, size: "sm", sx: {
'&:disabled': {
backgroundColor: 'transparent',
border: 'none',
},
} },
React.createElement(IconX, null))) }, textFieldProps, { ref: (node) => {
if (node) {
searchInputRef.current = node;
if (textFieldProps === null || textFieldProps === void 0 ? void 0 : textFieldProps.ref) {
// @ts-ignore
textFieldProps.ref = node;
}
}
} }))));
};
const MRT_LinearProgressBar = ({ isTopToolbar, table }) => {
const { options: { mantineProgressProps }, getState, } = table;
const { isLoading, showProgressBars } = getState();
const linearProgressProps = mantineProgressProps instanceof Function
? mantineProgressProps({ isTopToolbar, table })
: mantineProgressProps;
return (React.createElement(Collapse, { in: isLoading || showProgressBars, sx: {
bottom: isTopToolbar ? 0 : undefined,
position: 'absolute',
top: !isTopToolbar ? 0 : undefined,
width: '100%',
} },
React.createElement(Progress, Object.assign({ animate: true, "aria-label": "Loading", "aria-busy": "true", sx: {
position: 'relative',
}, value: 100 }, linearProgressProps))));
};
const commonActionButtonStyles = {
userSelect: 'none',
'&:disabled': {
backgroundColor: 'transparent',
border: 'none',
},
};
const MRT_TablePagination = ({ table, position = 'bottom', }) => {
var _a;
const { getPrePaginationRowModel, getState, setPageIndex, setPageSize, options: { enableToolbarInternalActions, icons: { IconChevronLeft, IconChevronRight }, localization, mantinePaginationProps, rowCount, }, } = table;
const { pagination: { pageSize = 10, pageIndex = 0 }, showGlobalFilter, } = getState();
const paginationProps = mantinePaginationProps instanceof Function
? mantinePaginationProps({ table })
: mantinePaginationProps;
const totalRowCount = rowCount !== null && rowCount !== void 0 ? rowCount : getPrePaginationRowModel().rows.length;
const showFirstLastPageButtons = totalRowCount / pageSize > 2 &&
(paginationProps === null || paginationProps === void 0 ? void 0 : paginationProps.showFirstLastPageButtons) !== false;
const firstRowIndex = pageIndex * pageSize;
const lastRowIndex = Math.min(pageIndex * pageSize + pageSize, totalRowCount);
return (React.createElement(Flex, Object.assign({ align: "center", justify: "space-between", gap: "lg", py: "xs", px: "sm", mt: position === 'top' && enableToolbarInternalActions && !showGlobalFilter
? '3rem'
: undefined }, paginationProps),
(paginationProps === null || paginationProps === void 0 ? void 0 : paginationProps.showRowsPerPage) !== false && (React.createElement(Select, { data: (_a = paginationProps === null || paginationProps === void 0 ? void 0 : paginationProps.rowsPerPageOptions) !== null && _a !== void 0 ? _a : [
'5',
'10',
'15',
'20',
'25',
'30',
'50',
'100',
], label: localization.rowsPerPage, onChange: (value) => setPageSize(+value), value: pageSize.toString(), sx: {
'@media (min-width: 720px)': {
display: 'flex',
alignItems: 'center',
gap: '8px',
},
'& .mantine-Select-input': {
width: '90px',
},
} })),
React.createElement(Text, null, `${firstRowIndex + 1}-${lastRowIndex} ${localization.of} ${totalRowCount}`),
React.createElement(Flex, { gap: "xs" },
showFirstLastPageButtons && (React.createElement(ActionIcon, { "aria-label": localization.goToFirstPage, disabled: pageIndex <= 0, onClick: () => setPageIndex(0), sx: commonActionButtonStyles },
React.createElement("b", { style: { transform: 'translate(4px, -1.5px)' } }, "|"),
React.createElement(IconChevronLeft, null))),
React.createElement(ActionIcon, { "aria-label": localization.goToPreviousPage, disabled: pageIndex <= 0, onClick: () => setPageIndex(pageIndex - 1), sx: commonActionButtonStyles },
React.createElement(IconChevronLeft, null)),
React.createElement(ActionIcon, { "aria-label": localization.goToNextPage, disabled: lastRowIndex >= totalRowCount, onClick: () => setPageIndex(pageIndex + 1), sx: commonActionButtonStyles },
React.createElement(IconChevronRight, null)),
showFirstLastPageButtons && (React.createElement(ActionIcon, { "aria-label": localization.goToLastPage, disabled: lastRowIndex >= totalRowCount, onClick: () => setPageIndex(Math.ceil(totalRowCount / pageSize) - 1), sx: commonActionButtonStyles },
React.createElement(IconChevronRight, null),
React.createElement("b", { style: { transform: 'translate(-4px, -1.5px)' } }, "|"))))));
};
const MRT_ToolbarAlertBanner = ({ stackAlertBanner, table, }) => {
var _a, _b;
const { getPrePaginationRowModel, getSelectedRowModel, getState, options: { icons: { IconX }, localization, mantineToolbarAlertBannerProps, mantineToolbarAlertBannerChipProps, positionToolbarAlertBanner, rowCount, }, } = table;
const { grouping, showAlertBanner } = getState();
const alertProps = mantineToolbarAlertBannerProps instanceof Function
? mantineToolbarAlertBannerProps({ table })
: mantineToolbarAlertBannerProps;
const chipProps = mantineToolbarAlertBannerChipProps instanceof Function
? mantineToolbarAlertBannerChipProps({ table })
: mantineToolbarAlertBannerChipProps;
const selectMessage = getSelectedRowModel().rows.length > 0
? (_b = (_a = localization.selectedCountOfRowCountRowsSelected) === null || _a === void 0 ? void 0 : _a.replace('{selectedCount}', getSelectedRowModel().rows.length.toString())) === null || _b === void 0 ? void 0 : _b.replace('{rowCount}', (rowCount !== null && rowCount !== void 0 ? rowCount : getPrePaginationRowModel().rows.length).toString())
: null;
const groupedByMessage = grouping.length > 0 ? (React.createElement(Flex, null,
localization.groupedBy,
' ',
grouping.map((columnId, index) => (React.createElement(Fragment, { key: `${index}-${columnId}` },
index > 0 ? localization.thenBy : '',
React.createElement(Chip, Object.assign({ onChange: () => table.getColumn(columnId).toggleGrouping(), sx: { paddingLeft: '1ch' } }, chipProps),
table.getColumn(columnId).columnDef.header,
' ',
React.createElement(IconX, { size: "12pt", style: { transform: 'translate(6px, 3px)' } }))))))) : null;
return (React.createElement(Collapse, { in: showAlertBanner || !!selectMessage || !!groupedByMessage, transitionDuration: stackAlertBanner ? 200 : 0 },
React.createElement(Alert, Object.assign({ color: "blue", icon: false }, alertProps, { sx: (theme) => (Object.assign({ borderRadius: 0, fontSize: '16px', left: 0, position: 'relative', marginBottom: stackAlertBanner
? 0
: positionToolbarAlertBanner === 'bottom'
? '-16px'
: undefined, padding: '8px', right: 0, top: 0, width: '100%', zIndex: 2 }, ((alertProps === null || alertProps === void 0 ? void 0 : alertProps.sx) instanceof Function
? alertProps.sx(theme)
: alertProps === null || alertProps === void 0 ? void 0 : alertProps.sx))) }),
(alertProps === null || alertProps === void 0 ? void 0 : alertProps.title) && React.createElement(Box, null, alertProps.title),
React.createElement(Flex, { sx: { padding: '8px 16px' } }, alertProps === null || alertProps === void 0 ? void 0 :
alertProps.children,
(alertProps === null || alertProps === void 0 ? void 0 : alertProps.children) && (selectMessage || groupedByMessage) && (React.createElement("br", null)),
selectMessage,
selectMessage && groupedByMessage && React.createElement("br", null),
groupedByMessage))));
};
const MRT_ToggleFullScreenButton = (_a) => {
var _b;
var { table } = _a, rest = __rest(_a, ["table"]);
const { getState, options: { icons: { IconMinimize, IconMaximize }, localization, }, setIsFullScreen, } = table;
const { isFullScreen } = getState();
const handleToggleFullScreen = () => {
setIsFullScreen(!isFullScreen);
};
return (React.createElement(Tooltip, { withinPortal: true, withArrow: true, label: (_b = rest === null || rest === void 0 ? void 0 : rest.title) !== null && _b !== void 0 ? _b : localization.toggleFullScreen },
React.createElement(ActionIcon, Object.assign({ "aria-label": localization.showHideFilters, onClick: handleToggleFullScreen, size: "lg" }, rest, { title: undefined }), isFullScreen ? React.createElement(IconMinimize, null) : React.createElement(IconMaximize, null))));
};
const MRT_ColumnPinningButtons = ({ column, table, }) => {
const { options: { icons: { IconPinned, IconPinnedOff }, localization, }, } = table;
const handlePinColumn = (pinDirection) => {
column.pin(pinDirection);
};
return (React.createElement(Flex, { sx: {
minWidth: '70px',
alignContent: 'center',
justifyContent: 'center',
} }, column.getIsPinned() ? (React.createElement(Tooltip, { withinPortal: true, withArrow: true, label: localization.unpin },
React.createElement(ActionIcon, { onClick: () => handlePinColumn(false), size: "md" },
React.createElement(IconPinnedOff, null)))) : (React.createElement(React.Fragment, null,
React.createElement(Tooltip, { withinPortal: true, withArrow: true, label: localization.pinToLeft },
React.createElement(ActionIcon, { onClick: () => handlePinColumn('left'), size: "md" },
React.createElement(IconPinned, { style: {
transform: 'rotate(90deg)',
} }))),
React.createElement(Tooltip, { withinPortal: true, withArrow: true, label: localization.pinToRight },
React.createElement(ActionIcon, { onClick: () => handlePinColumn('right'), size: "md" },
React.createElement(IconPinned, { style: {
transform: 'rotate(-90deg)',
} })))))));
};
const MRT_GrabHandleButton = ({ actionIconProps, onDragEnd, onDragStart, table, }) => {
var _a;
const { options: { icons: { IconGripHorizontal }, localization, }, } = table;
return (React.createElement(Tooltip, { withinPortal: true, withArrow: true, openDelay: 1000, position: "top", label: (_a = actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.title) !== null && _a !== void 0 ? _a : localization.move },
React.createElement(ActionIcon, Object.assign({ draggable: "true", size: "sm" }, actionIconProps, { onClick: (e) => {
var _a;
e.stopPropagation();
(_a = actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.onClick) === null || _a === void 0 ? void 0 : _a.call(actionIconProps, e);
}, onDragStart: onDragStart, onDragEnd: onDragEnd, sx: (theme) => (Object.assign({ cursor: 'grab', margin: '0 -0.16px', opacity: 0.5, padding: '2px', transition: 'opacity 100ms ease-in-out', '&:hover': {
backgroundColor: 'transparent',
opacity: 1,
}, '&:active': {
cursor: 'grabbing',
} }, ((actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.sx) instanceof Function
? actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.sx(theme)
: actionIconProps === null || actionIconProps === void 0 ? void 0 : actionIconProps.sx))), title: undefined }),
React.createElement(IconGripHorizontal, null))));
};
const MRT_ShowHideColumnsMenuItems = ({ allColumns, hoveredColumn, setHoveredColumn, column, isSubMenu, table, }) => {
var _a;
const { getState, options: { enableColumnOrdering, enableHiding, enablePinning, localization, }, setColumnOrder, } = table;
const { columnOrder } = getState();
const { columnDef } = column;
const { columnDefType } = columnDef;
const switchChecked = (columnDefType !== 'group' && column.getIsVisible()) ||
(columnDefType === 'group' &&
column.getLeafColumns().some((col) => col.getIsVisible()));
const handleToggleColumnHidden = (