Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
624 changes: 608 additions & 16 deletions .github/README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions config/vite/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
4 changes: 2 additions & 2 deletions demo/app.jsx
Original file line number Diff line number Diff line change
@@ -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";

Expand Down Expand Up @@ -61,7 +61,7 @@ function App() {

return (
<>
<ReactP5Wrapper sketch={state.sketch} rotation={state.rotation} />
<P5Canvas sketch={state.sketch} rotation={state.rotation} />
{state.sketch === record && (
<div style={{ marginTop: "1rem", marginBottom: "1rem" }}>
<button id="start-recording">Start Recording</button>
Expand Down
6 changes: 6 additions & 0 deletions src/components/P5Canvas.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import * as React from "react";
import { propsAreEqual } from "@utils/propsAreEqual";

const P5CanvasGuard = React.lazy(() => import("@components/P5CanvasGuard"));

export const P5Canvas = React.memo(P5CanvasGuard, propsAreEqual);
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import * as React from "react";
import { type P5WrapperProps } from "@contracts/P5WrapperProps";
import { type P5WrapperPropsWithSketch } from "@contracts/P5WrapperPropsWithSketch";
import { type P5CanvasProps } from "@contracts/P5CanvasProps";
import { type P5CanvasPropsWithSketch } from "@contracts/P5CanvasPropsWithSketch";
import { type SketchProps } from "@contracts/SketchProps";
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(() =>
Expand All @@ -16,11 +16,11 @@ const ErrorBoundary = React.lazy(() =>
}))
);

const ReactP5WrapperGuard = <Props extends SketchProps>(
props: P5WrapperProps<Props>
const P5CanvasGuard = <Props extends SketchProps>(
props: P5CanvasProps<Props>
) => {
if (props.sketch === undefined) {
console.error("[ReactP5Wrapper] The `sketch` prop is required.");
console.error("[P5Canvas] The `sketch` prop is required.");

return props.fallback?.() ?? null;
}
Expand All @@ -43,13 +43,13 @@ const ReactP5WrapperGuard = <Props extends SketchProps>(
props.loading?.() ?? <p data-testid="loading">🚀 Loading...</p>
}
>
<ReactP5WrapperWithSketch
<P5CanvasWithSketch
/** @see https://github.com/P5-wrapper/react/discussions/360 */
{...(props as unknown as P5WrapperPropsWithSketch<Props>)}
{...(props as unknown as P5CanvasPropsWithSketch<Props>)}
/>
</React.Suspense>
</ErrorBoundary>
);
};

export default ReactP5WrapperGuard;
export default P5CanvasGuard;
56 changes: 56 additions & 0 deletions src/components/P5CanvasWithSketch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as React from "react";
import { CanvasContainerClassName } from "@constants/CanvasContainerClassName";
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 { removeP5CanvasInstance } from "@utils/removeP5CanvasInstance";
import { updateP5CanvasInstance } from "@utils/updateP5CanvasInstance";
import { withoutKeys } from "@utils/withoutKeys";

const P5CanvasWithSketch = <Props extends SketchProps>(
props: P5CanvasPropsWithSketch<Props>
) => {
const canvasContainerRef: CanvasContainerRef = React.useRef(null);
const p5CanvasInstanceRef: P5CanvasInstanceRef<Props> = React.useRef(null);
const sketchProps: SketchProps = React.useMemo(
() =>
withoutKeys(props, [
"sketch",
"fallback",
"loading",
"error",
"children"
]),
[props]
);

React.useEffect(() => {
p5CanvasInstanceRef.current = updateP5CanvasInstance(
p5CanvasInstanceRef,
canvasContainerRef,
props.sketch
);
}, [props.sketch]);

React.useEffect(() => {
/** @see https://github.com/P5-wrapper/react/discussions/360 */
p5CanvasInstanceRef.current?.updateWithProps?.(
sketchProps as unknown as Props
);
}, [sketchProps, canvasContainerRef, p5CanvasInstanceRef]);

React.useEffect(() => () => removeP5CanvasInstance(p5CanvasInstanceRef), []);

return (
<div
ref={canvasContainerRef}
className={CanvasContainerClassName}
data-testid="canvas-container"
>
{props.children}
</div>
);
};

export default P5CanvasWithSketch;
8 changes: 0 additions & 8 deletions src/components/ReactP5Wrapper.tsx

This file was deleted.

52 changes: 0 additions & 52 deletions src/components/ReactP5WrapperWithSketch.tsx

This file was deleted.

1 change: 1 addition & 0 deletions src/constants/CanvasContainerClassName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const CanvasContainerClassName = "canvas-container";
1 change: 0 additions & 1 deletion src/constants/P5WrapperClassName.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/contracts/CanvasContainer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type CanvasContainer = HTMLDivElement;
4 changes: 4 additions & 0 deletions src/contracts/CanvasContainerRef.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { type CanvasContainer } from "@contracts/CanvasContainer";
import { type RefObject } from "react";

export type CanvasContainerRef = RefObject<CanvasContainer | null>;
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import { type P5CanvasInstance } from "@contracts/P5CanvasInstance";
import { type SketchProps } from "@contracts/SketchProps";
import { type RefObject } from "react";

export type CanvasInstanceRef<Props extends SketchProps> =
/** Ref to the active p5.js sketch instance controlling the canvas */
export type P5CanvasInstanceRef<Props extends SketchProps> =
RefObject<P5CanvasInstance<Props> | null>;
Original file line number Diff line number Diff line change
Expand Up @@ -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<Props extends SketchProps = SketchProps> =
export type P5CanvasProps<Props extends SketchProps = SketchProps> =
WithChildren<InputProps<Props>>;
6 changes: 6 additions & 0 deletions src/contracts/P5CanvasPropsWithSketch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { type P5CanvasProps } from "@contracts/P5CanvasProps";
import { type Sketch } from "@contracts/Sketch";
import { type SketchProps } from "@contracts/SketchProps";

export type P5CanvasPropsWithSketch<Props extends SketchProps> =
P5CanvasProps<Props> & { sketch: Sketch<Props> };
6 changes: 0 additions & 6 deletions src/contracts/P5WrapperPropsWithSketch.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/contracts/Wrapper.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/contracts/WrapperRef.ts

This file was deleted.

6 changes: 3 additions & 3 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { ReactP5Wrapper } from "@components/ReactP5Wrapper";
export { P5WrapperClassName } from "@constants/P5WrapperClassName";
export { P5Canvas } from "@components/P5Canvas";
export { CanvasContainerClassName } from "@constants/CanvasContainerClassName";
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";
Original file line number Diff line number Diff line change
@@ -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 createCanvasInstance<Props extends SketchProps>(
export function createP5CanvasInstance<Props extends SketchProps>(
sketch: Sketch<Props>,
wrapper: Wrapper
canvasContainer: CanvasContainer
): P5CanvasInstance<Props> {
return new p5(sketch, wrapper);
return new p5(sketch, canvasContainer);
}
2 changes: 1 addition & 1 deletion src/utils/logErrorBoundaryError.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/utils/propsAreEqual.ts
Original file line number Diff line number Diff line change
@@ -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<Props extends SketchProps>(
previous: P5WrapperProps<Props>,
next: P5WrapperProps<Props>
previous: P5CanvasProps<Props>,
next: P5CanvasProps<Props>
) {
const differences = diff(previous, next);

Expand Down
9 changes: 0 additions & 9 deletions src/utils/removeCanvasInstance.ts

This file was deleted.

9 changes: 9 additions & 0 deletions src/utils/removeP5CanvasInstance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { type P5CanvasInstanceRef } from "@contracts/P5CanvasInstanceRef";
import { type SketchProps } from "@contracts/SketchProps";

export function removeP5CanvasInstance<Props extends SketchProps>(
p5CanvasInstanceRef: P5CanvasInstanceRef<Props>
) {
p5CanvasInstanceRef.current?.remove();
p5CanvasInstanceRef.current = null;
}
20 changes: 0 additions & 20 deletions src/utils/updateCanvasInstance.ts

This file was deleted.

20 changes: 20 additions & 0 deletions src/utils/updateP5CanvasInstance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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 { createP5CanvasInstance } from "@utils/createP5CanvasInstance";
import { removeP5CanvasInstance } from "@utils/removeP5CanvasInstance";

export function updateP5CanvasInstance<Props extends SketchProps>(
p5CanvasInstanceRef: P5CanvasInstanceRef<Props>,
canvasContainerRef: CanvasContainerRef,
sketch: Sketch<Props>
) {
if (canvasContainerRef.current === null) {
return null;
}

removeP5CanvasInstance(p5CanvasInstanceRef);

return createP5CanvasInstance(sketch, canvasContainerRef.current);
}
Loading
Loading