@layoutit/polycss-react 0.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Layoutit
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/README.md ADDED
@@ -0,0 +1,174 @@
1
+ > **Status: pre-1.0. APIs may still change before a stable 1.0 release.**
2
+
3
+ # @layoutit/polycss-react
4
+
5
+ Declarative React components for CSS-based polygon mesh rendering. Loads OBJ, glTF, GLB, and MagicaVoxel `.vox` files; renders each polygon as a real DOM element (atlas-backed `<i>` for both textured and flat-color faces) positioned with `transform: matrix3d(...)`. No WebGL, no canvas-as-scene.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @layoutit/polycss-react
11
+ ```
12
+
13
+ Requires React 18 or 19 as a peer dependency.
14
+
15
+ ## Quickstart
16
+
17
+ ```tsx
18
+ import { PolyCamera, PolyScene, PolyMesh } from "@layoutit/polycss-react";
19
+
20
+ export function App() {
21
+ return (
22
+ <PolyCamera rotX={65} rotY={45} perspective={1000}>
23
+ <PolyScene>
24
+ <PolyMesh src="/cottage.glb" />
25
+ </PolyScene>
26
+ </PolyCamera>
27
+ );
28
+ }
29
+ ```
30
+
31
+ Every polygon in the mesh is a real DOM element: inspect it in DevTools, style it with CSS, attach event handlers.
32
+
33
+ ## Component reference
34
+
35
+ ### `<PolyScene>`
36
+
37
+ Root of every React polycss render tree. Renders polygons and meshes inside a `<PolyCamera>` context, and owns scene-level lighting and atlas options.
38
+
39
+ | Prop | Type | Default | Description |
40
+ |---|---|---|---|
41
+ | `directionalLight` | `PolyDirectionalLight` | None | Directional light config |
42
+ | `ambientLight` | `PolyAmbientLight` | None | Ambient light config |
43
+ | `textureLighting` | `"baked" \| "dynamic"` | `"baked"` | Texture lighting mode |
44
+ | `atlasScale` | `number \| "auto"` | `"auto"` | Raster scale for generated atlas pages |
45
+ | `polygons` | `Polygon[]` | None | Static polygon array (composes with `children`) |
46
+ | `children` | `ReactNode` | None | `<PolyMesh>`, `<Poly>`, and/or `<PolyOrbitControls>` |
47
+
48
+ For pointer drag, wheel zoom, and autorotate, mount `<PolyOrbitControls>` (or `<PolyMapControls>` for pan-first map-style input) inside `<PolyCamera>`: it receives the camera context. Mirrors Three.js's split between camera state and input.
49
+
50
+ ### `<PolyMesh>`
51
+
52
+ Loads a mesh from a URL and renders its polygons. Manages blob-URL lifecycle automatically.
53
+
54
+ | Prop | Type | Description |
55
+ |---|---|---|
56
+ | `src` | `string` | URL to `.obj`, `.glb`, `.gltf`, or `.vox` |
57
+ | `polygons` | `Polygon[]` | Pre-parsed polygons (alternative to `src`) |
58
+ | `position` | `Vec3` | `[x, y, z]` offset in scene space |
59
+ | `scale` | `number \| Vec3` | Uniform or per-axis scale |
60
+ | `rotation` | `Vec3` | Euler angles in degrees `[x, y, z]` |
61
+ | `atlasScale` | `number \| "auto"` | Raster scale for generated atlas pages |
62
+ | `autoCenter` | `boolean` | Shift mesh so its bbox center is at origin |
63
+ | `mtl` | `string` | Companion `.mtl` URL for OBJ models |
64
+ | `parseOptions` | `UseMeshOptions` | Forwarded to `loadMesh` |
65
+ | `fallback` | `ReactNode` | Rendered while loading |
66
+ | `errorFallback` | `(error: Error) => ReactNode` | Rendered on parse failure |
67
+ | `children` | `(polygon, index) => ReactNode` | Per-polygon render prop override |
68
+
69
+ ### `<Poly>`
70
+
71
+ Single polygon. The atomic primitive: renders one atlas-backed `<i>` for UV-textured and flat-color faces. Forwards all standard DOM props.
72
+
73
+ | Prop | Type | Description |
74
+ |---|---|---|
75
+ | `vertices` | `Vec3[]` | Required: 3+ `[x, y, z]` points |
76
+ | `color` | `string` | CSS color; used when no texture is set |
77
+ | `texture` | `string` | Image URL for UV-mapped rendering |
78
+ | `uvs` | `Vec2[]` | UV coordinates, one per vertex |
79
+ | `data` | `Record<string, string \| number \| boolean>` | Reflected as `data-*` DOM attributes |
80
+ | `position` | `Vec3` | Local offset |
81
+ | `scale` | `number \| Vec3` | Scale |
82
+ | `rotation` | `Vec3` | Euler rotation in degrees |
83
+ | `atlasScale` | `number \| "auto"` | Raster scale for generated atlas pages |
84
+ | `onClick` | `MouseEventHandler` | Standard DOM event handler |
85
+ | `onMouseEnter` | `MouseEventHandler` | |
86
+ | `className` | `string` | CSS class |
87
+ | `style` | `CSSProperties` | Inline style |
88
+ | `aria-label` | `string` | ARIA label |
89
+
90
+ ### `<PolyCamera>`
91
+
92
+ Camera wrapper for perspective, rotation, zoom, target, and dolly distance. React scenes must render inside `<PolyCamera>` (or `<PolyPerspectiveCamera>` / `<PolyOrthographicCamera>`) so controls and scenes share camera state.
93
+
94
+ ### Hooks
95
+
96
+ | Hook | Description |
97
+ |---|---|
98
+ | `usePolyCamera(options)` | Internal camera integration hook (used by `<PolyCamera>`) |
99
+ | `usePolySceneContext(polygons, options)` | Lower-level hook for building custom scene wrappers |
100
+ | `usePolyMesh(src, options?)` | Fetch + parse a mesh. Returns `{ polygons, loading, error, warnings, dispose }`. Manages blob-URL lifecycle: safe across rapid src changes and unmounts. |
101
+
102
+ ### Utility
103
+
104
+ | Export | Description |
105
+ |---|---|
106
+ | `injectPolyBaseStyles(doc?)` | Inject polycss base CSS into the document. Idempotent. Called automatically by `<PolyScene>`; manual call only needed for custom scene hosts. Polygon defaults are scoped to `.polycss-scene`. |
107
+
108
+ ## Re-exports from `@layoutit/polycss-core`
109
+
110
+ All types and core functions are re-exported for convenience, so you never need to add `@layoutit/polycss-core` to your dependencies:
111
+
112
+ ```ts
113
+ import type { Polygon, Vec2, Vec3, PolyDirectionalLight, PolyAmbientLight, ParseResult } from "@layoutit/polycss-react";
114
+ import { parseObj, parseGltf, parseVox, loadMesh, normalizePolygons, mergePolygons } from "@layoutit/polycss-react";
115
+ ```
116
+
117
+ ## Per-polygon interactivity example
118
+
119
+ ```tsx
120
+ import { useState } from "react";
121
+ import { PolyCamera, PolyScene, Poly } from "@layoutit/polycss-react";
122
+ import type { Polygon } from "@layoutit/polycss-react";
123
+
124
+ export function InteractiveMesh({ polygons }: { polygons: Polygon[] }) {
125
+ const [hoveredId, setHoveredId] = useState<number | null>(null);
126
+
127
+ return (
128
+ <PolyCamera rotX={65} rotY={45}>
129
+ <PolyScene>
130
+ {polygons.map((p, i) => (
131
+ <Poly
132
+ key={i}
133
+ {...p}
134
+ onClick={() => alert(`clicked polygon ${i}`)}
135
+ onMouseEnter={() => setHoveredId(i)}
136
+ onMouseLeave={() => setHoveredId(null)}
137
+ className={hoveredId === i ? "highlight" : ""}
138
+ style={{ transition: "filter 0.2s" }}
139
+ />
140
+ ))}
141
+ </PolyScene>
142
+ </PolyCamera>
143
+ );
144
+ }
145
+ ```
146
+
147
+ ```css
148
+ .highlight { filter: brightness(1.5); }
149
+ ```
150
+
151
+ ## `usePolyMesh`: imperative loading
152
+
153
+ ```tsx
154
+ import { PolyCamera, PolyScene, Poly, usePolyMesh } from "@layoutit/polycss-react";
155
+
156
+ function Viewer() {
157
+ const { polygons, loading, error } = usePolyMesh("/cottage.glb");
158
+
159
+ if (loading) return <div>Loading…</div>;
160
+ if (error) return <div>Error: {error.message}</div>;
161
+
162
+ return (
163
+ <PolyCamera>
164
+ <PolyScene>
165
+ {polygons.map((p, i) => <Poly key={i} {...p} />)}
166
+ </PolyScene>
167
+ </PolyCamera>
168
+ );
169
+ }
170
+ ```
171
+
172
+ ## Docs
173
+
174
+ Full documentation at [polycss.com](https://polycss.com).