ok it kinda renders

This commit is contained in:
Michael Zhang 2024-06-27 19:23:36 -05:00
parent c79fb7de78
commit 354ecd33a6
6 changed files with 80 additions and 48 deletions

15
README.md Normal file
View 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

Binary file not shown.

View file

@ -1,6 +1,7 @@
{
"dependencies": {
"d3": "^7.9.0",
"nanoid": "^5.0.7",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
@ -11,6 +12,13 @@
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react-swc": "^3.7.0",
"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"
}
}

View file

@ -19,3 +19,11 @@ text {
fill: #666;
font-size: 16px;
}
.nodeContainer {
box-sizing: border-box;
border: 1px solid gray;
border-radius: 4px;
width: 100%;
height: 100%;
}

View file

@ -2,8 +2,10 @@ import * as d3 from "d3";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import styles from "./App.module.scss";
import { createPortal } from "react-dom";
import { nanoid } from "nanoid";
interface NodeInfo extends d3.SimulationNodeDatum {
id: string;
name: string;
}
@ -16,7 +18,7 @@ const nodes: NodeInfo[] = [
{ name: "F" },
{ name: "G" },
{ name: "H" },
];
].map((node) => ({ ...node, id: nanoid() }));
const links = [
{ source: 0, target: 1 },
@ -31,7 +33,6 @@ const links = [
export default function App() {
const svgRef = useRef();
const simulationRef = useRef();
// Resize listener
const [rect, setRect] = useState<DOMRectReadOnly | null>(null);
@ -46,25 +47,7 @@ export default function App() {
const [simulationNodes, setSimulationNodes] = useState(() => nodes);
const ticked = useCallback((simulation: d3.Simulation<NodeInfo, any>) => {
const nodes = simulation.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);
setSimulationNodes([...nodes]);
}, []);
useEffect(() => {
@ -72,13 +55,11 @@ export default function App() {
const simulation = d3
.forceSimulation<NodeInfo>(nodes)
.force("charge", d3.forceManyBody())
.force("charge", d3.forceManyBody().strength(-500))
.force("link", d3.forceLink(links))
.force("center", d3.forceCenter(rect.width / 2, rect.height / 2));
simulation.on("tick", () => ticked(simulation));
simulationRef.current = simulation;
}, [ticked, rect]);
return (
@ -89,15 +70,19 @@ export default function App() {
<g className="links" />
<g className="nodes">
{simulationNodes.map((node, idx) => {
console.log("node", node);
return (
<text
key={idx}
x={(node.x ?? 0).toString()}
y={(node.y ?? 0).toString()}
>
{node.name}
</text>
<g key={idx}>
<foreignObject
width={120}
height={80}
x={(node.x ?? 0).toString()}
y={(node.y ?? 0).toString()}
>
<div data-xmlns="http://www.w3.org/1999/xhtml" id={node.id}>
<Counter />
</div>
</foreignObject>
</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() {
const [counter, setCounter] = useState(0);
@ -133,13 +111,14 @@ function Counter() {
};
return (
<div className="btn__container">
<button className="control__btn" onClick={increase}>
+
</button>
<div className={styles.nodeContainer}>
<button className="control__btn" onClick={decrease}>
-
</button>
{counter}
<button className="control__btn" onClick={increase}>
+
</button>
<button className="reset" onClick={reset}>
Reset
</button>

View file

@ -1,5 +1,27 @@
{
"compilerOptions": {
"jsx": "react-jsx"
}
"compilerOptions": {
// 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
}
}