@almadar/ui 6.12.0 → 6.14.0

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.
Files changed (47) hide show
  1. package/dist/{UserContext-g_LcDiGN.d.cts → CurrentPagePathContext-J1lqjvAq.d.cts} +2 -97
  2. package/dist/{UserContext-g_LcDiGN.d.ts → CurrentPagePathContext-J1lqjvAq.d.ts} +2 -97
  3. package/dist/{EntityBindingContext-D5lRu6p1.d.cts → EntityBindingContext-BMz9xiBa.d.cts} +2 -3
  4. package/dist/{EntityBindingContext-D5lRu6p1.d.ts → EntityBindingContext-BMz9xiBa.d.ts} +2 -3
  5. package/dist/{GameAudioProvider-D8GynTNq.d.cts → GameAudioProvider-Cpw_lMPY.d.cts} +1 -1
  6. package/dist/{GameAudioProvider-Dozqx4sL.d.ts → GameAudioProvider-DIjFiy70.d.ts} +1 -1
  7. package/dist/UserContext-D566nfWA.d.cts +99 -0
  8. package/dist/UserContext-D566nfWA.d.ts +99 -0
  9. package/dist/avl/index.cjs +571 -70
  10. package/dist/avl/index.d.cts +1 -1
  11. package/dist/avl/index.d.ts +1 -1
  12. package/dist/avl/index.js +573 -72
  13. package/dist/{avl-schema-parser-PVu8rgsy.d.cts → avl-schema-parser-B25PL-a8.d.cts} +1 -1
  14. package/dist/{avl-schema-parser-DX-aVCCm.d.ts → avl-schema-parser-CM0pQo8E.d.ts} +1 -1
  15. package/dist/components/index.cjs +564 -117
  16. package/dist/components/index.d.cts +8 -24
  17. package/dist/components/index.d.ts +8 -24
  18. package/dist/components/index.js +566 -118
  19. package/dist/context/index.d.cts +2 -1
  20. package/dist/context/index.d.ts +2 -1
  21. package/dist/lib/drawable/three/index.cjs +126 -3
  22. package/dist/lib/drawable/three/index.d.cts +3 -3
  23. package/dist/lib/drawable/three/index.d.ts +3 -3
  24. package/dist/lib/drawable/three/index.js +126 -3
  25. package/dist/lib/index.cjs +1 -4
  26. package/dist/lib/index.d.cts +2 -2
  27. package/dist/lib/index.d.ts +2 -2
  28. package/dist/lib/index.js +1 -4
  29. package/dist/{offline-executor-QUdKOj7f.d.cts → offline-executor-DdV2o0Zu.d.cts} +4 -19
  30. package/dist/{offline-executor-QUdKOj7f.d.ts → offline-executor-DdV2o0Zu.d.ts} +4 -19
  31. package/dist/{paintDispatch-CK5uwYEq.d.cts → paintDispatch-Dh1pgljl.d.cts} +79 -1
  32. package/dist/{paintDispatch-CK5uwYEq.d.ts → paintDispatch-Dh1pgljl.d.ts} +79 -1
  33. package/dist/providers/index.cjs +558 -62
  34. package/dist/providers/index.d.cts +10 -9
  35. package/dist/providers/index.d.ts +10 -9
  36. package/dist/providers/index.js +559 -63
  37. package/dist/renderer/index.cjs +0 -15
  38. package/dist/renderer/index.d.cts +4 -9
  39. package/dist/renderer/index.d.ts +4 -9
  40. package/dist/renderer/index.js +1 -15
  41. package/dist/runtime/index.cjs +573 -81
  42. package/dist/runtime/index.d.cts +14 -11
  43. package/dist/runtime/index.d.ts +14 -11
  44. package/dist/runtime/index.js +575 -83
  45. package/dist/{verificationRegistry-D8bHWD8Q.d.ts → verificationRegistry-Cwa52VyK.d.ts} +1 -1
  46. package/dist/{verificationRegistry-BLsjb1oU.d.cts → verificationRegistry-DTrKDRoa.d.cts} +1 -1
  47. package/package.json +4 -4
@@ -77,7 +77,7 @@ import { CSS } from '@dnd-kit/utilities';
77
77
  import { ordered, lib } from 'emojilib';
78
78
  import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
79
79
  import { forceSimulation, forceLink, forceManyBody, forceCollide, forceX, forceY } from 'd3-force';
80
- import { isDrawHostPattern, getPatternDefinition as getPatternDefinition$1, getPatternFieldsContract, getComponentForPattern as getComponentForPattern$1 } from '@almadar/core/patterns';
80
+ import { SELF_OVERLAY_PATTERN_TYPES, isDrawHostPattern, getPatternDefinition as getPatternDefinition$1, getPatternFieldsContract, getComponentForPattern as getComponentForPattern$1 } from '@almadar/core/patterns';
81
81
  import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
82
82
 
83
83
  var __defProp = Object.defineProperty;
@@ -8829,6 +8829,14 @@ function createWebPainter(ctx, onAssetLoad) {
8829
8829
  ctx.drawImage(img, dest.x, dest.y, dw, dh);
8830
8830
  }
8831
8831
  },
8832
+ blitTransformed(tex, src, affine) {
8833
+ const img = imageByHandle.get(tex);
8834
+ if (!img) return;
8835
+ ctx.save();
8836
+ ctx.transform(affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]);
8837
+ ctx.drawImage(img, src.x, src.y, src.w, src.h, src.x, src.y, src.w, src.h);
8838
+ ctx.restore();
8839
+ },
8832
8840
  fillRect(x, y, w, h, style) {
8833
8841
  ctx.fillStyle = toCanvasStyle(style);
8834
8842
  ctx.fillRect(x, y, w, h);
@@ -9418,6 +9426,271 @@ var init_DrawGroup = __esm({
9418
9426
  init_registry();
9419
9427
  }
9420
9428
  });
