graphics-debug 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -131,6 +131,36 @@ const graphicsObjects = getGraphicsObjectsFromLogString(logString)
131
131
  // Array<GraphicsObject>
132
132
  ```
133
133
 
134
+ ### Example Graphics JSON
135
+
136
+ An example graphics JSON file is provided in the repository to help you get started quickly.
137
+
138
+ You can find the example file at [`site/examples/exampleGraphics.json`](site/examples/exampleGraphics.json). This file contains a sample graphics object that you can use to test the functionality of the `graphics-debug` module.
139
+
140
+ Here is the content of the `exampleGraphics.json` file:
141
+
142
+ ```JSON
143
+ {
144
+ "title": "Example Usage",
145
+ "rects": [
146
+ {
147
+ "center": { "x": 0, "y": 0 },
148
+ "width": 100,
149
+ "height": 100,
150
+ "fill": "green"
151
+ }
152
+ ],
153
+ "points": [
154
+ {
155
+ "x": 50,
156
+ "y": 50,
157
+ "color": "red",
158
+ "label": "Test Output!"
159
+ }
160
+ ]
161
+ }
134
162
  ```
135
163
 
136
- ```
164
+ You can load this example into the application to visualize the graphics objects and understand how the `graphics-debug` module works.
165
+
166
+
package/dist/cli/cli.js CHANGED
@@ -10,7 +10,6 @@ import "../chunk-5FZF67ET.js";
10
10
 
11
11
  // cli/cli.ts
12
12
  import { parseArgs } from "node:util";
13
- import "node:fs";
14
13
  import { writeFileSync } from "node:fs";
