diff --git a/CHANGELOG.md b/CHANGELOG.md
index e74de7807..f7278e3bc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,8 +3,10 @@
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
+- 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)
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..0d7d967b6
--- /dev/null
+++ b/app/examples/pinning-the-first-column/PinFirstColumnExamples.tsx
@@ -0,0 +1,246 @@
+'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 (
+
+
+
+
+
+ ),
+ render: (employee) => (
+
+ showModal({ employee, action: 'view' })}
+ >
+
+
+ showModal({ employee, action: 'edit' })}
+ >
+
+
+ showModal({ employee, action: 'delete' })}
+ >
+
+
+
+ ),
+ },
+ { 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 PinFirstColumnExampleWithRecordSelection() {
+ const [selectedRecord, setSelectedRecord] = useState([]);
+
+ // example-start with-record-selection
+ return (
+
+
+
+
+
+ ),
+ render: (employee) => (
+
+ showModal({ employee, action: 'view' })}
+ >
+
+
+ showModal({ employee, action: 'edit' })}
+ >
+
+
+ showModal({ employee, action: 'delete' })}
+ >
+
+
+
+ ),
+ },
+ { 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
+ />
+ );
+ // 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..9354a930d
--- /dev/null
+++ b/app/examples/pinning-the-first-column/page.tsx
@@ -0,0 +1,65 @@
+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 {
+ PinFirstAndLastColumnsExampleWithRecordSelection,
+ 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<
+ Record<'without-record-selection' | 'with-record-selection' | 'first-last-and-record-selection', string>
+ >(`${PATH}/PinFirstColumnExamples.tsx`);
+
+ return (
+ <>
+
+ fix, fixed, affix, sticky
+
+ 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 pinFirstColumn
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:
+
+
+ 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.
+
+ 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/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.json b/package.json
index c2f39d160..b8858d6ad 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",
@@ -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/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..a06e877be 100644
--- a/package/DataTable.tsx
+++ b/package/DataTable.tsx
@@ -35,6 +35,7 @@ export function DataTable({
columns,
storeColumnsKey,
groups,
+ pinFirstColumn,
pinLastColumn,
defaultColumnProps,
defaultColumnRender,
@@ -144,7 +145,7 @@ 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);
const [scrolledToTop, setScrolledToTop] = useState(true);
@@ -249,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 };
@@ -287,7 +288,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 +309,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 +327,7 @@ export function DataTable({
ref={headerRef}
+ selectionColumnHeaderRef={selectionColumnHeaderRef}
className={classNames?.header}
style={styles?.header}
columns={effectiveColumns}
@@ -334,7 +342,7 @@ export function DataTable({
selectionIndeterminate={someRecordsSelected && !allSelectableRecordsSelected}
onSelectionChange={handleHeaderSelectionChange}
selectionCheckboxProps={allRecordsSelectionCheckboxProps}
- selectorCellShadowVisible={selectionVisibleAndNotScrolledToLeft}
+ selectorCellShadowVisible={selectorCellShadowVisible}
selectionColumnClassName={selectionColumnClassName}
selectionColumnStyle={selectionColumnStyle}
/>
@@ -403,7 +411,7 @@ export function DataTable({
className={rowClassName}
style={rowStyle}
customAttributes={customRowAttributes}
- selectorCellShadowVisible={selectionVisibleAndNotScrolledToLeft}
+ selectorCellShadowVisible={selectorCellShadowVisible}
selectionColumnClassName={selectionColumnClassName}
selectionColumnStyle={selectionColumnStyle}
/>
@@ -421,7 +429,7 @@ export function DataTable({
columns={effectiveColumns}
defaultColumnProps={defaultColumnProps}
selectionVisible={selectionColumnVisible}
- selectorCellShadowVisible={selectionVisibleAndNotScrolledToLeft}
+ selectorCellShadowVisible={selectorCellShadowVisible}
scrollDiff={tableHeight - scrollViewportHeight}
/>
)}
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;
+ }
}
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.
*/
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"