@wave3d/core 0.1.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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/config/model.d.ts +240 -0
  5. package/dist/config/model.js +496 -0
  6. package/dist/config/model.js.map +1 -0
  7. package/dist/core-loader.d.ts +10 -0
  8. package/dist/core-loader.js +12 -0
  9. package/dist/core-loader.js.map +1 -0
  10. package/dist/index.d.ts +4 -0
  11. package/dist/index.js +3 -0
  12. package/dist/presets.d.ts +8 -0
  13. package/dist/presets.js +544 -0
  14. package/dist/presets.js.map +1 -0
  15. package/dist/renderer/WaveGeometry.d.ts +31 -0
  16. package/dist/renderer/WaveGeometry.js +92 -0
  17. package/dist/renderer/WaveGeometry.js.map +1 -0
  18. package/dist/renderer/WaveRenderer.d.ts +232 -0
  19. package/dist/renderer/WaveRenderer.js +1118 -0
  20. package/dist/renderer/WaveRenderer.js.map +1 -0
  21. package/dist/renderer/heroPalette.d.ts +10 -0
  22. package/dist/renderer/heroPalette.js +34 -0
  23. package/dist/renderer/heroPalette.js.map +1 -0
  24. package/dist/renderer/index.d.ts +4 -0
  25. package/dist/renderer/index.js +4 -0
  26. package/dist/renderer/palette.d.ts +67 -0
  27. package/dist/renderer/palette.js +535 -0
  28. package/dist/renderer/palette.js.map +1 -0
  29. package/dist/renderer/shaders.js +545 -0
  30. package/dist/renderer/shaders.js.map +1 -0
  31. package/dist/shell/createWave.d.ts +58 -0
  32. package/dist/shell/createWave.js +161 -0
  33. package/dist/shell/createWave.js.map +1 -0
  34. package/dist/shell/poster.js +64 -0
  35. package/dist/shell/poster.js.map +1 -0
  36. package/dist/shell/probe.js +34 -0
  37. package/dist/shell/probe.js.map +1 -0
  38. package/dist/standalone/wave3d.standalone.js +13507 -0
  39. package/dist/standalone.d.ts +13 -0
  40. package/dist/standalone.js +17 -0
  41. package/dist/standalone.js.map +1 -0
  42. package/dist/studio/StudioWaveRenderer.d.ts +187 -0
  43. package/dist/studio/StudioWaveRenderer.js +905 -0
  44. package/dist/studio/StudioWaveRenderer.js.map +1 -0
  45. package/dist/studio/index.d.ts +3 -0
  46. package/dist/studio/index.js +3 -0
  47. package/dist/studio/randomize.d.ts +28 -0
  48. package/dist/studio/randomize.js +264 -0
  49. package/dist/studio/randomize.js.map +1 -0
  50. package/dist/util/base64.js +14 -0
  51. package/dist/util/base64.js.map +1 -0
  52. package/dist/util/math.js +18 -0
  53. package/dist/util/math.js.map +1 -0
  54. package/package.json +76 -0
  55. package/skills/wave3d/SKILL.md +158 -0
