@wave3d/core 0.2.0 โ 0.2.2
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 +25 -19
- package/dist/studio/index.d.ts +2 -1
- package/dist/studio/index.js +2 -1
- package/dist/studio/thumbnail.d.ts +14 -0
- package/dist/studio/thumbnail.js +32 -0
- package/dist/studio/thumbnail.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# @wave3d/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The framework-agnostic renderer and config model behind [Wave Studio](https://wave-studio.pages.dev): glossy, twisting 3D gradient waves driven by one JSON config.
|
|
4
4
|
|
|
5
|
-
A
|
|
5
|
+
A wave is a strip swept along a curve, with a gradient running down its length and a satin sheen. The renderer and every export read from the same `WaveConfig`, so what you design is exactly what ships.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> ๐ก Fastest way in: design a wave in **[Wave Studio](https://wave-studio.pages.dev)**, hit **โจโฉ Export code**, and copy the snippet. This package is what that snippet imports.
|
|
8
|
+
|
|
9
|
+
## ๐ฆ Install
|
|
8
10
|
|
|
9
11
|
```sh
|
|
10
12
|
pnpm add @wave3d/core three # three is a peer dependency
|
|
@@ -12,9 +14,9 @@ pnpm add @wave3d/core three # three is a peer dependency
|
|
|
12
14
|
|
|
13
15
|
`three` is a peer dependency (`>=0.180 <1`); add `@types/three` for TypeScript.
|
|
14
16
|
|
|
15
|
-
## Drop-in wave
|
|
17
|
+
## Drop-in wave
|
|
16
18
|
|
|
17
|
-
The
|
|
19
|
+
The default entry is poster-first: it shows a poster immediately, then upgrades to live WebGL only when the browser can run it. It falls back to the poster on no-WebGL, Save-Data, reduced motion, or a lost context, and `three.js` is code-split out of the initial load.
|
|
18
20
|
|
|
19
21
|
```ts
|
|
20
22
|
import { createWave } from "@wave3d/core";
|
|
@@ -25,41 +27,45 @@ const handle = createWave(document.getElementById("wave"), config, {
|
|
|
25
27
|
// handle.set(nextConfig) ยท handle.pause() ยท handle.play() ยท handle.snapshot() ยท handle.destroy()
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
Capture the live frame as an image
|
|
30
|
+
Capture the live frame as an image you can host and reuse as the poster for reduced-motion, no-WebGL, and Save-Data visitors:
|
|
29
31
|
|
|
30
32
|
```ts
|
|
31
|
-
const blob = await handle.snapshot(); // options: { type?, quality?, transparent? }
|
|
33
|
+
const blob = await handle.snapshot(); // resolves null until running. options: { type?, quality?, transparent? }
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
## Single `<script>` from a CDN
|
|
36
|
+
## Single `<script>` from a CDN
|
|
37
|
+
|
|
38
|
+
`three` is bundled into the standalone build, so this needs nothing else:
|
|
35
39
|
|
|
36
40
|
```html
|
|
37
41
|
<script type="module">
|
|
38
42
|
import { mountWave } from "https://esm.sh/@wave3d/core/standalone";
|
|
39
43
|
mountWave(document.getElementById("wave"), {
|
|
40
|
-
/* config */
|
|
44
|
+
/* your exported config */
|
|
41
45
|
});
|
|
42
46
|
</script>
|
|
43
47
|
```
|
|
44
48
|
|
|
45
49
|
## Entry points
|
|
46
50
|
|
|
47
|
-
| Import | What
|
|
48
|
-
| ------------------------- |
|
|
49
|
-
| `@wave3d/core` | poster-first shell (`createWave
|
|
50
|
-
| `@wave3d/core/renderer` | the raw `WaveRenderer`
|
|
51
|
-
| `@wave3d/core/presets` | the built-in `PRESETS`
|
|
52
|
-
| `@wave3d/core/studio` | `StudioWaveRenderer` + randomizers
|
|
53
|
-
| `@wave3d/core/standalone` | single-file build with three bundled (the CDN entry)
|
|
51
|
+
| Import | What |
|
|
52
|
+
| ------------------------- | -------------------------------------------------------------- |
|
|
53
|
+
| `@wave3d/core` | poster-first shell (`createWave` / `mountWave`) + config model |
|
|
54
|
+
| `@wave3d/core/renderer` | the raw `WaveRenderer` and `WaveGeometry` (static three) |
|
|
55
|
+
| `@wave3d/core/presets` | the built-in `PRESETS` |
|
|
56
|
+
| `@wave3d/core/studio` | `StudioWaveRenderer` + randomizers |
|
|
57
|
+
| `@wave3d/core/standalone` | single-file build with three bundled (the CDN entry) |
|
|
54
58
|
|
|
55
59
|
## Framework wrappers
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
Prefer a component? Reach for the wrapper for your framework:
|
|
62
|
+
|
|
63
|
+
- **React** โ [`@wave3d/react`](https://www.npmjs.com/package/@wave3d/react): the `<Wave3D>` component.
|
|
64
|
+
- **Vue, Svelte, or plain HTML** โ [`@wave3d/element`](https://www.npmjs.com/package/@wave3d/element): the `<wave-3d>` custom element.
|
|
59
65
|
|
|
60
66
|
## Credits
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
Built by [Amir Abushanab](https://github.com/Amir-Abushanab).
|
|
63
69
|
|
|
64
70
|
## License
|
|
65
71
|
|
package/dist/studio/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { randomizeBackground, randomizeColor, randomizeConfig, randomizeFinish, randomizeGlobal, randomizeGradient, randomizeLights, randomizeSpine, randomizeTransform, randomizeTwist, randomizeWave } from "./randomize.js";
|
|
2
2
|
import { StudioWaveRenderer } from "./StudioWaveRenderer.js";
|
|
3
|
-
|
|
3
|
+
import { createThumbHost, prepThumbConfig, renderThumbFrame } from "./thumbnail.js";
|
|
4
|
+
export { StudioWaveRenderer, createThumbHost, prepThumbConfig, randomizeBackground, randomizeColor, randomizeConfig, randomizeFinish, randomizeGlobal, randomizeGradient, randomizeLights, randomizeSpine, randomizeTransform, randomizeTwist, randomizeWave, renderThumbFrame };
|
package/dist/studio/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { randomizeBackground, randomizeColor, randomizeConfig, randomizeFinish, randomizeGlobal, randomizeGradient, randomizeLights, randomizeSpine, randomizeTransform, randomizeTwist, randomizeWave } from "./randomize.js";
|
|
2
2
|
import { StudioWaveRenderer } from "./StudioWaveRenderer.js";
|
|
3
|
-
|
|
3
|
+
import { createThumbHost, prepThumbConfig, renderThumbFrame } from "./thumbnail.js";
|
|
4
|
+
export { StudioWaveRenderer, createThumbHost, prepThumbConfig, randomizeBackground, randomizeColor, randomizeConfig, randomizeFinish, randomizeGlobal, randomizeGradient, randomizeLights, randomizeSpine, randomizeTransform, randomizeTwist, randomizeWave, renderThumbFrame };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StudioConfig } from "../config/model.js";
|
|
2
|
+
import { WaveRenderer } from "../renderer/WaveRenderer.js";
|
|
3
|
+
|
|
4
|
+
//#region src/studio/thumbnail.d.ts
|
|
5
|
+
/** A hidden host div that is in layout (so clientWidth/Height are real) but off-screen. */
|
|
6
|
+
declare function createThumbHost(width: number, height: number): HTMLDivElement;
|
|
7
|
+
/** Mutate `cfg` for a thumbnail still: static frame, opaque, white page behind solid themes
|
|
8
|
+
* (wireframe keys its between-line colour off the dark page background, so keep it). */
|
|
9
|
+
declare function prepThumbConfig(cfg: StudioConfig): void;
|
|
10
|
+
/** Render the current config to a fresh 2D canvas (null if the WebGL canvas is missing). */
|
|
11
|
+
declare function renderThumbFrame(renderer: WaveRenderer, host: HTMLElement): HTMLCanvasElement | null;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { createThumbHost, prepThumbConfig, renderThumbFrame };
|
|
14
|
+
//# sourceMappingURL=thumbnail.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/studio/thumbnail.ts
|
|
2
|
+
/** A hidden host div that is in layout (so clientWidth/Height are real) but off-screen. */
|
|
3
|
+
function createThumbHost(width, height) {
|
|
4
|
+
const host = document.createElement("div");
|
|
5
|
+
host.style.cssText = `position:fixed;left:-10000px;top:0;width:${width}px;height:${height}px;opacity:0;pointer-events:none;`;
|
|
6
|
+
document.body.appendChild(host);
|
|
7
|
+
return host;
|
|
8
|
+
}
|
|
9
|
+
/** Mutate `cfg` for a thumbnail still: static frame, opaque, white page behind solid themes
|
|
10
|
+
* (wireframe keys its between-line colour off the dark page background, so keep it). */
|
|
11
|
+
function prepThumbConfig(cfg) {
|
|
12
|
+
cfg.paused = true;
|
|
13
|
+
cfg.transparentBackground = false;
|
|
14
|
+
if (cfg.waves[0]?.theme !== "wireframe") cfg.background = "#ffffff";
|
|
15
|
+
}
|
|
16
|
+
/** Render the current config to a fresh 2D canvas (null if the WebGL canvas is missing). */
|
|
17
|
+
function renderThumbFrame(renderer, host) {
|
|
18
|
+
renderer.resize();
|
|
19
|
+
renderer.renderOnce();
|
|
20
|
+
renderer.renderOnce();
|
|
21
|
+
const gl = host.querySelector("canvas");
|
|
22
|
+
if (!gl) return null;
|
|
23
|
+
const out = document.createElement("canvas");
|
|
24
|
+
out.width = gl.width;
|
|
25
|
+
out.height = gl.height;
|
|
26
|
+
out.getContext("2d")?.drawImage(gl, 0, 0);
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { createThumbHost, prepThumbConfig, renderThumbFrame };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=thumbnail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thumbnail.js","names":[],"sources":["../../src/studio/thumbnail.ts"],"sourcesContent":["/**\n * Offscreen thumbnail rendering: turn a config into a still frame with one hidden, reused\n * WaveRenderer. Used by the studio's preset + history thumbnails and by the wave gallery grid.\n */\nimport type { WaveRenderer } from \"../renderer/WaveRenderer\";\nimport type { StudioConfig } from \"../config/model\";\n\n/** A hidden host div that is in layout (so clientWidth/Height are real) but off-screen. */\nexport function createThumbHost(width: number, height: number): HTMLDivElement {\n const host = document.createElement(\"div\");\n host.style.cssText = `position:fixed;left:-10000px;top:0;width:${width}px;height:${height}px;opacity:0;pointer-events:none;`;\n document.body.appendChild(host);\n return host;\n}\n\n/** Mutate `cfg` for a thumbnail still: static frame, opaque, white page behind solid themes\n * (wireframe keys its between-line colour off the dark page background, so keep it). */\nexport function prepThumbConfig(cfg: StudioConfig): void {\n cfg.paused = true;\n cfg.transparentBackground = false;\n if (cfg.waves[0]?.theme !== \"wireframe\") cfg.background = \"#ffffff\";\n}\n\n/** Render the current config to a fresh 2D canvas (null if the WebGL canvas is missing). */\nexport function renderThumbFrame(\n renderer: WaveRenderer,\n host: HTMLElement,\n): HTMLCanvasElement | null {\n renderer.resize();\n renderer.renderOnce();\n renderer.renderOnce(); // 2nd pass so any shader recompile (theme/blend variant) is applied\n const gl = host.querySelector(\"canvas\");\n if (!gl) return null;\n // Copy to a 2D canvas before encoding (reliable read of the WebGL drawing buffer).\n const out = document.createElement(\"canvas\");\n out.width = gl.width;\n out.height = gl.height;\n out.getContext(\"2d\")?.drawImage(gl, 0, 0);\n return out;\n}\n"],"mappings":";;AAQA,SAAgB,gBAAgB,OAAe,QAAgC;CAC7E,MAAM,OAAO,SAAS,cAAc,KAAK;CACzC,KAAK,MAAM,UAAU,4CAA4C,MAAM,YAAY,OAAO;CAC1F,SAAS,KAAK,YAAY,IAAI;CAC9B,OAAO;AACT;;;AAIA,SAAgB,gBAAgB,KAAyB;CACvD,IAAI,SAAS;CACb,IAAI,wBAAwB;CAC5B,IAAI,IAAI,MAAM,EAAE,EAAE,UAAU,aAAa,IAAI,aAAa;AAC5D;;AAGA,SAAgB,iBACd,UACA,MAC0B;CAC1B,SAAS,OAAO;CAChB,SAAS,WAAW;CACpB,SAAS,WAAW;CACpB,MAAM,KAAK,KAAK,cAAc,QAAQ;CACtC,IAAI,CAAC,IAAI,OAAO;CAEhB,MAAM,MAAM,SAAS,cAAc,QAAQ;CAC3C,IAAI,QAAQ,GAAG;CACf,IAAI,SAAS,GAAG;CAChB,IAAI,WAAW,IAAI,CAAC,EAAE,UAAU,IAAI,GAAG,CAAC;CACxC,OAAO;AACT"}
|