layout context

This commit is contained in:
1ilit 2023-09-19 15:48:48 +03:00
parent 23e58a0110
commit 1eea618faa
6 changed files with 140 additions and 139 deletions

View File

@ -1,11 +1,13 @@
import React, { useRef, useState } from "react"; import React, { useContext, useRef, useState } from "react";
import { useDrop } from "react-dnd"; import { useDrop } from "react-dnd";
import Table from "./table"; import Table from "./table";
import { defaultTableTheme, Cardinality, Constraint } from "../data/data"; import { defaultTableTheme, Cardinality, Constraint } from "../data/data";
import Area from "./area"; import Area from "./area";
import Relationship from "./relationship"; import Relationship from "./relationship";
import { TableContext } from "../pages/editor";
export default function Canvas(props) { export default function Canvas(props) {
const { tables, setTables } = useContext(TableContext);
const ObjectType = { const ObjectType = {
NONE: 0, NONE: 0,
TABLE: 1, TABLE: 1,
@ -51,7 +53,7 @@ export default function Canvas(props) {
const handleMouseDownRect = (e, id, type) => { const handleMouseDownRect = (e, id, type) => {
const { clientX, clientY } = e; const { clientX, clientY } = e;
if (type === ObjectType.TABLE) { if (type === ObjectType.TABLE) {
const table = props.tables.find((t) => t.id === id); const table = tables.find((t) => t.id === id);
setOffset({ setOffset({
x: clientX - table.x, x: clientX - table.x,
y: clientY - table.y, y: clientY - table.y,
@ -87,8 +89,8 @@ export default function Canvas(props) {
const dy = e.clientY - panOffset.y; const dy = e.clientY - panOffset.y;
setPanOffset({ x: e.clientX, y: e.clientY }); setPanOffset({ x: e.clientX, y: e.clientY });
props.setTables( setTables(
props.tables.map((t) => ({ tables.map((t) => ({
...t, ...t,
x: t.x + dx, x: t.x + dx,
y: t.y + dy, y: t.y + dy,
@ -113,7 +115,7 @@ export default function Canvas(props) {
})) }))
); );
} else if (dragging[0] === ObjectType.TABLE && dragging[1] >= 0) { } else if (dragging[0] === ObjectType.TABLE && dragging[1] >= 0) {
const updatedTables = props.tables.map((t) => { const updatedTables = tables.map((t) => {
if (t.id === dragging[1]) { if (t.id === dragging[1]) {
const updatedTable = { const updatedTable = {
...t, ...t,
@ -124,20 +126,19 @@ export default function Canvas(props) {
} }
return t; return t;
}); });
props.setTables(updatedTables); setTables(updatedTables);
const updatedRelationShips = props.relationships.map((r) => { const updatedRelationShips = props.relationships.map((r) => {
if (r.startTableId === dragging[1]) { if (r.startTableId === dragging[1]) {
return { return {
...r, ...r,
startX: props.tables[r.startTableId].x + 15, startX: tables[r.startTableId].x + 15,
startY: startY: tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19,
props.tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19,
}; };
} else if (r.endTableId === dragging[1]) { } else if (r.endTableId === dragging[1]) {
return { return {
...r, ...r,
endX: props.tables[r.endTableId].x + 15, endX: tables[r.endTableId].x + 15,
endY: props.tables[r.endTableId].y + r.endFieldId * 36 + 50 + 19, endY: tables[r.endTableId].y + r.endFieldId * 36 + 50 + 19,
}; };
} }
return r; return r;
@ -246,10 +247,10 @@ export default function Canvas(props) {
...line, ...line,
endTableId: onRect.tableId, endTableId: onRect.tableId,
endFieldId: onRect.field, endFieldId: onRect.field,
endX: props.tables[onRect.tableId].x + 15, endX: tables[onRect.tableId].x + 15,
endY: props.tables[onRect.tableId].y + onRect.field * 36 + 50 + 19, endY: tables[onRect.tableId].y + onRect.field * 36 + 50 + 19,
name: `${props.tables[line.startTableId].name}_to_${ name: `${tables[line.startTableId].name}_to_${
props.tables[onRect.tableId].name tables[onRect.tableId].name
}`, }`,
id: prev.length, id: prev.length,
}, },
@ -265,8 +266,8 @@ export default function Canvas(props) {
const x = offset.x - canvasRect.left - 100 * 0.5; const x = offset.x - canvasRect.left - 100 * 0.5;
const y = offset.y - canvasRect.top - 100 * 0.5; const y = offset.y - canvasRect.top - 100 * 0.5;
const newTable = { const newTable = {
id: props.tables.length, id: tables.length,
name: `table_${props.tables.length}`, name: `table_${tables.length}`,
x: x, x: x,
y: y, y: y,
fields: [ fields: [
@ -286,7 +287,7 @@ export default function Canvas(props) {
indices: [], indices: [],
color: defaultTableTheme, color: defaultTableTheme,
}; };
props.setTables((prev) => [...prev, newTable]); setTables((prev) => [...prev, newTable]);
props.setCode((prev) => props.setCode((prev) =>
prev === "" prev === ""
? `CREATE TABLE \`${newTable.name}\`;` ? `CREATE TABLE \`${newTable.name}\`;`
@ -297,7 +298,7 @@ export default function Canvas(props) {
isOver: !!monitor.isOver(), isOver: !!monitor.isOver(),
}), }),
}), }),
[props.tables] [tables]
); );
return ( return (
@ -352,13 +353,10 @@ export default function Canvas(props) {
setAreas={props.setAreas} setAreas={props.setAreas}
></Area> ></Area>
))} ))}
{props.tables.map((table, i) => ( {tables.map((table, i) => (
<Table <Table
key={table.id} key={table.id}
id={table.id}
tableData={table} tableData={table}
tables={props.tables}
setTables={props.setTables}
setOnRect={setOnRect} setOnRect={setOnRect}
handleGripField={handleGripField} handleGripField={handleGripField}
setLine={setLine} setLine={setLine}

View File

@ -1,14 +1,15 @@
import { React, useState, useRef } from "react"; import { React, useState } from "react";
import CodeMirror from "@uiw/react-codemirror"; import CodeMirror from "@uiw/react-codemirror";
import { createTheme } from "@uiw/codemirror-themes"; import { createTheme } from "@uiw/codemirror-themes";
import { sql } from "@codemirror/lang-sql"; import { sql } from "@codemirror/lang-sql";
import { tags as t } from "@lezer/highlight"; import { tags as t } from "@lezer/highlight";
import Shape from "./shape"; import Shape from "./shape";
import { Parser } from "node-sql-parser"; // import { Parser } from "node-sql-parser";
import { Tabs } from "@douyinfe/semi-ui"; import { Tabs } from "@douyinfe/semi-ui";
import TableOverview from "./table_overview"; import TableOverview from "./table_overview";
import ReferenceOverview from "./reference_overview"; import ReferenceOverview from "./reference_overview";
import { defaultTableTheme } from "../data/data"; import { defaultTableTheme } from "../data/data";
// import { TableContext } from "../pages/editor";
const myTheme = createTheme({ const myTheme = createTheme({
dark: "light", dark: "light",
@ -26,7 +27,8 @@ const myTheme = createTheme({
const EditorPanel = (props) => { const EditorPanel = (props) => {
const [tab, setTab] = useState("1"); const [tab, setTab] = useState("1");
const map = useRef(new Map()); // const map = useRef(new Map());
// const {tables, setTables} = useContext(TableContext);
const tabList = [ const tabList = [
{ tab: "Tables", itemKey: "1" }, { tab: "Tables", itemKey: "1" },
@ -35,11 +37,10 @@ const EditorPanel = (props) => {
{ tab: "Editor", itemKey: "4" }, { tab: "Editor", itemKey: "4" },
]; ];
const contentList = [ const contentList = [
<TableOverview tables={props.tables} setTables={props.setTables} />, <TableOverview />,
<ReferenceOverview <ReferenceOverview
relationships={props.relationships} relationships={props.relationships}
setRelationships={props.setRelationships} setRelationships={props.setRelationships}
tables={props.tables}
/>, />,
<Shape />, <Shape />,
<CodeMirror <CodeMirror
@ -99,44 +100,44 @@ const EditorPanel = (props) => {
<br /> <br />
<button <button
onClick={() => { onClick={() => {
try { // try {
const parser = new Parser(); // const parser = new Parser();
const ast = parser.astify(props.code); // const ast = parser.astify(props.code);
console.log(ast); // console.log(ast);
ast.forEach((e) => { // ast.forEach((e) => {
e.table.forEach((t) => { // e.table.forEach((t) => {
if (map.current.has(t.table)) { // if (map.current.has(t.table)) {
return; // return;
} // }
map.current.set(t.table, t); // map.current.set(t.table, t);
const newTable = { // const newTable = {
id: props.tables.length, // id: props.tables.length,
name: `table_${props.tables.length}`, // name: `table_${props.tables.length}`,
x: 0, // x: 0,
y: 0, // y: 0,
fields: [ // fields: [
{ // {
name: "id", // name: "id",
type: "UUID", // type: "UUID",
default: "", // default: "",
check: "", // check: "",
primary: true, // primary: true,
unique: true, // unique: true,
notNull: true, // notNull: true,
increment: true, // increment: true,
comment: "", // comment: "",
}, // },
], // ],
comment: "", // comment: "",
indices: [], // indices: [],
color: defaultTableTheme, // color: defaultTableTheme,
}; // };
props.setTables((prev) => [...prev, newTable]); // props.setTables((prev) => [...prev, newTable]);
}); // });
}); // });
} catch (e) { // } catch (e) {
alert("parsing error"); // alert("parsing error");
} // }
}} }}
> >
parse parse

View File

@ -1,4 +1,4 @@
import React, { useState } from "react"; import React, { useContext, useState } from "react";
import { import {
AutoComplete, AutoComplete,
Collapse, Collapse,
@ -23,6 +23,7 @@ import {
IllustrationNoContentDark, IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations"; } from "@douyinfe/semi-illustrations";
import { Cardinality, Constraint } from "../data/data"; import { Cardinality, Constraint } from "../data/data";
import { TableContext } from "../pages/editor";
export default function ReferenceOverview(props) { export default function ReferenceOverview(props) {
const columns = [ const columns = [
@ -35,6 +36,7 @@ export default function ReferenceOverview(props) {
dataIndex: "foreign", dataIndex: "foreign",
}, },
]; ];
const { tables } = useContext(TableContext);
const [refActiveIndex, setRefActiveIndex] = useState(""); const [refActiveIndex, setRefActiveIndex] = useState("");
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const [filteredResult, setFilteredResult] = useState( const [filteredResult, setFilteredResult] = useState(
@ -108,11 +110,11 @@ export default function ReferenceOverview(props) {
<div className="flex justify-between items-center my-1"> <div className="flex justify-between items-center my-1">
<div className="me-3"> <div className="me-3">
<strong>Primary: </strong> <strong>Primary: </strong>
{props.tables[r.endTableId].name} {tables[r.endTableId].name}
</div> </div>
<div className="mx-1"> <div className="mx-1">
<strong>Foreign: </strong> <strong>Foreign: </strong>
{props.tables[r.startTableId].name} {tables[r.startTableId].name}
</div> </div>
<div className="ms-1"> <div className="ms-1">
<Popover <Popover
@ -123,19 +125,18 @@ export default function ReferenceOverview(props) {
dataSource={[ dataSource={[
{ {
key: "1", key: "1",
foreign: props.tables[r.startTableId].name, foreign: tables[r.startTableId].name,
primary: props.tables[r.endTableId].name, primary: tables[r.endTableId].name,
}, },
{ {
key: "2", key: "2",
foreign: foreign:
props.tables[r.startTableId].fields[ tables[r.startTableId].fields[
r.startFieldId r.startFieldId
].name, ].name,
primary: primary:
props.tables[r.endTableId].fields[ tables[r.endTableId].fields[r.endFieldId]
r.endFieldId .name,
].name,
}, },
]} ]}
pagination={false} pagination={false}

View File

@ -12,13 +12,14 @@ import {
Button, Button,
SideSheet, SideSheet,
} from "@douyinfe/semi-ui"; } from "@douyinfe/semi-ui";
import { LayoutContext } from "../pages/editor"; import { LayoutContext, TableContext } from "../pages/editor";
export default function Table(props) { export default function Table(props) {
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const [hoveredField, setHoveredField] = useState(-1); const [hoveredField, setHoveredField] = useState(-1);
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const {layout} = useContext(LayoutContext); const {layout} = useContext(LayoutContext);
const {setTables} = useContext(TableContext);
// const [editFieldVisible, setEditFieldVisible] = useState(-1); // const [editFieldVisible, setEditFieldVisible] = useState(-1);
// const [field, setField] = useState({ // const [field, setField] = useState({
// name: "", // name: "",
@ -36,7 +37,7 @@ export default function Table(props) {
return ( return (
<g> <g>
<foreignObject <foreignObject
key={props.id} key={props.tableData.id}
x={props.tableData.x} x={props.tableData.x}
y={props.tableData.y} y={props.tableData.y}
width={200} width={200}
@ -199,7 +200,7 @@ export default function Table(props) {
onMouseEnter={() => { onMouseEnter={() => {
setHoveredField(i); setHoveredField(i);
props.setOnRect({ props.setOnRect({
tableId: props.id, tableId: props.tableData.id,
field: i, field: i,
}); });
}} }}
@ -217,7 +218,7 @@ export default function Table(props) {
props.setLine((prev) => ({ props.setLine((prev) => ({
...prev, ...prev,
startFieldId: i, startFieldId: i,
startTableId: props.id, startTableId: props.tableData.id,
startX: props.tableData.x + 15, startX: props.tableData.x + 15,
startY: props.tableData.y + i * 36 + 50 + 19, startY: props.tableData.y + i * 36 + 50 + 19,
endX: props.tableData.x + 15, endX: props.tableData.x + 15,
@ -237,13 +238,13 @@ export default function Table(props) {
backgroundColor: "#d42020", backgroundColor: "#d42020",
}} }}
onClick={(ev) => { onClick={(ev) => {
props.setTables((prev) => { setTables((prev) => {
const updatedTables = [...prev]; const updatedTables = [...prev];
const updatedFields = [ const updatedFields = [
...updatedTables[props.id].fields, ...updatedTables[props.tableData.id].fields,
]; ];
updatedFields.splice(i, 1); updatedFields.splice(i, 1);
updatedTables[props.id].fields = [...updatedFields]; updatedTables[props.tableData.id].fields = [...updatedFields];
return updatedTables; return updatedTables;
}); });
}} }}

View File

@ -1,4 +1,4 @@
import { React, useState } from "react"; import { React, useContext, useState } from "react";
import { defaultTableTheme, sqlDataTypes, tableThemes } from "../data/data"; import { defaultTableTheme, sqlDataTypes, tableThemes } from "../data/data";
import { import {
Collapse, Collapse,
@ -27,20 +27,22 @@ import {
IllustrationNoContent, IllustrationNoContent,
IllustrationNoContentDark, IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations"; } from "@douyinfe/semi-illustrations";
import { TableContext } from "../pages/editor";
export default function TableOverview(props) { export default function TableOverview(props) {
const [indexActiveKey, setIndexActiveKey] = useState(""); const [indexActiveKey, setIndexActiveKey] = useState("");
const [tableActiveKey, setTableActiveKey] = useState(""); const [tableActiveKey, setTableActiveKey] = useState("");
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const { tables, setTables } = useContext(TableContext);
const [filteredResult, setFilteredResult] = useState( const [filteredResult, setFilteredResult] = useState(
props.tables.map((t) => { tables.map((t) => {
return t.name; return t.name;
}) })
); );
const handleStringSearch = (value) => { const handleStringSearch = (value) => {
setFilteredResult( setFilteredResult(
props.tables tables
.map((t) => { .map((t) => {
return t.name; return t.name;
}) })
@ -49,7 +51,7 @@ export default function TableOverview(props) {
}; };
const updatedField = (tid, fid, updatedValues) => { const updatedField = (tid, fid, updatedValues) => {
props.setTables((prev) => setTables((prev) =>
prev.map((table, i) => { prev.map((table, i) => {
if (tid === i) { if (tid === i) {
return { return {
@ -65,7 +67,7 @@ export default function TableOverview(props) {
}; };
const updateTable = (tid, updatedValues) => { const updateTable = (tid, updatedValues) => {
props.setTables((prev) => setTables((prev) =>
prev.map((table, i) => { prev.map((table, i) => {
if (tid === i) { if (tid === i) {
return { return {
@ -92,7 +94,7 @@ export default function TableOverview(props) {
onSearch={(v) => handleStringSearch(v)} onSearch={(v) => handleStringSearch(v)}
onChange={(v) => setValue(v)} onChange={(v) => setValue(v)}
onSelect={(v) => { onSelect={(v) => {
const { id } = props.tables.find((t) => t.name === v); const { id } = tables.find((t) => t.name === v);
setTableActiveKey(`${id}`); setTableActiveKey(`${id}`);
document document
.getElementById(`scroll_table_${id}`) .getElementById(`scroll_table_${id}`)
@ -107,9 +109,7 @@ export default function TableOverview(props) {
block block
onClick={() => { onClick={() => {
const id = const id =
props.tables.length === 0 tables.length === 0 ? 0 : tables[tables.length - 1].id + 1;
? 0
: props.tables[props.tables.length - 1].id + 1;
const newTable = { const newTable = {
id: id, id: id,
name: `table_${id}`, name: `table_${id}`,
@ -132,7 +132,7 @@ export default function TableOverview(props) {
indices: [], indices: [],
color: defaultTableTheme, color: defaultTableTheme,
}; };
props.setTables((prev) => [...prev, newTable]); setTables((prev) => [...prev, newTable]);
}} }}
> >
Add table Add table
@ -144,7 +144,7 @@ export default function TableOverview(props) {
onChange={(k) => setTableActiveKey(k)} onChange={(k) => setTableActiveKey(k)}
accordion accordion
> >
{props.tables.length <= 0 ? ( {tables.length <= 0 ? (
<div className="select-none"> <div className="select-none">
<Empty <Empty
image={ image={
@ -160,7 +160,7 @@ export default function TableOverview(props) {
/> />
</div> </div>
) : ( ) : (
props.tables.map((t, i) => ( tables.map((t, i) => (
<div id={`scroll_table_${t.id}`} key={t.id}> <div id={`scroll_table_${t.id}`} key={t.id}>
<Collapse.Panel header={<div>{t.name}</div>} itemKey={`${t.id}`}> <Collapse.Panel header={<div>{t.name}</div>} itemKey={`${t.id}`}>
{t.fields.map((f, j) => ( {t.fields.map((f, j) => (
@ -296,7 +296,7 @@ export default function TableOverview(props) {
type="danger" type="danger"
block block
onClick={(ev) => { onClick={(ev) => {
props.setTables((prev) => { setTables((prev) => {
const updatedTables = [...prev]; const updatedTables = [...prev];
const updatedFields = [ const updatedFields = [
...updatedTables[t.id].fields, ...updatedTables[t.id].fields,
@ -349,7 +349,7 @@ export default function TableOverview(props) {
className="w-full" className="w-full"
defaultValue={idx.fields} defaultValue={idx.fields}
onChange={(value) => { onChange={(value) => {
const updatedTables = [...props.tables]; const updatedTables = [...tables];
const updatedIndices = [...t.indices]; const updatedIndices = [...t.indices];
updatedIndices[k] = { updatedIndices[k] = {
name: `${value.join("_")}_index`, name: `${value.join("_")}_index`,
@ -359,7 +359,7 @@ export default function TableOverview(props) {
...t, ...t,
indices: [...updatedIndices], indices: [...updatedIndices],
}; };
props.setTables(updatedTables); setTables(updatedTables);
}} }}
/> />
<Popover <Popover
@ -379,14 +379,14 @@ export default function TableOverview(props) {
type="danger" type="danger"
block block
onClick={() => { onClick={() => {
const updatedTables = [...props.tables]; const updatedTables = [...tables];
const updatedIndices = [...t.indices]; const updatedIndices = [...t.indices];
updatedIndices.splice(k, 1); updatedIndices.splice(k, 1);
updatedTables[i] = { updatedTables[i] = {
...t, ...t,
indices: [...updatedIndices], indices: [...updatedIndices],
}; };
props.setTables(updatedTables); setTables(updatedTables);
}} }}
> >
Delete Delete
@ -506,7 +506,7 @@ export default function TableOverview(props) {
block block
onClick={() => { onClick={() => {
setIndexActiveKey("1"); setIndexActiveKey("1");
const updatedTables = [...props.tables]; const updatedTables = [...tables];
updatedTables[i] = { updatedTables[i] = {
...t, ...t,
indices: [ indices: [
@ -514,7 +514,7 @@ export default function TableOverview(props) {
{ name: `index_${t.indices.length}`, fields: [] }, { name: `index_${t.indices.length}`, fields: [] },
], ],
}; };
props.setTables(updatedTables); setTables(updatedTables);
}} }}
> >
Add index Add index
@ -523,7 +523,7 @@ export default function TableOverview(props) {
<Col span={6}> <Col span={6}>
<Button <Button
onClick={() => { onClick={() => {
const updatedTables = [...props.tables]; const updatedTables = [...tables];
updatedTables[i].fields = [ updatedTables[i].fields = [
...updatedTables[i].fields, ...updatedTables[i].fields,
{ {
@ -537,7 +537,7 @@ export default function TableOverview(props) {
comment: "", comment: "",
}, },
]; ];
props.setTables(updatedTables); setTables(updatedTables);
}} }}
block block
> >
@ -550,7 +550,7 @@ export default function TableOverview(props) {
type="danger" type="danger"
onClick={() => { onClick={() => {
Toast.success(`Table deleted!`); Toast.success(`Table deleted!`);
props.setTables((prev) => setTables((prev) =>
prev prev
.filter((e) => e.id !== i) .filter((e) => e.id !== i)
.map((e, idx) => ({ ...e, id: idx })) .map((e, idx) => ({ ...e, id: idx }))

View File

@ -7,6 +7,7 @@ import Canvas from "../components/canvas";
import EditorPanel from "../components/editor_panel"; import EditorPanel from "../components/editor_panel";
export const LayoutContext = createContext(); export const LayoutContext = createContext();
export const TableContext = createContext();
export default function Editor(props) { export default function Editor(props) {
const [code, setCode] = useState(""); const [code, setCode] = useState("");
@ -33,51 +34,50 @@ export default function Editor(props) {
if (w > 340) setWidth(w); if (w > 340) setWidth(w);
}; };
const value = {layout, setLayout}; const layoutValue = { layout, setLayout };
const tableValue = { tables, setTables };
return ( return (
<LayoutContext.Provider value={value}> <LayoutContext.Provider value={layoutValue}>
<div className="h-[100vh] overflow-hidden"> <TableContext.Provider value={tableValue}>
<ControlPanel/> <div className="h-[100vh] overflow-hidden">
<div <ControlPanel />
className={ <div
layout.header className={
? `flex h-[calc(100vh-123.93px)]` layout.header
: `flex h-[calc(100vh-51.97px)]` ? `flex h-[calc(100vh-123.93px)]`
} : `flex h-[calc(100vh-51.97px)]`
onMouseUp={() => setResize(false)} }
onMouseMove={dragHandler} onMouseUp={() => setResize(false)}
> onMouseMove={dragHandler}
<DndProvider backend={HTML5Backend}> >
{layout.sidebar && ( <DndProvider backend={HTML5Backend}>
<EditorPanel {layout.sidebar && (
tables={tables} <EditorPanel
setTables={setTables} code={code}
setCode={setCode}
relationships={relationships}
setRelationships={setRelationships}
areas={areas}
setAreas={setAreas}
resize={resize}
setResize={setResize}
width={width}
/>
)}
<Canvas
code={code} code={code}
setCode={setCode} setCode={setCode}
relationships={relationships} relationships={relationships}
setRelationships={setRelationships} setRelationships={setRelationships}
areas={areas} areas={areas}
setAreas={setAreas} setAreas={setAreas}
resize={resize}
setResize={setResize}
width={width}
/> />
)} </DndProvider>
<Canvas {layout.services && <Sidebar />}
tables={tables} </div>
setTables={setTables}
code={code}
setCode={setCode}
relationships={relationships}
setRelationships={setRelationships}
areas={areas}
setAreas={setAreas}
/>
</DndProvider>
{layout.services && <Sidebar />}
</div> </div>
</div> </TableContext.Provider>
</LayoutContext.Provider> </LayoutContext.Provider>
); );
} }