15
14
  async function getInput() {
16
15
  if (process.stdin.isTTY && process.stderr.isTTY) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../cli/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\"\nimport { readFileSync } from \"node:fs\"\nimport { writeFileSync } from \"node:fs\"\nimport {\n getSvgsFromLogString,\n getHtmlFromLogString,\n getGraphicsObjectsFromLogString,\n} from \"../lib\"\n\nasync function getInput(): Promise<string> {\n // Check if there's data being piped in\n if (process.stdin.isTTY && process.stderr.isTTY) {\n console.error(\n \"Error: No input provided. Pipe in content with graphics objects.\",\n )\n process.exit(1)\n }\n\n const chunks = []\n\n // Read from stdin if available\n if (!process.stdin.isTTY) {\n for await (const chunk of process.stdin) {\n chunks.push(chunk)\n }\n }\n\n return chunks.join(\"\")\n}\n\nasync function main() {\n const { values } = parseArgs({\n options: {\n html: { type: \"boolean\" },\n url: { type: \"boolean\" },\n help: { type: \"boolean\" },\n },\n })\n\n if (values.help) {\n console.log(`\nUsage: graphics-debug [options]\n\nOptions:\n --html Output a single HTML file with all graphics\n --url Print a url to view the graphics in a browser\n --help Show this help message\n\nExamples:\n cat debug.log | graphics-debug\n echo '{ graphics: { points: [{x: 0, y: 0}] } }' | graphics-debug --html\n `)\n process.exit(0)\n }\n\n const input = await getInput()\n\n if (values.html) {\n const html = getHtmlFromLogString(input)\n writeFileSync(\"graphicsdebug.debug.html\", html)\n console.log('Wrote to \"graphicsdebug.debug.html\"')\n } else if (values.url) {\n const graphicsObjects = getGraphicsObjectsFromLogString(input)\n if (graphicsObjects.length === 0) {\n console.error(\"No graphics objects found in input\")\n process.exit(0)\n }\n\n const { url } = await fetch(\"https://gdstore.seve.workers.dev/store\", {\n method: \"POST\",\n body: JSON.stringify({\n graphicsObjects: getGraphicsObjectsFromLogString(input),\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n }).then((res) => res.json())\n\n const token = url.split(\"/get/\").pop()\n\n console.log(`https://graphicsdebug.com/t/${token}`)\n } else {\n const svgs = getSvgsFromLogString(input)\n svgs.forEach((svg, i) => {\n const filename = `${svg.title.toLowerCase().replace(/\\s+/g, \"-\")}-${i + 1}.debug.svg`\n writeFileSync(filename, svg.svg)\n console.log(`Wrote to \"${filename}\"`)\n })\n }\n}\n\nmain().catch((err) => {\n console.error(\"Error:\", err)\n process.exit(1)\n})\n"],"mappings":";;;;;;;;;;;AACA,SAAS,iBAAiB;AAC1B,OAA6B;AAC7B,SAAS,qBAAqB;AAO9B,eAAe,WAA4B;AAEzC,MAAI,QAAQ,MAAM,SAAS,QAAQ,OAAO,OAAO;AAC/C,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,CAAC;AAGhB,MAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,qBAAiB,SAAS,QAAQ,OAAO;AACvC,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,EAAE;AACvB;AAEA,eAAe,OAAO;AACpB,QAAM,EAAE,OAAO,IAAI,UAAU;AAAA,IAC3B,SAAS;AAAA,MACP,MAAM,EAAE,MAAM,UAAU;AAAA,MACxB,KAAK,EAAE,MAAM,UAAU;AAAA,MACvB,MAAM,EAAE,MAAM,UAAU;AAAA,IAC1B;AAAA,EACF,CAAC;AAED,MAAI,OAAO,MAAM;AACf,YAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAWX;AACD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,QAAQ,MAAM,SAAS;AAE7B,MAAI,OAAO,MAAM;AACf,UAAM,OAAO,qBAAqB,KAAK;AACvC,kBAAc,4BAA4B,IAAI;AAC9C,YAAQ,IAAI,qCAAqC;AAAA,EACnD,WAAW,OAAO,KAAK;AACrB,UAAM,kBAAkB,gCAAgC,KAAK;AAC7D,QAAI,gBAAgB,WAAW,GAAG;AAChC,cAAQ,MAAM,oCAAoC;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,EAAE,IAAI,IAAI,MAAM,MAAM,0CAA0C;AAAA,MACpE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,iBAAiB,gCAAgC,KAAK;AAAA,MACxD,CAAC;AAAA,MACD,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,IACF,CAAC,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC;AAE3B,UAAM,QAAQ,IAAI,MAAM,OAAO,EAAE,IAAI;AAErC,YAAQ,IAAI,+BAA+B,KAAK,EAAE;AAAA,EACpD,OAAO;AACL,UAAM,OAAO,qBAAqB,KAAK;AACvC,SAAK,QAAQ,CAAC,KAAK,MAAM;AACvB,YAAM,WAAW,GAAG,IAAI,MAAM,YAAY,EAAE,QAAQ,QAAQ,GAAG,CAAC,IAAI,IAAI,CAAC;AACzE,oBAAc,UAAU,IAAI,GAAG;AAC/B,cAAQ,IAAI,aAAa,QAAQ,GAAG;AAAA,IACtC,CAAC;AAAA,EACH;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,UAAU,GAAG;AAC3B,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../cli/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { parseArgs } from \"node:util\"\nimport { readFileSync } from \"node:fs\"\nimport { writeFileSync } from \"node:fs\"\nimport {\n getSvgsFromLogString,\n getHtmlFromLogString,\n getGraphicsObjectsFromLogString,\n} from \"../lib\"\n\nasync function getInput(): Promise<string> {\n // Check if there's data being piped in\n if (process.stdin.isTTY && process.stderr.isTTY) {\n console.error(\n \"Error: No input provided. Pipe in content with graphics objects.\",\n )\n process.exit(1)\n }\n\n const chunks = []\n\n // Read from stdin if available\n if (!process.stdin.isTTY) {\n for await (const chunk of process.stdin) {\n chunks.push(chunk)\n }\n }\n\n return chunks.join(\"\")\n}\n\nasync function main() {\n const { values } = parseArgs({\n options: {\n html: { type: \"boolean\" },\n url: { type: \"boolean\" },\n help: { type: \"boolean\" },\n },\n })\n\n if (values.help) {\n console.log(`\nUsage: graphics-debug [options]\n\nOptions:\n --html Output a single HTML file with all graphics\n --url Print a url to view the graphics in a browser\n --help Show this help message\n\nExamples:\n cat debug.log | graphics-debug\n echo '{ graphics: { points: [{x: 0, y: 0}] } }' | graphics-debug --html\n `)\n process.exit(0)\n }\n\n const input = await getInput()\n\n if (values.html) {\n const html = getHtmlFromLogString(input)\n writeFileSync(\"graphicsdebug.debug.html\", html)\n console.log('Wrote to \"graphicsdebug.debug.html\"')\n } else if (values.url) {\n const graphicsObjects = getGraphicsObjectsFromLogString(input)\n if (graphicsObjects.length === 0) {\n console.error(\"No graphics objects found in input\")\n process.exit(0)\n }\n\n const { url } = await fetch(\"https://gdstore.seve.workers.dev/store\", {\n method: \"POST\",\n body: JSON.stringify({\n graphicsObjects: getGraphicsObjectsFromLogString(input),\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n }).then((res) => res.json())\n\n const token = url.split(\"/get/\").pop()\n\n console.log(`https://graphicsdebug.com/t/${token}`)\n } else {\n const svgs = getSvgsFromLogString(input)\n svgs.forEach((svg, i) => {\n const filename = `${svg.title.toLowerCase().replace(/\\s+/g, \"-\")}-${i + 1}.debug.svg`\n writeFileSync(filename, svg.svg)\n console.log(`Wrote to \"${filename}\"`)\n })\n }\n}\n\nmain().catch((err) => {\n console.error(\"Error:\", err)\n process.exit(1)\n})\n"],"mappings":";;;;;;;;;;;AACA,SAAS,iBAAiB;AAE1B,SAAS,qBAAqB;AAO9B,eAAe,WAA4B;AAEzC,MAAI,QAAQ,MAAM,SAAS,QAAQ,OAAO,OAAO;AAC/C,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,CAAC;AAGhB,MAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,qBAAiB,SAAS,QAAQ,OAAO;AACvC,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,EAAE;AACvB;AAEA,eAAe,OAAO;AACpB,QAAM,EAAE,OAAO,IAAI,UAAU;AAAA,IAC3B,SAAS;AAAA,MACP,MAAM,EAAE,MAAM,UAAU;AAAA,MACxB,KAAK,EAAE,MAAM,UAAU;AAAA,MACvB,MAAM,EAAE,MAAM,UAAU;AAAA,IAC1B;AAAA,EACF,CAAC;AAED,MAAI,OAAO,MAAM;AACf,YAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAWX;AACD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,QAAQ,MAAM,SAAS;AAE7B,MAAI,OAAO,MAAM;AACf,UAAM,OAAO,qBAAqB,KAAK;AACvC,kBAAc,4BAA4B,IAAI;AAC9C,YAAQ,IAAI,qCAAqC;AAAA,EACnD,WAAW,OAAO,KAAK;AACrB,UAAM,kBAAkB,gCAAgC,KAAK;AAC7D,QAAI,gBAAgB,WAAW,GAAG;AAChC,cAAQ,MAAM,oCAAoC;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,EAAE,IAAI,IAAI,MAAM,MAAM,0CAA0C;AAAA,MACpE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,iBAAiB,gCAAgC,KAAK;AAAA,MACxD,CAAC;AAAA,MACD,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,IACF,CAAC,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC;AAE3B,UAAM,QAAQ,IAAI,MAAM,OAAO,EAAE,IAAI;AAErC,YAAQ,IAAI,+BAA+B,KAAK,EAAE;AAAA,EACpD,OAAO;AACL,UAAM,OAAO,qBAAqB,KAAK;AACvC,SAAK,QAAQ,CAAC,KAAK,MAAM;AACvB,YAAM,WAAW,GAAG,IAAI,MAAM,YAAY,EAAE,QAAQ,QAAQ,GAAG,CAAC,IAAI,IAAI,CAAC;AACzE,oBAAc,UAAU,IAAI,GAAG;AAC/B,cAAQ,IAAI,aAAa,QAAQ,GAAG;AAAA,IACtC,CAAC;AAAA,EACH;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,UAAU,GAAG;AAC3B,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
