@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
@@ -78,7 +78,7 @@ import { CSS } from '@dnd-kit/utilities';
78
78
  import { ordered, lib } from 'emojilib';
79
79
  import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
80
80
  import { forceSimulation, forceLink, forceManyBody, forceCollide, forceX, forceY } from 'd3-force';
81
- import { isDrawHostPattern, getPatternDefinition, getPatternFieldsContract, getComponentForPattern as getComponentForPattern$1 } from '@almadar/core/patterns';
81
+ import { SELF_OVERLAY_PATTERN_TYPES, isDrawHostPattern, getPatternDefinition, getPatternFieldsContract, getComponentForPattern as getComponentForPattern$1 } from '@almadar/core/patterns';
82
82
 
83
83
  var __defProp = Object.defineProperty;
84
84
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -7782,7 +7782,7 @@ var init_DialogueBubble = __esm({
7782
7782
  init_Typography();
7783
7783
  init_GameIcon();
7784
7784
  DEFAULT_PORTRAIT = {
7785
- url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
7785
+ url: "https://almadar-kflow-assets.web.app/shared/ui-winter-ski-board/default/units/hero/hero.png",
7786
7786
  role: "effect",
7787
7787
  category: "character"
7788
7788
  };
@@ -9106,6 +9106,14 @@ function createWebPainter(ctx, onAssetLoad) {
9106
9106
  ctx.drawImage(img, dest.x, dest.y, dw, dh);
9107
9107
  }
9108
9108
  },
9109
+ blitTransformed(tex, src, affine) {
9110
+ const img = imageByHandle.get(tex);
9111
+ if (!img) return;
9112
+ ctx.save();
9113
+ ctx.transform(affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]);
9114
+ ctx.drawImage(img, src.x, src.y, src.w, src.h, src.x, src.y, src.w, src.h);
9115
+ ctx.restore();
9116
+ },
9109
9117
  fillRect(x, y, w, h, style) {
9110
9118
  ctx.fillStyle = toCanvasStyle(style);
9111
9119
  ctx.fillRect(x, y, w, h);
@@ -9612,6 +9620,271 @@ var init_DrawGroup = __esm({
9612
9620
  init_registry();
9613
9621
  }
9614
9622
  });
