From 16f0f46b914a27d23e65b8e9388a870eb4113fe7 Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Thu, 4 Jan 2024 22:16:48 +0200 Subject: [PATCH 1/9] Implement pinFirstColumn feature --- app/config.ts | 5 + .../PinFirstColumnExamples.tsx | 160 ++++++++++++++++++ .../pinning-the-first-column/page.tsx | 57 +++++++ .../PinLastColumnExample.tsx | 17 +- app/examples/pinning-the-last-column/page.tsx | 5 +- package/DataTable.css | 79 +++++++++ package/DataTable.tsx | 21 ++- package/DataTableHeader.tsx | 3 + package/DataTableHeaderSelectorCell.tsx | 29 ++-- package/types/DataTableProps.ts | 5 + 10 files changed, 359 insertions(+), 22 deletions(-) create mode 100644 app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx create mode 100644 app/examples/pinning-the-first-column/page.tsx diff --git a/app/config.ts b/app/config.ts index a64a0a12e..dc58291b8 100644 --- a/app/config.ts +++ b/app/config.ts @@ -207,6 +207,11 @@ export const ROUTES: RouteInfo[] = [ title: 'Pinning the last column', description: `Example: how to pin the last column on ${PRODUCT_NAME}`, }, + { + href: '/examples/pinning-the-first-column', + title: 'Pinning the first column', + description: `Example: how to pin the first column on ${PRODUCT_NAME}`, + }, { href: '/examples/links-or-buttons-inside-clickable-rows-or-cells', title: 'Links or buttons inside clickable rows or cells', diff --git a/app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx b/app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx new file mode 100644 index 000000000..626ede588 --- /dev/null +++ b/app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx @@ -0,0 +1,160 @@ +'use client'; + +import { ActionIcon, Box, Button, Grid, GridCol, Group, Stack, Text } from '@mantine/core'; +import { closeModal, openModal } from '@mantine/modals'; +import { IconEdit, IconEye, IconTrash } from '@tabler/icons-react'; +import { DataTable } from '__PACKAGE__'; +import { useState } from 'react'; +import { employees, type Employee } from '~/data'; + +const records = employees.slice(0, 5); + +const showModal = ({ employee, action }: { employee: Employee; action: 'view' | 'edit' | 'delete' }) => { + openModal({ + modalId: action, + title: + action === 'view' + ? 'Showing company information' + : action === 'edit' + ? 'Editing company information' + : 'Deleting company', + children: ( + + + {action === 'view' + ? 'Here’s where you could show more information...' + : action === 'edit' + ? 'Here’s where you could put an edit form...' + : 'Here’s where you could ask for confirmation before deleting...'} + + + ID + {employee.id} + First name + {employee.firstName} + Last name + {employee.lastName} + + + + ), + }); +}; + +export function PinFirstColumnExampleWithoutRecordSelection() { + // example-start without-record-selection + return ( + Row actions, + textAlign: 'right', + render: (employee) => ( + + showModal({ employee, action: 'view' })} + > + + + showModal({ employee, action: 'edit' })} + > + + + showModal({ employee, action: 'delete' })} + > + + + + ), + }, + ]} + records={records} + // example-resume + /> + ); + // example-end +} + +export function PinFirstColumnExampleWithRecordSelection() { + const [selectedRecord, setSelectedRecord] = useState([]); + + // example-start with-record-selection + return ( + Row actions, + textAlign: 'right', + render: (employee) => ( + + showModal({ employee, action: 'view' })} + > + + + showModal({ employee, action: 'edit' })} + > + + + showModal({ employee, action: 'delete' })} + > + + + + ), + }, + ]} + records={records} + // example-resume + /> + ); + // example-end +} diff --git a/app/examples/pinning-the-first-column/page.tsx b/app/examples/pinning-the-first-column/page.tsx new file mode 100644 index 000000000..2cf9e8593 --- /dev/null +++ b/app/examples/pinning-the-first-column/page.tsx @@ -0,0 +1,57 @@ +import { Code } from '@mantine/core'; +import type { Route } from 'next'; +import { CodeBlock } from '~/components/CodeBlock'; +import { InternalLink } from '~/components/InternalLink'; +import { PageNavigation } from '~/components/PageNavigation'; +import { PageTitle } from '~/components/PageTitle'; +import { Txt } from '~/components/Txt'; +import { readCodeFile } from '~/lib/code'; +import { getRouteMetadata } from '~/lib/utils'; +import { + PinFirstColumnExampleWithoutRecordSelection, + PinFirstColumnExampleWithRecordSelection, +} from './PinFirstColumnExamples'; + +const PATH: Route = '/examples/pinning-the-first-column'; + +export const metadata = getRouteMetadata(PATH); + +export default async function PinFirstColumnExamplePage() { + const code = await readCodeFile>( + `${PATH}/PinFirstColumnExamples.tsx` + ); + + return ( + <> + + + + Pinning the first column to the left side of the table could be useful when you have a table with many columns + and you want to make sure the first column is always visible, even when the table is scrolled horizontally. For + instance, you could use this feature to ensure that{' '} + row actions placed on the first column are always + visible. + + + You can achieve this by setting the pinLastColumn DataTable prop to true: + + + Here is the code: + + + You can also combine this feature with{' '} + row selection, in which case both the selection + checkbox and the first user-provided column will be pinned to the left side of the table: + + + Here is the code: + + + Combining this feature with column grouping may lead + to minor visual artifacts. + + Head over to the next example to discover more features. + + + ); +} diff --git a/app/examples/pinning-the-last-column/PinLastColumnExample.tsx b/app/examples/pinning-the-last-column/PinLastColumnExample.tsx index 1ab300625..f8f439ca1 100644 --- a/app/examples/pinning-the-last-column/PinLastColumnExample.tsx +++ b/app/examples/pinning-the-last-column/PinLastColumnExample.tsx @@ -4,6 +4,7 @@ import { ActionIcon, Box, Button, Grid, GridCol, Group, Stack, Text } from '@man import { closeModal, openModal } from '@mantine/modals'; import { IconEdit, IconEye, IconTrash } from '@tabler/icons-react'; import { DataTable } from '__PACKAGE__'; +import { useState } from 'react'; import { employees, type Employee } from '~/data'; const records = employees.slice(0, 5); @@ -15,16 +16,16 @@ const showModal = ({ employee, action }: { employee: Employee; action: 'view' | action === 'view' ? 'Showing company information' : action === 'edit' - ? 'Editing company information' - : 'Deleting company', + ? 'Editing company information' + : 'Deleting company', children: ( {action === 'view' ? 'Here’s where you could show more information...' : action === 'edit' - ? 'Here’s where you could put an edit form...' - : 'Here’s where you could ask for confirmation before deleting...'} + ? 'Here’s where you could put an edit form...' + : 'Here’s where you could ask for confirmation before deleting...'} ID @@ -41,10 +42,13 @@ const showModal = ({ employee, action }: { employee: Employee; action: 'view' | }; export function PinLastColumnExample() { + const [selectedRecord, setSelectedRecord] = useState([]); + // example-start return ( Row actions, textAlign: 'right', render: (employee) => ( - // example-skip action cells custom rendering - // example-resume ), }, ]} records={records} + selectedRecords={selectedRecord} + onSelectedRecordsChange={setSelectedRecord} + // example-resume /> ); // example-end diff --git a/app/examples/pinning-the-last-column/page.tsx b/app/examples/pinning-the-last-column/page.tsx index 70e6332c3..eae791f60 100644 --- a/app/examples/pinning-the-last-column/page.tsx +++ b/app/examples/pinning-the-last-column/page.tsx @@ -42,7 +42,10 @@ export default async function PinLastColumnExamplePage() { Combining this feature with column grouping may lead to minor visual artifacts. - Head over to the next example to discover more features. + + Head over to the next example to discover how you can pin the first column to the{' '} + left side of the table. + ); diff --git a/package/DataTable.css b/package/DataTable.css index 7c2d4f215..aec8bb072 100644 --- a/package/DataTable.css +++ b/package/DataTable.css @@ -154,3 +154,82 @@ } } } + +.mantine-datatable-pin-first-column:not(.mantine-datatable-selection-column-visible) + th:not(.mantine-datatable-column-group-header-cell):first-of-type, +.mantine-datatable-pin-first-column:not(.mantine-datatable-selection-column-visible) + td:not(.mantine-datatable-row-expansion-cell):first-of-type, +.mantine-datatable-pin-first-column.mantine-datatable-selection-column-visible + th:not(.mantine-datatable-column-group-header-cell):nth-of-type(2), +.mantine-datatable-pin-first-column.mantine-datatable-selection-column-visible + td:not(.mantine-datatable-row-expansion-cell):nth-of-type(2) { + position: sticky; + left: var(--mantine-datatable-selection-column-width); + z-index: 1; + + &::after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + right: calc(-1 * var(--mantine-spacing-xs)); + border-left: 1px solid var(--mantine-datatable-row-border-color); + width: var(--mantine-spacing-xs); + background: var(--mantine-datatable-shadow-background-left); + pointer-events: none; + opacity: 0; + transition: opacity 0.2s; + } +} + +.mantine-datatable-pin-first-column:not(.mantine-datatable-selection-column-visible) + th:not(.mantine-datatable-column-group-header-cell):first-of-type, +.mantine-datatable-pin-first-column:not(.mantine-datatable-selection-column-visible) + tr[data-with-row-border]:not(:last-of-type) + td:not(.mantine-datatable-row-expansion-cell):first-of-type, +.mantine-datatable-pin-first-column.mantine-datatable-selection-column-visible + th:not(.mantine-datatable-column-group-header-cell):nth-of-type(2), +.mantine-datatable-pin-first-column.mantine-datatable-selection-column-visible + tr[data-with-row-border]:not(:last-of-type) + td:not(.mantine-datatable-row-expansion-cell):nth-of-type(2) { + &::after { + top: rem(-1px); + bottom: rem(-1px); + } +} + +.mantine-datatable-pin-first-column:not(.mantine-datatable-selection-column-visible) tfoot th:first-of-type::after, +.mantine-datatable-pin-first-column.mantine-datatable-selection-column-visible tfoot th:nth-of-type(2)::after { + top: rem(-1px); +} + +.mantine-datatable-pin-first-column:not(.mantine-datatable-selection-column-visible) + tr[data-selected] + td:not(.mantine-datatable-row-expansion-cell):first-of-type, +.mantine-datatable-pin-first-column.mantine-datatable-selection-column-visible + tr[data-selected] + td:not(.mantine-datatable-row-expansion-cell):nth-of-type(2) { + background: inherit; + &::before { + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: var(--mantine-primary-color-light); + } +} + +.mantine-datatable-pin-first-column-scrolled:not(.mantine-datatable-selection-column-visible) + th:not(.mantine-datatable-column-group-header-cell):first-of-type, +.mantine-datatable-pin-first-column-scrolled:not(.mantine-datatable-selection-column-visible) + td:not(.mantine-datatable-row-expansion-cell):first-of-type, +.mantine-datatable-pin-first-column-scrolled.mantine-datatable-selection-column-visible + th:not(.mantine-datatable-column-group-header-cell):nth-of-type(2), +.mantine-datatable-pin-first-column-scrolled.mantine-datatable-selection-column-visible + td:not(.mantine-datatable-row-expansion-cell):nth-of-type(2) { + &::after { + opacity: 1; + } +} diff --git a/package/DataTable.tsx b/package/DataTable.tsx index c83f1d502..f9ddb6454 100644 --- a/package/DataTable.tsx +++ b/package/DataTable.tsx @@ -1,7 +1,7 @@ import { Box, Table, type MantineSize } from '@mantine/core'; import { useMergedRef } from '@mantine/hooks'; import clsx from 'clsx'; -import { useCallback, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { DataTableColumnsProvider } from './DataTableDragToggleProvider'; import { DataTableEmptyRow } from './DataTableEmptyRow'; import { DataTableEmptyState } from './DataTableEmptyState'; @@ -35,6 +35,7 @@ export function DataTable({ columns, storeColumnsKey, groups, + pinFirstColumn, pinLastColumn, defaultColumnProps, defaultColumnRender, @@ -147,6 +148,13 @@ export function DataTable({ const mergedTableRef = useMergedRef(localTableRef, tableRef); + const selectionColumnHeaderRef = useRef(null); + const [selectionColumnWidth, setSelectionColumnWidth] = useState(0); + + useEffect(() => { + if (selectionColumnHeaderRef.current) setSelectionColumnWidth(selectionColumnHeaderRef.current.offsetWidth); + }, []); + const [scrolledToTop, setScrolledToTop] = useState(true); const [scrolledToBottom, setScrolledToBottom] = useState(true); const [scrolledToLeft, setScrolledToLeft] = useState(true); @@ -287,7 +295,7 @@ export function DataTable({ viewportRef={useMergedRef(scrollViewportRef, scrollViewportRefProp)} topShadowVisible={!scrolledToTop} leftShadowVisible={!scrolledToLeft} - leftShadowBehind={selectionColumnVisible} + leftShadowBehind={selectionColumnVisible || !!pinFirstColumn} rightShadowVisible={!scrolledToRight} rightShadowBehind={pinLastColumn} bottomShadowVisible={!scrolledToBottom} @@ -308,10 +316,16 @@ export function DataTable({ 'mantine-datatable-last-row-border-bottom-visible': tableHeight < scrollViewportHeight, 'mantine-datatable-pin-last-column': pinLastColumn, 'mantine-datatable-pin-last-column-scrolled': !scrolledToRight && pinLastColumn, + 'mantine-datatable-selection-column-visible': selectionColumnVisible, + 'mantine-datatable-pin-first-column': pinFirstColumn, + 'mantine-datatable-pin-first-column-scrolled': !scrolledToLeft && pinFirstColumn, }, classNames?.table )} - style={styles?.table} + style={{ + ...styles?.table, + '--mantine-datatable-selection-column-width': `${selectionColumnWidth}px`, + }} data-striped={(recordsLength && striped) || undefined} data-highlight-on-hover={highlightOnHover || undefined} {...otherProps} @@ -320,6 +334,7 @@ export function DataTable({ ref={headerRef} + selectionColumnHeaderRef={selectionColumnHeaderRef} className={classNames?.header} style={styles?.header} columns={effectiveColumns} diff --git a/package/DataTableHeader.tsx b/package/DataTableHeader.tsx index 9b922ad98..4bd2c927f 100644 --- a/package/DataTableHeader.tsx +++ b/package/DataTableHeader.tsx @@ -7,6 +7,7 @@ import { DataTableHeaderSelectorCell } from './DataTableHeaderSelectorCell'; import type { DataTableColumn, DataTableColumnGroup, DataTableSelectionTrigger, DataTableSortProps } from './types'; type DataTableHeaderProps = { + selectionColumnHeaderRef: React.ForwardedRef; className: string | undefined; style?: MantineStyleProp; sortStatus: DataTableSortProps['sortStatus']; @@ -28,6 +29,7 @@ type DataTableHeaderProps = { export const DataTableHeader = forwardRef(function DataTableHeader( { + selectionColumnHeaderRef, className, style, sortStatus, @@ -50,6 +52,7 @@ export const DataTableHeader = forwardRef(function DataTableHeader( ) { const allRecordsSelectorCell = selectionVisible ? ( +) { const enabled = !checkboxProps.disabled; return ( ); -} +}); diff --git a/package/types/DataTableProps.ts b/package/types/DataTableProps.ts index 36782cb8c..12cd06aaa 100644 --- a/package/types/DataTableProps.ts +++ b/package/types/DataTableProps.ts @@ -72,6 +72,11 @@ export type DataTableProps> = { */ fetching?: boolean; + /** + * If true, the first column will be pinned to the left side of the table. + */ + pinFirstColumn?: boolean; + /** * If true, the last column will be pinned to the right side of the table. */ From eaf59eda06294da1f2e3b6c909c4fedd0f8a2343 Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Thu, 4 Jan 2024 22:50:57 +0200 Subject: [PATCH 2/9] Add reminder to extract a hook --- package/DataTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/DataTable.tsx b/package/DataTable.tsx index f9ddb6454..18b445c9c 100644 --- a/package/DataTable.tsx +++ b/package/DataTable.tsx @@ -148,9 +148,9 @@ export function DataTable({ const mergedTableRef = useMergedRef(localTableRef, tableRef); + // todo extract this to a hook before merging const selectionColumnHeaderRef = useRef(null); const [selectionColumnWidth, setSelectionColumnWidth] = useState(0); - useEffect(() => { if (selectionColumnHeaderRef.current) setSelectionColumnWidth(selectionColumnHeaderRef.current.offsetWidth); }, []); From 94a5fc36cc34cc97453941d32f236cf364cdbe3f Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Mon, 8 Jan 2024 19:00:14 +0200 Subject: [PATCH 3/9] Refactor selection column width computation to useElementOuterSize --- package/DataTable.tsx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/package/DataTable.tsx b/package/DataTable.tsx index 18b445c9c..946876840 100644 --- a/package/DataTable.tsx +++ b/package/DataTable.tsx @@ -1,7 +1,7 @@ import { Box, Table, type MantineSize } from '@mantine/core'; import { useMergedRef } from '@mantine/hooks'; import clsx from 'clsx'; -import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useCallback, useMemo, useState } from 'react'; import { DataTableColumnsProvider } from './DataTableDragToggleProvider'; import { DataTableEmptyRow } from './DataTableEmptyRow'; import { DataTableEmptyState } from './DataTableEmptyState'; @@ -145,16 +145,9 @@ export function DataTable({ const { ref: localTableRef, width: tableWidth, height: tableHeight } = useElementOuterSize(); const { ref: footerRef, height: footerHeight } = useElementOuterSize(); const { ref: paginationRef, height: paginationHeight } = useElementOuterSize(); - + const { ref: selectionColumnHeaderRef, width: selectionColumnWidth } = useElementOuterSize(); const mergedTableRef = useMergedRef(localTableRef, tableRef); - // todo extract this to a hook before merging - const selectionColumnHeaderRef = useRef(null); - const [selectionColumnWidth, setSelectionColumnWidth] = useState(0); - useEffect(() => { - if (selectionColumnHeaderRef.current) setSelectionColumnWidth(selectionColumnHeaderRef.current.offsetWidth); - }, []); - const [scrolledToTop, setScrolledToTop] = useState(true); const [scrolledToBottom, setScrolledToBottom] = useState(true); const [scrolledToLeft, setScrolledToLeft] = useState(true); From 9c11015794f8bd45e93c5c3e0d6e30b007a66827 Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Mon, 8 Jan 2024 19:24:30 +0200 Subject: [PATCH 4/9] Update fist col pinning examples --- .../PinFirstColumnExamples.tsx | 130 +++++++++++++++--- .../pinning-the-first-column/page.tsx | 16 ++- 2 files changed, 120 insertions(+), 26 deletions(-) diff --git a/app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx b/app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx index 626ede588..0d7d967b6 100644 --- a/app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx +++ b/app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx @@ -49,20 +49,17 @@ export function PinFirstColumnExampleWithoutRecordSelection() { // example-skip other table props withTableBorder columns={[ - { accessor: 'firstName', noWrap: true }, - { accessor: 'lastName', noWrap: true }, - { accessor: 'department.name', title: 'Department' }, - { accessor: 'department.company.name', title: 'Company', noWrap: true }, - { accessor: 'department.company.city', title: 'City', noWrap: true }, - { accessor: 'department.company.state', title: 'State' }, - { accessor: 'department.company.streetAddress', title: 'Address', noWrap: true }, - { accessor: 'department.company.missionStatement', title: 'Mission statement', noWrap: true }, { accessor: 'actions', - title: Row actions, - textAlign: 'right', + title: ( + + + + + + ), render: (employee) => ( - + ), }, + { accessor: 'firstName', noWrap: true }, + { accessor: 'lastName', noWrap: true }, + { accessor: 'department.name', title: 'Department' }, + { accessor: 'department.company.name', title: 'Company', noWrap: true }, + { accessor: 'department.company.city', title: 'City', noWrap: true }, + { accessor: 'department.company.state', title: 'State' }, + { accessor: 'department.company.streetAddress', title: 'Address', noWrap: true }, + { accessor: 'department.company.missionStatement', title: 'Mission statement', noWrap: true }, ]} records={records} // example-resume @@ -110,20 +115,17 @@ export function PinFirstColumnExampleWithRecordSelection() { // example-skip other table props withTableBorder columns={[ - { accessor: 'firstName', noWrap: true }, - { accessor: 'lastName', noWrap: true }, - { accessor: 'department.name', title: 'Department' }, - { accessor: 'department.company.name', title: 'Company', noWrap: true }, - { accessor: 'department.company.city', title: 'City', noWrap: true }, - { accessor: 'department.company.state', title: 'State' }, - { accessor: 'department.company.streetAddress', title: 'Address', noWrap: true }, - { accessor: 'department.company.missionStatement', title: 'Mission statement', noWrap: true }, { accessor: 'actions', - title: Row actions, - textAlign: 'right', + title: ( + + + + + + ), render: (employee) => ( - + ), }, + { accessor: 'firstName', noWrap: true }, + { accessor: 'lastName', noWrap: true }, + { accessor: 'department.name', title: 'Department' }, + { accessor: 'department.company.name', title: 'Company', noWrap: true }, + { accessor: 'department.company.city', title: 'City', noWrap: true }, + { accessor: 'department.company.state', title: 'State' }, + { accessor: 'department.company.streetAddress', title: 'Address', noWrap: true }, + { accessor: 'department.company.missionStatement', title: 'Mission statement', noWrap: true }, + ]} + records={records} + // example-resume + /> + ); + // example-end +} + +export function PinFirstAndLastColumnsExampleWithRecordSelection() { + const [selectedRecord, setSelectedRecord] = useState([]); + + // example-start first-last-and-record-selection + return ( + + + + + ), + render: (employee) => ( + + showModal({ employee, action: 'view' })} + > + + + showModal({ employee, action: 'edit' })} + > + + + + ), + }, + { accessor: 'firstName', noWrap: true }, + { accessor: 'lastName', noWrap: true }, + { accessor: 'department.name', title: 'Department' }, + { accessor: 'department.company.name', title: 'Company', noWrap: true }, + { accessor: 'department.company.city', title: 'City', noWrap: true }, + { accessor: 'department.company.state', title: 'State' }, + { accessor: 'department.company.streetAddress', title: 'Address', noWrap: true }, + { accessor: 'department.company.missionStatement', title: 'Mission statement', noWrap: true }, + { + accessor: 'delete', + title: ( + + + + ), + render: (employee) => ( + showModal({ employee, action: 'delete' })} + > + + + ), + }, ]} records={records} // example-resume diff --git a/app/examples/pinning-the-first-column/page.tsx b/app/examples/pinning-the-first-column/page.tsx index 2cf9e8593..9354a930d 100644 --- a/app/examples/pinning-the-first-column/page.tsx +++ b/app/examples/pinning-the-first-column/page.tsx @@ -8,6 +8,7 @@ import { Txt } from '~/components/Txt'; import { readCodeFile } from '~/lib/code'; import { getRouteMetadata } from '~/lib/utils'; import { + PinFirstAndLastColumnsExampleWithRecordSelection, PinFirstColumnExampleWithoutRecordSelection, PinFirstColumnExampleWithRecordSelection, } from './PinFirstColumnExamples'; @@ -17,9 +18,9 @@ const PATH: Route = '/examples/pinning-the-first-column'; export const metadata = getRouteMetadata(PATH); export default async function PinFirstColumnExamplePage() { - const code = await readCodeFile>( - `${PATH}/PinFirstColumnExamples.tsx` - ); + const code = await readCodeFile< + Record<'without-record-selection' | 'with-record-selection' | 'first-last-and-record-selection', string> + >(`${PATH}/PinFirstColumnExamples.tsx`); return ( <> @@ -33,7 +34,7 @@ export default async function PinFirstColumnExamplePage() { visible. - You can achieve this by setting the pinLastColumn DataTable prop to true: + You can achieve this by setting the pinFirstColumn DataTable prop to true: Here is the code: @@ -46,6 +47,13 @@ export default async function PinFirstColumnExamplePage() { Here is the code: + + You can use row selection and pin both the first + and the last column at the same time: + + + Here is the code: + Combining this feature with column grouping may lead to minor visual artifacts. From 2e306d59a394ccfa24eacbf45ef56c310947a0ae Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Mon, 8 Jan 2024 19:31:08 +0200 Subject: [PATCH 5/9] Fix minor selector cell shadow issue with pinFirstColumn --- package/DataTable.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package/DataTable.tsx b/package/DataTable.tsx index 946876840..a06e877be 100644 --- a/package/DataTable.tsx +++ b/package/DataTable.tsx @@ -250,7 +250,7 @@ export function DataTable({ ]); const { lastSelectionChangeIndex, setLastSelectionChangeIndex } = useLastSelectionChangeIndex(recordIds); - const selectionVisibleAndNotScrolledToLeft = selectionColumnVisible && !scrolledToLeft; + const selectorCellShadowVisible = selectionColumnVisible && !scrolledToLeft && !pinFirstColumn; const marginProperties = { m, my, mx, mt, mb, ml, mr }; @@ -342,7 +342,7 @@ export function DataTable({ selectionIndeterminate={someRecordsSelected && !allSelectableRecordsSelected} onSelectionChange={handleHeaderSelectionChange} selectionCheckboxProps={allRecordsSelectionCheckboxProps} - selectorCellShadowVisible={selectionVisibleAndNotScrolledToLeft} + selectorCellShadowVisible={selectorCellShadowVisible} selectionColumnClassName={selectionColumnClassName} selectionColumnStyle={selectionColumnStyle} /> @@ -411,7 +411,7 @@ export function DataTable({ className={rowClassName} style={rowStyle} customAttributes={customRowAttributes} - selectorCellShadowVisible={selectionVisibleAndNotScrolledToLeft} + selectorCellShadowVisible={selectorCellShadowVisible} selectionColumnClassName={selectionColumnClassName} selectionColumnStyle={selectionColumnStyle} /> @@ -429,7 +429,7 @@ export function DataTable({ columns={effectiveColumns} defaultColumnProps={defaultColumnProps} selectionVisible={selectionColumnVisible} - selectorCellShadowVisible={selectionVisibleAndNotScrolledToLeft} + selectorCellShadowVisible={selectorCellShadowVisible} scrollDiff={tableHeight - scrollViewportHeight} /> )} From d474d02139066f28af98455d0e1dfa450c7ec9ba Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Mon, 8 Jan 2024 19:35:43 +0200 Subject: [PATCH 6/9] Update changelog & bump version --- CHANGELOG.md | 3 ++- package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e74de7807..c160df901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,9 @@ The following is a list of notable changes to the Mantine DataTable component. Minor versions that are not listed in the changelog are bug fixes and small improvements. -## 7.4.1 (2024-01-04) +## 7.4.1 (2024-01-08) +- Implement `pinFirstColumn` feature - Expose `tableRef` property to access the table element ## 7.4.0 (2024-01-04) diff --git a/package.json b/package.json index c2f39d160..f6dce2b68 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mantine-datatable", - "version": "7.4.0", + "version": "7.4.1", "description": "The lightweight, dependency-free, dark-theme aware table component for your Mantine UI data-rich applications, featuring asynchronous data loading support, pagination, intuitive Gmail-style additive batch rows selection, column sorting, custom cell data rendering, row expansion, nesting, context menus, and much more", "keywords": [ "mantine", From b435929486baf064a794f6fc972009e391333280 Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Mon, 8 Jan 2024 19:55:36 +0200 Subject: [PATCH 7/9] Fix #508 --- app/examples/records-selection/RecordsSelectionExamples.tsx | 4 +++- package/DataTableEmptyRow.css | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/examples/records-selection/RecordsSelectionExamples.tsx b/app/examples/records-selection/RecordsSelectionExamples.tsx index ea10f66db..e2db59f1f 100644 --- a/app/examples/records-selection/RecordsSelectionExamples.tsx +++ b/app/examples/records-selection/RecordsSelectionExamples.tsx @@ -27,7 +27,9 @@ export function RecordsSelectionExample() { highlightOnHover withTableBorder withColumnBorders - records={companies} + // records={companies} + mih={200} + records={[]} columns={columns} selectedRecords={selectedRecords} onSelectedRecordsChange={setSelectedRecords} diff --git a/package/DataTableEmptyRow.css b/package/DataTableEmptyRow.css index e22281b56..76da88daa 100644 --- a/package/DataTableEmptyRow.css +++ b/package/DataTableEmptyRow.css @@ -1,3 +1,6 @@ .mantine-datatable-empty-row { - background: transparent; + &, + .mantine-datatable-table[data-highlight-on-hover] tbody &:hover { + background: transparent; + } } From 57ad9a00d260e4454ffddd1aa2a57d554c48c812 Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Mon, 8 Jan 2024 19:57:28 +0200 Subject: [PATCH 8/9] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c160df901..f7278e3bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Minor versions that are not listed in the changelog are bug fixes and small impr ## 7.4.1 (2024-01-08) - Implement `pinFirstColumn` feature +- Fix minor UI glitch when using highlight on hover and the table contains no records (issue [#508](https://github.com/icflorescu/mantine-datatable/issues/508)) - Expose `tableRef` property to access the table element ## 7.4.0 (2024-01-04) From a1c7c0f19423dfe30e941ec58a082cd8d968c63d Mon Sep 17 00:00:00 2001 From: Ionut-Cristian Florescu Date: Mon, 8 Jan 2024 19:59:00 +0200 Subject: [PATCH 9/9] Update dev deps --- package.json | 16 ++--- yarn.lock | 191 +++++++++++++++++++++++++++++---------------------- 2 files changed, 118 insertions(+), 89 deletions(-) diff --git a/package.json b/package.json index f6dce2b68..b8858d6ad 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ }, "devDependencies": { "@docsearch/react": "^3.5.2", - "@ducanh2912/next-pwa": "^10.0.2", + "@ducanh2912/next-pwa": "^10.1.0", "@faker-js/faker": "^8.3.1", "@formkit/auto-animate": "^0.8.1", "@mantine/code-highlight": "^7.4.0", @@ -82,13 +82,13 @@ "@mantine/modals": "^7.4.0", "@mantine/notifications": "^7.4.0", "@tabler/icons-react": "^2.45.0", - "@tanstack/react-query": "^5.17.1", + "@tanstack/react-query": "^5.17.9", "@types/lodash": "^4.14.202", - "@types/node": "^20.10.6", - "@types/react": "^18.2.46", + "@types/node": "^20.10.7", + "@types/react": "^18.2.47", "@types/react-dom": "^18.2.18", - "@typescript-eslint/eslint-plugin": "^6.17.0", - "@typescript-eslint/parser": "^6.17.0", + "@typescript-eslint/eslint-plugin": "^6.18.0", + "@typescript-eslint/parser": "^6.18.0", "clsx": "^2.1.0", "cssnano": "^6.0.3", "dayjs": "^1.11.10", @@ -96,9 +96,9 @@ "eslint-config-next": "^14.0.4", "eslint-config-prettier": "^9.1.0", "lodash": "^4.17.21", - "mantine-contextmenu": "^7.3.3", + "mantine-contextmenu": "^7.4.0", "next": "14.0.4", - "postcss": "^8.4.32", + "postcss": "^8.4.33", "postcss-cli": "^11.0.0", "postcss-import": "^16.0.0", "postcss-preset-mantine": "^1.12.3", diff --git a/yarn.lock b/yarn.lock index 08944fd7e..e7fff727a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1101,15 +1101,15 @@ "@docsearch/css" "3.5.2" algoliasearch "^4.19.1" -"@ducanh2912/next-pwa@^10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@ducanh2912/next-pwa/-/next-pwa-10.0.2.tgz#9020de491f8bd43e65ba095a6f786ead4d68657e" - integrity sha512-6/6+l0L+xHCD9TluaoXlwKHl65iZ0OlvTO2L1YPV9zyZjN9sl4DbEjQ7JbOADnUGGbGVicPE4MhViGJA0+ezjQ== +"@ducanh2912/next-pwa@^10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@ducanh2912/next-pwa/-/next-pwa-10.1.0.tgz#5ca377402ed37938fac756683b6a1c9cf74636ac" + integrity sha512-4jrV+bEiiqP2CQGqRQ3Gx4rpYjRai4bAkTUZLdAMTFXVPFEy825IOL55mj7BESdRQXb4YtpUULr80gREm7sXIA== dependencies: clean-webpack-plugin "4.0.0" fast-glob "3.3.2" semver "7.5.4" - terser-webpack-plugin "5.3.9" + terser-webpack-plugin "5.3.10" workbox-build "7.0.0" workbox-core "7.0.0" workbox-webpack-plugin "7.0.0" @@ -1482,6 +1482,14 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.20": + version "0.3.20" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" + integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@mantine/code-highlight@^7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@mantine/code-highlight/-/code-highlight-7.4.0.tgz#55c9fdf797529776a0d1e6c05342cfc45222abee" @@ -1747,17 +1755,17 @@ resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-2.45.0.tgz#c6dff8df5b33492b832a65b778e8be4b45eed739" integrity sha512-J10UDghOni9wlrj5CpKAzychDCABCKYq897mGg0wGFsd+tYLaUdz0dt/HZeGnV8gZJo0hIiTPLGwBp5EW42Qsg== -"@tanstack/query-core@5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.17.1.tgz#341d975dce20c5c9e0767a3a69c0bfbc9ca16114" - integrity sha512-kUXozQmU7NBtzX5dM6qfFNZN+YK/9Ct37hnG/ogdgI4mExIx7VH/qRepsPhKfNrJz2w81/JykmM3Uug6sVpUSw== +"@tanstack/query-core@5.17.9": + version "5.17.9" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.17.9.tgz#1dac85c7c674bdfd132fe7cd5cb898921000bdcf" + integrity sha512-8xcvpWIPaRMDNLMvG9ugcUJMgFK316ZsqkPPbsI+TMZsb10N9jk0B6XgPk4/kgWC2ziHyWR7n7wUhxmD0pChQw== -"@tanstack/react-query@^5.17.1": - version "5.17.1" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.17.1.tgz#37efbb4573d3f4cc8c62e5ea6c7398d27f52db2a" - integrity sha512-4JYgX0kU+pvwVQi5eRiHGvBK7WnahEl6lmaxd32ZVSKmByAxLgaewoxBR03cdDNse8lUD2zGOe0sx3M/EGRlmA== +"@tanstack/react-query@^5.17.9": + version "5.17.9" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.17.9.tgz#74826465c1b2ecde17c6d2f1d03f10b611ac2363" + integrity sha512-M5E9gwUq1Stby/pdlYjBlL24euIVuGbWKIFCbtnQxSdXI4PgzjTSdXdV3QE6fc+itF+TUvX/JPTKIwq8yuBXcg== dependencies: - "@tanstack/query-core" "5.17.1" + "@tanstack/query-core" "5.17.9" "@trysound/sax@0.2.0": version "0.2.0" @@ -1823,10 +1831,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.9.tgz#c7164e0f8d3f12dfae336af0b1f7fdec8c6b204f" integrity sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ== -"@types/node@^20.10.6": - version "20.10.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.6.tgz#a3ec84c22965802bf763da55b2394424f22bfbb5" - integrity sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw== +"@types/node@^20.10.7": + version "20.10.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.7.tgz#40fe8faf25418a75de9fe68a8775546732a3a901" + integrity sha512-fRbIKb8C/Y2lXxB5eVMj4IU7xpdox0Lh8bUPEdtLysaylsml1hOOx1+STloRs/B9nf7C6kPRmmg/V7aQW7usNg== dependencies: undici-types "~5.26.4" @@ -1851,10 +1859,10 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/react@^18.2.46": - version "18.2.46" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.46.tgz#f04d6c528f8f136ea66333bc66abcae46e2680df" - integrity sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w== +"@types/react@^18.2.47": + version "18.2.47" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.47.tgz#85074b27ab563df01fbc3f68dc64bf7050b0af40" + integrity sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -1882,16 +1890,16 @@ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311" integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g== -"@typescript-eslint/eslint-plugin@^6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz#dfc38f790704ba8a54a1277c51efdb489f6ecf9f" - integrity sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ== +"@typescript-eslint/eslint-plugin@^6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.0.tgz#94b86f3c25b468c714a04bd490017ecec2fd3746" + integrity sha512-3lqEvQUdCozi6d1mddWqd+kf8KxmGq2Plzx36BlkjuQe3rSTm/O98cLf0A4uDO+a5N1KD2SeEEl6fW97YHY+6w== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.17.0" - "@typescript-eslint/type-utils" "6.17.0" - "@typescript-eslint/utils" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" + "@typescript-eslint/scope-manager" "6.18.0" + "@typescript-eslint/type-utils" "6.18.0" + "@typescript-eslint/utils" "6.18.0" + "@typescript-eslint/visitor-keys" "6.18.0" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -1910,24 +1918,24 @@ "@typescript-eslint/visitor-keys" "6.3.0" debug "^4.3.4" -"@typescript-eslint/parser@^6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.17.0.tgz#8cd7a0599888ca6056082225b2fdf9a635bf32a1" - integrity sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A== +"@typescript-eslint/parser@^6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.18.0.tgz#d494161d64832e869f0a6acc6000a2cdff858383" + integrity sha512-v6uR68SFvqhNQT41frCMCQpsP+5vySy6IdgjlzUWoo7ALCnpaWYcz/Ij2k4L8cEsL0wkvOviCMpjmtRtHNOKzA== dependencies: - "@typescript-eslint/scope-manager" "6.17.0" - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/typescript-estree" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" + "@typescript-eslint/scope-manager" "6.18.0" + "@typescript-eslint/types" "6.18.0" + "@typescript-eslint/typescript-estree" "6.18.0" + "@typescript-eslint/visitor-keys" "6.18.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz#70e6c1334d0d76562dfa61aed9009c140a7601b4" - integrity sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA== +"@typescript-eslint/scope-manager@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.18.0.tgz#24ca6fc1f4a2afa71122dcfca9282878687d9997" + integrity sha512-o/UoDT2NgOJ2VfHpfr+KBY2ErWvCySNUIX/X7O9g8Zzt/tXdpfEU43qbNk8LVuWUT2E0ptzTWXh79i74PP0twA== dependencies: - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" + "@typescript-eslint/types" "6.18.0" + "@typescript-eslint/visitor-keys" "6.18.0" "@typescript-eslint/scope-manager@6.3.0": version "6.3.0" @@ -1937,33 +1945,33 @@ "@typescript-eslint/types" "6.3.0" "@typescript-eslint/visitor-keys" "6.3.0" -"@typescript-eslint/type-utils@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz#5febad3f523e393006614cbda28b826925b728d5" - integrity sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg== +"@typescript-eslint/type-utils@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.18.0.tgz#a492da599da5c38c70aa9ff9bfb473961b8ae663" + integrity sha512-ZeMtrXnGmTcHciJN1+u2CigWEEXgy1ufoxtWcHORt5kGvpjjIlK9MUhzHm4RM8iVy6dqSaZA/6PVkX6+r+ChjQ== dependencies: - "@typescript-eslint/typescript-estree" "6.17.0" - "@typescript-eslint/utils" "6.17.0" + "@typescript-eslint/typescript-estree" "6.18.0" + "@typescript-eslint/utils" "6.18.0" debug "^4.3.4" ts-api-utils "^1.0.1" -"@typescript-eslint/types@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.17.0.tgz#844a92eb7c527110bf9a7d177e3f22bd5a2f40cb" - integrity sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A== +"@typescript-eslint/types@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.18.0.tgz#ffce610a1540c17cf7d8ecf2bb34b8b0e2e77101" + integrity sha512-/RFVIccwkwSdW/1zeMx3hADShWbgBxBnV/qSrex6607isYjj05t36P6LyONgqdUrNLl5TYU8NIKdHUYpFvExkA== "@typescript-eslint/types@6.3.0": version "6.3.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.3.0.tgz#84517f1427923e714b8418981e493b6635ab4c9d" integrity sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg== -"@typescript-eslint/typescript-estree@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz#b913d19886c52d8dc3db856903a36c6c64fd62aa" - integrity sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg== +"@typescript-eslint/typescript-estree@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.0.tgz#1c357c3ca435c3cfa2af6b9daf45ca0bc2bb059a" + integrity sha512-klNvl+Ql4NsBNGB4W9TZ2Od03lm7aGvTbs0wYaFYsplVPhr+oeXjlPZCDI4U9jgJIDK38W1FKhacCFzCC+nbIg== dependencies: - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/visitor-keys" "6.17.0" + "@typescript-eslint/types" "6.18.0" + "@typescript-eslint/visitor-keys" "6.18.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -1984,25 +1992,25 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.17.0.tgz#f2b16d4c9984474656c420438cdede7eccd4079e" - integrity sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ== +"@typescript-eslint/utils@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.18.0.tgz#4d07c9c08f84b9939a1aca7aef98c8f378936142" + integrity sha512-wiKKCbUeDPGaYEYQh1S580dGxJ/V9HI7K5sbGAVklyf+o5g3O+adnS4UNJajplF4e7z2q0uVBaTdT/yLb4XAVA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.17.0" - "@typescript-eslint/types" "6.17.0" - "@typescript-eslint/typescript-estree" "6.17.0" + "@typescript-eslint/scope-manager" "6.18.0" + "@typescript-eslint/types" "6.18.0" + "@typescript-eslint/typescript-estree" "6.18.0" semver "^7.5.4" -"@typescript-eslint/visitor-keys@6.17.0": - version "6.17.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz#3ed043709c39b43ec1e58694f329e0b0430c26b6" - integrity sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg== +"@typescript-eslint/visitor-keys@6.18.0": + version "6.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.0.tgz#3c8733737786fa6c78a347b4fa306ae7155b560f" + integrity sha512-1wetAlSZpewRDb2h9p/Q8kRjdGuqdTAQbkJIOUMLug2LBLG+QOjiWoSj6/3B/hA9/tVTFFdtiKvAYoYnSRW/RA== dependencies: - "@typescript-eslint/types" "6.17.0" + "@typescript-eslint/types" "6.18.0" eslint-visitor-keys "^3.4.1" "@typescript-eslint/visitor-keys@6.3.0": @@ -4378,10 +4386,10 @@ magic-string@^0.25.0, magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" -mantine-contextmenu@^7.3.3: - version "7.3.3" - resolved "https://registry.yarnpkg.com/mantine-contextmenu/-/mantine-contextmenu-7.3.3.tgz#a1236efd8c7c7af8800e10154a41aba0cb62121b" - integrity sha512-Sfj53bYTBT5dHeNPBzlLLB1yemxXXMoZn/xkys0jzXorKf8NuRiAV2SLtP9wizrZ8T4AYSZaGLfDyBnKbXiSrg== +mantine-contextmenu@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/mantine-contextmenu/-/mantine-contextmenu-7.4.0.tgz#b0d5015e0d30fc4accf4f04c4047f7114b5e45ec" + integrity sha512-+U9KYHaLN8t6SBR+GH+PLH5gajtBdovQHQwS0gbdckDPd6fGFpcRcMRRXYN9f+2tL4gYaX740kMf4uwnsfZCKw== mdn-data@2.0.28: version "2.0.28" @@ -5054,10 +5062,10 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.32: - version "8.4.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.32.tgz#1dac6ac51ab19adb21b8b34fd2d93a86440ef6c9" - integrity sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw== +postcss@^8.4.33: + version "8.4.33" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" + integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg== dependencies: nanoid "^3.3.7" picocolors "^1.0.0" @@ -5799,7 +5807,18 @@ tempy@^0.6.0: type-fest "^0.16.0" unique-string "^2.0.0" -terser-webpack-plugin@5.3.9, terser-webpack-plugin@^5.3.7: +terser-webpack-plugin@5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser-webpack-plugin@^5.3.7: version "5.3.9" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== @@ -5820,6 +5839,16 @@ terser@^5.0.0, terser@^5.16.8: commander "^2.20.0" source-map-support "~0.5.20" +terser@^5.26.0: + version "5.26.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.26.0.tgz#ee9f05d929f4189a9c28a0feb889d96d50126fe1" + integrity sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"