|
1 | 1 | import diff from "microdiff";
|
2 | 2 | import p5 from "p5";
|
3 |
| -import React, { createRef, FC, memo, useState } from "react"; |
| 3 | +import React, { createRef, memo, useState } from "react"; |
4 | 4 | import { useIsomorphicEffect } from "rooks";
|
5 | 5 |
|
6 | 6 | type Wrapper = HTMLDivElement;
|
| 7 | +type WithChildren<T = unknown> = T & { children?: React.ReactNode }; |
| 8 | +type InputProps<Props extends SketchProps = SketchProps> = Props & { |
| 9 | + sketch: Sketch<Props>; |
| 10 | +}; |
| 11 | +export type Sketch<Props extends SketchProps = SketchProps> = ( |
| 12 | + instance: P5Instance<Props> |
| 13 | +) => void; |
| 14 | +export type SketchProps = { [key: string]: unknown }; |
| 15 | +export type P5WrapperProps<Props extends SketchProps = SketchProps> = |
| 16 | + WithChildren<InputProps<Props>>; |
| 17 | +export type P5Instance<Props extends SketchProps = SketchProps> = p5 & { |
| 18 | + updateWithProps?: (props: Props) => void; |
| 19 | +}; |
7 | 20 |
|
8 |
| -export interface SketchProps { |
9 |
| - [key: string]: any; |
10 |
| -} |
11 |
| - |
12 |
| -export interface Sketch { |
13 |
| - (instance: P5Instance): void; |
14 |
| -} |
15 |
| - |
16 |
| -export interface P5WrapperProps extends SketchProps { |
17 |
| - sketch: Sketch; |
18 |
| -} |
19 |
| - |
20 |
| -export interface P5Instance extends p5 { |
21 |
| - updateWithProps?: (props: SketchProps) => void; |
22 |
| -} |
23 |
| - |
24 |
| -function createCanvas(sketch: Sketch, wrapper: Wrapper): P5Instance { |
| 21 | +function createCanvas<Props extends SketchProps = SketchProps>( |
| 22 | + sketch: Sketch<Props>, |
| 23 | + wrapper: Wrapper |
| 24 | +): P5Instance<Props> { |
25 | 25 | return new p5(sketch, wrapper);
|
26 | 26 | }
|
27 | 27 |
|
28 |
| -const ReactP5WrapperComponent: FC<P5WrapperProps> = ({ |
| 28 | +function ReactP5WrapperComponent<Props extends SketchProps = SketchProps>({ |
29 | 29 | sketch,
|
30 | 30 | children,
|
31 | 31 | ...props
|
32 |
| -}) => { |
| 32 | +}: P5WrapperProps<Props>) { |
33 | 33 | const wrapperRef = createRef<Wrapper>();
|
34 |
| - const [instance, setInstance] = useState<P5Instance>(); |
| 34 | + const [instance, setInstance] = useState<P5Instance<Props>>(); |
35 | 35 |
|
36 | 36 | useIsomorphicEffect(() => {
|
37 | 37 | if (wrapperRef.current === null) {
|
38 | 38 | return;
|
39 | 39 | }
|
40 | 40 |
|
41 | 41 | instance?.remove();
|
42 |
| - const canvas = createCanvas(sketch, wrapperRef.current); |
| 42 | + const canvas = createCanvas<Props>(sketch, wrapperRef.current); |
43 | 43 | setInstance(canvas);
|
44 | 44 | }, [sketch]);
|
45 | 45 |
|
46 |
| - useIsomorphicEffect(() => { |
47 |
| - instance?.updateWithProps?.(props); |
48 |
| - }, [props, instance]); |
| 46 | + useIsomorphicEffect( |
| 47 | + /** |
| 48 | + * The `as any` cast is begrudgingly required due to a known limitation of the TypeScript compiler as demonstrated in issues: |
| 49 | + * |
| 50 | + * - https://github.com/microsoft/TypeScript/issues/35858 |
| 51 | + * - https://github.com/microsoft/TypeScript/issues/37670 |
| 52 | + * |
| 53 | + * Potentially this will be resolved by this PR once it is eventually merged: |
| 54 | + * |
| 55 | + * - https://github.com/microsoft/TypeScript/pull/42382 |
| 56 | + * |
| 57 | + * Etiher way, until a resolution is merged into the TypeScript compiler that addressed this isssue, we need to use this workaround. |
| 58 | + * We could also remove this if we manage find a reasonable workaround of some sort ourselves of course. |
| 59 | + * If a workaround / change of implementation comes to mind, please raise an issue on the repository or feel free to open a PR! |
| 60 | + */ |
| 61 | + () => instance?.updateWithProps?.(props as any), |
| 62 | + [props, instance] |
| 63 | + ); |
49 | 64 |
|
50 | 65 | useIsomorphicEffect(() => () => instance?.remove(), []);
|
51 | 66 |
|
52 | 67 | return <div ref={wrapperRef}>{children}</div>;
|
53 |
| -}; |
| 68 | +} |
54 | 69 |
|
55 |
| -function propsAreEqual(previous: P5WrapperProps, next: P5WrapperProps) { |
| 70 | +function propsAreEqual<Props extends SketchProps = SketchProps>( |
| 71 | + previous: P5WrapperProps<Props>, |
| 72 | + next: P5WrapperProps<Props> |
| 73 | +) { |
56 | 74 | const differences = diff(previous, next);
|
57 | 75 |
|
58 | 76 | return differences.length === 0;
|
|
0 commit comments