@almadar/ui 6.13.0 → 6.15.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-EJoTtuTR.d.cts} +9 -3
  4. package/dist/{EntityBindingContext-D5lRu6p1.d.ts → EntityBindingContext-EJoTtuTR.d.ts} +9 -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 +373 -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 +375 -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 +366 -55
  34. package/dist/providers/index.d.cts +10 -9
  35. package/dist/providers/index.d.ts +10 -9
  36. package/dist/providers/index.js +367 -56
  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 +375 -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 +377 -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,6 +1,6 @@
1
1
  import * as React87 from 'react';
2
2
  import React87__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useSyncExternalStore, Suspense, useState, useLayoutEffect, lazy, useId } from 'react';
3
- import { EventBusContext, useTraitScopeChain, RenderSlotProvider, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, useEntitySchema, getAllPages, matchPathAmong, CurrentPagePathProvider, NavStackProvider, OrbitalProvider, TraitScopeProvider, useNavStack, ServerBridgeProvider, useCurrentPagePath, useRenderSlot, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext } from '@almadar/ui/providers';
3
+ import { EventBusContext, useTraitScopeChain, RenderSlotProvider, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, useEntitySchema, useUser, getAllPages, matchPathAmong, CurrentPagePathProvider, NavStackProvider, OrbitalProvider, TraitScopeProvider, useNavStack, ServerBridgeProvider, useCurrentPagePath, useRenderSlot, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext } from '@almadar/ui/providers';
4
4
  export { EntitySchemaProvider, ServerBridgeProvider, TraitContext, TraitProvider, useEntitySchema, useEntitySchemaOptional, useServerBridge, useTrait, useTraitContext } from '@almadar/ui/providers';
5
5
  import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
6
6
  import { perfStore, pushPerfEntry, wrapCallbackForEvent, perfStart, perfEnd, perfGauge, prepareSchemaForPreview, perfTimeAsync, collectTraitRefsFromResolvedTrait, buildOrbitalsByTrait, collectEmbeddedTraits } from '@almadar/runtime/ui';
@@ -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
  import { isKnownStdOperator } from '@almadar/std/registry';
83
83
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
84
84
 
@@ -8346,7 +8346,7 @@ var init_DialogueBubble = __esm({
8346
8346
  init_Typography();
8347
8347
  init_GameIcon();
8348
8348
  DEFAULT_PORTRAIT = {
8349
- url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
8349
+ url: "https://almadar-kflow-assets.web.app/shared/ui-winter-ski-board/default/units/hero/hero.png",
8350
8350
  role: "effect",
8351
8351
  category: "character"
8352
8352
  };
@@ -9563,6 +9563,14 @@ function createWebPainter(ctx, onAssetLoad) {
9563
9563
  ctx.drawImage(img, dest.x, dest.y, dw, dh);
9564
9564
  }
9565
9565
  },
9566
+ blitTransformed(tex, src, affine) {
9567
+ const img = imageByHandle.get(tex);
9568
+ if (!img) return;
9569
+ ctx.save();
9570
+ ctx.transform(affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]);
9571
+ ctx.drawImage(img, src.x, src.y, src.w, src.h, src.x, src.y, src.w, src.h);
9572
+ ctx.restore();
9573
+ },
9566
9574
  fillRect(x, y, w, h, style) {
9567
9575
  ctx.fillStyle = toCanvasStyle(style);
9568
9576
  ctx.fillRect(x, y, w, h);
@@ -10069,6 +10077,271 @@ var init_DrawGroup = __esm({
10069
10077
  init_registry();
10070
10078
  }
10071
10079
  });
