ok it kinda renders
This commit is contained in:
parent
c79fb7de78
commit
354ecd33a6
6 changed files with 80 additions and 48 deletions
15
README.md
Normal file
15
README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# matter
|
||||||
|
|
||||||
|
To install dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
To run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bun run index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
This project was created using `bun init` in bun v1.1.17. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
10
package.json
10
package.json
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3": "^7.9.0",
|
"d3": "^7.9.0",
|
||||||
|
"nanoid": "^5.0.7",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "^18.3.1"
|
||||||
},
|
},
|
||||||
|
@ -11,6 +12,13 @@
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@vitejs/plugin-react-swc": "^3.7.0",
|
"@vitejs/plugin-react-swc": "^3.7.0",
|
||||||
"sass": "^1.77.6",
|
"sass": "^1.77.6",
|
||||||
"vite": "^5.3.2"
|
"vite": "^5.3.2",
|
||||||
|
"@types/bun": "latest"
|
||||||
|
},
|
||||||
|
"name": "matter",
|
||||||
|
"module": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,3 +19,11 @@ text {
|
||||||
fill: #666;
|
fill: #666;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nodeContainer {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid gray;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
65
src/App.tsx
65
src/App.tsx
|
@ -2,8 +2,10 @@ import * as d3 from "d3";
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import styles from "./App.module.scss";
|
import styles from "./App.module.scss";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
|
|
||||||
interface NodeInfo extends d3.SimulationNodeDatum {
|
interface NodeInfo extends d3.SimulationNodeDatum {
|
||||||
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +18,7 @@ const nodes: NodeInfo[] = [
|
||||||
{ name: "F" },
|
{ name: "F" },
|
||||||
{ name: "G" },
|
{ name: "G" },
|
||||||
{ name: "H" },
|
{ name: "H" },
|
||||||
];
|
].map((node) => ({ ...node, id: nanoid() }));
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
{ source: 0, target: 1 },
|
{ source: 0, target: 1 },
|
||||||
|
@ -31,7 +33,6 @@ const links = [
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const svgRef = useRef();
|
const svgRef = useRef();
|
||||||
const simulationRef = useRef();
|
|
||||||
|
|
||||||
// Resize listener
|
// Resize listener
|
||||||
const [rect, setRect] = useState<DOMRectReadOnly | null>(null);
|
const [rect, setRect] = useState<DOMRectReadOnly | null>(null);
|
||||||
|
@ -46,25 +47,7 @@ export default function App() {
|
||||||
const [simulationNodes, setSimulationNodes] = useState(() => nodes);
|
const [simulationNodes, setSimulationNodes] = useState(() => nodes);
|
||||||
const ticked = useCallback((simulation: d3.Simulation<NodeInfo, any>) => {
|
const ticked = useCallback((simulation: d3.Simulation<NodeInfo, any>) => {
|
||||||
const nodes = simulation.nodes();
|
const nodes = simulation.nodes();
|
||||||
// setSimulationNodes(nodes);
|
setSimulationNodes([...nodes]);
|
||||||
// d3.select("svg .links")
|
|
||||||
// .selectAll("line")
|
|
||||||
// .data(links)
|
|
||||||
// .join("line")
|
|
||||||
// .attr("x1", (d) => d.source.x)
|
|
||||||
// .attr("x2", (d) => d.target.x)
|
|
||||||
// .attr("y1", (d) => d.source.y)
|
|
||||||
// .attr("y2", (d) => d.target.y);
|
|
||||||
|
|
||||||
d3.select("svg .nodes")
|
|
||||||
.selectAll("rect")
|
|
||||||
.data(nodes)
|
|
||||||
.join("rect")
|
|
||||||
// .append("foreignObject")
|
|
||||||
.text((d) => d.name)
|
|
||||||
.attr("x", (d) => d.x)
|
|
||||||
.attr("y", (d) => d.y)
|
|
||||||
.attr("dy", (d) => 5);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -72,13 +55,11 @@ export default function App() {
|
||||||
|
|
||||||
const simulation = d3
|
const simulation = d3
|
||||||
.forceSimulation<NodeInfo>(nodes)
|
.forceSimulation<NodeInfo>(nodes)
|
||||||
.force("charge", d3.forceManyBody())
|
.force("charge", d3.forceManyBody().strength(-500))
|
||||||
.force("link", d3.forceLink(links))
|
.force("link", d3.forceLink(links))
|
||||||
.force("center", d3.forceCenter(rect.width / 2, rect.height / 2));
|
.force("center", d3.forceCenter(rect.width / 2, rect.height / 2));
|
||||||
|
|
||||||
simulation.on("tick", () => ticked(simulation));
|
simulation.on("tick", () => ticked(simulation));
|
||||||
|
|
||||||
simulationRef.current = simulation;
|
|
||||||
}, [ticked, rect]);
|
}, [ticked, rect]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -89,15 +70,19 @@ export default function App() {
|
||||||
<g className="links" />
|
<g className="links" />
|
||||||
<g className="nodes">
|
<g className="nodes">
|
||||||
{simulationNodes.map((node, idx) => {
|
{simulationNodes.map((node, idx) => {
|
||||||
console.log("node", node);
|
|
||||||
return (
|
return (
|
||||||
<text
|
<g key={idx}>
|
||||||
key={idx}
|
<foreignObject
|
||||||
x={(node.x ?? 0).toString()}
|
width={120}
|
||||||
y={(node.y ?? 0).toString()}
|
height={80}
|
||||||
>
|
x={(node.x ?? 0).toString()}
|
||||||
{node.name}
|
y={(node.y ?? 0).toString()}
|
||||||
</text>
|
>
|
||||||
|
<div data-xmlns="http://www.w3.org/1999/xhtml" id={node.id}>
|
||||||
|
<Counter />
|
||||||
|
</div>
|
||||||
|
</foreignObject>
|
||||||
|
</g>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</g>
|
</g>
|
||||||
|
@ -107,13 +92,6 @@ export default function App() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ForeignObjectWrapper({ id }) {
|
|
||||||
const el = useMemo(() => {
|
|
||||||
return document.getElementById(id);
|
|
||||||
}, [id]);
|
|
||||||
return createPortal(<Counter />, el);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Counter() {
|
function Counter() {
|
||||||
const [counter, setCounter] = useState(0);
|
const [counter, setCounter] = useState(0);
|
||||||
|
|
||||||
|
@ -133,13 +111,14 @@ function Counter() {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="btn__container">
|
<div className={styles.nodeContainer}>
|
||||||
<button className="control__btn" onClick={increase}>
|
|
||||||
+
|
|
||||||
</button>
|
|
||||||
<button className="control__btn" onClick={decrease}>
|
<button className="control__btn" onClick={decrease}>
|
||||||
-
|
-
|
||||||
</button>
|
</button>
|
||||||
|
{counter}
|
||||||
|
<button className="control__btn" onClick={increase}>
|
||||||
|
+
|
||||||
|
</button>
|
||||||
<button className="reset" onClick={reset}>
|
<button className="reset" onClick={reset}>
|
||||||
Reset
|
Reset
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -1,5 +1,27 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"jsx": "react-jsx"
|
// Enable latest features
|
||||||
}
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue