glyphcss 0.0.1 → 0.0.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/dist/index.d.ts CHANGED
@@ -1,17 +1,17 @@
1
- import { G as GlyphcssSceneHandle, a as GlyphcssCamera, b as GlyphcssTriangle, c as GlyphcssDirectionalLight, d as GlyphcssAmbientLight } from './elements-Bb37NHHO.js';
2
- export { e as GlyphcssFirstPersonCameraHandle, f as GlyphcssFirstPersonCameraOptions, g as GlyphcssHotspotElement, h as GlyphcssHotspotHandle, i as GlyphcssHotspotOptions, j as GlyphcssMapControlsElement, k as GlyphcssMeshElement, l as GlyphcssMeshHandle, m as GlyphcssMeshTransform, n as GlyphcssOrbitControlsElement, o as GlyphcssOrthographicCameraElement, p as GlyphcssOrthographicCameraHandle, q as GlyphcssOrthographicCameraOptions, r as GlyphcssPerspectiveCameraElement, s as GlyphcssPerspectiveCameraHandle, t as GlyphcssPerspectiveCameraOptions, u as GlyphcssSceneElement, v as GlyphcssSceneOptions, w as createGlyphcssFirstPersonCamera, x as createGlyphcssOrthographicCamera, y as createGlyphcssPerspectiveCamera, z as createGlyphcssScene } from './elements-Bb37NHHO.js';
3
- import { Hotspot, HotspotCell, GridSize, WireframeEdge, RenderMode, CharRamp } from '@glyphcss/core';
1
+ import { G as GlyphSceneHandle, a as GlyphCamera, b as GlyphDirectionalLight, c as GlyphAmbientLight } from './elements-DVWVBIG0.js';
2
+ export { d as GlyphHotspotElement, e as GlyphHotspotHandle, f as GlyphHotspotOptions, g as GlyphMapControlsElement, h as GlyphMeshElement, i as GlyphMeshHandle, j as GlyphMeshTransform, k as GlyphOrbitControlsElement, l as GlyphOrthographicCameraElement, m as GlyphOrthographicCameraHandle, n as GlyphOrthographicCameraOptions, o as GlyphPerspectiveCameraElement, p as GlyphPerspectiveCameraHandle, q as GlyphPerspectiveCameraOptions, r as GlyphSceneElement, s as GlyphSceneOptions, t as createGlyphCamera, u as createGlyphOrthographicCamera, v as createGlyphPerspectiveCamera, w as createGlyphScene } from './elements-DVWVBIG0.js';
3
+ import { Hotspot, HotspotCell, GridSize, Polygon, WireframeEdge, RenderMode, CharRamp } from '@glyphcss/core';
4
4
  export * from '@glyphcss/core';
5
5
 
6
6
  /**
7
- * createGlyphcssOrbitControls — orbit-mode camera input for a GlyphcssScene.
7
+ * createGlyphOrbitControls — orbit-mode camera input for a GlyphScene.
8
8
  *
9
9
  * Left-drag rotates rotX / rotY around the target (orbit). Wheel zooms or
10
- * dollies. Mirrors polycss's createPolyOrbitControls semantics, adapted for
11
- * the ASCII rasterizer's GlyphcssCamera instead of the CSS matrix3d camera.
10
+ * dollies. Mirrors glyphcss's createPolyOrbitControls semantics, adapted for
11
+ * the ASCII rasterizer's GlyphCamera instead of the CSS matrix3d camera.
12
12
  */
13
13
 
