Skip to content

Commit 8f2d54e

Browse files
authored
Add debug prop to Mafs (#173)
This adds `<Mafs debug />` which shows a helpfully zoomed out view, letting you peek beyond what the camera is limited to. https://github.com/user-attachments/assets/5da478ba-7422-47e4-b436-9eda91ce0cee
1 parent 1d00248 commit 8f2d54e

13 files changed

+203
-124
lines changed

.api-report/mafs.api.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export const Line: {
102102
};
103103

104104
// @public (undocumented)
105-
export function Mafs({ width: propWidth, height: propHeight, pan, zoom, viewBox, preserveAspectRatio, children, ssr, onClick, }: MafsProps): JSX_2.Element;
105+
export function Mafs({ width: propWidth, height: propHeight, pan, zoom, viewBox, preserveAspectRatio, children, ssr, debug, onClick, }: MafsProps): JSX_2.Element;
106106

107107
// @public (undocumented)
108108
export namespace Mafs {
@@ -127,6 +127,7 @@ export type MafsProps = React_2.PropsWithChildren<{
127127
preserveAspectRatio?: "contain" | false;
128128
onClick?: (point: vec.Vector2, event: MouseEvent) => void;
129129
ssr?: boolean;
130+
debug?: boolean;
130131
}>;
131132

132133
// @public (undocumented)

docs/app/guides/display/debug/page.tsx

+18-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Link from "next/link"
55
import CodeAndExample from "components/CodeAndExample"
66

77
import PizzaSliceExample from "guide-examples/custom/pizza-slice"
8+
import DebugExample from "guide-examples/debug/DebugExample"
89
import Example from "guide-examples/debug/PaneVisualizerExample"
910
import type { Metadata } from "next"
1011

@@ -16,8 +17,23 @@ export default function DebugPage() {
1617
return (
1718
<>
1819
<p>
19-
Mafs provides a few utilities for debugging or experimentation, underneath the{" "}
20-
<code>Debug</code> namespace.
20+
Mafs provides several utilities for debugging your visualizations. Perhaps the most useful
21+
utility the <code>debug</code> prop on <code>Mafs</code>. Adding this prop will force a
22+
larger SVG viewBox and add a red border around the <em>actual</em> viewBox.
23+
</p>
24+
25+
<CodeAndExample example={DebugExample} />
26+
27+
<p>
28+
In the above example, you can gain an insight into how Mafs lazy-loads the coordinate grid
29+
and the function being visualized. In the bottom left corner, there is also some debug
30+
information pinned to the viewport. More on that below.
31+
</p>
32+
33+
<h2>Other utilities</h2>
34+
35+
<p>
36+
Mafs also provides some debug components under the <code>Debug</code> namespace.
2137
</p>
2238

2339
<Code source={`import { Debug } from "mafs"`} language="tsx" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import { Mafs, Coordinates, Plot } from "mafs"
5+
6+
export default function Example() {
7+
const [debug, setDebug] = React.useState(true)
8+
9+
return (
10+
<div>
11+
{/* Set the `debug` prop on Mafs to get a bird's eye view. */}
12+
<Mafs debug={debug} height={400}>
13+
<Coordinates.Cartesian />
14+
<Plot.OfX y={(x) => Math.sin(x * Math.PI)} />
15+
</Mafs>
16+
<label className="p-4 bg-black flex gap-2 pointer">
17+
<input
18+
type="checkbox"
19+
checked={debug}
20+
onChange={(e) => setDebug(e.target.checked)}
21+
/>
22+
Debug
23+
</label>
24+
</div>
25+
)
26+
}

e2e/generated-vrt.spec.tsx

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import VectorFieldExample from "../docs/components/guide-examples/VectorFieldExa
2020
import PizzaMarch from "../docs/components/guide-examples/custom/pizza-march"
2121
import PizzaSlice from "../docs/components/guide-examples/custom/pizza-slice"
2222
import PointCloud from "../docs/components/guide-examples/custom/point-cloud"
23+
import DebugExample from "../docs/components/guide-examples/debug/DebugExample"
2324
import PaneVisualizerExample from "../docs/components/guide-examples/debug/PaneVisualizerExample"
2425
import DynamicMovablePoints from "../docs/components/guide-examples/display/DynamicMovablePoints"
2526
import PointsAlongFunction from "../docs/components/guide-examples/display/PointsAlongFunction"
@@ -188,6 +189,15 @@ test("guide-examples/custom/PointCloud", async ({ mount, page }) =>
188189
</TestContextProvider>,
189190
))
190191

192+
test("guide-examples/debug/DebugExample", async ({ mount, page }) =>
193+
await visualTest(
194+
mount,
195+
page,
196+
<TestContextProvider value={{ overrideHeight: 500 }}>
197+
<DebugExample />
198+
</TestContextProvider>,
199+
))
200+
191201
test("guide-examples/debug/PaneVisualizerExample", async ({ mount, page }) =>
192202
await visualTest(
193203
mount,
Loading
Loading
Loading

src/view/Mafs.tsx

+28-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import invariant from "tiny-invariant"
1212
import { useCamera } from "../gestures/useCamera"
1313
import { useWheelEnabler } from "../gestures/useWheelEnabler"
1414
import { TestContext } from "../context/TestContext"
15+
import { Debug } from "../debug"
1516

1617
export type MafsProps = React.PropsWithChildren<{
1718
width?: number | "auto"
@@ -49,6 +50,9 @@ export type MafsProps = React.PropsWithChildren<{
4950
* this prop is now ignored.
5051
*/
5152
ssr?: boolean
53+
54+
/** Take a peek outside the viewbox to make sure things are rendering properly. */
55+
debug?: boolean
5256
}>
5357

5458
export function Mafs({
@@ -60,6 +64,7 @@ export function Mafs({
6064
preserveAspectRatio = "contain",
6165
children,
6266
ssr = false,
67+
debug = false,
6368
onClick = undefined,
6469
}: MafsProps) {
6570
const testContext = React.useContext(TestContext)
@@ -92,6 +97,7 @@ export function Mafs({
9297
preserveAspectRatio={preserveAspectRatio}
9398
ssr={ssr}
9499
onClick={onClick}
100+
debug={debug}
95101
>
96102
{children}
97103
</MafsCanvas>
@@ -105,7 +111,9 @@ type MafsCanvasProps = {
105111
height: number
106112
desiredCssWidth: string
107113
rootRef: React.RefObject<HTMLDivElement>
108-
} & Required<Pick<MafsProps, "pan" | "zoom" | "viewBox" | "preserveAspectRatio" | "ssr">> &
114+
} & Required<
115+
Pick<MafsProps, "pan" | "zoom" | "viewBox" | "preserveAspectRatio" | "ssr" | "debug">
116+
> &
109117
Pick<MafsProps, "children" | "onClick">
110118

111119
function MafsCanvas({
@@ -119,6 +127,7 @@ function MafsCanvas({
119127
preserveAspectRatio,
120128
children,
121129
onClick,
130+
debug,
122131
}: MafsCanvasProps) {
123132
let minZoom = 1
124133
let maxZoom = 1
@@ -306,7 +315,12 @@ function MafsCanvas({
306315
<svg
307316
width={width}
308317
height={height}
309-
viewBox={`${viewBoxX} ${viewBoxY} ${width} ${height}`}
318+
viewBox={[
319+
viewBoxX - (debug ? 150 : 0),
320+
viewBoxY - (debug ? 150 : 0),
321+
width + (debug ? 300 : 0),
322+
height + (debug ? 300 : 0),
323+
].join(" ")}
310324
preserveAspectRatio="xMidYMin"
311325
style={{
312326
width: desiredCssWidth,
@@ -318,6 +332,18 @@ function MafsCanvas({
318332
}}
319333
>
320334
{children}
335+
{debug && (
336+
<rect
337+
x={viewBoxX}
338+
y={viewBoxY}
339+
width={width}
340+
height={height}
341+
fill="none"
342+
stroke="red"
343+
style={{ outline: "9999px solid #f002" }}
344+
/>
345+
)}
346+
{debug && <Debug.ViewportInfo />}
321347
</svg>
322348
</PaneManager>
323349
</TransformContext.Provider>

tests/frameworks/nextjs/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"react-dom": "^18.3.1"
1616
},
1717
"devDependencies": {
18-
"@types/node": "^20.16.11",
18+
"@types/node": "^20.16.13",
1919
"@types/react": "^18.3.11",
2020
"@types/react-dom": "^18.3.1",
2121
"typescript": "^5.6.3"

0 commit comments

Comments
 (0)