9623
+
9624
+ // lib/skinning.ts
9625
+ function composeAffine(a, b) {
9626
+ return [
9627
+ a[0] * b[0] + a[2] * b[1],
9628
+ a[1] * b[0] + a[3] * b[1],
9629
+ a[0] * b[2] + a[2] * b[3],
9630
+ a[1] * b[2] + a[3] * b[3],
9631
+ a[0] * b[4] + a[2] * b[5] + a[4],
9632
+ a[1] * b[4] + a[3] * b[5] + a[5]
9633
+ ];
9634
+ }
9635
+ function invertAffine(m) {
9636
+ const det = m[0] * m[3] - m[1] * m[2];
9637
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return IDENTITY;
9638
+ const inv = 1 / det;
9639
+ return [
9640
+ m[3] * inv,
9641
+ -m[1] * inv,
9642
+ -m[2] * inv,
9643
+ m[0] * inv,
9644
+ (m[2] * m[5] - m[3] * m[4]) * inv,
9645
+ (m[1] * m[4] - m[0] * m[5]) * inv
9646
+ ];
9647
+ }
9648
+ function applyAffine(m, x, y) {
9649
+ return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
9650
+ }
9651
+ function rotationAbout(pivot, degrees) {
9652
+ const r = degrees * Math.PI / 180;
9653
+ const cos = Math.cos(r);
9654
+ const sin = Math.sin(r);
9655
+ const [px, py] = pivot;
9656
+ return [cos, sin, -sin, cos, px - cos * px + sin * py, py - sin * px - cos * py];
9657
+ }
9658
+ function computeWorldMatrices(bones, pose) {
9659
+ const indexByName = /* @__PURE__ */ new Map();
9660
+ bones.forEach((b, i) => indexByName.set(b.name, i));
9661
+ const world = new Array(bones.length);
9662
+ const visiting = /* @__PURE__ */ new Set();
9663
+ const resolve = (i) => {
9664
+ const cached = world[i];
9665
+ if (cached) return cached;
9666
+ if (visiting.has(i)) return IDENTITY;
9667
+ visiting.add(i);
9668
+ const b = bones[i];
9669
+ const parentIndex = b.parent === null ? void 0 : indexByName.get(b.parent);
9670
+ const parentWorld = parentIndex === void 0 ? IDENTITY : resolve(parentIndex);
9671
+ const local = rotationAbout(b.pivot, pose[b.name] ?? 0);
9672
+ const m = composeAffine(parentWorld, local);
9673
+ visiting.delete(i);
9674
+ world[i] = m;
9675
+ return m;
9676
+ };
9677
+ return bones.map((_, i) => resolve(i));
9678
+ }
9679
+ function skinVertices(mesh, bindWorld, curWorld) {
9680
+ const skinMats = /* @__PURE__ */ new Map();
9681
+ const skinMat = (bone) => {
9682
+ let m = skinMats.get(bone);
9683
+ if (!m) {
9684
+ m = composeAffine(curWorld[bone] ?? IDENTITY, invertAffine(bindWorld[bone] ?? IDENTITY));
9685
+ skinMats.set(bone, m);
9686
+ }
9687
+ return m;
9688
+ };
9689
+ return mesh.vertices.map((v) => {
9690
+ if (v.weights.length === 0) return [v.x, v.y];
9691
+ let x = 0;
9692
+ let y = 0;
9693
+ for (const { bone, w } of v.weights) {
9694
+ const [bx, by] = applyAffine(skinMat(bone), v.x, v.y);
9695
+ x += w * bx;
9696
+ y += w * by;
9697
+ }
9698
+ return [x, y];
9699
+ });
9700
+ }
9701
+ function triangleAffine(src, dst) {
9702
+ const [s0, s1, s2] = src;
9703
+ const det = s0[0] * (s1[1] - s2[1]) + s1[0] * (s2[1] - s0[1]) + s2[0] * (s0[1] - s1[1]);
9704
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return null;
9705
+ const [d0, d1, d2] = dst;
9706
+ const a = (d0[0] * (s1[1] - s2[1]) + d1[0] * (s2[1] - s0[1]) + d2[0] * (s0[1] - s1[1])) / det;
9707
+ const c = (d0[0] * (s2[0] - s1[0]) + d1[0] * (s0[0] - s2[0]) + d2[0] * (s1[0] - s0[0])) / det;
9708
+ 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;
9709
+ const b = (d0[1] * (s1[1] - s2[1]) + d1[1] * (s2[1] - s0[1]) + d2[1] * (s0[1] - s1[1])) / det;
9710
+ const d = (d0[1] * (s2[0] - s1[0]) + d1[1] * (s0[0] - s2[0]) + d2[1] * (s1[0] - s0[0])) / det;
9711
+ 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;
9712
+ return [a, b, c, d, e, f3];
9713
+ }
9714
+ function isRigBundle(json) {
9715
+ return json.mesh !== void 0 || json.bones !== void 0;
9716
+ }
9717
+ function getRigBundle(url, onReady) {
9718
+ if (meshCache.has(url)) return meshCache.get(url) ?? void 0;
9719
+ meshCache.set(url, void 0);
9720
+ fetch(url).then((r) => {
9721
+ if (!r.ok) throw new Error(`rigbundle fetch failed: HTTP ${r.status}`);
9722
+ return r.json();
9723
+ }).then((json) => {
9724
+ const ok = isRigBundle(json) || Array.isArray(json.vertices);
9725
+ if (!ok) throw new Error("rigbundle payload is neither a SkinMesh nor a rigbundle");
9726
+ meshCache.set(url, json);
9727
+ onReady();
9728
+ }).catch(() => {
9729
+ meshCache.set(url, null);
9730
+ onReady();
9731
+ });
9732
+ return void 0;
9733
+ }
9734
+ function skinMeshFailed(url) {
9735
+ return meshCache.get(url) === null;
9736
+ }
9737
+ function vertexBounds(points) {
9738
+ if (points.length === 0) return null;
9739
+ let minX = Infinity;
9740
+ let minY = Infinity;
9741
+ let maxX = -Infinity;
9742
+ let maxY = -Infinity;
9743
+ for (const [x, y] of points) {
9744
+ if (x < minX) minX = x;
9745
+ if (y < minY) minY = y;
9746
+ if (x > maxX) maxX = x;
9747
+ if (y > maxY) maxY = y;
9748
+ }
9749
+ return { minX, minY, maxX, maxY };
9750
+ }
9751
+ var IDENTITY, meshCache;
9752
+ var init_skinning = __esm({
9753
+ "lib/skinning.ts"() {
9754
+ IDENTITY = [1, 0, 0, 1, 0, 0];
9755
+ meshCache = /* @__PURE__ */ new Map();
9756
+ }
9757
+ });
9758
+ function warnMissingOnce2(reason, node) {
9759
+ const key = `${reason}:${node.asset.url}:${String(node.meshUrl)}`;
9760
+ if (loggedMissing2.has(key)) return;
9761
+ loggedMissing2.add(key);
9762
+ skinnedLog.warn("draw-skinned-mesh unresolvable \u2014 painting fallback", { reason, url: node.asset.url, meshUrl: node.meshUrl });
9763
+ }
9764
+ function dominantBone(v) {
9765
+ let best = -1;
9766
+ let bestW = 0;
9767
+ for (const { bone, w } of v.weights) {
9768
+ if (w > bestW) {
9769
+ bestW = w;
9770
+ best = bone;
9771
+ }
9772
+ }
9773
+ return best;
9774
+ }
9775
+ function resolveSkinPose(node, clip) {
9776
+ const effectiveClip = clip ?? node.clip;
9777
+ if (effectiveClip && node.frame !== void 0 && effectiveClip.frames.length > 0) {
9778
+ return effectiveClip.frames[node.frame % effectiveClip.frames.length];
9779
+ }
9780
+ return node.pose ?? {};
9781
+ }
9782
+ function resolveRig(node, dctx) {
9783
+ const fetched = node.meshUrl ? getRigBundle(node.meshUrl, dctx.invalidate) : void 0;
9784
+ if (node.meshUrl && fetched === void 0) return void 0;
9785
+ const rb = fetched && isRigBundle(fetched) ? fetched : void 0;
9786
+ const mesh = node.mesh ?? rb?.mesh ?? (!rb ? fetched : void 0);
9787
+ if (!mesh) return void 0;
9788
+ const bones = node.bones.length > 0 ? node.bones : rb?.bones ?? [];
9789
+ if (bones.length === 0) return void 0;
9790
+ const clip = node.clip ?? (node.clipName ? rb?.clips?.[node.clipName] : void 0);
9791
+ return { mesh, bones, clip };
9792
+ }
9793
+ function meshHasPixelUVs(mesh) {
9794
+ const cached = pixelUVByMesh.get(mesh);
9795
+ if (cached !== void 0) return cached;
9796
+ let pixel = false;
9797
+ for (const v of mesh.vertices) {
9798
+ if (v.u < 0 || v.u > 1 || v.v < 0 || v.v > 1) {
9799
+ pixel = true;
9800
+ break;
9801
+ }
9802
+ }
9803
+ pixelUVByMesh.set(mesh, pixel);
9804
+ return pixel;
9805
+ }
9806
+ function paintMeshPass(painter, node, bones, mesh, tex, dctx, pose, opacity) {
9807
+ const bindWorld = computeWorldMatrices(bones, {});
9808
+ const curWorld = computeWorldMatrices(bones, pose);
9809
+ const skinned = skinVertices(mesh, bindWorld, curWorld);
9810
+ const origin = dctx.projector.project(node.position);
9811
+ const tw = dctx.projector.tileWidth;
9812
+ painter.save();
9813
+ if (opacity !== 1) painter.setAlpha(opacity);
9814
+ for (const [i0, i1, i2] of mesh.triangles) {
9815
+ const v0 = mesh.vertices[i0];
9816
+ const v1 = mesh.vertices[i1];
9817
+ const v2 = mesh.vertices[i2];
9818
+ const p0 = skinned[i0];
9819
+ const p1 = skinned[i1];
9820
+ const p2 = skinned[i2];
9821
+ if (!v0 || !v1 || !v2 || !p0 || !p1 || !p2) continue;
9822
+ const dst = [
9823
+ [origin.x + p0[0] * tw, origin.y + p0[1] * tw],
9824
+ [origin.x + p1[0] * tw, origin.y + p1[1] * tw],
9825
+ [origin.x + p2[0] * tw, origin.y + p2[1] * tw]
9826
+ ];
9827
+ if (node.weightsOverlay || !tex) {
9828
+ if (!node.weightsOverlay) continue;
9829
+ const bone = dominantBone(v0);
9830
+ painter.fillPoly(
9831
+ dst.map(([x, y]) => ({ x, y })),
9832
+ WEIGHT_PALETTE[(bone % WEIGHT_PALETTE.length + WEIGHT_PALETTE.length) % WEIGHT_PALETTE.length]
9833
+ );
9834
+ continue;
9835
+ }
9836
+ const pixelUV = meshHasPixelUVs(mesh);
9837
+ const uv = pixelUV ? [[v0.u, v0.v], [v1.u, v1.v], [v2.u, v2.v]] : [
9838
+ [v0.u * tex.width, v0.v * tex.height],
9839
+ [v1.u * tex.width, v1.v * tex.height],
9840
+ [v2.u * tex.width, v2.v * tex.height]
9841
+ ];
9842
+ const affine = triangleAffine(uv, dst);
9843
+ if (!affine) continue;
9844
+ painter.save();
9845
+ painter.clipPath(`M ${dst[0][0]} ${dst[0][1]} L ${dst[1][0]} ${dst[1][1]} L ${dst[2][0]} ${dst[2][1]} Z`);
9846
+ painter.blitTransformed(tex, { x: 0, y: 0, w: tex.width, h: tex.height }, affine);
9847
+ painter.restore();
9848
+ }
9849
+ painter.restore();
9850
+ }
9851
+ function DrawSkinnedMesh(props) {
9852
+ const register = useContext(DrawableRegistryContext);
9853
+ if (register) register({ ...props, type: "draw-skinned-mesh" });
9854
+ return null;
9855
+ }
9856
+ var skinnedLog, loggedMissing2, WEIGHT_PALETTE, pixelUVByMesh, paintSkinnedMesh;
9857
+ var init_DrawSkinnedMesh = __esm({
9858
+ "components/game/atoms/DrawSkinnedMesh.tsx"() {
9859
+ "use client";
9860
+ init_imageCache();
9861
+ init_contract();
9862
+ init_registry();
9863
+ init_skinning();
9864
+ skinnedLog = createLogger("almadar:ui:draw-skinned-mesh");
9865
+ loggedMissing2 = /* @__PURE__ */ new Set();
9866
+ WEIGHT_PALETTE = Array.from({ length: 10 }, (_, i) => `hsl(${i * 36 % 360}, 70%, 55%)`);
9867
+ pixelUVByMesh = /* @__PURE__ */ new WeakMap();
9868
+ paintSkinnedMesh = (painter, node, dctx) => {
9869
+ if (!isValidScenePos(node.position)) return;
9870
+ const rig = resolveRig(node, dctx);
9871
+ if (!rig) {
9872
+ if (node.meshUrl && skinMeshFailed(node.meshUrl)) warnMissingOnce2("mesh-failed", node);
9873
+ else if (!node.mesh && !node.meshUrl) warnMissingOnce2("mesh-missing", node);
9874
+ return;
9875
+ }
9876
+ const tex = node.weightsOverlay ? null : painter.resolveTexture(node.asset.url);
9877
+ if (!node.weightsOverlay && !tex) {
9878
+ if (getImageStatus(node.asset.url) === "failed") warnMissingOnce2("texture-failed", node);
9879
+ return;
9880
+ }
9881
+ if (node.ghost && rig.clip && rig.clip.frames.length > 0) {
9882
+ paintMeshPass(painter, node, rig.bones, rig.mesh, tex, dctx, rig.clip.frames[node.ghost.frame % rig.clip.frames.length], node.ghost.opacity);
9883
+ }
9884
+ paintMeshPass(painter, node, rig.bones, rig.mesh, tex, dctx, resolveSkinPose(node, rig.clip), node.opacity ?? 1);
9885
+ };
9886
+ }
9887
+ });
9615
9888
  function applyMeshAnimation(node, timeMs) {
9616
9889
  const anim = node.animation;
9617
9890
  if (!anim || !(anim.durationMs > 0) || anim.keyframes.length === 0) return null;
@@ -9936,6 +10209,9 @@ function paintDrawable(painter, node, dctx) {
9936
10209
  case "draw-mesh":
9937
10210
  warnUnsupported2d("draw-mesh");
9938
10211
  break;
10212
+ case "draw-skinned-mesh":
10213
+ paintSkinnedMesh(painter, node, dctx);
10214
+ break;
9939
10215
  case "draw-sprite-layer":
9940
10216
  paintSpriteLayer(painter, node, dctx);
9941
10217
  break;
@@ -9960,6 +10236,7 @@ var init_paintDispatch = __esm({
9960
10236
  init_DrawShape();
9961
10237
  init_DrawText();
9962
10238
  init_DrawGroup();
10239
+ init_DrawSkinnedMesh();
9963
10240
  init_DrawMesh();
9964
10241
  init_DrawSpriteLayer();
9965
10242
  init_DrawShapeLayer();
@@ -9980,6 +10257,21 @@ function shapeDrawnItem(n) {
9980
10257
  if (n.shape !== "rect") return { pos: n.position, id: n.id };
9981
10258
  return { pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height, rotation: n.rotate };
9982
10259
  }
10260
+ function skinnedMeshDrawnItem(n) {
10261
+ const mesh = n.mesh;
10262
+ if (!mesh || n.bones.length === 0) return { pos: n.position, id: n.id };
10263
+ const bindWorld = computeWorldMatrices(n.bones, {});
10264
+ const curWorld = computeWorldMatrices(n.bones, resolveSkinPose(n));
10265
+ const bounds = vertexBounds(skinVertices(mesh, bindWorld, curWorld));
10266
+ if (!bounds) return { pos: n.position, id: n.id };
10267
+ return {
10268
+ pos: { ...n.position, x: n.position.x + bounds.minX, y: n.position.y + bounds.minY },
10269
+ id: n.id,
10270
+ anchor: "top-left",
10271
+ width: bounds.maxX - bounds.minX,
10272
+ height: bounds.maxY - bounds.minY
10273
+ };
10274
+ }
9983
10275
  function collectDrawnItems(nodes) {
9984
10276
  const out = [];
9985
10277
  for (const n of nodes) {
@@ -9990,6 +10282,9 @@ function collectDrawnItems(nodes) {
9990
10282
  case "draw-shape":
9991
10283
  if (isValidScenePos(n.position)) out.push(shapeDrawnItem(n));
9992
10284
  break;
10285
+ case "draw-skinned-mesh":
10286
+ if (isValidScenePos(n.position)) out.push(skinnedMeshDrawnItem(n));
10287
+ break;
9993
10288
  case "draw-text":
9994
10289
  case "draw-group":
9995
10290
  case "draw-mesh":
@@ -10057,6 +10352,8 @@ function rotatePoint(p, center, radians) {
10057
10352
  var init_hitTest = __esm({
10058
10353
  "lib/drawable/hitTest.ts"() {
10059
10354
  init_contract();
10355
+ init_DrawSkinnedMesh();
10356
+ init_skinning();
10060
10357
  }
10061
10358
  });
10062
10359
  function normalizeBackdrop(bg) {
@@ -11246,7 +11543,7 @@ var init_StateIndicator = __esm({
11246
11543
  init_cn();
11247
11544
  init_GameIcon();
11248
11545
  DEFAULT_ASSET_URL = {
11249
- url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
11546
+ url: "https://almadar-kflow-assets.web.app/shared/ui-topdown-dungeon-board/default/features/chest/chest.png",
11250
11547
  role: "ui",
11251
11548
  category: "state"
11252
11549
  };
@@ -12862,11 +13159,6 @@ function executeEffect(effect, config) {
12862
13159
  executeNavigate(path, params, config);
12863
13160
  break;
12864
13161
  }
12865
- case "notify": {
12866
- const [message, options] = args;
12867
- executeNotify(message, options, config);
12868
- break;
12869
- }
12870
13162
  case "emit": {
12871
13163
  const [event, payload] = args;
12872
13164
  executeEmit(event, payload, config);
@@ -12882,9 +13174,6 @@ function executeRenderUI(slot, patternConfig, config) {
12882
13174
  function executeNavigate(path, params, config) {
12883
13175
  config.navigate(path, params);
12884
13176
  }
12885
- function executeNotify(message, options, config) {
12886
- config.notify(message, options);
12887
- }
12888
13177
  function executeEmit(event, payload, config) {
12889
13178
  config.eventBus.emit(event, payload);
12890
13179
  }
@@ -13172,7 +13461,6 @@ var init_offline_executor = __esm({
13172
13461
  // Client effects - execute immediately
13173
13462
  case "render-ui":
13174
13463
  case "navigate":
13175
- case "notify":
13176
13464
  case "emit":
13177
13465
  clientEffects.push(effect);
13178
13466
  break;
@@ -15600,7 +15888,6 @@ var init_avl_atom_types = __esm({
15600
15888
  "persist": "data",
15601
15889
  "fetch": "data",
15602
15890
  "emit": "communication",
15603
- "notify": "communication",
15604
15891
  "call-service": "communication",
15605
15892
  "spawn": "lifecycle",
15606
15893
  "despawn": "lifecycle",
@@ -15748,12 +16035,6 @@ function effectIcon(type, x, y, s, color) {
15748
16035
  /* @__PURE__ */ jsx("line", { x1: x - s, y1: y, x2: x + s * 0.6, y2: y, stroke: color, strokeWidth: 1.5 }),
15749
16036
  /* @__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" })
15750
16037
  ] });
15751
- case "notify":
15752
- return /* @__PURE__ */ jsxs("g", { children: [
15753
- /* @__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 }),
15754
- /* @__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 }),
15755
- /* @__PURE__ */ jsx("circle", { cx: x, cy: y + s * 0.7, r: s * 0.2, fill: color })
15756
- ] });
15757
16038
  case "call-service":
15758
16039
  return /* @__PURE__ */ jsxs("g", { children: [
15759
16040
  /* @__PURE__ */ jsx("line", { x1: x - s, y1: y - s * 0.3, x2: x + s, y2: y - s * 0.3, stroke: color, strokeWidth: 1.5 }),
@@ -21007,9 +21288,6 @@ function getEffectSummary(effects) {
21007
21288
  case "emit":
21008
21289
  summaries.push(`\u2191 ${effect[1] || "event"}`);
21009
21290
  break;
21010
- case "notify":
21011
- summaries.push(`\u{1F4E7} ${effect[1] || ""}`);
21012
- break;
21013
21291
  case "persist":
21014
21292
  summaries.push(`\u{1F4BE} ${effect[1] || "save"}`);
21015
21293
  break;
@@ -21035,7 +21313,7 @@ function extractOutputsFromTransitions(transitions) {
21035
21313
  t.effects.forEach((effect) => {
21036
21314
  if (Array.isArray(effect)) {
21037
21315
  const op = effect[0];
21038
- if (["emit", "notify", "persist", "navigate", "call-service"].includes(op)) {
21316
+ if (["emit", "persist", "navigate", "call-service"].includes(op)) {
21039
21317
  if (isArraySExpr(effect)) {
21040
21318
  const humanText = formatSExprEffectToDomain(effect);
21041
21319
  outputs.add(humanText);
@@ -26419,6 +26697,18 @@ var init_useAuthContext = __esm({
26419
26697
  "hooks/useAuthContext.ts"() {
26420
26698
  }
26421
26699
  });
26700
+ function resolveActiveNavHref(items, currentPath) {
26701
+ let best;
26702
+ for (const item of items) {
26703
+ for (const href of item.children?.length ? [item.href, ...item.children.map((c) => c.href)] : [item.href]) {
26704
+ if (currentPath === href) return href;
26705
+ if (currentPath.startsWith(href + "/") && (!best || href.length > best.length)) {
26706
+ best = href;
26707
+ }
26708
+ }
26709
+ }
26710
+ return best;
26711
+ }
26422
26712
  var DashboardLayout, NavLink, NavLinkTopnav, NavLinkBottom;
26423
26713
  var init_DashboardLayout = __esm({
26424
26714
  "components/core/templates/DashboardLayout.tsx"() {
@@ -26490,6 +26780,7 @@ var init_DashboardLayout = __esm({
26490
26780
  const location = useLocation();
26491
26781
  const ctxPagePath = useCurrentPagePath();
26492
26782
  const activePath = (currentPath || void 0) ?? ctxPagePath ?? location.pathname;
26783
+ const activeHref = useMemo(() => resolveActiveNavHref(navItems, activePath), [navItems, activePath]);
26493
26784
  const { signOut: authSignOut } = useAuthContext();
26494
26785
  const user = userProp || (null);
26495
26786
  const { t } = useTranslate();
@@ -26582,7 +26873,7 @@ var init_DashboardLayout = __esm({
26582
26873
  NavLink,
26583
26874
  {
26584
26875
  item,
26585
- currentPath: activePath,
26876
+ activeHref,
26586
26877
  compact: isRail
26587
26878
  },
26588
26879
  item.href
@@ -26649,7 +26940,7 @@ var init_DashboardLayout = __esm({
26649
26940
  NavLinkTopnav,
26650
26941
  {
26651
26942
  item,
26652
- currentPath: activePath
26943
+ activeHref
26653
26944
  },
26654
26945
  item.href
26655
26946
  ))
@@ -26825,7 +27116,7 @@ var init_DashboardLayout = __esm({
26825
27116
  NavLinkBottom,
26826
27117
  {
26827
27118
  item,
26828
- currentPath: activePath
27119
+ activeHref
26829
27120
  },
26830
27121
  item.href
26831
27122
  )) })
@@ -26839,15 +27130,71 @@ var init_DashboardLayout = __esm({
26839
27130
  DashboardLayout.displayName = "DashboardLayout";
26840
27131
  NavLink = ({
26841
27132
  item,
26842
- currentPath,
27133
+ activeHref,
26843
27134
  compact = false
26844
27135
  }) => {
26845
- const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
27136
+ const hasChildren = !!item.children?.length;
27137
+ const childActive = hasChildren && item.children.some((child) => child.href === activeHref);
27138
+ const isActive = item.href === activeHref || childActive;
27139
+ const [open, setOpen] = useState(childActive);
26846
27140
  const iconClassName = cn(
26847
27141
  "h-5 w-5",
26848
27142
  isActive ? "text-primary-foreground" : "text-muted-foreground"
26849
27143
  );
26850
27144
  if (compact) {
27145
+ if (hasChildren) {
27146
+ return /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
27147
+ /* @__PURE__ */ jsx(
27148
+ Button,
27149
+ {
27150
+ variant: "ghost",
27151
+ title: item.label,
27152
+ "aria-label": item.label,
27153
+ "aria-expanded": open,
27154
+ className: cn(
27155
+ "flex items-center justify-center w-full px-2 py-2 rounded-lg transition-colors",
27156
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
27157
+ ),
27158
+ onClick: () => setOpen(!open),
27159
+ children: /* @__PURE__ */ jsxs(Box, { as: "span", className: "relative inline-flex", children: [
27160
+ 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() }),
27161
+ item.badge && /* @__PURE__ */ jsx(
27162
+ Badge,
27163
+ {
27164
+ variant: isActive ? "primary" : "default",
27165
+ size: "sm",
27166
+ className: "absolute -top-2 -right-2 px-1 py-0 text-[10px] leading-4",
27167
+ children: item.badge
27168
+ }
27169
+ )
27170
+ ] })
27171
+ }
27172
+ ),
27173
+ open && /* @__PURE__ */ jsxs(Fragment, { children: [
27174
+ /* @__PURE__ */ jsx(Box, { className: "fixed inset-0 z-20", onClick: () => setOpen(false) }),
27175
+ /* @__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) => {
27176
+ const childIsActive = child.href === activeHref;
27177
+ return /* @__PURE__ */ jsxs(
27178
+ Link,
27179
+ {
27180
+ to: child.href,
27181
+ onClick: () => setOpen(false),
27182
+ className: cn(
27183
+ "flex items-center gap-2 px-3 py-2 text-sm transition-colors",
27184
+ childIsActive ? "bg-muted text-foreground font-medium" : "text-muted-foreground hover:bg-muted hover:text-foreground"
27185
+ ),
27186
+ children: [
27187
+ 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" })),
27188
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: "flex-1", as: "span", children: child.label }),
27189
+ child.badge && /* @__PURE__ */ jsx(Badge, { variant: childIsActive ? "primary" : "default", size: "sm", children: child.badge })
27190
+ ]
27191
+ },
27192
+ child.href
27193
+ );
27194
+ }) })
27195
+ ] })
27196
+ ] });
27197
+ }
26851
27198
  return /* @__PURE__ */ jsx(
26852
27199
  Link,
26853
27200
  {
@@ -26873,6 +27220,78 @@ var init_DashboardLayout = __esm({
26873
27220
  }
26874
27221
  );
26875
27222
  }
27223
+ if (hasChildren) {
27224
+ return /* @__PURE__ */ jsxs(Box, { children: [
27225
+ /* @__PURE__ */ jsxs(
27226
+ Button,
27227
+ {
27228
+ variant: "ghost",
27229
+ "aria-expanded": open,
27230
+ className: cn(
27231
+ "flex items-center gap-3 w-full px-3 py-2 rounded-lg text-sm font-medium transition-colors",
27232
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
27233
+ ),
27234
+ onClick: () => setOpen(!open),
27235
+ children: [
27236
+ item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, className: iconClassName }) : /* @__PURE__ */ jsx(item.icon, { className: iconClassName })),
27237
+ /* @__PURE__ */ jsx(
27238
+ Typography,
27239
+ {
27240
+ variant: "small",
27241
+ color: isActive ? "inherit" : "primary",
27242
+ className: "flex-1 text-left",
27243
+ as: "span",
27244
+ children: item.label
27245
+ }
27246
+ ),
27247
+ item.badge && /* @__PURE__ */ jsx(Badge, { variant: isActive ? "primary" : "default", size: "sm", children: item.badge }),
27248
+ /* @__PURE__ */ jsx(
27249
+ Icon,
27250
+ {
27251
+ name: "chevron-down",
27252
+ className: cn("h-4 w-4 shrink-0 transition-transform", open && "rotate-180")
27253
+ }
27254
+ )
27255
+ ]
27256
+ }
27257
+ ),
27258
+ open && /* @__PURE__ */ jsx(
27259
+ VStack,
27260
+ {
27261
+ gap: "none",
27262
+ className: "mt-1 ml-4 pl-4 border-l border-border dark:border-border space-y-1",
27263
+ children: item.children.map((child) => {
27264
+ const childIsActive = child.href === activeHref;
27265
+ return /* @__PURE__ */ jsxs(
27266
+ Link,
27267
+ {
27268
+ to: child.href,
27269
+ className: cn(
27270
+ "flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm transition-colors",
27271
+ childIsActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
27272
+ ),
27273
+ children: [
27274
+ 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" })),
27275
+ /* @__PURE__ */ jsx(
27276
+ Typography,
27277
+ {
27278
+ variant: "small",
27279
+ color: childIsActive ? "inherit" : "primary",
27280
+ className: "flex-1",
27281
+ as: "span",
27282
+ children: child.label
27283
+ }
27284
+ ),
27285
+ child.badge && /* @__PURE__ */ jsx(Badge, { variant: childIsActive ? "primary" : "default", size: "sm", children: child.badge })
27286
+ ]
27287
+ },
27288
+ child.href
27289
+ );
27290
+ })
27291
+ }
27292
+ )
27293
+ ] });
27294
+ }
26876
27295
  return /* @__PURE__ */ jsxs(
26877
27296
  Link,
26878
27297
  {
@@ -26901,9 +27320,63 @@ var init_DashboardLayout = __esm({
26901
27320
  NavLink.displayName = "NavLink";
26902
27321
  NavLinkTopnav = ({
26903
27322
  item,
26904
- currentPath
27323
+ activeHref
26905
27324
  }) => {
26906
- const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
27325
+ const hasChildren = !!item.children?.length;
27326
+ const childActive = hasChildren && item.children.some((child) => child.href === activeHref);
27327
+ const isActive = item.href === activeHref || childActive;
27328
+ const [open, setOpen] = useState(false);
27329
+ if (hasChildren) {
27330
+ return /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
27331
+ /* @__PURE__ */ jsxs(
27332
+ Button,
27333
+ {
27334
+ variant: "ghost",
27335
+ "aria-expanded": open,
27336
+ className: cn(
27337
+ "flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors whitespace-nowrap",
27338
+ isActive ? "bg-primary text-primary-foreground shadow-sm" : "text-muted-foreground hover:bg-muted hover:text-foreground"
27339
+ ),
27340
+ onClick: () => setOpen(!open),
27341
+ children: [
27342
+ 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" })),
27343
+ /* @__PURE__ */ jsx(Typography, { variant: "small", color: "inherit", className: "flex-1", as: "span", children: item.label }),
27344
+ item.badge && /* @__PURE__ */ jsx(Badge, { variant: isActive ? "primary" : "default", size: "sm", children: item.badge }),
27345
+ /* @__PURE__ */ jsx(
27346
+ Icon,
27347
+ {
27348
+ name: "chevron-down",
27349
+ className: cn("h-3.5 w-3.5 shrink-0 transition-transform", open && "rotate-180")
27350
+ }
27351
+ )
27352
+ ]
27353
+ }
27354
+ ),
27355
+ open && /* @__PURE__ */ jsxs(Fragment, { children: [
27356
+ /* @__PURE__ */ jsx(Box, { className: "fixed inset-0 z-20", onClick: () => setOpen(false) }),
27357
+ /* @__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) => {
27358
+ const childIsActive = child.href === activeHref;
27359
+ return /* @__PURE__ */ jsxs(
27360
+ Link,
27361
+ {
27362
+ to: child.href,
27363
+ onClick: () => setOpen(false),
27364
+ className: cn(
27365
+ "flex items-center gap-2 px-3 py-2 text-sm transition-colors",
27366
+ childIsActive ? "bg-muted text-foreground font-medium" : "text-muted-foreground hover:bg-muted hover:text-foreground"
27367
+ ),
27368
+ children: [
27369
+ 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" })),
27370
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: "flex-1", as: "span", children: child.label }),
27371
+ child.badge && /* @__PURE__ */ jsx(Badge, { variant: childIsActive ? "primary" : "default", size: "sm", children: child.badge })
27372
+ ]
27373
+ },
27374
+ child.href
27375
+ );
27376
+ }) })
27377
+ ] })
27378
+ ] });
27379
+ }
26907
27380
  return /* @__PURE__ */ jsxs(
26908
27381
  Link,
26909
27382
  {
@@ -26923,9 +27396,9 @@ var init_DashboardLayout = __esm({
26923
27396
  NavLinkTopnav.displayName = "NavLinkTopnav";
26924
27397
  NavLinkBottom = ({
26925
27398
  item,
26926
- currentPath
27399
+ activeHref
26927
27400
  }) => {
26928
- const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
27401
+ const isActive = item.href === activeHref;
26929
27402
  const iconClassName = cn(
26930
27403
  "h-5 w-5",
26931
27404
  isActive ? "text-primary" : "text-muted-foreground"
@@ -27864,7 +28337,9 @@ function DataGrid({
27864
28337
  const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
27865
28338
  const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
27866
28339
  const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
27867
- const hasRenderProp = typeof children === "function";
28340
+ const renderItemFn = typeof schemaRenderItem === "function" ? schemaRenderItem : void 0;
28341
+ const itemRenderer = typeof children === "function" ? children : renderItemFn;
28342
+ const hasRenderProp = typeof itemRenderer === "function";
27868
28343
  useEffect(() => {
27869
28344
  if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
27870
28345
  const schemaArr = Array.isArray(schemaRenderItem) ? schemaRenderItem : null;
@@ -27938,7 +28413,7 @@ function DataGrid({
27938
28413
  onClick: handleCardClick?.(itemData),
27939
28414
  className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
27940
28415
  children: [
27941
- children(itemData, index),
28416
+ itemRenderer(itemData, index),
27942
28417
  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: [
27943
28418
  inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxs(
27944
28419
  Button,
@@ -28271,7 +28746,9 @@ function DataList({
28271
28746
  );
28272
28747
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
28273
28748
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
28274
- const hasRenderProp = typeof children === "function";
28749
+ const renderItemFn = typeof schemaRenderItem === "function" ? schemaRenderItem : void 0;
28750
+ const itemRenderer = typeof children === "function" ? children : renderItemFn;
28751
+ const hasRenderProp = typeof itemRenderer === "function";
28275
28752
  React89__default.useEffect(() => {
28276
28753
  const renderItemTypeOf = typeof schemaRenderItem;
28277
28754
  const childrenTypeOf = typeof children;
@@ -28489,7 +28966,7 @@ function DataList({
28489
28966
  const actions = renderItemActions(itemData);
28490
28967
  return wrapDnd(
28491
28968
  /* @__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: [
28492
- children(itemData, index),
28969
+ itemRenderer(itemData, index),
28493
28970
  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: [
28494
28971
  /* @__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 }),
28495
28972
  /* @__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(
@@ -35033,7 +35510,7 @@ function TableView({
35033
35510
  columns,
35034
35511
  fields,
35035
35512
  itemActions,
35036
- maxInlineActions: _maxInlineActions,
35513
+ maxInlineActions,
35037
35514
  itemClickEvent = "",
35038
35515
  selectable = false,
35039
35516
  selectEvent,
@@ -35066,6 +35543,12 @@ function TableView({
35066
35543
  const [localSelected, setLocalSelected] = React89__default.useState(/* @__PURE__ */ new Set());
35067
35544
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
35068
35545
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
35546
+ const inlineActions = maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : [];
35547
+ const overflowActions = maxInlineActions != null ? actionDefs.slice(maxInlineActions) : actionDefs;
35548
+ const fireAction = (action, row) => eventBus.emit(`UI:${action.event}`, {
35549
+ id: row.id,
35550
+ row
35551
+ });
35069
35552
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
35070
35553
  const dnd = useDataDnd({
35071
35554
  items: allDataRaw,
@@ -35241,7 +35724,7 @@ function TableView({
35241
35724
  }
35242
35725
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
35243
35726
  }),
35244
- hasActions && /* @__PURE__ */ jsx(
35727
+ hasActions && /* @__PURE__ */ jsxs(
35245
35728
  HStack,
35246
35729
  {
35247
35730
  gap: "xs",
@@ -35255,23 +35738,38 @@ function TableView({
35255
35738
  "border-l border-[var(--color-border)]",
35256
35739
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
35257
35740
  ),
35258
- children: /* @__PURE__ */ jsx(
35259
- Menu,
35260
- {
35261
- position: "bottom-end",
35262
- 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" }) }),
35263
- items: actionDefs.map((action) => ({
35264
- label: action.label,
35265
- icon: action.icon,
35266
- event: action.event,
35267
- variant: action.variant === "danger" ? "danger" : "default",
35268
- onClick: () => eventBus.emit(`UI:${action.event}`, {
35269
- id: row.id,
35270
- row
35271
- })
35272
- }))
35273
- }
35274
- )
35741
+ children: [
35742
+ inlineActions.map((action) => /* @__PURE__ */ jsxs(
35743
+ Button,
35744
+ {
35745
+ variant: action.variant ?? "ghost",
35746
+ size: "sm",
35747
+ onClick: () => fireAction(action, row),
35748
+ "data-testid": `action-${action.event}`,
35749
+ "data-row-id": String(row.id),
35750
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
35751
+ children: [
35752
+ action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
35753
+ action.label
35754
+ ]
35755
+ },
35756
+ action.event
35757
+ )),
35758
+ overflowActions.length > 0 && /* @__PURE__ */ jsx(
35759
+ Menu,
35760
+ {
35761
+ position: "bottom-end",
35762
+ 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" }) }),
35763
+ items: overflowActions.map((action) => ({
35764
+ label: action.label,
35765
+ icon: action.icon,
35766
+ event: action.event,
35767
+ variant: action.variant === "danger" ? "danger" : "default",
35768
+ onClick: () => fireAction(action, row)
35769
+ }))
35770
+ }
35771
+ )
35772
+ ]
35275
35773
  }
35276
35774
  )
35277
35775
  ]
@@ -51103,6 +51601,7 @@ var init_component_registry_generated = __esm({
51103
51601
  init_DrawMesh();
51104
51602
  init_DrawShape();
51105
51603
  init_DrawShapeLayer();
51604
+ init_DrawSkinnedMesh();
51106
51605
  init_DrawSprite();
51107
51606
  init_DrawSpriteLayer();
51108
51607
  init_DrawText();
@@ -51381,6 +51880,7 @@ var init_component_registry_generated = __esm({
51381
51880
  "DrawMesh": DrawMesh,
51382
51881
  "DrawShape": DrawShape,
51383
51882
  "DrawShapeLayer": DrawShapeLayer,
51883
+ "DrawSkinnedMesh": DrawSkinnedMesh,
51384
51884
  "DrawSprite": DrawSprite,
51385
51885
  "DrawSpriteLayer": DrawSpriteLayer,
51386
51886
  "DrawText": DrawText,
@@ -51709,7 +52209,7 @@ function renderContainedPortal(t, slot, content, onDismiss) {
51709
52209
  const slotId = `slot-${slot}`;
51710
52210
  switch (slot) {
51711
52211
  case "modal":
51712
- if (SELF_OVERLAY_PATTERNS.has(content.pattern)) {
52212
+ if (SELF_OVERLAY_PATTERN_TYPES.has(content.pattern)) {
51713
52213
  return /* @__PURE__ */ jsx(Box, { id: slotId, className: "contents", children: slotContent });
51714
52214
  }
51715
52215
  return /* @__PURE__ */ jsx(
@@ -52052,7 +52552,7 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
52052
52552
  children
52053
52553
  }
52054
52554
  );
52055
- wrapper = pattern !== void 0 && SELF_OVERLAY_PATTERNS.has(pattern) ? innerContent : /* @__PURE__ */ jsx(Modal, { isOpen: true, onClose: handleDismiss, showCloseButton: true, size: "lg", children: innerContent });
52555
+ wrapper = pattern !== void 0 && SELF_OVERLAY_PATTERN_TYPES.has(pattern) ? innerContent : /* @__PURE__ */ jsx(Modal, { isOpen: true, onClose: handleDismiss, showCloseButton: true, size: "lg", children: innerContent });
52056
52556
  break;
52057
52557
  }
52058
52558
  case "drawer":
@@ -52112,7 +52612,7 @@ function SlotPortal({
52112
52612
  let wrapper;
52113
52613
  switch (slot) {
52114
52614
  case "modal":
52115
- wrapper = SELF_OVERLAY_PATTERNS.has(content.pattern) ? /* @__PURE__ */ jsx(Box, { id: slotId, children: slotContent }) : /* @__PURE__ */ jsx(
52615
+ wrapper = SELF_OVERLAY_PATTERN_TYPES.has(content.pattern) ? /* @__PURE__ */ jsx(Box, { id: slotId, children: slotContent }) : /* @__PURE__ */ jsx(
52116
52616
  Modal,
52117
52617
  {
52118
52618
  isOpen: true,
@@ -52619,7 +53119,7 @@ function UISlotRenderer({
52619
53119
  }
52620
53120
  return wrapped;
52621
53121
  }
52622
- var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, SELF_OVERLAY_PATTERNS, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
53122
+ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
52623
53123
  var init_UISlotRenderer = __esm({
52624
53124
  "components/core/organisms/UISlotRenderer.tsx"() {
52625
53125
  "use client";
@@ -52650,7 +53150,6 @@ var init_UISlotRenderer = __esm({
52650
53150
  modal: "form",
52651
53151
  drawer: "form"
52652
53152
  };
52653
- SELF_OVERLAY_PATTERNS = /* @__PURE__ */ new Set(["modal", "confirm-dialog"]);
52654
53153
  CONTENT_NODE_SLOTS = /* @__PURE__ */ new Set([
52655
53154
  "logo",
52656
53155
  "master",
@@ -54071,9 +54570,6 @@ function ServerBridgeProvider({
54071
54570
  });
54072
54571
  } else if (effectType === "navigate-back") {
54073
54572
  effects.push({ type: "navigate-back", traitName });
54074
- } else if (effectType === "notify") {
54075
- const message = effect[1];
54076
- effects.push({ type: "notify", message: typeof message === "string" ? message : void 0, traitName });
54077
54573
  }
54078
54574
  }
54079
54575
  if (result.emittedEvents) {