@almadar/ui 6.13.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 +367 -61
  10. package/dist/avl/index.d.cts +1 -1
  11. package/dist/avl/index.d.ts +1 -1
  12. package/dist/avl/index.js +369 -63
  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 +360 -108
  16. package/dist/components/index.d.cts +8 -24
  17. package/dist/components/index.d.ts +8 -24
  18. package/dist/components/index.js +362 -109
  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 +354 -53
  34. package/dist/providers/index.d.cts +10 -9
  35. package/dist/providers/index.d.ts +10 -9
  36. package/dist/providers/index.js +355 -54
  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 +369 -72
  42. package/dist/runtime/index.d.cts +14 -11
  43. package/dist/runtime/index.d.ts +14 -11
  44. package/dist/runtime/index.js +371 -74
  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
@@ -1,18 +1,20 @@
1
1
  import React__default, { ReactNode } from 'react';
2
2
  import { EntityRow, SExpr } from '@almadar/core';
3
3
  export { ANONYMOUS_USER } from '@almadar/core';
4
- import { U as UIThemeDefinition, j as UserData } from '../UserContext-g_LcDiGN.js';
5
- export { a as CurrentPagePathContext, b as CurrentPagePathProvider, c as CurrentPagePathProviderProps, d as DesignThemeProvider, O as OrbitalThemeProvider, e as OrbitalThemeProviderProps, h as UserContext, i as UserContextValue, k as UserProvider, l as UserProviderProps, u as useCurrentPagePath, m as useDesignTheme, n as useHasPermission, o as useHasRole, q as useUser, r as useUserForEvaluation } from '../UserContext-g_LcDiGN.js';
4
+ import { U as UIThemeDefinition } from '../CurrentPagePathContext-J1lqjvAq.js';
5
+ export { a as CurrentPagePathContext, b as CurrentPagePathProvider, c as CurrentPagePathProviderProps, d as DesignThemeProvider, O as OrbitalThemeProvider, e as OrbitalThemeProviderProps, u as useCurrentPagePath, h as useDesignTheme } from '../CurrentPagePathContext-J1lqjvAq.js';
6
+ import { b as UserData } from '../UserContext-D566nfWA.js';
7
+ export { U as UserContext, a as UserContextValue, c as UserProvider, d as UserProviderProps, u as useHasPermission, e as useHasRole, f as useUser, g as useUserForEvaluation } from '../UserContext-D566nfWA.js';
6
8
  import { E as EventBusContextType } from '../event-bus-types-Bl78kokd.js';
