From fc93e29de8366a080f224825b4f9960bd45b0acd Mon Sep 17 00:00:00 2001
From: ugin <157204743+ugin-man@users.noreply.github.com>
Date: Tue, 8 Sep 2026 08:26:22 +0900
Subject: [PATCH] fix: use GraphicsObject shape fields in the fallback renderer
---
lib/react/SimpleGraphicsSVG.tsx | 24 ++++++------
tests/fallback-shapes.test.tsx | 69 +++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+), 12 deletions(-)
create mode 100644 tests/fallback-shapes.test.tsx
diff --git a/lib/react/SimpleGraphicsSVG.tsx b/lib/react/SimpleGraphicsSVG.tsx
index 3a73f9f..4e3f3c8 100644
--- a/lib/react/SimpleGraphicsSVG.tsx
+++ b/lib/react/SimpleGraphicsSVG.tsx
@@ -30,16 +30,16 @@ export function SimpleGraphicsSVG({ graphics }: { graphics: GraphicsObject }) {
for (const p of pts) consider(p.x, p.y)
}
for (const r of rects) {
- const x = (r as any).x ?? 0
- const y = (r as any).y ?? 0
+ const x = r.center.x - r.width / 2
+ const y = r.center.y - r.height / 2
const w = (r as any).width ?? 0
const h = (r as any).height ?? 0
consider(x, y)
consider(x + w, y + h)
}
for (const c of circles) {
- const x = (c as any).x ?? 0
- const y = (c as any).y ?? 0
+ const x = c.center.x
+ const y = c.center.y
const rad = (c as any).radius ?? 1
consider(x - rad, y - rad)
consider(x + rad, y + rad)
@@ -74,12 +74,12 @@ export function SimpleGraphicsSVG({ graphics }: { graphics: GraphicsObject }) {
{rects.map((r: any, i: number) => (
))}
@@ -97,11 +97,11 @@ export function SimpleGraphicsSVG({ graphics }: { graphics: GraphicsObject }) {
{circles.map((c: any, i: number) => (
))}
diff --git a/tests/fallback-shapes.test.tsx b/tests/fallback-shapes.test.tsx
new file mode 100644
index 0000000..04ed2f5
--- /dev/null
+++ b/tests/fallback-shapes.test.tsx
@@ -0,0 +1,69 @@
+import { expect, test } from "bun:test"
+import type { GraphicsObject } from "graphics-debug"
+import type { ReactElement } from "react"
+import { SimpleGraphicsSVG } from "../lib/react/SimpleGraphicsSVG"
+
+const {
+ renderToStaticMarkup,
+}: {
+ renderToStaticMarkup: (element: ReactElement) => string
+} = require("react-dom/server")
+
+const render = (graphics: GraphicsObject) =>
+ renderToStaticMarkup()
+
+test("fallback rectangles use their center and include their actual bounds", () => {
+ const svg = render({
+ rects: [{ center: { x: 100, y: -50 }, width: 20, height: 10 }],
+ })
+
+ expect(svg).toContain('x="90" y="-55" width="20" height="10"')
+ expect(svg).toContain('viewBox="80 -65 40 30"')
+})
+
+test("fallback circles use their center and include their actual bounds", () => {
+ const svg = render({
+ circles: [{ center: { x: -40, y: 70 }, radius: 5 }],
+ })
+
+ expect(svg).toContain('cx="-40" cy="70" r="5"')
+ expect(svg).toContain('viewBox="-55 55 30 30"')
+})
+
+test("the viewBox includes separated rectangles and circles", () => {
+ const svg = render({
+ rects: [{ center: { x: 100, y: -50 }, width: 20, height: 10 }],
+ circles: [{ center: { x: -40, y: 70 }, radius: 5 }],
+ })
+
+ expect(svg).toContain('viewBox="-55 -65 175 150"')
+})
+
+test("fallback shapes use the fill and stroke fields from GraphicsObject", () => {
+ const svg = render({
+ rects: [
+ {
+ center: { x: 0, y: 0 },
+ width: 20,
+ height: 10,
+ fill: "red",
+ stroke: "blue",
+ },
+ ],
+ circles: [
+ { center: { x: 40, y: 0 }, radius: 5, fill: "green", stroke: "purple" },
+ ],
+ })
+
+ expect(svg).toContain('fill="red" stroke="blue"')
+ expect(svg).toContain('fill="green" stroke="purple"')
+})
+
+test("rectangles centered at the origin extend to both sides of it", () => {
+ const svg = render({
+ rects: [{ center: { x: 0, y: 0 }, width: 20, height: 10 }],
+ })
+
+ expect(svg).toContain('x="-10" y="-5"')
+ expect(svg).toContain('viewBox="-20 -15 40 30"')
+})