@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
@@ -8420,7 +8420,7 @@ var init_DialogueBubble = __esm({
8420
8420
  init_Typography();
8421
8421
  init_GameIcon();
8422
8422
  DEFAULT_PORTRAIT = {
8423
- url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
8423
+ url: "https://almadar-kflow-assets.web.app/shared/ui-winter-ski-board/default/units/hero/hero.png",
8424
8424
  role: "effect",
8425
8425
  category: "character"
8426
8426
  };
@@ -9637,6 +9637,14 @@ function createWebPainter(ctx, onAssetLoad) {
9637
9637
  ctx.drawImage(img, dest.x, dest.y, dw, dh);
9638
9638
  }
9639
9639
  },
9640
+ blitTransformed(tex, src, affine) {
9641
+ const img = imageByHandle.get(tex);
9642
+ if (!img) return;
9643
+ ctx.save();
9644
+ ctx.transform(affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]);
9645
+ ctx.drawImage(img, src.x, src.y, src.w, src.h, src.x, src.y, src.w, src.h);
9646
+ ctx.restore();
9647
+ },
9640
9648
  fillRect(x, y, w, h, style) {
9641
9649
  ctx.fillStyle = toCanvasStyle(style);
9642
9650
  ctx.fillRect(x, y, w, h);
@@ -10143,6 +10151,271 @@ var init_DrawGroup = __esm({
10143
10151
  init_registry();
10144
10152
  }
10145
10153
  });