9429
+
9430
+ // lib/skinning.ts
9431
+ function composeAffine(a, b) {
9432
+ return [
9433
+ a[0] * b[0] + a[2] * b[1],
9434
+ a[1] * b[0] + a[3] * b[1],
9435
+ a[0] * b[2] + a[2] * b[3],
9436
+ a[1] * b[2] + a[3] * b[3],
9437
+ a[0] * b[4] + a[2] * b[5] + a[4],
9438
+ a[1] * b[4] + a[3] * b[5] + a[5]
9439
+ ];
9440
+ }
9441
+ function invertAffine(m) {
9442
+ const det = m[0] * m[3] - m[1] * m[2];
9443
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return IDENTITY;
9444
+ const inv = 1 / det;
9445
+ return [
9446
+ m[3] * inv,
9447
+ -m[1] * inv,
9448
+ -m[2] * inv,
9449
+ m[0] * inv,
9450
+ (m[2] * m[5] - m[3] * m[4]) * inv,
9451
+ (m[1] * m[4] - m[0] * m[5]) * inv
9452
+ ];
9453
+ }
9454
+ function applyAffine(m, x, y) {
9455
+ return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
9456
+ }
9457
+ function rotationAbout(pivot, degrees) {
9458
+ const r = degrees * Math.PI / 180;
9459
+ const cos = Math.cos(r);
9460
+ const sin = Math.sin(r);
9461
+ const [px, py] = pivot;
9462
+ return [cos, sin, -sin, cos, px - cos * px + sin * py, py - sin * px - cos * py];
9463
+ }
9464
+ function computeWorldMatrices(bones, pose) {
9465
+ const indexByName = /* @__PURE__ */ new Map();
9466
+ bones.forEach((b, i) => indexByName.set(b.name, i));
9467
+ const world = new Array(bones.length);
9468
+ const visiting = /* @__PURE__ */ new Set();
9469
+ const resolve = (i) => {
9470
+ const cached = world[i];
9471
+ if (cached) return cached;
9472
+ if (visiting.has(i)) return IDENTITY;
9473
+ visiting.add(i);
9474
+ const b = bones[i];
9475
+ const parentIndex = b.parent === null ? void 0 : indexByName.get(b.parent);
9476
+ const parentWorld = parentIndex === void 0 ? IDENTITY : resolve(parentIndex);
9477
+ const local = rotationAbout(b.pivot, pose[b.name] ?? 0);
9478
+ const m = composeAffine(parentWorld, local);
9479
+ visiting.delete(i);
9480
+ world[i] = m;
9481
+ return m;
9482
+ };
9483
+ return bones.map((_, i) => resolve(i));
9484
+ }
9485
+ function skinVertices(mesh, bindWorld, curWorld) {
9486
+ const skinMats = /* @__PURE__ */ new Map();
9487
+ const skinMat = (bone) => {
9488
+ let m = skinMats.get(bone);
9489
+ if (!m) {
9490
+ m = composeAffine(curWorld[bone] ?? IDENTITY, invertAffine(bindWorld[bone] ?? IDENTITY));
9491
+ skinMats.set(bone, m);
9492
+ }
9493
+ return m;
9494
+ };
9495
+ return mesh.vertices.map((v) => {
9496
+ if (v.weights.length === 0) return [v.x, v.y];
9497
+ let x = 0;
9498
+ let y = 0;
9499
+ for (const { bone, w } of v.weights) {
9500
+ const [bx, by] = applyAffine(skinMat(bone), v.x, v.y);
9501
+ x += w * bx;
9502
+ y += w * by;
9503
+ }
9504
+ return [x, y];
9505
+ });
9506
+ }
9507
+ function triangleAffine(src, dst) {
9508
+ const [s0, s1, s2] = src;
9509
+ const det = s0[0] * (s1[1] - s2[1]) + s1[0] * (s2[1] - s0[1]) + s2[0] * (s0[1] - s1[1]);
9510
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return null;
9511
+ const [d0, d1, d2] = dst;
9512
+ const a = (d0[0] * (s1[1] - s2[1]) + d1[0] * (s2[1] - s0[1]) + d2[0] * (s0[1] - s1[1])) / det;
9513
+ const c = (d0[0] * (s2[0] - s1[0]) + d1[0] * (s0[0] - s2[0]) + d2[0] * (s1[0] - s0[0])) / det;
9514
+ const e = (d0[0] * (s1[0] * s2[1] - s2[0] * s1[1]) + d1[0] * (s2[0] * s0[1] - s0[0] * s2[1]) + d2[0] * (s0[0] * s1[1] - s1[0] * s0[1])) / det;
9515
+ const b = (d0[1] * (s1[1] - s2[1]) + d1[1] * (s2[1] - s0[1]) + d2[1] * (s0[1] - s1[1])) / det;
9516
+ const d = (d0[1] * (s2[0] - s1[0]) + d1[1] * (s0[0] - s2[0]) + d2[1] * (s1[0] - s0[0])) / det;
9517
+ const f3 = (d0[1] * (s1[0] * s2[1] - s2[0] * s1[1]) + d1[1] * (s2[0] * s0[1] - s0[0] * s2[1]) + d2[1] * (s0[0] * s1[1] - s1[0] * s0[1])) / det;
9518
+ return [a, b, c, d, e, f3];
9519
+ }
9520
+ function isRigBundle(json) {
9521
+ return json.mesh !== void 0 || json.bones !== void 0;
9522
+ }
9523
+ function getRigBundle(url, onReady) {
9524
+ if (meshCache.has(url)) return meshCache.get(url) ?? void 0;
9525
+ meshCache.set(url, void 0);
9526
+ fetch(url).then((r) => {
9527
+ if (!r.ok) throw new Error(`rigbundle fetch failed: HTTP ${r.status}`);
9528
+ return r.json();
9529
+ }).then((json) => {
9530
+ const ok = isRigBundle(json) || Array.isArray(json.vertices);
9531
+ if (!ok) throw new Error("rigbundle payload is neither a SkinMesh nor a rigbundle");
9532
+ meshCache.set(url, json);
9533
+ onReady();
9534
+ }).catch(() => {
9535
+ meshCache.set(url, null);
9536
+ onReady();
9537
+ });
9538
+ return void 0;
9539
+ }
9540
+ function skinMeshFailed(url) {
9541
+ return meshCache.get(url) === null;
9542
+ }
9543
+ function vertexBounds(points) {
9544
+ if (points.length === 0) return null;
9545
+ let minX = Infinity;
9546
+ let minY = Infinity;
9547
+ let maxX = -Infinity;
9548
+ let maxY = -Infinity;
9549
+ for (const [x, y] of points) {
9550
+ if (x < minX) minX = x;
9551
+ if (y < minY) minY = y;
9552
+ if (x > maxX) maxX = x;
9553
+ if (y > maxY) maxY = y;
9554
+ }
9555
+ return { minX, minY, maxX, maxY };
9556
+ }
9557
+ var IDENTITY, meshCache;
9558
+ var init_skinning = __esm({
9559
+ "lib/skinning.ts"() {
9560
+ IDENTITY = [1, 0, 0, 1, 0, 0];
9561
+ meshCache = /* @__PURE__ */ new Map();
9562
+ }
9563
+ });
9564
+ function warnMissingOnce2(reason, node) {
9565
+ const key = `${reason}:${node.asset.url}:${String(node.meshUrl)}`;
9566
+ if (loggedMissing2.has(key)) return;
9567
+ loggedMissing2.add(key);
9568
+ skinnedLog.warn("draw-skinned-mesh unresolvable \u2014 painting fallback", { reason, url: node.asset.url, meshUrl: node.meshUrl });
9569
+ }
9570
+ function dominantBone(v) {
9571
+ let best = -1;
9572
+ let bestW = 0;
9573
+ for (const { bone, w } of v.weights) {
9574
+ if (w > bestW) {
9575
+ bestW = w;
9576
+ best = bone;
9577
+ }
9578
+ }
9579
+ return best;
9580
+ }
9581
+ function resolveSkinPose(node, clip) {
9582
+ const effectiveClip = clip ?? node.clip;
9583
+ if (effectiveClip && node.frame !== void 0 && effectiveClip.frames.length > 0) {
9584
+ return effectiveClip.frames[node.frame % effectiveClip.frames.length];
9585
+ }
9586
+ return node.pose ?? {};
9587
+ }
9588
+ function resolveRig(node, dctx) {
9589
+ const fetched = node.meshUrl ? getRigBundle(node.meshUrl, dctx.invalidate) : void 0;
9590
+ if (node.meshUrl && fetched === void 0) return void 0;
9591
+ const rb = fetched && isRigBundle(fetched) ? fetched : void 0;
9592
+ const mesh = node.mesh ?? rb?.mesh ?? (!rb ? fetched : void 0);
9593
+ if (!mesh) return void 0;
9594
+ const bones = node.bones.length > 0 ? node.bones : rb?.bones ?? [];
9595
+ if (bones.length === 0) return void 0;
9596
+ const clip = node.clip ?? (node.clipName ? rb?.clips?.[node.clipName] : void 0);
9597
+ return { mesh, bones, clip };
9598
+ }
9599
+ function meshHasPixelUVs(mesh) {
9600
+ const cached = pixelUVByMesh.get(mesh);
9601
+ if (cached !== void 0) return cached;
9602
+ let pixel = false;
9603
+ for (const v of mesh.vertices) {
9604
+ if (v.u < 0 || v.u > 1 || v.v < 0 || v.v > 1) {
9605
+ pixel = true;
9606
+ break;
9607
+ }
9608
+ }
9609
+ pixelUVByMesh.set(mesh, pixel);
9610
+ return pixel;
9611
+ }
9612
+ function paintMeshPass(painter, node, bones, mesh, tex, dctx, pose, opacity) {
9613
+ const bindWorld = computeWorldMatrices(bones, {});
9614
+ const curWorld = computeWorldMatrices(bones, pose);
9615
+ const skinned = skinVertices(mesh, bindWorld, curWorld);
9616
+ const origin = dctx.projector.project(node.position);
9617
+ const tw = dctx.projector.tileWidth;
9618
+ painter.save();
9619
+ if (opacity !== 1) painter.setAlpha(opacity);
9620
+ for (const [i0, i1, i2] of mesh.triangles) {
9621
+ const v0 = mesh.vertices[i0];
9622
+ const v1 = mesh.vertices[i1];
9623
+ const v2 = mesh.vertices[i2];
9624
+ const p0 = skinned[i0];
9625
+ const p1 = skinned[i1];
9626
+ const p2 = skinned[i2];
9627
+ if (!v0 || !v1 || !v2 || !p0 || !p1 || !p2) continue;
9628
+ const dst = [
9629
+ [origin.x + p0[0] * tw, origin.y + p0[1] * tw],
9630
+ [origin.x + p1[0] * tw, origin.y + p1[1] * tw],
9631
+ [origin.x + p2[0] * tw, origin.y + p2[1] * tw]
9632
+ ];
9633
+ if (node.weightsOverlay || !tex) {
9634
+ if (!node.weightsOverlay) continue;
9635
+ const bone = dominantBone(v0);
9636
+ painter.fillPoly(
9637
+ dst.map(([x, y]) => ({ x, y })),
9638
+ WEIGHT_PALETTE[(bone % WEIGHT_PALETTE.length + WEIGHT_PALETTE.length) % WEIGHT_PALETTE.length]
9639
+ );
9640
+ continue;
9641
+ }
9642
+ const pixelUV = meshHasPixelUVs(mesh);
9643
+ const uv = pixelUV ? [[v0.u, v0.v], [v1.u, v1.v], [v2.u, v2.v]] : [
9644
+ [v0.u * tex.width, v0.v * tex.height],
9645
+ [v1.u * tex.width, v1.v * tex.height],
9646
+ [v2.u * tex.width, v2.v * tex.height]
9647
+ ];
9648
+ const affine = triangleAffine(uv, dst);
9649
+ if (!affine) continue;
9650
+ painter.save();
9651
+ painter.clipPath(`M ${dst[0][0]} ${dst[0][1]} L ${dst[1][0]} ${dst[1][1]} L ${dst[2][0]} ${dst[2][1]} Z`);
9652
+ painter.blitTransformed(tex, { x: 0, y: 0, w: tex.width, h: tex.height }, affine);
9653
+ painter.restore();
9654
+ }
9655
+ painter.restore();
9656
+ }
9657
+ function DrawSkinnedMesh(props) {
9658
+ const register = useContext(DrawableRegistryContext);
9659
+ if (register) register({ ...props, type: "draw-skinned-mesh" });
9660
+ return null;
9661
+ }
9662
+ var skinnedLog, loggedMissing2, WEIGHT_PALETTE, pixelUVByMesh, paintSkinnedMesh;
9663
+ var init_DrawSkinnedMesh = __esm({
9664
+ "components/game/atoms/DrawSkinnedMesh.tsx"() {
9665
+ "use client";
9666
+ init_imageCache();
9667
+ init_contract();
9668
+ init_registry();
9669
+ init_skinning();
9670
+ skinnedLog = createLogger("almadar:ui:draw-skinned-mesh");
9671
+ loggedMissing2 = /* @__PURE__ */ new Set();
9672
+ WEIGHT_PALETTE = Array.from({ length: 10 }, (_, i) => `hsl(${i * 36 % 360}, 70%, 55%)`);
9673
+ pixelUVByMesh = /* @__PURE__ */ new WeakMap();
9674
+ paintSkinnedMesh = (painter, node, dctx) => {
9675
+ if (!isValidScenePos(node.position)) return;
9676
+ const rig = resolveRig(node, dctx);
9677
+ if (!rig) {
9678
+ if (node.meshUrl && skinMeshFailed(node.meshUrl)) warnMissingOnce2("mesh-failed", node);
9679
+ else if (!node.mesh && !node.meshUrl) warnMissingOnce2("mesh-missing", node);
9680
+ return;
9681
+ }
9682
+ const tex = node.weightsOverlay ? null : painter.resolveTexture(node.asset.url);
9683
+ if (!node.weightsOverlay && !tex) {
9684
+ if (getImageStatus(node.asset.url) === "failed") warnMissingOnce2("texture-failed", node);
9685
+ return;
9686
+ }
9687
+ if (node.ghost && rig.clip && rig.clip.frames.length > 0) {
9688
+ paintMeshPass(painter, node, rig.bones, rig.mesh, tex, dctx, rig.clip.frames[node.ghost.frame % rig.clip.frames.length], node.ghost.opacity);
9689
+ }
9690
+ paintMeshPass(painter, node, rig.bones, rig.mesh, tex, dctx, resolveSkinPose(node, rig.clip), node.opacity ?? 1);
9691
+ };
9692
+ }
9693
+ });
9421
9694
  function applyMeshAnimation(node, timeMs) {
9422
9695
  const anim = node.animation;
9423
9696
  if (!anim || !(anim.durationMs > 0) || anim.keyframes.length === 0) return null;
@@ -9742,6 +10015,9 @@ function paintDrawable(painter, node, dctx) {
9742
10015
  case "draw-mesh":
9743
10016
  warnUnsupported2d("draw-mesh");
9744
10017
  break;
10018
+ case "draw-skinned-mesh":
10019
+ paintSkinnedMesh(painter, node, dctx);
10020
+ break;
9745
10021
  case "draw-sprite-layer":
9746
10022
  paintSpriteLayer(painter, node, dctx);
9747
10023
  break;
@@ -9766,6 +10042,7 @@ var init_paintDispatch = __esm({
9766
10042
  init_DrawShape();
9767
10043
  init_DrawText();
9768
10044
  init_DrawGroup();
10045
+ init_DrawSkinnedMesh();
9769
10046
  init_DrawMesh();
9770
10047
  init_DrawSpriteLayer();
9771
10048
  init_DrawShapeLayer();
@@ -11426,7 +11703,6 @@ var init_avl_atom_types = __esm({
11426
11703
  "persist": "data",
11427
11704
  "fetch": "data",
11428
11705
  "emit": "communication",
11429
- "notify": "communication",
11430
11706
  "call-service": "communication",
11431
11707
  "spawn": "lifecycle",
11432
11708
  "despawn": "lifecycle",
@@ -11574,12 +11850,6 @@ function effectIcon(type, x, y, s, color) {
11574
11850
  /* @__PURE__ */ jsx("line", { x1: x - s, y1: y, x2: x + s * 0.6, y2: y, stroke: color, strokeWidth: 1.5 }),
11575
11851
  /* @__PURE__ */ jsx("polyline", { points: `${x + s * 0.1},${y - s * 0.5} ${x + s},${y} ${x + s * 0.1},${y + s * 0.5}`, fill: "none", stroke: color, strokeWidth: 1.5, strokeLinejoin: "round" })
11576
11852
  ] });
11577
- case "notify":
11578
- return /* @__PURE__ */ jsxs("g", { children: [
11579
- /* @__PURE__ */ jsx("path", { d: `M${x - s * 0.7},${y + s * 0.3} Q${x - s * 0.7},${y - s} ${x},${y - s} Q${x + s * 0.7},${y - s} ${x + s * 0.7},${y + s * 0.3} Z`, fill: "none", stroke: color, strokeWidth: 1.5 }),
11580
- /* @__PURE__ */ jsx("line", { x1: x - s * 0.8, y1: y + s * 0.3, x2: x + s * 0.8, y2: y + s * 0.3, stroke: color, strokeWidth: 1.5 }),
11581
- /* @__PURE__ */ jsx("circle", { cx: x, cy: y + s * 0.7, r: s * 0.2, fill: color })
11582
- ] });
11583
11853
  case "call-service":
11584
11854
  return /* @__PURE__ */ jsxs("g", { children: [
11585
11855
  /* @__PURE__ */ jsx("line", { x1: x - s, y1: y - s * 0.3, x2: x + s, y2: y - s * 0.3, stroke: color, strokeWidth: 1.5 }),
@@ -16836,9 +17106,6 @@ function getEffectSummary(effects) {
16836
17106
  case "emit":
16837
17107
  summaries.push(`\u2191 ${effect[1] || "event"}`);
16838
17108
  break;
16839
- case "notify":
16840
- summaries.push(`\u{1F4E7} ${effect[1] || ""}`);
16841
- break;
16842
17109
  case "persist":
16843
17110
  summaries.push(`\u{1F4BE} ${effect[1] || "save"}`);
16844
17111
  break;
@@ -16864,7 +17131,7 @@ function extractOutputsFromTransitions(transitions) {
16864
17131
  t.effects.forEach((effect) => {
16865
17132
  if (Array.isArray(effect)) {
16866
17133
  const op = effect[0];
16867
- if (["emit", "notify", "persist", "navigate", "call-service"].includes(op)) {
17134
+ if (["emit", "persist", "navigate", "call-service"].includes(op)) {
16868
17135
  if (isArraySExpr(effect)) {
16869
17136
  const humanText = formatSExprEffectToDomain(effect);
16870
17137
  outputs.add(humanText);
@@ -19828,6 +20095,21 @@ function shapeDrawnItem(n) {
19828
20095
  if (n.shape !== "rect") return { pos: n.position, id: n.id };
19829
20096
  return { pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height, rotation: n.rotate };
19830
20097
  }
20098
+ function skinnedMeshDrawnItem(n) {
20099
+ const mesh = n.mesh;
20100
+ if (!mesh || n.bones.length === 0) return { pos: n.position, id: n.id };
20101
+ const bindWorld = computeWorldMatrices(n.bones, {});
20102
+ const curWorld = computeWorldMatrices(n.bones, resolveSkinPose(n));
20103
+ const bounds = vertexBounds(skinVertices(mesh, bindWorld, curWorld));
20104
+ if (!bounds) return { pos: n.position, id: n.id };
20105
+ return {
20106
+ pos: { ...n.position, x: n.position.x + bounds.minX, y: n.position.y + bounds.minY },
20107
+ id: n.id,
20108
+ anchor: "top-left",
20109
+ width: bounds.maxX - bounds.minX,
20110
+ height: bounds.maxY - bounds.minY
20111
+ };
20112
+ }
19831
20113
  function collectDrawnItems(nodes) {
19832
20114
  const out = [];
19833
20115
  for (const n of nodes) {
@@ -19838,6 +20120,9 @@ function collectDrawnItems(nodes) {
19838
20120
  case "draw-shape":
19839
20121
  if (isValidScenePos(n.position)) out.push(shapeDrawnItem(n));
19840
20122
  break;
20123
+ case "draw-skinned-mesh":
20124
+ if (isValidScenePos(n.position)) out.push(skinnedMeshDrawnItem(n));
20125
+ break;
19841
20126
  case "draw-text":
19842
20127
  case "draw-group":
19843
20128
  case "draw-mesh":
@@ -19905,6 +20190,8 @@ function rotatePoint(p, center, radians) {
19905
20190
  var init_hitTest = __esm({
19906
20191
  "lib/drawable/hitTest.ts"() {
19907
20192
  init_contract();
20193
+ init_DrawSkinnedMesh();
20194
+ init_skinning();
19908
20195
  }
19909
20196
  });
19910
20197
  function normalizeBackdrop(bg) {
@@ -24038,6 +24325,18 @@ var init_useAuthContext = __esm({
24038
24325
  "hooks/useAuthContext.ts"() {
24039
24326
  }
24040
24327
  });
24328
+ function resolveActiveNavHref(items, currentPath) {
24329
+ let best;
24330
+ for (const item of items) {
24331
+ for (const href of item.children?.length ? [item.href, ...item.children.map((c) => c.href)] : [item.href]) {
24332
+ if (currentPath === href) return href;
24333
+ if (currentPath.startsWith(href + "/") && (!best || href.length > best.length)) {
24334
+ best = href;
24335
+ }
24336
+ }
24337
+ }
24338
+ return best;
24339
+ }
24041
24340
  var DashboardLayout, NavLink, NavLinkTopnav, NavLinkBottom;
24042
24341
  var init_DashboardLayout = __esm({
24043
24342
  "components/core/templates/DashboardLayout.tsx"() {
@@ -24109,6 +24408,7 @@ var init_DashboardLayout = __esm({
24109
24408
  const location = useLocation();
24110
24409
  const ctxPagePath = useCurrentPagePath();
24111
24410
  const activePath = (currentPath || void 0) ?? ctxPagePath ?? location.pathname;
24411
+ const activeHref = useMemo(() => resolveActiveNavHref(navItems, activePath), [navItems, activePath]);
24112
24412
  const { user: authUser, signOut: authSignOut } = useAuthContext();
24113
24413
  const user = userProp || (authUser ? {
24114
24414
  name: authUser.displayName || authUser.email?.split("@")[0] || "User",
@@ -24205,7 +24505,7 @@ var init_DashboardLayout = __esm({
24205
24505
  NavLink,
24206
24506
  {
24207
24507
  item,
24208
- currentPath: activePath,
24508
+ activeHref,
24209
24509
  compact: isRail
24210
24510
  },
24211
24511
  item.href
@@ -24272,7 +24572,7 @@ var init_DashboardLayout = __esm({
24272
24572
  NavLinkTopnav,
24273
24573
  {
24274
24574
  item,
24275
- currentPath: activePath
24575
+ activeHref
24276
24576
  },
24277
24577
  item.href
24278
24578
  ))
@@ -24448,7 +24748,7 @@ var init_DashboardLayout = __esm({
24448
24748
  NavLinkBottom,
24449
24749
  {
24450
24750
  item,
24451
- currentPath: activePath
24751
+ activeHref
24452
24752
  },
24453
24753
  item.href
24454
24754
  )) })
@@ -24462,15 +24762,71 @@ var init_DashboardLayout = __esm({
24462
24762
  DashboardLayout.displayName = "DashboardLayout";
24463
24763
  NavLink = ({
24464
24764
  item,
24465
- currentPath,
24765
+ activeHref,
24466
24766
  compact = false
24467
24767
  }) => {
24468
- const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
24768
+ const hasChildren = !!item.children?.length;
24769
+ const childActive = hasChildren && item.children.some((child) => child.href === activeHref);
24770
+ const isActive = item.href === activeHref || childActive;
24771
+ const [open, setOpen] = useState(childActive);
24469
24772
  const iconClassName = cn(
24470
24773
  "h-5 w-5",
24471
24774
  isActive ? "text-primary-foreground" : "text-muted-foreground"
24472
24775
  );
24473
24776
  if (compact) {
24777
+ if (hasChildren) {
24778
+ return /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
24779
+ /* @__PURE__ */ jsx(
24780
+ Button,
24781
+ {
24782
+ variant: "ghost",
24783
+ title: item.label,
24784
+ "aria-label": item.label,
24785
+ "aria-expanded": open,
24786
+ className: cn(
24787
+ "flex items-center justify-center w-full px-2 py-2 rounded-lg transition-colors",
24788
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
24789
+ ),
24790
+ onClick: () => setOpen(!open),
24791
+ children: /* @__PURE__ */ jsxs(Box, { as: "span", className: "relative inline-flex", children: [
24792
+ item.icon ? typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, className: iconClassName }) : /* @__PURE__ */ jsx(item.icon, { className: iconClassName }) : /* @__PURE__ */ jsx(Typography, { variant: "small", className: "font-semibold", as: "span", children: item.label.charAt(0).toUpperCase() }),
24793
+ item.badge && /* @__PURE__ */ jsx(
24794
+ Badge,
24795
+ {
24796
+ variant: isActive ? "primary" : "default",
24797
+ size: "sm",
24798
+ className: "absolute -top-2 -right-2 px-1 py-0 text-[10px] leading-4",
24799
+ children: item.badge
24800
+ }
24801
+ )
24802
+ ] })
24803
+ }
24804
+ ),
24805
+ open && /* @__PURE__ */ jsxs(Fragment, { children: [
24806
+ /* @__PURE__ */ jsx(Box, { className: "fixed inset-0 z-20", onClick: () => setOpen(false) }),
24807
+ /* @__PURE__ */ jsx(Box, { className: "absolute left-full top-0 ml-2 w-48 bg-card dark:bg-card rounded-lg shadow-lg border border-border dark:border-border py-1 z-30", children: item.children.map((child) => {
24808
+ const childIsActive = child.href === activeHref;
24809
+ return /* @__PURE__ */ jsxs(
24810
+ Link,
24811
+ {
24812
+ to: child.href,
24813
+ onClick: () => setOpen(false),
24814
+ className: cn(
24815
+ "flex items-center gap-2 px-3 py-2 text-sm transition-colors",
24816
+ childIsActive ? "bg-muted text-foreground font-medium" : "text-muted-foreground hover:bg-muted hover:text-foreground"
24817
+ ),
24818
+ children: [
24819
+ child.icon && (typeof child.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: child.icon, className: "h-4 w-4" }) : /* @__PURE__ */ jsx(child.icon, { className: "h-4 w-4" })),
24820
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: "flex-1", as: "span", children: child.label }),
24821
+ child.badge && /* @__PURE__ */ jsx(Badge, { variant: childIsActive ? "primary" : "default", size: "sm", children: child.badge })
24822
+ ]
24823
+ },
24824
+ child.href
24825
+ );
24826
+ }) })
24827
+ ] })
24828
+ ] });
24829
+ }
24474
24830
  return /* @__PURE__ */ jsx(
24475
24831
  Link,
24476
24832
  {
@@ -24496,6 +24852,78 @@ var init_DashboardLayout = __esm({
24496
24852
  }
24497
24853
  );
24498
24854
  }
24855
+ if (hasChildren) {
24856
+ return /* @__PURE__ */ jsxs(Box, { children: [
24857
+ /* @__PURE__ */ jsxs(
24858
+ Button,
24859
+ {
24860
+ variant: "ghost",
24861
+ "aria-expanded": open,
24862
+ className: cn(
24863
+ "flex items-center gap-3 w-full px-3 py-2 rounded-lg text-sm font-medium transition-colors",
24864
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
24865
+ ),
24866
+ onClick: () => setOpen(!open),
24867
+ children: [
24868
+ item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, className: iconClassName }) : /* @__PURE__ */ jsx(item.icon, { className: iconClassName })),
24869
+ /* @__PURE__ */ jsx(
24870
+ Typography,
24871
+ {
24872
+ variant: "small",
24873
+ color: isActive ? "inherit" : "primary",
24874
+ className: "flex-1 text-left",
24875
+ as: "span",
24876
+ children: item.label
24877
+ }
24878
+ ),
24879
+ item.badge && /* @__PURE__ */ jsx(Badge, { variant: isActive ? "primary" : "default", size: "sm", children: item.badge }),
24880
+ /* @__PURE__ */ jsx(
24881
+ Icon,
24882
+ {
24883
+ name: "chevron-down",
24884
+ className: cn("h-4 w-4 shrink-0 transition-transform", open && "rotate-180")
24885
+ }
24886
+ )
24887
+ ]
24888
+ }
24889
+ ),
24890
+ open && /* @__PURE__ */ jsx(
24891
+ VStack,
24892
+ {
24893
+ gap: "none",
24894
+ className: "mt-1 ml-4 pl-4 border-l border-border dark:border-border space-y-1",
24895
+ children: item.children.map((child) => {
24896
+ const childIsActive = child.href === activeHref;
24897
+ return /* @__PURE__ */ jsxs(
24898
+ Link,
24899
+ {
24900
+ to: child.href,
24901
+ className: cn(
24902
+ "flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm transition-colors",
24903
+ childIsActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
24904
+ ),
24905
+ children: [
24906
+ child.icon && (typeof child.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: child.icon, className: "h-4 w-4" }) : /* @__PURE__ */ jsx(child.icon, { className: "h-4 w-4" })),
24907
+ /* @__PURE__ */ jsx(
24908
+ Typography,
24909
+ {
24910
+ variant: "small",
24911
+ color: childIsActive ? "inherit" : "primary",
24912
+ className: "flex-1",
24913
+ as: "span",
24914
+ children: child.label
24915
+ }
24916
+ ),
24917
+ child.badge && /* @__PURE__ */ jsx(Badge, { variant: childIsActive ? "primary" : "default", size: "sm", children: child.badge })
24918
+ ]
24919
+ },
24920
+ child.href
24921
+ );
24922
+ })
24923
+ }
24924
+ )
24925
+ ] });
24926
+ }
24499
24927
  return /* @__PURE__ */ jsxs(
24500
24928
  Link,
24501
24929
  {
@@ -24524,9 +24952,63 @@ var init_DashboardLayout = __esm({
24524
24952
  NavLink.displayName = "NavLink";
24525
24953
  NavLinkTopnav = ({
24526
24954
  item,
24527
- currentPath
24955
+ activeHref
24528
24956
  }) => {
24529
- const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
24957
+ const hasChildren = !!item.children?.length;
24958
+ const childActive = hasChildren && item.children.some((child) => child.href === activeHref);
24959
+ const isActive = item.href === activeHref || childActive;
24960
+ const [open, setOpen] = useState(false);
24961
+ if (hasChildren) {
24962
+ return /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
24963
+ /* @__PURE__ */ jsxs(
24964
+ Button,
24965
+ {
24966
+ variant: "ghost",
24967
+ "aria-expanded": open,
24968
+ className: cn(
24969
+ "flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors whitespace-nowrap",
24970
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
24971
+ ),
24972
+ onClick: () => setOpen(!open),
24973
+ children: [
24974
+ item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, className: "h-4 w-4" }) : /* @__PURE__ */ jsx(item.icon, { className: "h-4 w-4" })),
24975
+ /* @__PURE__ */ jsx(Typography, { variant: "small", color: "inherit", className: "flex-1", as: "span", children: item.label }),
24976
+ item.badge && /* @__PURE__ */ jsx(Badge, { variant: isActive ? "primary" : "default", size: "sm", children: item.badge }),
24977
+ /* @__PURE__ */ jsx(
24978
+ Icon,
24979
+ {
24980
+ name: "chevron-down",
24981
+ className: cn("h-3.5 w-3.5 shrink-0 transition-transform", open && "rotate-180")
24982
+ }
24983
+ )
24984
+ ]
24985
+ }
24986
+ ),
24987
+ open && /* @__PURE__ */ jsxs(Fragment, { children: [
24988
+ /* @__PURE__ */ jsx(Box, { className: "fixed inset-0 z-20", onClick: () => setOpen(false) }),
24989
+ /* @__PURE__ */ jsx(Box, { className: "absolute left-0 top-full mt-1 w-48 bg-card dark:bg-card rounded-lg shadow-lg border border-border dark:border-border py-1 z-30", children: item.children.map((child) => {
24990
+ const childIsActive = child.href === activeHref;
24991
+ return /* @__PURE__ */ jsxs(
24992
+ Link,
24993
+ {
24994
+ to: child.href,
24995
+ onClick: () => setOpen(false),
24996
+ className: cn(
24997
+ "flex items-center gap-2 px-3 py-2 text-sm transition-colors",
24998
+ childIsActive ? "bg-muted text-foreground font-medium" : "text-muted-foreground hover:bg-muted hover:text-foreground"
24999
+ ),
25000
+ children: [
25001
+ child.icon && (typeof child.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: child.icon, className: "h-4 w-4" }) : /* @__PURE__ */ jsx(child.icon, { className: "h-4 w-4" })),
25002
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: "flex-1", as: "span", children: child.label }),
25003
+ child.badge && /* @__PURE__ */ jsx(Badge, { variant: childIsActive ? "primary" : "default", size: "sm", children: child.badge })
25004
+ ]
25005
+ },
25006
+ child.href
25007
+ );
25008
+ }) })
25009
+ ] })
25010
+ ] });
25011
+ }
24530
25012
  return /* @__PURE__ */ jsxs(
24531
25013
  Link,
24532
25014
  {
@@ -24546,9 +25028,9 @@ var init_DashboardLayout = __esm({
24546
25028
  NavLinkTopnav.displayName = "NavLinkTopnav";
24547
25029
  NavLinkBottom = ({
24548
25030
  item,
24549
- currentPath
25031
+ activeHref
24550
25032
  }) => {
24551
- const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
25033
+ const isActive = item.href === activeHref;
24552
25034
  const iconClassName = cn(
24553
25035
  "h-5 w-5",
24554
25036
  isActive ? "text-primary" : "text-muted-foreground"
@@ -25487,7 +25969,9 @@ function DataGrid({
25487
25969
  const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
25488
25970
  const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
25489
25971
  const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
25490
- const hasRenderProp = typeof children === "function";
25972
+ const renderItemFn = typeof schemaRenderItem === "function" ? schemaRenderItem : void 0;
25973
+ const itemRenderer = typeof children === "function" ? children : renderItemFn;
25974
+ const hasRenderProp = typeof itemRenderer === "function";
25491
25975
  useEffect(() => {
25492
25976
  if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
25493
25977
  const schemaArr = Array.isArray(schemaRenderItem) ? schemaRenderItem : null;
@@ -25561,7 +26045,7 @@ function DataGrid({
25561
26045
  onClick: handleCardClick?.(itemData),
25562
26046
  className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
25563
26047
  children: [
25564
- children(itemData, index),
26048
+ itemRenderer(itemData, index),
25565
26049
  actionDefs.length > 0 && /* @__PURE__ */ jsx(Box, { onClick: stopCardClick, className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: [
25566
26050
  inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxs(
25567
26051
  Button,
@@ -25894,7 +26378,9 @@ function DataList({
25894
26378
  );
25895
26379
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
25896
26380
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
25897
- const hasRenderProp = typeof children === "function";
26381
+ const renderItemFn = typeof schemaRenderItem === "function" ? schemaRenderItem : void 0;
26382
+ const itemRenderer = typeof children === "function" ? children : renderItemFn;
26383
+ const hasRenderProp = typeof itemRenderer === "function";
25898
26384
  React79__default.useEffect(() => {
25899
26385
  const renderItemTypeOf = typeof schemaRenderItem;
25900
26386
  const childrenTypeOf = typeof children;
@@ -26112,7 +26598,7 @@ function DataList({
26112
26598
  const actions = renderItemActions(itemData);
26113
26599
  return wrapDnd(
26114
26600
  /* @__PURE__ */ jsxs(Box, { "data-entity-row": true, "data-entity-id": id2, onClick: rowClickEvent ? handleRowClick(itemData) : void 0, className: cn("relative group/rowactions", rowClickEvent && "cursor-pointer"), children: [
26115
- children(itemData, index),
26601
+ itemRenderer(itemData, index),
26116
26602
  actions && /* @__PURE__ */ jsxs(Box, { className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: [
26117
26603
  /* @__PURE__ */ jsx(Box, { className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5 [@media(pointer:coarse)]:hidden", children: actions }),
26118
26604
  /* @__PURE__ */ jsx(Box, { className: "hidden [@media(pointer:coarse)]:block rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: /* @__PURE__ */ jsx(
@@ -31465,7 +31951,7 @@ var init_DialogueBubble = __esm({
31465
31951
  init_Typography();
31466
31952
  init_GameIcon();
31467
31953
  DEFAULT_PORTRAIT = {
31468
- url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
31954
+ url: "https://almadar-kflow-assets.web.app/shared/ui-winter-ski-board/default/units/hero/hero.png",
31469
31955
  role: "effect",
31470
31956
  category: "character"
31471
31957
  };
@@ -32457,7 +32943,7 @@ var init_StateIndicator = __esm({
32457
32943
  init_cn();
32458
32944
  init_GameIcon();
32459
32945
  DEFAULT_ASSET_URL = {
32460
- url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
32946
+ url: "https://almadar-kflow-assets.web.app/shared/ui-topdown-dungeon-board/default/features/chest/chest.png",
32461
32947
  role: "ui",
32462
32948
  category: "state"
32463
32949
  };
@@ -35158,13 +35644,13 @@ var init_MapView = __esm({
35158
35644
  shadowSize: [41, 41]
35159
35645
  });
35160
35646
  L.Marker.prototype.options.icon = defaultIcon;
35161
- const { useEffect: useEffect73, useRef: useRef70, useCallback: useCallback110, useState: useState110 } = React79__default;
35647
+ const { useEffect: useEffect72, useRef: useRef70, useCallback: useCallback109, useState: useState109 } = React79__default;
35162
35648
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
35163
35649
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
35164
35650
  function MapUpdater({ centerLat, centerLng, zoom }) {
35165
35651
  const map = useMap();
35166
35652
  const prevRef = useRef70({ centerLat, centerLng, zoom });
35167
- useEffect73(() => {
35653
+ useEffect72(() => {
35168
35654
  const prev = prevRef.current;
35169
35655
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
35170
35656
  map.setView([centerLat, centerLng], zoom);
@@ -35175,7 +35661,7 @@ var init_MapView = __esm({
35175
35661
  }
35176
35662
  function MapClickHandler({ onMapClick }) {
35177
35663
  const map = useMap();
35178
- useEffect73(() => {
35664
+ useEffect72(() => {
35179
35665
  if (!onMapClick) return;
35180
35666
  const handler = (e) => {
35181
35667
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -35203,8 +35689,8 @@ var init_MapView = __esm({
35203
35689
  showAttribution = true
35204
35690
  }) {
35205
35691
  const eventBus = useEventBus2();
35206
- const [clickedPosition, setClickedPosition] = useState110(null);
35207
- const handleMapClick = useCallback110((lat, lng) => {
35692
+ const [clickedPosition, setClickedPosition] = useState109(null);
35693
+ const handleMapClick = useCallback109((lat, lng) => {
35208
35694
  if (showClickedPin) {
35209
35695
  setClickedPosition({ lat, lng });
35210
35696
  }
@@ -35213,7 +35699,7 @@ var init_MapView = __esm({
35213
35699
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
35214
35700
  }
35215
35701
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
35216
- const handleMarkerClick = useCallback110((marker) => {
35702
+ const handleMarkerClick = useCallback109((marker) => {
35217
35703
  onMarkerClick?.(marker);
35218
35704
  if (markerClickEvent) {
35219
35705
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -36074,7 +36560,7 @@ function TableView({
36074
36560
  columns,
36075
36561
  fields,
36076
36562
  itemActions,
36077
- maxInlineActions: _maxInlineActions,
36563
+ maxInlineActions,
36078
36564
  itemClickEvent = "",
36079
36565
  selectable = false,
36080
36566
  selectEvent,
@@ -36107,6 +36593,12 @@ function TableView({
36107
36593
  const [localSelected, setLocalSelected] = React79__default.useState(/* @__PURE__ */ new Set());
36108
36594
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
36109
36595
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
36596
+ const inlineActions = maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : [];
36597
+ const overflowActions = maxInlineActions != null ? actionDefs.slice(maxInlineActions) : actionDefs;
36598
+ const fireAction = (action, row) => eventBus.emit(`UI:${action.event}`, {
36599
+ id: row.id,
36600
+ row
36601
+ });
36110
36602
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
36111
36603
  const dnd = useDataDnd({
36112
36604
  items: allDataRaw,
@@ -36282,7 +36774,7 @@ function TableView({
36282
36774
  }
36283
36775
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
36284
36776
  }),
36285
- hasActions && /* @__PURE__ */ jsx(
36777
+ hasActions && /* @__PURE__ */ jsxs(
36286
36778
  HStack,
36287
36779
  {
36288
36780
  gap: "xs",
@@ -36296,23 +36788,38 @@ function TableView({
36296
36788
  "border-l border-[var(--color-border)]",
36297
36789
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
36298
36790
  ),
36299
- children: /* @__PURE__ */ jsx(
36300
- Menu,
36301
- {
36302
- position: "bottom-end",
36303
- trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", "data-row-id": String(row.id), children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
36304
- items: actionDefs.map((action) => ({
36305
- label: action.label,
36306
- icon: action.icon,
36307
- event: action.event,
36308
- variant: action.variant === "danger" ? "danger" : "default",
36309
- onClick: () => eventBus.emit(`UI:${action.event}`, {
36310
- id: row.id,
36311
- row
36312
- })
36313
- }))
36314
- }
36315
- )
36791
+ children: [
36792
+ inlineActions.map((action) => /* @__PURE__ */ jsxs(
36793
+ Button,
36794
+ {
36795
+ variant: action.variant ?? "ghost",
36796
+ size: "sm",
36797
+ onClick: () => fireAction(action, row),
36798
+ "data-testid": `action-${action.event}`,
36799
+ "data-row-id": String(row.id),
36800
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
36801
+ children: [
36802
+ action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
36803
+ action.label
36804
+ ]
36805
+ },
36806
+ action.event
36807
+ )),
36808
+ overflowActions.length > 0 && /* @__PURE__ */ jsx(
36809
+ Menu,
36810
+ {
36811
+ position: "bottom-end",
36812
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", "data-row-id": String(row.id), children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
36813
+ items: overflowActions.map((action) => ({
36814
+ label: action.label,
36815
+ icon: action.icon,
36816
+ event: action.event,
36817
+ variant: action.variant === "danger" ? "danger" : "default",
36818
+ onClick: () => fireAction(action, row)
36819
+ }))
36820
+ }
36821
+ )
36822
+ ]
36316
36823
  }
36317
36824
  )
36318
36825
  ]
@@ -52373,6 +52880,7 @@ var init_component_registry_generated = __esm({
52373
52880
  init_DrawMesh();
52374
52881
  init_DrawShape();
52375
52882
  init_DrawShapeLayer();
52883
+ init_DrawSkinnedMesh();
52376
52884
  init_DrawSprite();
52377
52885
  init_DrawSpriteLayer();
52378
52886
  init_DrawText();
@@ -52651,6 +53159,7 @@ var init_component_registry_generated = __esm({
52651
53159
  "DrawMesh": DrawMesh,
52652
53160
  "DrawShape": DrawShape,
52653
53161
  "DrawShapeLayer": DrawShapeLayer,
53162
+ "DrawSkinnedMesh": DrawSkinnedMesh,
52654
53163
  "DrawSprite": DrawSprite,
52655
53164
  "DrawSpriteLayer": DrawSpriteLayer,
52656
53165
  "DrawText": DrawText,
@@ -52979,7 +53488,7 @@ function renderContainedPortal(t, slot, content, onDismiss) {
52979
53488
  const slotId = `slot-${slot}`;
52980
53489
  switch (slot) {
52981
53490
  case "modal":
52982
- if (SELF_OVERLAY_PATTERNS.has(content.pattern)) {
53491
+ if (SELF_OVERLAY_PATTERN_TYPES.has(content.pattern)) {
52983
53492
  return /* @__PURE__ */ jsx(Box, { id: slotId, className: "contents", children: slotContent });
52984
53493
  }
52985
53494
  return /* @__PURE__ */ jsx(
@@ -53322,7 +53831,7 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
53322
53831
  children
53323
53832
  }
53324
53833
  );
53325
- wrapper = pattern !== void 0 && SELF_OVERLAY_PATTERNS.has(pattern) ? innerContent : /* @__PURE__ */ jsx(Modal, { isOpen: true, onClose: handleDismiss, showCloseButton: true, size: "lg", children: innerContent });
53834
+ wrapper = pattern !== void 0 && SELF_OVERLAY_PATTERN_TYPES.has(pattern) ? innerContent : /* @__PURE__ */ jsx(Modal, { isOpen: true, onClose: handleDismiss, showCloseButton: true, size: "lg", children: innerContent });
53326
53835
  break;
53327
53836
  }
53328
53837
  case "drawer":
@@ -53382,7 +53891,7 @@ function SlotPortal({
53382
53891
  let wrapper;
53383
53892
  switch (slot) {
53384
53893
  case "modal":
53385
- wrapper = SELF_OVERLAY_PATTERNS.has(content.pattern) ? /* @__PURE__ */ jsx(Box, { id: slotId, children: slotContent }) : /* @__PURE__ */ jsx(
53894
+ wrapper = SELF_OVERLAY_PATTERN_TYPES.has(content.pattern) ? /* @__PURE__ */ jsx(Box, { id: slotId, children: slotContent }) : /* @__PURE__ */ jsx(
53386
53895
  Modal,
53387
53896
  {
53388
53897
  isOpen: true,
@@ -53889,7 +54398,7 @@ function UISlotRenderer({
53889
54398
  }
53890
54399
  return wrapped;
53891
54400
  }
53892
- var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, SELF_OVERLAY_PATTERNS, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
54401
+ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
53893
54402
  var init_UISlotRenderer = __esm({
53894
54403
  "components/core/organisms/UISlotRenderer.tsx"() {
53895
54404
  "use client";
@@ -53920,7 +54429,6 @@ var init_UISlotRenderer = __esm({
53920
54429
  modal: "form",
53921
54430
  drawer: "form"
53922
54431
  };
53923
- SELF_OVERLAY_PATTERNS = /* @__PURE__ */ new Set(["modal", "confirm-dialog"]);
53924
54432
  CONTENT_NODE_SLOTS = /* @__PURE__ */ new Set([
53925
54433
  "logo",
53926
54434
  "master",
@@ -54113,66 +54621,6 @@ init_UISlotRenderer();
54113
54621
  init_ModalSlot();
54114
54622
  init_DrawerSlot();
54115
54623
  init_ToastSlot();
54116
-
54117
- // components/core/organisms/NotifyListener.tsx
54118
- init_useEventBus();
54119
- init_Toast();
54120
- init_Box();
54121
- var nextId = 0;
54122
- function NotifyListener() {
54123
- const eventBus = useEventBus();
54124
- const [items, setItems] = useState([]);
54125
- const [portalRoot, setPortalRoot] = useState(null);
54126
- useEffect(() => {
54127
- let root = document.getElementById("ui-notify-portal-root");
54128
- if (!root) {
54129
- root = document.createElement("div");
54130
- root.id = "ui-notify-portal-root";
54131
- document.body.appendChild(root);
54132
- }
54133
- setPortalRoot(root);
54134
- }, []);
54135
- const handleDismiss = useCallback((id) => {
54136
- setItems((prev) => prev.filter((item) => item.id !== id));
54137
- }, []);
54138
- useEffect(() => {
54139
- const unsubscribe = eventBus.on("UI:NOTIFY", (event) => {
54140
- const payload = event.payload;
54141
- const message = payload && typeof payload.message === "string" ? payload.message : "Notification";
54142
- const severityMap = {
54143
- success: "success",
54144
- error: "error",
54145
- warning: "warning",
54146
- info: "info"
54147
- };
54148
- const variant = payload && String(payload.severity) in severityMap ? severityMap[String(payload.severity)] : "info";
54149
- const id = ++nextId;
54150
- setItems((prev) => {
54151
- const last = prev[prev.length - 1];
54152
- if (last && last.message === message && last.variant === variant) return prev;
54153
- return [...prev, { id, message, variant }].slice(-4);
54154
- });
54155
- });
54156
- return unsubscribe;
54157
- }, [eventBus]);
54158
- if (!portalRoot || items.length === 0) return null;
54159
- return createPortal(
54160
- /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50 pointer-events-auto flex flex-col gap-2", children: items.map((item) => /* @__PURE__ */ jsx(
54161
- Toast,
54162
- {
54163
- variant: item.variant,
54164
- message: item.message,
54165
- duration: 5e3,
54166
- onDismiss: () => handleDismiss(item.id)
54167
- },
54168
- item.id
54169
- )) }),
54170
- portalRoot
54171
- );
54172
- }
54173
- NotifyListener.displayName = "NotifyListener";
54174
-
54175
- // components/core/organisms/index.ts
54176
54624
  init_Timeline();
54177
54625
  init_MediaGallery();
54178
54626
 
@@ -56513,4 +56961,4 @@ function assertUniqueSlotsPerHost(manifest) {
56513
56961
  }
56514
56962
  }
56515
56963
 
56516
- export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgoGraphCanvas, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, CommandPalette, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DockLayout, DocumentDetails, DocumentPanel, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmojiPicker, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, FloatingToolbar, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, FxOverlay, GameAudioCue, GameAudioToggle, GameHud, GameIcon, GameMenu, GameShell, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, ImportPreviewTree, ImportProgress, ImportSourcePicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, LearningScene3D, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NotifyListener, NumberStepper, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, PageTransition, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, Presence, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, RichTextEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, SharedEntityStoreContext, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateGraph, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VersionDiff, ViolationAlert, VoteStack, WizardContainer, WizardNavigation, WizardProgress, arrowBetween, assertUniqueSlotsPerHost, billboardLabel, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, cylinderBetween, dispatchCommandPaletteCommand, get3DClickPayload, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, keyChord, makeAsset, makeAssetMap, mapBookData, mergeCaptureTables, meshSphere, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, registerCodeLanguageLoader, renderPatternValue, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, sanitizeRichHtml, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useKeyboardRouter, useLongPress, useMediaQuery, useOrbitalHistory, usePresence, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate117 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
56964
+ export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgoGraphCanvas, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, CommandPalette, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DockLayout, DocumentDetails, DocumentPanel, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmojiPicker, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, FloatingToolbar, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, FxOverlay, GameAudioCue, GameAudioToggle, GameHud, GameIcon, GameMenu, GameShell, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, ImportPreviewTree, ImportProgress, ImportSourcePicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, LearningScene3D, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NumberStepper, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, PageTransition, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, Presence, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, RichTextEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, SharedEntityStoreContext, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateGraph, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VersionDiff, ViolationAlert, VoteStack, WizardContainer, WizardNavigation, WizardProgress, arrowBetween, assertUniqueSlotsPerHost, billboardLabel, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, cylinderBetween, dispatchCommandPaletteCommand, get3DClickPayload, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, keyChord, makeAsset, makeAssetMap, mapBookData, mergeCaptureTables, meshSphere, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, registerCodeLanguageLoader, renderPatternValue, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, sanitizeRichHtml, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useKeyboardRouter, useLongPress, useMediaQuery, useOrbitalHistory, usePresence, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate117 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };