@particle-academy/fancy-3d-babylon 0.2.0 → 0.2.1
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/CHANGELOG.md +97 -0
- package/LICENSE +21 -0
- package/dist/react.cjs +4 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +4 -1
- package/dist/react.js.map +1 -1
- package/package.json +10 -8
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@particle-academy/fancy-3d-babylon` are documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
|
|
7
|
+
> **Pre-1.0:** breaking changes land in MINOR releases. Until 1.0 the minor
|
|
8
|
+
> number is not a compatibility promise — read the entry, not the version.
|
|
9
|
+
|
|
10
|
+
> This file starts here. Earlier releases predate it and were never written up;
|
|
11
|
+
> `git log` is the record for those. It is not backfilled rather than
|
|
12
|
+
> guessed-at, because a changelog that invents its own history is worse than one
|
|
13
|
+
> that admits where it begins.
|
|
14
|
+
|
|
15
|
+
## [Unreleased]
|
|
16
|
+
|
|
17
|
+
## 0.2.1 — 2026-11-13
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **Releases need a lab-run certificate.** `publish.yml` gains a read-only
|
|
22
|
+
`lab-certificate` job that every publishing job needs: a tag is published only
|
|
23
|
+
when the fancy-labs lab has certified that exact version and commit. Consumers
|
|
24
|
+
do nothing; this changes how releases are cut, not what the package does.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- **The `<Stage>` canvas now shows a keyboard focus ring.** It was focusable (`tabIndex=0`, the camera controls listen on it) but carried an inline `outline: none`, so a keyboard user tabbing onto it saw nothing. `<Stage>` now renders a scoped `<style>` giving the canvas, marked `data-fancy-3d-canvas`, an inset `:focus-visible` box-shadow ring in the kit focus token (`--fancy-focus`, dark `--fancy-focus-dark`, falling back to Tailwind blue-500/400). It is a box-shadow because the inline outline beats any stylesheet outline, and a `<style>` rather than Tailwind classes because a consumer's Tailwind is not guaranteed to scan this package. Nothing to do; set `--fancy-focus` to restyle it.
|
|
29
|
+
|
|
30
|
+
- **`CHANGELOG.md` is now in the published tarball.** `files` did not whitelist it, so npm never shipped it — and this package puts breaking changes in MINOR releases and tells you in the README to read the entry before taking one. The instruction existed for the author, who has the file, and not for the consumer, who is the only one being instructed. Nothing for you to do; the file simply arrives from this release on.
|
|
31
|
+
|
|
32
|
+
### Security
|
|
33
|
+
|
|
34
|
+
- Update Vitest to 4.1.12 and patch the transitive undici development dependency for security fixes; dev toolchain only, nothing to do.
|
|
35
|
+
|
|
36
|
+
- `source-map-js` is pinned forward to `^1.2.2` via `overrides`. Versions up to
|
|
37
|
+
1.2.1 allow an event-loop denial of service through indexed source-map section
|
|
38
|
+
offsets, and it arrives here transitively through the build toolchain.
|
|
39
|
+
**Nothing for a consumer to do, and no runtime change**: an npm package does
|
|
40
|
+
not ship a lockfile, so this governs builds OF this repo, not anything
|
|
41
|
+
installed FROM it. Recorded rather than left silent because the override it
|
|
42
|
+
sits beside — `shell-quote` `^1.9.0`, added for an earlier advisory — was
|
|
43
|
+
carried with no note of why, and had drifted back inside the vulnerable range
|
|
44
|
+
before anyone looked.
|
|
45
|
+
- **Dev toolchain only — no runtime change, nothing for consumers to do.** The
|
|
46
|
+
lockfile now resolves `vite` 8.3.5 (was 8.2.2), whose bundled
|
|
47
|
+
`launch-editor` fixes GHSA-587h-7wmj-h5pm (HIGH, `fs.existsSync()` check
|
|
48
|
+
bypassable on Windows), GHSA-698v-4r3x-3vcv (`escapeCmdArgs()` omits `%`
|
|
49
|
+
escaping on Windows) and GHSA-r825-w8mm-5pxw (editor CLI flag
|
|
50
|
+
misinterpretation). `vite` is only reached through the test/dev toolchain
|
|
51
|
+
and the published package does not ship our lockfile, so the exposure was
|
|
52
|
+
this repo's own dev server.
|
|
53
|
+
|
|
54
|
+
## 0.2.0 — 2026-08-07
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- **BREAKING — Node 22 is no longer supported.** `engines.node` moves from `>=22` to `>=22`.
|
|
59
|
+
|
|
60
|
+
**What you must do:** on Node 22 or newer, nothing. Note npm only *warns* on an `engines` mismatch while **pnpm fails the install**, so this surfaces differently depending on your package manager. Node 18 is end-of-life and 20 is maintenance-only.
|
|
61
|
+
|
|
62
|
+
- **BREAKING — React 18 is no longer supported.** `peerDependencies.react` / `react-dom` are now `^19.0.0`.
|
|
63
|
+
|
|
64
|
+
**What you must do:** on React 19, nothing. On React 18, stay on the previous release, or upgrade your app to 19 first.
|
|
65
|
+
|
|
66
|
+
React 18 support was a claim nothing tested — every build and test in this package ran against 19, so the 18 half of the old range was never executed. An untested compatibility claim is worse than an absent one, because it reads as support.
|
|
67
|
+
|
|
68
|
+
### Why
|
|
69
|
+
|
|
70
|
+
These are the kit 0.5 platform floors, applied across every package at once so a consumer never has to resolve a mix. **No API changed, nothing was removed, nothing was renamed** — only what the package requires.
|
|
71
|
+
|
|
72
|
+
## 0.1.2 — 2026-06-15
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
|
|
76
|
+
- granular @babylonjs/core imports for tree-shaking
|
|
77
|
+
|
|
78
|
+
## 0.1.1 — 2026-06-02
|
|
79
|
+
|
|
80
|
+
- Maintenance only (2 internal commits).
|
|
81
|
+
|
|
82
|
+
## 0.1.0 — 2026-05-27
|
|
83
|
+
|
|
84
|
+
- Maintenance only (2 internal commits).
|
|
85
|
+
|
|
86
|
+
### Changed
|
|
87
|
+
|
|
88
|
+
- Widened the `@particle-academy/fancy-3d` requirement from `^0.4.0` to `>=0.4 <2.0`, so a
|
|
89
|
+
sibling minor release is an upgrade and not a resolver conflict. **No action
|
|
90
|
+
needed** — widening a range only adds candidates; the version you have today
|
|
91
|
+
still resolves.
|
|
92
|
+
|
|
93
|
+
A caret on a `0.x` range locks the MINOR, so this pinned a sibling at
|
|
94
|
+
whatever it happened to be on the day it was written, and each sibling
|
|
95
|
+
release then read as a conflict to the resolver rather than an upgrade.
|
|
96
|
+
Nothing here was using an API the newer minors removed — the range was the
|
|
97
|
+
whole problem.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Particle Academy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/react.cjs
CHANGED
|
@@ -67,6 +67,7 @@ function useStage() {
|
|
|
67
67
|
if (!ctx) throw new Error("useStage() must be called inside <Stage>");
|
|
68
68
|
return ctx;
|
|
69
69
|
}
|
|
70
|
+
var STAGE_FOCUS_CSS = '[data-fancy-3d-canvas]:focus-visible { box-shadow: inset 0 0 0 2px var(--fancy-focus, var(--color-blue-500, #3b82f6)); } :where(.dark, [data-theme="dark"]) [data-fancy-3d-canvas]:focus-visible { box-shadow: inset 0 0 0 2px var(--fancy-focus-dark, var(--color-blue-400, #60a5fa)); }';
|
|
70
71
|
function Stage({
|
|
71
72
|
children,
|
|
72
73
|
cameraRadius = 10,
|
|
@@ -144,12 +145,14 @@ function Stage({
|
|
|
144
145
|
style: { position: "relative", overflow: "hidden", ...style },
|
|
145
146
|
"data-fancy-3d-stage": "",
|
|
146
147
|
children: [
|
|
148
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { "data-fancy-3d-stage-css": "", children: STAGE_FOCUS_CSS }),
|
|
147
149
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
148
150
|
"canvas",
|
|
149
151
|
{
|
|
150
152
|
ref: canvasRef,
|
|
151
153
|
style: { display: "block", width: "100%", height: "100%", outline: "none" },
|
|
152
|
-
tabIndex: 0
|
|
154
|
+
tabIndex: 0,
|
|
155
|
+
"data-fancy-3d-canvas": ""
|
|
153
156
|
}
|
|
154
157
|
),
|
|
155
158
|
/* @__PURE__ */ jsxRuntime.jsx(
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.tsx"],"names":["createContext","useContext","useRef","useState","useEffect","engine","Engine","scene","BJScene","Color4","ArcRotateCamera","Vector3","HemisphericLight","Color3","DirectionalLight","jsxs","jsx","MeshBuilder","StandardMaterial","Mesh","Matrix","useLayoutEffect"],"mappings":"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","file":"react.cjs","sourcesContent":["/**\n * `<Stage>` and `<Monitor>` — declarative React API for fancy-3d.\n *\n * <Stage>\n * <Monitor position={[0, 2, 0]} width={4} height={2.5}>\n * <Card>...real react-fancy components...</Card>\n * </Monitor>\n * </Stage>\n *\n * `<Stage>` owns the Babylon engine + scene + render loop and exposes them\n * via context. `<Monitor>` builds a bezel mesh, projects its world-space\n * corners to screen space each frame, and renders its children into a\n * positioned DOM overlay. Children are real React: full interactivity,\n * accessibility, and styling — no canvas-rasterized snapshot.\n\n * Renamed from `<Screen>` in v0.3.0 to free the name for\n * `@particle-academy/fancy-screens`'s `<Screen>` (containerized application\n * surface). The behavior here is unchanged.\n *\n * Tradeoffs of mount mode (vs. painted texture):\n * - Pro: live, interactive, perfect text rendering.\n * - Con: HTML overlay always renders on top of the WebGL canvas; depth\n * sorting against other 3D objects is approximate (we hide the overlay\n * when the mesh is behind the camera or fully occluded by frustum).\n */\n// Granular @babylonjs/core imports (not the barrel) for tree-shaking; each\n// non-\".pure\" module self-applies its side effects (camera inputs, shaders,\n// engine extensions), so `attachControl` / rendering behave exactly as before.\nimport { ArcRotateCamera } from \"@babylonjs/core/Cameras/arcRotateCamera\";\nimport { Color3, Color4 } from \"@babylonjs/core/Maths/math.color\";\nimport { DirectionalLight } from \"@babylonjs/core/Lights/directionalLight\";\nimport { Engine } from \"@babylonjs/core/Engines/engine\";\nimport { HemisphericLight } from \"@babylonjs/core/Lights/hemisphericLight\";\nimport { Matrix, Vector3 } from \"@babylonjs/core/Maths/math.vector\";\nimport { Mesh } from \"@babylonjs/core/Meshes/mesh\";\nimport { MeshBuilder } from \"@babylonjs/core/Meshes/meshBuilder\";\nimport { Scene as BJScene } from \"@babylonjs/core/scene\";\nimport { StandardMaterial } from \"@babylonjs/core/Materials/standardMaterial\";\nimport type { Camera } from \"@babylonjs/core/Cameras/camera\";\nimport {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* 2D perspective transform — maps a unit rectangle to a 4-point quad */\n/* via a 3x3 homography, packed into a CSS matrix3d for transform. */\n/* ------------------------------------------------------------------ */\n\ntype Mat3 = [number, number, number, number, number, number, number, number, number];\n\nfunction adj3(m: Mat3): Mat3 {\n return [\n m[4] * m[8] - m[5] * m[7], m[2] * m[7] - m[1] * m[8], m[1] * m[5] - m[2] * m[4],\n m[5] * m[6] - m[3] * m[8], m[0] * m[8] - m[2] * m[6], m[2] * m[3] - m[0] * m[5],\n m[3] * m[7] - m[4] * m[6], m[1] * m[6] - m[0] * m[7], m[0] * m[4] - m[1] * m[3],\n ];\n}\n\nfunction multmm(a: Mat3, b: Mat3): Mat3 {\n const c: number[] = new Array(9);\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n let cij = 0;\n for (let k = 0; k < 3; k++) cij += a[3 * i + k] * b[3 * k + j];\n c[3 * i + j] = cij;\n }\n }\n return c as Mat3;\n}\n\nfunction multmv(m: Mat3, v: [number, number, number]): [number, number, number] {\n return [\n m[0] * v[0] + m[1] * v[1] + m[2] * v[2],\n m[3] * v[0] + m[4] * v[1] + m[5] * v[2],\n m[6] * v[0] + m[7] * v[1] + m[8] * v[2],\n ];\n}\n\nfunction basisToPoints(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): Mat3 {\n const m: Mat3 = [x1, x2, x3, y1, y2, y3, 1, 1, 1];\n const v = multmv(adj3(m), [x4, y4, 1]);\n return multmm(m, [v[0], 0, 0, 0, v[1], 0, 0, 0, v[2]]);\n}\n\n/** Compute a homography that maps (0,0)→p1, (w,0)→p2, (w,h)→p3, (0,h)→p4. */\nfunction quadToQuad(\n w: number, h: number,\n x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number\n): Mat3 {\n const s = basisToPoints(0, 0, w, 0, w, h, 0, h);\n const d = basisToPoints(x1, y1, x2, y2, x3, y3, x4, y4);\n const t = multmm(d, adj3(s));\n // Normalize so t[8] is 1\n const n = t[8];\n for (let i = 0; i < 9; i++) t[i] /= n;\n return t;\n}\n\n/** Pack a 3x3 homography into a CSS matrix3d() string. */\nfunction matrix3dString(t: Mat3): string {\n return `matrix3d(${t[0]}, ${t[3]}, 0, ${t[6]}, ${t[1]}, ${t[4]}, 0, ${t[7]}, 0, 0, 1, 0, ${t[2]}, ${t[5]}, 0, ${t[8]})`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Stage context */\n/* ------------------------------------------------------------------ */\n\ninterface StageContextValue {\n engine: Engine;\n scene: BJScene;\n /** The HTML <canvas> the engine renders into — its bounding rect anchors overlays. */\n canvas: HTMLCanvasElement;\n /** Subscribe to per-frame ticks. Returns an unsubscribe fn. */\n onFrame(cb: () => void): () => void;\n /** The DOM container that screen overlays mount into. */\n overlayRoot: HTMLDivElement;\n}\n\nconst StageContext = createContext<StageContextValue | null>(null);\n\nexport function useStage(): StageContextValue {\n const ctx = useContext(StageContext);\n if (!ctx) throw new Error(\"useStage() must be called inside <Stage>\");\n return ctx;\n}\n\n/* ------------------------------------------------------------------ */\n/* Stage */\n/* ------------------------------------------------------------------ */\n\nexport interface StageProps {\n children?: ReactNode;\n /** Initial camera radius. Defaults to 10. */\n cameraRadius?: number;\n /** Initial camera target. Defaults to (0, 1.5, 0). */\n cameraTarget?: [number, number, number];\n /** Initial camera alpha (horizontal angle). Defaults to π/2. */\n cameraAlpha?: number;\n /** Initial camera beta (vertical angle). Defaults to π/2.4. */\n cameraBeta?: number;\n /** Background clear color. Defaults to a near-black. */\n clearColor?: string;\n /** Disable the default lights / camera if you want to set your own. */\n bare?: boolean;\n /** Callback after the scene is created — set up custom cameras, lights, meshes. */\n onReady?: (scene: BJScene) => void;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function Stage({\n children,\n cameraRadius = 10,\n cameraTarget = [0, 1.5, 0],\n cameraAlpha = Math.PI / 2,\n cameraBeta = Math.PI / 2.4,\n clearColor = \"#06080f\",\n bare = false,\n onReady,\n className,\n style,\n}: StageProps) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const [stage, setStage] = useState<StageContextValue | null>(null);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const overlay = overlayRef.current;\n if (!canvas || !overlay) return;\n\n const engine = new Engine(canvas, true, { stencil: true, preserveDrawingBuffer: true });\n const scene = new BJScene(engine);\n const c = Color4.FromHexString(clearColor);\n scene.clearColor = new Color4(c.r, c.g, c.b, 1);\n\n if (!bare) {\n const cam = new ArcRotateCamera(\n \"fancy3d-cam\",\n cameraAlpha,\n cameraBeta,\n cameraRadius,\n new Vector3(...cameraTarget),\n scene\n );\n cam.attachControl(canvas, true);\n cam.lowerRadiusLimit = 1;\n cam.upperRadiusLimit = 80;\n cam.wheelDeltaPercentage = 0.01;\n cam.upperBetaLimit = Math.PI / 2 - 0.05;\n\n const hemi = new HemisphericLight(\"fancy3d-hemi\", new Vector3(0, 1, 0), scene);\n hemi.intensity = 0.7;\n hemi.diffuse = new Color3(0.7, 0.78, 1);\n hemi.groundColor = new Color3(0.1, 0.1, 0.18);\n\n const dir = new DirectionalLight(\"fancy3d-dir\", new Vector3(-0.4, -1, -0.6), scene);\n dir.intensity = 0.6;\n }\n\n onReady?.(scene);\n\n const frameSubs = new Set<() => void>();\n scene.onBeforeRenderObservable.add(() => {\n frameSubs.forEach((cb) => cb());\n });\n\n engine.runRenderLoop(() => scene.render());\n const handleResize = () => engine.resize();\n window.addEventListener(\"resize\", handleResize);\n\n setStage({\n engine,\n scene,\n canvas,\n overlayRoot: overlay,\n onFrame(cb) {\n frameSubs.add(cb);\n return () => frameSubs.delete(cb);\n },\n });\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n engine.dispose();\n setStage(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ position: \"relative\", overflow: \"hidden\", ...style }}\n data-fancy-3d-stage=\"\"\n >\n <canvas\n ref={canvasRef}\n style={{ display: \"block\", width: \"100%\", height: \"100%\", outline: \"none\" }}\n tabIndex={0}\n />\n <div\n ref={overlayRef}\n style={{ position: \"absolute\", inset: 0, pointerEvents: \"none\" }}\n data-fancy-3d-overlay-root=\"\"\n />\n {stage && <StageContext.Provider value={stage}>{children}</StageContext.Provider>}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Monitor — interactive mount point on a 3D mesh */\n/* ------------------------------------------------------------------ */\n\nexport interface MonitorProps {\n children?: ReactNode;\n /** World-space center of the screen. */\n position: [number, number, number];\n /** Mesh dimensions in world units. */\n width: number;\n height: number;\n /** Y-axis rotation in radians. */\n rotationY?: number;\n /** Bezel color. Defaults to a near-black frame. */\n bezel?: string;\n /** Bezel thickness in world units. Defaults to 0.06. */\n bezelThickness?: number;\n /** Background color visible behind the React content. */\n background?: string;\n /** Design-time pixel width for the children. Defaults to `width * 360`. */\n pixelWidth?: number;\n /** Design-time pixel height for the children. Defaults to `height * 360`. */\n pixelHeight?: number;\n /** Optional name on the Babylon mesh. */\n name?: string;\n}\n\nexport function Monitor({\n children,\n position,\n width,\n height,\n rotationY = 0,\n bezel = \"#0b0f17\",\n bezelThickness = 0.06,\n background = \"#0b1220\",\n pixelWidth,\n pixelHeight,\n name = \"screen\",\n}: MonitorProps) {\n const stage = useStage();\n const meshRef = useRef<Mesh | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n // Design-time pixel size for the children. The matrix3d transform maps\n // this unit rectangle onto the projected mesh quad each frame.\n const innerSize = useRef({\n w: pixelWidth ?? Math.max(120, Math.round(width * 360)),\n h: pixelHeight ?? Math.max(80, Math.round(height * 360)),\n });\n\n // Build the bezel + invisible projection-target plane.\n useEffect(() => {\n const { scene } = stage;\n const bezelMesh = MeshBuilder.CreateBox(`${name}-bezel`, {\n width: width + bezelThickness * 2,\n height: height + bezelThickness * 2,\n depth: bezelThickness,\n }, scene);\n bezelMesh.position = new Vector3(position[0], position[1], position[2]);\n bezelMesh.rotation.y = rotationY;\n const bezelMat = new StandardMaterial(`${name}-bezel-mat`, scene);\n bezelMat.diffuseColor = Color3.FromHexString(bezel);\n bezelMat.specularColor = new Color3(0.05, 0.05, 0.05);\n bezelMesh.material = bezelMat;\n\n // Inner pane the overlay tracks. Its background fills behind the React\n // overlay (in case the overlay is briefly mispositioned); the React\n // children are stamped on top.\n const pane = MeshBuilder.CreatePlane(`${name}-pane`, { width, height, sideOrientation: Mesh.DOUBLESIDE }, scene);\n pane.position = new Vector3(position[0], position[1], position[2]);\n pane.rotation.y = rotationY;\n // The bezel's \"front\" face is on +Z (default camera sits on +Z). Offset\n // the pane forward of that face so the React HTML overlay lines up with\n // the visible front of the bezel rather than its hidden back.\n const forward = new Vector3(0, 0, 1);\n const rot = Matrix.RotationY(rotationY);\n const offset = Vector3.TransformNormal(forward.scale(bezelThickness / 2 + 0.001), rot);\n pane.position.addInPlace(offset);\n const paneMat = new StandardMaterial(`${name}-pane-mat`, scene);\n paneMat.diffuseColor = Color3.FromHexString(background);\n paneMat.emissiveColor = Color3.FromHexString(background).scale(0.4);\n pane.material = paneMat;\n pane.metadata = { fancy3d: \"screen\", screenName: name };\n meshRef.current = pane;\n\n return () => {\n pane.dispose();\n bezelMesh.dispose();\n meshRef.current = null;\n };\n }, [stage, name, width, height, bezel, bezelThickness, background, position, rotationY]);\n\n // Each frame: project the four mesh corners and apply the matrix3d\n // transform that maps the inner div's local pixel space to the projected\n // quad. Imperative — no React re-render per frame.\n useEffect(() => {\n const unsub = stage.onFrame(() => {\n const mesh = meshRef.current;\n const overlay = overlayRef.current;\n if (!mesh || !overlay) return;\n const cam = stage.scene.activeCamera;\n if (!cam) return;\n const engine = stage.engine;\n const renderW = engine.getRenderWidth();\n const renderH = engine.getRenderHeight();\n const viewport = cam.viewport.toGlobal(renderW, renderH);\n const tm = stage.scene.getTransformMatrix();\n const identity = Matrix.Identity();\n const wm = mesh.getWorldMatrix();\n\n const halfW = width / 2;\n const halfH = height / 2;\n // Mesh-local corners ordered: top-left, top-right, bottom-right, bottom-left.\n // Babylon's plane: +Y is up in world (when not rotated around X), so\n // mesh-local +Y = top.\n const localCorners = [\n new Vector3(-halfW, halfH, 0), // top-left\n new Vector3(halfW, halfH, 0), // top-right\n new Vector3(halfW, -halfH, 0), // bottom-right\n new Vector3(-halfW, -halfH, 0), // bottom-left\n ];\n const worldCorners = localCorners.map((v) => Vector3.TransformCoordinates(v, wm));\n\n // Edge-on cull only — hide overlay when the panel is nearly perpendicular\n // to the camera ray (where the projected quad collapses and matrix3d\n // becomes singular). The matrix3d transform handles both front and\n // back side rendering naturally, so we don't strictly cull by side.\n const camPos = cam.globalPosition;\n const right = worldCorners[1].subtract(worldCorners[0]);\n const up = worldCorners[0].subtract(worldCorners[3]);\n const normal = Vector3.Cross(up, right).normalize();\n const center = worldCorners[0].add(worldCorners[2]).scale(0.5);\n const toCam = camPos.subtract(center).normalize();\n const facing = Math.abs(Vector3.Dot(normal, toCam));\n\n const projected = worldCorners.map((c) => Vector3.Project(c, identity, tm, viewport));\n const inFrustum = projected.every((p) => p.z >= 0 && p.z <= 1);\n const visible = inFrustum && facing > 0.05;\n\n if (!visible) {\n if (overlay.style.display !== \"none\") overlay.style.display = \"none\";\n return;\n }\n\n // Depth-sort overlays: nearer-to-camera panels stack above farther ones.\n // Without this, DOM document order decides stacking and side screens\n // can render on top of the center screen even when 3D depth says\n // otherwise. NDC z is 0 at the near plane and 1 at the far plane, so\n // closer-to-camera = smaller z = higher z-index.\n const avgZ = (projected[0].z + projected[1].z + projected[2].z + projected[3].z) / 4;\n const depthZIndex = Math.round(Math.max(0, Math.min(1, 1 - avgZ)) * 100000);\n const zStr = String(depthZIndex);\n if (overlay.style.zIndex !== zStr) overlay.style.zIndex = zStr;\n\n const dpr = window.devicePixelRatio || 1;\n const w0 = innerSize.current.w;\n const h0 = innerSize.current.h;\n const t = quadToQuad(\n w0, h0,\n projected[0].x / dpr, projected[0].y / dpr,\n projected[1].x / dpr, projected[1].y / dpr,\n projected[2].x / dpr, projected[2].y / dpr,\n projected[3].x / dpr, projected[3].y / dpr\n );\n\n if (overlay.style.display !== \"block\") overlay.style.display = \"block\";\n overlay.style.transform = matrix3dString(t);\n });\n return unsub;\n }, [stage, width, height]);\n\n // Mount the overlay into the stage's overlay root.\n useLayoutEffect(() => {\n const el = overlayRef.current;\n if (!el) return;\n if (el.parentElement !== stage.overlayRoot) {\n stage.overlayRoot.appendChild(el);\n }\n return () => {\n if (el.parentElement === stage.overlayRoot) {\n stage.overlayRoot.removeChild(el);\n }\n };\n }, [stage]);\n\n return (\n <div\n ref={overlayRef}\n data-fancy-3d-screen={name}\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: innerSize.current.w,\n height: innerSize.current.h,\n transformOrigin: \"0 0\",\n pointerEvents: \"auto\",\n overflow: \"hidden\",\n background,\n borderRadius: 4,\n display: \"none\",\n }}\n >\n {children}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx"],"names":["createContext","useContext","useRef","useState","useEffect","engine","Engine","scene","BJScene","Color4","ArcRotateCamera","Vector3","HemisphericLight","Color3","DirectionalLight","jsxs","jsx","MeshBuilder","StandardMaterial","Mesh","Matrix","useLayoutEffect"],"mappings":"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","file":"react.cjs","sourcesContent":["/**\n * `<Stage>` and `<Monitor>` — declarative React API for fancy-3d.\n *\n * <Stage>\n * <Monitor position={[0, 2, 0]} width={4} height={2.5}>\n * <Card>...real react-fancy components...</Card>\n * </Monitor>\n * </Stage>\n *\n * `<Stage>` owns the Babylon engine + scene + render loop and exposes them\n * via context. `<Monitor>` builds a bezel mesh, projects its world-space\n * corners to screen space each frame, and renders its children into a\n * positioned DOM overlay. Children are real React: full interactivity,\n * accessibility, and styling — no canvas-rasterized snapshot.\n\n * Renamed from `<Screen>` in v0.3.0 to free the name for\n * `@particle-academy/fancy-screens`'s `<Screen>` (containerized application\n * surface). The behavior here is unchanged.\n *\n * Tradeoffs of mount mode (vs. painted texture):\n * - Pro: live, interactive, perfect text rendering.\n * - Con: HTML overlay always renders on top of the WebGL canvas; depth\n * sorting against other 3D objects is approximate (we hide the overlay\n * when the mesh is behind the camera or fully occluded by frustum).\n */\n// Granular @babylonjs/core imports (not the barrel) for tree-shaking; each\n// non-\".pure\" module self-applies its side effects (camera inputs, shaders,\n// engine extensions), so `attachControl` / rendering behave exactly as before.\nimport { ArcRotateCamera } from \"@babylonjs/core/Cameras/arcRotateCamera\";\nimport { Color3, Color4 } from \"@babylonjs/core/Maths/math.color\";\nimport { DirectionalLight } from \"@babylonjs/core/Lights/directionalLight\";\nimport { Engine } from \"@babylonjs/core/Engines/engine\";\nimport { HemisphericLight } from \"@babylonjs/core/Lights/hemisphericLight\";\nimport { Matrix, Vector3 } from \"@babylonjs/core/Maths/math.vector\";\nimport { Mesh } from \"@babylonjs/core/Meshes/mesh\";\nimport { MeshBuilder } from \"@babylonjs/core/Meshes/meshBuilder\";\nimport { Scene as BJScene } from \"@babylonjs/core/scene\";\nimport { StandardMaterial } from \"@babylonjs/core/Materials/standardMaterial\";\nimport type { Camera } from \"@babylonjs/core/Cameras/camera\";\nimport {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* 2D perspective transform — maps a unit rectangle to a 4-point quad */\n/* via a 3x3 homography, packed into a CSS matrix3d for transform. */\n/* ------------------------------------------------------------------ */\n\ntype Mat3 = [number, number, number, number, number, number, number, number, number];\n\nfunction adj3(m: Mat3): Mat3 {\n return [\n m[4] * m[8] - m[5] * m[7], m[2] * m[7] - m[1] * m[8], m[1] * m[5] - m[2] * m[4],\n m[5] * m[6] - m[3] * m[8], m[0] * m[8] - m[2] * m[6], m[2] * m[3] - m[0] * m[5],\n m[3] * m[7] - m[4] * m[6], m[1] * m[6] - m[0] * m[7], m[0] * m[4] - m[1] * m[3],\n ];\n}\n\nfunction multmm(a: Mat3, b: Mat3): Mat3 {\n const c: number[] = new Array(9);\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n let cij = 0;\n for (let k = 0; k < 3; k++) cij += a[3 * i + k] * b[3 * k + j];\n c[3 * i + j] = cij;\n }\n }\n return c as Mat3;\n}\n\nfunction multmv(m: Mat3, v: [number, number, number]): [number, number, number] {\n return [\n m[0] * v[0] + m[1] * v[1] + m[2] * v[2],\n m[3] * v[0] + m[4] * v[1] + m[5] * v[2],\n m[6] * v[0] + m[7] * v[1] + m[8] * v[2],\n ];\n}\n\nfunction basisToPoints(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): Mat3 {\n const m: Mat3 = [x1, x2, x3, y1, y2, y3, 1, 1, 1];\n const v = multmv(adj3(m), [x4, y4, 1]);\n return multmm(m, [v[0], 0, 0, 0, v[1], 0, 0, 0, v[2]]);\n}\n\n/** Compute a homography that maps (0,0)→p1, (w,0)→p2, (w,h)→p3, (0,h)→p4. */\nfunction quadToQuad(\n w: number, h: number,\n x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number\n): Mat3 {\n const s = basisToPoints(0, 0, w, 0, w, h, 0, h);\n const d = basisToPoints(x1, y1, x2, y2, x3, y3, x4, y4);\n const t = multmm(d, adj3(s));\n // Normalize so t[8] is 1\n const n = t[8];\n for (let i = 0; i < 9; i++) t[i] /= n;\n return t;\n}\n\n/** Pack a 3x3 homography into a CSS matrix3d() string. */\nfunction matrix3dString(t: Mat3): string {\n return `matrix3d(${t[0]}, ${t[3]}, 0, ${t[6]}, ${t[1]}, ${t[4]}, 0, ${t[7]}, 0, 0, 1, 0, ${t[2]}, ${t[5]}, 0, ${t[8]})`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Stage context */\n/* ------------------------------------------------------------------ */\n\ninterface StageContextValue {\n engine: Engine;\n scene: BJScene;\n /** The HTML <canvas> the engine renders into — its bounding rect anchors overlays. */\n canvas: HTMLCanvasElement;\n /** Subscribe to per-frame ticks. Returns an unsubscribe fn. */\n onFrame(cb: () => void): () => void;\n /** The DOM container that screen overlays mount into. */\n overlayRoot: HTMLDivElement;\n}\n\nconst StageContext = createContext<StageContextValue | null>(null);\n\nexport function useStage(): StageContextValue {\n const ctx = useContext(StageContext);\n if (!ctx) throw new Error(\"useStage() must be called inside <Stage>\");\n return ctx;\n}\n\n/* ------------------------------------------------------------------ */\n/* Stage */\n/* ------------------------------------------------------------------ */\n\nexport interface StageProps {\n children?: ReactNode;\n /** Initial camera radius. Defaults to 10. */\n cameraRadius?: number;\n /** Initial camera target. Defaults to (0, 1.5, 0). */\n cameraTarget?: [number, number, number];\n /** Initial camera alpha (horizontal angle). Defaults to π/2. */\n cameraAlpha?: number;\n /** Initial camera beta (vertical angle). Defaults to π/2.4. */\n cameraBeta?: number;\n /** Background clear color. Defaults to a near-black. */\n clearColor?: string;\n /** Disable the default lights / camera if you want to set your own. */\n bare?: boolean;\n /** Callback after the scene is created — set up custom cameras, lights, meshes. */\n onReady?: (scene: BJScene) => void;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * Keyboard focus ring for the Stage canvas. The canvas is focusable (the camera\n * controls attach to it) and carries an inline `outline: none`, which beats any\n * stylesheet outline — so the ring is a box-shadow, a separate property. Inset,\n * because the Stage container clips overflow. Shipped as a scoped `<style>`\n * rather than Tailwind classes: consumers are not guaranteed to scan this\n * package's dist, and a class nobody generates is a ring nobody sees.\n */\nconst STAGE_FOCUS_CSS =\n \"[data-fancy-3d-canvas]:focus-visible { box-shadow: inset 0 0 0 2px var(--fancy-focus, var(--color-blue-500, #3b82f6)); }\" +\n \" :where(.dark, [data-theme=\\\"dark\\\"]) [data-fancy-3d-canvas]:focus-visible { box-shadow: inset 0 0 0 2px var(--fancy-focus-dark, var(--color-blue-400, #60a5fa)); }\";\n\nexport function Stage({\n children,\n cameraRadius = 10,\n cameraTarget = [0, 1.5, 0],\n cameraAlpha = Math.PI / 2,\n cameraBeta = Math.PI / 2.4,\n clearColor = \"#06080f\",\n bare = false,\n onReady,\n className,\n style,\n}: StageProps) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const [stage, setStage] = useState<StageContextValue | null>(null);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const overlay = overlayRef.current;\n if (!canvas || !overlay) return;\n\n const engine = new Engine(canvas, true, { stencil: true, preserveDrawingBuffer: true });\n const scene = new BJScene(engine);\n const c = Color4.FromHexString(clearColor);\n scene.clearColor = new Color4(c.r, c.g, c.b, 1);\n\n if (!bare) {\n const cam = new ArcRotateCamera(\n \"fancy3d-cam\",\n cameraAlpha,\n cameraBeta,\n cameraRadius,\n new Vector3(...cameraTarget),\n scene\n );\n cam.attachControl(canvas, true);\n cam.lowerRadiusLimit = 1;\n cam.upperRadiusLimit = 80;\n cam.wheelDeltaPercentage = 0.01;\n cam.upperBetaLimit = Math.PI / 2 - 0.05;\n\n const hemi = new HemisphericLight(\"fancy3d-hemi\", new Vector3(0, 1, 0), scene);\n hemi.intensity = 0.7;\n hemi.diffuse = new Color3(0.7, 0.78, 1);\n hemi.groundColor = new Color3(0.1, 0.1, 0.18);\n\n const dir = new DirectionalLight(\"fancy3d-dir\", new Vector3(-0.4, -1, -0.6), scene);\n dir.intensity = 0.6;\n }\n\n onReady?.(scene);\n\n const frameSubs = new Set<() => void>();\n scene.onBeforeRenderObservable.add(() => {\n frameSubs.forEach((cb) => cb());\n });\n\n engine.runRenderLoop(() => scene.render());\n const handleResize = () => engine.resize();\n window.addEventListener(\"resize\", handleResize);\n\n setStage({\n engine,\n scene,\n canvas,\n overlayRoot: overlay,\n onFrame(cb) {\n frameSubs.add(cb);\n return () => frameSubs.delete(cb);\n },\n });\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n engine.dispose();\n setStage(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ position: \"relative\", overflow: \"hidden\", ...style }}\n data-fancy-3d-stage=\"\"\n >\n <style data-fancy-3d-stage-css=\"\">{STAGE_FOCUS_CSS}</style>\n <canvas\n ref={canvasRef}\n style={{ display: \"block\", width: \"100%\", height: \"100%\", outline: \"none\" }}\n tabIndex={0}\n data-fancy-3d-canvas=\"\"\n />\n <div\n ref={overlayRef}\n style={{ position: \"absolute\", inset: 0, pointerEvents: \"none\" }}\n data-fancy-3d-overlay-root=\"\"\n />\n {stage && <StageContext.Provider value={stage}>{children}</StageContext.Provider>}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Monitor — interactive mount point on a 3D mesh */\n/* ------------------------------------------------------------------ */\n\nexport interface MonitorProps {\n children?: ReactNode;\n /** World-space center of the screen. */\n position: [number, number, number];\n /** Mesh dimensions in world units. */\n width: number;\n height: number;\n /** Y-axis rotation in radians. */\n rotationY?: number;\n /** Bezel color. Defaults to a near-black frame. */\n bezel?: string;\n /** Bezel thickness in world units. Defaults to 0.06. */\n bezelThickness?: number;\n /** Background color visible behind the React content. */\n background?: string;\n /** Design-time pixel width for the children. Defaults to `width * 360`. */\n pixelWidth?: number;\n /** Design-time pixel height for the children. Defaults to `height * 360`. */\n pixelHeight?: number;\n /** Optional name on the Babylon mesh. */\n name?: string;\n}\n\nexport function Monitor({\n children,\n position,\n width,\n height,\n rotationY = 0,\n bezel = \"#0b0f17\",\n bezelThickness = 0.06,\n background = \"#0b1220\",\n pixelWidth,\n pixelHeight,\n name = \"screen\",\n}: MonitorProps) {\n const stage = useStage();\n const meshRef = useRef<Mesh | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n // Design-time pixel size for the children. The matrix3d transform maps\n // this unit rectangle onto the projected mesh quad each frame.\n const innerSize = useRef({\n w: pixelWidth ?? Math.max(120, Math.round(width * 360)),\n h: pixelHeight ?? Math.max(80, Math.round(height * 360)),\n });\n\n // Build the bezel + invisible projection-target plane.\n useEffect(() => {\n const { scene } = stage;\n const bezelMesh = MeshBuilder.CreateBox(`${name}-bezel`, {\n width: width + bezelThickness * 2,\n height: height + bezelThickness * 2,\n depth: bezelThickness,\n }, scene);\n bezelMesh.position = new Vector3(position[0], position[1], position[2]);\n bezelMesh.rotation.y = rotationY;\n const bezelMat = new StandardMaterial(`${name}-bezel-mat`, scene);\n bezelMat.diffuseColor = Color3.FromHexString(bezel);\n bezelMat.specularColor = new Color3(0.05, 0.05, 0.05);\n bezelMesh.material = bezelMat;\n\n // Inner pane the overlay tracks. Its background fills behind the React\n // overlay (in case the overlay is briefly mispositioned); the React\n // children are stamped on top.\n const pane = MeshBuilder.CreatePlane(`${name}-pane`, { width, height, sideOrientation: Mesh.DOUBLESIDE }, scene);\n pane.position = new Vector3(position[0], position[1], position[2]);\n pane.rotation.y = rotationY;\n // The bezel's \"front\" face is on +Z (default camera sits on +Z). Offset\n // the pane forward of that face so the React HTML overlay lines up with\n // the visible front of the bezel rather than its hidden back.\n const forward = new Vector3(0, 0, 1);\n const rot = Matrix.RotationY(rotationY);\n const offset = Vector3.TransformNormal(forward.scale(bezelThickness / 2 + 0.001), rot);\n pane.position.addInPlace(offset);\n const paneMat = new StandardMaterial(`${name}-pane-mat`, scene);\n paneMat.diffuseColor = Color3.FromHexString(background);\n paneMat.emissiveColor = Color3.FromHexString(background).scale(0.4);\n pane.material = paneMat;\n pane.metadata = { fancy3d: \"screen\", screenName: name };\n meshRef.current = pane;\n\n return () => {\n pane.dispose();\n bezelMesh.dispose();\n meshRef.current = null;\n };\n }, [stage, name, width, height, bezel, bezelThickness, background, position, rotationY]);\n\n // Each frame: project the four mesh corners and apply the matrix3d\n // transform that maps the inner div's local pixel space to the projected\n // quad. Imperative — no React re-render per frame.\n useEffect(() => {\n const unsub = stage.onFrame(() => {\n const mesh = meshRef.current;\n const overlay = overlayRef.current;\n if (!mesh || !overlay) return;\n const cam = stage.scene.activeCamera;\n if (!cam) return;\n const engine = stage.engine;\n const renderW = engine.getRenderWidth();\n const renderH = engine.getRenderHeight();\n const viewport = cam.viewport.toGlobal(renderW, renderH);\n const tm = stage.scene.getTransformMatrix();\n const identity = Matrix.Identity();\n const wm = mesh.getWorldMatrix();\n\n const halfW = width / 2;\n const halfH = height / 2;\n // Mesh-local corners ordered: top-left, top-right, bottom-right, bottom-left.\n // Babylon's plane: +Y is up in world (when not rotated around X), so\n // mesh-local +Y = top.\n const localCorners = [\n new Vector3(-halfW, halfH, 0), // top-left\n new Vector3(halfW, halfH, 0), // top-right\n new Vector3(halfW, -halfH, 0), // bottom-right\n new Vector3(-halfW, -halfH, 0), // bottom-left\n ];\n const worldCorners = localCorners.map((v) => Vector3.TransformCoordinates(v, wm));\n\n // Edge-on cull only — hide overlay when the panel is nearly perpendicular\n // to the camera ray (where the projected quad collapses and matrix3d\n // becomes singular). The matrix3d transform handles both front and\n // back side rendering naturally, so we don't strictly cull by side.\n const camPos = cam.globalPosition;\n const right = worldCorners[1].subtract(worldCorners[0]);\n const up = worldCorners[0].subtract(worldCorners[3]);\n const normal = Vector3.Cross(up, right).normalize();\n const center = worldCorners[0].add(worldCorners[2]).scale(0.5);\n const toCam = camPos.subtract(center).normalize();\n const facing = Math.abs(Vector3.Dot(normal, toCam));\n\n const projected = worldCorners.map((c) => Vector3.Project(c, identity, tm, viewport));\n const inFrustum = projected.every((p) => p.z >= 0 && p.z <= 1);\n const visible = inFrustum && facing > 0.05;\n\n if (!visible) {\n if (overlay.style.display !== \"none\") overlay.style.display = \"none\";\n return;\n }\n\n // Depth-sort overlays: nearer-to-camera panels stack above farther ones.\n // Without this, DOM document order decides stacking and side screens\n // can render on top of the center screen even when 3D depth says\n // otherwise. NDC z is 0 at the near plane and 1 at the far plane, so\n // closer-to-camera = smaller z = higher z-index.\n const avgZ = (projected[0].z + projected[1].z + projected[2].z + projected[3].z) / 4;\n const depthZIndex = Math.round(Math.max(0, Math.min(1, 1 - avgZ)) * 100000);\n const zStr = String(depthZIndex);\n if (overlay.style.zIndex !== zStr) overlay.style.zIndex = zStr;\n\n const dpr = window.devicePixelRatio || 1;\n const w0 = innerSize.current.w;\n const h0 = innerSize.current.h;\n const t = quadToQuad(\n w0, h0,\n projected[0].x / dpr, projected[0].y / dpr,\n projected[1].x / dpr, projected[1].y / dpr,\n projected[2].x / dpr, projected[2].y / dpr,\n projected[3].x / dpr, projected[3].y / dpr\n );\n\n if (overlay.style.display !== \"block\") overlay.style.display = \"block\";\n overlay.style.transform = matrix3dString(t);\n });\n return unsub;\n }, [stage, width, height]);\n\n // Mount the overlay into the stage's overlay root.\n useLayoutEffect(() => {\n const el = overlayRef.current;\n if (!el) return;\n if (el.parentElement !== stage.overlayRoot) {\n stage.overlayRoot.appendChild(el);\n }\n return () => {\n if (el.parentElement === stage.overlayRoot) {\n stage.overlayRoot.removeChild(el);\n }\n };\n }, [stage]);\n\n return (\n <div\n ref={overlayRef}\n data-fancy-3d-screen={name}\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: innerSize.current.w,\n height: innerSize.current.h,\n transformOrigin: \"0 0\",\n pointerEvents: \"auto\",\n overflow: \"hidden\",\n background,\n borderRadius: 4,\n display: \"none\",\n }}\n >\n {children}\n </div>\n );\n}\n"]}
|
package/dist/react.js
CHANGED
|
@@ -65,6 +65,7 @@ function useStage() {
|
|
|
65
65
|
if (!ctx) throw new Error("useStage() must be called inside <Stage>");
|
|
66
66
|
return ctx;
|
|
67
67
|
}
|
|
68
|
+
var STAGE_FOCUS_CSS = '[data-fancy-3d-canvas]:focus-visible { box-shadow: inset 0 0 0 2px var(--fancy-focus, var(--color-blue-500, #3b82f6)); } :where(.dark, [data-theme="dark"]) [data-fancy-3d-canvas]:focus-visible { box-shadow: inset 0 0 0 2px var(--fancy-focus-dark, var(--color-blue-400, #60a5fa)); }';
|
|
68
69
|
function Stage({
|
|
69
70
|
children,
|
|
70
71
|
cameraRadius = 10,
|
|
@@ -142,12 +143,14 @@ function Stage({
|
|
|
142
143
|
style: { position: "relative", overflow: "hidden", ...style },
|
|
143
144
|
"data-fancy-3d-stage": "",
|
|
144
145
|
children: [
|
|
146
|
+
/* @__PURE__ */ jsx("style", { "data-fancy-3d-stage-css": "", children: STAGE_FOCUS_CSS }),
|
|
145
147
|
/* @__PURE__ */ jsx(
|
|
146
148
|
"canvas",
|
|
147
149
|
{
|
|
148
150
|
ref: canvasRef,
|
|
149
151
|
style: { display: "block", width: "100%", height: "100%", outline: "none" },
|
|
150
|
-
tabIndex: 0
|
|
152
|
+
tabIndex: 0,
|
|
153
|
+
"data-fancy-3d-canvas": ""
|
|
151
154
|
}
|
|
152
155
|
),
|
|
153
156
|
/* @__PURE__ */ jsx(
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.tsx"],"names":["BJScene"],"mappings":"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","file":"react.js","sourcesContent":["/**\n * `<Stage>` and `<Monitor>` — declarative React API for fancy-3d.\n *\n * <Stage>\n * <Monitor position={[0, 2, 0]} width={4} height={2.5}>\n * <Card>...real react-fancy components...</Card>\n * </Monitor>\n * </Stage>\n *\n * `<Stage>` owns the Babylon engine + scene + render loop and exposes them\n * via context. `<Monitor>` builds a bezel mesh, projects its world-space\n * corners to screen space each frame, and renders its children into a\n * positioned DOM overlay. Children are real React: full interactivity,\n * accessibility, and styling — no canvas-rasterized snapshot.\n\n * Renamed from `<Screen>` in v0.3.0 to free the name for\n * `@particle-academy/fancy-screens`'s `<Screen>` (containerized application\n * surface). The behavior here is unchanged.\n *\n * Tradeoffs of mount mode (vs. painted texture):\n * - Pro: live, interactive, perfect text rendering.\n * - Con: HTML overlay always renders on top of the WebGL canvas; depth\n * sorting against other 3D objects is approximate (we hide the overlay\n * when the mesh is behind the camera or fully occluded by frustum).\n */\n// Granular @babylonjs/core imports (not the barrel) for tree-shaking; each\n// non-\".pure\" module self-applies its side effects (camera inputs, shaders,\n// engine extensions), so `attachControl` / rendering behave exactly as before.\nimport { ArcRotateCamera } from \"@babylonjs/core/Cameras/arcRotateCamera\";\nimport { Color3, Color4 } from \"@babylonjs/core/Maths/math.color\";\nimport { DirectionalLight } from \"@babylonjs/core/Lights/directionalLight\";\nimport { Engine } from \"@babylonjs/core/Engines/engine\";\nimport { HemisphericLight } from \"@babylonjs/core/Lights/hemisphericLight\";\nimport { Matrix, Vector3 } from \"@babylonjs/core/Maths/math.vector\";\nimport { Mesh } from \"@babylonjs/core/Meshes/mesh\";\nimport { MeshBuilder } from \"@babylonjs/core/Meshes/meshBuilder\";\nimport { Scene as BJScene } from \"@babylonjs/core/scene\";\nimport { StandardMaterial } from \"@babylonjs/core/Materials/standardMaterial\";\nimport type { Camera } from \"@babylonjs/core/Cameras/camera\";\nimport {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* 2D perspective transform — maps a unit rectangle to a 4-point quad */\n/* via a 3x3 homography, packed into a CSS matrix3d for transform. */\n/* ------------------------------------------------------------------ */\n\ntype Mat3 = [number, number, number, number, number, number, number, number, number];\n\nfunction adj3(m: Mat3): Mat3 {\n return [\n m[4] * m[8] - m[5] * m[7], m[2] * m[7] - m[1] * m[8], m[1] * m[5] - m[2] * m[4],\n m[5] * m[6] - m[3] * m[8], m[0] * m[8] - m[2] * m[6], m[2] * m[3] - m[0] * m[5],\n m[3] * m[7] - m[4] * m[6], m[1] * m[6] - m[0] * m[7], m[0] * m[4] - m[1] * m[3],\n ];\n}\n\nfunction multmm(a: Mat3, b: Mat3): Mat3 {\n const c: number[] = new Array(9);\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n let cij = 0;\n for (let k = 0; k < 3; k++) cij += a[3 * i + k] * b[3 * k + j];\n c[3 * i + j] = cij;\n }\n }\n return c as Mat3;\n}\n\nfunction multmv(m: Mat3, v: [number, number, number]): [number, number, number] {\n return [\n m[0] * v[0] + m[1] * v[1] + m[2] * v[2],\n m[3] * v[0] + m[4] * v[1] + m[5] * v[2],\n m[6] * v[0] + m[7] * v[1] + m[8] * v[2],\n ];\n}\n\nfunction basisToPoints(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): Mat3 {\n const m: Mat3 = [x1, x2, x3, y1, y2, y3, 1, 1, 1];\n const v = multmv(adj3(m), [x4, y4, 1]);\n return multmm(m, [v[0], 0, 0, 0, v[1], 0, 0, 0, v[2]]);\n}\n\n/** Compute a homography that maps (0,0)→p1, (w,0)→p2, (w,h)→p3, (0,h)→p4. */\nfunction quadToQuad(\n w: number, h: number,\n x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number\n): Mat3 {\n const s = basisToPoints(0, 0, w, 0, w, h, 0, h);\n const d = basisToPoints(x1, y1, x2, y2, x3, y3, x4, y4);\n const t = multmm(d, adj3(s));\n // Normalize so t[8] is 1\n const n = t[8];\n for (let i = 0; i < 9; i++) t[i] /= n;\n return t;\n}\n\n/** Pack a 3x3 homography into a CSS matrix3d() string. */\nfunction matrix3dString(t: Mat3): string {\n return `matrix3d(${t[0]}, ${t[3]}, 0, ${t[6]}, ${t[1]}, ${t[4]}, 0, ${t[7]}, 0, 0, 1, 0, ${t[2]}, ${t[5]}, 0, ${t[8]})`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Stage context */\n/* ------------------------------------------------------------------ */\n\ninterface StageContextValue {\n engine: Engine;\n scene: BJScene;\n /** The HTML <canvas> the engine renders into — its bounding rect anchors overlays. */\n canvas: HTMLCanvasElement;\n /** Subscribe to per-frame ticks. Returns an unsubscribe fn. */\n onFrame(cb: () => void): () => void;\n /** The DOM container that screen overlays mount into. */\n overlayRoot: HTMLDivElement;\n}\n\nconst StageContext = createContext<StageContextValue | null>(null);\n\nexport function useStage(): StageContextValue {\n const ctx = useContext(StageContext);\n if (!ctx) throw new Error(\"useStage() must be called inside <Stage>\");\n return ctx;\n}\n\n/* ------------------------------------------------------------------ */\n/* Stage */\n/* ------------------------------------------------------------------ */\n\nexport interface StageProps {\n children?: ReactNode;\n /** Initial camera radius. Defaults to 10. */\n cameraRadius?: number;\n /** Initial camera target. Defaults to (0, 1.5, 0). */\n cameraTarget?: [number, number, number];\n /** Initial camera alpha (horizontal angle). Defaults to π/2. */\n cameraAlpha?: number;\n /** Initial camera beta (vertical angle). Defaults to π/2.4. */\n cameraBeta?: number;\n /** Background clear color. Defaults to a near-black. */\n clearColor?: string;\n /** Disable the default lights / camera if you want to set your own. */\n bare?: boolean;\n /** Callback after the scene is created — set up custom cameras, lights, meshes. */\n onReady?: (scene: BJScene) => void;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function Stage({\n children,\n cameraRadius = 10,\n cameraTarget = [0, 1.5, 0],\n cameraAlpha = Math.PI / 2,\n cameraBeta = Math.PI / 2.4,\n clearColor = \"#06080f\",\n bare = false,\n onReady,\n className,\n style,\n}: StageProps) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const [stage, setStage] = useState<StageContextValue | null>(null);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const overlay = overlayRef.current;\n if (!canvas || !overlay) return;\n\n const engine = new Engine(canvas, true, { stencil: true, preserveDrawingBuffer: true });\n const scene = new BJScene(engine);\n const c = Color4.FromHexString(clearColor);\n scene.clearColor = new Color4(c.r, c.g, c.b, 1);\n\n if (!bare) {\n const cam = new ArcRotateCamera(\n \"fancy3d-cam\",\n cameraAlpha,\n cameraBeta,\n cameraRadius,\n new Vector3(...cameraTarget),\n scene\n );\n cam.attachControl(canvas, true);\n cam.lowerRadiusLimit = 1;\n cam.upperRadiusLimit = 80;\n cam.wheelDeltaPercentage = 0.01;\n cam.upperBetaLimit = Math.PI / 2 - 0.05;\n\n const hemi = new HemisphericLight(\"fancy3d-hemi\", new Vector3(0, 1, 0), scene);\n hemi.intensity = 0.7;\n hemi.diffuse = new Color3(0.7, 0.78, 1);\n hemi.groundColor = new Color3(0.1, 0.1, 0.18);\n\n const dir = new DirectionalLight(\"fancy3d-dir\", new Vector3(-0.4, -1, -0.6), scene);\n dir.intensity = 0.6;\n }\n\n onReady?.(scene);\n\n const frameSubs = new Set<() => void>();\n scene.onBeforeRenderObservable.add(() => {\n frameSubs.forEach((cb) => cb());\n });\n\n engine.runRenderLoop(() => scene.render());\n const handleResize = () => engine.resize();\n window.addEventListener(\"resize\", handleResize);\n\n setStage({\n engine,\n scene,\n canvas,\n overlayRoot: overlay,\n onFrame(cb) {\n frameSubs.add(cb);\n return () => frameSubs.delete(cb);\n },\n });\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n engine.dispose();\n setStage(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ position: \"relative\", overflow: \"hidden\", ...style }}\n data-fancy-3d-stage=\"\"\n >\n <canvas\n ref={canvasRef}\n style={{ display: \"block\", width: \"100%\", height: \"100%\", outline: \"none\" }}\n tabIndex={0}\n />\n <div\n ref={overlayRef}\n style={{ position: \"absolute\", inset: 0, pointerEvents: \"none\" }}\n data-fancy-3d-overlay-root=\"\"\n />\n {stage && <StageContext.Provider value={stage}>{children}</StageContext.Provider>}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Monitor — interactive mount point on a 3D mesh */\n/* ------------------------------------------------------------------ */\n\nexport interface MonitorProps {\n children?: ReactNode;\n /** World-space center of the screen. */\n position: [number, number, number];\n /** Mesh dimensions in world units. */\n width: number;\n height: number;\n /** Y-axis rotation in radians. */\n rotationY?: number;\n /** Bezel color. Defaults to a near-black frame. */\n bezel?: string;\n /** Bezel thickness in world units. Defaults to 0.06. */\n bezelThickness?: number;\n /** Background color visible behind the React content. */\n background?: string;\n /** Design-time pixel width for the children. Defaults to `width * 360`. */\n pixelWidth?: number;\n /** Design-time pixel height for the children. Defaults to `height * 360`. */\n pixelHeight?: number;\n /** Optional name on the Babylon mesh. */\n name?: string;\n}\n\nexport function Monitor({\n children,\n position,\n width,\n height,\n rotationY = 0,\n bezel = \"#0b0f17\",\n bezelThickness = 0.06,\n background = \"#0b1220\",\n pixelWidth,\n pixelHeight,\n name = \"screen\",\n}: MonitorProps) {\n const stage = useStage();\n const meshRef = useRef<Mesh | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n // Design-time pixel size for the children. The matrix3d transform maps\n // this unit rectangle onto the projected mesh quad each frame.\n const innerSize = useRef({\n w: pixelWidth ?? Math.max(120, Math.round(width * 360)),\n h: pixelHeight ?? Math.max(80, Math.round(height * 360)),\n });\n\n // Build the bezel + invisible projection-target plane.\n useEffect(() => {\n const { scene } = stage;\n const bezelMesh = MeshBuilder.CreateBox(`${name}-bezel`, {\n width: width + bezelThickness * 2,\n height: height + bezelThickness * 2,\n depth: bezelThickness,\n }, scene);\n bezelMesh.position = new Vector3(position[0], position[1], position[2]);\n bezelMesh.rotation.y = rotationY;\n const bezelMat = new StandardMaterial(`${name}-bezel-mat`, scene);\n bezelMat.diffuseColor = Color3.FromHexString(bezel);\n bezelMat.specularColor = new Color3(0.05, 0.05, 0.05);\n bezelMesh.material = bezelMat;\n\n // Inner pane the overlay tracks. Its background fills behind the React\n // overlay (in case the overlay is briefly mispositioned); the React\n // children are stamped on top.\n const pane = MeshBuilder.CreatePlane(`${name}-pane`, { width, height, sideOrientation: Mesh.DOUBLESIDE }, scene);\n pane.position = new Vector3(position[0], position[1], position[2]);\n pane.rotation.y = rotationY;\n // The bezel's \"front\" face is on +Z (default camera sits on +Z). Offset\n // the pane forward of that face so the React HTML overlay lines up with\n // the visible front of the bezel rather than its hidden back.\n const forward = new Vector3(0, 0, 1);\n const rot = Matrix.RotationY(rotationY);\n const offset = Vector3.TransformNormal(forward.scale(bezelThickness / 2 + 0.001), rot);\n pane.position.addInPlace(offset);\n const paneMat = new StandardMaterial(`${name}-pane-mat`, scene);\n paneMat.diffuseColor = Color3.FromHexString(background);\n paneMat.emissiveColor = Color3.FromHexString(background).scale(0.4);\n pane.material = paneMat;\n pane.metadata = { fancy3d: \"screen\", screenName: name };\n meshRef.current = pane;\n\n return () => {\n pane.dispose();\n bezelMesh.dispose();\n meshRef.current = null;\n };\n }, [stage, name, width, height, bezel, bezelThickness, background, position, rotationY]);\n\n // Each frame: project the four mesh corners and apply the matrix3d\n // transform that maps the inner div's local pixel space to the projected\n // quad. Imperative — no React re-render per frame.\n useEffect(() => {\n const unsub = stage.onFrame(() => {\n const mesh = meshRef.current;\n const overlay = overlayRef.current;\n if (!mesh || !overlay) return;\n const cam = stage.scene.activeCamera;\n if (!cam) return;\n const engine = stage.engine;\n const renderW = engine.getRenderWidth();\n const renderH = engine.getRenderHeight();\n const viewport = cam.viewport.toGlobal(renderW, renderH);\n const tm = stage.scene.getTransformMatrix();\n const identity = Matrix.Identity();\n const wm = mesh.getWorldMatrix();\n\n const halfW = width / 2;\n const halfH = height / 2;\n // Mesh-local corners ordered: top-left, top-right, bottom-right, bottom-left.\n // Babylon's plane: +Y is up in world (when not rotated around X), so\n // mesh-local +Y = top.\n const localCorners = [\n new Vector3(-halfW, halfH, 0), // top-left\n new Vector3(halfW, halfH, 0), // top-right\n new Vector3(halfW, -halfH, 0), // bottom-right\n new Vector3(-halfW, -halfH, 0), // bottom-left\n ];\n const worldCorners = localCorners.map((v) => Vector3.TransformCoordinates(v, wm));\n\n // Edge-on cull only — hide overlay when the panel is nearly perpendicular\n // to the camera ray (where the projected quad collapses and matrix3d\n // becomes singular). The matrix3d transform handles both front and\n // back side rendering naturally, so we don't strictly cull by side.\n const camPos = cam.globalPosition;\n const right = worldCorners[1].subtract(worldCorners[0]);\n const up = worldCorners[0].subtract(worldCorners[3]);\n const normal = Vector3.Cross(up, right).normalize();\n const center = worldCorners[0].add(worldCorners[2]).scale(0.5);\n const toCam = camPos.subtract(center).normalize();\n const facing = Math.abs(Vector3.Dot(normal, toCam));\n\n const projected = worldCorners.map((c) => Vector3.Project(c, identity, tm, viewport));\n const inFrustum = projected.every((p) => p.z >= 0 && p.z <= 1);\n const visible = inFrustum && facing > 0.05;\n\n if (!visible) {\n if (overlay.style.display !== \"none\") overlay.style.display = \"none\";\n return;\n }\n\n // Depth-sort overlays: nearer-to-camera panels stack above farther ones.\n // Without this, DOM document order decides stacking and side screens\n // can render on top of the center screen even when 3D depth says\n // otherwise. NDC z is 0 at the near plane and 1 at the far plane, so\n // closer-to-camera = smaller z = higher z-index.\n const avgZ = (projected[0].z + projected[1].z + projected[2].z + projected[3].z) / 4;\n const depthZIndex = Math.round(Math.max(0, Math.min(1, 1 - avgZ)) * 100000);\n const zStr = String(depthZIndex);\n if (overlay.style.zIndex !== zStr) overlay.style.zIndex = zStr;\n\n const dpr = window.devicePixelRatio || 1;\n const w0 = innerSize.current.w;\n const h0 = innerSize.current.h;\n const t = quadToQuad(\n w0, h0,\n projected[0].x / dpr, projected[0].y / dpr,\n projected[1].x / dpr, projected[1].y / dpr,\n projected[2].x / dpr, projected[2].y / dpr,\n projected[3].x / dpr, projected[3].y / dpr\n );\n\n if (overlay.style.display !== \"block\") overlay.style.display = \"block\";\n overlay.style.transform = matrix3dString(t);\n });\n return unsub;\n }, [stage, width, height]);\n\n // Mount the overlay into the stage's overlay root.\n useLayoutEffect(() => {\n const el = overlayRef.current;\n if (!el) return;\n if (el.parentElement !== stage.overlayRoot) {\n stage.overlayRoot.appendChild(el);\n }\n return () => {\n if (el.parentElement === stage.overlayRoot) {\n stage.overlayRoot.removeChild(el);\n }\n };\n }, [stage]);\n\n return (\n <div\n ref={overlayRef}\n data-fancy-3d-screen={name}\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: innerSize.current.w,\n height: innerSize.current.h,\n transformOrigin: \"0 0\",\n pointerEvents: \"auto\",\n overflow: \"hidden\",\n background,\n borderRadius: 4,\n display: \"none\",\n }}\n >\n {children}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx"],"names":["BJScene"],"mappings":"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","file":"react.js","sourcesContent":["/**\n * `<Stage>` and `<Monitor>` — declarative React API for fancy-3d.\n *\n * <Stage>\n * <Monitor position={[0, 2, 0]} width={4} height={2.5}>\n * <Card>...real react-fancy components...</Card>\n * </Monitor>\n * </Stage>\n *\n * `<Stage>` owns the Babylon engine + scene + render loop and exposes them\n * via context. `<Monitor>` builds a bezel mesh, projects its world-space\n * corners to screen space each frame, and renders its children into a\n * positioned DOM overlay. Children are real React: full interactivity,\n * accessibility, and styling — no canvas-rasterized snapshot.\n\n * Renamed from `<Screen>` in v0.3.0 to free the name for\n * `@particle-academy/fancy-screens`'s `<Screen>` (containerized application\n * surface). The behavior here is unchanged.\n *\n * Tradeoffs of mount mode (vs. painted texture):\n * - Pro: live, interactive, perfect text rendering.\n * - Con: HTML overlay always renders on top of the WebGL canvas; depth\n * sorting against other 3D objects is approximate (we hide the overlay\n * when the mesh is behind the camera or fully occluded by frustum).\n */\n// Granular @babylonjs/core imports (not the barrel) for tree-shaking; each\n// non-\".pure\" module self-applies its side effects (camera inputs, shaders,\n// engine extensions), so `attachControl` / rendering behave exactly as before.\nimport { ArcRotateCamera } from \"@babylonjs/core/Cameras/arcRotateCamera\";\nimport { Color3, Color4 } from \"@babylonjs/core/Maths/math.color\";\nimport { DirectionalLight } from \"@babylonjs/core/Lights/directionalLight\";\nimport { Engine } from \"@babylonjs/core/Engines/engine\";\nimport { HemisphericLight } from \"@babylonjs/core/Lights/hemisphericLight\";\nimport { Matrix, Vector3 } from \"@babylonjs/core/Maths/math.vector\";\nimport { Mesh } from \"@babylonjs/core/Meshes/mesh\";\nimport { MeshBuilder } from \"@babylonjs/core/Meshes/meshBuilder\";\nimport { Scene as BJScene } from \"@babylonjs/core/scene\";\nimport { StandardMaterial } from \"@babylonjs/core/Materials/standardMaterial\";\nimport type { Camera } from \"@babylonjs/core/Cameras/camera\";\nimport {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* 2D perspective transform — maps a unit rectangle to a 4-point quad */\n/* via a 3x3 homography, packed into a CSS matrix3d for transform. */\n/* ------------------------------------------------------------------ */\n\ntype Mat3 = [number, number, number, number, number, number, number, number, number];\n\nfunction adj3(m: Mat3): Mat3 {\n return [\n m[4] * m[8] - m[5] * m[7], m[2] * m[7] - m[1] * m[8], m[1] * m[5] - m[2] * m[4],\n m[5] * m[6] - m[3] * m[8], m[0] * m[8] - m[2] * m[6], m[2] * m[3] - m[0] * m[5],\n m[3] * m[7] - m[4] * m[6], m[1] * m[6] - m[0] * m[7], m[0] * m[4] - m[1] * m[3],\n ];\n}\n\nfunction multmm(a: Mat3, b: Mat3): Mat3 {\n const c: number[] = new Array(9);\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n let cij = 0;\n for (let k = 0; k < 3; k++) cij += a[3 * i + k] * b[3 * k + j];\n c[3 * i + j] = cij;\n }\n }\n return c as Mat3;\n}\n\nfunction multmv(m: Mat3, v: [number, number, number]): [number, number, number] {\n return [\n m[0] * v[0] + m[1] * v[1] + m[2] * v[2],\n m[3] * v[0] + m[4] * v[1] + m[5] * v[2],\n m[6] * v[0] + m[7] * v[1] + m[8] * v[2],\n ];\n}\n\nfunction basisToPoints(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number): Mat3 {\n const m: Mat3 = [x1, x2, x3, y1, y2, y3, 1, 1, 1];\n const v = multmv(adj3(m), [x4, y4, 1]);\n return multmm(m, [v[0], 0, 0, 0, v[1], 0, 0, 0, v[2]]);\n}\n\n/** Compute a homography that maps (0,0)→p1, (w,0)→p2, (w,h)→p3, (0,h)→p4. */\nfunction quadToQuad(\n w: number, h: number,\n x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number\n): Mat3 {\n const s = basisToPoints(0, 0, w, 0, w, h, 0, h);\n const d = basisToPoints(x1, y1, x2, y2, x3, y3, x4, y4);\n const t = multmm(d, adj3(s));\n // Normalize so t[8] is 1\n const n = t[8];\n for (let i = 0; i < 9; i++) t[i] /= n;\n return t;\n}\n\n/** Pack a 3x3 homography into a CSS matrix3d() string. */\nfunction matrix3dString(t: Mat3): string {\n return `matrix3d(${t[0]}, ${t[3]}, 0, ${t[6]}, ${t[1]}, ${t[4]}, 0, ${t[7]}, 0, 0, 1, 0, ${t[2]}, ${t[5]}, 0, ${t[8]})`;\n}\n\n/* ------------------------------------------------------------------ */\n/* Stage context */\n/* ------------------------------------------------------------------ */\n\ninterface StageContextValue {\n engine: Engine;\n scene: BJScene;\n /** The HTML <canvas> the engine renders into — its bounding rect anchors overlays. */\n canvas: HTMLCanvasElement;\n /** Subscribe to per-frame ticks. Returns an unsubscribe fn. */\n onFrame(cb: () => void): () => void;\n /** The DOM container that screen overlays mount into. */\n overlayRoot: HTMLDivElement;\n}\n\nconst StageContext = createContext<StageContextValue | null>(null);\n\nexport function useStage(): StageContextValue {\n const ctx = useContext(StageContext);\n if (!ctx) throw new Error(\"useStage() must be called inside <Stage>\");\n return ctx;\n}\n\n/* ------------------------------------------------------------------ */\n/* Stage */\n/* ------------------------------------------------------------------ */\n\nexport interface StageProps {\n children?: ReactNode;\n /** Initial camera radius. Defaults to 10. */\n cameraRadius?: number;\n /** Initial camera target. Defaults to (0, 1.5, 0). */\n cameraTarget?: [number, number, number];\n /** Initial camera alpha (horizontal angle). Defaults to π/2. */\n cameraAlpha?: number;\n /** Initial camera beta (vertical angle). Defaults to π/2.4. */\n cameraBeta?: number;\n /** Background clear color. Defaults to a near-black. */\n clearColor?: string;\n /** Disable the default lights / camera if you want to set your own. */\n bare?: boolean;\n /** Callback after the scene is created — set up custom cameras, lights, meshes. */\n onReady?: (scene: BJScene) => void;\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * Keyboard focus ring for the Stage canvas. The canvas is focusable (the camera\n * controls attach to it) and carries an inline `outline: none`, which beats any\n * stylesheet outline — so the ring is a box-shadow, a separate property. Inset,\n * because the Stage container clips overflow. Shipped as a scoped `<style>`\n * rather than Tailwind classes: consumers are not guaranteed to scan this\n * package's dist, and a class nobody generates is a ring nobody sees.\n */\nconst STAGE_FOCUS_CSS =\n \"[data-fancy-3d-canvas]:focus-visible { box-shadow: inset 0 0 0 2px var(--fancy-focus, var(--color-blue-500, #3b82f6)); }\" +\n \" :where(.dark, [data-theme=\\\"dark\\\"]) [data-fancy-3d-canvas]:focus-visible { box-shadow: inset 0 0 0 2px var(--fancy-focus-dark, var(--color-blue-400, #60a5fa)); }\";\n\nexport function Stage({\n children,\n cameraRadius = 10,\n cameraTarget = [0, 1.5, 0],\n cameraAlpha = Math.PI / 2,\n cameraBeta = Math.PI / 2.4,\n clearColor = \"#06080f\",\n bare = false,\n onReady,\n className,\n style,\n}: StageProps) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const [stage, setStage] = useState<StageContextValue | null>(null);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const overlay = overlayRef.current;\n if (!canvas || !overlay) return;\n\n const engine = new Engine(canvas, true, { stencil: true, preserveDrawingBuffer: true });\n const scene = new BJScene(engine);\n const c = Color4.FromHexString(clearColor);\n scene.clearColor = new Color4(c.r, c.g, c.b, 1);\n\n if (!bare) {\n const cam = new ArcRotateCamera(\n \"fancy3d-cam\",\n cameraAlpha,\n cameraBeta,\n cameraRadius,\n new Vector3(...cameraTarget),\n scene\n );\n cam.attachControl(canvas, true);\n cam.lowerRadiusLimit = 1;\n cam.upperRadiusLimit = 80;\n cam.wheelDeltaPercentage = 0.01;\n cam.upperBetaLimit = Math.PI / 2 - 0.05;\n\n const hemi = new HemisphericLight(\"fancy3d-hemi\", new Vector3(0, 1, 0), scene);\n hemi.intensity = 0.7;\n hemi.diffuse = new Color3(0.7, 0.78, 1);\n hemi.groundColor = new Color3(0.1, 0.1, 0.18);\n\n const dir = new DirectionalLight(\"fancy3d-dir\", new Vector3(-0.4, -1, -0.6), scene);\n dir.intensity = 0.6;\n }\n\n onReady?.(scene);\n\n const frameSubs = new Set<() => void>();\n scene.onBeforeRenderObservable.add(() => {\n frameSubs.forEach((cb) => cb());\n });\n\n engine.runRenderLoop(() => scene.render());\n const handleResize = () => engine.resize();\n window.addEventListener(\"resize\", handleResize);\n\n setStage({\n engine,\n scene,\n canvas,\n overlayRoot: overlay,\n onFrame(cb) {\n frameSubs.add(cb);\n return () => frameSubs.delete(cb);\n },\n });\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n engine.dispose();\n setStage(null);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <div\n ref={containerRef}\n className={className}\n style={{ position: \"relative\", overflow: \"hidden\", ...style }}\n data-fancy-3d-stage=\"\"\n >\n <style data-fancy-3d-stage-css=\"\">{STAGE_FOCUS_CSS}</style>\n <canvas\n ref={canvasRef}\n style={{ display: \"block\", width: \"100%\", height: \"100%\", outline: \"none\" }}\n tabIndex={0}\n data-fancy-3d-canvas=\"\"\n />\n <div\n ref={overlayRef}\n style={{ position: \"absolute\", inset: 0, pointerEvents: \"none\" }}\n data-fancy-3d-overlay-root=\"\"\n />\n {stage && <StageContext.Provider value={stage}>{children}</StageContext.Provider>}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Monitor — interactive mount point on a 3D mesh */\n/* ------------------------------------------------------------------ */\n\nexport interface MonitorProps {\n children?: ReactNode;\n /** World-space center of the screen. */\n position: [number, number, number];\n /** Mesh dimensions in world units. */\n width: number;\n height: number;\n /** Y-axis rotation in radians. */\n rotationY?: number;\n /** Bezel color. Defaults to a near-black frame. */\n bezel?: string;\n /** Bezel thickness in world units. Defaults to 0.06. */\n bezelThickness?: number;\n /** Background color visible behind the React content. */\n background?: string;\n /** Design-time pixel width for the children. Defaults to `width * 360`. */\n pixelWidth?: number;\n /** Design-time pixel height for the children. Defaults to `height * 360`. */\n pixelHeight?: number;\n /** Optional name on the Babylon mesh. */\n name?: string;\n}\n\nexport function Monitor({\n children,\n position,\n width,\n height,\n rotationY = 0,\n bezel = \"#0b0f17\",\n bezelThickness = 0.06,\n background = \"#0b1220\",\n pixelWidth,\n pixelHeight,\n name = \"screen\",\n}: MonitorProps) {\n const stage = useStage();\n const meshRef = useRef<Mesh | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n // Design-time pixel size for the children. The matrix3d transform maps\n // this unit rectangle onto the projected mesh quad each frame.\n const innerSize = useRef({\n w: pixelWidth ?? Math.max(120, Math.round(width * 360)),\n h: pixelHeight ?? Math.max(80, Math.round(height * 360)),\n });\n\n // Build the bezel + invisible projection-target plane.\n useEffect(() => {\n const { scene } = stage;\n const bezelMesh = MeshBuilder.CreateBox(`${name}-bezel`, {\n width: width + bezelThickness * 2,\n height: height + bezelThickness * 2,\n depth: bezelThickness,\n }, scene);\n bezelMesh.position = new Vector3(position[0], position[1], position[2]);\n bezelMesh.rotation.y = rotationY;\n const bezelMat = new StandardMaterial(`${name}-bezel-mat`, scene);\n bezelMat.diffuseColor = Color3.FromHexString(bezel);\n bezelMat.specularColor = new Color3(0.05, 0.05, 0.05);\n bezelMesh.material = bezelMat;\n\n // Inner pane the overlay tracks. Its background fills behind the React\n // overlay (in case the overlay is briefly mispositioned); the React\n // children are stamped on top.\n const pane = MeshBuilder.CreatePlane(`${name}-pane`, { width, height, sideOrientation: Mesh.DOUBLESIDE }, scene);\n pane.position = new Vector3(position[0], position[1], position[2]);\n pane.rotation.y = rotationY;\n // The bezel's \"front\" face is on +Z (default camera sits on +Z). Offset\n // the pane forward of that face so the React HTML overlay lines up with\n // the visible front of the bezel rather than its hidden back.\n const forward = new Vector3(0, 0, 1);\n const rot = Matrix.RotationY(rotationY);\n const offset = Vector3.TransformNormal(forward.scale(bezelThickness / 2 + 0.001), rot);\n pane.position.addInPlace(offset);\n const paneMat = new StandardMaterial(`${name}-pane-mat`, scene);\n paneMat.diffuseColor = Color3.FromHexString(background);\n paneMat.emissiveColor = Color3.FromHexString(background).scale(0.4);\n pane.material = paneMat;\n pane.metadata = { fancy3d: \"screen\", screenName: name };\n meshRef.current = pane;\n\n return () => {\n pane.dispose();\n bezelMesh.dispose();\n meshRef.current = null;\n };\n }, [stage, name, width, height, bezel, bezelThickness, background, position, rotationY]);\n\n // Each frame: project the four mesh corners and apply the matrix3d\n // transform that maps the inner div's local pixel space to the projected\n // quad. Imperative — no React re-render per frame.\n useEffect(() => {\n const unsub = stage.onFrame(() => {\n const mesh = meshRef.current;\n const overlay = overlayRef.current;\n if (!mesh || !overlay) return;\n const cam = stage.scene.activeCamera;\n if (!cam) return;\n const engine = stage.engine;\n const renderW = engine.getRenderWidth();\n const renderH = engine.getRenderHeight();\n const viewport = cam.viewport.toGlobal(renderW, renderH);\n const tm = stage.scene.getTransformMatrix();\n const identity = Matrix.Identity();\n const wm = mesh.getWorldMatrix();\n\n const halfW = width / 2;\n const halfH = height / 2;\n // Mesh-local corners ordered: top-left, top-right, bottom-right, bottom-left.\n // Babylon's plane: +Y is up in world (when not rotated around X), so\n // mesh-local +Y = top.\n const localCorners = [\n new Vector3(-halfW, halfH, 0), // top-left\n new Vector3(halfW, halfH, 0), // top-right\n new Vector3(halfW, -halfH, 0), // bottom-right\n new Vector3(-halfW, -halfH, 0), // bottom-left\n ];\n const worldCorners = localCorners.map((v) => Vector3.TransformCoordinates(v, wm));\n\n // Edge-on cull only — hide overlay when the panel is nearly perpendicular\n // to the camera ray (where the projected quad collapses and matrix3d\n // becomes singular). The matrix3d transform handles both front and\n // back side rendering naturally, so we don't strictly cull by side.\n const camPos = cam.globalPosition;\n const right = worldCorners[1].subtract(worldCorners[0]);\n const up = worldCorners[0].subtract(worldCorners[3]);\n const normal = Vector3.Cross(up, right).normalize();\n const center = worldCorners[0].add(worldCorners[2]).scale(0.5);\n const toCam = camPos.subtract(center).normalize();\n const facing = Math.abs(Vector3.Dot(normal, toCam));\n\n const projected = worldCorners.map((c) => Vector3.Project(c, identity, tm, viewport));\n const inFrustum = projected.every((p) => p.z >= 0 && p.z <= 1);\n const visible = inFrustum && facing > 0.05;\n\n if (!visible) {\n if (overlay.style.display !== \"none\") overlay.style.display = \"none\";\n return;\n }\n\n // Depth-sort overlays: nearer-to-camera panels stack above farther ones.\n // Without this, DOM document order decides stacking and side screens\n // can render on top of the center screen even when 3D depth says\n // otherwise. NDC z is 0 at the near plane and 1 at the far plane, so\n // closer-to-camera = smaller z = higher z-index.\n const avgZ = (projected[0].z + projected[1].z + projected[2].z + projected[3].z) / 4;\n const depthZIndex = Math.round(Math.max(0, Math.min(1, 1 - avgZ)) * 100000);\n const zStr = String(depthZIndex);\n if (overlay.style.zIndex !== zStr) overlay.style.zIndex = zStr;\n\n const dpr = window.devicePixelRatio || 1;\n const w0 = innerSize.current.w;\n const h0 = innerSize.current.h;\n const t = quadToQuad(\n w0, h0,\n projected[0].x / dpr, projected[0].y / dpr,\n projected[1].x / dpr, projected[1].y / dpr,\n projected[2].x / dpr, projected[2].y / dpr,\n projected[3].x / dpr, projected[3].y / dpr\n );\n\n if (overlay.style.display !== \"block\") overlay.style.display = \"block\";\n overlay.style.transform = matrix3dString(t);\n });\n return unsub;\n }, [stage, width, height]);\n\n // Mount the overlay into the stage's overlay root.\n useLayoutEffect(() => {\n const el = overlayRef.current;\n if (!el) return;\n if (el.parentElement !== stage.overlayRoot) {\n stage.overlayRoot.appendChild(el);\n }\n return () => {\n if (el.parentElement === stage.overlayRoot) {\n stage.overlayRoot.removeChild(el);\n }\n };\n }, [stage]);\n\n return (\n <div\n ref={overlayRef}\n data-fancy-3d-screen={name}\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: innerSize.current.w,\n height: innerSize.current.h,\n transformOrigin: \"0 0\",\n pointerEvents: \"auto\",\n overflow: \"hidden\",\n background,\n borderRadius: 4,\n display: \"none\",\n }}\n >\n {children}\n </div>\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@particle-academy/fancy-3d-babylon",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Babylon.js adapter for @particle-academy/fancy-3d — WebGL renderer, primitives, React components (Stage, Monitor, Card3D, Screen) that mount onto a Babylon Scene.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
"files": [
|
|
48
48
|
"dist",
|
|
49
|
-
"README.md"
|
|
49
|
+
"README.md",
|
|
50
|
+
"CHANGELOG.md"
|
|
50
51
|
],
|
|
51
52
|
"scripts": {
|
|
52
53
|
"build": "tsup",
|
|
@@ -80,24 +81,25 @@
|
|
|
80
81
|
"@babylonjs/core": "^9.0.0",
|
|
81
82
|
"@particle-academy/fancy-3d": "^0.4.2",
|
|
82
83
|
"@particle-academy/react-fancy": "^4.0.0",
|
|
83
|
-
"@types/react": "^19.2.
|
|
84
|
-
"@types/react-dom": "^19.2.
|
|
84
|
+
"@types/react": "^19.2.18",
|
|
85
|
+
"@types/react-dom": "^19.2.4",
|
|
85
86
|
"eslint": "^10.8.0",
|
|
86
87
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
87
88
|
"jsdom": "^29.1.1",
|
|
88
|
-
"react": "^19.2.
|
|
89
|
-
"react-dom": "^19.2.
|
|
89
|
+
"react": "^19.2.8",
|
|
90
|
+
"react-dom": "^19.2.8",
|
|
90
91
|
"tsup": "^8.5.0",
|
|
91
92
|
"typescript": "^5.8.0",
|
|
92
93
|
"typescript-eslint": "^8.65.0",
|
|
93
|
-
"vitest": "^
|
|
94
|
+
"vitest": "^4.1.12"
|
|
94
95
|
},
|
|
95
96
|
"publishConfig": {
|
|
96
97
|
"access": "public"
|
|
97
98
|
},
|
|
98
99
|
"license": "MIT",
|
|
99
100
|
"overrides": {
|
|
100
|
-
"esbuild": "^0.28.1"
|
|
101
|
+
"esbuild": "^0.28.1",
|
|
102
|
+
"source-map-js": "^1.2.2"
|
|
101
103
|
},
|
|
102
104
|
"engines": {
|
|
103
105
|
"node": ">=22"
|