Compare commits
2 Commits
v0.60.2-on
...
new-table-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3476f3032d | ||
|
|
4b757b382f |
@@ -34,6 +34,8 @@
|
|||||||
"@dnd-kit/core": "6.1.0",
|
"@dnd-kit/core": "6.1.0",
|
||||||
"@dnd-kit/modifiers": "7.0.0",
|
"@dnd-kit/modifiers": "7.0.0",
|
||||||
"@dnd-kit/sortable": "8.0.0",
|
"@dnd-kit/sortable": "8.0.0",
|
||||||
|
"@dnd-kit/utilities": "3.2.2",
|
||||||
|
"@faker-js/faker": "8.4.1",
|
||||||
"@grafana/data": "^9.5.2",
|
"@grafana/data": "^9.5.2",
|
||||||
"@mdx-js/loader": "2.3.0",
|
"@mdx-js/loader": "2.3.0",
|
||||||
"@mdx-js/react": "2.3.0",
|
"@mdx-js/react": "2.3.0",
|
||||||
@@ -43,6 +45,7 @@
|
|||||||
"@sentry/react": "7.102.1",
|
"@sentry/react": "7.102.1",
|
||||||
"@sentry/webpack-plugin": "2.16.0",
|
"@sentry/webpack-plugin": "2.16.0",
|
||||||
"@signozhq/design-tokens": "0.0.8",
|
"@signozhq/design-tokens": "0.0.8",
|
||||||
|
"@tanstack/react-table": "8.17.3",
|
||||||
"@uiw/react-md-editor": "3.23.5",
|
"@uiw/react-md-editor": "3.23.5",
|
||||||
"@visx/group": "3.3.0",
|
"@visx/group": "3.3.0",
|
||||||
"@visx/shape": "3.5.0",
|
"@visx/shape": "3.5.0",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { useOptionsMenu } from 'container/OptionsMenu';
|
|||||||
import { useActiveLog } from 'hooks/logs/useActiveLog';
|
import { useActiveLog } from 'hooks/logs/useActiveLog';
|
||||||
import { useCopyLogLink } from 'hooks/logs/useCopyLogLink';
|
import { useCopyLogLink } from 'hooks/logs/useCopyLogLink';
|
||||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||||
|
import PeriscopeTable from 'periscope/components/Table/Table';
|
||||||
import { memo, useCallback, useMemo, useRef } from 'react';
|
import { memo, useCallback, useMemo, useRef } from 'react';
|
||||||
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';
|
import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';
|
||||||
// interfaces
|
// interfaces
|
||||||
@@ -157,6 +158,7 @@ function LogsExplorerList({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="logs-list-view-container">
|
<div className="logs-list-view-container">
|
||||||
|
<PeriscopeTable />
|
||||||
{(isLoading || (isFetching && logs.length === 0)) && <LogsLoading />}
|
{(isLoading || (isFetching && logs.length === 0)) && <LogsLoading />}
|
||||||
|
|
||||||
{!isLoading &&
|
{!isLoading &&
|
||||||
|
|||||||
69
frontend/src/periscope/components/Table/Table.styles.scss
Normal file
69
frontend/src/periscope/components/Table/Table.styles.scss
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
table,
|
||||||
|
.divTable {
|
||||||
|
border: 1px solid lightgray;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tr {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr,
|
||||||
|
.tr {
|
||||||
|
width: fit-content;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
.th,
|
||||||
|
td,
|
||||||
|
.td {
|
||||||
|
box-shadow: inset 0 0 0 1px lightgray;
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
.th {
|
||||||
|
padding: 2px 4px;
|
||||||
|
position: relative;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td,
|
||||||
|
.td {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resizer {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
right: 0;
|
||||||
|
width: 5px;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
cursor: col-resize;
|
||||||
|
user-select: none;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resizer.isResizing {
|
||||||
|
background: blue;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.resizer {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*:hover > .resizer {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
border: 1px solid lightgray;
|
||||||
|
margin: 1rem auto;
|
||||||
|
}
|
||||||
295
frontend/src/periscope/components/Table/Table.tsx
Normal file
295
frontend/src/periscope/components/Table/Table.tsx
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/* eslint-disable react/jsx-props-no-spreading */
|
||||||
|
/* eslint-disable react/no-unstable-nested-components */
|
||||||
|
import './Table.styles.scss';
|
||||||
|
|
||||||
|
// needed for table body level scope DnD setup
|
||||||
|
import {
|
||||||
|
closestCenter,
|
||||||
|
DndContext,
|
||||||
|
DragEndEvent,
|
||||||
|
KeyboardSensor,
|
||||||
|
MouseSensor,
|
||||||
|
TouchSensor,
|
||||||
|
useSensor,
|
||||||
|
useSensors,
|
||||||
|
} from '@dnd-kit/core';
|
||||||
|
import { restrictToHorizontalAxis } from '@dnd-kit/modifiers';
|
||||||
|
import {
|
||||||
|
arrayMove,
|
||||||
|
horizontalListSortingStrategy,
|
||||||
|
SortableContext,
|
||||||
|
useSortable,
|
||||||
|
} from '@dnd-kit/sortable';
|
||||||
|
// needed for row & cell level scope DnD setup
|
||||||
|
import { CSS } from '@dnd-kit/utilities';
|
||||||
|
import {
|
||||||
|
Cell,
|
||||||
|
ColumnDef,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
Header,
|
||||||
|
Table,
|
||||||
|
useReactTable,
|
||||||
|
} from '@tanstack/react-table';
|
||||||
|
import React, { CSSProperties } from 'react';
|
||||||
|
|
||||||
|
import { makeData, Person } from './makeData';
|
||||||
|
|
||||||
|
function DraggableTableHeader({
|
||||||
|
header,
|
||||||
|
}: {
|
||||||
|
header: Header<Person, unknown>;
|
||||||
|
}): JSX.Element {
|
||||||
|
const {
|
||||||
|
attributes,
|
||||||
|
isDragging,
|
||||||
|
listeners,
|
||||||
|
setNodeRef,
|
||||||
|
transform,
|
||||||
|
} = useSortable({
|
||||||
|
id: header.column.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const style: CSSProperties = {
|
||||||
|
opacity: isDragging ? 0.8 : 1,
|
||||||
|
position: 'relative',
|
||||||
|
transform: CSS.Translate.toString(transform), // translate instead of transform to avoid squishing
|
||||||
|
transition: 'width transform 0.2s ease-in-out',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
width: header.column.getSize(),
|
||||||
|
zIndex: isDragging ? 1 : 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<th colSpan={header.colSpan} ref={setNodeRef} style={style}>
|
||||||
|
{header.isPlaceholder
|
||||||
|
? null
|
||||||
|
: flexRender(header.column.columnDef.header, header.getContext())}
|
||||||
|
<button type="button" {...attributes} {...listeners}>
|
||||||
|
🟰
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div
|
||||||
|
{...{
|
||||||
|
onDoubleClick: (): void => header.column.resetSize(),
|
||||||
|
onMouseDown: header.getResizeHandler(),
|
||||||
|
onTouchStart: header.getResizeHandler(),
|
||||||
|
className: `resizer ${header.column.getIsResizing() ? 'isResizing' : ''}`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DragAlongCell({ cell }: { cell: Cell<Person, unknown> }): JSX.Element {
|
||||||
|
const { isDragging, setNodeRef, transform } = useSortable({
|
||||||
|
id: cell.column.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const style: CSSProperties = {
|
||||||
|
opacity: isDragging ? 0.8 : 1,
|
||||||
|
position: 'relative',
|
||||||
|
transform: CSS.Translate.toString(transform), // translate instead of transform to avoid squishing
|
||||||
|
transition: 'width transform 0.2s ease-in-out',
|
||||||
|
width: cell.column.getSize(),
|
||||||
|
zIndex: isDragging ? 1 : 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<td style={style} ref={setNodeRef}>
|
||||||
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
|
</td>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// un-memoized normal table body component - see memoized version below
|
||||||
|
function TableBody({ table }: { table: Table<Person> }): JSX.Element {
|
||||||
|
const { columnOrder } = table.getState();
|
||||||
|
|
||||||
|
console.log('columnOrder', columnOrder);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
{...{
|
||||||
|
className: 'tbody',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{table.getRowModel().rows.map((row) => (
|
||||||
|
<div key={row.id} className="tr">
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<SortableContext
|
||||||
|
key={cell.id}
|
||||||
|
items={columnOrder}
|
||||||
|
strategy={horizontalListSortingStrategy}
|
||||||
|
>
|
||||||
|
<DragAlongCell key={cell.id} cell={cell} />
|
||||||
|
</SortableContext>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// special memoized wrapper for our table body that we will use during column resizing
|
||||||
|
export const MemoizedTableBody = React.memo(
|
||||||
|
TableBody,
|
||||||
|
(prev, next) => prev.table.options.data === next.table.options.data,
|
||||||
|
) as typeof TableBody;
|
||||||
|
|
||||||
|
function PeriscopeTable(): JSX.Element {
|
||||||
|
const columns = React.useMemo<ColumnDef<Person>[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
accessorKey: 'firstName',
|
||||||
|
cell: (info): any => info.getValue(),
|
||||||
|
id: 'firstName',
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row): any => row.lastName,
|
||||||
|
cell: (info): any => info.getValue(),
|
||||||
|
header: (): JSX.Element => <span>Last Name</span>,
|
||||||
|
id: 'lastName',
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'age',
|
||||||
|
header: (): any => 'Age',
|
||||||
|
id: 'age',
|
||||||
|
size: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'visits',
|
||||||
|
header: (): JSX.Element => <span>Visits</span>,
|
||||||
|
id: 'visits',
|
||||||
|
size: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'status',
|
||||||
|
header: 'Status',
|
||||||
|
id: 'status',
|
||||||
|
size: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: 'progress',
|
||||||
|
header: 'Profile Progress',
|
||||||
|
id: 'progress',
|
||||||
|
size: 180,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const [data, setData] = React.useState(() => makeData(20));
|
||||||
|
const [columnOrder, setColumnOrder] = React.useState<string[]>(() =>
|
||||||
|
columns.map((c) => c.id!),
|
||||||
|
);
|
||||||
|
const [columnVisibility, setColumnVisibility] = React.useState({});
|
||||||
|
|
||||||
|
const table = useReactTable({
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
state: {
|
||||||
|
columnOrder,
|
||||||
|
columnVisibility,
|
||||||
|
},
|
||||||
|
defaultColumn: {
|
||||||
|
minSize: 60,
|
||||||
|
maxSize: 800,
|
||||||
|
},
|
||||||
|
columnResizeMode: 'onChange',
|
||||||
|
onColumnOrderChange: setColumnOrder,
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
debugTable: true,
|
||||||
|
debugHeaders: true,
|
||||||
|
debugColumns: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instead of calling `column.getSize()` on every render for every header
|
||||||
|
* and especially every data cell (very expensive),
|
||||||
|
* we will calculate all column sizes at once at the root table level in a useMemo
|
||||||
|
* and pass the column sizes down as CSS variables to the <table> element.
|
||||||
|
*/
|
||||||
|
const columnSizeVars = React.useMemo(() => {
|
||||||
|
const headers = table.getFlatHeaders();
|
||||||
|
const colSizes: { [key: string]: number } = {};
|
||||||
|
for (let i = 0; i < headers.length; i++) {
|
||||||
|
const header = headers[i]!;
|
||||||
|
colSizes[`--header-${header.id}-size`] = header.getSize();
|
||||||
|
colSizes[`--col-${header.column.id}-size`] = header.column.getSize();
|
||||||
|
}
|
||||||
|
return colSizes;
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [table.getState().columnSizingInfo, table.getState().columnSizing]);
|
||||||
|
|
||||||
|
// reorder columns after drag & drop
|
||||||
|
function handleDragEnd(event: DragEndEvent): void {
|
||||||
|
const { active, over } = event;
|
||||||
|
|
||||||
|
console.log('active', active, over);
|
||||||
|
if (active && over && active.id !== over.id) {
|
||||||
|
setColumnOrder((columnOrder) => {
|
||||||
|
const oldIndex = columnOrder.indexOf(active.id as string);
|
||||||
|
const newIndex = columnOrder.indexOf(over.id as string);
|
||||||
|
return arrayMove(columnOrder, oldIndex, newIndex); // this is just a splice util
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sensors = useSensors(
|
||||||
|
useSensor(MouseSensor, {}),
|
||||||
|
useSensor(TouchSensor, {}),
|
||||||
|
useSensor(KeyboardSensor, {}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DndContext
|
||||||
|
collisionDetection={closestCenter}
|
||||||
|
modifiers={[restrictToHorizontalAxis]}
|
||||||
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
|
onDragEnd={handleDragEnd}
|
||||||
|
sensors={sensors}
|
||||||
|
>
|
||||||
|
<div className="p-2">
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<div
|
||||||
|
className="divTable"
|
||||||
|
style={{
|
||||||
|
...columnSizeVars, // Define column sizes on the <table> element
|
||||||
|
width: table.getTotalSize(),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="thead">
|
||||||
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
|
<div key={headerGroup.id} className="tr">
|
||||||
|
<SortableContext
|
||||||
|
items={columnOrder}
|
||||||
|
strategy={horizontalListSortingStrategy}
|
||||||
|
>
|
||||||
|
{headerGroup.headers.map((header) => (
|
||||||
|
<div
|
||||||
|
key={header.id}
|
||||||
|
className="th"
|
||||||
|
style={{
|
||||||
|
width: `calc(var(--header-${header?.id}-size) * 1px)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DraggableTableHeader key={header.id} header={header} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</SortableContext>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TableBody table={table} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DndContext>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PeriscopeTable;
|
||||||
46
frontend/src/periscope/components/Table/makeData.ts
Normal file
46
frontend/src/periscope/components/Table/makeData.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { faker } from '@faker-js/faker';
|
||||||
|
|
||||||
|
export type Person = {
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
age: number;
|
||||||
|
visits: number;
|
||||||
|
progress: number;
|
||||||
|
status: 'relationship' | 'complicated' | 'single';
|
||||||
|
subRows?: Person[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const range = (len: number) => {
|
||||||
|
const arr: number[] = [];
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
arr.push(i);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
const newPerson = (): Person => ({
|
||||||
|
firstName: faker.person.firstName(),
|
||||||
|
lastName: faker.person.lastName(),
|
||||||
|
age: faker.number.int(40),
|
||||||
|
visits: faker.number.int(1000),
|
||||||
|
progress: faker.number.int(100),
|
||||||
|
status: faker.helpers.shuffle<Person['status']>([
|
||||||
|
'relationship',
|
||||||
|
'complicated',
|
||||||
|
'single',
|
||||||
|
])[0]!,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function makeData(...lens: number[]): any {
|
||||||
|
const makeDataLevel = (depth = 0): Person[] => {
|
||||||
|
const len = lens[depth]!;
|
||||||
|
return range(len).map(
|
||||||
|
(d): Person => ({
|
||||||
|
...newPerson(),
|
||||||
|
subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return makeDataLevel();
|
||||||
|
}
|
||||||
@@ -2541,7 +2541,7 @@
|
|||||||
"@dnd-kit/utilities" "^3.2.2"
|
"@dnd-kit/utilities" "^3.2.2"
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@dnd-kit/utilities@^3.2.2":
|
"@dnd-kit/utilities@3.2.2", "@dnd-kit/utilities@^3.2.2":
|
||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.2.tgz#5a32b6af356dc5f74d61b37d6f7129a4040ced7b"
|
resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.2.tgz#5a32b6af356dc5f74d61b37d6f7129a4040ced7b"
|
||||||
integrity sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==
|
integrity sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==
|
||||||
@@ -2597,6 +2597,11 @@
|
|||||||
minimatch "^3.0.4"
|
minimatch "^3.0.4"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
|
"@faker-js/faker@8.4.1":
|
||||||
|
version "8.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-8.4.1.tgz#5d5e8aee8fce48f5e189bf730ebd1f758f491451"
|
||||||
|
integrity sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==
|
||||||
|
|
||||||
"@floating-ui/core@^1.4.2":
|
"@floating-ui/core@^1.4.2":
|
||||||
version "1.5.2"
|
version "1.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.5.2.tgz#53a0f7a98c550e63134d504f26804f6b83dbc071"
|
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.5.2.tgz#53a0f7a98c550e63134d504f26804f6b83dbc071"
|
||||||
@@ -3800,6 +3805,18 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@sinonjs/commons" "^1.7.0"
|
"@sinonjs/commons" "^1.7.0"
|
||||||
|
|
||||||
|
"@tanstack/react-table@8.17.3":
|
||||||
|
version "8.17.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.17.3.tgz#4e10b4cf5355a40d6d72a83d3f4b3ecd32f56bf4"
|
||||||
|
integrity sha512-5gwg5SvPD3lNAXPuJJz1fOCEZYk9/GeBFH3w/hCgnfyszOIzwkwgp5I7Q4MJtn0WECp84b5STQUDdmvGi8m3nA==
|
||||||
|
dependencies:
|
||||||
|
"@tanstack/table-core" "8.17.3"
|
||||||
|
|
||||||
|
"@tanstack/table-core@8.17.3":
|
||||||
|
version "8.17.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.17.3.tgz#d7a9830abb29cd369b52b2a7159dc0360af646fd"
|
||||||
|
integrity sha512-mPBodDGVL+fl6d90wUREepHa/7lhsghg2A3vFpakEhrhtbIlgNAZiMr7ccTgak5qbHqF14Fwy+W1yFWQt+WmYQ==
|
||||||
|
|
||||||
"@testing-library/dom@^8.5.0":
|
"@testing-library/dom@^8.5.0":
|
||||||
version "8.20.0"
|
version "8.20.0"
|
||||||
resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz"
|
resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user