@almadar/ui 5.139.0 → 5.140.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.
@@ -15632,6 +15632,12 @@ function createWebPainter(ctx, onAssetLoad) {
15632
15632
  for (let i = 1; i < points.length; i++) ctx.lineTo(points[i].x, points[i].y);
15633
15633
  if (closed) ctx.closePath();
15634
15634
  };
15635
+ const toCanvasStyle = (style) => {
15636
+ if (typeof style === "string") return style;
15637
+ const g = style.kind === "linear" ? ctx.createLinearGradient(style.x1, style.y1, style.x2, style.y2) : ctx.createRadialGradient(style.cx, style.cy, 0, style.cx, style.cy, style.r);
15638
+ for (const stop of style.stops) g.addColorStop(stop.offset, stop.color);
15639
+ return g;
15640
+ };
15635
15641
  return {
15636
15642
  setViewport(width, height, dpr) {
15637
15643
  vw = width;
@@ -15685,47 +15691,47 @@ function createWebPainter(ctx, onAssetLoad) {
15685
15691
  ctx.drawImage(img, dest.x, dest.y, dw, dh);
15686
15692
  }
15687
15693
  },
15688
- fillRect(x, y, w, h, color) {
15689
- ctx.fillStyle = color;
15694
+ fillRect(x, y, w, h, style) {
15695
+ ctx.fillStyle = toCanvasStyle(style);
15690
15696
  ctx.fillRect(x, y, w, h);
15691
15697
  },
15692
- strokeRect(x, y, w, h, color, lineWidth = 1) {
15693
- ctx.strokeStyle = color;
15698
+ strokeRect(x, y, w, h, style, lineWidth = 1) {
15699
+ ctx.strokeStyle = toCanvasStyle(style);
15694
15700
  ctx.lineWidth = lineWidth;
15695
15701
  ctx.strokeRect(x, y, w, h);
15696
15702
  },
15697
- fillPoly(points, color) {
15703
+ fillPoly(points, style) {
15698
15704
  if (points.length === 0) return;
15699
15705
  tracePoly(points, true);
15700
- ctx.fillStyle = color;
15706
+ ctx.fillStyle = toCanvasStyle(style);
15701
15707
  ctx.fill();
15702
15708
  },
15703
- strokePoly(points, color, lineWidth = 1, closed = false) {
15709
+ strokePoly(points, style, lineWidth = 1, closed = false) {
15704
15710
  if (points.length === 0) return;
15705
15711
  tracePoly(points, closed);
15706
- ctx.strokeStyle = color;
15712
+ ctx.strokeStyle = toCanvasStyle(style);
15707
15713
  ctx.lineWidth = lineWidth;
15708
15714
  ctx.stroke();
15709
15715
  },
15710
- fillEllipse(cx, cy, rx, ry, color) {
15716
+ fillEllipse(cx, cy, rx, ry, style) {
15711
15717
  ctx.beginPath();
15712
15718
  ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
15713
- ctx.fillStyle = color;
15719
+ ctx.fillStyle = toCanvasStyle(style);
15714
15720
  ctx.fill();
15715
15721
  },
15716
- strokeEllipse(cx, cy, rx, ry, color, lineWidth = 1) {
15722
+ strokeEllipse(cx, cy, rx, ry, style, lineWidth = 1) {
15717
15723
  ctx.beginPath();
15718
15724
  ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
15719
- ctx.strokeStyle = color;
15725
+ ctx.strokeStyle = toCanvasStyle(style);
15720
15726
  ctx.lineWidth = lineWidth;
15721
15727
  ctx.stroke();
15722
15728
  },
15723
- fillPath(d, color) {
15724
- ctx.fillStyle = color;
15729
+ fillPath(d, style) {
15730
+ ctx.fillStyle = toCanvasStyle(style);
15725
15731
  ctx.fill(new Path2D(d));
15726
15732
  },
15727
- strokePath(d, color, lineWidth = 1) {
15728
- ctx.strokeStyle = color;
15733
+ strokePath(d, style, lineWidth = 1) {
15734
+ ctx.strokeStyle = toCanvasStyle(style);
15729
15735
  ctx.lineWidth = lineWidth;
15730
15736
  ctx.stroke(new Path2D(d));
15731
15737
  },
@@ -15962,6 +15968,84 @@ var init_registry = __esm({
15962
15968
  DrawableRegistryContext = createContext(null);
15963
15969
  }
15964
15970
  });
15971
+ function isAnimatedShape(node) {
15972
+ return Boolean(node.animation && node.animation.durationMs > 0 && node.animation.keyframes.length > 0);
15973
+ }
15974
+ function applyShapeAnimation(node, timeMs) {
15975
+ const anim = node.animation;
15976
+ if (!anim || !(anim.durationMs > 0) || anim.keyframes.length === 0) return node;
15977
+ const frames = [...anim.keyframes].sort((a, b) => a.at - b.at);
15978
+ const cycle = timeMs / anim.durationMs;
15979
+ const t = anim.loop === false ? Math.min(cycle, 1) : cycle - Math.floor(cycle);
15980
+ const out = { ...node };
15981
+ const trackValue = (key) => {
15982
+ const defined = frames.filter((f3) => f3[key] !== void 0);
15983
+ if (defined.length === 0) return void 0;
15984
+ let prev;
15985
+ let next;
15986
+ for (const f3 of defined) {
15987
+ if (f3.at <= t) prev = f3;
15988
+ else if (!next) next = f3;
15989
+ }
15990
+ if (!prev) return defined[0][key];
15991
+ if (!next) return prev[key];
15992
+ const span = next.at - prev.at;
15993
+ const k = span > 0 ? (t - prev.at) / span : 1;
15994
+ const a = prev[key];
15995
+ const b = next[key];
15996
+ if (typeof a === "number" && typeof b === "number") return lerp(a, b, k);
15997
+ return a;
15998
+ };
15999
+ for (const key of NUMERIC_TRACKS) {
16000
+ const v = trackValue(key);
16001
+ if (v !== void 0) out[key] = v;
16002
+ }
16003
+ const fill = trackValue("fill");
16004
+ if (fill !== void 0) out.fill = fill;
16005
+ const stroke = trackValue("stroke");
16006
+ if (stroke !== void 0) out.stroke = stroke;
16007
+ const shadowFrames = frames.filter((f3) => f3.shadow !== void 0);
16008
+ if (shadowFrames.length > 0) {
16009
+ const sh = trackValue("shadow");
16010
+ if (sh !== void 0) {
16011
+ let prevSh;
16012
+ let nextSh;
16013
+ for (const f3 of shadowFrames) {
16014
+ if (f3.at <= t) prevSh = f3;
16015
+ else if (!nextSh) nextSh = f3;
16016
+ }
16017
+ if (prevSh?.shadow && nextSh?.shadow) {
16018
+ const span = nextSh.at - prevSh.at;
16019
+ const k = span > 0 ? (t - prevSh.at) / span : 1;
16020
+ out.shadow = { color: prevSh.shadow.color, blur: lerp(prevSh.shadow.blur, nextSh.shadow.blur, k) };
16021
+ } else {
16022
+ out.shadow = sh;
16023
+ }
16024
+ }
16025
+ }
16026
+ return out;
16027
+ }
16028
+ function gradientStyle(g, ox, oy, scale) {
16029
+ if (g.kind === "linear") {
16030
+ if (!g.from || !g.to) return void 0;
16031
+ return {
16032
+ kind: "linear",
16033
+ x1: ox + g.from.x * scale,
16034
+ y1: oy + g.from.y * scale,
16035
+ x2: ox + g.to.x * scale,
16036
+ y2: oy + g.to.y * scale,
16037
+ stops: g.stops
16038
+ };
16039
+ }
16040
+ if (!g.center || g.radius === void 0) return void 0;
16041
+ return {
16042
+ kind: "radial",
16043
+ cx: ox + g.center.x * scale,
16044
+ cy: oy + g.center.y * scale,
16045
+ r: g.radius * scale,
16046
+ stops: g.stops
16047
+ };
16048
+ }
15965
16049
  function DrawShape(props) {
15966
16050
  const register = useContext(DrawableRegistryContext);
15967
16051
  if (register) {
@@ -15972,25 +16056,51 @@ function DrawShape(props) {
15972
16056
  ...opacity !== void 0 && opacity > 0 ? { opacity } : {}
15973
16057
  };
15974
16058
  register(node);
15975
- return /* @__PURE__ */ jsx("div", { "data-draw-shape-debug": "", style: { position: "absolute", width: 4, height: 4, background: "red", zIndex: 9999 } });
15976
16059
  }
15977
16060
  return null;
15978
16061
  }
15979
- var paintShape;
16062
+ var NUMERIC_TRACKS, lerp, paintShape;
15980
16063
  var init_DrawShape = __esm({
15981
16064
  "components/game/atoms/DrawShape.tsx"() {
15982
16065
  "use client";
15983
16066
  init_contract();
15984
16067
  init_registry();
15985
- paintShape = (painter, node, dctx) => {
16068
+ NUMERIC_TRACKS = [
16069
+ "offsetX",
16070
+ "offsetY",
16071
+ "rotate",
16072
+ "opacity",
16073
+ "radiusX",
16074
+ "radiusY",
16075
+ "width",
16076
+ "height",
16077
+ "strokeWidth"
16078
+ ];
16079
+ lerp = (a, b, k) => a + (b - a) * k;
16080
+ paintShape = (painter, rawNode, dctx) => {
16081
+ const node = dctx.time > 0 ? applyShapeAnimation(rawNode, dctx.time) : rawNode;
15986
16082
  if (!isValidScenePos(node.position)) return;
15987
16083
  painter.save();
15988
16084
  if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
16085
+ const origin = dctx.projector.project(node.position);
16086
+ const tileWidth = dctx.projector.tileWidth;
16087
+ if (node.rotate) {
16088
+ const pivot = node.pivot ?? { x: 0.5, y: 0.5 };
16089
+ const px = origin.x + pivot.x * tileWidth;
16090
+ const py = origin.y + pivot.y * tileWidth;
16091
+ painter.translate(px, py);
16092
+ painter.rotate(node.rotate);
16093
+ painter.translate(-px, -py);
16094
+ }
16095
+ if (node.shadow) painter.setShadow({ color: node.shadow.color, blur: node.shadow.blur * tileWidth });
16096
+ const fill = node.fill === "none" ? void 0 : node.fill;
16097
+ const stroke = node.stroke === "none" ? void 0 : node.stroke;
16098
+ const pxFill = node.gradient ? gradientStyle(node.gradient, origin.x, origin.y, tileWidth) ?? fill : fill;
15989
16099
  switch (node.shape) {
15990
16100
  case "cell": {
15991
16101
  const pts = dctx.projector.cellPath(node.position);
15992
- if (node.fill) painter.fillPoly(pts, node.fill);
15993
- if (node.stroke) painter.strokePoly(pts, node.stroke, node.strokeWidth ?? 1, true);
16102
+ if (pxFill) painter.fillPoly(pts, pxFill);
16103
+ if (stroke) painter.strokePoly(pts, stroke, node.strokeWidth ?? 1, true);
15994
16104
  break;
15995
16105
  }
15996
16106
  case "rect": {
@@ -16000,8 +16110,8 @@ var init_DrawShape = __esm({
16000
16110
  const y = p.y + (node.offsetY ?? 0) * tw;
16001
16111
  const w = (node.width ?? 0) * tw;
16002
16112
  const h = (node.height ?? 0) * tw;
16003
- if (node.fill) painter.fillRect(x, y, w, h, node.fill);
16004
- if (node.stroke) painter.strokeRect(x, y, w, h, node.stroke, node.strokeWidth ?? 1);
16113
+ if (pxFill) painter.fillRect(x, y, w, h, pxFill);
16114
+ if (stroke) painter.strokeRect(x, y, w, h, stroke, node.strokeWidth ?? 1);
16005
16115
  break;
16006
16116
  }
16007
16117
  case "ellipse": {
@@ -16011,26 +16121,26 @@ var init_DrawShape = __esm({
16011
16121
  const cy = p.y + (node.offsetY ?? 0) * tw;
16012
16122
  const rx = (node.radiusX ?? 0) * tw;
16013
16123
  const ry = (node.radiusY ?? rx) * tw;
16014
- if (node.fill) painter.fillEllipse(cx, cy, rx, ry, node.fill);
16015
- if (node.stroke) painter.strokeEllipse(cx, cy, rx, ry, node.stroke, node.strokeWidth ?? 1);
16124
+ if (pxFill) painter.fillEllipse(cx, cy, rx, ry, pxFill);
16125
+ if (stroke) painter.strokeEllipse(cx, cy, rx, ry, stroke, node.strokeWidth ?? 1);
16016
16126
  break;
16017
16127
  }
16018
16128
  case "poly": {
16019
- const base = dctx.projector.project(node.position);
16020
- const tw = dctx.projector.tileWidth;
16021
- const pts = (node.points ?? []).map((pt) => ({ x: base.x + pt.x * tw, y: base.y + pt.y * tw }));
16022
- if (node.fill) painter.fillPoly(pts, node.fill);
16023
- if (node.stroke) painter.strokePoly(pts, node.stroke, node.strokeWidth ?? 1, true);
16129
+ const pts = (node.points ?? []).map((pt) => ({
16130
+ x: origin.x + ((node.offsetX ?? 0) + pt.x) * tileWidth,
16131
+ y: origin.y + ((node.offsetY ?? 0) + pt.y) * tileWidth
16132
+ }));
16133
+ if (pxFill) painter.fillPoly(pts, pxFill);
16134
+ if (stroke) painter.strokePoly(pts, stroke, node.strokeWidth ?? 1, true);
16024
16135
  break;
16025
16136
  }
16026
16137
  case "path": {
16027
16138
  if (!node.d) break;
16028
- const base = dctx.projector.project(node.position);
16029
- const tw = dctx.projector.tileWidth;
16030
- painter.translate(base.x, base.y);
16031
- painter.scale(tw, tw);
16032
- if (node.fill) painter.fillPath(node.d, node.fill);
16033
- if (node.stroke) painter.strokePath(node.d, node.stroke, (node.strokeWidth ?? 1) / tw);
16139
+ painter.translate(origin.x + (node.offsetX ?? 0) * tileWidth, origin.y + (node.offsetY ?? 0) * tileWidth);
16140
+ painter.scale(tileWidth, tileWidth);
16141
+ const localFill = node.gradient ? gradientStyle(node.gradient, 0, 0, 1) ?? fill : fill;
16142
+ if (localFill) painter.fillPath(node.d, localFill);
16143
+ if (stroke) painter.strokePath(node.d, stroke, (node.strokeWidth ?? 1) / tileWidth);
16034
16144
  break;
16035
16145
  }
16036
16146
  }
@@ -16242,7 +16352,6 @@ function Canvas2D({
16242
16352
  childDrawablesRef.current.push(node);
16243
16353
  }, []);
16244
16354
  const hasJsxChildren = React76.Children.count(children) > 0;
16245
- drawables && drawables.length > 0 ? drawables : childDrawablesRef.current;
16246
16355
  function isDrawableLayer(node) {
16247
16356
  return node.type === "draw-sprite-layer" || node.type === "draw-shape-layer" || node.type === "draw-text-layer";
16248
16357
  }
@@ -16391,11 +16500,24 @@ function Canvas2D({
16391
16500
  }, [showMinimap, scenePositions]);
16392
16501
  const miniMapWidth = gridExtent.width || 10;
16393
16502
  const miniMapHeight = gridExtent.height || 10;
16394
- const draw = useCallback(() => {
16503
+ const drawableIsAnimated = (node) => {
16504
+ if (node.type === "draw-shape") return isAnimatedShape(node);
16505
+ if (node.type === "draw-group") return Array.isArray(node.items) && node.items.some(drawableIsAnimated);
16506
+ if (node.type === "draw-shape-layer") return Array.isArray(node.items) && node.items.some(isAnimatedShape);
16507
+ return false;
16508
+ };
16509
+ const animRafRef = useRef(0);
16510
+ const drawTimeRef = useRef(() => void 0);
16511
+ const draw = useCallback((timeMs = 0) => {
16395
16512
  const canvas = canvasRef.current;
16396
16513
  if (!canvas) return;
16397
16514
  const ctx = canvas.getContext("2d");
16398
16515
  if (!ctx) return;
16516
+ const scheduleAnimation = (nodes) => {
16517
+ if (!nodes.some(drawableIsAnimated)) return;
16518
+ cancelAnimationFrame(animRafRef.current);
16519
+ animRafRef.current = requestAnimationFrame(() => drawTimeRef.current(performance.now()));
16520
+ };
16399
16521
  const dpr = window.devicePixelRatio || 1;
16400
16522
  canvas.width = viewportSize.width * dpr;
16401
16523
  canvas.height = viewportSize.height * dpr;
@@ -16428,14 +16550,24 @@ function Canvas2D({
16428
16550
  if (!drawables || drawables.length === 0) {
16429
16551
  const childDrawables = childDrawablesRef.current;
16430
16552
  if (childDrawables.length === 0) return;
16553
+ const cam0 = cameraRef.current;
16554
+ if (camera !== "follow" && dragDistance() === 0) {
16555
+ const focus = cameraPos ?? defaultGridFocus;
16556
+ if (focus) {
16557
+ const p = projector.anchorPoint(focus, "center");
16558
+ cam0.x = p.x - viewportSize.width / 2;
16559
+ cam0.y = p.y - viewportSize.height / 2;
16560
+ }
16561
+ }
16431
16562
  const painter0 = createWebPainter(ctx, bumpAtlas);
16432
16563
  painter0.save();
16433
16564
  painter0.translate(viewportSize.width / 2, viewportSize.height / 2);
16434
- painter0.scale(cameraRef.current.zoom, cameraRef.current.zoom);
16435
- painter0.translate(-viewportSize.width / 2, -viewportSize.height / 2);
16436
- const dctx0 = { projector, time: 0, invalidate: bumpAtlas };
16565
+ painter0.scale(cam0.zoom, cam0.zoom);
16566
+ painter0.translate(-viewportSize.width / 2 - cam0.x, -viewportSize.height / 2 - cam0.y);
16567
+ const dctx0 = { projector, time: timeMs, invalidate: bumpAtlas };
16437
16568
  for (const node of childDrawables) paintDrawable(painter0, node, dctx0);
16438
16569
  painter0.restore();
16570
+ scheduleAnimation(childDrawables);
16439
16571
  return;
16440
16572
  }
16441
16573
  const cam = cameraRef.current;
@@ -16455,10 +16587,15 @@ function Canvas2D({
16455
16587
  painter.translate(viewportSize.width / 2, viewportSize.height / 2);
16456
16588
  painter.scale(cam.zoom, cam.zoom);
16457
16589
  painter.translate(-viewportSize.width / 2 - cam.x, -viewportSize.height / 2 - cam.y);
16458
- const dctx = { projector, time: 0, invalidate: bumpAtlas };
16590
+ const dctx = { projector, time: timeMs, invalidate: bumpAtlas };
16459
16591
  for (const node of drawables) paintDrawable(painter, node, dctx);
16460
16592
  painter.restore();
16593
+ scheduleAnimation(drawables);
16461
16594
  }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance]);
16595
+ useEffect(() => {
16596
+ drawTimeRef.current = draw;
16597
+ }, [draw]);
16598
+ useEffect(() => () => cancelAnimationFrame(animRafRef.current), []);
16462
16599
  useEffect(() => {
16463
16600
  if (camera !== "follow" || !followTarget) return;
16464
16601
  const p = projector.anchorPoint(followTarget, "center");
@@ -16681,15 +16818,7 @@ function Canvas2D({
16681
16818
  mapHeight: miniMapHeight
16682
16819
  }
16683
16820
  ) }),
16684
- hasJsxChildren && /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { position: "absolute", width: 0, height: 0, overflow: "hidden" }, children }),
16685
- /* @__PURE__ */ jsxs("div", { "data-debug": "", style: { position: "absolute", top: 0, left: 0, background: "yellow", color: "black", zIndex: 9999, fontSize: 24, padding: 8 }, children: [
16686
- "C=",
16687
- React76.Children.count(children),
16688
- " J=",
16689
- String(hasJsxChildren),
16690
- " D=",
16691
- drawables?.length ?? -1
16692
- ] })
16821
+ hasJsxChildren && /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { position: "absolute", width: 0, height: 0, overflow: "hidden" }, children })
16693
16822
  ]
16694
16823
  }
16695
16824
  ) });
@@ -16714,6 +16843,7 @@ var init_Canvas2D = __esm({
16714
16843
  init_webPainter2d();
16715
16844
  init_projector();
16716
16845
  init_paintDispatch();
16846
+ init_DrawShape();
16717
16847
  init_registry();
16718
16848
  init_hitTest();
16719
16849
  init_isometric();
@@ -46894,8 +47024,13 @@ function SlotContentRenderer({
46894
47024
  const isSingleChild = typeof childrenConfig === "string" || typeof childrenConfig === "object" && childrenConfig !== null && !Array.isArray(childrenConfig) && "type" in childrenConfig;
46895
47025
  const hasChildren = PATTERNS_WITH_CHILDREN.has(content.pattern) || Array.isArray(childrenConfig) && childrenConfig.length > 0 || isSingleChild;
46896
47026
  const isDrawHost = isDrawHostPattern(content.pattern);
47027
+ const arr = Array.isArray(childrenConfig) ? childrenConfig : childrenConfig ? [childrenConfig] : [];
47028
+ const hasTraitChildren = arr.some(
47029
+ (c) => typeof c === "string" && TRAIT_BINDING_RE.test(c)
47030
+ );
47031
+ const drawHostUsesReactChildren = isDrawHost && hasTraitChildren;
46897
47032
  const myPath = patternPath ?? "root";
46898
- const renderedChildren = hasChildren && !isDrawHost ? renderPatternChildren(childrenConfig, onDismiss, content.id, myPath, content.sourceTrait, {
47033
+ const renderedChildren = hasChildren && (!isDrawHost || drawHostUsesReactChildren) ? renderPatternChildren(childrenConfig, onDismiss, content.id, myPath, content.sourceTrait, {
46899
47034
  slot: content.slot,
46900
47035
  transitionEvent: content.transitionEvent,
46901
47036
  fromState: content.fromState,
@@ -46956,7 +47091,7 @@ function SlotContentRenderer({
46956
47091
  for (const [k, v] of Object.entries(nodeSlotOverrides)) {
46957
47092
  finalProps[k] = v;
46958
47093
  }
46959
- if (isDrawHost && Array.isArray(childrenConfig) && childrenConfig.length > 0) {
47094
+ if (isDrawHost && !drawHostUsesReactChildren && Array.isArray(childrenConfig) && childrenConfig.length > 0) {
46960
47095
  finalProps.drawables = toDrawableNodes(childrenConfig);
46961
47096
  }
46962
47097
  const entityVal = finalProps.entity;
@@ -47135,6 +47270,8 @@ var init_UISlotRenderer = __esm({
47135
47270
  "vstack",
47136
47271
  "hstack",
47137
47272
  "box",
47273
+ "canvas",
47274
+ "canvas-2d",
47138
47275
  "grid",
47139
47276
  "center",
47140
47277
  "card",
@@ -3,7 +3,7 @@ import React__default, { Component, ReactNode, ErrorInfo } from 'react';
3
3
  import { ScenePos, EventEmit, JsonObject, OrbitalSchema } from '@almadar/core';
4
4
  import * as THREE from 'three';
5
5
  import { QuadraticBezierCurve3 } from 'three';
6
- import { D as DrawableNode } from '../../../paintDispatch-DXygiK7M.cjs';
6
+ import { D as DrawableNode } from '../../../paintDispatch-B5pPeSEp.cjs';
7
7
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
8
8
  import { I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-B8Onmfsu.cjs';
9
9
  export { U as UnitAnimationState } from '../../../avl-schema-parser-B8Onmfsu.cjs';
@@ -3,7 +3,7 @@ import React__default, { Component, ReactNode, ErrorInfo } from 'react';
3
3
  import { ScenePos, EventEmit, JsonObject, OrbitalSchema } from '@almadar/core';
4
4
  import * as THREE from 'three';
5
5
  import { QuadraticBezierCurve3 } from 'three';
6
- import { D as DrawableNode } from '../../../paintDispatch-DXygiK7M.js';
6
+ import { D as DrawableNode } from '../../../paintDispatch-B5pPeSEp.js';
7
7
  import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
8
8
  import { I as IsometricTile, a as IsometricUnit, b as IsometricFeature, A as ApplicationLevelData, O as OrbitalLevelData, T as TraitLevelData, c as TransitionLevelData } from '../../../avl-schema-parser-B8Onmfsu.js';
9
9
  export { U as UnitAnimationState } from '../../../avl-schema-parser-B8Onmfsu.js';
@@ -1,7 +1,7 @@
1
- export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-CL0kdshO.cjs';
1
+ export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-DkGYzPOg.cjs';
2
2
  import { FieldValue, EntityRow, EventPayload } from '@almadar/core';
3
3
  export { AssetLoadStatus, BridgeHealth, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
4
- import '../paintDispatch-DXygiK7M.cjs';
4
+ import '../paintDispatch-B5pPeSEp.cjs';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -1,7 +1,7 @@
1
- export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-CCaph5o9.js';
1
+ export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-Do5Ra3l3.js';
2
2
  import { FieldValue, EntityRow, EventPayload } from '@almadar/core';
3
3
  export { AssetLoadStatus, BridgeHealth, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
4
- import '../paintDispatch-DXygiK7M.js';
4
+ import '../paintDispatch-B5pPeSEp.js';
5
5
  import 'clsx';
6
6
 
7
7
  /**
@@ -17,6 +17,11 @@ interface PainterShadow {
17
17
  color: string;
18
18
  blur: number;
19
19
  }
20
+ /** One color stop of a {@link PainterGradient}; `offset` is 0..1 along the gradient. */
21
+ interface PainterGradientStop {
22
+ offset: number;
23
+ color: string;
24
+ }
20
25
 
21
26
  /**
22
27
  * Drawable contract — the shared vocabulary every neutral drawable primitive
@@ -110,6 +115,64 @@ interface DrawSpriteProps extends DrawableBase {
110
115
  */
111
116
 
112
117
  type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly' | 'path';
118
+ /** One gradient color stop; `offset` is 0..1 along the gradient axis. */
119
+ type DrawShapeGradientStop = PainterGradientStop;
120
+ /**
121
+ * A gradient fill in world units relative to the cell's projected top-left —
122
+ * same coordinate convention as `points` and `d`. Overrides `fill` when present.
123
+ */
124
+ interface DrawShapeGradient {
125
+ kind: 'linear' | 'radial';
126
+ /** Linear start point in world units. */
127
+ from?: PainterPoint;
128
+ /** Linear end point in world units. */
129
+ to?: PainterPoint;
130
+ /** Radial center in world units. */
131
+ center?: PainterPoint;
132
+ /** Radial radius in world units. */
133
+ radius?: number;
134
+ /** Ordered color stops. */
135
+ stops: DrawShapeGradientStop[];
136
+ }
137
+ /** A soft glow / drop-shadow behind the shape; `blur` is in world units. */
138
+ interface DrawShapeShadow {
139
+ color: string;
140
+ blur: number;
141
+ }
142
+ /**
143
+ * One keyframe of a {@link DrawShapeAnimation}: `at` is the 0..1 position in
144
+ * the cycle; every other field overrides the shape's base prop at that moment.
145
+ */
146
+ interface DrawShapeKeyframe {
147
+ at: number;
148
+ offsetX?: number;
149
+ offsetY?: number;
150
+ rotate?: number;
151
+ opacity?: number;
152
+ radiusX?: number;
153
+ radiusY?: number;
154
+ width?: number;
155
+ height?: number;
156
+ strokeWidth?: number;
157
+ fill?: string;
158
+ stroke?: string;
159
+ shadow?: DrawShapeShadow;
160
+ }
161
+ /**
162
+ * Declarative keyframe animation for a drawable. The host runs a paint clock
163
+ * while any drawable declares one; numeric tracks lerp between keyframes,
164
+ * string tracks hold the previous keyframe's value, `shadow` lerps `blur` and
165
+ * holds `color`. A track starts from the shape's base prop until its first
166
+ * keyframe defines it.
167
+ */
168
+ interface DrawShapeAnimation {
169
+ /** One cycle length in ms. */
170
+ durationMs: number;
171
+ /** Loop the cycle (default true); false plays once and holds the final keyframes. */
172
+ loop?: boolean;
173
+ /** Keyframes ordered by `at` (0..1). */
174
+ keyframes: DrawShapeKeyframe[];
175
+ }
113
176
  interface DrawShapeProps extends DrawableBase {
114
177
  type: 'draw-shape';
115
178
  shape: ShapeKind;
@@ -125,7 +188,7 @@ interface DrawShapeProps extends DrawableBase {
125
188
  radiusX?: number;
126
189
  /** Ellipse vertical radius in world units; omitted → `radiusX` (a circle). */
127
190
  radiusY?: number;
128
- /** Fine nudge from the anchor point in world units. */
191
+ /** Fine nudge in world units — applies to every shape kind except `cell` (rect/ellipse from their anchor point; poly/path from the projected top-left). */
129
192
  offsetX?: number;
130
193
  offsetY?: number;
131
194
  /** Poly vertices as world-unit offsets relative to the cell's projected top-left. */
@@ -133,8 +196,18 @@ interface DrawShapeProps extends DrawableBase {
133
196
  /** SVG path data in world units relative to the cell's projected top-left — same coordinate convention as `points`. */
134
197
  d?: string;
135
198
  fill?: string;
199
+ /** Gradient fill in world units; overrides `fill` when present. */
200
+ gradient?: DrawShapeGradient;
136
201
  stroke?: string;
137
202
  strokeWidth?: number;
203
+ /** Rotation in radians (painter units, same as `draw-group`), about `pivot`. */
204
+ rotate?: number;
205
+ /** Rotation pivot in world units relative to the cell's projected top-left; default `{x:0.5, y:0.5}` (cell center). */
206
+ pivot?: PainterPoint;
207
+ /** Soft glow / drop-shadow behind the shape; `blur` in world units. */
208
+ shadow?: DrawShapeShadow;
209
+ /** Keyframe animation over this shape's props; the host runs a paint clock while present. */
210
+ animation?: DrawShapeAnimation;
138
211
  /** 0..1 opacity. */
139
212
  opacity?: number;
140
213
  }
@@ -17,6 +17,11 @@ interface PainterShadow {
17
17
  color: string;
18
18
  blur: number;
19
19
  }
20
+ /** One color stop of a {@link PainterGradient}; `offset` is 0..1 along the gradient. */
21
+ interface PainterGradientStop {
22
+ offset: number;
23
+ color: string;
24
+ }
20
25
 
21
26
  /**
22
27
  * Drawable contract — the shared vocabulary every neutral drawable primitive
@@ -110,6 +115,64 @@ interface DrawSpriteProps extends DrawableBase {
110
115
  */
111
116
 
112
117
  type ShapeKind = 'cell' | 'rect' | 'ellipse' | 'poly' | 'path';
118
+ /** One gradient color stop; `offset` is 0..1 along the gradient axis. */
119
+ type DrawShapeGradientStop = PainterGradientStop;
120
+ /**
121
+ * A gradient fill in world units relative to the cell's projected top-left —
122
+ * same coordinate convention as `points` and `d`. Overrides `fill` when present.
123
+ */
124
+ interface DrawShapeGradient {
125
+ kind: 'linear' | 'radial';
126
+ /** Linear start point in world units. */
127
+ from?: PainterPoint;
128
+ /** Linear end point in world units. */
129
+ to?: PainterPoint;
130
+ /** Radial center in world units. */
131
+ center?: PainterPoint;
132
+ /** Radial radius in world units. */
133
+ radius?: number;
134
+ /** Ordered color stops. */
135
+ stops: DrawShapeGradientStop[];
136
+ }
137
+ /** A soft glow / drop-shadow behind the shape; `blur` is in world units. */
138
+ interface DrawShapeShadow {
139
+ color: string;
140
+ blur: number;
141
+ }
142
+ /**
143
+ * One keyframe of a {@link DrawShapeAnimation}: `at` is the 0..1 position in
144
+ * the cycle; every other field overrides the shape's base prop at that moment.
145
+ */
146
+ interface DrawShapeKeyframe {
147
+ at: number;
148
+ offsetX?: number;
149
+ offsetY?: number;
150
+ rotate?: number;
151
+ opacity?: number;
152
+ radiusX?: number;
153
+ radiusY?: number;
154
+ width?: number;
155
+ height?: number;
156
+ strokeWidth?: number;
157
+ fill?: string;
158
+ stroke?: string;
159
+ shadow?: DrawShapeShadow;
160
+ }
161
+ /**
162
+ * Declarative keyframe animation for a drawable. The host runs a paint clock
163
+ * while any drawable declares one; numeric tracks lerp between keyframes,
164
+ * string tracks hold the previous keyframe's value, `shadow` lerps `blur` and
165
+ * holds `color`. A track starts from the shape's base prop until its first
166
+ * keyframe defines it.
167
+ */
168
+ interface DrawShapeAnimation {
169
+ /** One cycle length in ms. */
170
+ durationMs: number;
171
+ /** Loop the cycle (default true); false plays once and holds the final keyframes. */
172
+ loop?: boolean;
173
+ /** Keyframes ordered by `at` (0..1). */
174
+ keyframes: DrawShapeKeyframe[];
175
+ }
113
176
  interface DrawShapeProps extends DrawableBase {
114
177
  type: 'draw-shape';
115
178
  shape: ShapeKind;
@@ -125,7 +188,7 @@ interface DrawShapeProps extends DrawableBase {
125
188
  radiusX?: number;
126
189
  /** Ellipse vertical radius in world units; omitted → `radiusX` (a circle). */
127
190
  radiusY?: number;
128
- /** Fine nudge from the anchor point in world units. */
191
+ /** Fine nudge in world units — applies to every shape kind except `cell` (rect/ellipse from their anchor point; poly/path from the projected top-left). */
129
192
  offsetX?: number;
130
193
  offsetY?: number;
131
194
  /** Poly vertices as world-unit offsets relative to the cell's projected top-left. */
@@ -133,8 +196,18 @@ interface DrawShapeProps extends DrawableBase {
133
196
  /** SVG path data in world units relative to the cell's projected top-left — same coordinate convention as `points`. */
134
197
  d?: string;
135
198
  fill?: string;
199
+ /** Gradient fill in world units; overrides `fill` when present. */
200
+ gradient?: DrawShapeGradient;
136
201
  stroke?: string;
137
202
  strokeWidth?: number;
203
+ /** Rotation in radians (painter units, same as `draw-group`), about `pivot`. */
204
+ rotate?: number;
205
+ /** Rotation pivot in world units relative to the cell's projected top-left; default `{x:0.5, y:0.5}` (cell center). */
206
+ pivot?: PainterPoint;
207
+ /** Soft glow / drop-shadow behind the shape; `blur` in world units. */
208
+ shadow?: DrawShapeShadow;
209
+ /** Keyframe animation over this shape's props; the host runs a paint clock while present. */
210
+ animation?: DrawShapeAnimation;
138
211
  /** 0..1 opacity. */
139
212
  opacity?: number;
140
213
  }