@fonsecabarreto/genesis-gl-react 0.1.31 → 0.1.33

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.
@@ -0,0 +1,579 @@
1
+ import {
2
+ useCameraControls,
3
+ useCameraMouseDrag,
4
+ useGenesisGL,
5
+ useRenderer,
6
+ useWorldToScreen
7
+ } from "./chunk-MAGVIIUT.js";
8
+
9
+ // src/components/GenesisGLCanvas.tsx
10
+ import React, { useRef, useCallback, useEffect } from "react";
11
+ import { jsx } from "react/jsx-runtime";
12
+ var GenesisGLCanvas = React.forwardRef(
13
+ ({
14
+ onReady,
15
+ onFrame,
16
+ width,
17
+ height,
18
+ initialYaw,
19
+ initialPitch,
20
+ initialZoom,
21
+ background,
22
+ style,
23
+ className
24
+ }, ref) => {
25
+ const canvasRef = useRef(null);
26
+ const setRef = useCallback(
27
+ (el) => {
28
+ canvasRef.current = el;
29
+ if (typeof ref === "function") ref(el);
30
+ else if (ref) ref.current = el;
31
+ },
32
+ [ref]
33
+ );
34
+ const onFrameRef = useRef(onFrame);
35
+ onFrameRef.current = onFrame;
36
+ const genesisContext = useGenesisGL({
37
+ canvasRef,
38
+ width,
39
+ height,
40
+ initialYaw,
41
+ initialPitch,
42
+ initialZoom,
43
+ onReady
44
+ });
45
+ const genesisContextRef = useRef(genesisContext);
46
+ genesisContextRef.current = genesisContext;
47
+ const stableOnFrame = useCallback((time) => {
48
+ const { renderer, scene } = genesisContextRef.current;
49
+ if (renderer && scene) {
50
+ renderer.render(scene);
51
+ onFrameRef.current?.(time);
52
+ }
53
+ }, []);
54
+ useEffect(() => {
55
+ if (genesisContext.renderer && background) {
56
+ genesisContext.renderer.clearColor = background;
57
+ }
58
+ }, [genesisContext.renderer, background]);
59
+ useRenderer({ renderer: genesisContext.renderer, onFrame: stableOnFrame });
60
+ useCameraMouseDrag(genesisContext, canvasRef);
61
+ return /* @__PURE__ */ jsx(
62
+ "canvas",
63
+ {
64
+ ref: setRef,
65
+ style: { display: "block", width: "100%", height: "100%", ...style },
66
+ className
67
+ }
68
+ );
69
+ }
70
+ );
71
+ GenesisGLCanvas.displayName = "GenesisGLCanvas";
72
+
73
+ // src/components/ViewportGizmo.tsx
74
+ import { useRef as useRef2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
75
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
76
+ var FACES = [
77
+ { label: "+X", dir: [1, 0, 0], color: "#ff5370" },
78
+ { label: "-X", dir: [-1, 0, 0], color: "#ff5370", dim: true },
79
+ { label: "+Y", dir: [0, 1, 0], color: "#c3e88d" },
80
+ { label: "-Y", dir: [0, -1, 0], color: "#c3e88d", dim: true },
81
+ { label: "+Z", dir: [0, 0, 1], color: "#82aaff" },
82
+ { label: "-Z", dir: [0, 0, -1], color: "#82aaff", dim: true }
83
+ ];
84
+ var SNAP_PITCH = {
85
+ "+Y": Math.PI / 2 - 0.01,
86
+ "-Y": -(Math.PI / 2 - 0.01)
87
+ };
88
+ function project(dir, yaw, pitch, radius) {
89
+ const [dx, dy, dz] = dir;
90
+ const cosY = Math.cos(-yaw);
91
+ const sinY = Math.sin(-yaw);
92
+ const rx = dx * cosY + dz * sinY;
93
+ const ry = dy;
94
+ const rz = -dx * sinY + dz * cosY;
95
+ const cosP = Math.cos(-pitch);
96
+ const sinP = Math.sin(-pitch);
97
+ const fx = rx;
98
+ const fy = ry * cosP - rz * sinP;
99
+ const fz = ry * sinP + rz * cosP;
100
+ return { x: fx * radius, y: -fy * radius, z: fz };
101
+ }
102
+ var DRAG_SENSITIVITY = 8e-3;
103
+ function ViewportGizmo({
104
+ context,
105
+ size = 96,
106
+ position = "top-right",
107
+ style
108
+ }) {
109
+ const { camera, setYaw, setPitch, rotate } = useCameraControls(context);
110
+ const dragging = useRef2(false);
111
+ const lastPos = useRef2({ x: 0, y: 0 });
112
+ const containerRef = useRef2(null);
113
+ const onMouseDown = useCallback2((e) => {
114
+ if (e.button !== 0) return;
115
+ dragging.current = true;
116
+ lastPos.current = { x: e.clientX, y: e.clientY };
117
+ e.stopPropagation();
118
+ e.preventDefault();
119
+ }, []);
120
+ useEffect2(() => {
121
+ const onMove = (e) => {
122
+ if (!dragging.current) return;
123
+ const dx = e.clientX - lastPos.current.x;
124
+ const dy = e.clientY - lastPos.current.y;
125
+ lastPos.current = { x: e.clientX, y: e.clientY };
126
+ rotate(-dx * DRAG_SENSITIVITY, -dy * DRAG_SENSITIVITY);
127
+ };
128
+ const onUp = () => {
129
+ dragging.current = false;
130
+ };
131
+ window.addEventListener("mousemove", onMove);
132
+ window.addEventListener("mouseup", onUp);
133
+ return () => {
134
+ window.removeEventListener("mousemove", onMove);
135
+ window.removeEventListener("mouseup", onUp);
136
+ };
137
+ }, [rotate]);
138
+ const snapTo = useCallback2((face) => {
139
+ const [dx, , dz] = face.dir;
140
+ const targetYaw = Math.atan2(dx, dz);
141
+ const targetPitch = SNAP_PITCH[face.label] ?? 0;
142
+ setYaw(targetYaw);
143
+ setPitch(targetPitch);
144
+ }, [setYaw, setPitch]);
145
+ const half = size / 2;
146
+ const dotRadius = size * 0.14;
147
+ const orbitRadius = half * 0.62;
148
+ const projected = FACES.map((face) => ({
149
+ ...face,
150
+ ...project(face.dir, camera.yaw, camera.pitch, orbitRadius)
151
+ })).sort((a, b) => a.z - b.z);
152
+ const posStyle = position === "top-right" ? { top: 12, right: 12 } : position === "top-left" ? { top: 12, left: 12 } : position === "bottom-right" ? { bottom: 12, right: 12 } : { bottom: 12, left: 12 };
153
+ return /* @__PURE__ */ jsx2(
154
+ "div",
155
+ {
156
+ ref: containerRef,
157
+ onMouseDown,
158
+ style: {
159
+ position: "absolute",
160
+ width: size,
161
+ height: size,
162
+ borderRadius: "50%",
163
+ background: "rgba(8,8,14,0.55)",
164
+ border: "1px solid rgba(255,255,255,0.07)",
165
+ backdropFilter: "blur(8px)",
166
+ cursor: dragging.current ? "grabbing" : "grab",
167
+ userSelect: "none",
168
+ ...posStyle,
169
+ ...style
170
+ },
171
+ children: /* @__PURE__ */ jsxs(
172
+ "svg",
173
+ {
174
+ width: size,
175
+ height: size,
176
+ viewBox: `${-half} ${-half} ${size} ${size}`,
177
+ style: { overflow: "visible", display: "block" },
178
+ children: [
179
+ ["x", "y", "z"].map((axis) => {
180
+ const pos = projected.find((f) => f.label === `+${axis.toUpperCase()}`);
181
+ const neg = projected.find((f) => f.label === `-${axis.toUpperCase()}`);
182
+ if (!pos || !neg) return null;
183
+ return /* @__PURE__ */ jsx2(
184
+ "line",
185
+ {
186
+ x1: neg.x,
187
+ y1: neg.y,
188
+ x2: pos.x,
189
+ y2: pos.y,
190
+ stroke: pos.color,
191
+ strokeWidth: 1.5,
192
+ strokeOpacity: 0.35
193
+ },
194
+ axis
195
+ );
196
+ }),
197
+ projected.map((face) => {
198
+ const isFront = face.z >= 0;
199
+ const opacity = isFront ? 1 : 0.28;
200
+ const r = isFront ? dotRadius : dotRadius * 0.75;
201
+ return /* @__PURE__ */ jsxs(
202
+ "g",
203
+ {
204
+ style: { cursor: "pointer" },
205
+ onClick: (e) => {
206
+ e.stopPropagation();
207
+ snapTo(face);
208
+ },
209
+ children: [
210
+ /* @__PURE__ */ jsx2(
211
+ "circle",
212
+ {
213
+ cx: face.x,
214
+ cy: face.y,
215
+ r,
216
+ fill: face.color,
217
+ fillOpacity: opacity * (face.dim ? 0.6 : 1),
218
+ stroke: face.color,
219
+ strokeWidth: isFront ? 1.5 : 0.5,
220
+ strokeOpacity: opacity * 0.6
221
+ }
222
+ ),
223
+ isFront && /* @__PURE__ */ jsx2(
224
+ "text",
225
+ {
226
+ x: face.x,
227
+ y: face.y,
228
+ textAnchor: "middle",
229
+ dominantBaseline: "central",
230
+ fontSize: r * 0.75,
231
+ fontWeight: 700,
232
+ fontFamily: "system-ui, monospace",
233
+ fill: "#fff",
234
+ fillOpacity: 0.9,
235
+ style: { pointerEvents: "none" },
236
+ children: face.label
237
+ }
238
+ )
239
+ ]
240
+ },
241
+ face.label
242
+ );
243
+ })
244
+ ]
245
+ }
246
+ )
247
+ }
248
+ );
249
+ }
250
+
251
+ // src/components/RotationControls.tsx
252
+ import { useState } from "react";
253
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
254
+ var STEP = 0.05;
255
+ function IconBtn({
256
+ children,
257
+ title,
258
+ onClick,
259
+ color
260
+ }) {
261
+ const [active, setActive] = useState(false);
262
+ const [hover, setHover] = useState(false);
263
+ return /* @__PURE__ */ jsx3(
264
+ "button",
265
+ {
266
+ title,
267
+ onClick,
268
+ onMouseEnter: () => setHover(true),
269
+ onMouseLeave: () => {
270
+ setHover(false);
271
+ setActive(false);
272
+ },
273
+ onMouseDown: () => setActive(true),
274
+ onMouseUp: () => setActive(false),
275
+ style: {
276
+ display: "flex",
277
+ alignItems: "center",
278
+ justifyContent: "center",
279
+ width: "22px",
280
+ height: "22px",
281
+ border: `1px solid ${hover ? color + "88" : color + "33"}`,
282
+ borderRadius: "5px",
283
+ background: active ? color + "30" : hover ? color + "18" : color + "0c",
284
+ color: hover ? color : color + "aa",
285
+ cursor: "pointer",
286
+ fontSize: "11px",
287
+ fontWeight: 700,
288
+ lineHeight: 1,
289
+ padding: 0,
290
+ transition: "all 0.12s",
291
+ transform: active ? "scale(0.88)" : "scale(1)",
292
+ flexShrink: 0
293
+ },
294
+ children
295
+ }
296
+ );
297
+ }
298
+ function AxisPill({
299
+ label,
300
+ color,
301
+ value,
302
+ onDec,
303
+ onInc,
304
+ onReset
305
+ }) {
306
+ const deg = (value * 180 / Math.PI).toFixed(1);
307
+ const normalized = (value % (Math.PI * 2) + Math.PI * 2) % (Math.PI * 2);
308
+ const pct = normalized / (Math.PI * 2) * 100;
309
+ return /* @__PURE__ */ jsxs2(
310
+ "div",
311
+ {
312
+ style: {
313
+ display: "flex",
314
+ alignItems: "center",
315
+ gap: "5px",
316
+ background: color + "0a",
317
+ border: `1px solid ${color}22`,
318
+ borderRadius: "8px",
319
+ padding: "5px 7px",
320
+ flex: 1,
321
+ minWidth: 0
322
+ },
323
+ children: [
324
+ /* @__PURE__ */ jsxs2("div", { style: { position: "relative", width: "18px", height: "18px", flexShrink: 0 }, children: [
325
+ /* @__PURE__ */ jsxs2("svg", { width: "18", height: "18", viewBox: "0 0 18 18", children: [
326
+ /* @__PURE__ */ jsx3("circle", { cx: "9", cy: "9", r: "7", fill: "none", stroke: color + "22", strokeWidth: "2" }),
327
+ /* @__PURE__ */ jsx3(
328
+ "circle",
329
+ {
330
+ cx: "9",
331
+ cy: "9",
332
+ r: "7",
333
+ fill: "none",
334
+ stroke: color,
335
+ strokeWidth: "2",
336
+ strokeDasharray: `${pct / 100 * 44} 44`,
337
+ strokeLinecap: "round",
338
+ transform: "rotate(-90 9 9)",
339
+ style: { transition: "stroke-dasharray 0.1s ease" }
340
+ }
341
+ )
342
+ ] }),
343
+ /* @__PURE__ */ jsx3(
344
+ "span",
345
+ {
346
+ style: {
347
+ position: "absolute",
348
+ inset: 0,
349
+ display: "flex",
350
+ alignItems: "center",
351
+ justifyContent: "center",
352
+ fontSize: "7px",
353
+ fontWeight: 800,
354
+ color,
355
+ letterSpacing: "-0.02em"
356
+ },
357
+ children: label
358
+ }
359
+ )
360
+ ] }),
361
+ /* @__PURE__ */ jsxs2(
362
+ "span",
363
+ {
364
+ style: {
365
+ fontSize: "10px",
366
+ color: color + "cc",
367
+ fontVariantNumeric: "tabular-nums",
368
+ width: "36px",
369
+ textAlign: "right",
370
+ flexShrink: 0
371
+ },
372
+ children: [
373
+ deg,
374
+ "\xB0"
375
+ ]
376
+ }
377
+ ),
378
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "3px", marginLeft: "2px" }, children: [
379
+ /* @__PURE__ */ jsx3(IconBtn, { color, title: `\u2212${label}`, onClick: onDec, children: "\u2212" }),
380
+ /* @__PURE__ */ jsx3(IconBtn, { color, title: `+${label}`, onClick: onInc, children: "+" }),
381
+ /* @__PURE__ */ jsx3(IconBtn, { color: color + "88", title: "Reset", onClick: onReset, children: "\u21BA" })
382
+ ] })
383
+ ]
384
+ }
385
+ );
386
+ }
387
+ function RotationControls({ context, style }) {
388
+ const { camera, rotate, setYaw, setPitch, reset } = useCameraControls(context);
389
+ return /* @__PURE__ */ jsxs2(
390
+ "div",
391
+ {
392
+ style: {
393
+ display: "flex",
394
+ alignItems: "center",
395
+ gap: "6px",
396
+ background: "rgba(8,8,12,0.78)",
397
+ border: "1px solid rgba(255,255,255,0.07)",
398
+ borderRadius: "12px",
399
+ padding: "6px 8px",
400
+ backdropFilter: "blur(16px)",
401
+ boxShadow: "0 4px 24px rgba(0,0,0,0.5)",
402
+ fontFamily: '"Inter", system-ui, monospace',
403
+ ...style
404
+ },
405
+ children: [
406
+ /* @__PURE__ */ jsx3(
407
+ "div",
408
+ {
409
+ title: context ? "Camera ready" : "Waiting for context\u2026",
410
+ style: {
411
+ width: "6px",
412
+ height: "6px",
413
+ borderRadius: "50%",
414
+ background: context ? "#c3e88d" : "#555",
415
+ boxShadow: context ? "0 0 6px #c3e88daa" : "none",
416
+ flexShrink: 0,
417
+ transition: "all 0.3s"
418
+ }
419
+ }
420
+ ),
421
+ /* @__PURE__ */ jsx3(
422
+ AxisPill,
423
+ {
424
+ label: "Yaw",
425
+ color: "#ff5370",
426
+ value: camera.yaw,
427
+ onDec: () => rotate(-STEP, 0),
428
+ onInc: () => rotate(STEP, 0),
429
+ onReset: () => setYaw(0)
430
+ }
431
+ ),
432
+ /* @__PURE__ */ jsx3(
433
+ AxisPill,
434
+ {
435
+ label: "Pitch",
436
+ color: "#82aaff",
437
+ value: camera.pitch,
438
+ onDec: () => rotate(0, -STEP),
439
+ onInc: () => rotate(0, STEP),
440
+ onReset: () => setPitch(0)
441
+ }
442
+ ),
443
+ /* @__PURE__ */ jsx3(IconBtn, { color: "#ffffff", title: "Reset all", onClick: reset, children: "\u2298" })
444
+ ]
445
+ }
446
+ );
447
+ }
448
+
449
+ // src/components/FaceLabel.tsx
450
+ import { jsx as jsx4 } from "react/jsx-runtime";
451
+ function transformLocalToWorld(m, x, y, z) {
452
+ return {
453
+ x: m[0] * x + m[4] * y + m[8] * z + m[12],
454
+ y: m[1] * x + m[5] * y + m[9] * z + m[13],
455
+ z: m[2] * x + m[6] * y + m[10] * z + m[14]
456
+ };
457
+ }
458
+ function cross(ax, ay, az, bx, by, bz) {
459
+ return {
460
+ x: ay * bz - az * by,
461
+ y: az * bx - ax * bz,
462
+ z: ax * by - ay * bx
463
+ };
464
+ }
465
+ function solveHomography(w, h, p) {
466
+ const [p0, p1, p2, p3] = p;
467
+ const sx = [0, w, w, 0];
468
+ const sy = [0, 0, h, h];
469
+ const dx = [p0.x, p1.x, p2.x, p3.x];
470
+ const dy = [p0.y, p1.y, p2.y, p3.y];
471
+ const M = [];
472
+ for (let i = 0; i < 4; i++) {
473
+ M.push([sx[i], sy[i], 1, 0, 0, 0, -dx[i] * sx[i], -dx[i] * sy[i], dx[i]]);
474
+ M.push([0, 0, 0, sx[i], sy[i], 1, -dy[i] * sx[i], -dy[i] * sy[i], dy[i]]);
475
+ }
476
+ const n = 8;
477
+ for (let col = 0; col < n; col++) {
478
+ let maxRow = col;
479
+ for (let row = col + 1; row < n; row++) {
480
+ if (Math.abs(M[row][col]) > Math.abs(M[maxRow][col])) maxRow = row;
481
+ }
482
+ [M[col], M[maxRow]] = [M[maxRow], M[col]];
483
+ if (Math.abs(M[col][col]) < 1e-10) return null;
484
+ const pivot = M[col][col];
485
+ for (let k = col; k <= n; k++) M[col][k] /= pivot;
486
+ for (let row = 0; row < n; row++) {
487
+ if (row === col) continue;
488
+ const f = M[row][col];
489
+ for (let k = col; k <= n; k++) M[row][k] -= f * M[col][k];
490
+ }
491
+ }
492
+ return M.map((row) => row[n]);
493
+ }
494
+ function buildMatrix3d(w, h, p) {
495
+ const hv = solveHomography(w, h, p);
496
+ if (!hv) return "none";
497
+ const [h00, h01, h02, h10, h11, h12, h20, h21] = hv;
498
+ return `matrix3d(${h00},${h10},0,${h20},${h01},${h11},0,${h21},0,0,1,0,${h02},${h12},0,1)`;
499
+ }
500
+ function FaceSkin({
501
+ context,
502
+ model,
503
+ corners,
504
+ children,
505
+ style,
506
+ className,
507
+ surfaceWidth = 300,
508
+ surfaceHeight = 200
509
+ }) {
510
+ const { project: project2 } = useWorldToScreen(context);
511
+ if (!model || !context) return null;
512
+ const mm = model.getModelMatrix();
513
+ const worldPts = corners.map(
514
+ ([lx, ly, lz]) => transformLocalToWorld(mm, lx, ly, lz)
515
+ );
516
+ const e1x = worldPts[1].x - worldPts[0].x;
517
+ const e1y = worldPts[1].y - worldPts[0].y;
518
+ const e1z = worldPts[1].z - worldPts[0].z;
519
+ const e2x = worldPts[3].x - worldPts[0].x;
520
+ const e2y = worldPts[3].y - worldPts[0].y;
521
+ const e2z = worldPts[3].z - worldPts[0].z;
522
+ const normal = cross(e1x, e1y, e1z, e2x, e2y, e2z);
523
+ const camera = context.viewport.camera;
524
+ const radius = Math.sqrt(
525
+ (camera.position[0] - camera.target[0]) ** 2 + (camera.position[1] - camera.target[1]) ** 2 + (camera.position[2] - camera.target[2]) ** 2
526
+ );
527
+ const eyeX = camera.target[0] + radius * Math.cos(camera.pitch) * Math.sin(camera.yaw);
528
+ const eyeY = camera.target[1] + radius * Math.sin(camera.pitch);
529
+ const eyeZ = camera.target[2] + radius * Math.cos(camera.pitch) * Math.cos(camera.yaw);
530
+ const toCamera = {
531
+ x: eyeX - worldPts[0].x,
532
+ y: eyeY - worldPts[0].y,
533
+ z: eyeZ - worldPts[0].z
534
+ };
535
+ const dot = normal.x * toCamera.x + normal.y * toCamera.y + normal.z * toCamera.z;
536
+ if (dot <= 0) return null;
537
+ const screenPts = worldPts.map((w) => project2(w.x, w.y, w.z));
538
+ if (screenPts.some((pt) => !pt.visible)) return null;
539
+ const remapped = [screenPts[3], screenPts[2], screenPts[1], screenPts[0]];
540
+ const matrix = buildMatrix3d(surfaceWidth, surfaceHeight, remapped);
541
+ return /* @__PURE__ */ jsx4(
542
+ "div",
543
+ {
544
+ style: {
545
+ position: "absolute",
546
+ inset: 0,
547
+ pointerEvents: "none",
548
+ overflow: "hidden"
549
+ },
550
+ children: /* @__PURE__ */ jsx4(
551
+ "div",
552
+ {
553
+ className,
554
+ style: {
555
+ position: "absolute",
556
+ top: 0,
557
+ left: 0,
558
+ width: surfaceWidth,
559
+ height: surfaceHeight,
560
+ transformOrigin: "0 0",
561
+ transform: matrix,
562
+ overflow: "hidden",
563
+ pointerEvents: "auto",
564
+ ...style
565
+ },
566
+ children
567
+ }
568
+ )
569
+ }
570
+ );
571
+ }
572
+
573
+ export {
574
+ GenesisGLCanvas,
575
+ ViewportGizmo,
576
+ RotationControls,
577
+ FaceSkin
578
+ };
579
+ //# sourceMappingURL=chunk-7RTMMLA7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/GenesisGLCanvas.tsx","../src/components/ViewportGizmo.tsx","../src/components/RotationControls.tsx","../src/components/FaceLabel.tsx"],"sourcesContent":["import React, { useRef, useCallback, useEffect } from 'react';\nimport { useGenesisGL } from '../hooks/useGenesisGL';\nimport type { GenesisGLContext } from '../hooks/useGenesisGL';\nimport { useRenderer } from '../hooks/useRenderer';\nimport { useCameraMouseDrag } from '../hooks/useCameraMouseDrag';\n\nexport interface GenesisGLCanvasProps {\n onReady?: (context: GenesisGLContext) => void;\n onFrame?: (time: number) => void;\n width?: number;\n height?: number;\n initialYaw?: number;\n initialPitch?: number;\n initialZoom?: number;\n /** RGBA clear color, e.g. [0.05, 0.05, 0.05, 1] */\n background?: [number, number, number, number];\n style?: React.CSSProperties;\n className?: string;\n}\n\nexport const GenesisGLCanvas = React.forwardRef<\n HTMLCanvasElement,\n GenesisGLCanvasProps\n>(\n (\n {\n onReady,\n onFrame,\n width,\n height,\n initialYaw,\n initialPitch,\n initialZoom,\n background,\n style,\n className,\n },\n ref,\n ) => {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n\n // Always use the internal ref for GL init; expose to parent via callback ref\n const setRef = useCallback(\n (el: HTMLCanvasElement | null) => {\n (\n canvasRef as React.MutableRefObject<HTMLCanvasElement | null>\n ).current = el;\n if (typeof ref === 'function') ref(el);\n else if (ref) ref.current = el;\n },\n [ref],\n );\n\n const onFrameRef = useRef(onFrame);\n onFrameRef.current = onFrame;\n\n const genesisContext = useGenesisGL({\n canvasRef,\n width,\n height,\n initialYaw,\n initialPitch,\n initialZoom,\n onReady,\n });\n\n const genesisContextRef = useRef(genesisContext);\n genesisContextRef.current = genesisContext;\n\n const stableOnFrame = useCallback((time: number) => {\n const { renderer, scene } = genesisContextRef.current;\n if (renderer && scene) {\n renderer.render(scene);\n onFrameRef.current?.(time);\n }\n }, []);\n\n useEffect(() => {\n if (genesisContext.renderer && background) {\n genesisContext.renderer.clearColor = background;\n }\n }, [genesisContext.renderer, background]);\n\n useRenderer({ renderer: genesisContext.renderer, onFrame: stableOnFrame });\n useCameraMouseDrag(genesisContext, canvasRef);\n\n return (\n <canvas\n ref={setRef}\n style={{ display: 'block', width: '100%', height: '100%', ...style }}\n className={className}\n />\n );\n },\n);\n\nGenesisGLCanvas.displayName = 'GenesisGLCanvas';\n","import React, { useRef, useEffect, useCallback } from 'react';\nimport { useCameraControls } from '../hooks/useCameraControls';\nimport type { GenesisGLContext } from '../hooks/useGenesisGL';\n\nexport interface ViewportGizmoProps {\n context: GenesisGLContext | null;\n /** Size of the gizmo widget in px. Default 96 */\n size?: number;\n /** Corner to anchor in. Default 'top-right' */\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n style?: React.CSSProperties;\n}\n\n// Each axis face: label, unit direction [x,y,z], color\nconst FACES = [\n { label: '+X', dir: [1, 0, 0] as [number, number, number], color: '#ff5370' },\n { label: '-X', dir: [-1, 0, 0] as [number, number, number], color: '#ff5370', dim: true },\n { label: '+Y', dir: [0, 1, 0] as [number, number, number], color: '#c3e88d' },\n { label: '-Y', dir: [0, -1, 0] as [number, number, number], color: '#c3e88d', dim: true },\n { label: '+Z', dir: [0, 0, 1] as [number, number, number], color: '#82aaff' },\n { label: '-Z', dir: [0, 0, -1] as [number, number, number], color: '#82aaff', dim: true },\n];\n\nconst SNAP_PITCH: Record<string, number> = {\n '+Y': Math.PI / 2 - 0.01,\n '-Y': -(Math.PI / 2 - 0.01),\n};\n\n/** Project a unit-sphere point through the camera's current yaw/pitch to a 2D gizmo position. */\nfunction project(\n dir: [number, number, number],\n yaw: number,\n pitch: number,\n radius: number,\n): { x: number; y: number; z: number } {\n // Rotate dir by the inverse camera orbit (yaw around Y, pitch around X)\n const [dx, dy, dz] = dir;\n\n // Apply inverse yaw (rotate around Y)\n const cosY = Math.cos(-yaw);\n const sinY = Math.sin(-yaw);\n const rx = dx * cosY + dz * sinY;\n const ry = dy;\n const rz = -dx * sinY + dz * cosY;\n\n // Apply inverse pitch (rotate around X)\n const cosP = Math.cos(-pitch);\n const sinP = Math.sin(-pitch);\n const fx = rx;\n const fy = ry * cosP - rz * sinP;\n const fz = ry * sinP + rz * cosP;\n\n return { x: fx * radius, y: -fy * radius, z: fz };\n}\n\nconst DRAG_SENSITIVITY = 0.008;\n\nexport function ViewportGizmo({\n context,\n size = 96,\n position = 'top-right',\n style,\n}: ViewportGizmoProps) {\n const { camera, setYaw, setPitch, rotate } = useCameraControls(context);\n const dragging = useRef(false);\n const lastPos = useRef({ x: 0, y: 0 });\n const containerRef = useRef<HTMLDivElement>(null);\n\n const onMouseDown = useCallback((e: React.MouseEvent) => {\n if (e.button !== 0) return;\n dragging.current = true;\n lastPos.current = { x: e.clientX, y: e.clientY };\n e.stopPropagation();\n e.preventDefault();\n }, []);\n\n useEffect(() => {\n const onMove = (e: MouseEvent) => {\n if (!dragging.current) return;\n const dx = e.clientX - lastPos.current.x;\n const dy = e.clientY - lastPos.current.y;\n lastPos.current = { x: e.clientX, y: e.clientY };\n rotate(-dx * DRAG_SENSITIVITY, -dy * DRAG_SENSITIVITY);\n };\n const onUp = () => { dragging.current = false; };\n window.addEventListener('mousemove', onMove);\n window.addEventListener('mouseup', onUp);\n return () => {\n window.removeEventListener('mousemove', onMove);\n window.removeEventListener('mouseup', onUp);\n };\n }, [rotate]);\n\n const snapTo = useCallback((face: typeof FACES[0]) => {\n const [dx, , dz] = face.dir;\n const targetYaw = Math.atan2(dx, dz);\n const targetPitch = SNAP_PITCH[face.label] ?? 0;\n setYaw(targetYaw);\n setPitch(targetPitch);\n }, [setYaw, setPitch]);\n\n const half = size / 2;\n const dotRadius = size * 0.14;\n const orbitRadius = half * 0.62;\n\n // Project all faces and sort back-to-front\n const projected = FACES.map((face) => ({\n ...face,\n ...project(face.dir, camera.yaw, camera.pitch, orbitRadius),\n })).sort((a, b) => a.z - b.z);\n\n const posStyle: React.CSSProperties =\n position === 'top-right' ? { top: 12, right: 12 } :\n position === 'top-left' ? { top: 12, left: 12 } :\n position === 'bottom-right' ? { bottom: 12, right: 12 } :\n { bottom: 12, left: 12 };\n\n return (\n <div\n ref={containerRef}\n onMouseDown={onMouseDown}\n style={{\n position: 'absolute',\n width: size,\n height: size,\n borderRadius: '50%',\n background: 'rgba(8,8,14,0.55)',\n border: '1px solid rgba(255,255,255,0.07)',\n backdropFilter: 'blur(8px)',\n cursor: dragging.current ? 'grabbing' : 'grab',\n userSelect: 'none',\n ...posStyle,\n ...style,\n }}\n >\n <svg\n width={size}\n height={size}\n viewBox={`${-half} ${-half} ${size} ${size}`}\n style={{ overflow: 'visible', display: 'block' }}\n >\n {/* Axis lines — draw behind dots */}\n {(['x', 'y', 'z'] as const).map((axis) => {\n const pos = projected.find((f) => f.label === `+${axis.toUpperCase()}`);\n const neg = projected.find((f) => f.label === `-${axis.toUpperCase()}`);\n if (!pos || !neg) return null;\n return (\n <line\n key={axis}\n x1={neg.x} y1={neg.y}\n x2={pos.x} y2={pos.y}\n stroke={pos.color}\n strokeWidth={1.5}\n strokeOpacity={0.35}\n />\n );\n })}\n\n {/* Dots — sorted back to front */}\n {projected.map((face) => {\n const isFront = face.z >= 0;\n const opacity = isFront ? 1 : 0.28;\n const r = isFront ? dotRadius : dotRadius * 0.75;\n return (\n <g\n key={face.label}\n style={{ cursor: 'pointer' }}\n onClick={(e) => { e.stopPropagation(); snapTo(face); }}\n >\n <circle\n cx={face.x} cy={face.y} r={r}\n fill={face.color}\n fillOpacity={opacity * (face.dim ? 0.6 : 1)}\n stroke={face.color}\n strokeWidth={isFront ? 1.5 : 0.5}\n strokeOpacity={opacity * 0.6}\n />\n {isFront && (\n <text\n x={face.x} y={face.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fontSize={r * 0.75}\n fontWeight={700}\n fontFamily=\"system-ui, monospace\"\n fill=\"#fff\"\n fillOpacity={0.9}\n style={{ pointerEvents: 'none' }}\n >\n {face.label}\n </text>\n )}\n </g>\n );\n })}\n </svg>\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport { useCameraControls } from '../hooks/useCameraControls';\nimport type { GenesisGLContext } from '../hooks/useGenesisGL';\n\nconst STEP = 0.05;\n\nfunction IconBtn({\n children,\n title,\n onClick,\n color,\n}: {\n children: React.ReactNode;\n title?: string;\n onClick: () => void;\n color: string;\n}) {\n const [active, setActive] = useState(false);\n const [hover, setHover] = useState(false);\n\n return (\n <button\n title={title}\n onClick={onClick}\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => { setHover(false); setActive(false); }}\n onMouseDown={() => setActive(true)}\n onMouseUp={() => setActive(false)}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '22px',\n height: '22px',\n border: `1px solid ${hover ? color + '88' : color + '33'}`,\n borderRadius: '5px',\n background: active ? color + '30' : hover ? color + '18' : color + '0c',\n color: hover ? color : color + 'aa',\n cursor: 'pointer',\n fontSize: '11px',\n fontWeight: 700,\n lineHeight: 1,\n padding: 0,\n transition: 'all 0.12s',\n transform: active ? 'scale(0.88)' : 'scale(1)',\n flexShrink: 0,\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction AxisPill({\n label,\n color,\n value,\n onDec,\n onInc,\n onReset,\n}: {\n label: string;\n color: string;\n value: number;\n onDec: () => void;\n onInc: () => void;\n onReset: () => void;\n}) {\n const deg = ((value * 180) / Math.PI).toFixed(1);\n const normalized = ((value % (Math.PI * 2)) + Math.PI * 2) % (Math.PI * 2);\n const pct = (normalized / (Math.PI * 2)) * 100;\n\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '5px',\n background: color + '0a',\n border: `1px solid ${color}22`,\n borderRadius: '8px',\n padding: '5px 7px',\n flex: 1,\n minWidth: 0,\n }}\n >\n <div style={{ position: 'relative', width: '18px', height: '18px', flexShrink: 0 }}>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\">\n <circle cx=\"9\" cy=\"9\" r=\"7\" fill=\"none\" stroke={color + '22'} strokeWidth=\"2\" />\n <circle\n cx=\"9\" cy=\"9\" r=\"7\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeDasharray={`${(pct / 100) * 44} 44`}\n strokeLinecap=\"round\"\n transform=\"rotate(-90 9 9)\"\n style={{ transition: 'stroke-dasharray 0.1s ease' }}\n />\n </svg>\n <span\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '7px',\n fontWeight: 800,\n color,\n letterSpacing: '-0.02em',\n }}\n >\n {label}\n </span>\n </div>\n\n <span\n style={{\n fontSize: '10px',\n color: color + 'cc',\n fontVariantNumeric: 'tabular-nums',\n width: '36px',\n textAlign: 'right',\n flexShrink: 0,\n }}\n >\n {deg}°\n </span>\n\n <div style={{ display: 'flex', gap: '3px', marginLeft: '2px' }}>\n <IconBtn color={color} title={`−${label}`} onClick={onDec}>−</IconBtn>\n <IconBtn color={color} title={`+${label}`} onClick={onInc}>+</IconBtn>\n <IconBtn color={color + '88'} title=\"Reset\" onClick={onReset}>↺</IconBtn>\n </div>\n </div>\n );\n}\n\nexport interface RotationControlsProps {\n context: GenesisGLContext | null;\n style?: React.CSSProperties;\n}\n\nexport function RotationControls({ context, style }: RotationControlsProps) {\n const { camera, rotate, setYaw, setPitch, reset } = useCameraControls(context);\n\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n background: 'rgba(8,8,12,0.78)',\n border: '1px solid rgba(255,255,255,0.07)',\n borderRadius: '12px',\n padding: '6px 8px',\n backdropFilter: 'blur(16px)',\n boxShadow: '0 4px 24px rgba(0,0,0,0.5)',\n fontFamily: '\"Inter\", system-ui, monospace',\n ...style,\n }}\n >\n <div\n title={context ? 'Camera ready' : 'Waiting for context…'}\n style={{\n width: '6px',\n height: '6px',\n borderRadius: '50%',\n background: context ? '#c3e88d' : '#555',\n boxShadow: context ? '0 0 6px #c3e88daa' : 'none',\n flexShrink: 0,\n transition: 'all 0.3s',\n }}\n />\n\n <AxisPill\n label=\"Yaw\"\n color=\"#ff5370\"\n value={camera.yaw}\n onDec={() => rotate(-STEP, 0)}\n onInc={() => rotate(STEP, 0)}\n onReset={() => setYaw(0)}\n />\n\n <AxisPill\n label=\"Pitch\"\n color=\"#82aaff\"\n value={camera.pitch}\n onDec={() => rotate(0, -STEP)}\n onInc={() => rotate(0, STEP)}\n onReset={() => setPitch(0)}\n />\n\n <IconBtn color=\"#ffffff\" title=\"Reset all\" onClick={reset}>⊘</IconBtn>\n </div>\n );\n}\n","import React from 'react';\nimport type { Model } from '@fonsecabarreto/genesis-gl-core/Core';\nimport type { GenesisGLContext } from '../hooks/useGenesisGL';\nimport { useWorldToScreen } from '../hooks/useWorldToScreen';\n\nexport interface FaceSkinProps {\n context: GenesisGLContext | null;\n model: Model | null;\n corners: [\n [number, number, number],\n [number, number, number],\n [number, number, number],\n [number, number, number],\n ];\n /** Width of the virtual surface div warped onto the face (px) */\n surfaceWidth?: number;\n /** Height of the virtual surface div warped onto the face (px) */\n surfaceHeight?: number;\n children?: React.ReactNode;\n style?: React.CSSProperties;\n className?: string;\n}\n\nfunction transformLocalToWorld(\n m: Float32Array,\n x: number,\n y: number,\n z: number,\n) {\n return {\n x: m[0] * x + m[4] * y + m[8] * z + m[12],\n y: m[1] * x + m[5] * y + m[9] * z + m[13],\n z: m[2] * x + m[6] * y + m[10] * z + m[14],\n };\n}\n\nfunction cross(\n ax: number,\n ay: number,\n az: number,\n bx: number,\n by: number,\n bz: number,\n) {\n return {\n x: ay * bz - az * by,\n y: az * bx - ax * bz,\n z: ax * by - ay * bx,\n };\n}\n\n/**\n * Solve for the homography matrix H (8 unknowns, h22=1) that maps\n * a w×h rectangle to four destination points using Gaussian elimination.\n * Returns [h00,h01,h02,h10,h11,h12,h20,h21] or null on failure.\n */\nfunction solveHomography(\n w: number,\n h: number,\n p: { x: number; y: number }[],\n): number[] | null {\n const [p0, p1, p2, p3] = p;\n const sx = [0, w, w, 0];\n const sy = [0, 0, h, h];\n const dx = [p0.x, p1.x, p2.x, p3.x];\n const dy = [p0.y, p1.y, p2.y, p3.y];\n\n // Build augmented 8×9 matrix\n const M: number[][] = [];\n for (let i = 0; i < 4; i++) {\n M.push([sx[i], sy[i], 1, 0, 0, 0, -dx[i] * sx[i], -dx[i] * sy[i], dx[i]]);\n M.push([0, 0, 0, sx[i], sy[i], 1, -dy[i] * sx[i], -dy[i] * sy[i], dy[i]]);\n }\n\n const n = 8;\n for (let col = 0; col < n; col++) {\n let maxRow = col;\n for (let row = col + 1; row < n; row++) {\n if (Math.abs(M[row][col]) > Math.abs(M[maxRow][col])) maxRow = row;\n }\n [M[col], M[maxRow]] = [M[maxRow], M[col]];\n if (Math.abs(M[col][col]) < 1e-10) return null;\n const pivot = M[col][col];\n for (let k = col; k <= n; k++) M[col][k] /= pivot;\n for (let row = 0; row < n; row++) {\n if (row === col) continue;\n const f = M[row][col];\n for (let k = col; k <= n; k++) M[row][k] -= f * M[col][k];\n }\n }\n\n return M.map((row) => row[n]);\n}\n\n/**\n * Build the CSS matrix3d string that perspectively maps a w×h div\n * (origin top-left) onto four screen-space points [p0,p1,p2,p3]\n * corresponding to the div corners (0,0),(w,0),(w,h),(0,h).\n */\nfunction buildMatrix3d(\n w: number,\n h: number,\n p: { x: number; y: number }[],\n): string {\n const hv = solveHomography(w, h, p);\n if (!hv) return 'none';\n const [h00, h01, h02, h10, h11, h12, h20, h21] = hv;\n // CSS matrix3d is column-major 4×4\n return (\n `matrix3d(` +\n `${h00},${h10},0,${h20},` +\n `${h01},${h11},0,${h21},` +\n `0,0,1,0,` +\n `${h02},${h12},0,1)`\n );\n}\n\nexport function FaceSkin({\n context,\n model,\n corners,\n children,\n style,\n className,\n surfaceWidth = 300,\n surfaceHeight = 200,\n}: FaceSkinProps) {\n const { project } = useWorldToScreen(context);\n\n if (!model || !context) return null;\n\n const mm = model.getModelMatrix() as unknown as Float32Array;\n\n const worldPts = corners.map(([lx, ly, lz]) =>\n transformLocalToWorld(mm, lx, ly, lz),\n );\n\n const e1x = worldPts[1].x - worldPts[0].x;\n const e1y = worldPts[1].y - worldPts[0].y;\n const e1z = worldPts[1].z - worldPts[0].z;\n const e2x = worldPts[3].x - worldPts[0].x;\n const e2y = worldPts[3].y - worldPts[0].y;\n const e2z = worldPts[3].z - worldPts[0].z;\n const normal = cross(e1x, e1y, e1z, e2x, e2y, e2z);\n\n const camera = context.viewport!.camera;\n const radius = Math.sqrt(\n (camera.position[0] - camera.target[0]) ** 2 +\n (camera.position[1] - camera.target[1]) ** 2 +\n (camera.position[2] - camera.target[2]) ** 2,\n );\n const eyeX =\n camera.target[0] + radius * Math.cos(camera.pitch) * Math.sin(camera.yaw);\n const eyeY = camera.target[1] + radius * Math.sin(camera.pitch);\n const eyeZ =\n camera.target[2] + radius * Math.cos(camera.pitch) * Math.cos(camera.yaw);\n\n const toCamera = {\n x: eyeX - worldPts[0].x,\n y: eyeY - worldPts[0].y,\n z: eyeZ - worldPts[0].z,\n };\n const dot =\n normal.x * toCamera.x + normal.y * toCamera.y + normal.z * toCamera.z;\n\n if (dot <= 0) return null;\n\n const screenPts = worldPts.map((w) => project(w.x, w.y, w.z));\n if (screenPts.some((pt) => !pt.visible)) return null;\n\n // Remap corners so the div renders right-side-up from the isometric view:\n // div (0,0)→screenPts[3], (w,0)→[2], (w,h)→[1], (0,h)→[0]\n const remapped = [screenPts[3], screenPts[2], screenPts[1], screenPts[0]];\n const matrix = buildMatrix3d(surfaceWidth, surfaceHeight, remapped);\n\n return (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n pointerEvents: 'none',\n overflow: 'hidden',\n }}\n >\n <div\n className={className}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: surfaceWidth,\n height: surfaceHeight,\n transformOrigin: '0 0',\n transform: matrix,\n overflow: 'hidden',\n pointerEvents: 'auto',\n ...style,\n }}\n >\n {children}\n </div>\n </div>\n );\n}\n\nexport { FaceSkin as FaceLabel };\nexport type { FaceSkinProps as FaceLabelProps };\n"],"mappings":";;;;;;;;;AAAA,OAAO,SAAS,QAAQ,aAAa,iBAAiB;AAuFhD;AAnEC,IAAM,kBAAkB,MAAM;AAAA,EAInC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GACA,QACG;AACH,UAAM,YAAY,OAA0B,IAAI;AAGhD,UAAM,SAAS;AAAA,MACb,CAAC,OAAiC;AAChC,QACE,UACA,UAAU;AACZ,YAAI,OAAO,QAAQ,WAAY,KAAI,EAAE;AAAA,iBAC5B,IAAK,KAAI,UAAU;AAAA,MAC9B;AAAA,MACA,CAAC,GAAG;AAAA,IACN;AAEA,UAAM,aAAa,OAAO,OAAO;AACjC,eAAW,UAAU;AAErB,UAAM,iBAAiB,aAAa;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,oBAAoB,OAAO,cAAc;AAC/C,sBAAkB,UAAU;AAE5B,UAAM,gBAAgB,YAAY,CAAC,SAAiB;AAClD,YAAM,EAAE,UAAU,MAAM,IAAI,kBAAkB;AAC9C,UAAI,YAAY,OAAO;AACrB,iBAAS,OAAO,KAAK;AACrB,mBAAW,UAAU,IAAI;AAAA,MAC3B;AAAA,IACF,GAAG,CAAC,CAAC;AAEL,cAAU,MAAM;AACd,UAAI,eAAe,YAAY,YAAY;AACzC,uBAAe,SAAS,aAAa;AAAA,MACvC;AAAA,IACF,GAAG,CAAC,eAAe,UAAU,UAAU,CAAC;AAExC,gBAAY,EAAE,UAAU,eAAe,UAAU,SAAS,cAAc,CAAC;AACzE,uBAAmB,gBAAgB,SAAS;AAE5C,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,OAAO,EAAE,SAAS,SAAS,OAAO,QAAQ,QAAQ,QAAQ,GAAG,MAAM;AAAA,QACnE;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,gBAAgB,cAAc;;;AChG9B,SAAgB,UAAAA,SAAQ,aAAAC,YAAW,eAAAC,oBAAmB;AAmJ1C,gBAAAC,MAiBA,YAjBA;AArIZ,IAAM,QAAQ;AAAA,EACZ,EAAE,OAAO,MAAM,KAAK,CAAC,GAAG,GAAG,CAAC,GAA+B,OAAO,UAAU;AAAA,EAC5E,EAAE,OAAO,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,GAA+B,OAAO,WAAW,KAAK,KAAK;AAAA,EACxF,EAAE,OAAO,MAAM,KAAK,CAAC,GAAG,GAAG,CAAC,GAA+B,OAAO,UAAU;AAAA,EAC5E,EAAE,OAAO,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,GAA+B,OAAO,WAAW,KAAK,KAAK;AAAA,EACxF,EAAE,OAAO,MAAM,KAAK,CAAC,GAAG,GAAG,CAAC,GAA+B,OAAO,UAAU;AAAA,EAC5E,EAAE,OAAO,MAAM,KAAK,CAAC,GAAG,GAAG,EAAE,GAA+B,OAAO,WAAW,KAAK,KAAK;AAC1F;AAEA,IAAM,aAAqC;AAAA,EACzC,MAAM,KAAK,KAAK,IAAI;AAAA,EACpB,MAAM,EAAE,KAAK,KAAK,IAAI;AACxB;AAGA,SAAS,QACP,KACA,KACA,OACA,QACqC;AAErC,QAAM,CAAC,IAAI,IAAI,EAAE,IAAI;AAGrB,QAAM,OAAO,KAAK,IAAI,CAAC,GAAG;AAC1B,QAAM,OAAO,KAAK,IAAI,CAAC,GAAG;AAC1B,QAAM,KAAK,KAAK,OAAO,KAAK;AAC5B,QAAM,KAAK;AACX,QAAM,KAAK,CAAC,KAAK,OAAO,KAAK;AAG7B,QAAM,OAAO,KAAK,IAAI,CAAC,KAAK;AAC5B,QAAM,OAAO,KAAK,IAAI,CAAC,KAAK;AAC5B,QAAM,KAAK;AACX,QAAM,KAAK,KAAK,OAAO,KAAK;AAC5B,QAAM,KAAK,KAAK,OAAO,KAAK;AAE5B,SAAO,EAAE,GAAG,KAAK,QAAQ,GAAG,CAAC,KAAK,QAAQ,GAAG,GAAG;AAClD;AAEA,IAAM,mBAAmB;AAElB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX;AACF,GAAuB;AACrB,QAAM,EAAE,QAAQ,QAAQ,UAAU,OAAO,IAAI,kBAAkB,OAAO;AACtE,QAAM,WAAWC,QAAO,KAAK;AAC7B,QAAM,UAAUA,QAAO,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AACrC,QAAM,eAAeA,QAAuB,IAAI;AAEhD,QAAM,cAAcC,aAAY,CAAC,MAAwB;AACvD,QAAI,EAAE,WAAW,EAAG;AACpB,aAAS,UAAU;AACnB,YAAQ,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ;AAC/C,MAAE,gBAAgB;AAClB,MAAE,eAAe;AAAA,EACnB,GAAG,CAAC,CAAC;AAEL,EAAAC,WAAU,MAAM;AACd,UAAM,SAAS,CAAC,MAAkB;AAChC,UAAI,CAAC,SAAS,QAAS;AACvB,YAAM,KAAK,EAAE,UAAU,QAAQ,QAAQ;AACvC,YAAM,KAAK,EAAE,UAAU,QAAQ,QAAQ;AACvC,cAAQ,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ;AAC/C,aAAO,CAAC,KAAK,kBAAkB,CAAC,KAAK,gBAAgB;AAAA,IACvD;AACA,UAAM,OAAO,MAAM;AAAE,eAAS,UAAU;AAAA,IAAO;AAC/C,WAAO,iBAAiB,aAAa,MAAM;AAC3C,WAAO,iBAAiB,WAAW,IAAI;AACvC,WAAO,MAAM;AACX,aAAO,oBAAoB,aAAa,MAAM;AAC9C,aAAO,oBAAoB,WAAW,IAAI;AAAA,IAC5C;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,SAASD,aAAY,CAAC,SAA0B;AACpD,UAAM,CAAC,IAAI,EAAE,EAAE,IAAI,KAAK;AACxB,UAAM,YAAY,KAAK,MAAM,IAAI,EAAE;AACnC,UAAM,cAAc,WAAW,KAAK,KAAK,KAAK;AAC9C,WAAO,SAAS;AAChB,aAAS,WAAW;AAAA,EACtB,GAAG,CAAC,QAAQ,QAAQ,CAAC;AAErB,QAAM,OAAO,OAAO;AACpB,QAAM,YAAY,OAAO;AACzB,QAAM,cAAc,OAAO;AAG3B,QAAM,YAAY,MAAM,IAAI,CAAC,UAAU;AAAA,IACrC,GAAG;AAAA,IACH,GAAG,QAAQ,KAAK,KAAK,OAAO,KAAK,OAAO,OAAO,WAAW;AAAA,EAC5D,EAAE,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AAE5B,QAAM,WACJ,aAAa,cAAiB,EAAE,KAAK,IAAI,OAAO,GAAG,IACnD,aAAa,aAAiB,EAAE,KAAK,IAAI,MAAM,GAAG,IAClD,aAAa,iBAAiB,EAAE,QAAQ,IAAI,OAAO,GAAG,IACxB,EAAE,QAAQ,IAAI,MAAM,GAAG;AAEvD,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,gBAAgB;AAAA,QAChB,QAAQ,SAAS,UAAU,aAAa;AAAA,QACxC,YAAY;AAAA,QACZ,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI;AAAA,UAC1C,OAAO,EAAE,UAAU,WAAW,SAAS,QAAQ;AAAA,UAG7C;AAAA,aAAC,KAAK,KAAK,GAAG,EAAY,IAAI,CAAC,SAAS;AACxC,oBAAM,MAAM,UAAU,KAAK,CAAC,MAAM,EAAE,UAAU,IAAI,KAAK,YAAY,CAAC,EAAE;AACtE,oBAAM,MAAM,UAAU,KAAK,CAAC,MAAM,EAAE,UAAU,IAAI,KAAK,YAAY,CAAC,EAAE;AACtE,kBAAI,CAAC,OAAO,CAAC,IAAK,QAAO;AACzB,qBACE,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBAEC,IAAI,IAAI;AAAA,kBAAG,IAAI,IAAI;AAAA,kBACnB,IAAI,IAAI;AAAA,kBAAG,IAAI,IAAI;AAAA,kBACnB,QAAQ,IAAI;AAAA,kBACZ,aAAa;AAAA,kBACb,eAAe;AAAA;AAAA,gBALV;AAAA,cAMP;AAAA,YAEJ,CAAC;AAAA,YAGA,UAAU,IAAI,CAAC,SAAS;AACvB,oBAAM,UAAU,KAAK,KAAK;AAC1B,oBAAM,UAAU,UAAU,IAAI;AAC9B,oBAAM,IAAI,UAAU,YAAY,YAAY;AAC5C,qBACE;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAO,EAAE,QAAQ,UAAU;AAAA,kBAC3B,SAAS,CAAC,MAAM;AAAE,sBAAE,gBAAgB;AAAG,2BAAO,IAAI;AAAA,kBAAG;AAAA,kBAErD;AAAA,oCAAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,IAAI,KAAK;AAAA,wBAAG,IAAI,KAAK;AAAA,wBAAG;AAAA,wBACxB,MAAM,KAAK;AAAA,wBACX,aAAa,WAAW,KAAK,MAAM,MAAM;AAAA,wBACzC,QAAQ,KAAK;AAAA,wBACb,aAAa,UAAU,MAAM;AAAA,wBAC7B,eAAe,UAAU;AAAA;AAAA,oBAC3B;AAAA,oBACC,WACC,gBAAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,GAAG,KAAK;AAAA,wBAAG,GAAG,KAAK;AAAA,wBACnB,YAAW;AAAA,wBACX,kBAAiB;AAAA,wBACjB,UAAU,IAAI;AAAA,wBACd,YAAY;AAAA,wBACZ,YAAW;AAAA,wBACX,MAAK;AAAA,wBACL,aAAa;AAAA,wBACb,OAAO,EAAE,eAAe,OAAO;AAAA,wBAE9B,eAAK;AAAA;AAAA,oBACR;AAAA;AAAA;AAAA,gBAzBG,KAAK;AAAA,cA2BZ;AAAA,YAEJ,CAAC;AAAA;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;;;ACtMA,SAAgB,gBAAgB;AAqB5B,gBAAAI,MAkEI,QAAAC,aAlEJ;AAjBJ,IAAM,OAAO;AAEb,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AAExC,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,cAAc,MAAM,SAAS,IAAI;AAAA,MACjC,cAAc,MAAM;AAAE,iBAAS,KAAK;AAAG,kBAAU,KAAK;AAAA,MAAG;AAAA,MACzD,aAAa,MAAM,UAAU,IAAI;AAAA,MACjC,WAAW,MAAM,UAAU,KAAK;AAAA,MAChC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,aAAa,QAAQ,QAAQ,OAAO,QAAQ,IAAI;AAAA,QACxD,cAAc;AAAA,QACd,YAAY,SAAS,QAAQ,OAAO,QAAQ,QAAQ,OAAO,QAAQ;AAAA,QACnE,OAAO,QAAQ,QAAQ,QAAQ;AAAA,QAC/B,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,WAAW,SAAS,gBAAgB;AAAA,QACpC,YAAY;AAAA,MACd;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,OAAQ,QAAQ,MAAO,KAAK,IAAI,QAAQ,CAAC;AAC/C,QAAM,cAAe,SAAS,KAAK,KAAK,KAAM,KAAK,KAAK,MAAM,KAAK,KAAK;AACxE,QAAM,MAAO,cAAc,KAAK,KAAK,KAAM;AAE3C,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,YAAY,QAAQ;AAAA,QACpB,QAAQ,aAAa,KAAK;AAAA,QAC1B,cAAc;AAAA,QACd,SAAS;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,MACZ;AAAA,MAEA;AAAA,wBAAAA,MAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,QAAQ,YAAY,EAAE,GAC/E;AAAA,0BAAAA,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAClC;AAAA,4BAAAD,KAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,MAAK,QAAO,QAAQ,QAAQ,MAAM,aAAY,KAAI;AAAA,YAC9E,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBAAI,IAAG;AAAA,gBAAI,GAAE;AAAA,gBAChB,MAAK;AAAA,gBACL,QAAQ;AAAA,gBACR,aAAY;AAAA,gBACZ,iBAAiB,GAAI,MAAM,MAAO,EAAE;AAAA,gBACpC,eAAc;AAAA,gBACd,WAAU;AAAA,gBACV,OAAO,EAAE,YAAY,6BAA6B;AAAA;AAAA,YACpD;AAAA,aACF;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,OAAO;AAAA,gBACP,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,gBAAgB;AAAA,gBAChB,UAAU;AAAA,gBACV,YAAY;AAAA,gBACZ;AAAA,gBACA,eAAe;AAAA,cACjB;AAAA,cAEC;AAAA;AAAA,UACH;AAAA,WACF;AAAA,QAEA,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO,QAAQ;AAAA,cACf,oBAAoB;AAAA,cACpB,OAAO;AAAA,cACP,WAAW;AAAA,cACX,YAAY;AAAA,YACd;AAAA,YAEC;AAAA;AAAA,cAAI;AAAA;AAAA;AAAA,QACP;AAAA,QAEA,gBAAAA,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,OAAO,YAAY,MAAM,GAC3D;AAAA,0BAAAD,KAAC,WAAQ,OAAc,OAAO,SAAI,KAAK,IAAI,SAAS,OAAO,oBAAC;AAAA,UAC5D,gBAAAA,KAAC,WAAQ,OAAc,OAAO,IAAI,KAAK,IAAI,SAAS,OAAO,eAAC;AAAA,UAC5D,gBAAAA,KAAC,WAAQ,OAAO,QAAQ,MAAM,OAAM,SAAQ,SAAS,SAAS,oBAAC;AAAA,WACjE;AAAA;AAAA;AAAA,EACF;AAEJ;AAOO,SAAS,iBAAiB,EAAE,SAAS,MAAM,GAA0B;AAC1E,QAAM,EAAE,QAAQ,QAAQ,QAAQ,UAAU,MAAM,IAAI,kBAAkB,OAAO;AAE7E,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,GAAG;AAAA,MACL;AAAA,MAEA;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,UAAU,iBAAiB;AAAA,YAClC,OAAO;AAAA,cACL,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,cAAc;AAAA,cACd,YAAY,UAAU,YAAY;AAAA,cAClC,WAAW,UAAU,sBAAsB;AAAA,cAC3C,YAAY;AAAA,cACZ,YAAY;AAAA,YACd;AAAA;AAAA,QACF;AAAA,QAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,OAAM;AAAA,YACN,OAAO,OAAO;AAAA,YACd,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC;AAAA,YAC5B,OAAO,MAAM,OAAO,MAAM,CAAC;AAAA,YAC3B,SAAS,MAAM,OAAO,CAAC;AAAA;AAAA,QACzB;AAAA,QAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,OAAM;AAAA,YACN,OAAO,OAAO;AAAA,YACd,OAAO,MAAM,OAAO,GAAG,CAAC,IAAI;AAAA,YAC5B,OAAO,MAAM,OAAO,GAAG,IAAI;AAAA,YAC3B,SAAS,MAAM,SAAS,CAAC;AAAA;AAAA,QAC3B;AAAA,QAEA,gBAAAA,KAAC,WAAQ,OAAM,WAAU,OAAM,aAAY,SAAS,OAAO,oBAAC;AAAA;AAAA;AAAA,EAC9D;AAEJ;;;ACbM,gBAAAE,YAAA;AAjKN,SAAS,sBACP,GACA,GACA,GACA,GACA;AACA,SAAO;AAAA,IACL,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE;AAAA,IACxC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE;AAAA,IACxC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,IAAI,IAAI,EAAE,EAAE;AAAA,EAC3C;AACF;AAEA,SAAS,MACP,IACA,IACA,IACA,IACA,IACA,IACA;AACA,SAAO;AAAA,IACL,GAAG,KAAK,KAAK,KAAK;AAAA,IAClB,GAAG,KAAK,KAAK,KAAK;AAAA,IAClB,GAAG,KAAK,KAAK,KAAK;AAAA,EACpB;AACF;AAOA,SAAS,gBACP,GACA,GACA,GACiB;AACjB,QAAM,CAAC,IAAI,IAAI,IAAI,EAAE,IAAI;AACzB,QAAM,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;AACtB,QAAM,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;AACtB,QAAM,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAClC,QAAM,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAGlC,QAAM,IAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,MAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AACxE,MAAE,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AAAA,EAC1E;AAEA,QAAM,IAAI;AACV,WAAS,MAAM,GAAG,MAAM,GAAG,OAAO;AAChC,QAAI,SAAS;AACb,aAAS,MAAM,MAAM,GAAG,MAAM,GAAG,OAAO;AACtC,UAAI,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,KAAK,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAG,UAAS;AAAA,IACjE;AACA,KAAC,EAAE,GAAG,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,EAAE,GAAG,CAAC;AACxC,QAAI,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,MAAO,QAAO;AAC1C,UAAM,QAAQ,EAAE,GAAG,EAAE,GAAG;AACxB,aAAS,IAAI,KAAK,KAAK,GAAG,IAAK,GAAE,GAAG,EAAE,CAAC,KAAK;AAC5C,aAAS,MAAM,GAAG,MAAM,GAAG,OAAO;AAChC,UAAI,QAAQ,IAAK;AACjB,YAAM,IAAI,EAAE,GAAG,EAAE,GAAG;AACpB,eAAS,IAAI,KAAK,KAAK,GAAG,IAAK,GAAE,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;AAC9B;AAOA,SAAS,cACP,GACA,GACA,GACQ;AACR,QAAM,KAAK,gBAAgB,GAAG,GAAG,CAAC;AAClC,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,IAAI;AAEjD,SACE,YACG,GAAG,IAAI,GAAG,MAAM,GAAG,IACnB,GAAG,IAAI,GAAG,MAAM,GAAG,YAEnB,GAAG,IAAI,GAAG;AAEjB;AAEO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,gBAAgB;AAClB,GAAkB;AAChB,QAAM,EAAE,SAAAC,SAAQ,IAAI,iBAAiB,OAAO;AAE5C,MAAI,CAAC,SAAS,CAAC,QAAS,QAAO;AAE/B,QAAM,KAAK,MAAM,eAAe;AAEhC,QAAM,WAAW,QAAQ;AAAA,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,MACvC,sBAAsB,IAAI,IAAI,IAAI,EAAE;AAAA,EACtC;AAEA,QAAM,MAAM,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE;AACxC,QAAM,MAAM,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE;AACxC,QAAM,MAAM,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE;AACxC,QAAM,MAAM,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE;AACxC,QAAM,MAAM,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE;AACxC,QAAM,MAAM,SAAS,CAAC,EAAE,IAAI,SAAS,CAAC,EAAE;AACxC,QAAM,SAAS,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAEjD,QAAM,SAAS,QAAQ,SAAU;AACjC,QAAM,SAAS,KAAK;AAAA,KACjB,OAAO,SAAS,CAAC,IAAI,OAAO,OAAO,CAAC,MAAM,KACxC,OAAO,SAAS,CAAC,IAAI,OAAO,OAAO,CAAC,MAAM,KAC1C,OAAO,SAAS,CAAC,IAAI,OAAO,OAAO,CAAC,MAAM;AAAA,EAC/C;AACA,QAAM,OACJ,OAAO,OAAO,CAAC,IAAI,SAAS,KAAK,IAAI,OAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG;AAC1E,QAAM,OAAO,OAAO,OAAO,CAAC,IAAI,SAAS,KAAK,IAAI,OAAO,KAAK;AAC9D,QAAM,OACJ,OAAO,OAAO,CAAC,IAAI,SAAS,KAAK,IAAI,OAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG;AAE1E,QAAM,WAAW;AAAA,IACf,GAAG,OAAO,SAAS,CAAC,EAAE;AAAA,IACtB,GAAG,OAAO,SAAS,CAAC,EAAE;AAAA,IACtB,GAAG,OAAO,SAAS,CAAC,EAAE;AAAA,EACxB;AACA,QAAM,MACJ,OAAO,IAAI,SAAS,IAAI,OAAO,IAAI,SAAS,IAAI,OAAO,IAAI,SAAS;AAEtE,MAAI,OAAO,EAAG,QAAO;AAErB,QAAM,YAAY,SAAS,IAAI,CAAC,MAAMA,SAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AAC5D,MAAI,UAAU,KAAK,CAAC,OAAO,CAAC,GAAG,OAAO,EAAG,QAAO;AAIhD,QAAM,WAAW,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC,GAAG,UAAU,CAAC,GAAG,UAAU,CAAC,CAAC;AACxE,QAAM,SAAS,cAAc,cAAc,eAAe,QAAQ;AAElE,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO;AAAA,QACP,eAAe;AAAA,QACf,UAAU;AAAA,MACZ;AAAA,MAEA,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,OAAO;AAAA,YACL,UAAU;AAAA,YACV,KAAK;AAAA,YACL,MAAM;AAAA,YACN,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,iBAAiB;AAAA,YACjB,WAAW;AAAA,YACX,UAAU;AAAA,YACV,eAAe;AAAA,YACf,GAAG;AAAA,UACL;AAAA,UAEC;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;","names":["useRef","useEffect","useCallback","jsx","useRef","useCallback","useEffect","jsx","jsxs","jsx","project"]}