10154
+
10155
+ // lib/skinning.ts
10156
+ function composeAffine(a, b) {
10157
+ return [
10158
+ a[0] * b[0] + a[2] * b[1],
10159
+ a[1] * b[0] + a[3] * b[1],
10160
+ a[0] * b[2] + a[2] * b[3],
10161
+ a[1] * b[2] + a[3] * b[3],
10162
+ a[0] * b[4] + a[2] * b[5] + a[4],
10163
+ a[1] * b[4] + a[3] * b[5] + a[5]
10164
+ ];
10165
+ }
10166
+ function invertAffine(m) {
10167
+ const det = m[0] * m[3] - m[1] * m[2];
10168
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return IDENTITY;
10169
+ const inv = 1 / det;
10170
+ return [
10171
+ m[3] * inv,
10172
+ -m[1] * inv,
10173
+ -m[2] * inv,
10174
+ m[0] * inv,
10175
+ (m[2] * m[5] - m[3] * m[4]) * inv,
10176
+ (m[1] * m[4] - m[0] * m[5]) * inv
10177
+ ];
10178
+ }
10179
+ function applyAffine(m, x, y) {
10180
+ return [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
10181
+ }
10182
+ function rotationAbout(pivot, degrees) {
10183
+ const r = degrees * Math.PI / 180;
10184
+ const cos = Math.cos(r);
10185
+ const sin = Math.sin(r);
10186
+ const [px, py] = pivot;
10187
+ return [cos, sin, -sin, cos, px - cos * px + sin * py, py - sin * px - cos * py];
10188
+ }
10189
+ function computeWorldMatrices(bones, pose) {
10190
+ const indexByName = /* @__PURE__ */ new Map();
10191
+ bones.forEach((b, i) => indexByName.set(b.name, i));
10192
+ const world = new Array(bones.length);
10193
+ const visiting = /* @__PURE__ */ new Set();
10194
+ const resolve = (i) => {
10195
+ const cached = world[i];
10196
+ if (cached) return cached;
10197
+ if (visiting.has(i)) return IDENTITY;
10198
+ visiting.add(i);
10199
+ const b = bones[i];
10200
+ const parentIndex = b.parent === null ? void 0 : indexByName.get(b.parent);
10201
+ const parentWorld = parentIndex === void 0 ? IDENTITY : resolve(parentIndex);
10202
+ const local = rotationAbout(b.pivot, pose[b.name] ?? 0);
10203
+ const m = composeAffine(parentWorld, local);
10204
+ visiting.delete(i);
10205
+ world[i] = m;
10206
+ return m;
10207
+ };
10208
+ return bones.map((_, i) => resolve(i));
10209
+ }
10210
+ function skinVertices(mesh, bindWorld, curWorld) {
10211
+ const skinMats = /* @__PURE__ */ new Map();
10212
+ const skinMat = (bone) => {
10213
+ let m = skinMats.get(bone);
10214
+ if (!m) {
10215
+ m = composeAffine(curWorld[bone] ?? IDENTITY, invertAffine(bindWorld[bone] ?? IDENTITY));
10216
+ skinMats.set(bone, m);
10217
+ }
10218
+ return m;
10219
+ };
10220
+ return mesh.vertices.map((v) => {
10221
+ if (v.weights.length === 0) return [v.x, v.y];
10222
+ let x = 0;
10223
+ let y = 0;
10224
+ for (const { bone, w } of v.weights) {
10225
+ const [bx, by] = applyAffine(skinMat(bone), v.x, v.y);
10226
+ x += w * bx;
10227
+ y += w * by;
10228
+ }
10229
+ return [x, y];
10230
+ });
10231
+ }
10232
+ function triangleAffine(src, dst) {
10233
+ const [s0, s1, s2] = src;
10234
+ const det = s0[0] * (s1[1] - s2[1]) + s1[0] * (s2[1] - s0[1]) + s2[0] * (s0[1] - s1[1]);
10235
+ if (!Number.isFinite(det) || Math.abs(det) < 1e-12) return null;
10236
+ const [d0, d1, d2] = dst;
10237
+ const a = (d0[0] * (s1[1] - s2[1]) + d1[0] * (s2[1] - s0[1]) + d2[0] * (s0[1] - s1[1])) / det;
10238
+ const c = (d0[0] * (s2[0] - s1[0]) + d1[0] * (s0[0] - s2[0]) + d2[0] * (s1[0] - s0[0])) / det;
10239
+ 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;
10240
+ const b = (d0[1] * (s1[1] - s2[1]) + d1[1] * (s2[1] - s0[1]) + d2[1] * (s0[1] - s1[1])) / det;
10241
+ const d = (d0[1] * (s2[0] - s1[0]) + d1[1] * (s0[0] - s2[0]) + d2[1] * (s1[0] - s0[0])) / det;
10242
+ 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;
10243
+ return [a, b, c, d, e, f3];
10244
+ }
10245
+ function isRigBundle(json) {
10246
+ return json.mesh !== void 0 || json.bones !== void 0;
10247
+ }
10248
+ function getRigBundle(url, onReady) {
10249
+ if (meshCache.has(url)) return meshCache.get(url) ?? void 0;
10250
+ meshCache.set(url, void 0);
10251
+ fetch(url).then((r) => {
10252
+ if (!r.ok) throw new Error(`rigbundle fetch failed: HTTP ${r.status}`);
10253
+ return r.json();
10254
+ }).then((json) => {
10255
+ const ok = isRigBundle(json) || Array.isArray(json.vertices);
10256
+ if (!ok) throw new Error("rigbundle payload is neither a SkinMesh nor a rigbundle");
10257
+ meshCache.set(url, json);
10258
+ onReady();
10259
+ }).catch(() => {
10260
+ meshCache.set(url, null);
10261
+ onReady();
10262
+ });
10263
+ return void 0;
10264
+ }
10265
+ function skinMeshFailed(url) {
10266
+ return meshCache.get(url) === null;
10267
+ }
10268
+ function vertexBounds(points) {
10269
+ if (points.length === 0) return null;
10270
+ let minX = Infinity;
10271
+ let minY = Infinity;
10272
+ let maxX = -Infinity;
10273
+ let maxY = -Infinity;
10274
+ for (const [x, y] of points) {
10275
+ if (x < minX) minX = x;
10276
+ if (y < minY) minY = y;
10277
+ if (x > maxX) maxX = x;
10278
+ if (y > maxY) maxY = y;
10279
+ }
10280
+ return { minX, minY, maxX, maxY };
10281
+ }
10282
+ var IDENTITY, meshCache;
10283
+ var init_skinning = __esm({
10284
+ "lib/skinning.ts"() {
10285
+ IDENTITY = [1, 0, 0, 1, 0, 0];
10286
+ meshCache = /* @__PURE__ */ new Map();
10287
+ }
10288
+ });
10289
+ function warnMissingOnce2(reason, node) {
10290
+ const key = `${reason}:${node.asset.url}:${String(node.meshUrl)}`;
10291
+ if (loggedMissing2.has(key)) return;
10292
+ loggedMissing2.add(key);
10293
+ skinnedLog.warn("draw-skinned-mesh unresolvable \u2014 painting fallback", { reason, url: node.asset.url, meshUrl: node.meshUrl });
10294
+ }
10295
+ function dominantBone(v) {
10296
+ let best = -1;
10297
+ let bestW = 0;
10298
+ for (const { bone, w } of v.weights) {
10299
+ if (w > bestW) {
10300
+ bestW = w;
10301
+ best = bone;
10302
+ }
10303
+ }
10304
+ return best;
10305
+ }
10306
+ function resolveSkinPose(node, clip) {
10307
+ const effectiveClip = clip ?? node.clip;
10308
+ if (effectiveClip && node.frame !== void 0 && effectiveClip.frames.length > 0) {
10309
+ return effectiveClip.frames[node.frame % effectiveClip.frames.length];
10310
+ }
10311
+ return node.pose ?? {};
10312
+ }
10313
+ function resolveRig(node, dctx) {
10314
+ const fetched = node.meshUrl ? getRigBundle(node.meshUrl, dctx.invalidate) : void 0;
10315
+ if (node.meshUrl && fetched === void 0) return void 0;
10316
+ const rb = fetched && isRigBundle(fetched) ? fetched : void 0;
10317
+ const mesh = node.mesh ?? rb?.mesh ?? (!rb ? fetched : void 0);
10318
+ if (!mesh) return void 0;
10319
+ const bones = node.bones.length > 0 ? node.bones : rb?.bones ?? [];
10320
+ if (bones.length === 0) return void 0;
10321
+ const clip = node.clip ?? (node.clipName ? rb?.clips?.[node.clipName] : void 0);
10322
+ return { mesh, bones, clip };
10323
+ }
10324
+ function meshHasPixelUVs(mesh) {
10325
+ const cached = pixelUVByMesh.get(mesh);
10326
+ if (cached !== void 0) return cached;
10327
+ let pixel = false;
10328
+ for (const v of mesh.vertices) {
10329
+ if (v.u < 0 || v.u > 1 || v.v < 0 || v.v > 1) {
10330
+ pixel = true;
10331
+ break;
10332
+ }
10333
+ }
10334
+ pixelUVByMesh.set(mesh, pixel);
10335
+ return pixel;
10336
+ }
10337
+ function paintMeshPass(painter, node, bones, mesh, tex, dctx, pose, opacity) {
10338
+ const bindWorld = computeWorldMatrices(bones, {});
10339
+ const curWorld = computeWorldMatrices(bones, pose);
10340
+ const skinned = skinVertices(mesh, bindWorld, curWorld);
10341
+ const origin = dctx.projector.project(node.position);
10342
+ const tw = dctx.projector.tileWidth;
10343
+ painter.save();
10344
+ if (opacity !== 1) painter.setAlpha(opacity);
10345
+ for (const [i0, i1, i2] of mesh.triangles) {
10346
+ const v0 = mesh.vertices[i0];
10347
+ const v1 = mesh.vertices[i1];
10348
+ const v2 = mesh.vertices[i2];
10349
+ const p0 = skinned[i0];
10350
+ const p1 = skinned[i1];
10351
+ const p2 = skinned[i2];
10352
+ if (!v0 || !v1 || !v2 || !p0 || !p1 || !p2) continue;
10353
+ const dst = [
10354
+ [origin.x + p0[0] * tw, origin.y + p0[1] * tw],
10355
+ [origin.x + p1[0] * tw, origin.y + p1[1] * tw],
10356
+ [origin.x + p2[0] * tw, origin.y + p2[1] * tw]
10357
+ ];
10358
+ if (node.weightsOverlay || !tex) {
10359
+ if (!node.weightsOverlay) continue;
10360
+ const bone = dominantBone(v0);
10361
+ painter.fillPoly(
10362
+ dst.map(([x, y]) => ({ x, y })),
10363
+ WEIGHT_PALETTE[(bone % WEIGHT_PALETTE.length + WEIGHT_PALETTE.length) % WEIGHT_PALETTE.length]
10364
+ );
10365
+ continue;
10366
+ }
10367
+ const pixelUV = meshHasPixelUVs(mesh);
10368
+ const uv = pixelUV ? [[v0.u, v0.v], [v1.u, v1.v], [v2.u, v2.v]] : [
10369
+ [v0.u * tex.width, v0.v * tex.height],
10370
+ [v1.u * tex.width, v1.v * tex.height],
10371
+ [v2.u * tex.width, v2.v * tex.height]
10372
+ ];
10373
+ const affine = triangleAffine(uv, dst);
10374
+ if (!affine) continue;
10375
+ painter.save();
10376
+ painter.clipPath(`M ${dst[0][0]} ${dst[0][1]} L ${dst[1][0]} ${dst[1][1]} L ${dst[2][0]} ${dst[2][1]} Z`);
10377
+ painter.blitTransformed(tex, { x: 0, y: 0, w: tex.width, h: tex.height }, affine);
10378
+ painter.restore();
10379
+ }
10380
+ painter.restore();
10381
+ }
10382
+ function DrawSkinnedMesh(props) {
10383
+ const register = React87.useContext(DrawableRegistryContext);
10384
+ if (register) register({ ...props, type: "draw-skinned-mesh" });
10385
+ return null;
10386
+ }
10387
+ var skinnedLog, loggedMissing2, WEIGHT_PALETTE, pixelUVByMesh, paintSkinnedMesh;
10388
+ var init_DrawSkinnedMesh = __esm({
10389
+ "components/game/atoms/DrawSkinnedMesh.tsx"() {
10390
+ "use client";
10391
+ init_imageCache();
10392
+ init_contract();
10393
+ init_registry();
10394
+ init_skinning();
10395
+ skinnedLog = logger.createLogger("almadar:ui:draw-skinned-mesh");
10396
+ loggedMissing2 = /* @__PURE__ */ new Set();
10397
+ WEIGHT_PALETTE = Array.from({ length: 10 }, (_, i) => `hsl(${i * 36 % 360}, 70%, 55%)`);
10398
+ pixelUVByMesh = /* @__PURE__ */ new WeakMap();
10399
+ paintSkinnedMesh = (painter, node, dctx) => {
10400
+ if (!isValidScenePos(node.position)) return;
10401
+ const rig = resolveRig(node, dctx);
10402
+ if (!rig) {
10403
+ if (node.meshUrl && skinMeshFailed(node.meshUrl)) warnMissingOnce2("mesh-failed", node);
10404
+ else if (!node.mesh && !node.meshUrl) warnMissingOnce2("mesh-missing", node);
10405
+ return;
10406
+ }
10407
+ const tex = node.weightsOverlay ? null : painter.resolveTexture(node.asset.url);
10408
+ if (!node.weightsOverlay && !tex) {
10409
+ if (getImageStatus(node.asset.url) === "failed") warnMissingOnce2("texture-failed", node);
10410
+ return;
10411
+ }
10412
+ if (node.ghost && rig.clip && rig.clip.frames.length > 0) {
10413
+ paintMeshPass(painter, node, rig.bones, rig.mesh, tex, dctx, rig.clip.frames[node.ghost.frame % rig.clip.frames.length], node.ghost.opacity);
10414
+ }
10415
+ paintMeshPass(painter, node, rig.bones, rig.mesh, tex, dctx, resolveSkinPose(node, rig.clip), node.opacity ?? 1);
10416
+ };
10417
+ }
10418
+ });
10146
10419
  function applyMeshAnimation(node, timeMs) {
10147
10420
  const anim = node.animation;
10148
10421
  if (!anim || !(anim.durationMs > 0) || anim.keyframes.length === 0) return null;
@@ -10467,6 +10740,9 @@ function paintDrawable(painter, node, dctx) {
10467
10740
  case "draw-mesh":
10468
10741
  warnUnsupported2d("draw-mesh");
10469
10742
  break;
10743
+ case "draw-skinned-mesh":
10744
+ paintSkinnedMesh(painter, node, dctx);
10745
+ break;
10470
10746
  case "draw-sprite-layer":
10471
10747
  paintSpriteLayer(painter, node, dctx);
10472
10748
  break;
@@ -10491,6 +10767,7 @@ var init_paintDispatch = __esm({
10491
10767
  init_DrawShape();
10492
10768
  init_DrawText();
10493
10769
  init_DrawGroup();
10770
+ init_DrawSkinnedMesh();
10494
10771
  init_DrawMesh();
10495
10772
  init_DrawSpriteLayer();
10496
10773
  init_DrawShapeLayer();
@@ -10511,6 +10788,21 @@ function shapeDrawnItem(n) {
10511
10788
  if (n.shape !== "rect") return { pos: n.position, id: n.id };
10512
10789
  return { pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height, rotation: n.rotate };
10513
10790
  }
10791
+ function skinnedMeshDrawnItem(n) {
10792
+ const mesh = n.mesh;
10793
+ if (!mesh || n.bones.length === 0) return { pos: n.position, id: n.id };
10794
+ const bindWorld = computeWorldMatrices(n.bones, {});
10795
+ const curWorld = computeWorldMatrices(n.bones, resolveSkinPose(n));
10796
+ const bounds = vertexBounds(skinVertices(mesh, bindWorld, curWorld));
10797
+ if (!bounds) return { pos: n.position, id: n.id };
10798
+ return {
10799
+ pos: { ...n.position, x: n.position.x + bounds.minX, y: n.position.y + bounds.minY },
10800
+ id: n.id,
10801
+ anchor: "top-left",
10802
+ width: bounds.maxX - bounds.minX,
10803
+ height: bounds.maxY - bounds.minY
10804
+ };
10805
+ }
10514
10806
  function collectDrawnItems(nodes) {
10515
10807
  const out = [];
10516
10808
  for (const n of nodes) {
@@ -10521,6 +10813,9 @@ function collectDrawnItems(nodes) {
10521
10813
  case "draw-shape":
10522
10814
  if (isValidScenePos(n.position)) out.push(shapeDrawnItem(n));
10523
10815
  break;
10816
+ case "draw-skinned-mesh":
10817
+ if (isValidScenePos(n.position)) out.push(skinnedMeshDrawnItem(n));
10818
+ break;
10524
10819
  case "draw-text":
10525
10820
  case "draw-group":
10526
10821
  case "draw-mesh":
@@ -10588,6 +10883,8 @@ function rotatePoint(p, center, radians) {
10588
10883
  var init_hitTest = __esm({
10589
10884
  "lib/drawable/hitTest.ts"() {
10590
10885
  init_contract();
10886
+ init_DrawSkinnedMesh();
10887
+ init_skinning();
10591
10888
  }
10592
10889
  });
10593
10890
  function normalizeBackdrop(bg) {
@@ -11777,7 +12074,7 @@ var init_StateIndicator = __esm({
11777
12074
  init_cn();
11778
12075
  init_GameIcon();
11779
12076
  DEFAULT_ASSET_URL = {
11780
- url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
12077
+ url: "https://almadar-kflow-assets.web.app/shared/ui-topdown-dungeon-board/default/features/chest/chest.png",
11781
12078
  role: "ui",
11782
12079
  category: "state"
11783
12080
  };
@@ -15744,7 +16041,6 @@ var init_avl_atom_types = __esm({
15744
16041
  "persist": "data",
15745
16042
  "fetch": "data",
15746
16043
  "emit": "communication",
15747
- "notify": "communication",
15748
16044
  "call-service": "communication",
15749
16045
  "spawn": "lifecycle",
15750
16046
  "despawn": "lifecycle",
@@ -15892,12 +16188,6 @@ function effectIcon(type, x, y, s, color) {
15892
16188
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: x - s, y1: y, x2: x + s * 0.6, y2: y, stroke: color, strokeWidth: 1.5 }),
15893
16189
  /* @__PURE__ */ jsxRuntime.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" })
15894
16190
  ] });
15895
- case "notify":
15896
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
15897
- /* @__PURE__ */ jsxRuntime.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 }),
15898
- /* @__PURE__ */ jsxRuntime.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 }),
15899
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x, cy: y + s * 0.7, r: s * 0.2, fill: color })
15900
- ] });
15901
16191
  case "call-service":
15902
16192
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
15903
16193
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: x - s, y1: y - s * 0.3, x2: x + s, y2: y - s * 0.3, stroke: color, strokeWidth: 1.5 }),
@@ -21101,9 +21391,6 @@ function getEffectSummary(effects) {
21101
21391
  case "emit":
21102
21392
  summaries.push(`\u2191 ${effect[1] || "event"}`);
21103
21393
  break;
21104
- case "notify":
21105
- summaries.push(`\u{1F4E7} ${effect[1] || ""}`);
21106
- break;
21107
21394
  case "persist":
21108
21395
  summaries.push(`\u{1F4BE} ${effect[1] || "save"}`);
21109
21396
  break;
@@ -21129,7 +21416,7 @@ function extractOutputsFromTransitions(transitions) {
21129
21416
  t.effects.forEach((effect) => {
21130
21417
  if (Array.isArray(effect)) {
21131
21418
  const op = effect[0];
21132
- if (["emit", "notify", "persist", "navigate", "call-service"].includes(op)) {
21419
+ if (["emit", "persist", "navigate", "call-service"].includes(op)) {
21133
21420
  if (isArraySExpr(effect)) {
21134
21421
  const humanText = formatSExprEffectToDomain(effect);
21135
21422
  outputs.add(humanText);
@@ -28072,7 +28359,9 @@ function DataGrid({
28072
28359
  const cardClickAction = actionDefs.find((a) => a.variant !== "danger");
28073
28360
  const handleCardClick = cardClickAction ? (itemData) => () => fireAction(cardClickAction, itemData) : void 0;
28074
28361
  const stopCardClick = handleCardClick ? (e) => e.stopPropagation() : void 0;
28075
- const hasRenderProp = typeof children === "function";
28362
+ const renderItemFn = typeof schemaRenderItem === "function" ? schemaRenderItem : void 0;
28363
+ const itemRenderer = typeof children === "function" ? children : renderItemFn;
28364
+ const hasRenderProp = typeof itemRenderer === "function";
28076
28365
  React87.useEffect(() => {
28077
28366
  if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
28078
28367
  const schemaArr = Array.isArray(schemaRenderItem) ? schemaRenderItem : null;
@@ -28146,7 +28435,7 @@ function DataGrid({
28146
28435
  onClick: handleCardClick?.(itemData),
28147
28436
  className: cn("relative group/rowactions", handleCardClick && "cursor-pointer", isSelected && "ring-2 ring-primary rounded-lg"),
28148
28437
  children: [
28149
- children(itemData, index),
28438
+ itemRenderer(itemData, index),
28150
28439
  actionDefs.length > 0 && /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs(HStack, { gap: "xs", className: "rounded-md border border-border bg-card/95 backdrop-blur-sm shadow-sm p-0.5", children: [
28151
28440
  inlineCardActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
28152
28441
  Button,
@@ -28479,7 +28768,9 @@ function DataList({
28479
28768
  );
28480
28769
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
28481
28770
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
28482
- const hasRenderProp = typeof children === "function";
28771
+ const renderItemFn = typeof schemaRenderItem === "function" ? schemaRenderItem : void 0;
28772
+ const itemRenderer = typeof children === "function" ? children : renderItemFn;
28773
+ const hasRenderProp = typeof itemRenderer === "function";
28483
28774
  React87__namespace.default.useEffect(() => {
28484
28775
  const renderItemTypeOf = typeof schemaRenderItem;
28485
28776
  const childrenTypeOf = typeof children;
@@ -28697,7 +28988,7 @@ function DataList({
28697
28988
  const actions = renderItemActions(itemData);
28698
28989
  return wrapDnd(
28699
28990
  /* @__PURE__ */ jsxRuntime.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: [
28700
- children(itemData, index),
28991
+ itemRenderer(itemData, index),
28701
28992
  actions && /* @__PURE__ */ jsxRuntime.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: [
28702
28993
  /* @__PURE__ */ jsxRuntime.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 }),
28703
28994
  /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(
@@ -35071,7 +35362,7 @@ function TableView({
35071
35362
  columns,
35072
35363
  fields,
35073
35364
  itemActions,
35074
- maxInlineActions: _maxInlineActions,
35365
+ maxInlineActions,
35075
35366
  itemClickEvent = "",
35076
35367
  selectable = false,
35077
35368
  selectEvent,
@@ -35104,6 +35395,12 @@ function TableView({
35104
35395
  const [localSelected, setLocalSelected] = React87__namespace.default.useState(/* @__PURE__ */ new Set());
35105
35396
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
35106
35397
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
35398
+ const inlineActions = maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : [];
35399
+ const overflowActions = maxInlineActions != null ? actionDefs.slice(maxInlineActions) : actionDefs;
35400
+ const fireAction = (action, row) => eventBus.emit(`UI:${action.event}`, {
35401
+ id: row.id,
35402
+ row
35403
+ });
35107
35404
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
35108
35405
  const dnd = useDataDnd({
35109
35406
  items: allDataRaw,
@@ -35279,7 +35576,7 @@ function TableView({
35279
35576
  }
35280
35577
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format) }) }, col.key);
35281
35578
  }),
35282
- hasActions && /* @__PURE__ */ jsxRuntime.jsx(
35579
+ hasActions && /* @__PURE__ */ jsxRuntime.jsxs(
35283
35580
  HStack,
35284
35581
  {
35285
35582
  gap: "xs",
@@ -35293,23 +35590,38 @@ function TableView({
35293
35590
  "border-l border-[var(--color-border)]",
35294
35591
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
35295
35592
  ),
35296
- children: /* @__PURE__ */ jsxRuntime.jsx(
35297
- Menu,
35298
- {
35299
- position: "bottom-end",
35300
- trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", "data-row-id": String(row.id), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
35301
- items: actionDefs.map((action) => ({
35302
- label: action.label,
35303
- icon: action.icon,
35304
- event: action.event,
35305
- variant: action.variant === "danger" ? "danger" : "default",
35306
- onClick: () => eventBus.emit(`UI:${action.event}`, {
35307
- id: row.id,
35308
- row
35309
- })
35310
- }))
35311
- }
35312
- )
35593
+ children: [
35594
+ inlineActions.map((action) => /* @__PURE__ */ jsxRuntime.jsxs(
35595
+ Button,
35596
+ {
35597
+ variant: action.variant ?? "ghost",
35598
+ size: "sm",
35599
+ onClick: () => fireAction(action, row),
35600
+ "data-testid": `action-${action.event}`,
35601
+ "data-row-id": String(row.id),
35602
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
35603
+ children: [
35604
+ action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
35605
+ action.label
35606
+ ]
35607
+ },
35608
+ action.event
35609
+ )),
35610
+ overflowActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
35611
+ Menu,
35612
+ {
35613
+ position: "bottom-end",
35614
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", "data-row-id": String(row.id), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
35615
+ items: overflowActions.map((action) => ({
35616
+ label: action.label,
35617
+ icon: action.icon,
35618
+ event: action.event,
35619
+ variant: action.variant === "danger" ? "danger" : "default",
35620
+ onClick: () => fireAction(action, row)
35621
+ }))
35622
+ }
35623
+ )
35624
+ ]
35313
35625
  }
35314
35626
  )
35315
35627
  ]
@@ -51022,6 +51334,7 @@ var init_component_registry_generated = __esm({
51022
51334
  init_DrawMesh();
51023
51335
  init_DrawShape();
51024
51336
  init_DrawShapeLayer();
51337
+ init_DrawSkinnedMesh();
51025
51338
  init_DrawSprite();
51026
51339
  init_DrawSpriteLayer();
51027
51340
  init_DrawText();
@@ -51300,6 +51613,7 @@ var init_component_registry_generated = __esm({
51300
51613
  "DrawMesh": DrawMesh,
51301
51614
  "DrawShape": DrawShape,
51302
51615
  "DrawShapeLayer": DrawShapeLayer,
51616
+ "DrawSkinnedMesh": DrawSkinnedMesh,
51303
51617
  "DrawSprite": DrawSprite,
51304
51618
  "DrawSpriteLayer": DrawSpriteLayer,
51305
51619
  "DrawText": DrawText,
@@ -51628,7 +51942,7 @@ function renderContainedPortal(t, slot, content, onDismiss) {
51628
51942
  const slotId = `slot-${slot}`;
51629
51943
  switch (slot) {
51630
51944
  case "modal":
51631
- if (SELF_OVERLAY_PATTERNS.has(content.pattern)) {
51945
+ if (patterns.SELF_OVERLAY_PATTERN_TYPES.has(content.pattern)) {
51632
51946
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { id: slotId, className: "contents", children: slotContent });
51633
51947
  }
51634
51948
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -51971,7 +52285,7 @@ function CompiledPortal({ slot, className, pattern, sourceTrait, children }) {
51971
52285
  children
51972
52286
  }
51973
52287
  );
51974
- wrapper = pattern !== void 0 && SELF_OVERLAY_PATTERNS.has(pattern) ? innerContent : /* @__PURE__ */ jsxRuntime.jsx(Modal, { isOpen: true, onClose: handleDismiss, showCloseButton: true, size: "lg", children: innerContent });
52288
+ wrapper = pattern !== void 0 && patterns.SELF_OVERLAY_PATTERN_TYPES.has(pattern) ? innerContent : /* @__PURE__ */ jsxRuntime.jsx(Modal, { isOpen: true, onClose: handleDismiss, showCloseButton: true, size: "lg", children: innerContent });
51975
52289
  break;
51976
52290
  }
51977
52291
  case "drawer":
@@ -52031,7 +52345,7 @@ function SlotPortal({
52031
52345
  let wrapper;
52032
52346
  switch (slot) {
52033
52347
  case "modal":
52034
- wrapper = SELF_OVERLAY_PATTERNS.has(content.pattern) ? /* @__PURE__ */ jsxRuntime.jsx(Box, { id: slotId, children: slotContent }) : /* @__PURE__ */ jsxRuntime.jsx(
52348
+ wrapper = patterns.SELF_OVERLAY_PATTERN_TYPES.has(content.pattern) ? /* @__PURE__ */ jsxRuntime.jsx(Box, { id: slotId, children: slotContent }) : /* @__PURE__ */ jsxRuntime.jsx(
52035
52349
  Modal,
52036
52350
  {
52037
52351
  isOpen: true,
@@ -52538,7 +52852,7 @@ function UISlotRenderer({
52538
52852
  }
52539
52853
  return wrapped;
52540
52854
  }
52541
- var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, SELF_OVERLAY_PATTERNS, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
52855
+ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
52542
52856
  var init_UISlotRenderer = __esm({
52543
52857
  "components/core/organisms/UISlotRenderer.tsx"() {
52544
52858
  "use client";
@@ -52569,7 +52883,6 @@ var init_UISlotRenderer = __esm({
52569
52883
  modal: "form",
52570
52884
  drawer: "form"
52571
52885
  };
52572
- SELF_OVERLAY_PATTERNS = /* @__PURE__ */ new Set(["modal", "confirm-dialog"]);
52573
52886
  CONTENT_NODE_SLOTS = /* @__PURE__ */ new Set([
52574
52887
  "logo",
52575
52888
  "master",
@@ -52682,7 +52995,7 @@ function runTickFrame(entityId, orderedWriters, store) {
52682
52995
  }
52683
52996
  var log3 = logger.createLogger("almadar:ui:effects:client-handlers");
52684
52997
  function createClientEffectHandlers(options) {
52685
- const { eventBus, slotSetter, navigate, navigateBack, notify, callService, liveEntity, persistDelegated } = options;
52998
+ const { eventBus, slotSetter, navigate, navigateBack, callService, liveEntity, persistDelegated } = options;
52686
52999
  return {
52687
53000
  emit: (event, payload, source) => {
52688
53001
  const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
@@ -52738,9 +53051,6 @@ function createClientEffectHandlers(options) {
52738
53051
  }),
52739
53052
  navigateBack: navigateBack ?? (() => {
52740
53053
  log3.warn("No navigate-back handler, ignoring");
52741
- }),
52742
- notify: notify ?? ((msg, type) => {
52743
- log3.debug("notify", { type, message: msg });
52744
53054
  })
52745
53055
  };
52746
53056
  }
@@ -53111,6 +53421,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53111
53421
  sharedEntityLog.debug("useTraitStateMachine start", { traitBindingsCount: traitBindings.length, traitNames: traitBindings.map((b) => b.trait.name) });
53112
53422
  const eventBus = useEventBus();
53113
53423
  const { entities } = providers.useEntitySchema();
53424
+ const { user: viewer } = providers.useUser();
53114
53425
  const traitConfigsByName = options?.traitConfigsByName;
53115
53426
  const orbitalsByTrait = options?.orbitalsByTrait;
53116
53427
  const callsiteCaptureChildrenByTrait = options?.callsiteCaptureChildrenByTrait;
@@ -53424,7 +53735,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53424
53735
  },
53425
53736
  navigate: optionsRef.current?.navigate,
53426
53737
  navigateBack: optionsRef.current?.navigateBack,
53427
- notify: optionsRef.current?.notify,
53428
53738
  callService: optionsRef.current?.callService,
53429
53739
  // The canonical client `set` writes `(set @entity.X)` straight into
53430
53740
  // the trait's one live store — the same object bound below. This is
@@ -53491,8 +53801,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53491
53801
  emit: clientHandlers.emit,
53492
53802
  renderUI: clientHandlers.renderUI,
53493
53803
  navigate: clientHandlers.navigate,
53494
- navigateBack: clientHandlers.navigateBack,
53495
- notify: clientHandlers.notify
53804
+ navigateBack: clientHandlers.navigateBack
53496
53805
  };
53497
53806
  }
53498
53807
  const sharedWrites = [];
@@ -53517,7 +53826,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53517
53826
  const bindingCtx = {
53518
53827
  entity: liveEntity,
53519
53828
  payload: payload || {},
53520
- state: previousState
53829
+ state: previousState,
53830
+ ...viewer ? { user: viewer } : {}
53521
53831
  };
53522
53832
  if (callsitePayload) {
53523
53833
  bindingCtx.callsitePayload = callsitePayload;
@@ -53614,7 +53924,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53614
53924
  });
53615
53925
  }
53616
53926
  return { emitted: emittedDuringExec, serverEffectResults };
53617
- }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot, orbitalsByTrait]);
53927
+ }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot, orbitalsByTrait, viewer]);
53618
53928
  const reRenderCallsiteCaptureChildren = React87.useCallback(async (traitName, callsitePayload, entityByTrait, log11, visited = /* @__PURE__ */ new Set()) => {
53619
53929
  const children = callsiteCaptureChildrenByTrait?.get(traitName);
53620
53930
  if (!children || children.size === 0) return;
@@ -53659,7 +53969,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53659
53969
  const guardCtx = {
53660
53970
  entity,
53661
53971
  payload: {},
53662
- state: currentState
53972
+ state: currentState,
53973
+ ...viewer ? { user: viewer } : {}
53663
53974
  };
53664
53975
  const bindingCfg = getBindingConfig(binding) ?? traitConfigsByName?.[traitName];
53665
53976
  if (bindingCfg) {
@@ -53687,7 +53998,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53687
53998
  const emitFromSharedWriter = React87.useCallback((event, payload, source) => {
53688
53999
  const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
53689
54000
  eventBus.emit(prefixedEvent, payload, source);
53690
- }, [eventBus]);
54001
+ }, [eventBus, viewer]);
53691
54002
  React87.useEffect(() => {
53692
54003
  const scheduler = runtime.createTickScheduler();
53693
54004
  const timedTick = (key, fn) => () => ui.perfTimeAsync(key, fn);
@@ -53749,6 +54060,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53749
54060
  const _perfT0 = ui.perfStart("processEvent:total");
53750
54061
  const bindings = traitBindingsRef.current;
53751
54062
  const currentManager = managerRef.current;
54063
+ if (sourceTrait === void 0 && tick === void 0) {
54064
+ for (const snap of traitSnapshotDataRef.current.values()) {
54065
+ snap.cascadeReceived = [];
54066
+ }
54067
+ }
53752
54068
  crossTraitLog.debug("processEvent:enter", () => ({
53753
54069
  event: normalizedEvent,
53754
54070
  payload: JSON.stringify(payload ?? null),
@@ -53924,6 +54240,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
53924
54240
  // the verifier reads emittedEvents only.
53925
54241
  orbitalName: "",
53926
54242
  success: true,
54243
+ transitioned: true,
53927
54244
  clientEffects: effectTraces.length,
53928
54245
  dataEntities: {},
53929
54246
  emittedEvents,
@@ -54657,7 +54974,8 @@ function OrbPreview({
54657
54974
  transport,
54658
54975
  getAccessToken,
54659
54976
  initialPagePath,
54660
- isolated = false
54977
+ isolated = false,
54978
+ user = null
54661
54979
  }) {
54662
54980
  if (serverUrl && transport) {
54663
54981
  throw new Error("OrbPreview accepts serverUrl OR transport, not both");
@@ -54667,11 +54985,7 @@ function OrbPreview({
54667
54985
  const handleLocalFallback = React87.useCallback(() => {
54668
54986
  if (localFallback) return;
54669
54987
  setLocalFallback(true);
54670
- eventBus.emit("UI:NOTIFY", {
54671
- message: "Preview server unreachable \u2014 running locally without server-side state.",
54672
- severity: "warning"
54673
- });
54674
- }, [localFallback, eventBus]);
54988
+ }, [localFallback]);
54675
54989
  const parseResult = React87.useMemo(() => {
54676
54990
  let parsed;
54677
54991
  if (typeof schema === "string") {
@@ -54830,7 +55144,7 @@ function OrbPreview({
54830
55144
  storageKey: `almadar:navstack:${parseResult.schema.name ?? "preview"}`,
54831
55145
  children: [
54832
55146
  /* @__PURE__ */ jsxRuntime.jsx(NavStackRefBridge, { apiRef: navStackRef }),
54833
- /* @__PURE__ */ jsxRuntime.jsx(providers.OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, isolated, children: /* @__PURE__ */ jsxRuntime.jsx(context.UISlotProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
55147
+ /* @__PURE__ */ jsxRuntime.jsx(providers.OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, isolated, user, children: /* @__PURE__ */ jsxRuntime.jsx(context.UISlotProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
54834
55148
  SchemaRunner,
54835
55149
  {
54836
55150
  schema: parseResult.schema,
@@ -55005,7 +55319,7 @@ function useOrbitalPluginHost() {
55005
55319
  return { getState: ctx.getState, lastEvent: ctx.lastEvent, errors: ctx.errors };
55006
55320
  }
55007
55321
  function buildMockEffectHandlers(opts) {
55008
- const { pluginId, denySet, slotsRef, renderedSlotsRef, navigateRef, notifyRef } = opts;
55322
+ const { pluginId, denySet, slotsRef, renderedSlotsRef, navigateRef } = opts;
55009
55323
  const handlers = {
55010
55324
  renderUI: (slot, pattern, props, priority) => {
55011
55325
  if (!isUISlot(slot)) {
@@ -55025,11 +55339,6 @@ function buildMockEffectHandlers(opts) {
55025
55339
  } else if (navigateRef.current) {
55026
55340
  handlers.navigate = (path) => navigateRef.current?.(path);
55027
55341
  }
55028
- if (denySet.has("notify")) {
55029
- handlers.notify = (message, type) => log10.warn("notify:denied", { pluginId, message, type });
55030
- } else if (notifyRef.current) {
55031
- handlers.notify = (message, type) => notifyRef.current?.(message, type);
55032
- }
55033
55342
  if (denySet.has("persist")) {
55034
55343
  handlers.persist = async (action, entityType) => {
55035
55344
  log10.warn("persist:denied", { pluginId, action, entityType });
@@ -55050,7 +55359,6 @@ function PluginRuntimeMount({
55050
55359
  transport,
55051
55360
  deny,
55052
55361
  navigate,
55053
- notify,
55054
55362
  onTransition,
55055
55363
  onDispatched,
55056
55364
  onError
@@ -55062,8 +55370,6 @@ function PluginRuntimeMount({
55062
55370
  const renderedSlotsRef = React87.useRef(/* @__PURE__ */ new Set());
55063
55371
  const navigateRef = React87.useRef(navigate);
55064
55372
  navigateRef.current = navigate;
55065
- const notifyRef = React87.useRef(notify);
55066
- notifyRef.current = notify;
55067
55373
  const [mockRuntime] = React87.useState(() => {
55068
55374
  if (mode !== "mock") return void 0;
55069
55375
  return new OrbitalServerRuntime.OrbitalServerRuntime({
@@ -55074,8 +55380,7 @@ function PluginRuntimeMount({
55074
55380
  denySet: new Set(deny ?? []),
55075
55381
  slotsRef,
55076
55382
  renderedSlotsRef,
55077
- navigateRef,
55078
- notifyRef
55383
+ navigateRef
55079
55384
  })
55080
55385
  });
55081
55386
  });
@@ -55234,7 +55539,6 @@ function OrbitalPluginHost({
55234
55539
  transport,
55235
55540
  deny,
55236
55541
  navigate,
55237
- notify,
55238
55542
  onTransition,
55239
55543
  children
55240
55544
  }) {
@@ -55285,7 +55589,6 @@ function OrbitalPluginHost({
55285
55589
  transport,
55286
55590
  deny,
55287
55591
  navigate,
55288
- notify,
55289
55592
  onTransition,
55290
55593
  onDispatched: handleDispatched,
55291
55594
  onError: handleError