7
- export { A as AccessTokenProvider, E as EntityBindingContext, a as EntityBindingSource, b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, S as SendEventResult, e as ServerBridgeContextValue, f as ServerBridgeProvider, g as ServerBridgeProviderProps, h as ServerBridgeTransport, i as ServerClientEffect, j as ServerResponseMeta, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, u as useEntityBindingSnapshot, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-D5lRu6p1.js';
8
- import { j as UseOfflineExecutorResult, U as UseOfflineExecutorOptions } from '../offline-executor-QUdKOj7f.js';
9
- export { c as NavigationContextValue, d as NavigationProvider, e as NavigationProviderProps, f as NavigationState, k as comparePathSpecificity, m as extractRouteParams, n as findPageByName, o as findPageByPath, p as getAllPages, q as getDefaultPage, r as matchPath, s as matchPathAmong, t as pathMatches, u as useActivePage, v as useInitPayload, w as useNavigateTo, x as useNavigation, y as useNavigationId, z as useNavigationState } from '../offline-executor-QUdKOj7f.js';
10
- import '../verificationRegistry-D8bHWD8Q.js';
11
- export { G as GameAudioContext, a as GameAudioContextValue, b as GameAudioProvider, c as GameAudioProviderProps, u as useGameAudioContext, d as useGameAudioContextOptional } from '../GameAudioProvider-Dozqx4sL.js';
9
+ export { A as AccessTokenProvider, E as EntityBindingContext, a as EntityBindingSource, b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, S as SendEventResult, e as ServerBridgeContextValue, f as ServerBridgeProvider, g as ServerBridgeProviderProps, h as ServerBridgeTransport, i as ServerClientEffect, j as ServerResponseMeta, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, u as useEntityBindingSnapshot, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-BMz9xiBa.js';
10
+ import { i as UseOfflineExecutorResult, U as UseOfflineExecutorOptions } from '../offline-executor-DdV2o0Zu.js';
11
+ export { N as NavigationContextValue, c as NavigationProvider, d as NavigationProviderProps, e as NavigationState, j as comparePathSpecificity, l as extractRouteParams, m as findPageByName, n as findPageByPath, o as getAllPages, p as getDefaultPage, q as matchPath, r as matchPathAmong, s as pathMatches, u as useActivePage, t as useInitPayload, v as useNavigateTo, w as useNavigation, x as useNavigationId, y as useNavigationState } from '../offline-executor-DdV2o0Zu.js';
12
+ import '../verificationRegistry-Cwa52VyK.js';
13
+ export { G as GameAudioContext, a as GameAudioContextValue, b as GameAudioProvider, c as GameAudioProviderProps, u as useGameAudioContext, d as useGameAudioContextOptional } from '../GameAudioProvider-DIjFiy70.js';
12
14
  export { N as NavPageDecl, a as NavStackApi, b as NavStackProvider, c as NavStackProviderProps, d as NavStackRouterBridge, e as NavStackRouterBridgeProps, u as useNavStack } from '../NavStackContext-bw2nlBgT.js';
13
15
  import '@almadar/core/patterns';
14
16
  import '@almadar/runtime';
15
- import '../paintDispatch-CK5uwYEq.js';
17
+ import '../paintDispatch-Dh1pgljl.js';
16
18
 
17
19
  /**
18
20
  * EventBusProvider - React context provider for the event bus
@@ -449,7 +451,6 @@ interface OfflineModeProviderProps extends UseOfflineExecutorOptions {
449
451
  * autoSync={true}
450
452
  * renderToSlot={slotManager.render}
451
453
  * navigate={router.push}
452
- * notify={toast.show}
453
454
  * eventBus={{ emit: bus.emit }}
454
455
  * >
455
456
  * <PreviewPage />
@@ -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);
@@ -28059,7 +28337,9 @@ function DataGrid({
28059
28337
  const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
28060
28338
  const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
28061
28339
  const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
28062
- 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";
28063
28343
  useEffect(() => {
28064
28344
  if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
28065
28345
  const schemaArr = Array.isArray(schemaRenderItem) ? schemaRenderItem : null;
@@ -28133,7 +28413,7 @@ function DataGrid({
28133
28413
  onClick: handleCardClick?.(itemData),
28134
28414
  className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
28135
28415
  children: [
28136
- children(itemData, index),
28416
+ itemRenderer(itemData, index),
28137
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: [
28138
28418
  inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxs(
28139
28419
  Button,
@@ -28466,7 +28746,9 @@ function DataList({
28466
28746
  );
28467
28747
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
28468
28748
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
28469
- 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";
28470
28752
  React89__default.useEffect(() => {
28471
28753
  const renderItemTypeOf = typeof schemaRenderItem;
28472
28754
  const childrenTypeOf = typeof children;
@@ -28684,7 +28966,7 @@ function DataList({
28684
28966
  const actions = renderItemActions(itemData);
28685
28967
  return wrapDnd(
28686
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: [
28687
- children(itemData, index),
28969
+ itemRenderer(itemData, index),
28688
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: [
28689
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 }),
28690
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(
@@ -35228,7 +35510,7 @@ function TableView({
35228
35510
  columns,
35229
35511
  fields,
35230
35512
  itemActions,
35231
- maxInlineActions: _maxInlineActions,
35513
+ maxInlineActions,
35232
35514
  itemClickEvent = "",
35233
35515
  selectable = false,
35234
35516
  selectEvent,
@@ -35261,6 +35543,12 @@ function TableView({
35261
35543
  const [localSelected, setLocalSelected] = React89__default.useState(/* @__PURE__ */ new Set());
35262
35544
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
35263
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
+ });
35264
35552
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
35265
35553
  const dnd = useDataDnd({
35266
35554
  items: allDataRaw,
@@ -35436,7 +35724,7 @@ function TableView({
35436
35724
  }
35437
35725
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
35438
35726
  }),
35439
- hasActions && /* @__PURE__ */ jsx(
35727
+ hasActions && /* @__PURE__ */ jsxs(
35440
35728
  HStack,
35441
35729
  {
35442
35730
  gap: "xs",
@@ -35450,23 +35738,38 @@ function TableView({
35450
35738
  "border-l border-[var(--color-border)]",
35451
35739
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
35452
35740
  ),
35453
- children: /* @__PURE__ */ jsx(
35454
- Menu,
35455
- {
35456
- position: "bottom-end",
35457
- 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" }) }),
35458
- items: actionDefs.map((action) => ({
35459
- label: action.label,
35460
- icon: action.icon,
35461
- event: action.event,
35462
- variant: action.variant === "danger" ? "danger" : "default",
35463
- onClick: () => eventBus.emit(`UI:${action.event}`, {
35464
- id: row.id,
35465
- row
35466
- })
35467
- }))
35468
- }
35469
- )
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
+ ]
35470
35773
  }
35471
35774
  )
35472
35775
  ]
@@ -51298,6 +51601,7 @@ var init_component_registry_generated = __esm({
51298
51601
  init_DrawMesh();
51299
51602
  init_DrawShape();
51300
51603
  init_DrawShapeLayer();
51604
+ init_DrawSkinnedMesh();
51301
51605
  init_DrawSprite();
51302
51606
  init_DrawSpriteLayer();
51303
51607
  init_DrawText();
@@ -51576,6 +51880,7 @@ var init_component_registry_generated = __esm({
51576
51880
  "DrawMesh": DrawMesh,
51577
51881
  "DrawShape": DrawShape,
51578
51882
  "DrawShapeLayer": DrawShapeLayer,
51883
+ "DrawSkinnedMesh": DrawSkinnedMesh,
51579
51884
  "DrawSprite": DrawSprite,
51580
51885
  "DrawSpriteLayer": DrawSpriteLayer,
51581
51886
  "DrawText": DrawText,
@@ -51904,7 +52209,7 @@ function renderContainedPortal(t, slot, content, onDismiss) {
51904
52209
  const slotId = `slot-${slot}`;
51905
52210
  switch (slot) {
51906
52211
  case "modal":
51907
- if (SELF_OVERLAY_PATTERNS.has(content.pattern)) {
52212
+ if (SELF_OVERLAY_PATTERN_TYPES.has(content.pattern)) {
51908
52213
  return /* @__PURE__ */ jsx(Box, { id: slotId, className: "contents", children: slotContent });
51909
52214
  }
51910
52215
  return /* @__PURE__ */ jsx(
@@ -52247,7 +52552,7 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
52247
52552
  children
52248
52553
  }
52249
52554
  );
52250
- 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 });
52251
52556
  break;
52252
52557
  }
52253
52558
  case "drawer":
@@ -52307,7 +52612,7 @@ function SlotPortal({
52307
52612
  let wrapper;
52308
52613
  switch (slot) {
52309
52614
  case "modal":
52310
- 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(
52311
52616
  Modal,
52312
52617
  {
52313
52618
  isOpen: true,
@@ -52814,7 +53119,7 @@ function UISlotRenderer({
52814
53119
  }
52815
53120
  return wrapped;
52816
53121
  }
52817
- 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;
52818
53123
  var init_UISlotRenderer = __esm({
52819
53124
  "components/core/organisms/UISlotRenderer.tsx"() {
52820
53125
  "use client";
@@ -52845,7 +53150,6 @@ var init_UISlotRenderer = __esm({
52845
53150
  modal: "form",
52846
53151
  drawer: "form"
52847
53152
  };
52848
- SELF_OVERLAY_PATTERNS = /* @__PURE__ */ new Set(["modal", "confirm-dialog"]);
52849
53153
  CONTENT_NODE_SLOTS = /* @__PURE__ */ new Set([
52850
53154
  "logo",
52851
53155
  "master",
@@ -54266,9 +54570,6 @@ function ServerBridgeProvider({
54266
54570
  });
54267
54571
  } else if (effectType === "navigate-back") {
54268
54572
  effects.push({ type: "navigate-back", traitName });
54269
- } else if (effectType === "notify") {
54270
- const message = effect[1];
54271
- effects.push({ type: "notify", message: typeof message === "string" ? message : void 0, traitName });
54272
54573
  }
54273
54574
  }
54274
54575
  if (result.emittedEvents) {