From ce0964d822c5b1688e9fcfd34f33a2daf30012e3 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Tue, 19 Aug 2025 10:48:59 +0100 Subject: [PATCH 01/17] Change component name from ReactP5Wrapper to P5Canvas --- config/vite/library.ts | 4 +- demo/app.jsx | 4 +- .../{ReactP5Wrapper.tsx => P5Canvas.tsx} | 2 +- src/components/ReactP5WrapperGuard.tsx | 2 +- src/main.tsx | 2 +- src/utils/logErrorBoundaryError.ts | 2 +- ...ctP5Wrapper.test.tsx => P5Canvas.test.tsx} | 74 +++++++++---------- tests/exports.test.tsx | 8 +- tests/utils/logErrorBoundaryError.test.ts | 18 ++--- 9 files changed, 54 insertions(+), 62 deletions(-) rename src/components/{ReactP5Wrapper.tsx => P5Canvas.tsx} (69%) rename tests/components/{ReactP5Wrapper.test.tsx => P5Canvas.test.tsx} (82%) diff --git a/config/vite/library.ts b/config/vite/library.ts index 144b53ae..09f1c8d3 100644 --- a/config/vite/library.ts +++ b/config/vite/library.ts @@ -26,8 +26,8 @@ export function library(root: string): UserConfig { emptyOutDir: true, lib: { entry: resolve(root, "src", "main.tsx"), - name: "ReactP5Wrapper", - fileName: "ReactP5Wrapper", + name: "P5Canvas", + fileName: "P5Canvas", formats: ["es", "cjs"] }, rollupOptions: { diff --git a/demo/app.jsx b/demo/app.jsx index 4124ef98..34db3b0c 100644 --- a/demo/app.jsx +++ b/demo/app.jsx @@ -1,4 +1,4 @@ -import { ReactP5Wrapper } from "@/main.tsx"; +import { P5Canvas } from "@/main.tsx"; import React, { useCallback, useMemo, useState } from "react"; import { createRoot } from "react-dom/client"; @@ -61,7 +61,7 @@ function App() { return ( <> - + {state.sketch === record && (
diff --git a/src/components/ReactP5Wrapper.tsx b/src/components/P5Canvas.tsx similarity index 69% rename from src/components/ReactP5Wrapper.tsx rename to src/components/P5Canvas.tsx index 508c5b5b..67a40e87 100644 --- a/src/components/ReactP5Wrapper.tsx +++ b/src/components/P5Canvas.tsx @@ -5,4 +5,4 @@ const ReactP5WrapperGuard = React.lazy( () => import("@components/ReactP5WrapperGuard") ); -export const ReactP5Wrapper = React.memo(ReactP5WrapperGuard, propsAreEqual); +export const P5Canvas = React.memo(ReactP5WrapperGuard, propsAreEqual); diff --git a/src/components/ReactP5WrapperGuard.tsx b/src/components/ReactP5WrapperGuard.tsx index 0b11d71a..bfdb75be 100644 --- a/src/components/ReactP5WrapperGuard.tsx +++ b/src/components/ReactP5WrapperGuard.tsx @@ -20,7 +20,7 @@ const ReactP5WrapperGuard = ( props: P5WrapperProps ) => { if (props.sketch === undefined) { - console.error("[ReactP5Wrapper] The `sketch` prop is required."); + console.error("[P5Canvas] The `sketch` prop is required."); return props.fallback?.() ?? null; } diff --git a/src/main.tsx b/src/main.tsx index 5531cc7e..673315c7 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,4 +1,4 @@ -export { ReactP5Wrapper } from "@components/ReactP5Wrapper"; +export { P5Canvas } from "@components/P5Canvas"; export { P5WrapperClassName } from "@constants/P5WrapperClassName"; export { type P5CanvasInstance } from "@contracts/P5CanvasInstance"; export { type P5WrapperProps } from "@contracts/P5WrapperProps"; diff --git a/src/utils/logErrorBoundaryError.ts b/src/utils/logErrorBoundaryError.ts index 300b10ac..8761309e 100644 --- a/src/utils/logErrorBoundaryError.ts +++ b/src/utils/logErrorBoundaryError.ts @@ -1,5 +1,5 @@ const errorIntroduction = - "[ReactP5Wrapper] The error boundary was triggered. The error message was:"; + "[P5Canvas] The error boundary was triggered. The error message was:"; function tidyErrorLogText(text: string): string { return text diff --git a/tests/components/ReactP5Wrapper.test.tsx b/tests/components/P5Canvas.test.tsx similarity index 82% rename from tests/components/ReactP5Wrapper.test.tsx rename to tests/components/P5Canvas.test.tsx index 0cdeacab..770b06a3 100644 --- a/tests/components/ReactP5Wrapper.test.tsx +++ b/tests/components/P5Canvas.test.tsx @@ -1,4 +1,4 @@ -import { ReactP5Wrapper } from "@components/ReactP5Wrapper"; +import { P5Canvas } from "@components/P5Canvas"; import { P5WrapperClassName } from "@constants/P5WrapperClassName"; import { type P5CanvasInstance } from "@contracts/P5CanvasInstance"; import { type Sketch } from "@contracts/Sketch"; @@ -36,12 +36,12 @@ async function waitForLoading(findByTestId: RenderResult["findByTestId"]) { }); } -describe("ReactP5Wrapper", () => { +describe("P5Canvas", () => { describe("Rendering", () => { describe("Client", () => { it("Renders the canvas into the wrapping element", async () => { const sketch = createSketch(); - const { findByTestId } = render(); + const { findByTestId } = render(); const canvas = await waitForCanvas(findByTestId); expect(canvas).toBeInstanceOf(HTMLCanvasElement); @@ -49,11 +49,9 @@ describe("ReactP5Wrapper", () => { it("Recreates the P5 instance when the sketch is changed", async () => { const sketch = createSketch(); - const { rerender, findByTestId } = render( - - ); + const { rerender, findByTestId } = render(); - rerender(); + rerender(); const canvas = await waitForCanvas(findByTestId); expect(canvas).toBeInstanceOf(HTMLCanvasElement); @@ -61,7 +59,7 @@ describe("ReactP5Wrapper", () => { it("Adds a utility css class to the wrapping element", async () => { const sketch = createSketch(); - const { findByTestId } = render(); + const { findByTestId } = render(); const wrapper = await findByTestId("wrapper"); @@ -72,7 +70,7 @@ describe("ReactP5Wrapper", () => { it("Unmounts the canvas when the element is removed from the DOM", async () => { const sketch = createSketch(); const { container, unmount, findByTestId } = render( - + ); await waitForCanvas(findByTestId); @@ -85,7 +83,7 @@ describe("ReactP5Wrapper", () => { }); it("Should not render anything when the `sketch` and `fallback` props are not provided", () => { - const { container } = render(); + const { container } = render(); expect(container.innerHTML).toBe(""); }); @@ -96,12 +94,12 @@ describe("ReactP5Wrapper", () => { .spyOn(console, "error") .mockImplementation(errorLogger); - render(); + render(); await waitFor(() => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( - "[ReactP5Wrapper] The `sketch` prop is required." + "[P5Canvas] The `sketch` prop is required." ); errorLoggerSpy.mockReset(); @@ -111,9 +109,7 @@ describe("ReactP5Wrapper", () => { it("Should use the fallback UI if the sketch is undefined on initial render", async () => { const fallbackView = vi.fn(() =>
); - const { findByTestId } = render( - - ); + const { findByTestId } = render(); const fallback = await findByTestId("fallback"); @@ -125,12 +121,12 @@ describe("ReactP5Wrapper", () => { const sketch = createSketch(); const fallbackView = vi.fn(() =>
); const { rerender, findByTestId } = render( -

Oh no

} sketch={sketch} /> +

Oh no

} sketch={sketch} /> ); await waitForCanvas(findByTestId); - rerender(); + rerender(); const fallback = await findByTestId("fallback"); @@ -140,7 +136,7 @@ describe("ReactP5Wrapper", () => { it.skip("Should show the default loading UI when the `loading` prop is not set and the sketch is not yet loaded", async () => { const sketch = createSketch(); - const { findByTestId } = render(); + const { findByTestId } = render(); const loading = await waitForLoading(findByTestId); expect(loading).toBeInstanceOf(HTMLParagraphElement); @@ -153,7 +149,7 @@ describe("ReactP5Wrapper", () => {

Loading test...

)); const { findByTestId } = render( - + ); const loading = await waitForLoading(findByTestId); @@ -169,9 +165,9 @@ describe("ReactP5Wrapper", () => { }; const { findByTestId } = render( - + - + ); const error = await findByTestId("error"); @@ -192,9 +188,9 @@ describe("ReactP5Wrapper", () => { }; const { findByTestId } = render( - + - +
); const error = await findByTestId("error"); @@ -216,9 +212,9 @@ describe("ReactP5Wrapper", () => { }; const { findByTestId } = render( - + - +
); await findByTestId("error"); @@ -226,7 +222,7 @@ describe("ReactP5Wrapper", () => { expect(errorLoggerSpy).toHaveBeenCalledTimes(2); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -241,9 +237,7 @@ describe("ReactP5Wrapper", () => { describe("Server", () => { it("Renders as expected when using `renderToString`", () => { const sketch = createSketch(); - const StringComponent = renderToString( - - ); + const StringComponent = renderToString(); expect(StringComponent).toBe( `
` @@ -253,7 +247,7 @@ describe("ReactP5Wrapper", () => { it("Renders as expected when using `renderToStaticMarkup`", () => { const sketch = createSketch(); const StaticComponent = renderToStaticMarkup( - + ); expect(StaticComponent).toBe( @@ -268,9 +262,7 @@ describe("ReactP5Wrapper", () => { const updateFunction = vi.fn(); const sketch = createSketch(updateFunction); - const { findByTestId } = render( - - ); + const { findByTestId } = render(); await waitForCanvas(findByTestId); @@ -283,12 +275,12 @@ describe("ReactP5Wrapper", () => { const updateFunction = vi.fn(); const sketch = createSketch(updateFunction); const { rerender, findByTestId } = render( - + ); await waitForCanvas(findByTestId); - rerender(); + rerender(); expect(sketch).toHaveBeenCalledOnce(); expect(updateFunction).toHaveBeenCalledTimes(2); @@ -299,12 +291,12 @@ describe("ReactP5Wrapper", () => { const updateFunction = vi.fn(); const sketch = createSketch(updateFunction); const { rerender, findByTestId } = render( - + ); await waitForCanvas(findByTestId); - rerender(); + rerender(); expect(sketch).toHaveBeenCalledOnce(); expect(updateFunction).toHaveBeenCalledTimes(2); @@ -315,12 +307,12 @@ describe("ReactP5Wrapper", () => { const updateFunction = vi.fn(); const sketch = createSketch(updateFunction); const { rerender, findByTestId } = render( - + ); await waitForCanvas(findByTestId); - rerender(); + rerender(); expect(sketch).toHaveBeenCalledOnce(); expect(updateFunction).toHaveBeenCalledTimes(2); @@ -331,12 +323,12 @@ describe("ReactP5Wrapper", () => { const updateFunction = vi.fn(); const sketch = createSketch(updateFunction); const { rerender, findByTestId } = render( - + ); await waitForCanvas(findByTestId); - rerender(); + rerender(); expect(sketch).toHaveBeenCalledOnce(); expect(updateFunction).toHaveBeenCalledTimes(2); diff --git a/tests/exports.test.tsx b/tests/exports.test.tsx index 0c3fb976..ffff95f2 100644 --- a/tests/exports.test.tsx +++ b/tests/exports.test.tsx @@ -1,4 +1,4 @@ -import { P5WrapperClassName, ReactP5Wrapper } from "@/main"; +import { P5Canvas, P5WrapperClassName } from "@/main"; import { createElement, isValidElement } from "react"; import { assert, describe, expect, it, vi } from "vitest"; @@ -15,13 +15,13 @@ describe("Exports", () => { }); it("Exports the wrapper component", () => { - expect(ReactP5Wrapper).not.toBeUndefined(); + expect(P5Canvas).not.toBeUndefined(); }); }); - describe("ReactP5Wrapper", () => { + describe("P5Canvas", () => { it("Exports the wrapper component as a react element", () => { - const component = createElement(ReactP5Wrapper, { + const component = createElement(P5Canvas, { sketch: vi.fn() }); diff --git a/tests/utils/logErrorBoundaryError.test.ts b/tests/utils/logErrorBoundaryError.test.ts index 1894468d..4288e93f 100644 --- a/tests/utils/logErrorBoundaryError.test.ts +++ b/tests/utils/logErrorBoundaryError.test.ts @@ -31,7 +31,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -45,7 +45,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -59,7 +59,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -73,7 +73,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -87,7 +87,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -101,7 +101,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -115,7 +115,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -129,7 +129,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( @@ -143,7 +143,7 @@ describe("logErrorBoundaryError", () => { expect(errorLoggerSpy).toHaveBeenCalledOnce(); expect(errorLoggerSpy).toHaveBeenCalledWith( expect.stringContaining( - "[ReactP5Wrapper] The error boundary was triggered. The error message was:" + "[P5Canvas] The error boundary was triggered. The error message was:" ) ); expect(errorLoggerSpy).toHaveBeenCalledWith( From df9295c75c3f09d5299c157af7826faa4bb4f914 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:41:25 +0100 Subject: [PATCH 02/17] Rename ReactP5WrapperGuard to P5CanvasGuard --- src/components/P5Canvas.tsx | 6 ++---- .../{ReactP5WrapperGuard.tsx => P5CanvasGuard.tsx} | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) rename src/components/{ReactP5WrapperGuard.tsx => P5CanvasGuard.tsx} (94%) diff --git a/src/components/P5Canvas.tsx b/src/components/P5Canvas.tsx index 67a40e87..7251a7e1 100644 --- a/src/components/P5Canvas.tsx +++ b/src/components/P5Canvas.tsx @@ -1,8 +1,6 @@ import * as React from "react"; import { propsAreEqual } from "@utils/propsAreEqual"; -const ReactP5WrapperGuard = React.lazy( - () => import("@components/ReactP5WrapperGuard") -); +const P5CanvasGuard = React.lazy(() => import("@components/P5CanvasGuard")); -export const P5Canvas = React.memo(ReactP5WrapperGuard, propsAreEqual); +export const P5Canvas = React.memo(P5CanvasGuard, propsAreEqual); diff --git a/src/components/ReactP5WrapperGuard.tsx b/src/components/P5CanvasGuard.tsx similarity index 94% rename from src/components/ReactP5WrapperGuard.tsx rename to src/components/P5CanvasGuard.tsx index bfdb75be..817699ef 100644 --- a/src/components/ReactP5WrapperGuard.tsx +++ b/src/components/P5CanvasGuard.tsx @@ -16,7 +16,7 @@ const ErrorBoundary = React.lazy(() => })) ); -const ReactP5WrapperGuard = ( +const P5CanvasGuard = ( props: P5WrapperProps ) => { if (props.sketch === undefined) { @@ -52,4 +52,4 @@ const ReactP5WrapperGuard = ( ); }; -export default ReactP5WrapperGuard; +export default P5CanvasGuard; From 376fd3722cd730166abdf43a6bc4379452d84e07 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:47:17 +0100 Subject: [PATCH 03/17] Rename ReactP5WrapperWithSketch to P5CanvasWithSketch --- src/components/P5CanvasGuard.tsx | 6 +++--- ...{ReactP5WrapperWithSketch.tsx => P5CanvasWithSketch.tsx} | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/components/{ReactP5WrapperWithSketch.tsx => P5CanvasWithSketch.tsx} (93%) diff --git a/src/components/P5CanvasGuard.tsx b/src/components/P5CanvasGuard.tsx index 817699ef..a29a1a86 100644 --- a/src/components/P5CanvasGuard.tsx +++ b/src/components/P5CanvasGuard.tsx @@ -6,8 +6,8 @@ import { logErrorBoundaryError } from "@utils/logErrorBoundaryError"; import { ReactNode } from "react"; import { FallbackProps } from "react-error-boundary"; -const ReactP5WrapperWithSketch = React.lazy( - () => import("@components/ReactP5WrapperWithSketch") +const P5CanvasWithSketch = React.lazy( + () => import("@components/P5CanvasWithSketch") ); const ErrorBoundary = React.lazy(() => @@ -43,7 +43,7 @@ const P5CanvasGuard = ( props.loading?.() ??

🚀 Loading...

} > - )} /> diff --git a/src/components/ReactP5WrapperWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx similarity index 93% rename from src/components/ReactP5WrapperWithSketch.tsx rename to src/components/P5CanvasWithSketch.tsx index 1f7d5be6..8f34a288 100644 --- a/src/components/ReactP5WrapperWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -8,7 +8,7 @@ import { removeCanvasInstance } from "@utils/removeCanvasInstance"; import { updateCanvasInstance } from "@utils/updateCanvasInstance"; import { withoutKeys } from "@utils/withoutKeys"; -const ReactP5WrapperWithSketch = ( +const P5CanvasWithSketch = ( props: P5WrapperPropsWithSketch ) => { const wrapperRef: WrapperRef = React.useRef(null); @@ -49,4 +49,4 @@ const ReactP5WrapperWithSketch = ( ); }; -export default ReactP5WrapperWithSketch; +export default P5CanvasWithSketch; From 7472e719f79eb0a4c515e7d8fc00413a77f2fdad Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Tue, 19 Aug 2025 12:03:15 +0100 Subject: [PATCH 04/17] Rename P5WrapperProps to P5CanvasProps --- src/components/P5CanvasGuard.tsx | 4 ++-- src/contracts/{P5WrapperProps.ts => P5CanvasProps.ts} | 2 +- src/contracts/P5WrapperPropsWithSketch.ts | 4 ++-- src/main.tsx | 2 +- src/utils/propsAreEqual.ts | 6 +++--- tests/utils/propsAreEqual.test.ts | 10 +++++----- 6 files changed, 14 insertions(+), 14 deletions(-) rename src/contracts/{P5WrapperProps.ts => P5CanvasProps.ts} (75%) diff --git a/src/components/P5CanvasGuard.tsx b/src/components/P5CanvasGuard.tsx index a29a1a86..c271e1bf 100644 --- a/src/components/P5CanvasGuard.tsx +++ b/src/components/P5CanvasGuard.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { type P5WrapperProps } from "@contracts/P5WrapperProps"; +import { type P5CanvasProps } from "@contracts/P5CanvasProps"; import { type P5WrapperPropsWithSketch } from "@contracts/P5WrapperPropsWithSketch"; import { type SketchProps } from "@contracts/SketchProps"; import { logErrorBoundaryError } from "@utils/logErrorBoundaryError"; @@ -17,7 +17,7 @@ const ErrorBoundary = React.lazy(() => ); const P5CanvasGuard = ( - props: P5WrapperProps + props: P5CanvasProps ) => { if (props.sketch === undefined) { console.error("[P5Canvas] The `sketch` prop is required."); diff --git a/src/contracts/P5WrapperProps.ts b/src/contracts/P5CanvasProps.ts similarity index 75% rename from src/contracts/P5WrapperProps.ts rename to src/contracts/P5CanvasProps.ts index ecb7a6e9..3a0722db 100644 --- a/src/contracts/P5WrapperProps.ts +++ b/src/contracts/P5CanvasProps.ts @@ -2,5 +2,5 @@ import { type InputProps } from "@contracts/InputProps"; import { type SketchProps } from "@contracts/SketchProps"; import { type WithChildren } from "@contracts/WithChildren"; -export type P5WrapperProps = +export type P5CanvasProps = WithChildren>; diff --git a/src/contracts/P5WrapperPropsWithSketch.ts b/src/contracts/P5WrapperPropsWithSketch.ts index 2836d717..1cd6dc03 100644 --- a/src/contracts/P5WrapperPropsWithSketch.ts +++ b/src/contracts/P5WrapperPropsWithSketch.ts @@ -1,6 +1,6 @@ -import { type P5WrapperProps } from "@contracts/P5WrapperProps"; +import { type P5CanvasProps } from "@contracts/P5CanvasProps"; import { type Sketch } from "@contracts/Sketch"; import { type SketchProps } from "@contracts/SketchProps"; export type P5WrapperPropsWithSketch = - P5WrapperProps & { sketch: Sketch }; + P5CanvasProps & { sketch: Sketch }; diff --git a/src/main.tsx b/src/main.tsx index 673315c7..e2e8c9ec 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,6 @@ export { P5Canvas } from "@components/P5Canvas"; export { P5WrapperClassName } from "@constants/P5WrapperClassName"; export { type P5CanvasInstance } from "@contracts/P5CanvasInstance"; -export { type P5WrapperProps } from "@contracts/P5WrapperProps"; +export { type P5CanvasProps } from "@contracts/P5CanvasProps"; export { type Sketch } from "@contracts/Sketch"; export { type SketchProps } from "@contracts/SketchProps"; diff --git a/src/utils/propsAreEqual.ts b/src/utils/propsAreEqual.ts index cfd84aeb..f436dcc0 100644 --- a/src/utils/propsAreEqual.ts +++ b/src/utils/propsAreEqual.ts @@ -1,10 +1,10 @@ -import { type P5WrapperProps } from "@contracts/P5WrapperProps"; +import { type P5CanvasProps } from "@contracts/P5CanvasProps"; import { type SketchProps } from "@contracts/SketchProps"; import diff from "microdiff"; export function propsAreEqual( - previous: P5WrapperProps, - next: P5WrapperProps + previous: P5CanvasProps, + next: P5CanvasProps ) { const differences = diff(previous, next); diff --git a/tests/utils/propsAreEqual.test.ts b/tests/utils/propsAreEqual.test.ts index b5520ef0..84bcf305 100644 --- a/tests/utils/propsAreEqual.test.ts +++ b/tests/utils/propsAreEqual.test.ts @@ -1,24 +1,24 @@ -import { type P5WrapperProps } from "@contracts/P5WrapperProps"; +import { type P5CanvasProps } from "@contracts/P5CanvasProps"; import { propsAreEqual } from "@utils/propsAreEqual"; import { describe, expect, it, vi } from "vitest"; describe("propsAreEqual", () => { it("Returns true when the current and next props are the same", () => { const sketch = vi.fn(); - const current: P5WrapperProps = { sketch }; - const next: P5WrapperProps = { sketch }; + const current: P5CanvasProps = { sketch }; + const next: P5CanvasProps = { sketch }; const equal = propsAreEqual(current, next); expect(equal).toBe(true); }); it("Returns false when the current and next props are not the same", () => { - const current: P5WrapperProps = { + const current: P5CanvasProps = { sketch: () => { return; } }; - const next: P5WrapperProps = { + const next: P5CanvasProps = { sketch: () => { return; } From e99ca714b6eb81e816f2072e4c3e3a83604e3a96 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Tue, 19 Aug 2025 12:11:21 +0100 Subject: [PATCH 05/17] Rename P5WrapperPropsWithSketch to P5CanvasPropsWithSketch --- src/components/P5CanvasGuard.tsx | 4 ++-- src/components/P5CanvasWithSketch.tsx | 4 ++-- ...P5WrapperPropsWithSketch.ts => P5CanvasPropsWithSketch.ts} | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/contracts/{P5WrapperPropsWithSketch.ts => P5CanvasPropsWithSketch.ts} (77%) diff --git a/src/components/P5CanvasGuard.tsx b/src/components/P5CanvasGuard.tsx index c271e1bf..a6f50562 100644 --- a/src/components/P5CanvasGuard.tsx +++ b/src/components/P5CanvasGuard.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { type P5CanvasProps } from "@contracts/P5CanvasProps"; -import { type P5WrapperPropsWithSketch } from "@contracts/P5WrapperPropsWithSketch"; +import { type P5CanvasPropsWithSketch } from "@contracts/P5CanvasPropsWithSketch"; import { type SketchProps } from "@contracts/SketchProps"; import { logErrorBoundaryError } from "@utils/logErrorBoundaryError"; import { ReactNode } from "react"; @@ -45,7 +45,7 @@ const P5CanvasGuard = ( > )} + {...(props as unknown as P5CanvasPropsWithSketch)} /> diff --git a/src/components/P5CanvasWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx index 8f34a288..fabd8ac2 100644 --- a/src/components/P5CanvasWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { P5WrapperClassName } from "@constants/P5WrapperClassName"; import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; -import { type P5WrapperPropsWithSketch } from "@contracts/P5WrapperPropsWithSketch"; +import { type P5CanvasPropsWithSketch } from "@contracts/P5CanvasPropsWithSketch"; import { type SketchProps } from "@contracts/SketchProps"; import { type WrapperRef } from "@contracts/WrapperRef"; import { removeCanvasInstance } from "@utils/removeCanvasInstance"; @@ -9,7 +9,7 @@ import { updateCanvasInstance } from "@utils/updateCanvasInstance"; import { withoutKeys } from "@utils/withoutKeys"; const P5CanvasWithSketch = ( - props: P5WrapperPropsWithSketch + props: P5CanvasPropsWithSketch ) => { const wrapperRef: WrapperRef = React.useRef(null); const canvasInstanceRef: CanvasInstanceRef = React.useRef(null); diff --git a/src/contracts/P5WrapperPropsWithSketch.ts b/src/contracts/P5CanvasPropsWithSketch.ts similarity index 77% rename from src/contracts/P5WrapperPropsWithSketch.ts rename to src/contracts/P5CanvasPropsWithSketch.ts index 1cd6dc03..8a75061a 100644 --- a/src/contracts/P5WrapperPropsWithSketch.ts +++ b/src/contracts/P5CanvasPropsWithSketch.ts @@ -2,5 +2,5 @@ import { type P5CanvasProps } from "@contracts/P5CanvasProps"; import { type Sketch } from "@contracts/Sketch"; import { type SketchProps } from "@contracts/SketchProps"; -export type P5WrapperPropsWithSketch = +export type P5CanvasPropsWithSketch = P5CanvasProps & { sketch: Sketch }; From 25e90a518d8a43d43c1509a97ec727409822ffb3 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Tue, 19 Aug 2025 14:44:07 +0100 Subject: [PATCH 06/17] Rename P5WrapperClassName to CanvasContainerClassName --- src/components/P5CanvasWithSketch.tsx | 8 ++++++-- src/constants/CanvasContainerClassName.ts | 1 + src/constants/P5WrapperClassName.ts | 1 - src/main.tsx | 2 +- tests/components/P5Canvas.test.tsx | 8 ++++---- tests/constants/CanvasContainerClassName.test.ts | 9 +++++++++ tests/constants/P5WrapperClassName.test.ts | 9 --------- tests/exports.test.tsx | 12 ++++++------ 8 files changed, 27 insertions(+), 23 deletions(-) create mode 100644 src/constants/CanvasContainerClassName.ts delete mode 100644 src/constants/P5WrapperClassName.ts create mode 100644 tests/constants/CanvasContainerClassName.test.ts delete mode 100644 tests/constants/P5WrapperClassName.test.ts diff --git a/src/components/P5CanvasWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx index fabd8ac2..7d8780d1 100644 --- a/src/components/P5CanvasWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { P5WrapperClassName } from "@constants/P5WrapperClassName"; +import { CanvasContainerClassName } from "@constants/CanvasContainerClassName"; import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; import { type P5CanvasPropsWithSketch } from "@contracts/P5CanvasPropsWithSketch"; import { type SketchProps } from "@contracts/SketchProps"; @@ -43,7 +43,11 @@ const P5CanvasWithSketch = ( React.useEffect(() => () => removeCanvasInstance(canvasInstanceRef), []); return ( -
+
{props.children}
); diff --git a/src/constants/CanvasContainerClassName.ts b/src/constants/CanvasContainerClassName.ts new file mode 100644 index 00000000..ce9a05e9 --- /dev/null +++ b/src/constants/CanvasContainerClassName.ts @@ -0,0 +1 @@ +export const CanvasContainerClassName = "canvas-container"; diff --git a/src/constants/P5WrapperClassName.ts b/src/constants/P5WrapperClassName.ts deleted file mode 100644 index a00bbc49..00000000 --- a/src/constants/P5WrapperClassName.ts +++ /dev/null @@ -1 +0,0 @@ -export const P5WrapperClassName = "p5-wrapper-react"; diff --git a/src/main.tsx b/src/main.tsx index e2e8c9ec..eb272f07 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,5 +1,5 @@ export { P5Canvas } from "@components/P5Canvas"; -export { P5WrapperClassName } from "@constants/P5WrapperClassName"; +export { CanvasContainerClassName } from "@constants/CanvasContainerClassName"; export { type P5CanvasInstance } from "@contracts/P5CanvasInstance"; export { type P5CanvasProps } from "@contracts/P5CanvasProps"; export { type Sketch } from "@contracts/Sketch"; diff --git a/tests/components/P5Canvas.test.tsx b/tests/components/P5Canvas.test.tsx index 770b06a3..d679b7ed 100644 --- a/tests/components/P5Canvas.test.tsx +++ b/tests/components/P5Canvas.test.tsx @@ -1,5 +1,5 @@ import { P5Canvas } from "@components/P5Canvas"; -import { P5WrapperClassName } from "@constants/P5WrapperClassName"; +import { CanvasContainerClassName } from "@constants/CanvasContainerClassName"; import { type P5CanvasInstance } from "@contracts/P5CanvasInstance"; import { type Sketch } from "@contracts/Sketch"; import { render, RenderResult, waitFor } from "@testing-library/react"; @@ -64,7 +64,7 @@ describe("P5Canvas", () => { const wrapper = await findByTestId("wrapper"); expect(wrapper).toBeInstanceOf(HTMLDivElement); - expect(wrapper.className).toBe(P5WrapperClassName); + expect(wrapper.className).toBe(CanvasContainerClassName); }); it("Unmounts the canvas when the element is removed from the DOM", async () => { @@ -240,7 +240,7 @@ describe("P5Canvas", () => { const StringComponent = renderToString(); expect(StringComponent).toBe( - `
` + `
` ); }); @@ -251,7 +251,7 @@ describe("P5Canvas", () => { ); expect(StaticComponent).toBe( - `
` + `
` ); }); }); diff --git a/tests/constants/CanvasContainerClassName.test.ts b/tests/constants/CanvasContainerClassName.test.ts new file mode 100644 index 00000000..bbe5c22f --- /dev/null +++ b/tests/constants/CanvasContainerClassName.test.ts @@ -0,0 +1,9 @@ +import { CanvasContainerClassName } from "@constants/CanvasContainerClassName"; +import { describe, expect, it } from "vitest"; + +describe("CanvasContainerClassName", () => { + it("Is exported as a non-empty string", () => { + expect(CanvasContainerClassName).toBeTypeOf("string"); + expect(CanvasContainerClassName.length).toBeGreaterThan(0); + }); +}); diff --git a/tests/constants/P5WrapperClassName.test.ts b/tests/constants/P5WrapperClassName.test.ts deleted file mode 100644 index a7eb2809..00000000 --- a/tests/constants/P5WrapperClassName.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { P5WrapperClassName } from "@constants/P5WrapperClassName"; -import { describe, expect, it } from "vitest"; - -describe("P5WrapperClassName", () => { - it("Is exported as a non-empty string", () => { - expect(P5WrapperClassName).toBeTypeOf("string"); - expect(P5WrapperClassName.length).toBeGreaterThan(0); - }); -}); diff --git a/tests/exports.test.tsx b/tests/exports.test.tsx index ffff95f2..2ee02602 100644 --- a/tests/exports.test.tsx +++ b/tests/exports.test.tsx @@ -1,17 +1,17 @@ -import { P5Canvas, P5WrapperClassName } from "@/main"; +import { CanvasContainerClassName, P5Canvas } from "@/main"; import { createElement, isValidElement } from "react"; import { assert, describe, expect, it, vi } from "vitest"; describe("Exports", () => { - describe("P5WrapperClassName", () => { + describe("CanvasContainerClassName", () => { it("Exports the css class name used on the wrapper", () => { - expect(P5WrapperClassName).not.toBeUndefined(); - expect(P5WrapperClassName).toBe("p5-wrapper-react"); + expect(CanvasContainerClassName).not.toBeUndefined(); + expect(CanvasContainerClassName).toBe("canvas-container"); }); it("Exports the css class name used on the wrapper as a non-empty string", () => { - expect(typeof P5WrapperClassName).toBe("string"); - expect(P5WrapperClassName.length).toBeGreaterThan(0); + expect(typeof CanvasContainerClassName).toBe("string"); + expect(CanvasContainerClassName.length).toBeGreaterThan(0); }); it("Exports the wrapper component", () => { From 03ad9c1ebfd6ae6a6957db37f6d7360ee5133248 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Tue, 19 Aug 2025 14:48:58 +0100 Subject: [PATCH 07/17] Update data-testid --- src/components/P5CanvasWithSketch.tsx | 2 +- tests/components/P5Canvas.test.tsx | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/P5CanvasWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx index 7d8780d1..0708faeb 100644 --- a/src/components/P5CanvasWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -46,7 +46,7 @@ const P5CanvasWithSketch = (
{props.children}
diff --git a/tests/components/P5Canvas.test.tsx b/tests/components/P5Canvas.test.tsx index d679b7ed..ce63e4b6 100644 --- a/tests/components/P5Canvas.test.tsx +++ b/tests/components/P5Canvas.test.tsx @@ -17,8 +17,8 @@ function createSketch( async function waitForCanvas(findByTestId: RenderResult["findByTestId"]) { return await waitFor(async () => { - const wrapper = await findByTestId("wrapper"); - const canvas = wrapper.querySelector("canvas"); + const canvasContainer = await findByTestId("canvas-container"); + const canvas = canvasContainer.querySelector("canvas"); assert(canvas instanceof HTMLCanvasElement); @@ -61,10 +61,10 @@ describe("P5Canvas", () => { const sketch = createSketch(); const { findByTestId } = render(); - const wrapper = await findByTestId("wrapper"); + const canvasContainer = await findByTestId("canvas-container"); - expect(wrapper).toBeInstanceOf(HTMLDivElement); - expect(wrapper.className).toBe(CanvasContainerClassName); + expect(canvasContainer).toBeInstanceOf(HTMLDivElement); + expect(canvasContainer.className).toBe(CanvasContainerClassName); }); it("Unmounts the canvas when the element is removed from the DOM", async () => { @@ -240,7 +240,7 @@ describe("P5Canvas", () => { const StringComponent = renderToString(); expect(StringComponent).toBe( - `
` + `
` ); }); @@ -251,7 +251,7 @@ describe("P5Canvas", () => { ); expect(StaticComponent).toBe( - `
` + `
` ); }); }); From 93a24641937d580eafb57d680fba8e8461023830 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Tue, 19 Aug 2025 23:50:22 +0100 Subject: [PATCH 08/17] Rename WrapperRef to CanvasContainerRef --- src/components/P5CanvasWithSketch.tsx | 10 +++++----- .../{WrapperRef.ts => CanvasContainerRef.ts} | 2 +- src/utils/updateCanvasInstance.ts | 8 ++++---- tests/utils/updateCanvasInstance.test.ts | 14 +++++++------- 4 files changed, 17 insertions(+), 17 deletions(-) rename src/contracts/{WrapperRef.ts => CanvasContainerRef.ts} (60%) diff --git a/src/components/P5CanvasWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx index 0708faeb..8ba83c4a 100644 --- a/src/components/P5CanvasWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -1,9 +1,9 @@ import * as React from "react"; import { CanvasContainerClassName } from "@constants/CanvasContainerClassName"; +import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; import { type P5CanvasPropsWithSketch } from "@contracts/P5CanvasPropsWithSketch"; import { type SketchProps } from "@contracts/SketchProps"; -import { type WrapperRef } from "@contracts/WrapperRef"; import { removeCanvasInstance } from "@utils/removeCanvasInstance"; import { updateCanvasInstance } from "@utils/updateCanvasInstance"; import { withoutKeys } from "@utils/withoutKeys"; @@ -11,7 +11,7 @@ import { withoutKeys } from "@utils/withoutKeys"; const P5CanvasWithSketch = ( props: P5CanvasPropsWithSketch ) => { - const wrapperRef: WrapperRef = React.useRef(null); + const canvasContainerRef: CanvasContainerRef = React.useRef(null); const canvasInstanceRef: CanvasInstanceRef = React.useRef(null); const userProvidedProps: SketchProps = React.useMemo( () => @@ -28,7 +28,7 @@ const P5CanvasWithSketch = ( React.useEffect(() => { canvasInstanceRef.current = updateCanvasInstance( canvasInstanceRef, - wrapperRef, + canvasContainerRef, props.sketch ); }, [props.sketch]); @@ -38,13 +38,13 @@ const P5CanvasWithSketch = ( canvasInstanceRef.current?.updateWithProps?.( userProvidedProps as unknown as Props ); - }, [userProvidedProps, wrapperRef, canvasInstanceRef]); + }, [userProvidedProps, canvasContainerRef, canvasInstanceRef]); React.useEffect(() => () => removeCanvasInstance(canvasInstanceRef), []); return (
diff --git a/src/contracts/WrapperRef.ts b/src/contracts/CanvasContainerRef.ts similarity index 60% rename from src/contracts/WrapperRef.ts rename to src/contracts/CanvasContainerRef.ts index 6961c2a8..212696d6 100644 --- a/src/contracts/WrapperRef.ts +++ b/src/contracts/CanvasContainerRef.ts @@ -1,4 +1,4 @@ import { type Wrapper } from "@contracts/Wrapper"; import { type RefObject } from "react"; -export type WrapperRef = RefObject; +export type CanvasContainerRef = RefObject; diff --git a/src/utils/updateCanvasInstance.ts b/src/utils/updateCanvasInstance.ts index e8d92593..b3f7d9c0 100644 --- a/src/utils/updateCanvasInstance.ts +++ b/src/utils/updateCanvasInstance.ts @@ -1,20 +1,20 @@ +import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; import { type Sketch } from "@contracts/Sketch"; import { type SketchProps } from "@contracts/SketchProps"; -import { type WrapperRef } from "@contracts/WrapperRef"; import { createCanvasInstance } from "@utils/createCanvasInstance"; import { removeCanvasInstance } from "@utils/removeCanvasInstance"; export function updateCanvasInstance( canvasInstanceRef: CanvasInstanceRef, - wrapperRef: WrapperRef, + canvasContainerRef: CanvasContainerRef, sketch: Sketch ) { - if (wrapperRef.current === null) { + if (canvasContainerRef.current === null) { return null; } removeCanvasInstance(canvasInstanceRef); - return createCanvasInstance(sketch, wrapperRef.current); + return createCanvasInstance(sketch, canvasContainerRef.current); } diff --git a/tests/utils/updateCanvasInstance.test.ts b/tests/utils/updateCanvasInstance.test.ts index e9a5faf8..7ccdb748 100644 --- a/tests/utils/updateCanvasInstance.test.ts +++ b/tests/utils/updateCanvasInstance.test.ts @@ -1,7 +1,7 @@ import { SketchProps } from "@/main"; +import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; import p5 from "@contracts/p5"; -import { type WrapperRef } from "@contracts/WrapperRef"; import { createCanvasInstance } from "@utils/createCanvasInstance"; import { updateCanvasInstance } from "@utils/updateCanvasInstance"; import { createRef } from "react"; @@ -11,16 +11,16 @@ describe("updateCanvasInstance", () => { it("Should update a canvas instance to a new version", () => { const sketch = vi.fn(); const wrapper = document.createElement("div"); - const wrapperRef: WrapperRef = createRef(); + const canvasContainerRef: CanvasContainerRef = createRef(); const canvasInstanceRef: CanvasInstanceRef = createRef(); const instance = createCanvasInstance(sketch, wrapper); - wrapperRef.current = wrapper; + canvasContainerRef.current = wrapper; canvasInstanceRef.current = instance; const updatedCanvasInstanceRef = updateCanvasInstance( canvasInstanceRef, - wrapperRef, + canvasContainerRef, sketch ); @@ -29,10 +29,10 @@ describe("updateCanvasInstance", () => { expect(instance).not.toEqual(updatedCanvasInstanceRef); }); - it("Should return undefined if the wrapperRef value is null", () => { + it("Should return undefined if the canvasContainerRef value is null", () => { const sketch = vi.fn(); const wrapper = document.createElement("div"); - const wrapperRef: WrapperRef = createRef(); + const canvasContainerRef: CanvasContainerRef = createRef(); const canvasInstanceRef: CanvasInstanceRef = createRef(); const instance = createCanvasInstance(sketch, wrapper); @@ -40,7 +40,7 @@ describe("updateCanvasInstance", () => { const updatedCanvasInstanceRef = updateCanvasInstance( canvasInstanceRef, - wrapperRef, + canvasContainerRef, sketch ); From 2a5a06cf09c325c358227f2fe36cbc0853a8167c Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Wed, 20 Aug 2025 00:36:35 +0100 Subject: [PATCH 09/17] Rename CanvasInstanceRef to P5CanvasInstanceRef --- src/components/P5CanvasWithSketch.tsx | 14 +++++++------- ...asInstanceRef.ts => P5CanvasInstanceRef.ts} | 3 ++- src/utils/removeCanvasInstance.ts | 8 ++++---- src/utils/updateCanvasInstance.ts | 6 +++--- tests/utils/removeCanvasInstance.test.ts | 18 +++++++++--------- tests/utils/updateCanvasInstance.test.ts | 14 +++++++------- 6 files changed, 32 insertions(+), 31 deletions(-) rename src/contracts/{CanvasInstanceRef.ts => P5CanvasInstanceRef.ts} (62%) diff --git a/src/components/P5CanvasWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx index 8ba83c4a..12257400 100644 --- a/src/components/P5CanvasWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { CanvasContainerClassName } from "@constants/CanvasContainerClassName"; import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; -import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; +import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { type P5CanvasPropsWithSketch } from "@contracts/P5CanvasPropsWithSketch"; import { type SketchProps } from "@contracts/SketchProps"; import { removeCanvasInstance } from "@utils/removeCanvasInstance"; @@ -12,7 +12,7 @@ const P5CanvasWithSketch = ( props: P5CanvasPropsWithSketch ) => { const canvasContainerRef: CanvasContainerRef = React.useRef(null); - const canvasInstanceRef: CanvasInstanceRef = React.useRef(null); + const p5CanvasInstanceRef: P5CanvasInstanceRef = React.useRef(null); const userProvidedProps: SketchProps = React.useMemo( () => withoutKeys(props, [ @@ -26,8 +26,8 @@ const P5CanvasWithSketch = ( ); React.useEffect(() => { - canvasInstanceRef.current = updateCanvasInstance( - canvasInstanceRef, + p5CanvasInstanceRef.current = updateCanvasInstance( + p5CanvasInstanceRef, canvasContainerRef, props.sketch ); @@ -35,12 +35,12 @@ const P5CanvasWithSketch = ( React.useEffect(() => { /** @see https://github.com/P5-wrapper/react/discussions/360 */ - canvasInstanceRef.current?.updateWithProps?.( + p5CanvasInstanceRef.current?.updateWithProps?.( userProvidedProps as unknown as Props ); - }, [userProvidedProps, canvasContainerRef, canvasInstanceRef]); + }, [userProvidedProps, canvasContainerRef, p5CanvasInstanceRef]); - React.useEffect(() => () => removeCanvasInstance(canvasInstanceRef), []); + React.useEffect(() => () => removeCanvasInstance(p5CanvasInstanceRef), []); return (
= +/** Ref to the active p5.js sketch instance controlling the canvas */ +export type P5CanvasInstanceRef = RefObject | null>; diff --git a/src/utils/removeCanvasInstance.ts b/src/utils/removeCanvasInstance.ts index 2dba2b5b..63595173 100644 --- a/src/utils/removeCanvasInstance.ts +++ b/src/utils/removeCanvasInstance.ts @@ -1,9 +1,9 @@ -import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; +import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { type SketchProps } from "@contracts/SketchProps"; export function removeCanvasInstance( - canvasInstanceRef: CanvasInstanceRef + p5CanvasInstanceRef: P5CanvasInstanceRef ) { - canvasInstanceRef.current?.remove(); - canvasInstanceRef.current = null; + p5CanvasInstanceRef.current?.remove(); + p5CanvasInstanceRef.current = null; } diff --git a/src/utils/updateCanvasInstance.ts b/src/utils/updateCanvasInstance.ts index b3f7d9c0..4f53ae86 100644 --- a/src/utils/updateCanvasInstance.ts +++ b/src/utils/updateCanvasInstance.ts @@ -1,12 +1,12 @@ import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; -import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; +import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { type Sketch } from "@contracts/Sketch"; import { type SketchProps } from "@contracts/SketchProps"; import { createCanvasInstance } from "@utils/createCanvasInstance"; import { removeCanvasInstance } from "@utils/removeCanvasInstance"; export function updateCanvasInstance( - canvasInstanceRef: CanvasInstanceRef, + p5CanvasInstanceRef: P5CanvasInstanceRef, canvasContainerRef: CanvasContainerRef, sketch: Sketch ) { @@ -14,7 +14,7 @@ export function updateCanvasInstance( return null; } - removeCanvasInstance(canvasInstanceRef); + removeCanvasInstance(p5CanvasInstanceRef); return createCanvasInstance(sketch, canvasContainerRef.current); } diff --git a/tests/utils/removeCanvasInstance.test.ts b/tests/utils/removeCanvasInstance.test.ts index cc858363..502d141a 100644 --- a/tests/utils/removeCanvasInstance.test.ts +++ b/tests/utils/removeCanvasInstance.test.ts @@ -1,6 +1,6 @@ import { SketchProps } from "@/main"; -import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; import p5 from "@contracts/p5"; +import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { removeCanvasInstance } from "@utils/removeCanvasInstance"; import { createRef } from "react"; import { describe, expect, it, vi } from "vitest"; @@ -11,10 +11,10 @@ describe("removeCanvasInstance", () => { return; }); const removeSpy = vi.spyOn(instance, "remove"); - const canvasInstanceRef: CanvasInstanceRef = createRef(); - canvasInstanceRef.current = instance; + const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); + p5CanvasInstanceRef.current = instance; - removeCanvasInstance(canvasInstanceRef); + removeCanvasInstance(p5CanvasInstanceRef); expect(removeSpy).toHaveBeenCalledOnce(); }); @@ -23,13 +23,13 @@ describe("removeCanvasInstance", () => { const instance = new p5(() => { return; }); - const canvasInstanceRef: CanvasInstanceRef = createRef(); - canvasInstanceRef.current = instance; + const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); + p5CanvasInstanceRef.current = instance; - expect(canvasInstanceRef.current).not.toBeNull(); + expect(p5CanvasInstanceRef.current).not.toBeNull(); - removeCanvasInstance(canvasInstanceRef); + removeCanvasInstance(p5CanvasInstanceRef); - expect(canvasInstanceRef.current).toBeNull(); + expect(p5CanvasInstanceRef.current).toBeNull(); }); }); diff --git a/tests/utils/updateCanvasInstance.test.ts b/tests/utils/updateCanvasInstance.test.ts index 7ccdb748..81ead9ba 100644 --- a/tests/utils/updateCanvasInstance.test.ts +++ b/tests/utils/updateCanvasInstance.test.ts @@ -1,7 +1,7 @@ import { SketchProps } from "@/main"; import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; -import { type CanvasInstanceRef } from "@contracts/CanvasInstanceRef"; import p5 from "@contracts/p5"; +import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { createCanvasInstance } from "@utils/createCanvasInstance"; import { updateCanvasInstance } from "@utils/updateCanvasInstance"; import { createRef } from "react"; @@ -12,14 +12,14 @@ describe("updateCanvasInstance", () => { const sketch = vi.fn(); const wrapper = document.createElement("div"); const canvasContainerRef: CanvasContainerRef = createRef(); - const canvasInstanceRef: CanvasInstanceRef = createRef(); + const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); const instance = createCanvasInstance(sketch, wrapper); canvasContainerRef.current = wrapper; - canvasInstanceRef.current = instance; + p5CanvasInstanceRef.current = instance; const updatedCanvasInstanceRef = updateCanvasInstance( - canvasInstanceRef, + p5CanvasInstanceRef, canvasContainerRef, sketch ); @@ -33,13 +33,13 @@ describe("updateCanvasInstance", () => { const sketch = vi.fn(); const wrapper = document.createElement("div"); const canvasContainerRef: CanvasContainerRef = createRef(); - const canvasInstanceRef: CanvasInstanceRef = createRef(); + const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); const instance = createCanvasInstance(sketch, wrapper); - canvasInstanceRef.current = instance; + p5CanvasInstanceRef.current = instance; const updatedCanvasInstanceRef = updateCanvasInstance( - canvasInstanceRef, + p5CanvasInstanceRef, canvasContainerRef, sketch ); From a4e3a2c2d9e182cf0796cb4e5476ba08820e5ff2 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:13:50 +0100 Subject: [PATCH 10/17] Rename userProvidedProps to sketchProps --- src/components/P5CanvasWithSketch.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/P5CanvasWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx index 12257400..0bd84aa8 100644 --- a/src/components/P5CanvasWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -13,7 +13,7 @@ const P5CanvasWithSketch = ( ) => { const canvasContainerRef: CanvasContainerRef = React.useRef(null); const p5CanvasInstanceRef: P5CanvasInstanceRef = React.useRef(null); - const userProvidedProps: SketchProps = React.useMemo( + const sketchProps: SketchProps = React.useMemo( () => withoutKeys(props, [ "sketch", @@ -36,9 +36,9 @@ const P5CanvasWithSketch = ( React.useEffect(() => { /** @see https://github.com/P5-wrapper/react/discussions/360 */ p5CanvasInstanceRef.current?.updateWithProps?.( - userProvidedProps as unknown as Props + sketchProps as unknown as Props ); - }, [userProvidedProps, canvasContainerRef, p5CanvasInstanceRef]); + }, [sketchProps, canvasContainerRef, p5CanvasInstanceRef]); React.useEffect(() => () => removeCanvasInstance(p5CanvasInstanceRef), []); From 973ffd85c6216bbe01399e773e984699dda9eac6 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:28:31 +0100 Subject: [PATCH 11/17] Rename removeCanvasInstance to removeP5CanvasInstance --- src/components/P5CanvasWithSketch.tsx | 4 ++-- ...{removeCanvasInstance.ts => removeP5CanvasInstance.ts} | 2 +- src/utils/updateCanvasInstance.ts | 4 ++-- ...vasInstance.test.ts => removeP5CanvasInstance.test.ts} | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) rename src/utils/{removeCanvasInstance.ts => removeP5CanvasInstance.ts} (80%) rename tests/utils/{removeCanvasInstance.test.ts => removeP5CanvasInstance.test.ts} (81%) diff --git a/src/components/P5CanvasWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx index 0bd84aa8..9ca66a3e 100644 --- a/src/components/P5CanvasWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -4,7 +4,7 @@ import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { type P5CanvasPropsWithSketch } from "@contracts/P5CanvasPropsWithSketch"; import { type SketchProps } from "@contracts/SketchProps"; -import { removeCanvasInstance } from "@utils/removeCanvasInstance"; +import { removeP5CanvasInstance } from "@utils/removeP5CanvasInstance"; import { updateCanvasInstance } from "@utils/updateCanvasInstance"; import { withoutKeys } from "@utils/withoutKeys"; @@ -40,7 +40,7 @@ const P5CanvasWithSketch = ( ); }, [sketchProps, canvasContainerRef, p5CanvasInstanceRef]); - React.useEffect(() => () => removeCanvasInstance(p5CanvasInstanceRef), []); + React.useEffect(() => () => removeP5CanvasInstance(p5CanvasInstanceRef), []); return (
( +export function removeP5CanvasInstance( p5CanvasInstanceRef: P5CanvasInstanceRef ) { p5CanvasInstanceRef.current?.remove(); diff --git a/src/utils/updateCanvasInstance.ts b/src/utils/updateCanvasInstance.ts index 4f53ae86..011a26ea 100644 --- a/src/utils/updateCanvasInstance.ts +++ b/src/utils/updateCanvasInstance.ts @@ -3,7 +3,7 @@ import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { type Sketch } from "@contracts/Sketch"; import { type SketchProps } from "@contracts/SketchProps"; import { createCanvasInstance } from "@utils/createCanvasInstance"; -import { removeCanvasInstance } from "@utils/removeCanvasInstance"; +import { removeP5CanvasInstance } from "@utils/removeP5CanvasInstance"; export function updateCanvasInstance( p5CanvasInstanceRef: P5CanvasInstanceRef, @@ -14,7 +14,7 @@ export function updateCanvasInstance( return null; } - removeCanvasInstance(p5CanvasInstanceRef); + removeP5CanvasInstance(p5CanvasInstanceRef); return createCanvasInstance(sketch, canvasContainerRef.current); } diff --git a/tests/utils/removeCanvasInstance.test.ts b/tests/utils/removeP5CanvasInstance.test.ts similarity index 81% rename from tests/utils/removeCanvasInstance.test.ts rename to tests/utils/removeP5CanvasInstance.test.ts index 502d141a..7524533c 100644 --- a/tests/utils/removeCanvasInstance.test.ts +++ b/tests/utils/removeP5CanvasInstance.test.ts @@ -1,11 +1,11 @@ import { SketchProps } from "@/main"; import p5 from "@contracts/p5"; import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; -import { removeCanvasInstance } from "@utils/removeCanvasInstance"; +import { removeP5CanvasInstance } from "@utils/removeP5CanvasInstance"; import { createRef } from "react"; import { describe, expect, it, vi } from "vitest"; -describe("removeCanvasInstance", () => { +describe("removeP5CanvasInstance", () => { it("Calls the remove method on the canvas if it exists", () => { const instance = new p5(() => { return; @@ -14,7 +14,7 @@ describe("removeCanvasInstance", () => { const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); p5CanvasInstanceRef.current = instance; - removeCanvasInstance(p5CanvasInstanceRef); + removeP5CanvasInstance(p5CanvasInstanceRef); expect(removeSpy).toHaveBeenCalledOnce(); }); @@ -28,7 +28,7 @@ describe("removeCanvasInstance", () => { expect(p5CanvasInstanceRef.current).not.toBeNull(); - removeCanvasInstance(p5CanvasInstanceRef); + removeP5CanvasInstance(p5CanvasInstanceRef); expect(p5CanvasInstanceRef.current).toBeNull(); }); From 5179713f34d0a69f20a9d29b3f10e3ad819d1733 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:37:17 +0100 Subject: [PATCH 12/17] Rename updateCanvasInstance to updateP5CanvasInstance --- src/components/P5CanvasWithSketch.tsx | 4 ++-- ...nvasInstance.ts => updateP5CanvasInstance.ts} | 2 +- ...ce.test.ts => updateP5CanvasInstance.test.ts} | 16 ++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) rename src/utils/{updateCanvasInstance.ts => updateP5CanvasInstance.ts} (91%) rename tests/utils/{updateCanvasInstance.test.ts => updateP5CanvasInstance.test.ts} (73%) diff --git a/src/components/P5CanvasWithSketch.tsx b/src/components/P5CanvasWithSketch.tsx index 9ca66a3e..7916f198 100644 --- a/src/components/P5CanvasWithSketch.tsx +++ b/src/components/P5CanvasWithSketch.tsx @@ -5,7 +5,7 @@ import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { type P5CanvasPropsWithSketch } from "@contracts/P5CanvasPropsWithSketch"; import { type SketchProps } from "@contracts/SketchProps"; import { removeP5CanvasInstance } from "@utils/removeP5CanvasInstance"; -import { updateCanvasInstance } from "@utils/updateCanvasInstance"; +import { updateP5CanvasInstance } from "@utils/updateP5CanvasInstance"; import { withoutKeys } from "@utils/withoutKeys"; const P5CanvasWithSketch = ( @@ -26,7 +26,7 @@ const P5CanvasWithSketch = ( ); React.useEffect(() => { - p5CanvasInstanceRef.current = updateCanvasInstance( + p5CanvasInstanceRef.current = updateP5CanvasInstance( p5CanvasInstanceRef, canvasContainerRef, props.sketch diff --git a/src/utils/updateCanvasInstance.ts b/src/utils/updateP5CanvasInstance.ts similarity index 91% rename from src/utils/updateCanvasInstance.ts rename to src/utils/updateP5CanvasInstance.ts index 011a26ea..4a9da160 100644 --- a/src/utils/updateCanvasInstance.ts +++ b/src/utils/updateP5CanvasInstance.ts @@ -5,7 +5,7 @@ import { type SketchProps } from "@contracts/SketchProps"; import { createCanvasInstance } from "@utils/createCanvasInstance"; import { removeP5CanvasInstance } from "@utils/removeP5CanvasInstance"; -export function updateCanvasInstance( +export function updateP5CanvasInstance( p5CanvasInstanceRef: P5CanvasInstanceRef, canvasContainerRef: CanvasContainerRef, sketch: Sketch diff --git a/tests/utils/updateCanvasInstance.test.ts b/tests/utils/updateP5CanvasInstance.test.ts similarity index 73% rename from tests/utils/updateCanvasInstance.test.ts rename to tests/utils/updateP5CanvasInstance.test.ts index 81ead9ba..b8d125de 100644 --- a/tests/utils/updateCanvasInstance.test.ts +++ b/tests/utils/updateP5CanvasInstance.test.ts @@ -3,12 +3,12 @@ import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; import p5 from "@contracts/p5"; import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { createCanvasInstance } from "@utils/createCanvasInstance"; -import { updateCanvasInstance } from "@utils/updateCanvasInstance"; +import { updateP5CanvasInstance } from "@utils/updateP5CanvasInstance"; import { createRef } from "react"; import { describe, expect, it, vi } from "vitest"; -describe("updateCanvasInstance", () => { - it("Should update a canvas instance to a new version", () => { +describe("updateP5CanvasInstance", () => { + it("Should update a P5 canvas instance to a new version", () => { const sketch = vi.fn(); const wrapper = document.createElement("div"); const canvasContainerRef: CanvasContainerRef = createRef(); @@ -18,15 +18,15 @@ describe("updateCanvasInstance", () => { canvasContainerRef.current = wrapper; p5CanvasInstanceRef.current = instance; - const updatedCanvasInstanceRef = updateCanvasInstance( + const updatedP5CanvasInstanceRef = updateP5CanvasInstance( p5CanvasInstanceRef, canvasContainerRef, sketch ); expect(instance).toBeInstanceOf(p5); - expect(updatedCanvasInstanceRef).toBeInstanceOf(p5); - expect(instance).not.toEqual(updatedCanvasInstanceRef); + expect(updatedP5CanvasInstanceRef).toBeInstanceOf(p5); + expect(instance).not.toEqual(updatedP5CanvasInstanceRef); }); it("Should return undefined if the canvasContainerRef value is null", () => { @@ -38,12 +38,12 @@ describe("updateCanvasInstance", () => { p5CanvasInstanceRef.current = instance; - const updatedCanvasInstanceRef = updateCanvasInstance( + const updatedP5CanvasInstanceRef = updateP5CanvasInstance( p5CanvasInstanceRef, canvasContainerRef, sketch ); - expect(updatedCanvasInstanceRef).toBeNull(); + expect(updatedP5CanvasInstanceRef).toBeNull(); }); }); From 828ea01990619e60c6f284ac824c2676a50b785b Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:43:57 +0100 Subject: [PATCH 13/17] Rename createCanvasInstance to createP5CanvasInstance --- .../{createCanvasInstance.ts => createP5CanvasInstance.ts} | 2 +- src/utils/updateP5CanvasInstance.ts | 4 ++-- ...anvasInstance.test.ts => createP5CanvasInstance.test.ts} | 6 +++--- tests/utils/updateP5CanvasInstance.test.ts | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) rename src/utils/{createCanvasInstance.ts => createP5CanvasInstance.ts} (84%) rename tests/utils/{createCanvasInstance.test.ts => createP5CanvasInstance.test.ts} (62%) diff --git a/src/utils/createCanvasInstance.ts b/src/utils/createP5CanvasInstance.ts similarity index 84% rename from src/utils/createCanvasInstance.ts rename to src/utils/createP5CanvasInstance.ts index d764d7ba..19aebbb9 100644 --- a/src/utils/createCanvasInstance.ts +++ b/src/utils/createP5CanvasInstance.ts @@ -4,7 +4,7 @@ import { type Sketch } from "@contracts/Sketch"; import { type SketchProps } from "@contracts/SketchProps"; import { type Wrapper } from "@contracts/Wrapper"; -export function createCanvasInstance( +export function createP5CanvasInstance( sketch: Sketch, wrapper: Wrapper ): P5CanvasInstance { diff --git a/src/utils/updateP5CanvasInstance.ts b/src/utils/updateP5CanvasInstance.ts index 4a9da160..9a63a01a 100644 --- a/src/utils/updateP5CanvasInstance.ts +++ b/src/utils/updateP5CanvasInstance.ts @@ -2,7 +2,7 @@ import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; import { type Sketch } from "@contracts/Sketch"; import { type SketchProps } from "@contracts/SketchProps"; -import { createCanvasInstance } from "@utils/createCanvasInstance"; +import { createP5CanvasInstance } from "@utils/createP5CanvasInstance"; import { removeP5CanvasInstance } from "@utils/removeP5CanvasInstance"; export function updateP5CanvasInstance( @@ -16,5 +16,5 @@ export function updateP5CanvasInstance( removeP5CanvasInstance(p5CanvasInstanceRef); - return createCanvasInstance(sketch, canvasContainerRef.current); + return createP5CanvasInstance(sketch, canvasContainerRef.current); } diff --git a/tests/utils/createCanvasInstance.test.ts b/tests/utils/createP5CanvasInstance.test.ts similarity index 62% rename from tests/utils/createCanvasInstance.test.ts rename to tests/utils/createP5CanvasInstance.test.ts index aacd2e63..2851e8c6 100644 --- a/tests/utils/createCanvasInstance.test.ts +++ b/tests/utils/createP5CanvasInstance.test.ts @@ -1,12 +1,12 @@ import p5 from "@contracts/p5"; -import { createCanvasInstance } from "@utils/createCanvasInstance"; +import { createP5CanvasInstance } from "@utils/createP5CanvasInstance"; import { describe, expect, it, vi } from "vitest"; -describe("createCanvasInstance", () => { +describe("createP5CanvasInstance", () => { it("Should construct a valid implementation of p5 in instance mode", () => { const sketch = vi.fn(); const wrapper = document.createElement("div"); - const instance = createCanvasInstance(sketch, wrapper); + const instance = createP5CanvasInstance(sketch, wrapper); expect(instance).toBeInstanceOf(p5); }); diff --git a/tests/utils/updateP5CanvasInstance.test.ts b/tests/utils/updateP5CanvasInstance.test.ts index b8d125de..50ed5de9 100644 --- a/tests/utils/updateP5CanvasInstance.test.ts +++ b/tests/utils/updateP5CanvasInstance.test.ts @@ -2,7 +2,7 @@ import { SketchProps } from "@/main"; import { type CanvasContainerRef } from "@contracts/CanvasContainerRef"; import p5 from "@contracts/p5"; import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef"; -import { createCanvasInstance } from "@utils/createCanvasInstance"; +import { createP5CanvasInstance } from "@utils/createP5CanvasInstance"; import { updateP5CanvasInstance } from "@utils/updateP5CanvasInstance"; import { createRef } from "react"; import { describe, expect, it, vi } from "vitest"; @@ -13,7 +13,7 @@ describe("updateP5CanvasInstance", () => { const wrapper = document.createElement("div"); const canvasContainerRef: CanvasContainerRef = createRef(); const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); - const instance = createCanvasInstance(sketch, wrapper); + const instance = createP5CanvasInstance(sketch, wrapper); canvasContainerRef.current = wrapper; p5CanvasInstanceRef.current = instance; @@ -34,7 +34,7 @@ describe("updateP5CanvasInstance", () => { const wrapper = document.createElement("div"); const canvasContainerRef: CanvasContainerRef = createRef(); const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); - const instance = createCanvasInstance(sketch, wrapper); + const instance = createP5CanvasInstance(sketch, wrapper); p5CanvasInstanceRef.current = instance; From 627c0bfa9500b54f51b1b120d1cf05c194c16fd4 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Thu, 21 Aug 2025 13:58:49 +0100 Subject: [PATCH 14/17] Rename Wrapper to CanvasContainer --- src/contracts/CanvasContainer.ts | 1 + src/contracts/CanvasContainerRef.ts | 4 ++-- src/contracts/Wrapper.ts | 1 - src/utils/createP5CanvasInstance.ts | 6 +++--- tests/utils/createP5CanvasInstance.test.ts | 4 ++-- tests/utils/updateP5CanvasInstance.test.ts | 10 +++++----- 6 files changed, 13 insertions(+), 13 deletions(-) create mode 100644 src/contracts/CanvasContainer.ts delete mode 100644 src/contracts/Wrapper.ts diff --git a/src/contracts/CanvasContainer.ts b/src/contracts/CanvasContainer.ts new file mode 100644 index 00000000..6492afa2 --- /dev/null +++ b/src/contracts/CanvasContainer.ts @@ -0,0 +1 @@ +export type CanvasContainer = HTMLDivElement; diff --git a/src/contracts/CanvasContainerRef.ts b/src/contracts/CanvasContainerRef.ts index 212696d6..546b5fa9 100644 --- a/src/contracts/CanvasContainerRef.ts +++ b/src/contracts/CanvasContainerRef.ts @@ -1,4 +1,4 @@ -import { type Wrapper } from "@contracts/Wrapper"; +import { type CanvasContainer } from "@contracts/CanvasContainer"; import { type RefObject } from "react"; -export type CanvasContainerRef = RefObject; +export type CanvasContainerRef = RefObject; diff --git a/src/contracts/Wrapper.ts b/src/contracts/Wrapper.ts deleted file mode 100644 index 8fc34d11..00000000 --- a/src/contracts/Wrapper.ts +++ /dev/null @@ -1 +0,0 @@ -export type Wrapper = HTMLDivElement; diff --git a/src/utils/createP5CanvasInstance.ts b/src/utils/createP5CanvasInstance.ts index 19aebbb9..4f4337ff 100644 --- a/src/utils/createP5CanvasInstance.ts +++ b/src/utils/createP5CanvasInstance.ts @@ -1,12 +1,12 @@ +import { type CanvasContainer } from "@contracts/CanvasContainer"; import p5 from "@contracts/p5"; import { type P5CanvasInstance } from "@contracts/P5CanvasInstance"; import { type Sketch } from "@contracts/Sketch"; import { type SketchProps } from "@contracts/SketchProps"; -import { type Wrapper } from "@contracts/Wrapper"; export function createP5CanvasInstance( sketch: Sketch, - wrapper: Wrapper + canvasContainer: CanvasContainer ): P5CanvasInstance { - return new p5(sketch, wrapper); + return new p5(sketch, canvasContainer); } diff --git a/tests/utils/createP5CanvasInstance.test.ts b/tests/utils/createP5CanvasInstance.test.ts index 2851e8c6..c338ef27 100644 --- a/tests/utils/createP5CanvasInstance.test.ts +++ b/tests/utils/createP5CanvasInstance.test.ts @@ -5,8 +5,8 @@ import { describe, expect, it, vi } from "vitest"; describe("createP5CanvasInstance", () => { it("Should construct a valid implementation of p5 in instance mode", () => { const sketch = vi.fn(); - const wrapper = document.createElement("div"); - const instance = createP5CanvasInstance(sketch, wrapper); + const canvasContainer = document.createElement("div"); + const instance = createP5CanvasInstance(sketch, canvasContainer); expect(instance).toBeInstanceOf(p5); }); diff --git a/tests/utils/updateP5CanvasInstance.test.ts b/tests/utils/updateP5CanvasInstance.test.ts index 50ed5de9..7fc3e2c9 100644 --- a/tests/utils/updateP5CanvasInstance.test.ts +++ b/tests/utils/updateP5CanvasInstance.test.ts @@ -10,12 +10,12 @@ import { describe, expect, it, vi } from "vitest"; describe("updateP5CanvasInstance", () => { it("Should update a P5 canvas instance to a new version", () => { const sketch = vi.fn(); - const wrapper = document.createElement("div"); + const canvasContainer = document.createElement("div"); const canvasContainerRef: CanvasContainerRef = createRef(); const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); - const instance = createP5CanvasInstance(sketch, wrapper); + const instance = createP5CanvasInstance(sketch, canvasContainer); - canvasContainerRef.current = wrapper; + canvasContainerRef.current = canvasContainer; p5CanvasInstanceRef.current = instance; const updatedP5CanvasInstanceRef = updateP5CanvasInstance( @@ -31,10 +31,10 @@ describe("updateP5CanvasInstance", () => { it("Should return undefined if the canvasContainerRef value is null", () => { const sketch = vi.fn(); - const wrapper = document.createElement("div"); + const canvasContainer = document.createElement("div"); const canvasContainerRef: CanvasContainerRef = createRef(); const p5CanvasInstanceRef: P5CanvasInstanceRef = createRef(); - const instance = createP5CanvasInstance(sketch, wrapper); + const instance = createP5CanvasInstance(sketch, canvasContainer); p5CanvasInstanceRef.current = instance; From 5fbcc509989c275079ff5fa8e7d741e954ac46ed Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Thu, 21 Aug 2025 14:06:38 +0100 Subject: [PATCH 15/17] Actualize test descriptions --- tests/components/P5Canvas.test.tsx | 10 +++++----- tests/exports.test.tsx | 8 ++++---- tests/utils/removeP5CanvasInstance.test.ts | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/components/P5Canvas.test.tsx b/tests/components/P5Canvas.test.tsx index ce63e4b6..7d6f70f0 100644 --- a/tests/components/P5Canvas.test.tsx +++ b/tests/components/P5Canvas.test.tsx @@ -39,7 +39,7 @@ async function waitForLoading(findByTestId: RenderResult["findByTestId"]) { describe("P5Canvas", () => { describe("Rendering", () => { describe("Client", () => { - it("Renders the canvas into the wrapping element", async () => { + it("Renders the P5 canvas into the container element", async () => { const sketch = createSketch(); const { findByTestId } = render(); const canvas = await waitForCanvas(findByTestId); @@ -57,7 +57,7 @@ describe("P5Canvas", () => { expect(canvas).toBeInstanceOf(HTMLCanvasElement); }); - it("Adds a utility css class to the wrapping element", async () => { + it("Adds a utility css class to the container element", async () => { const sketch = createSketch(); const { findByTestId } = render(); @@ -158,7 +158,7 @@ describe("P5Canvas", () => { expect(loading.innerHTML).toBe("Loading test..."); }); - it("Should show the default error UI when the `error` prop is not set an error is thrown within the subtree of the wrapper", async () => { + it("Should show the default error UI when the `error` prop is not set an error is thrown within the subtree of the canvas container", async () => { const sketch = createSketch(); const ErrorChild = () => { throw new Error("oops"); @@ -176,7 +176,7 @@ describe("P5Canvas", () => { expect(error.textContent).toBe("❌ - Something went wrong"); }); - it("Should show the error UI when the `error` prop is set an error is thrown within the subtree of the wrapper", async () => { + it("Should show the error UI when the `error` prop is set an error is thrown within the subtree of the canvas container", async () => { const sketch = createSketch(); const ErrorView = vi.fn(error => { assert(error instanceof Error); @@ -200,7 +200,7 @@ describe("P5Canvas", () => { expect(error.innerHTML).toBe("Error: oops"); }); - it("Should log the error when an error is thrown within the subtree of the wrapper", async () => { + it("Should log the error when an error is thrown within the subtree of the canvas container", async () => { const sketch = createSketch(); const ErrorView = vi.fn(() =>
); const errorLogger = vi.fn(); diff --git a/tests/exports.test.tsx b/tests/exports.test.tsx index 2ee02602..6e3f4638 100644 --- a/tests/exports.test.tsx +++ b/tests/exports.test.tsx @@ -4,23 +4,23 @@ import { assert, describe, expect, it, vi } from "vitest"; describe("Exports", () => { describe("CanvasContainerClassName", () => { - it("Exports the css class name used on the wrapper", () => { + it("Exports the css class name used on the canvas container", () => { expect(CanvasContainerClassName).not.toBeUndefined(); expect(CanvasContainerClassName).toBe("canvas-container"); }); - it("Exports the css class name used on the wrapper as a non-empty string", () => { + it("Exports the css class name used on the canvas container as a non-empty string", () => { expect(typeof CanvasContainerClassName).toBe("string"); expect(CanvasContainerClassName.length).toBeGreaterThan(0); }); - it("Exports the wrapper component", () => { + it("Exports the P5 canvas component", () => { expect(P5Canvas).not.toBeUndefined(); }); }); describe("P5Canvas", () => { - it("Exports the wrapper component as a react element", () => { + it("Exports the P5 canvas component as a React element", () => { const component = createElement(P5Canvas, { sketch: vi.fn() }); diff --git a/tests/utils/removeP5CanvasInstance.test.ts b/tests/utils/removeP5CanvasInstance.test.ts index 7524533c..a49d6a37 100644 --- a/tests/utils/removeP5CanvasInstance.test.ts +++ b/tests/utils/removeP5CanvasInstance.test.ts @@ -6,7 +6,7 @@ import { createRef } from "react"; import { describe, expect, it, vi } from "vitest"; describe("removeP5CanvasInstance", () => { - it("Calls the remove method on the canvas if it exists", () => { + it("Calls the remove method on the P5 canvas instance if it exists", () => { const instance = new p5(() => { return; }); @@ -19,7 +19,7 @@ describe("removeP5CanvasInstance", () => { expect(removeSpy).toHaveBeenCalledOnce(); }); - it("Sets the provided canvas instance ref to null", () => { + it("Sets the provided P5 canvas instance ref to null", () => { const instance = new p5(() => { return; }); From 98cb261285090f42abe1b7d9777852f43b2ead43 Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Fri, 22 Aug 2025 00:39:00 +0100 Subject: [PATCH 16/17] Add examples to README for version 5 --- .github/README.md | 606 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 590 insertions(+), 16 deletions(-) diff --git a/.github/README.md b/.github/README.md index 9912977a..fcf3f841 100644 --- a/.github/README.md +++ b/.github/README.md @@ -27,8 +27,8 @@ package manager: ### Peer dependencies -Please note that `p5`, `react` and `react-dom` are peer dependencies, meaning -you should ensure they are installed before installing React P5 Wrapper. +Please note that `p5`, `react` and `react-dom` are peer dependencies. Make sure +they are installed in your project before installing this package. ```js "peerDependencies": { @@ -38,6 +38,20 @@ you should ensure they are installed before installing React P5 Wrapper. }, ``` +
Version 5 +

+ +```js +"peerDependencies": { + "p5": ">= 2.0.0", + "react": ">= 19.0.0", + "react-dom": ">= 19.0.0" +}, +``` + +

+
+ ### TypeScript If you would like to use Typescript, you should install `p5` types in the @@ -114,14 +128,44 @@ export function App() { } ``` +
Version 5 +

+ +```jsx +import * as React from "react"; +import { P5Canvas } from "@p5-wrapper/react"; + +function sketch(p5) { + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.draw = () => { + p5.background(250); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +} + +export function App() { + return ; +} +``` + +

+
+ ### TypeScript TypeScript sketches can be declared in two different ways, below you will find two ways to declare a sketch, both examples do the exact same thing. -In short though, the `ReactP5Wrapper` component requires you to pass a `sketch` -prop. The `sketch` prop is simply a function which takes a `p5` instance as it's -first and only argument. +In short though, the component requires you to pass a `sketch` prop. The +`sketch` prop is simply a function which takes a `p5` instance as it's first and +only argument. #### Option 1: Declaring a sketch using the `P5CanvasInstance` type @@ -149,6 +193,36 @@ export function App() { } ``` +
Version 5 +

+ +```tsx +import * as React from "react"; +import { P5Canvas, P5CanvasInstance } from "@p5-wrapper/react"; + +function sketch(p5: P5CanvasInstance) { + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.draw = () => { + p5.background(250); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +} + +export function App() { + return ; +} +``` + +

+
+ #### Option 2: Declaring a sketch using the `Sketch` type Using the `Sketch` type has one nice benefit over using `P5CanvasInstance` and @@ -185,6 +259,36 @@ export function App() { } ``` +
Version 5 +

+ +```tsx +import * as React from "react"; +import { P5Canvas, Sketch } from "@p5-wrapper/react"; + +const sketch: Sketch = p5 => { + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.draw = () => { + p5.background(250); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +}; + +export function App() { + return ; +} +``` + +

+
+ #### TypeScript Generics We also support the use of Generics to add type definitions for your props. If @@ -265,6 +369,60 @@ export function App() { } ``` +
Version 5 +

+ +```tsx +import { P5Canvas, P5CanvasInstance, SketchProps } from "@p5-wrapper/react"; +import React, { useEffect, useState } from "react"; + +type MySketchProps = SketchProps & { + rotation: number; +}; + +function sketch(p5: P5CanvasInstance) { + let rotation = 0; + + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.updateWithProps = props => { + if (props.rotation) { + rotation = (props.rotation * Math.PI) / 180; + } + }; + + p5.draw = () => { + p5.background(100); + p5.normalMaterial(); + p5.noStroke(); + p5.push(); + p5.rotateY(rotation); + p5.box(100); + p5.pop(); + }; +} + +export function App() { + const [rotation, setRotation] = useState(0); + + useEffect(() => { + const interval = setInterval( + () => setRotation(rotation => rotation + 100), + 100 + ); + + return () => { + clearInterval(interval); + }; + }, []); + + return ; +} +``` + +

+
+ ##### Usage with the `Sketch` type ```tsx @@ -315,6 +473,60 @@ export function App() { } ``` +
Version 5 +

+ +```tsx +import { P5Canvas, Sketch, SketchProps } from "@p5-wrapper/react"; +import React, { useEffect, useState } from "react"; + +type MySketchProps = SketchProps & { + rotation: number; +}; + +const sketch: Sketch = p5 => { + let rotation = 0; + + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.updateWithProps = props => { + if (props.rotation) { + rotation = (props.rotation * Math.PI) / 180; + } + }; + + p5.draw = () => { + p5.background(100); + p5.normalMaterial(); + p5.noStroke(); + p5.push(); + p5.rotateY(rotation); + p5.box(100); + p5.pop(); + }; +}; + +export function App() { + const [rotation, setRotation] = useState(0); + + useEffect(() => { + const interval = setInterval( + () => setRotation(rotation => rotation + 100), + 100 + ); + + return () => { + clearInterval(interval); + }; + }, []); + + return ; +} +``` + +

+
+ ### Using abstracted setup and draw functions ```jsx @@ -350,23 +562,61 @@ export function App() { } ``` +
Version 5 +

+ +```jsx +import * as React from "react"; +import { P5Canvas } from "@p5-wrapper/react"; + +function setup(p5) { + return () => { + p5.createCanvas(600, 400, p5.WEBGL); + }; +} + +function draw(p5) { + return () => { + p5.background(250); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +} + +function sketch(p5) { + p5.setup = setup(p5); + p5.draw = draw(p5); +} + +export function App() { + return ; +} +``` + +

+
+ ### Props -The only required property of the `ReactP5Wrapper` component is the `sketch` -prop. The `sketch` prop is a function that will be passed a p5 instance to use -for rendering your sketches as shown in [the usage section](#usage) above. +The only required property is the sketch prop. The sketch prop is a function +that will be passed a p5 instance to use for rendering your sketches (see the +usage section above). -You can pass as many custom props as you want to the `ReactP5Wrapper` component -and these will all be passed into the `updateWithProps` method if you have -defined it within your sketch. +You can pass as many custom props as you want. These will be passed into the +updateWithProps method if you have defined it within your sketch. #### Reacting to props In the below example you see the `updateWithProps` method being used. This is called when the component initially renders and when the props passed to the wrapper are changed, if it is set within your sketch. This way we can render our -`ReactP5Wrapper` component and react to component prop changes directly within -our sketches! +component (`ReactP5Wrapper` in v4, or `P5Canvas` in v5) and react to component +prop changes directly within our sketches! ```jsx import { ReactP5Wrapper } from "@p5-wrapper/react"; @@ -412,12 +662,63 @@ export function App() { } ``` +
Version 5 +

+ +```jsx +import { P5Canvas } from "@p5-wrapper/react"; +import React, { useEffect, useState } from "react"; + +function sketch(p5) { + let rotation = 0; + + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.updateWithProps = props => { + if (props.rotation) { + rotation = (props.rotation * Math.PI) / 180; + } + }; + + p5.draw = () => { + p5.background(100); + p5.normalMaterial(); + p5.noStroke(); + p5.push(); + p5.rotateY(rotation); + p5.box(100); + p5.pop(); + }; +} + +export function App() { + const [rotation, setRotation] = useState(0); + + useEffect(() => { + const interval = setInterval( + () => setRotation(rotation => rotation + 100), + 100 + ); + + return () => { + clearInterval(interval); + }; + }, []); + + return ; +} +``` + +

+
+ ### Children To render a component on top of the sketch, you can add it as a child of the -`ReactP5Wrapper` component and then use the exported `P5WrapperClassName` -constant in your css-in-js library of choice to style one element above the -other via css. +component (`ReactP5Wrapper` in v4, or `P5Canvas` in v5) and then use the +exported constant (`P5WrapperClassName` in v4, or `CanvasContainerClassName` in +v5) in your css-in-js library of choice to style one element above the other via +css. For instance, using [styled components](https://styled-components.com), we could center some text on top of our sketch like so: @@ -470,6 +771,61 @@ export function App() { } ``` +
Version 5 +

+ +```jsx +import { CanvasContainerClassName, P5Canvas } from "@p5-wrapper/react"; +import styled, { createGlobalStyle } from "styled-components"; + +const GlobalWrapperStyles = createGlobalStyle` + .${CanvasContainerClassName} { + position: relative; + } +`; + +const StyledCentredText = styled.span` + .${CanvasContainerClassName} & { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; + font-size: 2rem; + margin: 0; + text-align: center; + } +`; + +export function App() { + const [rotation, setRotation] = useState(0); + + useEffect(() => { + const interval = setInterval( + () => setRotation(rotation => rotation + 100), + 100 + ); + + return () => { + clearInterval(interval); + }; + }, []); + + return ( + + + + Hello world! + + + ); +} +``` + +

+
+
+ Of course, you can also use any other css-in-js library or by just using simple css to achieve almost anything you can imagine just by using the wrapper class as your root selector. @@ -543,6 +899,72 @@ export function App() { } ``` +
Version 5 +

+ +```jsx +import * as React from "react"; +import { P5Canvas } from "@p5-wrapper/react"; + +function sketchOne(p5) { + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.draw = () => { + p5.background(250); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +} + +function sketchTwo(p5) { + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.draw = () => { + p5.background(500); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +} + +export function App() { + const [sketch, setSketch] = React.useState(undefined); + const chooseNothing = () => setSketch(undefined); + const chooseSketchOne = () => setSketch(sketchOne); + const chooseSketchTwo = () => setSketch(sketchTwo); + + return ( + <> +

    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+ No sketch selected yet.} sketch={sketch} /> + + ); +} +``` + +

+
+
+ In this case, by default the fallback UI containing `

No sketch selected yet.

` will be rendered, then if you select a sketch, it will be rendered until you choose to once again "show nothing" which @@ -608,6 +1030,55 @@ export function App() { } ``` +
Version 5 +

+ +```tsx +import * as React from "react"; +import { P5Canvas, P5CanvasInstance } from "@p5-wrapper/react"; + +// This child will throw an error, oh no! +function ErrorChild() { + throw new Error("oops"); +} + +// This view will catch the thrown error and give you access to what exactly was thrown. +function ErrorUI(error: any) { + if (error instanceof Error) { + return

An error occured: {error.message}

; + } + + return

An unknown error occured: {error.toString()}

; +} + +function sketch(p5: P5CanvasInstance) { + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.draw = () => { + p5.background(250); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +} + +export function App() { + return ( + + + + ); +} +``` + +
+

+
+ Instead of the sketch, this will render `

An error occured: oops

`. Note that in truth, the `ErrorView` will **always** receive `any` values since JS / TS allow you to `throw` whatever values you want to, this is why we have to add @@ -651,6 +1122,41 @@ export function App() { } ``` +
Version 5 +

+ +```tsx +import * as React from "react"; +import { P5Canvas, P5CanvasInstance } from "@p5-wrapper/react"; + +function LoadingUI() { + return

The sketch is being loaded.

; +} + +function sketch(p5: P5CanvasInstance) { + p5.setup = () => p5.createCanvas(600, 400, p5.WEBGL); + + p5.draw = () => { + p5.background(250); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +} + +export function App() { + return ; +} +``` + +

+
+
+ In the initial period between the sketch render starting and it's lazy loading ending, the `LoadingUI` will be shown! @@ -739,6 +1245,74 @@ export default function App() { } ``` +
Version 5 +

+ +```tsx +import * as p5 from "p5"; +import { P5Canvas, Sketch } from "@p5-wrapper/react"; +import React, { useEffect, useState } from "react"; + +(window as any).p5 = p5; + +await import("p5/lib/addons/p5.sound"); + +const sketch: Sketch = p5 => { + let song: p5.SoundFile; + let button: p5.Element; + + p5.setup = () => { + p5.createCanvas(600, 400, p5.WEBGL); + p5.background(255, 0, 0); + button = p5.createButton("Toggle audio"); + + button.mousePressed(() => { + if (!song) { + const songPath = "/piano.mp3"; + song = p5.loadSound( + songPath, + () => { + song.play(); + }, + () => { + console.error( + `Could not load the requested sound file ${songPath}` + ); + } + ); + return; + } + + if (!song.isPlaying()) { + song.play(); + return; + } + + song.pause(); + }); + }; + + p5.draw = () => { + p5.background(250); + p5.normalMaterial(); + p5.push(); + p5.rotateZ(p5.frameCount * 0.01); + p5.rotateX(p5.frameCount * 0.01); + p5.rotateY(p5.frameCount * 0.01); + p5.plane(100); + p5.pop(); + }; +}; + +export default function App() { + return ; +} +``` + +

+
+
+ In this Typescript + React example, we can see a few key things. - Firstly we need to set `p5` on the `window` object manually. This is because From c34bc64a6e2ff99e13336e82ffd9d54f472fd03d Mon Sep 17 00:00:00 2001 From: Eugene Dyko <13007925+yevdyko@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:42:52 +0100 Subject: [PATCH 17/17] Add migration notes to README --- .github/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/README.md b/.github/README.md index fcf3f841..4ccac7f1 100644 --- a/.github/README.md +++ b/.github/README.md @@ -16,6 +16,24 @@ A component to integrate [P5.js](https://p5js.org/) sketches into > in your sketches and much more besides, you can read more on the upcoming > version of the [P5 docs](https://beta.p5js.org/). +## ⚠️ Migration Notes + +The main component for rendering p5 sketches in React depends on your version: + +- Version 4 and earlier: use `ReactP5Wrapper`. +- Version 5 and later: use `P5Canvas`. + +Both components work in the same way. + +Breaking changes in v5: + +1. Component rename + - `ReactP5Wrapper` → `P5Canvas` + +2. Types + - `P5WrapperProps` → `P5CanvasProps` + - `P5WrapperClassName` → `CanvasContainerClassName` + ## Installation To install, use the following command in the format appropriate to your chosen