@wave3d/react 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -7,10 +7,10 @@ Poster-first and lazy: it renders a server-safe `<div>`, then on the client moun
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
pnpm add @wave3d/react
|
|
10
|
+
pnpm add @wave3d/react three # + @types/three for TypeScript
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
`react` (`>=18`)
|
|
13
|
+
`react` (`>=18`) and `three` are peer dependencies; `@wave3d/core` is bundled in.
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
@@ -28,6 +28,20 @@ Server-render your own poster by passing it as a child — the shell adopts it:
|
|
|
28
28
|
</Wave3D>
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
## Capture a poster
|
|
32
|
+
|
|
33
|
+
`onReady` hands you the live `WaveRenderer` — capture the current frame as an image (e.g. to generate the `poster` that reduced-motion / no-WebGL / Save-Data visitors see):
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<Wave3D
|
|
37
|
+
preset="Hero"
|
|
38
|
+
onReady={async (renderer) => {
|
|
39
|
+
const blob = await renderer.captureImage("image/webp"); // transparent by default
|
|
40
|
+
// host / cache `blob`, then serve it as the poster
|
|
41
|
+
}}
|
|
42
|
+
/>
|
|
43
|
+
```
|
|
44
|
+
|
|
31
45
|
## Props
|
|
32
46
|
|
|
33
47
|
| Prop | Type | Notes |
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
|
-
import { BlendMode, ColorStop, FallbackReason, FallbackReason as FallbackReason$1, StudioConfig, StudioConfig as StudioConfig$1, WaveHandle, WaveRenderer, WaveRenderer as WaveRenderer$1 } from "@wave3d/core";
|
|
2
|
+
import { BlendMode, ColorStop, FallbackReason, FallbackReason as FallbackReason$1, SnapshotOptions, StudioConfig, StudioConfig as StudioConfig$1, WaveHandle, WaveRenderer, WaveRenderer as WaveRenderer$1 } from "@wave3d/core";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
5
5
|
/** Flat props mapped onto the first wave. */
|
|
@@ -48,5 +48,5 @@ interface Wave3DProps extends FlatWaveProps, FlatSceneProps {
|
|
|
48
48
|
*/
|
|
49
49
|
declare function Wave3D(props: Wave3DProps): ReactElement;
|
|
50
50
|
//#endregion
|
|
51
|
-
export { type FallbackReason, type StudioConfig, Wave3D, Wave3D as default, Wave3DProps, type WaveHandle, type WaveRenderer };
|
|
51
|
+
export { type FallbackReason, type SnapshotOptions, type StudioConfig, Wave3D, Wave3D as default, Wave3DProps, type WaveHandle, type WaveRenderer };
|
|
52
52
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport type { CSSProperties, ReactNode, ReactElement } from \"react\";\nimport { createWave, createDefaultConfig, makeStops } from \"@wave3d/core\";\nimport type {\n StudioConfig,\n WaveConfig,\n ColorStop,\n BlendMode,\n WaveHandle,\n WaveOptions,\n WaveRenderer,\n FallbackReason,\n} from \"@wave3d/core\";\n\n/** Flat props mapped onto the first wave. */\ninterface FlatWaveProps {\n palette?: string[] | ColorStop[];\n fiberCount?: number;\n fiberStrength?: number;\n sheen?: number;\n iridescence?: number;\n displaceAmount?: number;\n speed?: number;\n opacity?: number;\n blendMode?: BlendMode;\n theme?: \"solid\" | \"wireframe\";\n}\n\n/** Flat props mapped onto the scene. */\ninterface FlatSceneProps {\n background?: string;\n transparentBackground?: boolean;\n quality?: number;\n dprMax?: number;\n loopSeconds?: number;\n introRamp?: boolean;\n paused?: boolean;\n}\n\nexport interface Wave3DProps extends FlatWaveProps, FlatSceneProps {\n /** A preset: a function (tree-shakeable) or a name string (lazy-imports the presets chunk). */\n preset?: string | (() => Partial<StudioConfig>);\n /** Escape hatch: a full/partial config, applied last. Precedence: default ← preset ← flat props ← config. */\n config?: Partial<StudioConfig>;\n poster?: string;\n lazy?: boolean;\n webgl?: \"auto\" | \"force\" | \"off\";\n respectReducedMotion?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Custom SSR poster markup, e.g. `<img data-wave3d-poster src=\"…\" />` — the shell adopts it. */\n children?: ReactNode;\n onReady?: (renderer: WaveRenderer) => void;\n onFallback?: (reason: FallbackReason) => void;\n}\n\nfunction normalizePalette(p: string[] | ColorStop[]): ColorStop[] {\n return p.length > 0 && typeof p[0] === \"string\" ? makeStops(p as string[]) : (p as ColorStop[]);\n}\n\n/** Resolve the base config: function preset (sync) → its config; string preset → lazy-load presets. */\nasync function resolveBase(preset: Wave3DProps[\"preset\"]): Promise<StudioConfig> {\n if (typeof preset === \"function\") return { ...createDefaultConfig(), ...preset() };\n if (typeof preset === \"string\") {\n const { PRESETS } = await import(\"@wave3d/core/presets\");\n const make = PRESETS[preset];\n if (make) return make();\n }\n return createDefaultConfig();\n}\n\n/** Base config we can build synchronously (function preset / default) — a string preset resolves later. */\nfunction syncBase(preset: Wave3DProps[\"preset\"]): StudioConfig {\n return typeof preset === \"function\"\n ? { ...createDefaultConfig(), ...preset() }\n : createDefaultConfig();\n}\n\n/** Apply the flat props (and the config escape hatch) onto a full base config. */\nfunction buildConfig(base: StudioConfig, props: Wave3DProps): Partial<StudioConfig> {\n const w: WaveConfig = base.waves[0];\n if (props.palette !== undefined) w.palette = normalizePalette(props.palette);\n if (props.fiberCount !== undefined) w.fiberCount = props.fiberCount;\n if (props.fiberStrength !== undefined) w.fiberStrength = props.fiberStrength;\n if (props.sheen !== undefined) w.sheen = props.sheen;\n if (props.iridescence !== undefined) w.iridescence = props.iridescence;\n if (props.displaceAmount !== undefined) w.displaceAmount = props.displaceAmount;\n if (props.speed !== undefined) w.speed = props.speed;\n if (props.opacity !== undefined) w.opacity = props.opacity;\n if (props.blendMode !== undefined) w.blendMode = props.blendMode;\n if (props.theme !== undefined) w.theme = props.theme;\n if (props.background !== undefined) base.background = props.background;\n if (props.transparentBackground !== undefined)\n base.transparentBackground = props.transparentBackground;\n if (props.quality !== undefined) base.quality = props.quality;\n if (props.dprMax !== undefined) base.dprMax = props.dprMax;\n if (props.loopSeconds !== undefined) base.loopSeconds = props.loopSeconds;\n if (props.introRamp !== undefined) base.introRamp = props.introRamp;\n if (props.paused !== undefined) base.paused = props.paused;\n return { ...base, ...props.config };\n}\n\n/** A stable string that changes whenever the resolved config would — keys the update effect. */\nfunction configKey(props: Wave3DProps): string {\n const flat: Record<string, unknown> = {};\n const keys = [\n \"palette\",\n \"fiberCount\",\n \"fiberStrength\",\n \"sheen\",\n \"iridescence\",\n \"displaceAmount\",\n \"speed\",\n \"opacity\",\n \"blendMode\",\n \"theme\",\n \"background\",\n \"transparentBackground\",\n \"quality\",\n \"dprMax\",\n \"loopSeconds\",\n \"introRamp\",\n \"paused\",\n ] as const;\n for (const k of keys) if (props[k] !== undefined) flat[k] = props[k];\n return JSON.stringify({\n preset: typeof props.preset === \"function\" ? \"fn\" : props.preset,\n flat,\n config: props.config,\n });\n}\n\n/**\n * A drop-in, self-optimizing gradient wave. Renders a `<div>` (SSR-safe; pass an\n * `<img data-wave3d-poster>` child for a server-rendered poster) and, on the client, mounts the\n * shell — poster-first, lazy, WebGL/reduced-motion/save-data aware, with the engine code-split out.\n */\nexport function Wave3D(props: Wave3DProps): ReactElement {\n const { className, style, children } = props;\n const containerRef = useRef<HTMLDivElement>(null);\n const handleRef = useRef<WaveHandle | null>(null);\n // Keep the latest callbacks in a ref so they never force a remount.\n const cbRef = useRef<Pick<Wave3DProps, \"onReady\" | \"onFallback\">>({});\n cbRef.current.onReady = props.onReady;\n cbRef.current.onFallback = props.onFallback;\n\n // Mount once. StrictMode double-mount is safe: destroy() aborts a pending upgrade, and the\n // pre-upgrade create/destroy is DOM-only (poster + IntersectionObserver).\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n let cancelled = false;\n const options: WaveOptions = {\n poster: props.poster,\n lazy: props.lazy,\n webgl: props.webgl,\n respectReducedMotion: props.respectReducedMotion,\n onReady: (r) => cbRef.current.onReady?.(r),\n onFallback: (reason) => cbRef.current.onFallback?.(reason),\n };\n const handle = createWave(container, buildConfig(syncBase(props.preset), props), options);\n handleRef.current = handle;\n // A string preset resolves asynchronously; stage/set the real config once it loads.\n if (typeof props.preset === \"string\") {\n void resolveBase(props.preset).then((base) => {\n if (!cancelled && handleRef.current === handle) handle.set(buildConfig(base, props));\n });\n }\n return () => {\n cancelled = true;\n handle.destroy();\n handleRef.current = null;\n };\n // Mount-time only (options are captured once; config changes flow through the effect below).\n }, []);\n\n // Push config changes (flat props / config / preset) to the live handle.\n const key = configKey(props);\n useEffect(() => {\n const handle = handleRef.current;\n if (!handle) return;\n const apply = (base: StudioConfig): void => {\n if (handleRef.current === handle) handle.set(buildConfig(base, props));\n };\n if (typeof props.preset === \"string\") void resolveBase(props.preset).then(apply);\n else apply(syncBase(props.preset));\n // Re-runs only when the serialized config (`key`) changes; `props` is read fresh inside.\n }, [key]);\n\n return (\n <div ref={containerRef} className={className} style={style}>\n {children}\n </div>\n );\n}\n\nexport default Wave3D;\nexport type { StudioConfig, WaveHandle, WaveRenderer, FallbackReason } from \"@wave3d/core\";\n"],"mappings":";;;;;AA0DA,SAAS,iBAAiB,GAAwC;CAChE,OAAO,EAAE,SAAS,KAAK,OAAO,EAAE,OAAO,WAAW,UAAU,CAAa,IAAK;AAChF;;AAGA,eAAe,YAAY,QAAsD;CAC/E,IAAI,OAAO,WAAW,YAAY,OAAO;EAAE,GAAG,oBAAoB;EAAG,GAAG,OAAO;CAAE;CACjF,IAAI,OAAO,WAAW,UAAU;EAC9B,MAAM,EAAE,YAAY,MAAM,OAAO;EACjC,MAAM,OAAO,QAAQ;EACrB,IAAI,MAAM,OAAO,KAAK;CACxB;CACA,OAAO,oBAAoB;AAC7B;;AAGA,SAAS,SAAS,QAA6C;CAC7D,OAAO,OAAO,WAAW,aACrB;EAAE,GAAG,oBAAoB;EAAG,GAAG,OAAO;CAAE,IACxC,oBAAoB;AAC1B;;AAGA,SAAS,YAAY,MAAoB,OAA2C;CAClF,MAAM,IAAgB,KAAK,MAAM;CACjC,IAAI,MAAM,YAAY,KAAA,GAAW,EAAE,UAAU,iBAAiB,MAAM,OAAO;CAC3E,IAAI,MAAM,eAAe,KAAA,GAAW,EAAE,aAAa,MAAM;CACzD,IAAI,MAAM,kBAAkB,KAAA,GAAW,EAAE,gBAAgB,MAAM;CAC/D,IAAI,MAAM,UAAU,KAAA,GAAW,EAAE,QAAQ,MAAM;CAC/C,IAAI,MAAM,gBAAgB,KAAA,GAAW,EAAE,cAAc,MAAM;CAC3D,IAAI,MAAM,mBAAmB,KAAA,GAAW,EAAE,iBAAiB,MAAM;CACjE,IAAI,MAAM,UAAU,KAAA,GAAW,EAAE,QAAQ,MAAM;CAC/C,IAAI,MAAM,YAAY,KAAA,GAAW,EAAE,UAAU,MAAM;CACnD,IAAI,MAAM,cAAc,KAAA,GAAW,EAAE,YAAY,MAAM;CACvD,IAAI,MAAM,UAAU,KAAA,GAAW,EAAE,QAAQ,MAAM;CAC/C,IAAI,MAAM,eAAe,KAAA,GAAW,KAAK,aAAa,MAAM;CAC5D,IAAI,MAAM,0BAA0B,KAAA,GAClC,KAAK,wBAAwB,MAAM;CACrC,IAAI,MAAM,YAAY,KAAA,GAAW,KAAK,UAAU,MAAM;CACtD,IAAI,MAAM,WAAW,KAAA,GAAW,KAAK,SAAS,MAAM;CACpD,IAAI,MAAM,gBAAgB,KAAA,GAAW,KAAK,cAAc,MAAM;CAC9D,IAAI,MAAM,cAAc,KAAA,GAAW,KAAK,YAAY,MAAM;CAC1D,IAAI,MAAM,WAAW,KAAA,GAAW,KAAK,SAAS,MAAM;CACpD,OAAO;EAAE,GAAG;EAAM,GAAG,MAAM;CAAO;AACpC;;AAGA,SAAS,UAAU,OAA4B;CAC7C,MAAM,OAAgC,CAAC;CAoBvC,KAAK,MAAM,KAAK;EAlBd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAEiB,GAAG,IAAI,MAAM,OAAO,KAAA,GAAW,KAAK,KAAK,MAAM;CAClE,OAAO,KAAK,UAAU;EACpB,QAAQ,OAAO,MAAM,WAAW,aAAa,OAAO,MAAM;EAC1D;EACA,QAAQ,MAAM;CAChB,CAAC;AACH;;;;;;AAOA,SAAgB,OAAO,OAAkC;CACvD,MAAM,EAAE,WAAW,OAAO,aAAa;CACvC,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,YAAY,OAA0B,IAAI;CAEhD,MAAM,QAAQ,OAAoD,CAAC,CAAC;CACpE,MAAM,QAAQ,UAAU,MAAM;CAC9B,MAAM,QAAQ,aAAa,MAAM;CAIjC,gBAAgB;EACd,MAAM,YAAY,aAAa;EAC/B,IAAI,CAAC,WAAW;EAChB,IAAI,YAAY;EAChB,MAAM,UAAuB;GAC3B,QAAQ,MAAM;GACd,MAAM,MAAM;GACZ,OAAO,MAAM;GACb,sBAAsB,MAAM;GAC5B,UAAU,MAAM,MAAM,QAAQ,UAAU,CAAC;GACzC,aAAa,WAAW,MAAM,QAAQ,aAAa,MAAM;EAC3D;EACA,MAAM,SAAS,WAAW,WAAW,YAAY,SAAS,MAAM,MAAM,GAAG,KAAK,GAAG,OAAO;EACxF,UAAU,UAAU;EAEpB,IAAI,OAAO,MAAM,WAAW,UAC1B,YAAiB,MAAM,MAAM,CAAC,CAAC,MAAM,SAAS;GAC5C,IAAI,CAAC,aAAa,UAAU,YAAY,QAAQ,OAAO,IAAI,YAAY,MAAM,KAAK,CAAC;EACrF,CAAC;EAEH,aAAa;GACX,YAAY;GACZ,OAAO,QAAQ;GACf,UAAU,UAAU;EACtB;CAEF,GAAG,CAAC,CAAC;CAIL,gBAAgB;EACd,MAAM,SAAS,UAAU;EACzB,IAAI,CAAC,QAAQ;EACb,MAAM,SAAS,SAA6B;GAC1C,IAAI,UAAU,YAAY,QAAQ,OAAO,IAAI,YAAY,MAAM,KAAK,CAAC;EACvE;EACA,IAAI,OAAO,MAAM,WAAW,UAAU,YAAiB,MAAM,MAAM,CAAC,CAAC,KAAK,KAAK;OAC1E,MAAM,SAAS,MAAM,MAAM,CAAC;CAEnC,GAAG,CAVS,UAAU,KAUhB,CAAC,CAAC;CAER,OACE,oBAAC,OAAD;EAAK,KAAK;EAAyB;EAAkB;EAClD;CACE,CAAA;AAET"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport type { CSSProperties, ReactNode, ReactElement } from \"react\";\nimport { createWave, createDefaultConfig, makeStops } from \"@wave3d/core\";\nimport type {\n StudioConfig,\n WaveConfig,\n ColorStop,\n BlendMode,\n WaveHandle,\n WaveOptions,\n WaveRenderer,\n FallbackReason,\n} from \"@wave3d/core\";\n\n/** Flat props mapped onto the first wave. */\ninterface FlatWaveProps {\n palette?: string[] | ColorStop[];\n fiberCount?: number;\n fiberStrength?: number;\n sheen?: number;\n iridescence?: number;\n displaceAmount?: number;\n speed?: number;\n opacity?: number;\n blendMode?: BlendMode;\n theme?: \"solid\" | \"wireframe\";\n}\n\n/** Flat props mapped onto the scene. */\ninterface FlatSceneProps {\n background?: string;\n transparentBackground?: boolean;\n quality?: number;\n dprMax?: number;\n loopSeconds?: number;\n introRamp?: boolean;\n paused?: boolean;\n}\n\nexport interface Wave3DProps extends FlatWaveProps, FlatSceneProps {\n /** A preset: a function (tree-shakeable) or a name string (lazy-imports the presets chunk). */\n preset?: string | (() => Partial<StudioConfig>);\n /** Escape hatch: a full/partial config, applied last. Precedence: default ← preset ← flat props ← config. */\n config?: Partial<StudioConfig>;\n poster?: string;\n lazy?: boolean;\n webgl?: \"auto\" | \"force\" | \"off\";\n respectReducedMotion?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Custom SSR poster markup, e.g. `<img data-wave3d-poster src=\"…\" />` — the shell adopts it. */\n children?: ReactNode;\n onReady?: (renderer: WaveRenderer) => void;\n onFallback?: (reason: FallbackReason) => void;\n}\n\nfunction normalizePalette(p: string[] | ColorStop[]): ColorStop[] {\n return p.length > 0 && typeof p[0] === \"string\" ? makeStops(p as string[]) : (p as ColorStop[]);\n}\n\n/** Resolve the base config: function preset (sync) → its config; string preset → lazy-load presets. */\nasync function resolveBase(preset: Wave3DProps[\"preset\"]): Promise<StudioConfig> {\n if (typeof preset === \"function\") return { ...createDefaultConfig(), ...preset() };\n if (typeof preset === \"string\") {\n const { PRESETS } = await import(\"@wave3d/core/presets\");\n const make = PRESETS[preset];\n if (make) return make();\n }\n return createDefaultConfig();\n}\n\n/** Base config we can build synchronously (function preset / default) — a string preset resolves later. */\nfunction syncBase(preset: Wave3DProps[\"preset\"]): StudioConfig {\n return typeof preset === \"function\"\n ? { ...createDefaultConfig(), ...preset() }\n : createDefaultConfig();\n}\n\n/** Apply the flat props (and the config escape hatch) onto a full base config. */\nfunction buildConfig(base: StudioConfig, props: Wave3DProps): Partial<StudioConfig> {\n const w: WaveConfig = base.waves[0];\n if (props.palette !== undefined) w.palette = normalizePalette(props.palette);\n if (props.fiberCount !== undefined) w.fiberCount = props.fiberCount;\n if (props.fiberStrength !== undefined) w.fiberStrength = props.fiberStrength;\n if (props.sheen !== undefined) w.sheen = props.sheen;\n if (props.iridescence !== undefined) w.iridescence = props.iridescence;\n if (props.displaceAmount !== undefined) w.displaceAmount = props.displaceAmount;\n if (props.speed !== undefined) w.speed = props.speed;\n if (props.opacity !== undefined) w.opacity = props.opacity;\n if (props.blendMode !== undefined) w.blendMode = props.blendMode;\n if (props.theme !== undefined) w.theme = props.theme;\n if (props.background !== undefined) base.background = props.background;\n if (props.transparentBackground !== undefined)\n base.transparentBackground = props.transparentBackground;\n if (props.quality !== undefined) base.quality = props.quality;\n if (props.dprMax !== undefined) base.dprMax = props.dprMax;\n if (props.loopSeconds !== undefined) base.loopSeconds = props.loopSeconds;\n if (props.introRamp !== undefined) base.introRamp = props.introRamp;\n if (props.paused !== undefined) base.paused = props.paused;\n return { ...base, ...props.config };\n}\n\n/** A stable string that changes whenever the resolved config would — keys the update effect. */\nfunction configKey(props: Wave3DProps): string {\n const flat: Record<string, unknown> = {};\n const keys = [\n \"palette\",\n \"fiberCount\",\n \"fiberStrength\",\n \"sheen\",\n \"iridescence\",\n \"displaceAmount\",\n \"speed\",\n \"opacity\",\n \"blendMode\",\n \"theme\",\n \"background\",\n \"transparentBackground\",\n \"quality\",\n \"dprMax\",\n \"loopSeconds\",\n \"introRamp\",\n \"paused\",\n ] as const;\n for (const k of keys) if (props[k] !== undefined) flat[k] = props[k];\n return JSON.stringify({\n preset: typeof props.preset === \"function\" ? \"fn\" : props.preset,\n flat,\n config: props.config,\n });\n}\n\n/**\n * A drop-in, self-optimizing gradient wave. Renders a `<div>` (SSR-safe; pass an\n * `<img data-wave3d-poster>` child for a server-rendered poster) and, on the client, mounts the\n * shell — poster-first, lazy, WebGL/reduced-motion/save-data aware, with the engine code-split out.\n */\nexport function Wave3D(props: Wave3DProps): ReactElement {\n const { className, style, children } = props;\n const containerRef = useRef<HTMLDivElement>(null);\n const handleRef = useRef<WaveHandle | null>(null);\n // Keep the latest callbacks in a ref so they never force a remount.\n const cbRef = useRef<Pick<Wave3DProps, \"onReady\" | \"onFallback\">>({});\n cbRef.current.onReady = props.onReady;\n cbRef.current.onFallback = props.onFallback;\n\n // Mount once. StrictMode double-mount is safe: destroy() aborts a pending upgrade, and the\n // pre-upgrade create/destroy is DOM-only (poster + IntersectionObserver).\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n let cancelled = false;\n const options: WaveOptions = {\n poster: props.poster,\n lazy: props.lazy,\n webgl: props.webgl,\n respectReducedMotion: props.respectReducedMotion,\n onReady: (r) => cbRef.current.onReady?.(r),\n onFallback: (reason) => cbRef.current.onFallback?.(reason),\n };\n const handle = createWave(container, buildConfig(syncBase(props.preset), props), options);\n handleRef.current = handle;\n // A string preset resolves asynchronously; stage/set the real config once it loads.\n if (typeof props.preset === \"string\") {\n void resolveBase(props.preset).then((base) => {\n if (!cancelled && handleRef.current === handle) handle.set(buildConfig(base, props));\n });\n }\n return () => {\n cancelled = true;\n handle.destroy();\n handleRef.current = null;\n };\n // Mount-time only (options are captured once; config changes flow through the effect below).\n }, []);\n\n // Push config changes (flat props / config / preset) to the live handle.\n const key = configKey(props);\n useEffect(() => {\n const handle = handleRef.current;\n if (!handle) return;\n const apply = (base: StudioConfig): void => {\n if (handleRef.current === handle) handle.set(buildConfig(base, props));\n };\n if (typeof props.preset === \"string\") void resolveBase(props.preset).then(apply);\n else apply(syncBase(props.preset));\n // Re-runs only when the serialized config (`key`) changes; `props` is read fresh inside.\n }, [key]);\n\n return (\n <div ref={containerRef} className={className} style={style}>\n {children}\n </div>\n );\n}\n\nexport default Wave3D;\nexport type {\n StudioConfig,\n WaveHandle,\n WaveRenderer,\n FallbackReason,\n SnapshotOptions,\n} from \"@wave3d/core\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wave3d/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "React <Wave3D> component for @wave3d — a drop-in, self-optimizing animated gradient wave",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"animation",
|
|
@@ -36,14 +36,22 @@
|
|
|
36
36
|
"publishConfig": {
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@wave3d/core": "^0.2.0"
|
|
41
|
+
},
|
|
39
42
|
"devDependencies": {
|
|
40
43
|
"@types/react": "^19.0.0",
|
|
41
|
-
"react": "^19.0.0"
|
|
42
|
-
"@wave3d/core": "0.1.0"
|
|
44
|
+
"react": "^19.0.0"
|
|
43
45
|
},
|
|
44
46
|
"peerDependencies": {
|
|
47
|
+
"@types/three": ">=0.180",
|
|
45
48
|
"react": ">=18",
|
|
46
|
-
"
|
|
49
|
+
"three": ">=0.180 <1"
|
|
50
|
+
},
|
|
51
|
+
"peerDependenciesMeta": {
|
|
52
|
+
"@types/three": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
47
55
|
},
|
|
48
56
|
"scripts": {
|
|
49
57
|
"typecheck": "tsc --noEmit",
|