@@ -0,0 +1,8 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { GraphicsObject } from './types.js';
3
+
4
+ declare const InteractiveGraphics: ({ graphics, }: {
5
+ graphics: GraphicsObject;
6
+ }) => react_jsx_runtime.JSX.Element;
7
+
8
+ export { InteractiveGraphics };
@@ -0,0 +1,346 @@
1
+ // site/components/InteractiveGraphics/InteractiveGraphics.tsx
2
+ import {
3
+ compose,
4
+ scale,
5
+ translate
6
+ } from "transformation-matrix";
7
+ import { useState as useState4 } from "react";
8
+ import useMouseMatrixTransform from "use-mouse-matrix-transform";
9
+ import { SuperGrid } from "react-supergrid";
10
+ import useResizeObserver from "@react-hook/resize-observer";
11
+
12
+ // site/components/InteractiveGraphics/Line.tsx
13
+ import { applyToPoint } from "transformation-matrix";
14
+ import { lighten } from "polished";
15
+ import { useState } from "react";
16
+
17
+ // site/components/InteractiveGraphics/Tooltip.tsx
18
+ import { jsx } from "react/jsx-runtime";
19
+ var Tooltip = ({ text }) => {
20
+ return /* @__PURE__ */ jsx("div", { className: "inline-block", children: /* @__PURE__ */ jsx(
21
+ "div",
22
+ {
23
+ style: {
24
+ background: "white",
25
+ border: "1px solid #ccc",
26
+ boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.1)",
27
+ borderRadius: "4px",
28
+ padding: "4px 8px",
29
+ fontSize: "12px",
30
+ maxWidth: "300px",
31
+ overflow: "hidden",
32
+ textOverflow: "ellipsis"
33
+ },
34
+ children: text
35
+ }
36
+ ) });
37
+ };
38
+
39
+ // site/utils/distToLineSegment.ts
40
+ var distToLineSegment = (px, py, x1, y1, x2, y2) => {
41
+ const A = px - x1;
42
+ const B = py - y1;
43
+ const C = x2 - x1;
44
+ const D = y2 - y1;
45
+ const dot = A * C + B * D;
46
+ const lenSq = C * C + D * D;
47
+ let param = -1;
48
+ if (lenSq !== 0) param = dot / lenSq;
49
+ let xx = 0;
50
+ let yy = 0;
51
+ if (param < 0) {
52
+ xx = x1;
53
+ yy = y1;
54
+ } else if (param > 1) {
55
+ xx = x2;
56
+ yy = y2;
57
+ } else {
58
+ xx = x1 + param * C;
59
+ yy = y1 + param * D;
60
+ }
61
+ const dx = px - xx;
62
+ const dy = py - yy;
63
+ return Math.sqrt(dx * dx + dy * dy);
64
+ };
65
+
66
+ // site/components/InteractiveGraphics/defaultColors.ts
67
+ var defaultColors = [
68
+ "rgba(239, 68, 68, 0.8)",
69
+ // red-300
70
+ "rgba(249, 115, 22, 0.8)",
71
+ // orange-300
72
+ "rgba(245, 158, 11, 0.8)",
73
+ // amber-300
74
+ "rgba(234, 179, 8, 0.8)",
75
+ // yellow-300
76
+ "rgba(132, 204, 22, 0.8)",
77
+ // lime-300
78
+ "rgba(34, 197, 94, 0.8)",
79
+ // green-300
80
+ "rgba(16, 185, 129, 0.8)",
81
+ // emerald-300
82
+ "rgba(20, 184, 166, 0.8)",
83
+ // teal-300
84
+ "rgba(6, 182, 212, 0.8)",
85
+ // cyan-300
86
+ "rgba(14, 165, 233, 0.8)",
87
+ // sky-300
88
+ "rgba(59, 130, 246, 0.8)",
89
+ // blue-300
90
+ "rgba(99, 102, 241, 0.8)",
91
+ // indigo-300
92
+ "rgba(139, 92, 246, 0.8)",
93
+ // violet-300
94
+ "rgba(168, 85, 247, 0.8)",
95
+ // purple-300
96
+ "rgba(217, 70, 239, 0.8)",
97
+ // fuchsia-300
98
+ "rgba(236, 72, 153, 0.8)",
99
+ // pink-300
100
+ "rgba(249, 168, 212, 0.8)",
101
+ // rose-300
102
+ "rgba(161, 161, 170, 0.8)"
103
+ // zinc-300
104
+ ];
105
+
106
+ // site/components/InteractiveGraphics/Line.tsx
107
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
108
+ var Line = ({
109
+ line,
110
+ index,
111
+ interactiveState
112
+ }) => {
113
+ const { activeLayers, activeStep, realToScreen } = interactiveState;
114
+ const {
115
+ points,
116
+ layer,
117
+ step,
118
+ strokeColor,
119
+ strokeWidth = 1 / realToScreen.a
120
+ } = line;
121
+ const [isHovered, setIsHovered] = useState(false);
122
+ const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
123
+ const screenPoints = points.map((p) => applyToPoint(realToScreen, p));
124
+ const handleMouseMove = (e) => {
125
+ const rect = e.currentTarget.getBoundingClientRect();
126
+ const mouseX = e.clientX - rect.left;
127
+ const mouseY = e.clientY - rect.top;
128
+ const hoverThreshold = 10;
129
+ setMousePos({ x: mouseX, y: mouseY });
130
+ let isNearLine = false;
131
+ for (let i = 0; i < screenPoints.length - 1; i++) {
132
+ const dist = distToLineSegment(
133
+ mouseX,
134
+ mouseY,
135
+ screenPoints[i].x,
136
+ screenPoints[i].y,
137
+ screenPoints[i + 1].x,
138
+ screenPoints[i + 1].y
139
+ );
140
+ if (dist < hoverThreshold) {
141
+ isNearLine = true;
142
+ break;
143
+ }
144
+ }
145
+ setIsHovered(isNearLine);
146
+ };
147
+ const baseColor = strokeColor ?? defaultColors[index % defaultColors.length];
148
+ return /* @__PURE__ */ jsxs(
149
+ "svg",
150
+ {
151
+ style: {
152
+ position: "absolute",
153
+ top: 0,
154
+ left: 0,
155
+ right: 0,
156
+ bottom: 0
157
+ },
158
+ onMouseMove: handleMouseMove,
159
+ onMouseLeave: () => setIsHovered(false),
160
+ children: [
161
+ /* @__PURE__ */ jsx2(
162
+ "polyline",
163
+ {
164
+ points: screenPoints.map((p) => `${p.x},${p.y}`).join(" "),
165
+ stroke: isHovered ? lighten(0.2, baseColor) : baseColor,
166
+ strokeWidth: strokeWidth * realToScreen.a
167
+ }
168
+ ),
169
+ isHovered && line.label && /* @__PURE__ */ jsx2(
170
+ "foreignObject",
171
+ {
172
+ x: mousePos.x,
173
+ y: mousePos.y - 40,
174
+ width: 300,
175
+ height: 40,
176
+ children: /* @__PURE__ */ jsx2(Tooltip, { text: line.label })
177
+ }
178
+ )
179
+ ]
180
+ }
181
+ );
182
+ };
183
+
184
+ // site/components/InteractiveGraphics/Point.tsx
185
+ import { applyToPoint as applyToPoint2 } from "transformation-matrix";
186
+ import { lighten as lighten2 } from "polished";
187
+ import { useState as useState2 } from "react";
188
+ import { jsx as jsx3 } from "react/jsx-runtime";
189
+ var Point = ({
190
+ point,
191
+ interactiveState,
192
+ index
193
+ }) => {
194
+ const { color, label, layer, step } = point;
195
+ const { activeLayers, activeStep, realToScreen } = interactiveState;
196
+ const [isHovered, setIsHovered] = useState2(false);
197
+ const screenPoint = applyToPoint2(realToScreen, point);
198
+ const size = 10;
199
+ return /* @__PURE__ */ jsx3(
200
+ "div",
201
+ {
202
+ style: {
203
+ position: "absolute",
204
+ left: screenPoint.x - size / 2,
205
+ top: screenPoint.y - size / 2,
206
+ width: size,
207
+ height: size,
208
+ borderRadius: "50%",
209
+ border: `2px solid ${isHovered ? lighten2(0.2, color ?? defaultColors[index % defaultColors.length]) : color ?? defaultColors[index % defaultColors.length]}`,
210
+ cursor: "pointer",
211
+ transition: "border-color 0.2s"
212
+ },
213
+ onMouseEnter: () => setIsHovered(true),
214
+ onMouseLeave: () => setIsHovered(false),
215
+ children: isHovered && label && /* @__PURE__ */ jsx3(
216
+ "div",
217
+ {
218
+ style: {
219
+ position: "absolute",
220
+ bottom: "100%",
221
+ left: "50%",
222
+ transform: "translateX(-50%)",
223
+ marginBottom: 8
224
+ },
225
+ children: /* @__PURE__ */ jsx3(Tooltip, { text: label })
226
+ }
227
+ )
228
+ }
229
+ );
230
+ };
231
+
232
+ // site/components/InteractiveGraphics/Rect.tsx
233
+ import { applyToPoint as applyToPoint3 } from "transformation-matrix";
234
+ import { lighten as lighten3 } from "polished";
235
+ import { useState as useState3 } from "react";
236
+ import { jsx as jsx4 } from "react/jsx-runtime";
237
+ var Rect = ({
238
+ rect,
239
+ interactiveState,
240
+ index
241
+ }) => {
242
+ const defaultColor = defaultColors[index % defaultColors.length];
243
+ const { center, width, height, fill, stroke, layer, step } = rect;
244
+ const { activeLayers, activeStep, realToScreen } = interactiveState;
245
+ const [isHovered, setIsHovered] = useState3(false);
246
+ const screenCenter = applyToPoint3(realToScreen, center);
247
+ const screenWidth = width * realToScreen.a;
248
+ const screenHeight = height * Math.abs(realToScreen.d);
249
+ const hasStrokeOrFill = fill !== void 0 || stroke !== void 0;
250
+ let backgroundColor = hasStrokeOrFill ? fill || "transparent" : defaultColor;
251
+ if (isHovered) {
252
+ backgroundColor = lighten3(0.2, backgroundColor);
253
+ }
254
+ return /* @__PURE__ */ jsx4(
255
+ "div",
256
+ {
257
+ style: {
258
+ position: "absolute",
259
+ left: screenCenter.x - screenWidth / 2,
260
+ top: screenCenter.y - screenHeight / 2,
261
+ width: screenWidth,
262
+ height: screenHeight,
263
+ backgroundColor,
264
+ border: stroke ? `2px solid ${isHovered ? lighten3(0.2, stroke) : stroke}` : "none",
265
+ cursor: "pointer",
266
+ transition: "border-color 0.2s"
267
+ },
268
+ onMouseEnter: () => setIsHovered(true),
269
+ onMouseLeave: () => setIsHovered(false),
270
+ children: isHovered && rect.label && /* @__PURE__ */ jsx4(
271
+ "div",
272
+ {
273
+ style: {
274
+ position: "absolute",
275
+ bottom: "100%",
276
+ left: "50%",
277
+ transform: "translateX(-50%)",
278
+ marginBottom: 8
279
+ },
280
+ children: /* @__PURE__ */ jsx4(Tooltip, { text: rect.label })
281
+ }
282
+ )
283
+ }
284
+ );
285
+ };
286
+
287
+ // site/components/InteractiveGraphics/InteractiveGraphics.tsx
288
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
289
+ var InteractiveGraphics = ({
290
+ graphics
291
+ }) => {
292
+ const [activeLayers, setActiveLayers] = useState4(null);
293
+ const [activeStep, setActiveStep] = useState4(null);
294
+ const [size, setSize] = useState4({ width: 600, height: 600 });
295
+ const { transform: realToScreen, ref } = useMouseMatrixTransform({
296
+ initialTransform: compose(translate(0, size.height), scale(1, -1))
297
+ });
298
+ useResizeObserver(ref, (entry) => {
299
+ setSize({
300
+ width: entry.contentRect.width,
301
+ height: entry.contentRect.height
302
+ });
303
+ });
304
+ const interactiveState = {
305
+ activeLayers,
306
+ activeStep,
307
+ realToScreen
308
+ };
309
+ return /* @__PURE__ */ jsxs2(
310
+ "div",
311
+ {
312
+ ref,
313
+ style: {
314
+ position: "relative",
315
+ height: 600,
316
+ overflow: "hidden"
317
+ },
318
+ children: [
319
+ graphics.lines?.map((l, i) => /* @__PURE__ */ jsx5(Line, { line: l, index: i, interactiveState }, i)),
320
+ graphics.rects?.map((r, i) => /* @__PURE__ */ jsx5(Rect, { rect: r, index: i, interactiveState }, i)),
321
+ graphics.points?.map((p, i) => /* @__PURE__ */ jsx5(
322
+ Point,
323
+ {
324
+ point: p,
325
+ index: i,
326
+ interactiveState
327
+ },
328
+ i
329
+ )),
330
+ /* @__PURE__ */ jsx5(
331
+ SuperGrid,
332
+ {
333
+ stringifyCoord: (x, y) => `${x.toFixed(2)}, ${y.toFixed(2)}`,
334
+ width: size.width,
335
+ height: size.height,
336
+ transform: realToScreen
337
+ }
338
+ )
339
+ ]
340
+ }
341
+ );
342
+ };
343
+ export {
344
+ InteractiveGraphics
345
+ };
346
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../site/components/InteractiveGraphics/InteractiveGraphics.tsx","../../site/components/InteractiveGraphics/Line.tsx","../../site/components/InteractiveGraphics/Tooltip.tsx","../../site/utils/distToLineSegment.ts","../../site/components/InteractiveGraphics/defaultColors.ts","../../site/components/InteractiveGraphics/Point.tsx","../../site/components/InteractiveGraphics/Rect.tsx"],"sourcesContent":["import {\n compose,\n type Matrix,\n applyToPoint,\n scale,\n translate,\n} from \"transformation-matrix\"\nimport { GraphicsObject } from \"../../../lib\"\nimport { useState } from \"react\"\nimport useMouseMatrixTransform from \"use-mouse-matrix-transform\"\nimport { InteractiveState } from \"./InteractiveState\"\nimport { SuperGrid } from \"react-supergrid\"\nimport useResizeObserver from \"@react-hook/resize-observer\"\nimport { Line } from \"./Line\"\nimport { Point } from \"./Point\"\nimport { Rect } from \"./Rect\"\n\nexport const InteractiveGraphics = ({\n graphics,\n}: { graphics: GraphicsObject }) => {\n const [activeLayers, setActiveLayers] = useState<string[] | null>(null)\n const [activeStep, setActiveStep] = useState<number | null>(null)\n const [size, setSize] = useState({ width: 600, height: 600 })\n\n const { transform: realToScreen, ref } = useMouseMatrixTransform({\n initialTransform: compose(translate(0, size.height), scale(1, -1)),\n })\n\n useResizeObserver(ref, (entry: ResizeObserverEntry) => {\n setSize({\n width: entry.contentRect.width,\n height: entry.contentRect.height,\n })\n })\n\n const interactiveState: InteractiveState = {\n activeLayers: activeLayers,\n activeStep: activeStep,\n realToScreen: realToScreen,\n }\n\n return (\n <div\n ref={ref}\n style={{\n position: \"relative\",\n height: 600,\n overflow: \"hidden\",\n }}\n >\n {graphics.lines?.map((l, i) => (\n <Line key={i} line={l} index={i} interactiveState={interactiveState} />\n ))}\n {graphics.rects?.map((r, i) => (\n <Rect key={i} rect={r} index={i} interactiveState={interactiveState} />\n ))}\n {graphics.points?.map((p, i) => (\n <Point\n key={i}\n point={p}\n index={i}\n interactiveState={interactiveState}\n />\n ))}\n <SuperGrid\n stringifyCoord={(x, y) => `${x.toFixed(2)}, ${y.toFixed(2)}`}\n width={size.width}\n height={size.height}\n transform={realToScreen}\n />\n </div>\n )\n}\n","import type * as Types from \"lib/types\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { InteractiveState } from \"./InteractiveState\"\nimport { lighten } from \"polished\"\nimport { useState } from \"react\"\nimport { Tooltip } from \"./Tooltip\"\nimport { distToLineSegment } from \"site/utils/distToLineSegment\"\nimport { defaultColors } from \"./defaultColors\"\n\nexport const Line = ({\n line,\n index,\n interactiveState,\n}: { line: Types.Line; index: number; interactiveState: InteractiveState }) => {\n const { activeLayers, activeStep, realToScreen } = interactiveState\n const {\n points,\n layer,\n step,\n strokeColor,\n strokeWidth = 1 / realToScreen.a,\n } = line\n const [isHovered, setIsHovered] = useState(false)\n const [mousePos, setMousePos] = useState({ x: 0, y: 0 })\n\n const screenPoints = points.map((p) => applyToPoint(realToScreen, p))\n\n const handleMouseMove = (e: React.MouseEvent) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const mouseX = e.clientX - rect.left\n const mouseY = e.clientY - rect.top\n const hoverThreshold = 10 // pixels\n\n setMousePos({ x: mouseX, y: mouseY })\n\n // Check distance to each line segment\n let isNearLine = false\n for (let i = 0; i < screenPoints.length - 1; i++) {\n const dist = distToLineSegment(\n mouseX,\n mouseY,\n screenPoints[i].x,\n screenPoints[i].y,\n screenPoints[i + 1].x,\n screenPoints[i + 1].y,\n )\n if (dist < hoverThreshold) {\n isNearLine = true\n break\n }\n }\n\n setIsHovered(isNearLine)\n }\n\n const baseColor = strokeColor ?? defaultColors[index % defaultColors.length]\n\n return (\n <svg\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n }}\n onMouseMove={handleMouseMove}\n onMouseLeave={() => setIsHovered(false)}\n >\n <polyline\n points={screenPoints.map((p) => `${p.x},${p.y}`).join(\" \")}\n stroke={isHovered ? lighten(0.2, baseColor) : baseColor}\n strokeWidth={strokeWidth * realToScreen.a}\n />\n {isHovered && line.label && (\n <foreignObject\n x={mousePos.x}\n y={mousePos.y - 40}\n width={300}\n height={40}\n >\n <Tooltip text={line.label} />\n </foreignObject>\n )}\n </svg>\n )\n}\n","export const Tooltip = ({ text }: { text: string }) => {\n return (\n <div className=\"inline-block\">\n <div\n style={{\n background: \"white\",\n border: \"1px solid #ccc\",\n boxShadow: \"0 0 10px 0 rgba(0, 0, 0, 0.1)\",\n borderRadius: \"4px\",\n padding: \"4px 8px\",\n fontSize: \"12px\",\n maxWidth: \"300px\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {text}\n </div>\n </div>\n )\n}\n","// Calculate distance from point to line segment\nexport const distToLineSegment = (\n px: number,\n py: number,\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n) => {\n const A = px - x1\n const B = py - y1\n const C = x2 - x1\n const D = y2 - y1\n\n const dot = A * C + B * D\n const lenSq = C * C + D * D\n let param = -1\n\n if (lenSq !== 0) param = dot / lenSq\n\n let xx = 0\n let yy = 0\n\n if (param < 0) {\n xx = x1\n yy = y1\n } else if (param > 1) {\n xx = x2\n yy = y2\n } else {\n xx = x1 + param * C\n yy = y1 + param * D\n }\n\n const dx = px - xx\n const dy = py - yy\n return Math.sqrt(dx * dx + dy * dy)\n}\n","// These are default colors if no color is provided\n// colors are made based on the index of the item in the array\n\nexport const defaultColors = [\n \"rgba(239, 68, 68, 0.8)\", // red-300\n \"rgba(249, 115, 22, 0.8)\", // orange-300\n \"rgba(245, 158, 11, 0.8)\", // amber-300\n \"rgba(234, 179, 8, 0.8)\", // yellow-300\n \"rgba(132, 204, 22, 0.8)\", // lime-300\n \"rgba(34, 197, 94, 0.8)\", // green-300\n \"rgba(16, 185, 129, 0.8)\", // emerald-300\n \"rgba(20, 184, 166, 0.8)\", // teal-300\n \"rgba(6, 182, 212, 0.8)\", // cyan-300\n \"rgba(14, 165, 233, 0.8)\", // sky-300\n \"rgba(59, 130, 246, 0.8)\", // blue-300\n \"rgba(99, 102, 241, 0.8)\", // indigo-300\n \"rgba(139, 92, 246, 0.8)\", // violet-300\n \"rgba(168, 85, 247, 0.8)\", // purple-300\n \"rgba(217, 70, 239, 0.8)\", // fuchsia-300\n \"rgba(236, 72, 153, 0.8)\", // pink-300\n \"rgba(249, 168, 212, 0.8)\", // rose-300\n \"rgba(161, 161, 170, 0.8)\", // zinc-300\n]\n","import type * as Types from \"lib/types\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { InteractiveState } from \"./InteractiveState\"\nimport { lighten } from \"polished\"\nimport { useState } from \"react\"\nimport { Tooltip } from \"./Tooltip\"\nimport { defaultColors } from \"./defaultColors\"\n\nexport const Point = ({\n point,\n interactiveState,\n index,\n}: {\n point: Types.Point\n interactiveState: InteractiveState\n index: number\n}) => {\n const { color, label, layer, step } = point\n const { activeLayers, activeStep, realToScreen } = interactiveState\n const [isHovered, setIsHovered] = useState(false)\n\n const screenPoint = applyToPoint(realToScreen, point)\n const size = 10\n\n return (\n <div\n style={{\n position: \"absolute\",\n left: screenPoint.x - size / 2,\n top: screenPoint.y - size / 2,\n width: size,\n height: size,\n borderRadius: \"50%\",\n border: `2px solid ${\n isHovered\n ? lighten(0.2, color ?? defaultColors[index % defaultColors.length])\n : color ?? defaultColors[index % defaultColors.length]\n }`,\n cursor: \"pointer\",\n transition: \"border-color 0.2s\",\n }}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {isHovered && label && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: 8,\n }}\n >\n <Tooltip text={label} />\n </div>\n )}\n </div>\n )\n}\n","import type * as Types from \"lib/types\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport type { InteractiveState } from \"./InteractiveState\"\nimport { lighten } from \"polished\"\nimport { useState } from \"react\"\nimport { Tooltip } from \"./Tooltip\"\nimport { defaultColors } from \"./defaultColors\"\n\nexport const Rect = ({\n rect,\n interactiveState,\n index,\n}: {\n rect: Types.Rect\n interactiveState: InteractiveState\n index: number\n}) => {\n const defaultColor = defaultColors[index % defaultColors.length]\n const { center, width, height, fill, stroke, layer, step } = rect\n const { activeLayers, activeStep, realToScreen } = interactiveState\n const [isHovered, setIsHovered] = useState(false)\n\n const screenCenter = applyToPoint(realToScreen, center)\n const screenWidth = width * realToScreen.a\n const screenHeight = height * Math.abs(realToScreen.d)\n\n // Default style when neither fill nor stroke is specified\n const hasStrokeOrFill = fill !== undefined || stroke !== undefined\n\n let backgroundColor = hasStrokeOrFill ? fill || \"transparent\" : defaultColor\n if (isHovered) {\n backgroundColor = lighten(0.2, backgroundColor)\n }\n\n return (\n <div\n style={{\n position: \"absolute\",\n left: screenCenter.x - screenWidth / 2,\n top: screenCenter.y - screenHeight / 2,\n width: screenWidth,\n height: screenHeight,\n backgroundColor,\n border: stroke\n ? `2px solid ${isHovered ? lighten(0.2, stroke) : stroke}`\n : \"none\",\n cursor: \"pointer\",\n transition: \"border-color 0.2s\",\n }}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {isHovered && rect.label && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: 8,\n }}\n >\n <Tooltip text={rect.label} />\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["useState","jsx","applyToPoint","lighten","useState","jsx","useState","applyToPoint","lighten","applyToPoint","lighten","useState","jsx","useState","applyToPoint","lighten","jsx","jsxs","useState"]}
@@ -3,6 +3,8 @@ interface Point {
3
3
  y: number;
4
4
  color?: string;
5
5
  label?: string;
6
+ layer?: string;
7
+ step?: number;
6
8
  }
