mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-10 07:25:35 +00:00
feat: sortable table component
This commit is contained in:
22
inertia/components/common/icon_button.tsx
Normal file
22
inertia/components/common/icon_button.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
const IconButton = styled.button(({ theme }) => ({
|
||||||
|
cursor: 'pointer',
|
||||||
|
height: '2rem',
|
||||||
|
width: '2rem',
|
||||||
|
fontSize: '1rem',
|
||||||
|
color: theme.colors.font,
|
||||||
|
backgroundColor: theme.colors.grey,
|
||||||
|
borderRadius: '50%',
|
||||||
|
border: 0,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
|
||||||
|
'&:disabled': {
|
||||||
|
cursor: 'not-allowed',
|
||||||
|
opacity: 0.15,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default IconButton;
|
||||||
218
inertia/components/common/table.tsx
Normal file
218
inertia/components/common/table.tsx
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
import {
|
||||||
|
ColumnDef,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
PaginationState,
|
||||||
|
useReactTable,
|
||||||
|
} from '@tanstack/react-table';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import IconButton from '~/components/common/icon_button';
|
||||||
|
|
||||||
|
import {
|
||||||
|
MdKeyboardArrowLeft,
|
||||||
|
MdKeyboardArrowRight,
|
||||||
|
MdKeyboardDoubleArrowLeft,
|
||||||
|
MdKeyboardDoubleArrowRight,
|
||||||
|
} from 'react-icons/md';
|
||||||
|
import Input from '~/components/common/form/_input';
|
||||||
|
|
||||||
|
const TablePageFooter = styled.div({
|
||||||
|
display: 'flex',
|
||||||
|
gap: '1em',
|
||||||
|
alignItems: 'center',
|
||||||
|
});
|
||||||
|
|
||||||
|
const Box = styled(TablePageFooter)({
|
||||||
|
gap: '0.35em',
|
||||||
|
});
|
||||||
|
|
||||||
|
const Resizer = styled.div<{ isResizing: boolean }>(
|
||||||
|
({ theme, isResizing }) => ({
|
||||||
|
cursor: 'col-resize',
|
||||||
|
userSelect: 'none',
|
||||||
|
touchAction: 'none',
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
height: '100%',
|
||||||
|
width: '5px',
|
||||||
|
opacity: !isResizing ? 0 : 1,
|
||||||
|
background: !isResizing ? theme.colors.white : theme.colors.primary,
|
||||||
|
'&:hover': {
|
||||||
|
opacity: 0.5,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
type TableProps<T> = {
|
||||||
|
columns: ColumnDef<T>[];
|
||||||
|
data: T[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Table<T>({ columns, data }: TableProps<T>) {
|
||||||
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
|
||||||
|
const table = useReactTable({
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
enableColumnResizing: true,
|
||||||
|
columnResizeMode: 'onChange',
|
||||||
|
state: {
|
||||||
|
pagination,
|
||||||
|
},
|
||||||
|
onPaginationChange: setPagination,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
debugTable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div css={{ fontSize: '0.9rem', paddingBlock: '1em' }}>
|
||||||
|
<div
|
||||||
|
css={{
|
||||||
|
maxWidth: '100%',
|
||||||
|
marginBottom: '1em',
|
||||||
|
display: 'block',
|
||||||
|
overflowX: 'auto',
|
||||||
|
overflowY: 'hidden',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
|
<tr key={headerGroup.id}>
|
||||||
|
{headerGroup.headers.map((header) => (
|
||||||
|
<th
|
||||||
|
key={header.id}
|
||||||
|
style={{
|
||||||
|
width: header.getSize(),
|
||||||
|
}}
|
||||||
|
css={{
|
||||||
|
position: 'relative',
|
||||||
|
userSelect: 'none',
|
||||||
|
// resizer
|
||||||
|
'&:hover > div > div': {
|
||||||
|
opacity: 0.5,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
colSpan={header.colSpan}
|
||||||
|
>
|
||||||
|
{header.isPlaceholder ? null : (
|
||||||
|
<div
|
||||||
|
css={{
|
||||||
|
cursor: header.column.getCanSort()
|
||||||
|
? 'pointer'
|
||||||
|
: 'default',
|
||||||
|
}}
|
||||||
|
onClick={header.column.getToggleSortingHandler()}
|
||||||
|
title={
|
||||||
|
header.column.getCanSort()
|
||||||
|
? header.column.getNextSortingOrder() === 'asc'
|
||||||
|
? 'Sort ascending'
|
||||||
|
: header.column.getNextSortingOrder() === 'desc'
|
||||||
|
? 'Sort descending'
|
||||||
|
: 'Clear sort'
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{flexRender(
|
||||||
|
header.column.columnDef.header,
|
||||||
|
header.getContext()
|
||||||
|
)}
|
||||||
|
{{
|
||||||
|
asc: ' 🔼',
|
||||||
|
desc: ' 🔽',
|
||||||
|
}[header.column.getIsSorted() as string] ?? null}
|
||||||
|
{header.column.getCanResize() && (
|
||||||
|
<Resizer
|
||||||
|
onMouseDown={header.getResizeHandler()}
|
||||||
|
onTouchStart={header.getResizeHandler()}
|
||||||
|
isResizing={header.column.getIsResizing()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{table
|
||||||
|
.getRowModel()
|
||||||
|
.rows.slice(0, 10)
|
||||||
|
.map((row) => (
|
||||||
|
<tr key={row.id}>
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<td key={cell.id} style={{ width: cell.column.getSize() }}>
|
||||||
|
{flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext()
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{table.getPageCount() > 1 && (
|
||||||
|
<TablePageFooter>
|
||||||
|
<Box>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => table.setPageIndex(0)}
|
||||||
|
disabled={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
<MdKeyboardDoubleArrowLeft />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => table.previousPage()}
|
||||||
|
disabled={!table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
<MdKeyboardArrowLeft />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => table.nextPage()}
|
||||||
|
disabled={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
<MdKeyboardArrowRight />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
|
||||||
|
disabled={!table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
<MdKeyboardDoubleArrowRight />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<span>Page</span>
|
||||||
|
<strong>
|
||||||
|
{table.getState().pagination.pageIndex + 1} of{' '}
|
||||||
|
{table.getPageCount()}
|
||||||
|
</strong>
|
||||||
|
</Box>
|
||||||
|
<Box>
|
||||||
|
Go to page
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max={table.getPageCount()}
|
||||||
|
defaultValue={table.getState().pagination.pageIndex + 1}
|
||||||
|
onChange={(e) => {
|
||||||
|
const page = e.target.value ? Number(e.target.value) - 1 : 0;
|
||||||
|
table.setPageIndex(page);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</TablePageFooter>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -131,7 +131,9 @@ function GlobalStyles() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'th, td': {
|
'th, td': {
|
||||||
whiteSpace: 'nowrap',
|
whiteSspace: 'nowrap',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
},
|
},
|
||||||
|
|
||||||
'tr:nth-of-type(even)': {
|
'tr:nth-of-type(even)': {
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||||
import { ReactNode } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import RoundedImage from '~/components/common/rounded_image';
|
import Table from '~/components/common/table';
|
||||||
import TextEllipsis from '~/components/common/text_ellipsis';
|
|
||||||
import ContentLayout from '~/components/layouts/content_layout';
|
import ContentLayout from '~/components/layouts/content_layout';
|
||||||
import { DATE_FORMAT } from '~/constants';
|
import { DATE_FORMAT } from '~/constants';
|
||||||
import { sortByCreationDate } from '~/lib/array';
|
|
||||||
import { UserWithRelationCount } from '~/types/app';
|
import { UserWithRelationCount } from '~/types/app';
|
||||||
|
|
||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
@@ -19,15 +18,18 @@ interface AdminDashboardProps {
|
|||||||
totalLinks: number;
|
totalLinks: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Cell = styled.div<{ column?: boolean; fixed?: boolean }>(
|
const CenteredCell = styled.div({
|
||||||
({ column, fixed }) => ({
|
display: 'flex',
|
||||||
width: '100%',
|
alignItems: 'center',
|
||||||
display: 'flex',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
flexDirection: 'column',
|
||||||
justifyContent: fixed ? 'unset' : 'center',
|
});
|
||||||
gap: column ? 0 : '0.35em',
|
|
||||||
flexDirection: column ? 'column' : 'row',
|
const RenderDateCell = (info: any) => (
|
||||||
})
|
<CenteredCell>
|
||||||
|
<span>{dayjs(info.getValue().toString()).fromNow()}</span>
|
||||||
|
<span>{dayjs(info.getValue().toString()).format(DATE_FORMAT)}</span>
|
||||||
|
</CenteredCell>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ThemeProvider = (props: AdminDashboardProps) => (
|
const ThemeProvider = (props: AdminDashboardProps) => (
|
||||||
@@ -44,95 +46,76 @@ function AdminDashboard({
|
|||||||
}: AdminDashboardProps) {
|
}: AdminDashboardProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
return (
|
const columns = useMemo(
|
||||||
<div style={{ overflow: 'auto', marginTop: '1em' }}>
|
() =>
|
||||||
<table>
|
[
|
||||||
<thead>
|
{
|
||||||
<tr>
|
accessorKey: 'id',
|
||||||
<TableCell type="th">#</TableCell>
|
header: (
|
||||||
<TableCell type="th">{t('common:name')}</TableCell>
|
<>
|
||||||
<TableCell type="th">{t('common:email')}</TableCell>
|
# <span css={{ color: theme.colors.grey }}>({users.length})</span>
|
||||||
<TableCell type="th">
|
</>
|
||||||
|
),
|
||||||
|
cell: (info) => info.getValue(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'fullname',
|
||||||
|
header: t('common:name'),
|
||||||
|
cell: (info) => info.getValue(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'email',
|
||||||
|
header: t('common:email'),
|
||||||
|
cell: (info) => info.getValue(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'count',
|
||||||
|
header: (
|
||||||
|
<>
|
||||||
{t('common:collection.collections', { count: totalCollections })}{' '}
|
{t('common:collection.collections', { count: totalCollections })}{' '}
|
||||||
<span css={{ color: theme.colors.grey }}>
|
<span css={{ color: theme.colors.grey }}>
|
||||||
({totalCollections})
|
({totalCollections})
|
||||||
</span>
|
</span>
|
||||||
</TableCell>
|
</>
|
||||||
<TableCell type="th">
|
),
|
||||||
|
cell: (info) => (info.getValue() as any)?.collection,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'count',
|
||||||
|
header: (
|
||||||
|
<>
|
||||||
{t('common:link.links', { count: totalLinks })}{' '}
|
{t('common:link.links', { count: totalLinks })}{' '}
|
||||||
<span css={{ color: theme.colors.grey }}>({totalLinks})</span>
|
<span css={{ color: theme.colors.grey }}>({totalLinks})</span>
|
||||||
</TableCell>
|
</>
|
||||||
<TableCell type="th">{t('admin:role')}</TableCell>
|
),
|
||||||
<TableCell type="th">{t('admin:created_at')}</TableCell>
|
cell: (info: any) => info.getValue()?.link,
|
||||||
<TableCell type="th">{t('admin:updated_at')}</TableCell>
|
},
|
||||||
</tr>
|
{
|
||||||
</thead>
|
accessorKey: 'isAdmin',
|
||||||
<tbody>
|
header: t('admin:role'),
|
||||||
{users.length !== 0 &&
|
cell: (info) =>
|
||||||
sortByCreationDate(users).map((user) => (
|
info.getValue() ? (
|
||||||
<TableUserRow user={user} key={user.id} />
|
<span style={{ color: theme.colors.lightRed }}>
|
||||||
))}
|
{t('admin:admin')}
|
||||||
</tbody>
|
</span>
|
||||||
</table>
|
) : (
|
||||||
</div>
|
<span style={{ color: theme.colors.green }}>
|
||||||
|
{t('admin:user')}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'createdAt',
|
||||||
|
header: t('admin:created_at'),
|
||||||
|
cell: RenderDateCell,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'updatedAt',
|
||||||
|
header: t('admin:updated_at'),
|
||||||
|
cell: RenderDateCell,
|
||||||
|
},
|
||||||
|
] as ColumnDef<UserWithRelationCount>[],
|
||||||
|
[]
|
||||||
);
|
);
|
||||||
}
|
return <Table columns={columns} data={users} />;
|
||||||
|
|
||||||
function TableUserRow({ user }: { user: UserWithRelationCount }) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const theme = useTheme();
|
|
||||||
const { id, fullname, avatarUrl, email, isAdmin, createdAt, updatedAt } =
|
|
||||||
user;
|
|
||||||
return (
|
|
||||||
<tr>
|
|
||||||
<TableCell type="td">{id}</TableCell>
|
|
||||||
<TableCell type="td" fixed>
|
|
||||||
{avatarUrl && (
|
|
||||||
<RoundedImage
|
|
||||||
src={avatarUrl}
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
alt={fullname}
|
|
||||||
title={fullname}
|
|
||||||
referrerPolicy="no-referrer"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<TextEllipsis>{fullname ?? '-'}</TextEllipsis>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell type="td">
|
|
||||||
<TextEllipsis>{email}</TextEllipsis>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell type="td">{user.count.collection}</TableCell>
|
|
||||||
<TableCell type="td">{user.count.link}</TableCell>
|
|
||||||
<TableCell type="td">
|
|
||||||
{isAdmin ? (
|
|
||||||
<span style={{ color: theme.colors.lightRed }}>
|
|
||||||
{t('admin:admin')}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span style={{ color: theme.colors.green }}>{t('admin:user')}</span>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell type="td" column>
|
|
||||||
<span>{dayjs(createdAt.toString()).fromNow()}</span>
|
|
||||||
<span>{dayjs(createdAt.toString()).format(DATE_FORMAT)}</span>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell type="td" column>
|
|
||||||
<span>{dayjs(updatedAt.toString()).fromNow()}</span>
|
|
||||||
<span>{dayjs(updatedAt.toString()).format(DATE_FORMAT)}</span>
|
|
||||||
</TableCell>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
type TableItem = {
|
|
||||||
children: ReactNode;
|
|
||||||
type: 'td' | 'th';
|
|
||||||
fixed?: boolean;
|
|
||||||
column?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
function TableCell({ children, type, ...props }: TableItem) {
|
|
||||||
const child = <Cell {...props}>{children}</Cell>;
|
|
||||||
return type === 'td' ? <td>{child}</td> : <th>{child}</th>;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@
|
|||||||
"@emotion/styled": "^11.11.5",
|
"@emotion/styled": "^11.11.5",
|
||||||
"@inertiajs/react": "^1.2.0",
|
"@inertiajs/react": "^1.2.0",
|
||||||
"@izzyjs/route": "^1.1.0-0",
|
"@izzyjs/route": "^1.1.0-0",
|
||||||
|
"@tanstack/react-table": "^8.20.5",
|
||||||
"@vinejs/vine": "^2.1.0",
|
"@vinejs/vine": "^2.1.0",
|
||||||
"bentocache": "^1.0.0-beta.9",
|
"bentocache": "^1.0.0-beta.9",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
|
|||||||
22
pnpm-lock.yaml
generated
22
pnpm-lock.yaml
generated
@@ -50,6 +50,9 @@ importers:
|
|||||||
'@izzyjs/route':
|
'@izzyjs/route':
|
||||||
specifier: ^1.1.0-0
|
specifier: ^1.1.0-0
|
||||||
version: 1.1.0-0(@adonisjs/core@6.12.1(@adonisjs/assembler@7.7.0(babel-plugin-macros@3.1.0)(typescript@5.4.5))(@vinejs/vine@2.1.0)(edge.js@6.0.2))(edge.js@6.0.2)
|
version: 1.1.0-0(@adonisjs/core@6.12.1(@adonisjs/assembler@7.7.0(babel-plugin-macros@3.1.0)(typescript@5.4.5))(@vinejs/vine@2.1.0)(edge.js@6.0.2))(edge.js@6.0.2)
|
||||||
|
'@tanstack/react-table':
|
||||||
|
specifier: ^8.20.5
|
||||||
|
version: 8.20.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@vinejs/vine':
|
'@vinejs/vine':
|
||||||
specifier: ^2.1.0
|
specifier: ^2.1.0
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
@@ -1244,6 +1247,17 @@ packages:
|
|||||||
resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
|
resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
|
||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
|
'@tanstack/react-table@8.20.5':
|
||||||
|
resolution: {integrity: sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=16.8'
|
||||||
|
react-dom: '>=16.8'
|
||||||
|
|
||||||
|
'@tanstack/table-core@8.20.5':
|
||||||
|
resolution: {integrity: sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
'@tokenizer/token@0.3.0':
|
'@tokenizer/token@0.3.0':
|
||||||
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
|
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
|
||||||
|
|
||||||
@@ -5877,6 +5891,14 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect: 2.0.1
|
defer-to-connect: 2.0.1
|
||||||
|
|
||||||
|
'@tanstack/react-table@8.20.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@tanstack/table-core': 8.20.5
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
|
'@tanstack/table-core@8.20.5': {}
|
||||||
|
|
||||||
'@tokenizer/token@0.3.0': {}
|
'@tokenizer/token@0.3.0': {}
|
||||||
|
|
||||||
'@tootallnate/quickjs-emscripten@0.23.0': {}
|
'@tootallnate/quickjs-emscripten@0.23.0': {}
|
||||||
|
|||||||
Reference in New Issue
Block a user