10080
+
10081
+ // lib/skinning.ts
10082
+ function composeAffine(a, b) {
10083
+ return [
10084
+ a[0] * b[0] + a[2] * b[1],
10085
+ a[1] * b[0] + a[3] * b[1],
10086
+ a[0] * b[2] + a[2] * b[3],
10087
+ a[1] * b[2] + a[3] * b[3],
10088
+ a[0] * b[4] + a[2] * b[5] + a[4],
10089
+ a[1] * b[4] + a[3] * b[5] + a[5]
10090
+ ];
10091
+ }
10092
+ function invertAffine(m) {
10093
+ const det = m[0] * m[3] - m[1] * m[2];
10094
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return IDENTITY;
10095
+ const inv = 1 / det;
10096
+ return [
10097
+ m[3] * inv,
10098
+ -m[1] * inv,
10099
+ -m[2] * inv,
10100
+ m[0] * inv,
10101
+ (m[2] * m[5] - m[3] * m[4]) * inv,
10102
+ (m[1] * m[4] - m[0] * m[5]) * inv
10103
+ ];
10104
+ }
10105
+ function applyAffine(m, x, y) {
10106
+ return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
10107
+ }
10108
+ function rotationAbout(pivot, degrees) {
10109
+ const r = degrees * Math.PI / 180;
10110
+ const cos = Math.cos(r);
10111
+ const sin = Math.sin(r);
10112
+ const [px, py] = pivot;
10113
+ return [cos, sin, -sin, cos, px - cos * px + sin * py, py - sin * px - cos * py];
10114
+ }
10115
+ function computeWorldMatrices(bones, pose) {
10116
+ const indexByName = /* @__PURE__ */ new Map();
10117
+ bones.forEach((b, i) => indexByName.set(b.name, i));
10118
+ const world = new Array(bones.length);
10119
+ const visiting = /* @__PURE__ */ new Set();
10120
+ const resolve = (i) => {
10121
+ const cached = world[i];
10122
+ if (cached) return cached;
10123
+ if (visiting.has(i)) return IDENTITY;
10124
+ visiting.add(i);
10125
+ const b = bones[i];
10126
+ const parentIndex = b.parent === null ? void 0 : indexByName.get(b.parent);
10127
+ const parentWorld = parentIndex === void 0 ? IDENTITY : resolve(parentIndex);
10128
+ const local = rotationAbout(b.pivot, pose[b.name] ?? 0);
10129
+ const m = composeAffine(parentWorld, local);
10130
+ visiting.delete(i);
10131
+ world[i] = m;
10132
+ return m;
10133
+ };
10134
+ return bones.map((_, i) => resolve(i));
10135
+ }
10136
+ function skinVertices(mesh, bindWorld, curWorld) {
10137
+ const skinMats = /* @__PURE__ */ new Map();
10138
+ const skinMat = (bone) => {
10139
+ let m = skinMats.get(bone);
10140
+ if (!m) {
10141
+ m = composeAffine(curWorld[bone] ?? IDENTITY, invertAffine(bindWorld[bone] ?? IDENTITY));
10142
+ skinMats.set(bone, m);
10143
+ }
10144
+ return m;
10145
+ };
10146
+ return mesh.vertices.map((v) => {
10147
+ if (v.weights.length === 0) return [v.x, v.y];
10148
+ let x = 0;
10149
+ let y = 0;
10150
+ for (const { bone, w } of v.weights) {
10151
+ const [bx, by] = applyAffine(skinMat(bone), v.x, v.y);
10152
+ x += w * bx;
10153
+ y += w * by;
10154
+ }
10155
+ return [x, y];
10156
+ });
10157
+ }
10158
+ function triangleAffine(src, dst) {
10159
+ const [s0, s1, s2] = src;
10160
+ const det = s0[0] * (s1[1] - s2[1]) + s1[0] * (s2[1] - s0[1]) + s2[0] * (s0[1] - s1[1]);
10161
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return null;
10162
+ const [d0, d1, d2] = dst;
10163
+ const a = (d0[0] * (s1[1] - s2[1]) + d1[0] * (s2[1] - s0[1]) + d2[0] * (s0[1] - s1[1])) / det;
10164
+ const c = (d0[0] * (s2[0] - s1[0]) + d1[0] * (s0[0] - s2[0]) + d2[0] * (s1[0] - s0[0])) / det;
10165
+ 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;
10166
+ const b = (d0[1] * (s1[1] - s2[1]) + d1[1] * (s2[1] - s0[1]) + d2[1] * (s0[1] - s1[1])) / det;
10167
+ const d = (d0[1] * (s2[0] - s1[0]) + d1[1] * (s0[0] - s2[0]) + d2[1] * (s1[0] - s0[0])) / det;
10168
+ 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;
10169
+ return [a, b, c, d, e, f3];
10170
+ }
10171
+ function isRigBundle(json) {
10172
+ return json.mesh !== void 0 || json.bones !== void 0;
10173
+ }
10174
+ function getRigBundle(url, onReady) {
10175
+ if (meshCache.has(url)) return meshCache.get(url) ?? void 0;
10176
+ meshCache.set(url, void 0);
10177
+ fetch(url).then((r) => {
10178
+ if (!r.ok) throw new Error(`rigbundle fetch failed: HTTP ${r.status}`);
10179
+ return r.json();
10180
+ }).then((json) => {
10181
+ const ok = isRigBundle(json) || Array.isArray(json.vertices);
10182
+ if (!ok) throw new Error("rigbundle payload is neither a SkinMesh nor a rigbundle");
10183
+ meshCache.set(url, json);
10184
+ onReady();
10185
+ }).catch(() => {
10186
+ meshCache.set(url, null);
10187
+ onReady();
10188
+ });
10189
+ return void 0;
10190
+ }
10191
+ function skinMeshFailed(url) {
10192
+ return meshCache.get(url) === null;
10193
+ }
10194
+ function vertexBounds(points) {
10195
+ if (points.length === 0) return null;
10196
+ let minX = Infinity;
10197
+ let minY = Infinity;
10198
+ let maxX = -Infinity;
10199
+ let maxY = -Infinity;
10200
+ for (const [x, y] of points) {
10201
+ if (x < minX) minX = x;
10202
+ if (y < minY) minY = y;
10203
+ if (x > maxX) maxX = x;
10204
+ if (y > maxY) maxY = y;
10205
+ }
10206
+ return { minX, minY, maxX, maxY };
10207
+ }
10208
+ var IDENTITY, meshCache;
10209
+ var init_skinning = __esm({
10210
+ "lib/skinning.ts"() {
10211
+ IDENTITY = [1, 0, 0, 1, 0, 0];
10212
+ meshCache = /* @__PURE__ */ new Map();
10213
+ }
10214
+ });
10215
+ function warnMissingOnce2(reason, node) {
10216
+ const key = `${reason}:${node.asset.url}:${String(node.meshUrl)}`;
10217
+ if (loggedMissing2.has(key)) return;
10218
+ loggedMissing2.add(key);
10219
+ skinnedLog.warn("draw-skinned-mesh unresolvable \u2014 painting fallback", { reason, url: node.asset.url, meshUrl: node.meshUrl });
10220
+ }
10221
+ function dominantBone(v) {
10222
+ let best = -1;
10223
+ let bestW = 0;
10224
+ for (const { bone, w } of v.weights) {
10225
+ if (w > bestW) {
10226
+ bestW = w;
10227
+ best = bone;
10228
+ }
10229
+ }
10230
+ return best;
10231
+ }
10232
+ function resolveSkinPose(node, clip) {
10233
+ const effectiveClip = clip ?? node.clip;
10234
+ if (effectiveClip && node.frame !== void 0 && effectiveClip.frames.length > 0) {
10235
+ return effectiveClip.frames[node.frame % effectiveClip.frames.length];
10236
+ }
10237
+ return node.pose ?? {};
10238
+ }
10239
+ function resolveRig(node, dctx) {
10240
+ const fetched = node.meshUrl ? getRigBundle(node.meshUrl, dctx.invalidate) : void 0;
10241
+ if (node.meshUrl && fetched === void 0) return void 0;
10242
+ const rb = fetched && isRigBundle(fetched) ? fetched : void 0;
10243
+ const mesh = node.mesh ?? rb?.mesh ?? (!rb ? fetched : void 0);
10244
+ if (!mesh) return void 0;
10245
+ const bones = node.bones.length > 0 ? node.bones : rb?.bones ?? [];
10246
+ if (bones.length === 0) return void 0;
10247
+ const clip = node.clip ?? (node.clipName ? rb?.clips?.[node.clipName] : void 0);
10248
+ return { mesh, bones, clip };
10249
+ }
10250
+ function meshHasPixelUVs(mesh) {
10251
+ const cached = pixelUVByMesh.get(mesh);
10252
+ if (cached !== void 0) return cached;
10253
+ let pixel = false;
10254
+ for (const v of mesh.vertices) {
10255
+ if (v.u < 0 || v.u > 1 || v.v < 0 || v.v > 1) {
10256
+ pixel = true;
10257
+ break;
10258
+ }
10259
+ }
10260
+ pixelUVByMesh.set(mesh, pixel);
10261
+ return pixel;
10262
+ }
10263
+ function paintMeshPass(painter, node, bones, mesh, tex, dctx, pose, opacity) {
10264
+ const bindWorld = computeWorldMatrices(bones, {});
10265
+ const curWorld = computeWorldMatrices(bones, pose);
10266
+ const skinned = skinVertices(mesh, bindWorld, curWorld);
10267
+ const origin = dctx.projector.project(node.position);
10268
+ const tw = dctx.projector.tileWidth;
10269
+ painter.save();
10270
+ if (opacity !== 1) painter.setAlpha(opacity);
10271
+ for (const [i0, i1, i2] of mesh.triangles) {
10272
+ const v0 = mesh.vertices[i0];
10273
+ const v1 = mesh.vertices[i1];
10274
+ const v2 = mesh.vertices[i2];
10275
+ const p0 = skinned[i0];
10276
+ const p1 = skinned[i1];
10277
+ const p2 = skinned[i2];
10278
+ if (!v0 || !v1 || !v2 || !p0 || !p1 || !p2) continue;
10279
+ const dst = [
10280
+ [origin.x + p0[0] * tw, origin.y + p0[1] * tw],
10281
+ [origin.x + p1[0] * tw, origin.y + p1[1] * tw],
10282
+ [origin.x + p2[0] * tw, origin.y + p2[1] * tw]
10283
+ ];
10284
+ if (node.weightsOverlay || !tex) {
10285
+ if (!node.weightsOverlay) continue;
10286
+ const bone = dominantBone(v0);
10287
+ painter.fillPoly(
10288
+ dst.map(([x, y]) => ({ x, y })),
10289
+ WEIGHT_PALETTE[(bone % WEIGHT_PALETTE.length + WEIGHT_PALETTE.length) % WEIGHT_PALETTE.length]
10290
+ );
10291
+ continue;
10292
+ }
10293
+ const pixelUV = meshHasPixelUVs(mesh);
10294
+ const uv = pixelUV ? [[v0.u, v0.v], [v1.u, v1.v], [v2.u, v2.v]] : [
10295
+ [v0.u * tex.width, v0.v * tex.height],
10296
+ [v1.u * tex.width, v1.v * tex.height],
10297
+ [v2.u * tex.width, v2.v * tex.height]
10298
+ ];
10299
+ const affine = triangleAffine(uv, dst);
10300
+ if (!affine) continue;
10301
+ painter.save();
10302
+ painter.clipPath(`M ${dst[0][0]} ${dst[0][1]} L ${dst[1][0]} ${dst[1][1]} L ${dst[2][0]} ${dst[2][1]} Z`);
10303
+ painter.blitTransformed(tex, { x: 0, y: 0, w: tex.width, h: tex.height }, affine);
10304
+ painter.restore();
10305
+ }
10306
+ painter.restore();
10307
+ }
10308
+ function DrawSkinnedMesh(props) {
10309
+ const register = useContext(DrawableRegistryContext);
10310
+ if (register) register({ ...props, type: "draw-skinned-mesh" });
10311
+ return null;
10312
+ }
10313
+ var skinnedLog, loggedMissing2, WEIGHT_PALETTE, pixelUVByMesh, paintSkinnedMesh;
10314
+ var init_DrawSkinnedMesh = __esm({
10315
+ "components/game/atoms/DrawSkinnedMesh.tsx"() {
10316
+ "use client";
10317
+ init_imageCache();
10318
+ init_contract();
10319
+ init_registry();
10320
+ init_skinning();
10321
+ skinnedLog = createLogger("almadar:ui:draw-skinned-mesh");
10322
+ loggedMissing2 = /* @__PURE__ */ new Set();
10323
+ WEIGHT_PALETTE = Array.from({ length: 10 }, (_, i) => `hsl(${i * 36 % 360}, 70%, 55%)`);
10324
+ pixelUVByMesh = /* @__PURE__ */ new WeakMap();
10325
+ paintSkinnedMesh = (painter, node, dctx) => {
10326
+ if (!isValidScenePos(node.position)) return;
10327
+ const rig = resolveRig(node, dctx);
10328
+ if (!rig) {
10329
+ if (node.meshUrl && skinMeshFailed(node.meshUrl)) warnMissingOnce2("mesh-failed", node);
10330
+ else if (!node.mesh && !node.meshUrl) warnMissingOnce2("mesh-missing", node);
10331
+ return;
10332
+ }
10333
+ const tex = node.weightsOverlay ? null : painter.resolveTexture(node.asset.url);
10334
+ if (!node.weightsOverlay && !tex) {
10335
+ if (getImageStatus(node.asset.url) === "failed") warnMissingOnce2("texture-failed", node);
10336
+ return;
10337
+ }
10338
+ if (node.ghost && rig.clip && rig.clip.frames.length > 0) {
10339
+ paintMeshPass(painter, node, rig.bones, rig.mesh, tex, dctx, rig.clip.frames[node.ghost.frame % rig.clip.frames.length], node.ghost.opacity);
10340
+ }
10341
+ paintMeshPass(painter, node, rig.bones, rig.mesh, tex, dctx, resolveSkinPose(node, rig.clip), node.opacity ?? 1);
10342
+ };
10343
+ }
10344
+ });
10072
10345
  function applyMeshAnimation(node, timeMs) {
10073
10346
  const anim = node.animation;
10074
10347
  if (!anim || !(anim.durationMs > 0) || anim.keyframes.length === 0) return null;
@@ -10393,6 +10666,9 @@ function paintDrawable(painter, node, dctx) {
10393
10666
  case "draw-mesh":
10394
10667
  warnUnsupported2d("draw-mesh");
10395
10668
  break;
10669
+ case "draw-skinned-mesh":
10670
+ paintSkinnedMesh(painter, node, dctx);
10671
+ break;
10396
10672
  case "draw-sprite-layer":
10397
10673
  paintSpriteLayer(painter, node, dctx);
10398
10674
  break;
@@ -10417,6 +10693,7 @@ var init_paintDispatch = __esm({
10417
10693
  init_DrawShape();
10418
10694
  init_DrawText();
10419
10695
  init_DrawGroup();
10696
+ init_DrawSkinnedMesh();
10420
10697
  init_DrawMesh();
10421
10698
  init_DrawSpriteLayer();
10422
10699
  init_DrawShapeLayer();
@@ -10437,6 +10714,21 @@ function shapeDrawnItem(n) {
10437
10714
  if (n.shape !== "rect") return { pos: n.position, id: n.id };
10438
10715
  return { pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height, rotation: n.rotate };
10439
10716
  }
10717
+ function skinnedMeshDrawnItem(n) {
10718
+ const mesh = n.mesh;
10719
+ if (!mesh || n.bones.length === 0) return { pos: n.position, id: n.id };
10720
+ const bindWorld = computeWorldMatrices(n.bones, {});
10721
+ const curWorld = computeWorldMatrices(n.bones, resolveSkinPose(n));
10722
+ const bounds = vertexBounds(skinVertices(mesh, bindWorld, curWorld));
10723
+ if (!bounds) return { pos: n.position, id: n.id };
10724
+ return {
10725
+ pos: { ...n.position, x: n.position.x + bounds.minX, y: n.position.y + bounds.minY },
10726
+ id: n.id,
10727
+ anchor: "top-left",
10728
+ width: bounds.maxX - bounds.minX,
10729
+ height: bounds.maxY - bounds.minY
10730
+ };
10731
+ }
10440
10732
  function collectDrawnItems(nodes) {
10441
10733
  const out = [];
10442
10734
  for (const n of nodes) {
@@ -10447,6 +10739,9 @@ function collectDrawnItems(nodes) {
10447
10739
  case "draw-shape":
10448
10740
  if (isValidScenePos(n.position)) out.push(shapeDrawnItem(n));
10449
10741
  break;
10742
+ case "draw-skinned-mesh":
10743
+ if (isValidScenePos(n.position)) out.push(skinnedMeshDrawnItem(n));
10744
+ break;
10450
10745
  case "draw-text":
10451
10746
  case "draw-group":
10452
10747
  case "draw-mesh":
@@ -10514,6 +10809,8 @@ function rotatePoint(p, center, radians) {
10514
10809
  var init_hitTest = __esm({
10515
10810
  "lib/drawable/hitTest.ts"() {
10516
10811
  init_contract();
10812
+ init_DrawSkinnedMesh();
10813
+ init_skinning();
10517
10814
  }
10518
10815
  });
10519
10816
  function normalizeBackdrop(bg) {
@@ -11703,7 +12000,7 @@ var init_StateIndicator = __esm({
11703
12000
  init_cn();
11704
12001
  init_GameIcon();
11705
12002
  DEFAULT_ASSET_URL = {
11706
- url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
12003
+ url: "https://almadar-kflow-assets.web.app/shared/ui-topdown-dungeon-board/default/features/chest/chest.png",
11707
12004
  role: "ui",
11708
12005
  category: "state"
11709
12006
  };
@@ -15670,7 +15967,6 @@ var init_avl_atom_types = __esm({
15670
15967
  "persist": "data",
15671
15968
  "fetch": "data",
15672
15969
  "emit": "communication",
15673
- "notify": "communication",
15674
15970
  "call-service": "communication",
15675
15971
  "spawn": "lifecycle",
15676
15972
  "despawn": "lifecycle",
@@ -15818,12 +16114,6 @@ function effectIcon(type, x, y, s, color) {
15818
16114
  /* @__PURE__ */ jsx("line", { x1: x - s, y1: y, x2: x + s * 0.6, y2: y, stroke: color, strokeWidth: 1.5 }),
15819
16115
  /* @__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" })
15820
16116
  ] });
15821
- case "notify":
15822
- return /* @__PURE__ */ jsxs("g", { children: [
15823
- /* @__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 }),
15824
- /* @__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 }),
15825
- /* @__PURE__ */ jsx("circle", { cx: x, cy: y + s * 0.7, r: s * 0.2, fill: color })
15826
- ] });
15827
16117
  case "call-service":
15828
16118
  return /* @__PURE__ */ jsxs("g", { children: [
15829
16119
  /* @__PURE__ */ jsx("line", { x1: x - s, y1: y - s * 0.3, x2: x + s, y2: y - s * 0.3, stroke: color, strokeWidth: 1.5 }),
@@ -21027,9 +21317,6 @@ function getEffectSummary(effects) {
21027
21317
  case "emit":
21028
21318
  summaries.push(`\u2191 ${effect[1] || "event"}`);
21029
21319
  break;
21030
- case "notify":
21031
- summaries.push(`\u{1F4E7} ${effect[1] || ""}`);
21032
- break;
21033
21320
  case "persist":
21034
21321
  summaries.push(`\u{1F4BE} ${effect[1] || "save"}`);
21035
21322
  break;
@@ -21055,7 +21342,7 @@ function extractOutputsFromTransitions(transitions) {
21055
21342
  t.effects.forEach((effect) => {
21056
21343
  if (Array.isArray(effect)) {
21057
21344
  const op = effect[0];
21058
- if (["emit", "notify", "persist", "navigate", "call-service"].includes(op)) {
21345
+ if (["emit", "persist", "navigate", "call-service"].includes(op)) {
21059
21346
  if (isArraySExpr(effect)) {
21060
21347
  const humanText = formatSExprEffectToDomain(effect);
21061
21348
  outputs.add(humanText);
@@ -27998,7 +28285,9 @@ function DataGrid({
27998
28285
  const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
27999
28286
  const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
28000
28287
  const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
28001
- const hasRenderProp = typeof children === "function";
28288
+ const renderItemFn = typeof schemaRenderItem === "function" ? schemaRenderItem : void 0;
28289
+ const itemRenderer = typeof children === "function" ? children : renderItemFn;
28290
+ const hasRenderProp = typeof itemRenderer === "function";
28002
28291
  useEffect(() => {
28003
28292
  if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
28004
28293
  const schemaArr = Array.isArray(schemaRenderItem) ? schemaRenderItem : null;
@@ -28072,7 +28361,7 @@ function DataGrid({
28072
28361
  onClick: handleCardClick?.(itemData),
28073
28362
  className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
28074
28363
  children: [
28075
- children(itemData, index),
28364
+ itemRenderer(itemData, index),
28076
28365
  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: [
28077
28366
  inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxs(
28078
28367
  Button,
@@ -28405,7 +28694,9 @@ function DataList({
28405
28694
  );
28406
28695
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
28407
28696
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
28408
- const hasRenderProp = typeof children === "function";
28697
+ const renderItemFn = typeof schemaRenderItem === "function" ? schemaRenderItem : void 0;
28698
+ const itemRenderer = typeof children === "function" ? children : renderItemFn;
28699
+ const hasRenderProp = typeof itemRenderer === "function";
28409
28700
  React87__default.useEffect(() => {
28410
28701
  const renderItemTypeOf = typeof schemaRenderItem;
28411
28702
  const childrenTypeOf = typeof children;
@@ -28623,7 +28914,7 @@ function DataList({
28623
28914
  const actions = renderItemActions(itemData);
28624
28915
  return wrapDnd(
28625
28916
  /* @__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: [
28626
- children(itemData, index),
28917
+ itemRenderer(itemData, index),
28627
28918
  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: [
28628
28919
  /* @__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 }),
28629
28920
  /* @__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(
@@ -34997,7 +35288,7 @@ function TableView({
34997
35288
  columns,
34998
35289
  fields,
34999
35290
  itemActions,
35000
- maxInlineActions: _maxInlineActions,
35291
+ maxInlineActions,
35001
35292
  itemClickEvent = "",
35002
35293
  selectable = false,
35003
35294
  selectEvent,
@@ -35030,6 +35321,12 @@ function TableView({
35030
35321
  const [localSelected, setLocalSelected] = React87__default.useState(/* @__PURE__ */ new Set());
35031
35322
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
35032
35323
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
35324
+ const inlineActions = maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : [];
35325
+ const overflowActions = maxInlineActions != null ? actionDefs.slice(maxInlineActions) : actionDefs;
35326
+ const fireAction = (action, row) => eventBus.emit(`UI:${action.event}`, {
35327
+ id: row.id,
35328
+ row
35329
+ });
35033
35330
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
35034
35331
  const dnd = useDataDnd({
35035
35332
  items: allDataRaw,
@@ -35205,7 +35502,7 @@ function TableView({
35205
35502
  }
35206
35503
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
35207
35504
  }),
35208
- hasActions && /* @__PURE__ */ jsx(
35505
+ hasActions && /* @__PURE__ */ jsxs(
35209
35506
  HStack,
35210
35507
  {
35211
35508
  gap: "xs",
@@ -35219,23 +35516,38 @@ function TableView({
35219
35516
  "border-l border-[var(--color-border)]",
35220
35517
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
35221
35518
  ),
35222
- children: /* @__PURE__ */ jsx(
35223
- Menu,
35224
- {
35225
- position: "bottom-end",
35226
- 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" }) }),
35227
- items: actionDefs.map((action) => ({
35228
- label: action.label,
35229
- icon: action.icon,
35230
- event: action.event,
35231
- variant: action.variant === "danger" ? "danger" : "default",
35232
- onClick: () => eventBus.emit(`UI:${action.event}`, {
35233
- id: row.id,
35234
- row
35235
- })
35236
- }))
35237
- }
35238
- )
35519
+ children: [
35520
+ inlineActions.map((action) => /* @__PURE__ */ jsxs(
35521
+ Button,
35522
+ {
35523
+ variant: action.variant ?? "ghost",
35524
+ size: "sm",
35525
+ onClick: () => fireAction(action, row),
35526
+ "data-testid": `action-${action.event}`,
35527
+ "data-row-id": String(row.id),
35528
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
35529
+ children: [
35530
+ action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
35531
+ action.label
35532
+ ]
35533
+ },
35534
+ action.event
35535
+ )),
35536
+ overflowActions.length > 0 && /* @__PURE__ */ jsx(
35537
+ Menu,
35538
+ {
35539
+ position: "bottom-end",
35540
+ 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" }) }),
35541
+ items: overflowActions.map((action) => ({
35542
+ label: action.label,
35543
+ icon: action.icon,
35544
+ event: action.event,
35545
+ variant: action.variant === "danger" ? "danger" : "default",
35546
+ onClick: () => fireAction(action, row)
35547
+ }))
35548
+ }
35549
+ )
35550
+ ]
35239
35551
  }
35240
35552
  )
35241
35553
  ]
@@ -50948,6 +51260,7 @@ var init_component_registry_generated = __esm({
50948
51260
  init_DrawMesh();
50949
51261
  init_DrawShape();
50950
51262
  init_DrawShapeLayer();
51263
+ init_DrawSkinnedMesh();
50951
51264
  init_DrawSprite();
50952
51265
  init_DrawSpriteLayer();
50953
51266
  init_DrawText();
@@ -51226,6 +51539,7 @@ var init_component_registry_generated = __esm({
51226
51539
  "DrawMesh": DrawMesh,
51227
51540
  "DrawShape": DrawShape,
51228
51541
  "DrawShapeLayer": DrawShapeLayer,
51542
+ "DrawSkinnedMesh": DrawSkinnedMesh,
51229
51543
  "DrawSprite": DrawSprite,
51230
51544
  "DrawSpriteLayer": DrawSpriteLayer,
51231
51545
  "DrawText": DrawText,
@@ -51554,7 +51868,7 @@ function renderContainedPortal(t, slot, content, onDismiss) {
51554
51868
  const slotId = `slot-${slot}`;
51555
51869
  switch (slot) {
51556
51870
  case "modal":
51557
- if (SELF_OVERLAY_PATTERNS.has(content.pattern)) {
51871
+ if (SELF_OVERLAY_PATTERN_TYPES.has(content.pattern)) {
51558
51872
  return /* @__PURE__ */ jsx(Box, { id: slotId, className: "contents", children: slotContent });
51559
51873
  }
51560
51874
  return /* @__PURE__ */ jsx(
@@ -51897,7 +52211,7 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
51897
52211
  children
51898
52212
  }
51899
52213
  );
51900
- wrapper = pattern !== void 0 && SELF_OVERLAY_PATTERNS.has(pattern) ? innerContent : /* @__PURE__ */ jsx(Modal, { isOpen: true, onClose: handleDismiss, showCloseButton: true, size: "lg", children: innerContent });
52214
+ wrapper = pattern !== void 0 && SELF_OVERLAY_PATTERN_TYPES.has(pattern) ? innerContent : /* @__PURE__ */ jsx(Modal, { isOpen: true, onClose: handleDismiss, showCloseButton: true, size: "lg", children: innerContent });
51901
52215
  break;
51902
52216
  }
51903
52217
  case "drawer":
@@ -51957,7 +52271,7 @@ function SlotPortal({
51957
52271
  let wrapper;
51958
52272
  switch (slot) {
51959
52273
  case "modal":
51960
- wrapper = SELF_OVERLAY_PATTERNS.has(content.pattern) ? /* @__PURE__ */ jsx(Box, { id: slotId, children: slotContent }) : /* @__PURE__ */ jsx(
52274
+ wrapper = SELF_OVERLAY_PATTERN_TYPES.has(content.pattern) ? /* @__PURE__ */ jsx(Box, { id: slotId, children: slotContent }) : /* @__PURE__ */ jsx(
51961
52275
  Modal,
51962
52276
  {
51963
52277
  isOpen: true,
@@ -52464,7 +52778,7 @@ function UISlotRenderer({
52464
52778
  }
52465
52779
  return wrapped;
52466
52780
  }
52467
- var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, SELF_OVERLAY_PATTERNS, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
52781
+ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
52468
52782
  var init_UISlotRenderer = __esm({
52469
52783
  "components/core/organisms/UISlotRenderer.tsx"() {
52470
52784
  "use client";
@@ -52495,7 +52809,6 @@ var init_UISlotRenderer = __esm({
52495
52809
  modal: "form",
52496
52810
  drawer: "form"
52497
52811
  };
52498
- SELF_OVERLAY_PATTERNS = /* @__PURE__ */ new Set(["modal", "confirm-dialog"]);
52499
52812
  CONTENT_NODE_SLOTS = /* @__PURE__ */ new Set([
52500
52813
  "logo",
52501
52814
  "master",
@@ -52608,7 +52921,7 @@ function runTickFrame(entityId, orderedWriters, store) {
52608
52921
  }
52609
52922
  var log3 = createLogger("almadar:ui:effects:client-handlers");
52610
52923
  function createClientEffectHandlers(options) {
52611
- const { eventBus, slotSetter, navigate, navigateBack, notify, callService, liveEntity, persistDelegated } = options;
52924
+ const { eventBus, slotSetter, navigate, navigateBack, callService, liveEntity, persistDelegated } = options;
52612
52925
  return {
52613
52926
  emit: (event, payload, source) => {
52614
52927
  const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
@@ -52664,9 +52977,6 @@ function createClientEffectHandlers(options) {
52664
52977
  }),
52665
52978
  navigateBack: navigateBack ?? (() => {
52666
52979
  log3.warn("No navigate-back handler, ignoring");
52667
- }),
52668
- notify: notify ?? ((msg, type) => {
52669
- log3.debug("notify", { type, message: msg });
52670
52980
  })
52671
52981
  };
52672
52982
  }
@@ -53037,6 +53347,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53037
53347
  sharedEntityLog.debug("useTraitStateMachine start", { traitBindingsCount: traitBindings.length, traitNames: traitBindings.map((b) => b.trait.name) });
53038
53348
  const eventBus = useEventBus();
53039
53349
  const { entities } = useEntitySchema();
53350
+ const { user: viewer } = useUser();
53040
53351
  const traitConfigsByName = options?.traitConfigsByName;
53041
53352
  const orbitalsByTrait = options?.orbitalsByTrait;
53042
53353
  const callsiteCaptureChildrenByTrait = options?.callsiteCaptureChildrenByTrait;
@@ -53350,7 +53661,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53350
53661
  },
53351
53662
  navigate: optionsRef.current?.navigate,
53352
53663
  navigateBack: optionsRef.current?.navigateBack,
53353
- notify: optionsRef.current?.notify,
53354
53664
  callService: optionsRef.current?.callService,
53355
53665
  // The canonical client `set` writes `(set @entity.X)` straight into
53356
53666
  // the trait's one live store — the same object bound below. This is
@@ -53417,8 +53727,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53417
53727
  emit: clientHandlers.emit,
53418
53728
  renderUI: clientHandlers.renderUI,
53419
53729
  navigate: clientHandlers.navigate,
53420
- navigateBack: clientHandlers.navigateBack,
53421
- notify: clientHandlers.notify
53730
+ navigateBack: clientHandlers.navigateBack
53422
53731
  };
53423
53732
  }
53424
53733
  const sharedWrites = [];
@@ -53443,7 +53752,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53443
53752
  const bindingCtx = {
53444
53753
  entity: liveEntity,
53445
53754
  payload: payload || {},
53446
- state: previousState
53755
+ state: previousState,
53756
+ ...viewer ? { user: viewer } : {}
53447
53757
  };
53448
53758
  if (callsitePayload) {
53449
53759
  bindingCtx.callsitePayload = callsitePayload;
@@ -53540,7 +53850,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53540
53850
  });
53541
53851
  }
53542
53852
  return { emitted: emittedDuringExec, serverEffectResults };
53543
- }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot, orbitalsByTrait]);
53853
+ }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot, orbitalsByTrait, viewer]);
53544
53854
  const reRenderCallsiteCaptureChildren = useCallback(async (traitName, callsitePayload, entityByTrait, log11, visited = /* @__PURE__ */ new Set()) => {
53545
53855
  const children = callsiteCaptureChildrenByTrait?.get(traitName);
53546
53856
  if (!children || children.size === 0) return;
@@ -53585,7 +53895,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53585
53895
  const guardCtx = {
53586
53896
  entity,
53587
53897
  payload: {},
53588
- state: currentState
53898
+ state: currentState,
53899
+ ...viewer ? { user: viewer } : {}
53589
53900
  };
53590
53901
  const bindingCfg = getBindingConfig(binding) ?? traitConfigsByName?.[traitName];
53591
53902
  if (bindingCfg) {
@@ -53613,7 +53924,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53613
53924
  const emitFromSharedWriter = useCallback((event, payload, source) => {
53614
53925
  const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
53615
53926
  eventBus.emit(prefixedEvent, payload, source);
53616
- }, [eventBus]);
53927
+ }, [eventBus, viewer]);
53617
53928
  useEffect(() => {
53618
53929
  const scheduler = createTickScheduler();
53619
53930
  const timedTick = (key, fn) => () => perfTimeAsync(key, fn);
@@ -53675,6 +53986,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53675
53986
  const _perfT0 = perfStart("processEvent:total");
53676
53987
  const bindings = traitBindingsRef.current;
53677
53988
  const currentManager = managerRef.current;
53989
+ if (sourceTrait === void 0 && tick === void 0) {
53990
+ for (const snap of traitSnapshotDataRef.current.values()) {
53991
+ snap.cascadeReceived = [];
53992
+ }
53993
+ }
53678
53994
  crossTraitLog.debug("processEvent:enter", () => ({
53679
53995
  event: normalizedEvent,
53680
53996
  payload: JSON.stringify(payload ?? null),
@@ -53850,6 +54166,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53850
54166
  // the verifier reads emittedEvents only.
53851
54167
  orbitalName: "",
53852
54168
  success: true,
54169
+ transitioned: true,
53853
54170
  clientEffects: effectTraces.length,
53854
54171
  dataEntities: {},
53855
54172
  emittedEvents,
@@ -54583,7 +54900,8 @@ function OrbPreview({
54583
54900
  transport,
54584
54901
  getAccessToken,
54585
54902
  initialPagePath,
54586
- isolated = false
54903
+ isolated = false,
54904
+ user = null
54587
54905
  }) {
54588
54906
  if (serverUrl && transport) {
54589
54907
  throw new Error("OrbPreview accepts serverUrl OR transport, not both");
@@ -54593,11 +54911,7 @@ function OrbPreview({
54593
54911
  const handleLocalFallback = useCallback(() => {
54594
54912
  if (localFallback) return;
54595
54913
  setLocalFallback(true);
54596
- eventBus.emit("UI:NOTIFY", {
54597
- message: "Preview server unreachable \u2014 running locally without server-side state.",
54598
- severity: "warning"
54599
- });
54600
- }, [localFallback, eventBus]);
54914
+ }, [localFallback]);
54601
54915
  const parseResult = useMemo(() => {
54602
54916
  let parsed;
54603
54917
  if (typeof schema === "string") {
@@ -54756,7 +55070,7 @@ function OrbPreview({
54756
55070
  storageKey: `almadar:navstack:${parseResult.schema.name ?? "preview"}`,
54757
55071
  children: [
54758
55072
  /* @__PURE__ */ jsx(NavStackRefBridge, { apiRef: navStackRef }),
54759
- /* @__PURE__ */ jsx(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, isolated, children: /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsx(
55073
+ /* @__PURE__ */ jsx(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, isolated, user, children: /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsx(
54760
55074
  SchemaRunner,
54761
55075
  {
54762
55076
  schema: parseResult.schema,
@@ -54931,7 +55245,7 @@ function useOrbitalPluginHost() {
54931
55245
  return { getState: ctx.getState, lastEvent: ctx.lastEvent, errors: ctx.errors };
54932
55246
  }
54933
55247
  function buildMockEffectHandlers(opts) {
54934
- const { pluginId, denySet, slotsRef, renderedSlotsRef, navigateRef, notifyRef } = opts;
55248
+ const { pluginId, denySet, slotsRef, renderedSlotsRef, navigateRef } = opts;
54935
55249
  const handlers = {
54936
55250
  renderUI: (slot, pattern, props, priority) => {
54937
55251
  if (!isUISlot(slot)) {
@@ -54951,11 +55265,6 @@ function buildMockEffectHandlers(opts) {
54951
55265
  } else if (navigateRef.current) {
54952
55266
  handlers.navigate = (path) => navigateRef.current?.(path);
54953
55267
  }
54954
- if (denySet.has("notify")) {
54955
- handlers.notify = (message, type) => log10.warn("notify:denied", { pluginId, message, type });
54956
- } else if (notifyRef.current) {
54957
- handlers.notify = (message, type) => notifyRef.current?.(message, type);
54958
- }
54959
55268
  if (denySet.has("persist")) {
54960
55269
  handlers.persist = async (action, entityType) => {
54961
55270
  log10.warn("persist:denied", { pluginId, action, entityType });
@@ -54976,7 +55285,6 @@ function PluginRuntimeMount({
54976
55285
  transport,
54977
55286
  deny,
54978
55287
  navigate,
54979
- notify,
54980
55288
  onTransition,
54981
55289
  onDispatched,
54982
55290
  onError
@@ -54988,8 +55296,6 @@ function PluginRuntimeMount({
54988
55296
  const renderedSlotsRef = useRef(/* @__PURE__ */ new Set());
54989
55297
  const navigateRef = useRef(navigate);
54990
55298
  navigateRef.current = navigate;
54991
- const notifyRef = useRef(notify);
54992
- notifyRef.current = notify;
54993
55299
  const [mockRuntime] = useState(() => {
54994
55300
  if (mode !== "mock") return void 0;
54995
55301
  return new OrbitalServerRuntime({
@@ -55000,8 +55306,7 @@ function PluginRuntimeMount({
55000
55306
  denySet: new Set(deny ?? []),
55001
55307
  slotsRef,
55002
55308
  renderedSlotsRef,
55003
- navigateRef,
55004
- notifyRef
55309
+ navigateRef
55005
55310
  })
55006
55311
  });
55007
55312
  });
@@ -55160,7 +55465,6 @@ function OrbitalPluginHost({
55160
55465
  transport,
55161
55466
  deny,
55162
55467
  navigate,
55163
- notify,
55164
55468
  onTransition,
55165
55469
  children
55166
55470
  }) {
@@ -55211,7 +55515,6 @@ function OrbitalPluginHost({
55211
55515
  transport,
55212
55516
  deny,
55213
55517
  navigate,
55214
- notify,
55215
55518
  onTransition,
55216
55519
  onDispatched: handleDispatched,
55217
55520
  onError: handleError