@@ -0,0 +1,158 @@
1
+ ---
2
+ name: wave3d
3
+ description: >
4
+ Add an animated 3D gradient "wave of light" (the glossy twisting ribbon seen across Stripe's
5
+ designs) to a website as a drop-in component, powered by three.js/WebGL. Load this when a user
6
+ wants a @wave3d package — @wave3d/react (<Wave3D>), @wave3d/element (<wave-3d>), or @wave3d/core
7
+ (createWave / mountWave) — or asks for an animated gradient hero background, a poster-first lazy
8
+ WebGL wave, a CDN <script> wave, or how to reproduce a wave exported from Wave Studio.
9
+ metadata:
10
+ type: core
11
+ library: "@wave3d/core"
12
+ library_version: "0.1.0"
13
+ sources:
14
+ - "wave3d/wave3d:README.md"
15
+ - "wave3d/wave3d:packages/core/src/config/model.ts"
16
+ - "wave3d/wave3d:packages/core/src/shell/createWave.ts"
17
+ - "wave3d/wave3d:packages/core/src/presets.ts"
18
+ ---
19
+
20
+ # @wave3d — drop-in animated 3D gradient waves
21
+
22
+ A self-optimizing gradient wave for the web: it shows a **poster first**, then **lazily** upgrades
23
+ to the live WebGL wave only when the browser can actually run it — falling back to the poster on
24
+ no-WebGL / Save-Data / reduced-motion / context-loss — with **three.js code-split out of the initial
25
+ load**. Framework-agnostic core, with React and web-component adapters.
26
+
27
+ ## When to use
28
+
29
+ - Adding an animated gradient hero / background / accent to a site (React, Vue, Svelte, plain HTML).
30
+ - Reproducing a wave designed in Wave Studio (paste the studio's "Export code" snippet).
31
+ - You need a WebGL background that is well-behaved: lazy, poster-fallback, reduced-motion aware.
32
+
33
+ ## Install
34
+
35
+ ```sh
36
+ pnpm add @wave3d/react @wave3d/core three # React
37
+ pnpm add @wave3d/element @wave3d/core three # <wave-3d> for Vue / Svelte / plain HTML
38
+ pnpm add @wave3d/core three # framework-agnostic createWave
39
+ ```
40
+
41
+ `three` is a **peer dependency** of `@wave3d/core` (`>=0.180 <1`). For TypeScript, also add
42
+ `@types/three` (three ships no types). Everything is **ESM-only** (`type: module`).
43
+
44
+ ## Choosing an entry
45
+
46
+ | Need | Use |
47
+ | ------------------------------------ | ------------------------------------------------------------------ |
48
+ | React | `import { Wave3D } from "@wave3d/react"` |
49
+ | Vue / Svelte / plain HTML | `import "@wave3d/element"` → `<wave-3d>` |
50
+ | Framework-agnostic, own DOM | `import { createWave } from "@wave3d/core"` (the poster shell) |
51
+ | Direct renderer (no shell/poster) | `import { WaveRenderer } from "@wave3d/core/renderer"` |
52
+ | One `<script>` from a CDN (three in) | `import { mountWave } from "@wave3d/core/standalone"` (via esm.sh) |
53
+ | Built-in presets | `import { PRESETS } from "@wave3d/core/presets"` |
54
+
55
+ The `.` entry (`@wave3d/core`) has **no static three import** — the engine arrives via a dynamic
56
+ import, so bundlers keep three out of your initial chunk until a wave actually upgrades.
57
+
58
+ ## Quick starts
59
+
60
+ **React**
61
+
62
+ ```tsx
63
+ import { Wave3D } from "@wave3d/react";
64
+
65
+ <Wave3D preset="Hero" poster="/wave.png" style={{ width: "100%", aspectRatio: "16 / 9" }} />;
66
+ ```
67
+
68
+ **Web component** (Vue / Svelte / HTML)
69
+
70
+ ```html
71
+ <script type="module">
72
+ import "@wave3d/element";
73
+ </script>
74
+ <wave-3d
75
+ preset="Hero"
76
+ poster="/wave.png"
77
+ style="display:block;width:100%;aspect-ratio:16/9"
78
+ ></wave-3d>
79
+ ```
80
+
81
+ **Vanilla / core**
82
+
83
+ ```ts
84
+ import { createWave } from "@wave3d/core";
85
+
86
+ const handle = createWave(
87
+ document.getElementById("wave"),
88
+ {
89
+ /* config */
90
+ },
91
+ { poster: "/wave.png" },
92
+ );
93
+ // handle: { state, renderer, set(config), play(), pause(), destroy() }
94
+ ```
95
+
96
+ ## Config model
97
+
98
+ A wave is one JSON-serializable `StudioConfig`: scene fields (`background`, `quality`, `dprMax`,
99
+ `loopSeconds`, `paused`, camera…) plus a `waves: WaveConfig[]` array (each wave has its own
100
+ `palette`, `fiberCount`, `speed`, `displaceAmount`, `twist…`, `blendMode`, `theme`, transform…).
101
+ Omitted fields fall back to `createDefaultConfig()`.
102
+
103
+ **React flat props** are a shortcut mapped onto `waves[0]` and the scene:
104
+ `palette` (`string[]` | `ColorStop[]`), `fiberCount`, `fiberStrength`, `sheen`, `iridescence`,
105
+ `displaceAmount`, `speed`, `opacity`, `blendMode`, `theme` → the first wave; `background`,
106
+ `transparentBackground`, `quality`, `dprMax`, `loopSeconds`, `introRamp`, `paused` → the scene.
107
+ **Precedence: default ← preset ← flat props ← `config`** (the `config` prop wins).
108
+
109
+ The studio's **Export code** button generates a ready-made snippet (a minimal config diff + a
110
+ poster) for every entry — the fastest way to hand a designed wave to a developer.
111
+
112
+ ## Presets
113
+
114
+ 13 built-in presets (`@wave3d/core/presets`): **Hero**, **Wave 2**, **Wave 3**, **Wave 4**,
115
+ **Wireframe**, **Neon Dark Multistrand**, **Mesh Gradient**, **Solar Bloom**, **Holographic**,
116
+ **Aurora**, **Palestine**, **Vaporwave Sunset**, **Kaleidoscope**.
117
+
118
+ - React: `preset="Hero"` (a **string** lazy-imports the presets chunk) or
119
+ `preset={() => PRESETS["Hero"]()}` (a **function** is tree-shakeable — bundles only that preset).
120
+ - Core/element: `createWave(el, PRESETS["Hero"]())` or `<wave-3d preset="Hero">`.
121
+
122
+ ## Poster & fallback recipe
123
+
124
+ The shell shows a poster immediately, then crossfades to the live wave.
125
+
126
+ - **Poster source:** the `poster` option/prop (URL or data-URI), or — for SSR — an
127
+ `<img data-wave3d-poster>` you render inside the container; the shell **adopts** it (no hydration
128
+ flash). React: pass it as a child. Generate a poster from the studio's Export code dialog.
129
+ - **`onFallback(reason)`** fires when the shell keeps the poster instead of upgrading; reasons:
130
+ `"no-webgl" | "reduced-motion" | "save-data" | "context-lost" | "load-error"`.
131
+ - **`onStateChange(state)`**: `"poster" → "loading" → "running"`, or `"fallback"`.
132
+
133
+ ## Performance
134
+
135
+ - Lazy by default (`lazy: true`, IntersectionObserver, `rootMargin: "200px"`) — the wave (and three)
136
+ only load near the viewport.
137
+ - Honors **Save-Data** (permanent poster) and **prefers-reduced-motion** (a frozen full frame;
138
+ `reducedMotionBehavior: "poster"` to show the poster instead) — both on by default.
139
+ - `dprMax` clamps device-pixel-ratio (default 2). `quality` and `waves.length` changing forces a
140
+ geometry **rebuild** (costlier than a uniform refresh); `fiberCount`, `loopSeconds` (0 = off),
141
+ and `paused` are cheap. The renderer already pauses offscreen and when the tab is hidden.
142
+
143
+ ## SSR / Next.js
144
+
145
+ - `@wave3d/react` is already marked `"use client"` — import it directly in a client component.
146
+ - All packages are **import-safe under Node** (no top-level DOM access; `@wave3d/element`'s
147
+ self-register is guarded), so SSR / RSC imports don't throw. The canvas only mounts client-side.
148
+ - Render a `<div>` with an `<img data-wave3d-poster>` child on the server for a zero-flash poster.
149
+
150
+ ## Pitfalls
151
+
152
+ - **three is a peer** — you must install it (`>=0.180 <1`); `@types/three` for TypeScript.
153
+ - **The container needs a size** — the wave fills it; give it width/height (e.g. `aspect-ratio`).
154
+ - **Don't recreate per render** — in React, changing flat props/`config` updates the live wave in
155
+ place; only a remount (or `handle.destroy()`) tears it down. (StrictMode double-mount is safe.)
156
+ - **`waves` replaces wholesale** — config merges are shallow, so a `waves` array you pass replaces
157
+ the default; include complete wave objects (the Export-code diff already does this).
158
+ - **reduced-motion defaults to true** — a motion-sensitive visitor sees a static frame, not motion.