14
- interface GlyphcssOrbitControlsOptions {
14
+ interface GlyphOrbitControlsOptions {
15
15
  /** Pointer-drag. Default: true. */
16
16
  drag?: boolean;
17
17
  /** Wheel / pinch zoom. Default: true. */
@@ -25,23 +25,23 @@ interface GlyphcssOrbitControlsOptions {
25
25
  pauseOnInteraction?: boolean;
26
26
  };
27
27
  }
28
- interface GlyphcssOrbitControlsHandle {
29
- update(opts: GlyphcssOrbitControlsOptions): void;
28
+ interface GlyphOrbitControlsHandle {
29
+ update(opts: GlyphOrbitControlsOptions): void;
30
30
  pause(): void;
31
31
  resume(): void;
32
32
  destroy(): void;
33
33
  }
34
- declare function createGlyphcssOrbitControls(scene: GlyphcssSceneHandle, options?: GlyphcssOrbitControlsOptions): GlyphcssOrbitControlsHandle;
34
+ declare function createGlyphOrbitControls(scene: GlyphSceneHandle, options?: GlyphOrbitControlsOptions): GlyphOrbitControlsHandle;
35
35
 
36
36
  /**
37
- * createGlyphcssMapControls — map/pan-mode camera input for a GlyphcssScene.
37
+ * createGlyphMapControls — map/pan-mode camera input for a GlyphScene.
38
38
  *
39
39
  * Left-drag pans the target (slippy-map semantics). Right-drag or
40
- * Shift+left-drag orbits. Wheel zooms. Mirrors polycss's createPolyMapControls
41
- * semantics, adapted for the ASCII rasterizer's GlyphcssCamera.
40
+ * Shift+left-drag orbits. Wheel zooms. Mirrors glyphcss's createPolyMapControls
41
+ * semantics, adapted for the ASCII rasterizer's GlyphCamera.
42
42
  */
43
43
 
44
- interface GlyphcssMapControlsOptions {
44
+ interface GlyphMapControlsOptions {
45
45
  drag?: boolean;
46
46
  wheel?: boolean;
47
47
  invert?: boolean | number;
@@ -51,35 +51,97 @@ interface GlyphcssMapControlsOptions {
51
51
  pauseOnInteraction?: boolean;
52
52
  };
53
53
  }
54
- interface GlyphcssMapControlsHandle {
55
- update(opts: GlyphcssMapControlsOptions): void;
54
+ interface GlyphMapControlsHandle {
55
+ update(opts: GlyphMapControlsOptions): void;
56
56
  pause(): void;
57
57
  resume(): void;
58
58
  destroy(): void;
59
59
  }
60
- declare function createGlyphcssMapControls(scene: GlyphcssSceneHandle, options?: GlyphcssMapControlsOptions): GlyphcssMapControlsHandle;
60
+ declare function createGlyphMapControls(scene: GlyphSceneHandle, options?: GlyphMapControlsOptions): GlyphMapControlsHandle;
61
61
 
62
62
  /**
63
- * createGlyphcssFirstPersonControls — first-person camera input for a GlyphcssScene.
63
+ * createGlyphFirstPersonControls — first-person camera input for a GlyphScene.
64
+ *
65
+ * Requires the scene to have a perspective camera. On attach, sets
66
+ * `camera.eyeMode = true` so the perspective projection switches to the
67
+ * eye-at-origin formulation (target = eye position, near-plane cull). On
68
+ * detach, restores `eyeMode = false`.
64
69
  *
65
70
  * Mouse-drag looks around (rotX/rotY). WASD or arrow keys move forward/backward/strafe.
66
- * Mirrors polycss's createPolyFirstPersonControls semantics for the ASCII rasterizer.
67
71
  */
68
72
 
69
- interface GlyphcssFirstPersonControlsOptions {
73
+ interface GlyphFirstPersonControlsOptions {
70
74
  drag?: boolean;
71
75
  keyboard?: boolean;
72
76
  moveSpeed?: number;
73
77
  lookSpeed?: number;
74
78
  invert?: boolean | number;
75
79
  }
76
- interface GlyphcssFirstPersonControlsHandle {
77
- update(opts: GlyphcssFirstPersonControlsOptions): void;
80
+ interface GlyphFirstPersonControlsHandle {
81
+ update(opts: GlyphFirstPersonControlsOptions): void;
78
82
  pause(): void;
79
83
  resume(): void;
80
84
  destroy(): void;
81
85
  }
82
- declare function createGlyphcssFirstPersonControls(scene: GlyphcssSceneHandle, options?: GlyphcssFirstPersonControlsOptions): GlyphcssFirstPersonControlsHandle;
86
+ declare function createGlyphFirstPersonControls(scene: GlyphSceneHandle, options?: GlyphFirstPersonControlsOptions): GlyphFirstPersonControlsHandle;
87
+
88
+ /**
89
+ * Mesh lookup helpers — mirrors voxcss's `findPolyMeshHandle`,
90
+ * `findMeshUnderPoint`, and `pointInMeshElement`.
91
+ *
92
+ * `findGlyphMeshHandle(host, id)` performs an O(n) walk of mesh elements
93
+ * under the given host, matching on the `data-glyph-mesh-id` attribute.
94
+ *
95
+ * `findMeshUnderPoint` and `pointInMeshElement` use bounding-box checks.
96
+ * TODO(hit-layer): replace the bbox check with proper polygon raycasting once
97
+ * the rasterizer hit-map is wired to the hit layer.
98
+ */
99
+
100
+ /**
101
+ * Given a host element and a string mesh id, return the mesh's HTMLElement
102
+ * (the `.glyph-mesh` wrapper div) if found, or `null`.
103
+ */
104
+ declare function findGlyphMeshHandle(host: HTMLElement, id: string): HTMLElement | null;
105
+ /**
106
+ * Bbox check — returns true when (x, y) in client coordinates falls inside
107
+ * the bounding rect of `el`.
108
+ *
109
+ * TODO(hit-layer): replace with polygon-level raycasting once available.
110
+ */
111
+ declare function pointInMeshElement(el: HTMLElement, clientX: number, clientY: number): boolean;
112
+ /**
113
+ * Returns the `.glyph-mesh` element whose bounding box contains the
114
+ * given client coordinates, or `null`.
115
+ *
116
+ * The `host` parameter scopes the search; pass the scene host element to
117
+ * avoid matching meshes from other scenes on the page.
118
+ *
119
+ * TODO(hit-layer): wire to rasterizer hit-map raycasting once available.
120
+ * Until then this returns a bbox-level approximation (not pixel-accurate).
121
+ */
122
+ declare function findMeshUnderPoint(host: HTMLElement | Document, clientX: number, clientY: number): HTMLElement | null;
123
+
124
+ /**
125
+ * Typed DOM event aliases for mesh interaction.
126
+ *
127
+ * `meshId` is populated when the event originates from a hit-layer lookup —
128
+ * it carries the string id of the mesh that was hit (the `id` prop / transform
129
+ * `id`).
130
+ *
131
+ * TODO(hit-layer): meshId will be set automatically once the rasterizer
132
+ * hit-map and per-polygon raycasting are wired into the hit-layer dispatch.
133
+ * Until then, consumers receive plain DOM events with `meshId` left undefined.
134
+ */
135
+ type GlyphPointerEvent = PointerEvent & {
136
+ meshId?: string;
137
+ };
138
+ type GlyphMouseEvent = MouseEvent & {
139
+ meshId?: string;
140
+ };
141
+ type GlyphWheelEvent = WheelEvent & {
142
+ meshId?: string;
143
+ };
144
+ type GlyphEventHandler<E = Event> = (event: E) => void;
83
145
 
84
146
  /**
85
147
  * Project a list of 3D hotspot anchors through the camera. Returns the
@@ -89,18 +151,18 @@ declare function createGlyphcssFirstPersonControls(scene: GlyphcssSceneHandle, o
89
151
  * the renderer and hit layer cannot drift out of sync as long as they
90
152
  * share a camera.
91
153
  */
92
- declare function projectHotspots(hotspots: readonly Hotspot[], camera: GlyphcssCamera, cols: number, rows: number, cellAspect: number): HotspotCell[];
154
+ declare function projectHotspots(hotspots: readonly Hotspot[], camera: GlyphCamera, cols: number, rows: number, cellAspect: number): HotspotCell[];
93
155
 
94
156
  interface RasterizeContextOptions {
95
- camera: GlyphcssCamera;
157
+ camera: GlyphCamera;
96
158
  grid: GridSize;
97
- /** Triangle list. Required for `solid` / `voxel` modes, optional otherwise. */
98
- triangles?: GlyphcssTriangle[];
99
- /** Explicit wireframe edges. If omitted in wireframe mode, edges are derived from `triangles`. */
159
+ /** Polygon list. Required for `solid` / `voxel` modes, optional otherwise. */
160
+ polygons?: Polygon[];
161
+ /** Explicit wireframe edges. If omitted in wireframe mode, edges are derived from `polygons` (fan-triangulated). */
100
162
  wireframe?: WireframeEdge[];
101
163
  mode?: RenderMode;
102
- directionalLight?: GlyphcssDirectionalLight;
103
- ambientLight?: GlyphcssAmbientLight;
164
+ directionalLight?: GlyphDirectionalLight;
165
+ ambientLight?: GlyphAmbientLight;
104
166
  /** Named wireframe glyph palette. Defaults to `"default"`. */
105
167
  glyphPalette?: string;
106
168
  /**
@@ -108,18 +170,34 @@ interface RasterizeContextOptions {
108
170
  * output is just one text node — fastest possible DOM update. Default `true`.
109
171
  */
110
172
  useColors?: boolean;
173
+ /**
174
+ * Smooth (Gouraud) shading. When `true`, per-pixel Lambert intensity is
175
+ * interpolated from per-vertex normals (averaged across adjacent polygons
176
+ * within `creaseAngle`). Default `false` — flat shading is glyph's default
177
+ * because the facets are part of the ASCII aesthetic.
178
+ */
179
+ smoothShading?: boolean;
180
+ /**
181
+ * Crease angle in degrees for smooth shading. Vertex normals are averaged
182
+ * across adjacent faces whose normals diverge by less than this angle;
183
+ * edges sharper than this stay flat-shaded. `0` collapses to pure flat
184
+ * shading; `180` smooths every shared vertex. Default `60`.
185
+ */
186
+ creaseAngle?: number;
111
187
  }
112
188
  interface RasterizeContext {
113
- camera: GlyphcssCamera;
189
+ camera: GlyphCamera;
114
190
  grid: GridSize;
115
- triangles: GlyphcssTriangle[];
191
+ polygons: Polygon[];
116
192
  wireframe: WireframeEdge[];
117
193
  mode: RenderMode;
118
- directionalLight: GlyphcssDirectionalLight;
119
- ambientLight: GlyphcssAmbientLight;
194
+ directionalLight: GlyphDirectionalLight;
195
+ ambientLight: GlyphAmbientLight;
120
196
  /** Named wireframe glyph palette passed to the rasterizer. */
121
197
  glyphPalette: string;
122
198
  useColors: boolean;
199
+ smoothShading: boolean;
200
+ creaseAngle: number;
123
201
  }
124
202
  declare function buildRasterizeContext(opts: RasterizeContextOptions): RasterizeContext;
125
203
 
@@ -172,6 +250,6 @@ declare const WIREFRAME_GLYPHS: WireframeGlyphTiers;
172
250
  /** Look up a named wireframe palette, falling back to `default`. */
173
251
  declare function getWireframeGlyphs(name: string): WireframeGlyphTiers;
174
252
 
175
- declare function injectGlyphcssBaseStyles(doc?: Document): void;
253
+ declare function injectGlyphBaseStyles(doc?: Document): void;
176
254
 
177
- export { DEFAULT_RAMP, GlyphcssAmbientLight, GlyphcssCamera, GlyphcssDirectionalLight, type GlyphcssFirstPersonControlsHandle, type GlyphcssFirstPersonControlsOptions, type GlyphcssMapControlsHandle, type GlyphcssMapControlsOptions, type GlyphcssOrbitControlsHandle, type GlyphcssOrbitControlsOptions, GlyphcssSceneHandle, GlyphcssTriangle, type RasterizeContext, type RasterizeContextOptions, SOLID_RAMP, WIREFRAME_GLYPHS, WIREFRAME_PALETTES, type WireframeGlyphTiers, bakeFrames, buildRasterizeContext, createGlyphcssFirstPersonControls, createGlyphcssMapControls, createGlyphcssOrbitControls, getWireframeGlyphs, injectGlyphcssBaseStyles, projectHotspots, rasterize };
255
+ export { DEFAULT_RAMP, GlyphAmbientLight, GlyphCamera, GlyphDirectionalLight, type GlyphEventHandler, type GlyphFirstPersonControlsHandle, type GlyphFirstPersonControlsOptions, type GlyphMapControlsHandle, type GlyphMapControlsOptions, type GlyphMouseEvent, type GlyphOrbitControlsHandle, type GlyphOrbitControlsOptions, type GlyphPointerEvent, GlyphSceneHandle, type GlyphWheelEvent, type RasterizeContext, type RasterizeContextOptions, SOLID_RAMP, WIREFRAME_GLYPHS, WIREFRAME_PALETTES, type WireframeGlyphTiers, bakeFrames, buildRasterizeContext, createGlyphFirstPersonControls, createGlyphMapControls, createGlyphOrbitControls, findGlyphMeshHandle, findMeshUnderPoint, getWireframeGlyphs, injectGlyphBaseStyles, pointInMeshElement, projectHotspots, rasterize };
package/dist/index.js CHANGED
@@ -1,9 +1,17 @@
1
- function D(n,t,e){let s=Math.cos(t),r=Math.sin(t),c=s*n[1]-r*n[0],o=r*n[1]+s*n[0],a=n[2],p=Math.cos(e),l=Math.sin(e),y=p*o-l*a,u=l*o+p*a;return[c,y,u]}function w(n={}){let t={rotX:n.rotX??0,rotY:n.rotY??0,distance:n.distance??3,scale:n.scale??.4,stretch:n.stretch??1,target:[0,0,0]},[e,s]=n.center??[.5,.5];return{kind:"perspective",get rotX(){return t.rotX},set rotX(r){t.rotX=r},get rotY(){return t.rotY},set rotY(r){t.rotY=r},get distance(){return t.distance},set distance(r){t.distance=r},get scale(){return t.scale},set scale(r){t.scale=r},get stretch(){return t.stretch},set stretch(r){t.stretch=r},get target(){return t.target},set target(r){t.target=r},project(r,c,o,a){let p=[r[0]-t.target[0],r[1]-t.target[1],r[2]-t.target[2]],l=D(p,t.rotY,t.rotX),y=30,u=1.5,b=l[2]*y,f=.001,d=1-b/t.distance;if(d<f)return[NaN,NaN,l[2]];let M=1/d,E=Math.min(c,o)*t.scale*u*M,T=c*e+l[0]*E*a*t.stretch,h=o*s+l[1]*E;return[T,h,l[2]]}}}function z(n={}){let t={rotX:n.rotX??0,rotY:n.rotY??0,distance:0,scale:n.zoom??.4,stretch:1,target:[0,0,0]},[e,s]=n.center??[.5,.5];return{kind:"orthographic",get rotX(){return t.rotX},set rotX(r){t.rotX=r},get rotY(){return t.rotY},set rotY(r){t.rotY=r},get distance(){return t.distance},set distance(r){t.distance=r},get scale(){return t.scale},set scale(r){t.scale=r},get stretch(){return t.stretch},set stretch(r){t.stretch=r},get target(){return t.target},set target(r){t.target=r},project(r,c,o,a){let p=[r[0]-t.target[0],r[1]-t.target[1],r[2]-t.target[2]],l=D(p,t.rotY,t.rotX),u=Math.min(c,o)*t.scale*1.5,b=c*e+l[0]*u*a*t.stretch,f=o*s+l[1]*u;return[b,f,l[2]]}}}function He(n={}){let t={rotX:n.rotX??Math.PI/2,rotY:n.rotY??0,distance:0,scale:1,stretch:1,target:n.origin??[0,0,0],focal:n.focal??1},[e,s]=n.center??[.5,.5];return{kind:"firstPerson",get rotX(){return t.rotX},set rotX(r){t.rotX=r},get rotY(){return t.rotY},set rotY(r){t.rotY=r},get distance(){return t.distance},set distance(r){t.distance=r,t.focal=Math.max(.05,r/100)},get scale(){return t.scale},set scale(r){t.scale=r},get stretch(){return t.stretch},set stretch(r){t.stretch=r},get target(){return t.target},set target(r){t.target=r},project(r,c,o,a){let p=[r[0]-t.target[0],r[1]-t.target[1],r[2]-t.target[2]],l=D(p,t.rotY,t.rotX);if(l[2]>=-.001)return[NaN,NaN,l[2]];let u=t.focal/-l[2],b=Math.min(c,o)*t.scale*u,f=c*e+l[0]*b*a*t.stretch,d=o*s+l[1]*b;return[f,d,l[2]]}}}import{trianglesToFeatureEdges as Pe}from"@glyphcss/core";var we={direction:[.5,.7,.5],intensity:1},Oe={intensity:.4};function V(n){let t=n.triangles??[],e=n.mode??(t.length?"solid":"wireframe"),s=n.wireframe??(e==="wireframe"?Pe(t):[]);return{camera:n.camera,grid:n.grid,triangles:t,wireframe:s,mode:e,directionalLight:n.directionalLight??we,ambientLight:n.ambientLight??Oe,glyphPalette:n.glyphPalette??"default",useColors:n.useColors??!0}}var ke=" .:-=+*#%@".split(""),Re=" .:-=+*#%@".split(""),F={default:{thin:"\xB7\u22C5\u2219\u02D9\xB7\u22C5\u2219".split(""),normal:"\u254B\u256C\u253C\u2573\u25C6\u25C7\u25CA\u25B2\u25B3\u25BC\u25BD\u25C8\u2B21\u2B22\u2234\u2235\u22A5\u2295\u2297\u2299\u229A\u229B".split(""),core:"\u2726\u2727\u2729\u25C9\u2299\u25CE".split(""),solid:" .:-=+*#%@".split("")},ascii:{thin:".'".split(""),normal:"+*x".split(""),core:"#@".split(""),solid:" .,:;!+=*xX#@".split("")},dots:{thin:"\xB7\u22C5".split(""),normal:"\u2022\u25CF".split(""),core:"\u25C9\u25CE".split(""),solid:" \xB7\u22C5\u2218\u2022\u25CF\u25C9\u25CE\u2B24".split("")},lines:{thin:"\u2500\u2502".split(""),normal:"\u2550\u2551".split(""),core:"\u2588".split(""),solid:" \u2500\u2550\u256C\u2551\u2588\u2593\u2592\u2591".split("")},blocks:{thin:"\u2591\u2581".split(""),normal:"\u2592\u2593\u258C\u2590\u2580\u2584".split(""),core:"\u2588".split(""),solid:" \u2591\u2592\u2593\u258C\u2590\u2588\u2580\u2584\u25A0".split("")},stars:{thin:"\xB7\u22C6".split(""),normal:"\u2726\u2727\u2729\u272A".split(""),core:"\u272B\u272C\u272D\u2605".split(""),solid:" \xB7\u22C6\u2217\u2726\u2727\u2729\u272A\u272B\u2605".split("")},arrows:{thin:"\xB7\u2219".split(""),normal:"\u2190\u2191\u2192\u2193".split(""),core:"\u2196\u2197\u2198\u2199\u2921\u2922".split(""),solid:" \xB7\u2219\u2191\u2197\u2192\u2198\u2193\u2199\u2190\u2196".split("")},braille:{thin:"\u2801\u2802\u2804\u2808".split(""),normal:"\u2803\u2805\u2806\u2809\u280A\u280B\u280C\u280D\u280E\u280F".split(""),core:"\u283F\u28FF".split(""),solid:" \u2801\u2803\u2807\u2827\u2837\u283F\u287F\u28FF".split("")},runes:{thin:".\xB7".split(""),normal:"\u16A0\u16A1\u16A2\u16A3\u16A4\u16A6\u16A8\u16B1\u16B2\u16B3\u16B7\u16B9\u16C3\u16C7\u16C9".split(""),core:"\u16DE\u16DF\u16E1\u16E2\u16E3".split(""),solid:" \xB7\u16A0\u16A3\u16A4\u16A8\u16B1\u16B7\u16DE\u16E2".split("")},math:{thin:"\u2219\u2218".split(""),normal:"\u2211\u220F\u222B\u221A\u221E\u2248\u2260\u2264\u2265\u2282\u2283\u2286\u2287".split(""),core:"\u222E\u222F\u2230\u2202".split(""),solid:" \u2219\u2218\u2211\u222B\u221A\u221E\u2248\u2295\u2297".split("")},binary:{thin:"\xB7.".split(""),normal:"01".split(""),core:"\u2588".split(""),solid:" .:01\u2588\u2588".split("")},hex:{thin:"\xB7\u2219".split(""),normal:"0123456789ABCDEF".split(""),core:"FFAA".split(""),solid:" 0123456789AF".split("")}},Fe=F.default;function I(n){return F[n]??F.default}function Y(n){let{camera:t,grid:e,wireframe:s,triangles:r,mode:c,directionalLight:o,ambientLight:a}=n,{cols:p,rows:l,cellAspect:y}=e;if(c==="solid")return Ie(n,p,l,y);let u=I(n.glyphPalette),b=new Uint8Array(p*l),f=n.useColors?new Array(p*l).fill(null):null;for(let d of s){let M=t.project(d.from,p,l,y),E=t.project(d.to,p,l,y);M[0]!==M[0]||E[0]!==E[0]||ze(b,f,M[0]|0,M[1]|0,E[0]|0,E[1]|0,d.weight??2,d.color??null,p,l)}return Ve(b,f,p,l,u)}function Ie(n,t,e,s){let{camera:r,triangles:c,directionalLight:o,ambientLight:a}=n,p=I(n.glyphPalette).solid,l=new Array(t*e).fill(" "),y=n.useColors,u=y?new Array(t*e).fill(null):null,b=new Float64Array(t*e).fill(-1/0),f=o.direction,d=Math.hypot(f[0],f[1],f[2])||1,M=f[0]/d,E=f[1]/d,T=f[2]/d,h=o.intensity??1,v=a.intensity??.4,G=N(o.color??"#ffffff"),C=N(a.color??"#ffffff");for(let g of c){let[i,x,L]=g.vertices,A=r.project(i,t,e,s),m=r.project(x,t,e,s),S=r.project(L,t,e,s);if(A[0]!==A[0]||m[0]!==m[0]||S[0]!==S[0])continue;let _=x[0]-i[0],P=x[1]-i[1],H=x[2]-i[2],le=L[0]-i[0],ce=L[1]-i[1],ae=L[2]-i[2],pe=P*ae-H*ce,ue=H*le-_*ae,de=_*ce-P*le,be=Math.hypot(pe,ue,de)||1,ve=(pe*M+ue*E+de*T)/be,R=Math.max(0,ve)*h,Ge=Math.min(1,Math.max(0,v+R)),Ee=Math.min(p.length-1,Ge*(p.length-1)|0),Me=p[Ee],he=null;if(y){let X=g.color?N(g.color):[255,255,255],Ce=v*C[0]/255+R*G[0]/255,Le=v*C[1]/255+R*G[1]/255,Ae=v*C[2]/255+R*G[2]/255,Se=Math.min(255,X[0]*Ce),Te=Math.min(255,X[1]*Le),_e=Math.min(255,X[2]*Ae);he=`#${B(Se)}${B(Te)}${B(_e)}`}let xe=(A[2]+m[2]+S[2])/3;Ye(A[0],A[1],m[0],m[1],S[0],S[1],xe,Me,he,l,u,b,t,e)}return Xe(l,u,t,e)}function Ye(n,t,e,s,r,c,o,a,p,l,y,u,b,f){let d=n,M=t,E=e,T=s,h=r,v=c;if(T<M){let g=d;d=E,E=g,g=M,M=T,T=g}if(v<M){let g=d;d=h,h=g,g=M,M=v,v=g}if(v<T){let g=E;E=h,h=g,g=T,T=v,v=g}let G=Math.max(0,Math.ceil(M)),C=Math.min(f-1,Math.floor(v));if(!(G>C))for(let g=G;g<=C;g++){let i=(g-M)/(v-M||1),x=d+(h-d)*i,L;if(g<T){let S=(g-M)/(T-M||1);L=d+(E-d)*S}else{let S=(g-T)/(v-T||1);L=E+(h-E)*S}let A=Math.max(0,Math.ceil(Math.min(x,L))),m=Math.min(b-1,Math.floor(Math.max(x,L)));for(let S=A;S<=m;S++){let _=g*b+S;o>u[_]&&(u[_]=o,l[_]=a,y&&(y[_]=p))}}}function Xe(n,t,e,s){let r=[],c=null,o="",a=()=>{o&&(c!==null?r.push(`<span style="color:${c}">${o}</span>`):r.push(o),o="")};for(let p=0;p<s;p++){for(let l=0;l<e;l++){let y=p*e+l,u=n[y],b=t&&u!==" "?t[y]??null:null;b!==c&&(a(),c=b),o+=u}a(),c=null,p<s-1&&r.push(`
2
- `)}return r.join("")}function De(n,t,e="y"){let{camera:s}=n,r=e==="y"?s.rotY:s.rotX,c=new Array(t);for(let o=0;o<t;o++){let a=r+o/t*Math.PI*2;e==="y"?s.rotY=a:s.rotX=a,c[o]=Y(n)}return e==="y"?s.rotY=r:s.rotX=r,c}function ze(n,t,e,s,r,c,o,a,p,l){let y=Math.abs(r-e),u=-Math.abs(c-s),b=e<r?1:-1,f=s<c?1:-1,d=y+u;for(;;){if(e>=0&&e<p&&s>=0&&s<l){let E=s*p+e;n[E]<o&&(n[E]=o,t&&(t[E]=a))}if(e===r&&s===c)break;let M=2*d;M>=u&&(d+=u,e+=b),M<=y&&(d+=y,s+=f)}}function Ve(n,t,e,s,r){let c=[],o=null,a="",p=()=>{a&&(o!==null?c.push(`<span style="color:${o}">${a}</span>`):c.push(a),a="")};for(let l=0;l<s;l++){for(let y=0;y<e;y++){let u=l*e+y,b=n[u],f,d;b===0?(f=" ",d=null):(f=b===1?r.thin[Math.random()*r.thin.length|0]:b===2?r.normal[Math.random()*r.normal.length|0]:r.core[Math.random()*r.core.length|0],d=t?t[u]??null:null),d!==o&&(p(),o=d),a+=f}p(),o=null,l<s-1&&c.push(`
3
- `)}return c.join("")}function N(n){let t=n.startsWith("#")?n.slice(1):n;if(t.length===3){let e=parseInt(t[0]+t[0],16),s=parseInt(t[1]+t[1],16),r=parseInt(t[2]+t[2],16);return[e||0,s||0,r||0]}if(t.length===6){let e=parseInt(t.slice(0,2),16),s=parseInt(t.slice(2,4),16),r=parseInt(t.slice(4,6),16);return[e||0,s||0,r||0]}return[255,255,255]}function B(n){let t=Math.max(0,Math.min(255,n|0)).toString(16);return t.length===1?"0"+t:t}var me="glyphcss-styles";function j(n){let t=n??(typeof document<"u"?document:void 0);if(!t||t.getElementById(me))return;let e=t.createElement("style");e.id=me,e.textContent=Ne,t.head.appendChild(e)}var Ne=`
1
+ function Fe(n,t,e){let o=Math.cos(t),r=Math.sin(t),s=o*n[1]-r*n[0],i=r*n[1]+o*n[0],a=n[2],u=Math.cos(e),c=Math.sin(e),h=u*i-c*a,d=c*i+u*a;return[s,h,d]}function K(n={}){let t={rotX:n.rotX??0,rotY:n.rotY??0,distance:n.distance??3,zoom:n.zoom??.4,stretch:n.stretch??1,target:[0,0,0],eyeMode:!1,focal:5},[e,o]=n.center??[.5,.5];return{kind:"perspective",get rotX(){return t.rotX},set rotX(r){t.rotX=r},get rotY(){return t.rotY},set rotY(r){t.rotY=r},get distance(){return t.distance},set distance(r){t.distance=r},get zoom(){return t.zoom},set zoom(r){t.zoom=r},get stretch(){return t.stretch},set stretch(r){t.stretch=r},get target(){return t.target},set target(r){t.target=r},get eyeMode(){return t.eyeMode},set eyeMode(r){t.eyeMode=r},project(r,s,i,a){let u=[r[0]-t.target[0],r[1]-t.target[1],r[2]-t.target[2]],c=Fe(u,t.rotY,t.rotX);if(t.eyeMode){if(c[2]>=-.001)return[NaN,NaN,c[2]];let x=t.focal/-c[2],p=Math.min(s,i)*t.zoom*x,b=s*e+c[0]*p*a*t.stretch,l=i*o+c[1]*p;return[b,l,c[2]]}let h=30,d=1.5,f=c[2]*h,m=.001,g=1-f/t.distance;if(g<m)return[NaN,NaN,c[2]];let L=1/g,E=Math.min(s,i)*t.zoom*d*L,S=s*e+c[0]*E*a*t.stretch,A=i*o+c[1]*E;return[S,A,c[2]]}}}function ee(n={}){let t={rotX:n.rotX??0,rotY:n.rotY??0,distance:0,zoom:n.zoom??.4,stretch:1,target:[0,0,0]},[e,o]=n.center??[.5,.5];return{kind:"orthographic",get rotX(){return t.rotX},set rotX(r){t.rotX=r},get rotY(){return t.rotY},set rotY(r){t.rotY=r},get distance(){return t.distance},set distance(r){t.distance=r},get zoom(){return t.zoom},set zoom(r){t.zoom=r},get stretch(){return t.stretch},set stretch(r){t.stretch=r},get target(){return t.target},set target(r){t.target=r},get eyeMode(){return!1},set eyeMode(r){},project(r,s,i,a){let u=[r[0]-t.target[0],r[1]-t.target[1],r[2]-t.target[2]],c=Fe(u,t.rotY,t.rotX),d=Math.min(s,i)*t.zoom*1.5,f=s*e+c[0]*d*a*t.stretch,m=i*o+c[1]*d;return[f,m,c[2]]}}}var tt=ee;var nt={direction:[.5,.7,.5],intensity:1},rt={intensity:.4};function ot(n){let t=new Set,e=[];for(let o of n){let r=o.vertices;if(!(r.length<2))for(let s=0;s<r.length;s++){let i=r[s],a=r[(s+1)%r.length],u=`${i[0]},${i[1]},${i[2]}`,c=`${a[0]},${a[1]},${a[2]}`,h=u<c?`${u}|${c}`:`${c}|${u}`;if(t.has(h))continue;t.add(h);let d={from:i,to:a,weight:2};o.color&&(d.color=o.color),e.push(d)}}return e}function fe(n){let t=n.polygons??[],e=n.mode??(t.length?"solid":"wireframe"),o=n.wireframe??(e==="wireframe"?ot(t):[]);return{camera:n.camera,grid:n.grid,polygons:t,wireframe:o,mode:e,directionalLight:n.directionalLight??nt,ambientLight:n.ambientLight??rt,glyphPalette:n.glyphPalette??"default",useColors:n.useColors??!0,smoothShading:n.smoothShading??!1,creaseAngle:n.creaseAngle??60}}var it=" .:-=+*#%@".split(""),st=" .:-=+*#%@".split(""),te={default:{thin:"\xB7\u22C5\u2219\u02D9\xB7\u22C5\u2219".split(""),normal:"\u254B\u256C\u253C\u2573\u25C6\u25C7\u25CA\u25B2\u25B3\u25BC\u25BD\u25C8\u2B21\u2B22\u2234\u2235\u22A5\u2295\u2297\u2299\u229A\u229B".split(""),core:"\u2726\u2727\u2729\u25C9\u2299\u25CE".split(""),solid:" .:-=+*#%@".split("")},ascii:{thin:".'".split(""),normal:"+*x".split(""),core:"#@".split(""),solid:" .,:;!+=*xX#@".split("")},dots:{thin:"\xB7\u22C5".split(""),normal:"\u2022\u25CF".split(""),core:"\u25C9\u25CE".split(""),solid:" \xB7\u22C5\u2218\u2022\u25CF\u25C9\u25CE\u2B24".split("")},lines:{thin:"\u2500\u2502".split(""),normal:"\u2550\u2551".split(""),core:"\u2588".split(""),solid:" \u2500\u2550\u256C\u2551\u2588\u2593\u2592\u2591".split("")},blocks:{thin:"\u2591\u2581".split(""),normal:"\u2592\u2593\u258C\u2590\u2580\u2584".split(""),core:"\u2588".split(""),solid:" \u2591\u2592\u2593\u258C\u2590\u2588\u2580\u2584\u25A0".split("")},stars:{thin:"\xB7\u22C6".split(""),normal:"\u2726\u2727\u2729\u272A".split(""),core:"\u272B\u272C\u272D\u2605".split(""),solid:" \xB7\u22C6\u2217\u2726\u2727\u2729\u272A\u272B\u2605".split("")},arrows:{thin:"\xB7\u2219".split(""),normal:"\u2190\u2191\u2192\u2193".split(""),core:"\u2196\u2197\u2198\u2199\u2921\u2922".split(""),solid:" \xB7\u2219\u2191\u2197\u2192\u2198\u2193\u2199\u2190\u2196".split("")},braille:{thin:"\u2801\u2802\u2804\u2808".split(""),normal:"\u2803\u2805\u2806\u2809\u280A\u280B\u280C\u280D\u280E\u280F".split(""),core:"\u283F\u28FF".split(""),solid:" \u2801\u2803\u2807\u2827\u2837\u283F\u287F\u28FF".split("")},runes:{thin:".\xB7".split(""),normal:"\u16A0\u16A1\u16A2\u16A3\u16A4\u16A6\u16A8\u16B1\u16B2\u16B3\u16B7\u16B9\u16C3\u16C7\u16C9".split(""),core:"\u16DE\u16DF\u16E1\u16E2\u16E3".split(""),solid:" \xB7\u16A0\u16A3\u16A4\u16A8\u16B1\u16B7\u16DE\u16E2".split("")},math:{thin:"\u2219\u2218".split(""),normal:"\u2211\u220F\u222B\u221A\u221E\u2248\u2260\u2264\u2265\u2282\u2283\u2286\u2287".split(""),core:"\u222E\u222F\u2230\u2202".split(""),solid:" \u2219\u2218\u2211\u222B\u221A\u221E\u2248\u2295\u2297".split("")},binary:{thin:"\xB7.".split(""),normal:"01".split(""),core:"\u2588".split(""),solid:" .:01\u2588\u2588".split("")},hex:{thin:"\xB7\u2219".split(""),normal:"0123456789ABCDEF".split(""),core:"FFAA".split(""),solid:" 0123456789AF".split("")}},lt=te.default;function ne(n){return te[n]??te.default}function re(n){let{camera:t,grid:e,wireframe:o,mode:r}=n,{cols:s,rows:i,cellAspect:a}=e;if(r==="solid")return at(n,s,i,a);let u=ne(n.glyphPalette),c=new Uint8Array(s*i),h=n.useColors?new Array(s*i).fill(null):null;for(let d of o){let f=t.project(d.from,s,i,a),m=t.project(d.to,s,i,a);f[0]!==f[0]||m[0]!==m[0]||mt(c,h,f[0]|0,f[1]|0,m[0]|0,m[1]|0,d.weight??2,d.color??null,s,i)}return ft(c,h,s,i,u)}function at(n,t,e,o){let{camera:r,polygons:s,directionalLight:i,ambientLight:a,smoothShading:u,creaseAngle:c}=n,h=ne(n.glyphPalette).solid,d=h.length-1,f=new Array(t*e).fill(" "),m=n.useColors,g=m?new Array(t*e).fill(null):null,L=new Float64Array(t*e).fill(-1/0),E=i.direction,S=Math.hypot(E[0],E[1],E[2])||1,A=E[0]/S,M=E[1]/S,x=E[2]/S,p=i.intensity??1,b=a.intensity??.4,l=ye(i.color??"#ffffff"),v=ye(a.color??"#ffffff"),G=u&&c>0?dt(s,c):null;for(let C=0;C<s.length;C++){let y=s[C],w=y.vertices;if(!(w.length<3))for(let _=1;_<w.length-1;_++){let H=_,I=_+1,z=w[0],P=w[H],F=w[I],O=r.project(z,t,e,o),k=r.project(P,t,e,o),Y=r.project(F,t,e,o);if(O[0]!==O[0]||k[0]!==k[0]||Y[0]!==Y[0])continue;let D=P[0]-z[0],B=P[1]-z[1],oe=P[2]-z[2],$=F[0]-z[0],N=F[1]-z[1],J=F[2]-z[2],Q=B*J-oe*N,j=oe*$-D*J,Pe=D*N-B*$,ie=Math.hypot(Q,j,Pe)||1,Be=Q/ie,We=j/ie,$e=Pe/ie,se,le,ae,ce,ue,de,pe,he,me;if(G){let U=G[C],X=U[0],V=U[H],q=U[I];se=X[0],le=X[1],ae=X[2],ce=V[0],ue=V[1],de=V[2],pe=q[0],he=q[1],me=q[2]}else se=ce=pe=Be,le=ue=he=We,ae=de=me=$e;let je=se*A+le*M+ae*x,Ue=ce*A+ue*M+de*x,qe=pe*A+he*M+me*x,Oe=Math.min(1,b+Math.max(0,je)*p),ke=Math.min(1,b+Math.max(0,Ue)*p),Re=Math.min(1,b+Math.max(0,qe)*p),Ie=null;if(m){let U=(Oe+ke+Re)/3,X=Math.max(0,U-b),V=y.color?ye(y.color):[255,255,255],q=b*v[0]/255+X*l[0]/255,Ke=b*v[1]/255+X*l[1]/255,Ze=b*v[2]/255+X*l[2]/255,Je=Math.min(255,V[0]*q),Qe=Math.min(255,V[1]*Ke),et=Math.min(255,V[2]*Ze);Ie=`#${ge(Je)}${ge(Qe)}${ge(et)}`}ut(O[0],O[1],O[2],Oe,k[0],k[1],k[2],ke,Y[0],Y[1],Y[2],Re,h,d,Ie,f,g,L,t,e)}}return pt(f,g,t,e)}var ct=new Float64Array([(0+.5)/16,(8+.5)/16,(2+.5)/16,(10+.5)/16,(12+.5)/16,(4+.5)/16,(14+.5)/16,(6+.5)/16,(3+.5)/16,(11+.5)/16,(1+.5)/16,(9+.5)/16,(15+.5)/16,(7+.5)/16,(13+.5)/16,(5+.5)/16]);function ut(n,t,e,o,r,s,i,a,u,c,h,d,f,m,g,L,E,S,A,M){let x=(r-n)*(c-t)-(s-t)*(u-n);if(x===0||x>0)return;let p=1/x,b=x>0,l=n<r?n:r;u<l&&(l=u);let v=n>r?n:r;u>v&&(v=u);let G=t<s?t:s;c<G&&(G=c);let C=t>s?t:s;c>C&&(C=c);let y=Math.max(0,Math.ceil(l)),w=Math.min(A-1,Math.floor(v)),_=Math.max(0,Math.ceil(G)),T=Math.min(M-1,Math.floor(C));if(!(y>w||_>T))for(let H=_;H<=T;H++){let I=H;for(let z=y;z<=w;z++){let P=z,F=(r-P)*(c-I)-(s-I)*(u-P),O=(u-P)*(t-I)-(c-I)*(n-P),k=(n-P)*(s-I)-(t-I)*(r-P);if(b?F<0||O<0||k<0:F>0||O>0||k>0)continue;let Y=(F*e+O*i+k*h)*p,D=H*A+z;if(Y>S[D]){S[D]=Y;let B=(F*o+O*a+k*d)*p,$=(B<0?0:B>1?1:B)*m,N=$|0,J=$-N,Q=ct[(H&3)*4+(z&3)],j=J>Q&&N<m?N+1:N;L[D]=f[j>m?m:j],E&&(E[D]=g)}}}}function dt(n,t){let e=n.length,o=new Array(e);for(let a=0;a<e;a++){let u=n[a].vertices;if(u.length<3){o[a]=[0,0,0];continue}let c=u[0],h=u[1],d=u[2],f=h[0]-c[0],m=h[1]-c[1],g=h[2]-c[2],L=d[0]-c[0],E=d[1]-c[1],S=d[2]-c[2],A=m*S-g*E,M=g*L-f*S,x=f*E-m*L,p=Math.hypot(A,M,x)||1;o[a]=[A/p,M/p,x/p]}let r=new Map;for(let a=0;a<e;a++){let u=n[a].vertices;for(let c=0;c<u.length;c++){let h=u[c],d=`${h[0]},${h[1]},${h[2]}`,f=r.get(d);f||(f=[],r.set(d,f)),(f.length===0||f[f.length-1]!==a)&&f.push(a)}}let s=Math.cos(t*Math.PI/180),i=new Array(e);for(let a=0;a<e;a++){let u=n[a].vertices,c=o[a],h=new Array(u.length);for(let d=0;d<u.length;d++){let f=u[d],m=r.get(`${f[0]},${f[1]},${f[2]}`),g=0,L=0,E=0;for(let A=0;A<m.length;A++){let M=m[A],x=o[M];c[0]*x[0]+c[1]*x[1]+c[2]*x[2]>=s&&(g+=x[0],L+=x[1],E+=x[2])}let S=Math.hypot(g,L,E)||1;h[d]=[g/S,L/S,E/S]}i[a]=h}return i}function pt(n,t,e,o){let r=[],s=null,i="",a=()=>{i&&(s!==null?r.push(`<span style="color:${s}">${i}</span>`):r.push(i),i="")};for(let u=0;u<o;u++){for(let c=0;c<e;c++){let h=u*e+c,d=n[h],f=t&&d!==" "?t[h]??null:null;f!==s&&(a(),s=f),i+=d}a(),s=null,u<o-1&&r.push(`
2
+ `)}return r.join("")}function ht(n,t,e="y"){let{camera:o}=n,r=e==="y"?o.rotY:o.rotX,s=new Array(t);for(let i=0;i<t;i++){let a=r+i/t*Math.PI*2;e==="y"?o.rotY=a:o.rotX=a,s[i]=re(n)}return e==="y"?o.rotY=r:o.rotX=r,s}function mt(n,t,e,o,r,s,i,a,u,c){let h=Math.abs(r-e),d=-Math.abs(s-o),f=e<r?1:-1,m=o<s?1:-1,g=h+d;for(;;){if(e>=0&&e<u&&o>=0&&o<c){let E=o*u+e;n[E]<i&&(n[E]=i,t&&(t[E]=a))}if(e===r&&o===s)break;let L=2*g;L>=d&&(g+=d,e+=f),L<=h&&(g+=h,o+=m)}}function ft(n,t,e,o,r){let s=[],i=null,a="",u=()=>{a&&(i!==null?s.push(`<span style="color:${i}">${a}</span>`):s.push(a),a="")};for(let c=0;c<o;c++){for(let h=0;h<e;h++){let d=c*e+h,f=n[d],m,g;f===0?(m=" ",g=null):(m=f===1?r.thin[Math.random()*r.thin.length|0]:f===2?r.normal[Math.random()*r.normal.length|0]:r.core[Math.random()*r.core.length|0],g=t?t[d]??null:null),g!==i&&(u(),i=g),a+=m}u(),i=null,c<o-1&&s.push(`
3
+ `)}return s.join("")}function ye(n){let t=n.startsWith("#")?n.slice(1):n;if(t.length===3){let e=parseInt(t[0]+t[0],16),o=parseInt(t[1]+t[1],16),r=parseInt(t[2]+t[2],16);return[e||0,o||0,r||0]}if(t.length===6){let e=parseInt(t.slice(0,2),16),o=parseInt(t.slice(2,4),16),r=parseInt(t.slice(4,6),16);return[e||0,o||0,r||0]}return[255,255,255]}function ge(n){let t=Math.max(0,Math.min(255,n|0)).toString(16);return t.length===1?"0"+t:t}var Ye="glyph-styles";function be(n){let t=n??(typeof document<"u"?document:void 0);if(!t||t.getElementById(Ye))return;let e=t.createElement("style");e.id=Ye,e.textContent=yt,t.head.appendChild(e)}var yt=`
4
+ /* \u2500\u2500 React / Vue host wrapper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
5
+
6
+ .glyph-host {
7
+ /* Fill the camera wrapper so autoSize can observe a non-zero height. */
8
+ width: 100%;
9
+ height: 100%;
10
+ }
11
+
4
12
  /* \u2500\u2500 Glyphcss scene container \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
5
13
 
6
- .glyphcss-scene {
14
+ .glyph-scene {
7
15
  position: relative;
8
16
  display: block;
9
17
  overflow: hidden;
@@ -12,8 +20,12 @@ function D(n,t,e){let s=Math.cos(t),r=Math.sin(t),c=s*n[1]-r*n[0],o=r*n[1]+s*n[0
12
20
 
13
21
  /* \u2500\u2500 ASCII output <pre> \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
14
22
 
15
- .glyphcss-scene .glyphcss-output {
16
- display: block;
23
+ .glyph-scene .glyph-output {
24
+ /* inline-block so the box shrinks to the text's natural width. With display:
25
+ block the pre inherits parent width, leaving empty space on the right, and
26
+ cellW = preRect.width / cols overshoots the actual character cell \u2014 placing
27
+ hotspots to the right of the rasterized glyph they're supposed to anchor. */
28
+ display: inline-block;
17
29
  margin: 0;
18
30
  padding: 0;
19
31
  font-family: monospace;
@@ -27,15 +39,24 @@ function D(n,t,e){let s=Math.cos(t),r=Math.sin(t),c=s*n[1]-r*n[0],o=r*n[1]+s*n[0
27
39
 
28
40
  /* \u2500\u2500 Hotspot overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
29
41
 
30
- .glyphcss-scene .glyphcss-hotspot-layer {
42
+ .glyph-scene .glyph-hotspot-layer {
31
43
  position: absolute;
32
44
  inset: 0;
33
45
  pointer-events: none;
46
+ /* Isolate the stacking context so per-hotspot z-index values (derived from
47
+ camera depth, sometimes negative) stay scoped INSIDE the layer. Without
48
+ this, a negative-z-index hotspot would render below the sibling <pre>,
49
+ hidden behind the rasterized glyphs. */
50
+ isolation: isolate;
34
51
  }
35
52
 
36
- .glyphcss-scene .glyphcss-hotspot {
53
+ .glyph-scene .glyph-hotspot {
37
54
  position: absolute;
38
55
  pointer-events: all;
39
56
  cursor: pointer;
57
+ /* Center the label on the projected anchor point rather than anchoring its
58
+ top-left corner there. Without this, padding / label width visually offset
59
+ the content from the 3D vertex being labelled. */
60
+ transform: translate(-50%, -50%);
40
61
  }
41
- `;function W(n,t,e,s,r){return n.map(c=>{let[o,a,p]=t.project(c.at,e,s,r),l=p>-3&&o>=0&&o<e&&a>=0&&a<s;return{id:c.id,col:o,row:a,depth:p,visible:l}})}var Be=1;function je(n,t){let{position:e,scale:s,rotation:r}=t;if(!e&&!s&&!r)return n;let[c,o,a]=e??[0,0,0],p=1,l=1,y=1;s!==void 0&&(typeof s=="number"?p=l=y=s:[p,l,y]=s);let[u,b,f]=r??[0,0,0],d=Math.cos(u),M=Math.sin(u),E=Math.cos(b),T=Math.sin(b),h=Math.cos(f),v=Math.sin(f);function G(C){let g=C[0]*p,i=C[1]*l,x=C[2]*y,L=h*g-v*i,A=v*g+h*i,m=x;return g=E*L+T*m,i=A,x=-T*L+E*m,L=g,A=d*i-M*x,m=M*i+d*x,[L+c,A+o,m+a]}return n.map(C=>({...C,vertices:[G(C.vertices[0]),G(C.vertices[1]),G(C.vertices[2])]}))}function U(n,t={}){j(n.ownerDocument??void 0);let e={mode:t.mode??"solid",glyphPalette:t.glyphPalette??"default",useColors:t.useColors??!0,cols:t.cols??80,rows:t.rows??24,cellAspect:t.cellAspect??2,directionalLight:t.directionalLight??{direction:[.5,.7,.5],intensity:1},ambientLight:t.ambientLight??{intensity:.4},camera:t.camera??w()},s=n.ownerDocument.createElement("div");s.className="glyphcss-scene";let r=n.ownerDocument.createElement("pre");r.className="glyphcss-output";let c=n.ownerDocument.createElement("div");c.className="glyphcss-hotspot-layer",s.appendChild(r),s.appendChild(c),n.appendChild(s);let o=new Map,a=[],p=!1;function l(){p||(p=!0,Promise.resolve().then(()=>{p=!1,y()}))}function y(){let h=[];for(let C of o.values()){let g=je(C.triangles,C.transform);for(let i of g)h.push(i)}let v=V({camera:e.camera,grid:{cols:e.cols,rows:e.rows,cellAspect:e.cellAspect},triangles:h,mode:e.mode,directionalLight:e.directionalLight,ambientLight:e.ambientLight,glyphPalette:e.glyphPalette,useColors:e.useColors}),G=Y(v);e.useColors?r.innerHTML=G:r.textContent=G,u()}function u(){let{cols:h,rows:v,cellAspect:G,camera:C}=e,g=W(a.map(A=>A.hotspot),C,h,v,G),i=r.getBoundingClientRect(),x=h>0?i.width/h:8,L=v>0?i.height/v:16;for(let A=0;A<a.length;A++){let{el:m}=a[A],S=g[A];S.visible?(m.style.display="",m.style.left=`${S.col*x}px`,m.style.top=`${S.row*L}px`,m.style.zIndex=String(Math.round(S.depth*1e3))):m.style.display="none"}}function b(h,v={}){let G=Be++;return o.set(G,{id:G,triangles:h,transform:v}),l(),{get id(){return G},get triangles(){return h},setTransform(C){let g=o.get(G);g&&(g.transform=C,l())},dispose(){o.delete(G),l()}}}function f(h,v){let G=n.ownerDocument.createElement("div");G.className="glyphcss-hotspot",G.setAttribute("data-hotspot-id",h.id);let[C,g]=h.size??[1,1];G.style.position="absolute",G.style.width=`${C}ch`,G.style.height=`${g*e.cellAspect}ch`,v&&G.addEventListener("click",v),c.appendChild(G);let i={hotspot:{id:h.id,at:h.at,size:h.size},el:G,onClick:v};return a.push(i),l(),{remove(){let x=a.indexOf(i);x>=0&&a.splice(x,1),v&&G.removeEventListener("click",v),c.removeChild(G),l()}}}function d(){y()}function M(h){h.mode!==void 0&&(e.mode=h.mode),h.glyphPalette!==void 0&&(e.glyphPalette=h.glyphPalette),h.useColors!==void 0&&(e.useColors=h.useColors),h.cols!==void 0&&(e.cols=h.cols),h.rows!==void 0&&(e.rows=h.rows),h.cellAspect!==void 0&&(e.cellAspect=h.cellAspect),h.directionalLight!==void 0&&(e.directionalLight=h.directionalLight),h.ambientLight!==void 0&&(e.ambientLight=h.ambientLight),h.camera!==void 0&&(e.camera=h.camera),l()}function E(){return{...e}}function T(){o.clear(),n.contains(s)&&n.removeChild(s)}return l(),{get host(){return n},get output(){return r},get camera(){return e.camera},add:b,addHotspot:f,rerender:d,setOptions:M,getOptions:E,destroy:T}}function q(n,t={}){let e=n.host,s=t.drag??!0,r=t.wheel??!0,c=fe(t.invert),o=t.animate??!1,a=!1,p=!1,l=null,y=null,u=null,b={x:0,y:0},f=n.camera;function d(i){if(!(!s||a)&&u===null&&i.isPrimary!==!1){i.preventDefault(),u=i.pointerId,b={x:i.clientX,y:i.clientY},e.style.cursor="grabbing";try{i.target.setPointerCapture(i.pointerId)}catch{}o&&o.pauseOnInteraction!==!1&&(p=!0)}}function M(i){if(u===null||i.pointerId!==u||!s||a)return;i.preventDefault();let x=i.clientX-b.x,L=i.clientY-b.y;b={x:i.clientX,y:i.clientY};let A=c,S=1/4*Math.PI/180;f.rotY=f.rotY-x*S*A,f.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,f.rotX+L*S*A)),n.rerender()}function E(i){if(u===i.pointerId){u=null,e.style.cursor=s&&!a?"grab":"";try{i.target.releasePointerCapture(i.pointerId)}catch{}o&&(p=!1)}}function T(i){if(!r||a)return;i.preventDefault();let x=i.deltaY*.001;f.scale=Math.max(.05,Math.min(10,f.scale*(1-x))),n.rerender()}function h(i){if(!(a||!o)){if(!p){let x=y!==null?Math.min(i-y,50):16.67,L=typeof o=="object"&&o.speed?o.speed:.3,A=typeof o=="object"&&o.axis?o.axis:"y",m=L*(Math.PI/180)*(x/16.67);A==="y"?f.rotY=f.rotY+m:f.rotX=f.rotX+m,n.rerender()}y=i,l=requestAnimationFrame(h)}}function v(){l===null&&typeof requestAnimationFrame<"u"&&o&&(l=requestAnimationFrame(h))}function G(){l!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(l),l=null),y=null}function C(){e.addEventListener("pointerdown",d),e.addEventListener("pointermove",M),e.addEventListener("pointerup",E),e.addEventListener("pointercancel",E),e.addEventListener("wheel",T,{passive:!1}),e.style.cursor=s?"grab":"",e.style.touchAction="none",e.style.userSelect="none"}function g(){e.removeEventListener("pointerdown",d),e.removeEventListener("pointermove",M),e.removeEventListener("pointerup",E),e.removeEventListener("pointercancel",E),e.removeEventListener("wheel",T),e.style.cursor="",e.style.touchAction="",e.style.userSelect=""}return C(),v(),{update(i){let x=!!o;s=i.drag??s,r=i.wheel??r,c=fe(i.invert),o=i.animate??o,!a&&u===null&&(e.style.cursor=s?"grab":"");let L=!!o;x&&!L?G():!x&&L&&v()},pause(){a||(a=!0,g(),G(),u=null,p=!1)},resume(){a&&(a=!1,C(),v())},destroy(){a||g(),G(),a=!0}}}function fe(n){return n===void 0||n===!1?1:n===!0?-1:n}function $(n,t={}){let e=n.host,s=t.drag??!0,r=t.wheel??!0,c=ye(t.invert),o=t.animate??!1,a=!1,p=!1,l=null,y=null,u=null,b={x:0,y:0},f=!1,d=n.camera,M=1/4*Math.PI/180,E=.02;function T(m){if(!(!s||a)&&u===null&&m.isPrimary!==!1){m.preventDefault(),u=m.pointerId,b={x:m.clientX,y:m.clientY},f=m.button===2,e.style.cursor="grabbing";try{m.target.setPointerCapture(m.pointerId)}catch{}o&&o.pauseOnInteraction!==!1&&(p=!0)}}function h(m){if(u===null||m.pointerId!==u||!s||a)return;m.preventDefault();let S=m.clientX-b.x,_=m.clientY-b.y;b={x:m.clientX,y:m.clientY};let P=c;if(f||m.shiftKey)d.rotY=d.rotY-S*M*P,d.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,d.rotX+_*M*P));else{let H=d.target;d.target=[H[0]-S*E/d.scale,H[1]-_*E/d.scale,H[2]]}n.rerender()}function v(m){if(u===m.pointerId){u=null,f=!1,e.style.cursor=s&&!a?"grab":"";try{m.target.releasePointerCapture(m.pointerId)}catch{}o&&(p=!1)}}function G(m){m.preventDefault()}function C(m){if(!r||a)return;m.preventDefault();let S=m.deltaY*.001;d.scale=Math.max(.05,Math.min(10,d.scale*(1-S))),n.rerender()}function g(m){if(!(a||!o)){if(!p){let S=y!==null?Math.min(m-y,50):16.67,_=typeof o=="object"&&o.speed?o.speed:.3,P=typeof o=="object"&&o.axis?o.axis:"y",H=_*(Math.PI/180)*(S/16.67);P==="y"?d.rotY=d.rotY+H:d.rotX=d.rotX+H,n.rerender()}y=m,l=requestAnimationFrame(g)}}function i(){l===null&&typeof requestAnimationFrame<"u"&&o&&(l=requestAnimationFrame(g))}function x(){l!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(l),l=null),y=null}function L(){e.addEventListener("pointerdown",T),e.addEventListener("pointermove",h),e.addEventListener("pointerup",v),e.addEventListener("pointercancel",v),e.addEventListener("contextmenu",G),e.addEventListener("wheel",C,{passive:!1}),e.style.cursor=s?"grab":"",e.style.touchAction="none",e.style.userSelect="none"}function A(){e.removeEventListener("pointerdown",T),e.removeEventListener("pointermove",h),e.removeEventListener("pointerup",v),e.removeEventListener("pointercancel",v),e.removeEventListener("contextmenu",G),e.removeEventListener("wheel",C),e.style.cursor="",e.style.touchAction="",e.style.userSelect=""}return L(),i(),{update(m){let S=!!o;s=m.drag??s,r=m.wheel??r,c=ye(m.invert),o=m.animate??o,!a&&u===null&&(e.style.cursor=s?"grab":"");let _=!!o;S&&!_?x():!S&&_&&i()},pause(){a||(a=!0,A(),x(),u=null,p=!1)},resume(){a&&(a=!1,L(),i())},destroy(){a||A(),x(),a=!0}}}function ye(n){return n===void 0||n===!1?1:n===!0?-1:n}function We(n,t={}){let e=n.host,s=t.drag??!0,r=t.keyboard??!0,c=t.moveSpeed??.05,o=t.lookSpeed??.004,a=ge(t.invert),p=!1,l=null,y={x:0,y:0},u=new Set,b=null,f=n.camera;function d(i){if(!(!s||p)&&l===null){i.preventDefault(),l=i.pointerId,y={x:i.clientX,y:i.clientY};try{i.target.setPointerCapture(i.pointerId)}catch{}}}function M(i){if(l===null||i.pointerId!==l||!s||p)return;i.preventDefault();let x=i.clientX-y.x,L=i.clientY-y.y;y={x:i.clientX,y:i.clientY},f.rotY=f.rotY-x*o*a,f.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,f.rotX+L*o*a)),n.rerender()}function E(i){if(l===i.pointerId){l=null;try{i.target.releasePointerCapture(i.pointerId)}catch{}}}function T(i){r&&!p&&u.add(i.key.toLowerCase())}function h(i){u.delete(i.key.toLowerCase())}function v(){if(p||!r||u.size===0)return;let i=f.target,x=Math.cos(f.rotY),L=Math.sin(f.rotY),A=!1;(u.has("w")||u.has("arrowup"))&&(f.target=[i[0]-L*c,i[1]-x*c,i[2]],A=!0),(u.has("s")||u.has("arrowdown"))&&(f.target=[i[0]+L*c,i[1]+x*c,i[2]],A=!0),(u.has("a")||u.has("arrowleft"))&&(f.target=[i[0]-x*c,i[1]+L*c,i[2]],A=!0),(u.has("d")||u.has("arrowright"))&&(f.target=[i[0]+x*c,i[1]-L*c,i[2]],A=!0),A&&n.rerender()}function G(){p||(v(),b=requestAnimationFrame(G))}function C(){e.addEventListener("pointerdown",d),e.addEventListener("pointermove",M),e.addEventListener("pointerup",E),e.addEventListener("pointercancel",E),r&&(e.ownerDocument?.addEventListener("keydown",T),e.ownerDocument?.addEventListener("keyup",h)),e.style.touchAction="none",e.style.userSelect="none",typeof requestAnimationFrame<"u"&&(b=requestAnimationFrame(G))}function g(){e.removeEventListener("pointerdown",d),e.removeEventListener("pointermove",M),e.removeEventListener("pointerup",E),e.removeEventListener("pointercancel",E),e.ownerDocument?.removeEventListener("keydown",T),e.ownerDocument?.removeEventListener("keyup",h),e.style.touchAction="",e.style.userSelect="",b!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(b),b=null),u.clear()}return C(),{update(i){s=i.drag??s,r=i.keyboard??r,c=i.moveSpeed??c,o=i.lookSpeed??o,a=ge(i.invert)},pause(){p||(p=!0,g(),l=null)},resume(){p&&(p=!1,C())},destroy(){p||g(),p=!0}}}function ge(n){return n===void 0||n===!1?1:n===!0?-1:n}var Ue=typeof HTMLElement<"u"?HTMLElement:class{},qe=["mode","glyph-palette","use-colors","cols","rows","cell-aspect","directional-direction","directional-intensity","ambient-intensity"];function O(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function $e(n){if(n==="wireframe"||n==="solid"||n==="voxel")return n}function Ze(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}var Z=class extends Ue{constructor(){super(...arguments);this._scene=null}static get observedAttributes(){return[...qe]}getScene(){return this._scene}_readOptions(){let e={},s=$e(this.getAttribute("mode"));s!==void 0&&(e.mode=s);let r=this.getAttribute("glyph-palette");r&&(e.glyphPalette=r);let c=Ze(this.getAttribute("use-colors"));c!==void 0&&(e.useColors=c);let o=O(this.getAttribute("cols"));o!==void 0&&(e.cols=o);let a=O(this.getAttribute("rows"));a!==void 0&&(e.rows=a);let p=O(this.getAttribute("cell-aspect"));p!==void 0&&(e.cellAspect=p);let l=O(this.getAttribute("directional-intensity"));l!==void 0&&(e.directionalLight={direction:[.5,.7,.5],intensity:l});let y=O(this.getAttribute("ambient-intensity"));return y!==void 0&&(e.ambientLight={intensity:y}),e}connectedCallback(){this._scene||(this._scene=U(this,this._readOptions()),this.dispatchEvent(new CustomEvent("glyphcss:scene-ready",{bubbles:!1})))}disconnectedCallback(){this._scene&&(this._scene.destroy(),this._scene=null)}attributeChangedCallback(e,s,r){s!==r&&this._scene&&this._scene.setOptions(this._readOptions())}};import{loadMesh as Ke}from"@glyphcss/core";var Je=typeof HTMLElement<"u"?HTMLElement:class{},Qe=["src","position","scale","rotation"];function K(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==3||t.some(e=>!Number.isFinite(e))))return[t[0],t[1],t[2]]}function et(n){if(n){if(!n.includes(",")){let t=parseFloat(n);return Number.isFinite(t)?t:void 0}return K(n)}}function tt(n){return n.closest("glyphcss-scene")??null}function nt(n){let t=[[0,0],[0,0],[0,0]],e=[];for(let s of n){let r=s.vertices;if(!(r.length<3))for(let c=1;c<r.length-1;c++)e.push({vertices:[r[0],r[c],r[c+1]],uvs:t,...s.color?{color:s.color}:{}})}return e}var J=class extends Je{constructor(){super(...arguments);this._handle=null;this._loadToken=0}static get observedAttributes(){return[...Qe]}getMeshHandle(){return this._handle}connectedCallback(){this._maybeLoad()}disconnectedCallback(){this._tearDown()}attributeChangedCallback(e,s,r){if(s!==r){if(e==="src"){this._tearDown(),this._maybeLoad();return}this._handle&&this._handle.setTransform(this._readTransform())}}_readTransform(){return{position:K(this.getAttribute("position")),scale:et(this.getAttribute("scale")),rotation:K(this.getAttribute("rotation"))}}_tearDown(){if(this._loadToken+=1,this._handle){try{this._handle.dispose()}catch{}this._handle=null}}async _maybeLoad(){let e=this.getAttribute("src");if(!e)return;let s=tt(this);if(!s)return;let r=++this._loadToken,c;try{c=await Ke(e)}catch(p){this.dispatchEvent(new CustomEvent("glyphcss:error",{detail:p,bubbles:!0}));return}if(r!==this._loadToken){try{c.dispose()}catch{}return}let o=s.getScene();if(!o){try{c.dispose()}catch{}return}let a=nt(c.polygons);this._handle=o.add(a,this._readTransform()),this.dispatchEvent(new CustomEvent("glyphcss:loaded",{detail:{triangles:a},bubbles:!0}))}};var rt=typeof HTMLElement<"u"?HTMLElement:class{};function st(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==3||t.some(e=>!Number.isFinite(e))))return[t[0],t[1],t[2]]}function ot(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==2||t.some(e=>!Number.isFinite(e))))return[t[0],t[1]]}function it(n){return n.closest("glyphcss-scene")??null}var Q=class extends rt{constructor(){super(...arguments);this._handle=null}static get observedAttributes(){return["at","size","hotspot-id"]}connectedCallback(){this._register()}disconnectedCallback(){this._handle&&(this._handle.remove(),this._handle=null)}attributeChangedCallback(e,s,r){s!==r&&(this._handle&&(this._handle.remove(),this._handle=null),this._register())}_register(){let e=st(this.getAttribute("at"));if(!e)return;let r=it(this)?.getScene();if(!r)return;let c=this.getAttribute("hotspot-id")??this.getAttribute("id")??String(Math.random()),o=ot(this.getAttribute("size"));this._handle=r.addHotspot({id:c,at:e,size:o},()=>this.dispatchEvent(new CustomEvent("glyphcss:hotspot-click",{detail:{id:c},bubbles:!0})))}};var lt=typeof HTMLElement<"u"?HTMLElement:class{};function k(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function ct(n){return n.closest("glyphcss-scene")??null}var ee=class extends lt{static get observedAttributes(){return["rot-x","rot-y","distance","scale","stretch"]}connectedCallback(){this._apply()}attributeChangedCallback(t,e,s){e!==s&&this._apply()}_apply(){let e=ct(this)?.getScene();if(!e)return;let s=w({rotX:k(this.getAttribute("rot-x")),rotY:k(this.getAttribute("rot-y")),distance:k(this.getAttribute("distance")),scale:k(this.getAttribute("scale")),stretch:k(this.getAttribute("stretch"))});e.setOptions({camera:s})}};var at=typeof HTMLElement<"u"?HTMLElement:class{};function te(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function pt(n){return n.closest("glyphcss-scene")??null}var ne=class extends at{static get observedAttributes(){return["rot-x","rot-y","zoom"]}connectedCallback(){this._apply()}attributeChangedCallback(t,e,s){e!==s&&this._apply()}_apply(){let e=pt(this)?.getScene();if(!e)return;let s=z({rotX:te(this.getAttribute("rot-x")),rotY:te(this.getAttribute("rot-y")),zoom:te(this.getAttribute("zoom"))});e.setOptions({camera:s})}};var ut=typeof HTMLElement<"u"?HTMLElement:class{};function dt(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function re(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}function ht(n){return n.closest("glyphcss-scene")??null}var se=class extends ut{constructor(){super(...arguments);this._controls=null}static get observedAttributes(){return["drag","wheel","invert","animate-speed","animate-axis"]}connectedCallback(){this._attach()}disconnectedCallback(){this._controls&&(this._controls.destroy(),this._controls=null)}attributeChangedCallback(e,s,r){s!==r&&this._controls?.update(this._readOptions())}_readOptions(){let e=re(this.getAttribute("drag")),s=re(this.getAttribute("wheel")),r=re(this.getAttribute("invert")),c=dt(this.getAttribute("animate-speed")),o=this.getAttribute("animate-axis")==="x"?"x":"y";return{...e!==void 0?{drag:e}:{},...s!==void 0?{wheel:s}:{},...r!==void 0?{invert:r}:{},...c!==void 0?{animate:{speed:c,axis:o}}:{}}}_attach(){if(this._controls)return;let e=ht(this);if(!e)return;let s=e.getScene();if(!s){let r=()=>{e.removeEventListener("glyphcss:scene-ready",r),this._attach()};e.addEventListener("glyphcss:scene-ready",r);return}this._controls=q(s,this._readOptions())}};var mt=typeof HTMLElement<"u"?HTMLElement:class{};function oe(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}function ft(n){return n.closest("glyphcss-scene")??null}var ie=class extends mt{constructor(){super(...arguments);this._controls=null}static get observedAttributes(){return["drag","wheel","invert"]}connectedCallback(){this._attach()}disconnectedCallback(){this._controls&&(this._controls.destroy(),this._controls=null)}attributeChangedCallback(e,s,r){s!==r&&this._controls?.update(this._readOptions())}_readOptions(){let e=oe(this.getAttribute("drag")),s=oe(this.getAttribute("wheel")),r=oe(this.getAttribute("invert"));return{...e!==void 0?{drag:e}:{},...s!==void 0?{wheel:s}:{},...r!==void 0?{invert:r}:{}}}_attach(){if(this._controls)return;let e=ft(this);if(!e)return;let s=e.getScene();if(!s){let r=()=>{e.removeEventListener("glyphcss:scene-ready",r),this._attach()};e.addEventListener("glyphcss:scene-ready",r);return}this._controls=$(s,this._readOptions())}};export*from"@glyphcss/core";export{ke as DEFAULT_RAMP,Q as GlyphcssHotspotElement,ie as GlyphcssMapControlsElement,J as GlyphcssMeshElement,se as GlyphcssOrbitControlsElement,ne as GlyphcssOrthographicCameraElement,ee as GlyphcssPerspectiveCameraElement,Z as GlyphcssSceneElement,Re as SOLID_RAMP,Fe as WIREFRAME_GLYPHS,F as WIREFRAME_PALETTES,De as bakeFrames,V as buildRasterizeContext,He as createGlyphcssFirstPersonCamera,We as createGlyphcssFirstPersonControls,$ as createGlyphcssMapControls,q as createGlyphcssOrbitControls,z as createGlyphcssOrthographicCamera,w as createGlyphcssPerspectiveCamera,U as createGlyphcssScene,I as getWireframeGlyphs,j as injectGlyphcssBaseStyles,W as projectHotspots,Y as rasterize};
62
+ `;function ve(n,t,e,o,r){return n.map(s=>{let[i,a,u]=t.project(s.at,e,o,r),c=u>-3&&i>=0&&i<e&&a>=0&&a<o;return{id:s.id,col:i,row:a,depth:u,visible:c}})}var gt=1;function bt(n,t){let{position:e,scale:o,rotation:r}=t;if(!e&&!o&&!r)return n;let[s,i,a]=e??[0,0,0],u=1,c=1,h=1;o!==void 0&&(typeof o=="number"?u=c=h=o:[u,c,h]=o);let[d,f,m]=r??[0,0,0],g=Math.cos(d),L=Math.sin(d),E=Math.cos(f),S=Math.sin(f),A=Math.cos(m),M=Math.sin(m);function x(p){let b=p[0]*u,l=p[1]*c,v=p[2]*h,G=A*b-M*l,C=M*b+A*l,y=v;return b=E*G+S*y,l=C,v=-S*G+E*y,G=b,C=g*l-L*v,y=L*l+g*v,[G+s,C+i,y+a]}return n.map(p=>({...p,vertices:p.vertices.map(x)}))}function Ee(n,t={}){be(n.ownerDocument??void 0);let e={mode:t.mode??"solid",glyphPalette:t.glyphPalette??"default",useColors:t.useColors??!0,cols:t.cols??80,rows:t.rows??24,cellAspect:t.cellAspect??2,directionalLight:t.directionalLight??{direction:[.5,.7,.5],intensity:1},ambientLight:t.ambientLight??{intensity:.4},camera:t.camera??K(),smoothShading:t.smoothShading??!1,creaseAngle:t.creaseAngle??60,autoSize:t.autoSize??!1},o=n.ownerDocument.createElement("div");o.className="glyph-scene";let r=n.ownerDocument.createElement("pre");r.className="glyph-output";let s=n.ownerDocument.createElement("div");s.className="glyph-hotspot-layer",o.appendChild(r),o.appendChild(s),n.appendChild(o);let i=new Map,a=[],u=!1;function c(){u||(u=!0,Promise.resolve().then(()=>{u=!1,h()}))}function h(){let p=[];for(let v of i.values()){let G=bt(v.polygons,v.transform);for(let C of G)p.push(C)}let b=fe({camera:e.camera,grid:{cols:e.cols,rows:e.rows,cellAspect:e.cellAspect},polygons:p,mode:e.mode,directionalLight:e.directionalLight,ambientLight:e.ambientLight,glyphPalette:e.glyphPalette,useColors:e.useColors,smoothShading:e.smoothShading,creaseAngle:e.creaseAngle}),l=re(b);e.useColors?r.innerHTML=l:r.textContent=l,d()}function d(){let{cols:p,rows:b,cellAspect:l,camera:v}=e,G=ve(a.map(_=>_.hotspot),v,p,b,l),C=r.getBoundingClientRect(),y=p>0?C.width/p:8,w=b>0?C.height/b:16;for(let _=0;_<a.length;_++){let{el:T}=a[_],H=G[_];H.visible?(T.style.display="",T.style.left=`${(H.col+.5)*y}px`,T.style.top=`${(H.row+.5)*w}px`,T.style.zIndex=String(Math.round(H.depth*1e3))):T.style.display="none"}}function f(p,b={}){let l=gt++;return i.set(l,{id:l,polygons:p,transform:b}),c(),{get id(){return l},get name(){return i.get(l)?.transform.id},get polygons(){return p},setTransform(v){let G=i.get(l);G&&(G.transform=v,c())},dispose(){i.delete(l),c()}}}function m(p,b){let l=n.ownerDocument.createElement("div");l.className="glyph-hotspot",l.setAttribute("data-hotspot-id",p.id);let[v,G]=p.size??[1,1];l.style.position="absolute",l.style.width=`${v}ch`,l.style.height=`${G*e.cellAspect}ch`,b&&l.addEventListener("click",b),s.appendChild(l);let C={hotspot:{id:p.id,at:p.at,size:p.size},el:l,onClick:b};return a.push(C),c(),{get el(){return l},remove(){let y=a.indexOf(C);y>=0&&a.splice(y,1),b&&l.removeEventListener("click",b),s.removeChild(l),c()}}}function g(){h()}function L(p){p.mode!==void 0&&(e.mode=p.mode),p.glyphPalette!==void 0&&(e.glyphPalette=p.glyphPalette),p.useColors!==void 0&&(e.useColors=p.useColors),p.cols!==void 0&&(e.cols=p.cols),p.rows!==void 0&&(e.rows=p.rows),p.cellAspect!==void 0&&(e.cellAspect=p.cellAspect),p.directionalLight!==void 0&&(e.directionalLight=p.directionalLight),p.ambientLight!==void 0&&(e.ambientLight=p.ambientLight),p.camera!==void 0&&(e.camera=p.camera),p.smoothShading!==void 0&&(e.smoothShading=p.smoothShading),p.creaseAngle!==void 0&&(e.creaseAngle=p.creaseAngle),p.autoSize!==void 0&&(e.autoSize=p.autoSize,e.autoSize&&!M&&typeof ResizeObserver<"u"?(M=new ResizeObserver(()=>A()),M.observe(n),A()):!e.autoSize&&M&&(M.disconnect(),M=null)),c()}function E(){return{...e}}function S(){let p=n.ownerDocument.createElement("span");p.textContent="M",p.style.cssText="position:absolute;visibility:hidden;font-family:inherit;font-size:inherit;line-height:inherit;white-space:pre;padding:0;margin:0",r.appendChild(p);let b=p.getBoundingClientRect();return p.remove(),{w:b.width||8,h:b.height||16}}function A(){let p=n.clientWidth,b=n.clientHeight;if(!p||!b)return;let l=S(),v=Math.max(20,Math.floor(p/l.w)),G=Math.max(8,Math.floor(b/l.h)),C=l.h/l.w,y=!1;e.cols!==v&&(e.cols=v,y=!0),e.rows!==G&&(e.rows=G,y=!0),Math.abs(e.cellAspect-C)>.01&&(e.cellAspect=C,y=!0),y&&c()}let M=null;e.autoSize&&typeof ResizeObserver<"u"&&(M=new ResizeObserver(()=>A()),M.observe(n),A());function x(){M&&(M.disconnect(),M=null),i.clear(),n.contains(o)&&n.removeChild(o)}return c(),{get host(){return n},get output(){return r},get camera(){return e.camera},add:f,addHotspot:m,rerender:g,setOptions:L,getOptions:E,fit:A,destroy:x}}function Ge(n,t={}){let e=n.host,o=t.drag??!0,r=t.wheel??!0,s=De(t.invert),i=t.animate??!1,a=!1,u=!1,c=null,h=null,d=null,f={x:0,y:0},m=n.camera;function g(l){if(!(!o||a)&&d===null&&l.isPrimary!==!1){l.preventDefault(),d=l.pointerId,f={x:l.clientX,y:l.clientY},e.style.cursor="grabbing";try{l.target.setPointerCapture(l.pointerId)}catch{}i&&i.pauseOnInteraction!==!1&&(u=!0)}}function L(l){if(d===null||l.pointerId!==d||!o||a)return;l.preventDefault();let v=l.clientX-f.x,G=l.clientY-f.y;f={x:l.clientX,y:l.clientY};let C=s,w=1/4*Math.PI/180;m.rotY=m.rotY-v*w*C,m.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,m.rotX-G*w*C)),n.rerender()}function E(l){if(d===l.pointerId){d=null,e.style.cursor=o&&!a?"grab":"";try{l.target.releasePointerCapture(l.pointerId)}catch{}i&&(u=!1)}}function S(l){if(!r||a)return;l.preventDefault();let v=l.deltaY*.001;m.zoom=Math.max(.05,Math.min(10,m.zoom*(1-v))),n.rerender()}function A(l){if(!(a||!i)){if(!u){let v=h!==null?Math.min(l-h,50):16.67,G=typeof i=="object"&&i.speed?i.speed:.3,C=typeof i=="object"&&i.axis?i.axis:"y",y=G*(Math.PI/180)*(v/16.67);C==="y"?m.rotY=m.rotY+y:m.rotX=m.rotX+y,n.rerender()}h=l,c=requestAnimationFrame(A)}}function M(){c===null&&typeof requestAnimationFrame<"u"&&i&&(c=requestAnimationFrame(A))}function x(){c!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(c),c=null),h=null}function p(){e.addEventListener("pointerdown",g),e.addEventListener("pointermove",L),e.addEventListener("pointerup",E),e.addEventListener("pointercancel",E),e.addEventListener("wheel",S,{passive:!1}),e.style.cursor=o?"grab":"",e.style.touchAction="none",e.style.userSelect="none"}function b(){e.removeEventListener("pointerdown",g),e.removeEventListener("pointermove",L),e.removeEventListener("pointerup",E),e.removeEventListener("pointercancel",E),e.removeEventListener("wheel",S),e.style.cursor="",e.style.touchAction="",e.style.userSelect=""}return p(),M(),{update(l){let v=!!i;o=l.drag??o,r=l.wheel??r,s=De(l.invert),i=l.animate??i,!a&&d===null&&(e.style.cursor=o?"grab":"");let G=!!i;v&&!G?x():!v&&G&&M()},pause(){a||(a=!0,b(),x(),d=null,u=!1)},resume(){a&&(a=!1,p(),M())},destroy(){a||b(),x(),a=!0}}}function De(n){return n===void 0||n===!1?1:n===!0?-1:n}function Me(n,t={}){let e=n.host,o=t.drag??!0,r=t.wheel??!0,s=Ne(t.invert),i=t.animate??!1,a=!1,u=!1,c=null,h=null,d=null,f={x:0,y:0},m=!1,g=n.camera,L=1/4*Math.PI/180,E=.02;function S(y){if(!(!o||a)&&d===null&&y.isPrimary!==!1){y.preventDefault(),d=y.pointerId,f={x:y.clientX,y:y.clientY},m=y.button===2,e.style.cursor="grabbing";try{y.target.setPointerCapture(y.pointerId)}catch{}i&&i.pauseOnInteraction!==!1&&(u=!0)}}function A(y){if(d===null||y.pointerId!==d||!o||a)return;y.preventDefault();let w=y.clientX-f.x,_=y.clientY-f.y;f={x:y.clientX,y:y.clientY};let T=s;if(m||y.shiftKey)g.rotY=g.rotY-w*L*T,g.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,g.rotX+_*L*T));else{let H=g.target;g.target=[H[0]-w*E/g.zoom,H[1]-_*E/g.zoom,H[2]]}n.rerender()}function M(y){if(d===y.pointerId){d=null,m=!1,e.style.cursor=o&&!a?"grab":"";try{y.target.releasePointerCapture(y.pointerId)}catch{}i&&(u=!1)}}function x(y){y.preventDefault()}function p(y){if(!r||a)return;y.preventDefault();let w=y.deltaY*.001;g.zoom=Math.max(.05,Math.min(10,g.zoom*(1-w))),n.rerender()}function b(y){if(!(a||!i)){if(!u){let w=h!==null?Math.min(y-h,50):16.67,_=typeof i=="object"&&i.speed?i.speed:.3,T=typeof i=="object"&&i.axis?i.axis:"y",H=_*(Math.PI/180)*(w/16.67);T==="y"?g.rotY=g.rotY+H:g.rotX=g.rotX+H,n.rerender()}h=y,c=requestAnimationFrame(b)}}function l(){c===null&&typeof requestAnimationFrame<"u"&&i&&(c=requestAnimationFrame(b))}function v(){c!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(c),c=null),h=null}function G(){e.addEventListener("pointerdown",S),e.addEventListener("pointermove",A),e.addEventListener("pointerup",M),e.addEventListener("pointercancel",M),e.addEventListener("contextmenu",x),e.addEventListener("wheel",p,{passive:!1}),e.style.cursor=o?"grab":"",e.style.touchAction="none",e.style.userSelect="none"}function C(){e.removeEventListener("pointerdown",S),e.removeEventListener("pointermove",A),e.removeEventListener("pointerup",M),e.removeEventListener("pointercancel",M),e.removeEventListener("contextmenu",x),e.removeEventListener("wheel",p),e.style.cursor="",e.style.touchAction="",e.style.userSelect=""}return G(),l(),{update(y){let w=!!i;o=y.drag??o,r=y.wheel??r,s=Ne(y.invert),i=y.animate??i,!a&&d===null&&(e.style.cursor=o?"grab":"");let _=!!i;w&&!_?v():!w&&_&&l()},pause(){a||(a=!0,C(),v(),d=null,u=!1)},resume(){a&&(a=!1,G(),l())},destroy(){a||C(),v(),a=!0}}}function Ne(n){return n===void 0||n===!1?1:n===!0?-1:n}function vt(n,t={}){if(n.camera.kind!=="perspective")throw new Error("glyphcss: GlyphFirstPersonControls requires a perspective camera. Use <GlyphPerspectiveCamera> (not <GlyphOrthographicCamera> / <GlyphCamera>).");n.camera.eyeMode=!0;let e=n.host,o=t.drag??!0,r=t.keyboard??!0,s=t.moveSpeed??.05,i=t.lookSpeed??.004,a=Xe(t.invert),u=!1,c=null,h={x:0,y:0},d=new Set,f=null,m=n.camera;function g(l){if(!(!o||u)&&c===null){l.preventDefault(),c=l.pointerId,h={x:l.clientX,y:l.clientY};try{l.target.setPointerCapture(l.pointerId)}catch{}}}function L(l){if(c===null||l.pointerId!==c||!o||u)return;l.preventDefault();let v=l.clientX-h.x,G=l.clientY-h.y;h={x:l.clientX,y:l.clientY},m.rotY=m.rotY-v*i*a,m.rotX=Math.max(-Math.PI/2,Math.min(Math.PI/2,m.rotX+G*i*a)),n.rerender()}function E(l){if(c===l.pointerId){c=null;try{l.target.releasePointerCapture(l.pointerId)}catch{}}}function S(l){r&&!u&&d.add(l.key.toLowerCase())}function A(l){d.delete(l.key.toLowerCase())}function M(){if(u||!r||d.size===0)return;let l=m.target,v=Math.cos(m.rotY),G=Math.sin(m.rotY),C=!1;(d.has("w")||d.has("arrowup"))&&(m.target=[l[0]-G*s,l[1]-v*s,l[2]],C=!0),(d.has("s")||d.has("arrowdown"))&&(m.target=[l[0]+G*s,l[1]+v*s,l[2]],C=!0),(d.has("a")||d.has("arrowleft"))&&(m.target=[l[0]-v*s,l[1]+G*s,l[2]],C=!0),(d.has("d")||d.has("arrowright"))&&(m.target=[l[0]+v*s,l[1]-G*s,l[2]],C=!0),C&&n.rerender()}function x(){u||(M(),f=requestAnimationFrame(x))}function p(){e.addEventListener("pointerdown",g),e.addEventListener("pointermove",L),e.addEventListener("pointerup",E),e.addEventListener("pointercancel",E),r&&(e.ownerDocument?.addEventListener("keydown",S),e.ownerDocument?.addEventListener("keyup",A)),e.style.touchAction="none",e.style.userSelect="none",typeof requestAnimationFrame<"u"&&(f=requestAnimationFrame(x))}function b(){e.removeEventListener("pointerdown",g),e.removeEventListener("pointermove",L),e.removeEventListener("pointerup",E),e.removeEventListener("pointercancel",E),e.ownerDocument?.removeEventListener("keydown",S),e.ownerDocument?.removeEventListener("keyup",A),e.style.touchAction="",e.style.userSelect="",f!==null&&(typeof cancelAnimationFrame<"u"&&cancelAnimationFrame(f),f=null),d.clear(),n.camera.eyeMode=!1}return p(),{update(l){o=l.drag??o,r=l.keyboard??r,s=l.moveSpeed??s,i=l.lookSpeed??i,a=Xe(l.invert)},pause(){u||(u=!0,b(),c=null)},resume(){u&&(u=!1,p())},destroy(){u||b(),u=!0}}}function Xe(n){return n===void 0||n===!1?1:n===!0?-1:n}function Et(n,t){let e=n.querySelector(`[data-glyph-mesh-id="${CSS.escape(t)}"]`);return e instanceof HTMLElement?e:null}function Ve(n,t,e){let o=n.getBoundingClientRect();return o.width<=0||o.height<=0?!1:t>=o.left&&t<=o.right&&e>=o.top&&e<=o.bottom}function Gt(n,t,e){let o=(n instanceof Document,n),r=Array.from(o.querySelectorAll(".glyph-mesh"));for(let s of r)if(Ve(s,t,e))return s;return null}var Mt=typeof HTMLElement<"u"?HTMLElement:class{},Ct=["mode","glyph-palette","use-colors","cols","rows","cell-aspect","directional-direction","directional-intensity","ambient-intensity","auto-size"];function Z(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function xt(n){if(n==="wireframe"||n==="solid"||n==="voxel")return n}function At(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}var Ce=class extends Mt{constructor(){super(...arguments);this._scene=null}static get observedAttributes(){return[...Ct]}getScene(){return this._scene}_readOptions(){let e={},o=xt(this.getAttribute("mode"));o!==void 0&&(e.mode=o);let r=this.getAttribute("glyph-palette");r&&(e.glyphPalette=r);let s=At(this.getAttribute("use-colors"));s!==void 0&&(e.useColors=s);let i=Z(this.getAttribute("cols"));i!==void 0&&(e.cols=i);let a=Z(this.getAttribute("rows"));a!==void 0&&(e.rows=a);let u=Z(this.getAttribute("cell-aspect"));u!==void 0&&(e.cellAspect=u);let c=Z(this.getAttribute("directional-intensity"));c!==void 0&&(e.directionalLight={direction:[.5,.7,.5],intensity:c});let h=Z(this.getAttribute("ambient-intensity"));return h!==void 0&&(e.ambientLight={intensity:h}),this.hasAttribute("auto-size")&&(e.autoSize=!0),e}_findCameraAncestor(){let e=this.parentElement;for(;e;){let o=e.tagName.toLowerCase();if(o==="glyph-perspective-camera"||o==="glyph-orthographic-camera")return e;e=e.parentElement}return null}_initScene(e){let o=typeof e.getCamera=="function"?e.getCamera():void 0,r=this._readOptions();o&&(r.camera=o),this._scene=Ee(this,r),this.dispatchEvent(new CustomEvent("glyphcss:scene-ready",{bubbles:!1}))}connectedCallback(){if(this._scene)return;let e=this._findCameraAncestor();if(!e)throw new Error("glyphcss: <glyph-scene> must be placed inside a <glyph-perspective-camera> or <glyph-orthographic-camera>.");if((typeof e.getCamera=="function"?e.getCamera():null)!==null)this._initScene(e);else{let r=()=>{e.removeEventListener("glyph:camera-ready",r),this._scene||this._initScene(e)};e.addEventListener("glyph:camera-ready",r)}}rerender(){this._scene?.rerender()}disconnectedCallback(){this._scene&&(this._scene.destroy(),this._scene=null)}attributeChangedCallback(e,o,r){o!==r&&this._scene&&this._scene.setOptions(this._readOptions())}};import{loadMesh as Lt,resolveGeometry as St,computeSceneBbox as wt}from"@glyphcss/core";var _t=typeof HTMLElement<"u"?HTMLElement:class{},Ht=["src","geometry","size","color","position","scale","rotation","normalize"];function Tt(n){let t=wt(n),e=(t.min[0]+t.max[0])/2,o=(t.min[1]+t.max[1])/2,r=(t.min[2]+t.max[2])/2,i=2/(Math.max(t.max[0]-t.min[0],t.max[1]-t.min[1],t.max[2]-t.min[2])||1);return n.map(a=>({...a,vertices:a.vertices.map(u=>[(u[0]-e)*i,(u[1]-o)*i,(u[2]-r)*i])}))}function xe(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==3||t.some(e=>!Number.isFinite(e))))return[t[0],t[1],t[2]]}function zt(n){if(n){if(!n.includes(",")){let t=parseFloat(n);return Number.isFinite(t)?t:void 0}return xe(n)}}function Pt(n){return n.closest("glyph-scene")??null}var Ae=class extends _t{constructor(){super(...arguments);this._handle=null;this._loadToken=0}static get observedAttributes(){return[...Ht]}getMeshHandle(){return this._handle}connectedCallback(){this._maybeLoad()}disconnectedCallback(){this._tearDown()}attributeChangedCallback(e,o,r){if(o!==r){if(e==="src"||e==="geometry"||e==="size"||e==="color"){this._tearDown(),this._maybeLoad();return}this._handle&&this._handle.setTransform(this._readTransform())}}_readTransform(){return{position:xe(this.getAttribute("position")),scale:zt(this.getAttribute("scale")),rotation:xe(this.getAttribute("rotation"))}}_tearDown(){if(this._loadToken+=1,this._handle){try{this._handle.dispose()}catch{}this._handle=null}}async _maybeLoad(){let e=this.getAttribute("src"),o=this.getAttribute("geometry"),r=Pt(this);if(r){if(!r.getScene()){let s=()=>{r.removeEventListener("glyphcss:scene-ready",s),this._maybeLoad()};r.addEventListener("glyphcss:scene-ready",s);return}if(e){let s=++this._loadToken,i;try{i=await Lt(e)}catch(h){this.dispatchEvent(new CustomEvent("glyphcss:error",{detail:h,bubbles:!0}));return}if(s!==this._loadToken){try{i.dispose()}catch{}return}let a=r.getScene();if(!a){try{i.dispose()}catch{}return}let c=this.hasAttribute("normalize")?Tt(i.polygons):i.polygons;this._handle=a.add(c,this._readTransform()),this.dispatchEvent(new CustomEvent("glyphcss:loaded",{detail:{polygons:c},bubbles:!0}));return}if(o){let s=r.getScene();if(!s)return;let i=this.getAttribute("size"),a=i!==null?parseFloat(i):1,u=this.getAttribute("color")??void 0,c;try{c=St(o,{size:Number.isFinite(a)?a:1,color:u})}catch(h){this.dispatchEvent(new CustomEvent("glyphcss:error",{detail:h,bubbles:!0}));return}this._handle=s.add(c,this._readTransform()),this.dispatchEvent(new CustomEvent("glyphcss:loaded",{detail:{polygons:c},bubbles:!0}))}}}};var Ot=typeof HTMLElement<"u"?HTMLElement:class{};function kt(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==3||t.some(e=>!Number.isFinite(e))))return[t[0],t[1],t[2]]}function Rt(n){if(!n)return;let t=n.split(",").map(e=>parseFloat(e.trim()));if(!(t.length!==2||t.some(e=>!Number.isFinite(e))))return[t[0],t[1]]}function It(n){return n.closest("glyph-scene")??null}var Le=class extends Ot{constructor(){super(...arguments);this._handle=null}static get observedAttributes(){return["at","size","hotspot-id"]}connectedCallback(){this._register()}disconnectedCallback(){this._handle&&this._unregister()}attributeChangedCallback(e,o,r){o!==r&&(this._handle&&this._unregister(),this._register())}_unregister(){if(!this._handle)return;let e=this._handle.el;for(;e.firstChild;)this.appendChild(e.firstChild);this._handle.remove(),this._handle=null}_register(){let e=kt(this.getAttribute("at"));if(!e)return;let o=It(this);if(!o)return;if(!o.getScene()){let u=()=>{o.removeEventListener("glyphcss:scene-ready",u),this._register()};o.addEventListener("glyphcss:scene-ready",u);return}let r=o.getScene();if(!r)return;let s=this.getAttribute("hotspot-id")??this.getAttribute("id")??String(Math.random()),i=Rt(this.getAttribute("size"));this._handle=r.addHotspot({id:s,at:e,size:i},()=>this.dispatchEvent(new CustomEvent("glyphcss:hotspot-click",{detail:{id:s},bubbles:!0})));let a=this._handle.el;for(;this.firstChild;)a.appendChild(this.firstChild)}};var Ft=typeof HTMLElement<"u"?HTMLElement:class{};function R(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}var Se=class extends Ft{constructor(){super(...arguments);this._camera=null}static get observedAttributes(){return["rot-x","rot-y","distance","zoom","stretch"]}getCamera(){return this._camera}connectedCallback(){this._camera=K({rotX:R(this.getAttribute("rot-x")),rotY:R(this.getAttribute("rot-y")),distance:R(this.getAttribute("distance")),zoom:R(this.getAttribute("zoom")),stretch:R(this.getAttribute("stretch"))}),this.dispatchEvent(new CustomEvent("glyph:camera-ready",{bubbles:!1}))}disconnectedCallback(){this._camera=null}attributeChangedCallback(e,o,r){if(o===r)return;let s=this._camera;if(!s)return;let i=R(this.getAttribute("rot-x")),a=R(this.getAttribute("rot-y")),u=R(this.getAttribute("distance")),c=R(this.getAttribute("zoom")),h=R(this.getAttribute("stretch")),d=!1;i!==void 0&&s.rotX!==i&&(s.rotX=i,d=!0),a!==void 0&&s.rotY!==a&&(s.rotY=a,d=!0),u!==void 0&&s.distance!==u&&(s.distance=u,d=!0),c!==void 0&&s.zoom!==c&&(s.zoom=c,d=!0),h!==void 0&&s.stretch!==h&&(s.stretch=h,d=!0),d&&this.querySelector("glyph-scene")?.rerender?.()}};var Yt=typeof HTMLElement<"u"?HTMLElement:class{};function W(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}var we=class extends Yt{constructor(){super(...arguments);this._camera=null}static get observedAttributes(){return["rot-x","rot-y","zoom"]}getCamera(){return this._camera}connectedCallback(){this._camera=ee({rotX:W(this.getAttribute("rot-x")),rotY:W(this.getAttribute("rot-y")),zoom:W(this.getAttribute("zoom"))}),this.dispatchEvent(new CustomEvent("glyph:camera-ready",{bubbles:!1}))}disconnectedCallback(){this._camera=null}attributeChangedCallback(e,o,r){if(o===r)return;let s=this._camera;if(!s)return;let i=W(this.getAttribute("rot-x")),a=W(this.getAttribute("rot-y")),u=W(this.getAttribute("zoom")),c=!1;i!==void 0&&s.rotX!==i&&(s.rotX=i,c=!0),a!==void 0&&s.rotY!==a&&(s.rotY=a,c=!0),u!==void 0&&s.zoom!==u&&(s.zoom=u,c=!0),c&&this.querySelector("glyph-scene")?.rerender?.()}};var Dt=typeof HTMLElement<"u"?HTMLElement:class{};function Nt(n){if(n==null)return;let t=parseFloat(n);return Number.isFinite(t)?t:void 0}function _e(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}function Xt(n){return n.closest("glyph-scene")??null}var He=class extends Dt{constructor(){super(...arguments);this._controls=null}static get observedAttributes(){return["drag","wheel","invert","animate-speed","animate-axis"]}connectedCallback(){this._attach()}disconnectedCallback(){this._controls&&(this._controls.destroy(),this._controls=null)}attributeChangedCallback(e,o,r){o!==r&&this._controls?.update(this._readOptions())}_readOptions(){let e=_e(this.getAttribute("drag")),o=_e(this.getAttribute("wheel")),r=_e(this.getAttribute("invert")),s=Nt(this.getAttribute("animate-speed")),i=this.getAttribute("animate-axis")==="x"?"x":"y";return{...e!==void 0?{drag:e}:{},...o!==void 0?{wheel:o}:{},...r!==void 0?{invert:r}:{},...s!==void 0?{animate:{speed:s,axis:i}}:{}}}_attach(){if(this._controls)return;let e=Xt(this);if(!e)return;let o=e.getScene();if(!o){let r=()=>{e.removeEventListener("glyphcss:scene-ready",r),this._attach()};e.addEventListener("glyphcss:scene-ready",r);return}this._controls=Ge(o,this._readOptions())}};var Vt=typeof HTMLElement<"u"?HTMLElement:class{};function Te(n){if(n!==null){if(n==="false")return!1;if(n==="true"||n==="")return!0}}function Bt(n){return n.closest("glyph-scene")??null}var ze=class extends Vt{constructor(){super(...arguments);this._controls=null}static get observedAttributes(){return["drag","wheel","invert"]}connectedCallback(){this._attach()}disconnectedCallback(){this._controls&&(this._controls.destroy(),this._controls=null)}attributeChangedCallback(e,o,r){o!==r&&this._controls?.update(this._readOptions())}_readOptions(){let e=Te(this.getAttribute("drag")),o=Te(this.getAttribute("wheel")),r=Te(this.getAttribute("invert"));return{...e!==void 0?{drag:e}:{},...o!==void 0?{wheel:o}:{},...r!==void 0?{invert:r}:{}}}_attach(){if(this._controls)return;let e=Bt(this);if(!e)return;let o=e.getScene();if(!o){let r=()=>{e.removeEventListener("glyphcss:scene-ready",r),this._attach()};e.addEventListener("glyphcss:scene-ready",r);return}this._controls=Me(o,this._readOptions())}};export*from"@glyphcss/core";export{it as DEFAULT_RAMP,Le as GlyphHotspotElement,ze as GlyphMapControlsElement,Ae as GlyphMeshElement,He as GlyphOrbitControlsElement,we as GlyphOrthographicCameraElement,Se as GlyphPerspectiveCameraElement,Ce as GlyphSceneElement,st as SOLID_RAMP,lt as WIREFRAME_GLYPHS,te as WIREFRAME_PALETTES,ht as bakeFrames,fe as buildRasterizeContext,tt as createGlyphCamera,vt as createGlyphFirstPersonControls,Me as createGlyphMapControls,Ge as createGlyphOrbitControls,ee as createGlyphOrthographicCamera,K as createGlyphPerspectiveCamera,Ee as createGlyphScene,Et as findGlyphMeshHandle,Gt as findMeshUnderPoint,ne as getWireframeGlyphs,be as injectGlyphBaseStyles,Ve as pointInMeshElement,ve as projectHotspots,re as rasterize};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "glyphcss",
3
- "version": "0.0.1",
4
- "description": "Glyphcss — ASCII paint backend with polycss's scene-composition API. Renders 3D meshes as ASCII art in a <pre> element.",
3
+ "version": "0.0.2",
4
+ "description": "Glyphcss — ASCII paint backend with glyphcss's scene-composition API. Renders 3D meshes as ASCII art in a <pre> element.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
@@ -33,7 +33,7 @@
33
33
  }
34
34
  },
35
35
  "dependencies": {
36
- "@glyphcss/core": "^0.0.1"
36
+ "@glyphcss/core": "^0.0.2"
37
37
  },
38
38
  "devDependencies": {
39
39
  "tsup": "^8.0.1",