7
9
  interface Line {
8
10
  points: {
@@ -11,6 +13,9 @@ interface Line {
11
13
  }[];
12
14
  strokeWidth?: number;
13
15
  strokeColor?: string;
16
+ layer?: string;
17
+ step?: number;
18
+ label?: string;
14
19
  }
15
20
  interface Rect {
16
21
  center: {
@@ -22,6 +27,9 @@ interface Rect {
22
27
  fill?: string;
23
28
  stroke?: string;
24
29
  color?: string;
30
+ layer?: string;
31
+ step?: number;
32
+ label?: string;
25
33
  }
26
34
  interface Circle {
27
35
  center: {
@@ -31,6 +39,8 @@ interface Circle {
31
39
  radius: number;
32
40
  fill?: string;
33
41
  stroke?: string;
42
+ layer?: string;
43
+ step?: number;
34
44
  }
35
45
  interface GraphicsObject {
36
46
  points?: Point[];
package/package.json CHANGED
@@ -2,16 +2,27 @@
2
2
  "name": "graphics-debug",
3
3
  "main": "dist/lib/index.js",
4
4
  "type": "module",
5
- "version": "0.0.5",
5
+ "version": "0.0.7",
6
6
  "files": [
7
7
  "dist"
8
8
  ],
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/lib/index.d.ts",
12
+ "import": "./dist/lib/index.js"
13
+ },
14
+ "./react": {
15
+ "types": "./dist/lib/react.d.ts",
16
+ "import": "./dist/lib/react.js"
17
+ }
18
+ },
9
19
  "bin": {
10
20
  "graphics-debug": "./dist/cli/cli.js",
11
21
  "gd": "./dist/cli/cli.js"
12
22
  },
13
23
  "scripts": {
14
- "start": "vite",
24
+ "start": "cosmos",
25
+ "start:landing": "vite",
15
26
  "build": "tsup-node ./cli ./lib --dts --format esm --sourcemap",
16
27
  "format": "biome format --write .",
17
28
  "format:check": "biome format .",
@@ -19,6 +30,7 @@
19
30
  },
20
31
  "devDependencies": {
21
32
  "@biomejs/biome": "^1.9.4",
33
+ "@react-hook/resize-observer": "^2.0.2",
22
34
  "@types/bun": "latest",
23
35
  "@types/debug": "^4.1.12",
24
36
  "@types/jsdom": "^21.1.7",
@@ -31,18 +43,24 @@
31
43
  "debug": "^4.3.7",
32
44
  "jsdom": "^25.0.1",
33
45
  "react": "^18.3.1",
46
+ "react-cosmos": "^6.2.3",
47
+ "react-cosmos-plugin-vite": "^6.2.0",
34
48
  "react-dom": "^18.3.1",
35
49
  "tsup": "^8.3.5",
36
- "vite": "^5.4.11"
50
+ "vite": "^5.4.11",
51
+ "vite-tsconfig-paths": "^5.1.4"
37
52
  },
38
53
  "peerDependencies": {
39
54
  "typescript": "^5.0.0"
40
55
  },
41
56
  "dependencies": {
42
57
  "@types/react-router-dom": "^5.3.3",
58
+ "polished": "^4.3.1",
43
59
  "pretty": "^2.0.0",
44
60
  "react-router-dom": "^6.28.0",
61
+ "react-supergrid": "^1.0.10",
45
62
  "svgson": "^5.3.1",
46
- "transformation-matrix": "^2.16.1"
63
+ "transformation-matrix": "^2.16.1",
64
+ "use-mouse-matrix-transform": "^1.3.0"
47
65
  }
48
66
  }