@almadar/ui 5.143.0 → 5.145.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.
@@ -1526,6 +1526,10 @@ var init_Icon = __esm({
1526
1526
  function isTilesheet(a) {
1527
1527
  return typeof a.tileWidth === "number";
1528
1528
  }
1529
+ function isSpriteSheetAtlas(a) {
1530
+ const s = a;
1531
+ return typeof s.frameWidth === "number" && typeof s.frameHeight === "number" && typeof s.animations === "object";
1532
+ }
1529
1533
  function getAtlas(url, onReady) {
1530
1534
  if (atlasCache.has(url)) return atlasCache.get(url) ?? void 0;
1531
1535
  atlasCache.set(url, void 0);
@@ -1565,6 +1569,7 @@ function subRectFor(atlas, sprite) {
1565
1569
  sh: atlas.tileHeight
1566
1570
  };
1567
1571
  }
1572
+ if (isSpriteSheetAtlas(atlas)) return null;
1568
1573
  const st = atlas.subTextures[sprite];
1569
1574
  if (!st) return null;
1570
1575
  return { sx: st.x, sy: st.y, sw: st.width, sh: st.height };
@@ -1874,7 +1879,7 @@ var init_Button = __esm({
1874
1879
  "data-testid": dataTestId ?? (action ? `action-${action}` : void 0),
1875
1880
  children: [
1876
1881
  isLoading ? /* @__PURE__ */ jsxRuntime.jsx(LucideIcons2.Loader2, { className: "h-icon-default w-icon-default animate-spin" }) : resolvedLeftIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: resolvedLeftIcon }),
1877
- children || label,
1882
+ (Array.isArray(children) ? children.length > 0 : Boolean(children)) ? children : label,
1878
1883
  resolvedRightIcon && !isLoading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: resolvedRightIcon })
1879
1884
  ]
1880
1885
  }
@@ -16021,6 +16026,138 @@ var init_contract = __esm({
16021
16026
  "lib/drawable/contract.ts"() {
16022
16027
  }
16023
16028
  });
16029
+
16030
+ // lib/spriteSheetConstants.ts
16031
+ exports.SHEET_COLUMNS = void 0; exports.SPRITE_SHEET_LAYOUT = void 0;
16032
+ var init_spriteSheetConstants = __esm({
16033
+ "lib/spriteSheetConstants.ts"() {
16034
+ exports.SHEET_COLUMNS = 8;
16035
+ exports.SPRITE_SHEET_LAYOUT = {
16036
+ idle: { row: 0, frames: 4, frameRate: 6, loop: true },
16037
+ walk: { row: 1, frames: 8, frameRate: 10, loop: true },
16038
+ attack: { row: 2, frames: 6, frameRate: 12, loop: false },
16039
+ hit: { row: 3, frames: 3, frameRate: 8, loop: false },
16040
+ death: { row: 4, frames: 6, frameRate: 8, loop: false }
16041
+ };
16042
+ }
16043
+ });
16044
+ function isAnimationName(name) {
16045
+ return core.ANIMATION_NAMES.includes(name);
16046
+ }
16047
+ function inferDirection(dx, dy) {
16048
+ if (dx === 0 && dy === 0) return "se";
16049
+ if (dx >= 0 && dy >= 0) return "se";
16050
+ if (dx <= 0 && dy >= 0) return "sw";
16051
+ if (dx >= 0 && dy <= 0) return "ne";
16052
+ return "nw";
16053
+ }
16054
+ function resolveSheetDirection(facing) {
16055
+ switch (facing) {
16056
+ case "se":
16057
+ return { sheetDir: "se", flipX: false };
16058
+ case "sw":
16059
+ return { sheetDir: "sw", flipX: false };
16060
+ case "ne":
16061
+ return { sheetDir: "sw", flipX: true };
16062
+ case "nw":
16063
+ return { sheetDir: "se", flipX: true };
16064
+ }
16065
+ }
16066
+ function frameRect(frame, row, columns, frameWidth, frameHeight) {
16067
+ return {
16068
+ sx: frame % columns * frameWidth,
16069
+ sy: row * frameHeight,
16070
+ sw: frameWidth,
16071
+ sh: frameHeight
16072
+ };
16073
+ }
16074
+ function getCurrentFrameFromDef(def, elapsed) {
16075
+ const frameDuration = 1e3 / def.frameRate;
16076
+ const totalDuration = def.frames * frameDuration;
16077
+ if (def.loop) {
16078
+ const frame2 = Math.floor(elapsed % totalDuration / frameDuration);
16079
+ return { frame: frame2, finished: false };
16080
+ }
16081
+ if (elapsed >= totalDuration) {
16082
+ return { frame: def.frames - 1, finished: true };
16083
+ }
16084
+ const frame = Math.floor(elapsed / frameDuration);
16085
+ return { frame, finished: false };
16086
+ }
16087
+ function getCurrentFrame(animName, elapsed) {
16088
+ return getCurrentFrameFromDef(exports.SPRITE_SHEET_LAYOUT[animName], elapsed);
16089
+ }
16090
+ function resolveFrame(sheetUrls, frameDims, animState) {
16091
+ if (!sheetUrls) return null;
16092
+ const real = sheetUrls[animState.direction];
16093
+ const { sheetUrl, flipX } = real ? { sheetUrl: real, flipX: false } : (() => {
16094
+ const legacy = resolveSheetDirection(animState.direction);
16095
+ return { sheetUrl: sheetUrls[legacy.sheetDir], flipX: legacy.flipX };
16096
+ })();
16097
+ if (!sheetUrl) return null;
16098
+ const def = exports.SPRITE_SHEET_LAYOUT[animState.animation];
16099
+ const { frame } = getCurrentFrame(animState.animation, animState.elapsed);
16100
+ const rect = frameRect(frame, def.row, def.frames, frameDims.width, frameDims.height);
16101
+ return {
16102
+ sheetUrl,
16103
+ sx: rect.sx,
16104
+ sy: rect.sy,
16105
+ sw: rect.sw,
16106
+ sh: rect.sh,
16107
+ flipX
16108
+ };
16109
+ }
16110
+ function createUnitAnimationState(unitId) {
16111
+ return {
16112
+ unitId,
16113
+ animation: "idle",
16114
+ direction: "se",
16115
+ frame: 0,
16116
+ elapsed: 0,
16117
+ queuedAnimation: null,
16118
+ finished: false
16119
+ };
16120
+ }
16121
+ function transitionAnimation(state, newAnim, direction) {
16122
+ if (state.animation === "death" && state.finished) return state;
16123
+ if (state.animation === newAnim && exports.SPRITE_SHEET_LAYOUT[newAnim].loop) {
16124
+ return direction ? { ...state, direction } : state;
16125
+ }
16126
+ return {
16127
+ ...state,
16128
+ animation: newAnim,
16129
+ direction: direction ?? state.direction,
16130
+ frame: 0,
16131
+ elapsed: 0,
16132
+ queuedAnimation: null,
16133
+ finished: false
16134
+ };
16135
+ }
16136
+ function tickAnimationState(state, deltaMs) {
16137
+ const newElapsed = state.elapsed + deltaMs;
16138
+ const { frame, finished } = getCurrentFrame(state.animation, newElapsed);
16139
+ const def = exports.SPRITE_SHEET_LAYOUT[state.animation];
16140
+ if (finished && !def.loop && !state.finished) {
16141
+ if (state.animation === "death") {
16142
+ return { ...state, elapsed: newElapsed, frame, finished: true };
16143
+ }
16144
+ const nextAnim = state.queuedAnimation ?? "idle";
16145
+ return {
16146
+ ...state,
16147
+ animation: nextAnim,
16148
+ elapsed: 0,
16149
+ frame: 0,
16150
+ queuedAnimation: null,
16151
+ finished: false
16152
+ };
16153
+ }
16154
+ return { ...state, elapsed: newElapsed, frame, finished };
16155
+ }
16156
+ var init_spriteAnimation = __esm({
16157
+ "lib/spriteAnimation.ts"() {
16158
+ init_spriteSheetConstants();
16159
+ }
16160
+ });
16024
16161
  function warnMissingOnce(reason, node) {
16025
16162
  const key = `${reason}:${node.asset.url}:${String(node.asset.atlas)}:${String(node.asset.sprite)}`;
16026
16163
  if (loggedMissing.has(key)) return;
@@ -16038,6 +16175,9 @@ function paintFallbackSquare(painter, node, dctx, reason) {
16038
16175
  painter.strokeRect(rect.x, rect.y, rect.w, rect.h, "#5e564b", Math.max(1, tw / 32));
16039
16176
  painter.restore();
16040
16177
  }
16178
+ function isAnimatedSprite(node) {
16179
+ return node.animation !== void 0 && typeof node.asset?.atlas === "string";
16180
+ }
16041
16181
  function DrawSprite(_props) {
16042
16182
  return null;
16043
16183
  }
@@ -16046,6 +16186,7 @@ var init_DrawSprite = __esm({
16046
16186
  "components/game/atoms/DrawSprite.tsx"() {
16047
16187
  "use client";
16048
16188
  init_atlasSlice();
16189
+ init_spriteAnimation();
16049
16190
  init_imageCache();
16050
16191
  init_contract();
16051
16192
  spriteLog = logger.createLogger("almadar:ui:draw-sprite");
@@ -16059,6 +16200,23 @@ var init_DrawSprite = __esm({
16059
16200
  return;
16060
16201
  }
16061
16202
  let src = typeof node.frame === "object" ? node.frame : void 0;
16203
+ if (!src && node.animation !== void 0 && typeof node.asset.atlas === "string") {
16204
+ const atlas = getAtlas(node.asset.atlas, dctx.invalidate);
16205
+ if (!atlas) {
16206
+ if (atlasFailed(node.asset.atlas)) paintFallbackSquare(painter, node, dctx, "atlas-failed");
16207
+ return;
16208
+ }
16209
+ if (isSpriteSheetAtlas(atlas)) {
16210
+ const def = isAnimationName(node.animation) ? atlas.animations[node.animation] : void 0;
16211
+ if (!def) {
16212
+ paintFallbackSquare(painter, node, dctx, "sprite-missing");
16213
+ return;
16214
+ }
16215
+ const { frame } = getCurrentFrameFromDef(node.loop === void 0 ? def : { ...def, loop: node.loop }, dctx.time);
16216
+ const r = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
16217
+ src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
16218
+ }
16219
+ }
16062
16220
  if (!src && isAtlasAsset(node.asset)) {
16063
16221
  const atlas = getAtlas(node.asset.atlas, dctx.invalidate);
16064
16222
  if (!atlas) {
@@ -16776,9 +16934,11 @@ function Canvas2D({
16776
16934
  const miniMapHeight = gridExtent.height || 10;
16777
16935
  const drawableIsAnimated = (node) => {
16778
16936
  if (node.type === "draw-shape") return isAnimatedShape(node);
16937
+ if (node.type === "draw-sprite") return isAnimatedSprite(node);
16779
16938
  if (node.type === "draw-group")
16780
16939
  return isAnimatedGroup(node) || Array.isArray(node.items) && node.items.some(drawableIsAnimated);
16781
16940
  if (node.type === "draw-shape-layer") return Array.isArray(node.items) && node.items.some(isAnimatedShape);
16941
+ if (node.type === "draw-sprite-layer") return Array.isArray(node.items) && node.items.some(isAnimatedSprite);
16782
16942
  return false;
16783
16943
  };
16784
16944
  const animRafRef = React77.useRef(0);
@@ -17119,6 +17279,7 @@ var init_Canvas2D = __esm({
17119
17279
  init_projector();
17120
17280
  init_paintDispatch();
17121
17281
  init_DrawShape();
17282
+ init_DrawSprite();
17122
17283
  init_DrawGroup();
17123
17284
  init_registry();
17124
17285
  init_hitTest();
@@ -17192,6 +17353,7 @@ function Canvas({
17192
17353
  cameraMode: to3DCameraMode(camera?.mode),
17193
17354
  ...zoom !== void 0 ? { scale: zoom } : {},
17194
17355
  ...camera?.fov !== void 0 ? { fov: camera.fov } : {},
17356
+ ...camera?.azimuth !== void 0 ? { azimuth: camera.azimuth } : {},
17195
17357
  ...camera?.target !== void 0 ? { followTarget: camera.target } : {},
17196
17358
  unitScale,
17197
17359
  backgroundColor,
@@ -20180,7 +20342,7 @@ var init_DashboardLayout = __esm({
20180
20342
  }, [isMobile, sidebarOpen]);
20181
20343
  const location = reactRouterDom.useLocation();
20182
20344
  const ctxPagePath = providers.useCurrentPagePath();
20183
- const activePath = currentPath ?? ctxPagePath ?? location.pathname;
20345
+ const activePath = (currentPath || void 0) ?? ctxPagePath ?? location.pathname;
20184
20346
  const { user: authUser, signOut: authSignOut } = useAuthContext();
20185
20347
  const user = userProp || (authUser ? {
20186
20348
  name: authUser.displayName || authUser.email?.split("@")[0] || "User",
@@ -20647,6 +20809,14 @@ var init_DashboardLayout = __esm({
20647
20809
  NavLinkBottom.displayName = "NavLinkBottom";
20648
20810
  }
20649
20811
  });
20812
+ function downloadItemUrl(url, label) {
20813
+ const a = document.createElement("a");
20814
+ a.href = url;
20815
+ a.download = url.startsWith("data:") ? label : url.split("/").pop() ?? "download";
20816
+ document.body.appendChild(a);
20817
+ a.click();
20818
+ a.remove();
20819
+ }
20650
20820
  function computeMenuStyle(position, triggerRect) {
20651
20821
  const isTop = position.startsWith("top");
20652
20822
  const isRight = position.endsWith("right") || position.endsWith("end");
@@ -20699,6 +20869,7 @@ function SubMenu({
20699
20869
  onClick: () => {
20700
20870
  if (item.disabled) return;
20701
20871
  if (item.event) eventBus.emit(`UI:${item.event}`, { itemId, label: item.label });
20872
+ if (item.url) downloadItemUrl(item.url, item.label);
20702
20873
  item.onClick?.();
20703
20874
  },
20704
20875
  "aria-disabled": item.disabled || void 0,
@@ -20852,6 +21023,7 @@ var init_Menu = __esm({
20852
21023
  setActiveSubMenu(itemId);
20853
21024
  } else {
20854
21025
  if (item.event) eventBus.emit(`UI:${item.event}`, { itemId, label: item.label });
21026
+ if (item.url) downloadItemUrl(item.url, item.label);
20855
21027
  item.onClick?.();
20856
21028
  setIsOpen(false);
20857
21029
  }
@@ -20887,12 +21059,19 @@ var init_Menu = __esm({
20887
21059
  "bottom-end": "bottom-start"
20888
21060
  };
20889
21061
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
20890
- const triggerChild = React77__namespace.default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", as: "span", children: trigger });
20891
- const triggerElement = React77__namespace.default.cloneElement(
20892
- triggerChild,
21062
+ const triggerElement = React77__namespace.default.isValidElement(trigger) ? React77__namespace.default.cloneElement(trigger, {
21063
+ ref: triggerRef,
21064
+ onClick: handleToggle
21065
+ }) : /* @__PURE__ */ jsxRuntime.jsx(
21066
+ exports.Box,
20893
21067
  {
20894
- ref: triggerRef,
20895
- onClick: handleToggle
21068
+ as: "span",
21069
+ ref: (el) => {
21070
+ triggerRef.current = el;
21071
+ },
21072
+ onClick: handleToggle,
21073
+ className: "inline-flex",
21074
+ children: typeof trigger === "string" || typeof trigger === "number" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", as: "span", children: trigger }) : trigger
20896
21075
  }
20897
21076
  );
20898
21077
  const renderMenuItems = (menuItems) => menuItems.map((item, index) => {
@@ -26577,134 +26756,6 @@ var init_makeAsset = __esm({
26577
26756
  }
26578
26757
  });
26579
26758
 
26580
- // lib/spriteSheetConstants.ts
26581
- exports.SHEET_COLUMNS = void 0; exports.SPRITE_SHEET_LAYOUT = void 0;
26582
- var init_spriteSheetConstants = __esm({
26583
- "lib/spriteSheetConstants.ts"() {
26584
- exports.SHEET_COLUMNS = 8;
26585
- exports.SPRITE_SHEET_LAYOUT = {
26586
- idle: { row: 0, frames: 4, frameRate: 6, loop: true },
26587
- walk: { row: 1, frames: 8, frameRate: 10, loop: true },
26588
- attack: { row: 2, frames: 6, frameRate: 12, loop: false },
26589
- hit: { row: 3, frames: 3, frameRate: 8, loop: false },
26590
- death: { row: 4, frames: 6, frameRate: 8, loop: false }
26591
- };
26592
- }
26593
- });
26594
-
26595
- // lib/spriteAnimation.ts
26596
- function inferDirection(dx, dy) {
26597
- if (dx === 0 && dy === 0) return "se";
26598
- if (dx >= 0 && dy >= 0) return "se";
26599
- if (dx <= 0 && dy >= 0) return "sw";
26600
- if (dx >= 0 && dy <= 0) return "ne";
26601
- return "nw";
26602
- }
26603
- function resolveSheetDirection(facing) {
26604
- switch (facing) {
26605
- case "se":
26606
- return { sheetDir: "se", flipX: false };
26607
- case "sw":
26608
- return { sheetDir: "sw", flipX: false };
26609
- case "ne":
26610
- return { sheetDir: "sw", flipX: true };
26611
- case "nw":
26612
- return { sheetDir: "se", flipX: true };
26613
- }
26614
- }
26615
- function frameRect(frame, row, columns, frameWidth, frameHeight) {
26616
- return {
26617
- sx: frame % columns * frameWidth,
26618
- sy: row * frameHeight,
26619
- sw: frameWidth,
26620
- sh: frameHeight
26621
- };
26622
- }
26623
- function getCurrentFrameFromDef(def, elapsed) {
26624
- const frameDuration = 1e3 / def.frameRate;
26625
- const totalDuration = def.frames * frameDuration;
26626
- if (def.loop) {
26627
- const frame2 = Math.floor(elapsed % totalDuration / frameDuration);
26628
- return { frame: frame2, finished: false };
26629
- }
26630
- if (elapsed >= totalDuration) {
26631
- return { frame: def.frames - 1, finished: true };
26632
- }
26633
- const frame = Math.floor(elapsed / frameDuration);
26634
- return { frame, finished: false };
26635
- }
26636
- function getCurrentFrame(animName, elapsed) {
26637
- return getCurrentFrameFromDef(exports.SPRITE_SHEET_LAYOUT[animName], elapsed);
26638
- }
26639
- function resolveFrame(sheetUrls, frameDims, animState) {
26640
- if (!sheetUrls) return null;
26641
- const { sheetDir, flipX } = resolveSheetDirection(animState.direction);
26642
- const sheetUrl = sheetUrls[sheetDir];
26643
- if (!sheetUrl) return null;
26644
- const def = exports.SPRITE_SHEET_LAYOUT[animState.animation];
26645
- const { frame } = getCurrentFrame(animState.animation, animState.elapsed);
26646
- const rect = frameRect(frame, def.row, def.frames, frameDims.width, frameDims.height);
26647
- return {
26648
- sheetUrl,
26649
- sx: rect.sx,
26650
- sy: rect.sy,
26651
- sw: rect.sw,
26652
- sh: rect.sh,
26653
- flipX
26654
- };
26655
- }
26656
- function createUnitAnimationState(unitId) {
26657
- return {
26658
- unitId,
26659
- animation: "idle",
26660
- direction: "se",
26661
- frame: 0,
26662
- elapsed: 0,
26663
- queuedAnimation: null,
26664
- finished: false
26665
- };
26666
- }
26667
- function transitionAnimation(state, newAnim, direction) {
26668
- if (state.animation === "death" && state.finished) return state;
26669
- if (state.animation === newAnim && exports.SPRITE_SHEET_LAYOUT[newAnim].loop) {
26670
- return direction ? { ...state, direction } : state;
26671
- }
26672
- return {
26673
- ...state,
26674
- animation: newAnim,
26675
- direction: direction ?? state.direction,
26676
- frame: 0,
26677
- elapsed: 0,
26678
- queuedAnimation: null,
26679
- finished: false
26680
- };
26681
- }
26682
- function tickAnimationState(state, deltaMs) {
26683
- const newElapsed = state.elapsed + deltaMs;
26684
- const { frame, finished } = getCurrentFrame(state.animation, newElapsed);
26685
- const def = exports.SPRITE_SHEET_LAYOUT[state.animation];
26686
- if (finished && !def.loop && !state.finished) {
26687
- if (state.animation === "death") {
26688
- return { ...state, elapsed: newElapsed, frame, finished: true };
26689
- }
26690
- const nextAnim = state.queuedAnimation ?? "idle";
26691
- return {
26692
- ...state,
26693
- animation: nextAnim,
26694
- elapsed: 0,
26695
- frame: 0,
26696
- queuedAnimation: null,
26697
- finished: false
26698
- };
26699
- }
26700
- return { ...state, elapsed: newElapsed, frame, finished };
26701
- }
26702
- var init_spriteAnimation = __esm({
26703
- "lib/spriteAnimation.ts"() {
26704
- init_spriteSheetConstants();
26705
- }
26706
- });
26707
-
26708
26759
  // lib/gameShared.ts
26709
26760
  var init_gameShared = __esm({
26710
26761
  "lib/gameShared.ts"() {
@@ -6,11 +6,11 @@ import { LucideIcon } from 'lucide-react';
6
6
  import { C as ColorToken, U as UiError, P as Point, L as LinkAction, I as ImageSource } from '../GameAudioProvider-CPGwD49P.cjs';
7
7
  export { A as AudioManifest, G as GameAudioContext, a as GameAudioContextValue, e as GameAudioControls, b as GameAudioProvider, c as GameAudioProviderProps, R as Rect, S as SoundEntry, f as UseGameAudioOptions, g as useGameAudio, u as useGameAudioContext } from '../GameAudioProvider-CPGwD49P.cjs';
8
8
  import { SExpr } from '@almadar/evaluator';
9
- import { U as UnitAnimationState, F as FacingDirection, S as SpriteSheetUrls, g as SpriteFrameDims, R as ResolvedFrame, h as CanvasLighting, i as CanvasPost, a as IsometricUnit, j as CameraState, k as FieldInfo, l as OrbitalTraitInfo, m as OrbitalPageInfo, T as TraitLevelData, E as ExternalLink } from '../avl-schema-parser-BZ8pICOS.cjs';
10
- export { B as BoardTile, G as GameAction, n as GamePhase, o as GameState, p as GameUnit, b as IsometricFeature, I as IsometricTile, P as Position, q as UnitTrait, r as calculateAttackTargets, s as calculateValidMoves, t as createInitialGameState } from '../avl-schema-parser-BZ8pICOS.cjs';
11
- import { D as DrawableNode } from '../paintDispatch-D3-5_cOb.cjs';
12
- import { C as ContentSegment, b as DomLayoutData, d as DomStateNode, V as VisualizerConfig, e as DomTransitionLabel } from '../cn-CvImTgKH.cjs';
13
- export { n as cn } from '../cn-CvImTgKH.cjs';
9
+ import { U as UnitAnimationState, F as FacingDirection, S as SpriteSheetUrls, g as SpriteFrameDims, R as ResolvedFrame, h as CanvasLighting, i as CanvasPost, a as IsometricUnit, j as CameraState, k as FieldInfo, l as OrbitalTraitInfo, m as OrbitalPageInfo, T as TraitLevelData, E as ExternalLink } from '../avl-schema-parser-DVmrgdwc.cjs';
10
+ export { B as BoardTile, G as GameAction, n as GamePhase, o as GameState, p as GameUnit, b as IsometricFeature, I as IsometricTile, P as Position, q as UnitTrait, r as calculateAttackTargets, s as calculateValidMoves, t as createInitialGameState } from '../avl-schema-parser-DVmrgdwc.cjs';
11
+ import { D as DrawableNode } from '../paintDispatch-Cb_hQj4Y.cjs';
12
+ import { C as ContentSegment, b as DomLayoutData, d as DomStateNode, V as VisualizerConfig, e as DomTransitionLabel } from '../cn-BdGFhYe3.cjs';
13
+ export { n as cn } from '../cn-BdGFhYe3.cjs';
14
14
  import { b as SlotContent } from '../useUISlots-BesZYMks.cjs';
15
15
  export { D as DEFAULT_SLOTS, S as SlotAnimation, a as SlotChangeCallback, c as SlotRenderConfig, U as UISlotManager, u as useUISlotManager } from '../useUISlots-BesZYMks.cjs';
16
16
  export { ALMADAR_DND_MIME, AuthContextValue, AuthUser, CanvasGestureCallbacks, CanvasGestureHandlers, CompileResult, CompileStage, DragReorderResult, DraggablePayload, Extension, ExtensionManifest, FileSystemFile, FileSystemStatus, GitHubRepo, GitHubStatus, HistoryChangeSummary, HistoryTimelineItem, I18nContextValue, I18nProvider, InfiniteScrollOptions, InfiniteScrollResult, LongPressHandlers, LongPressOptions, OpenFile, Positioned, PullToRefreshOptions, PullToRefreshResult, QuerySingletonEntity, QuerySingletonResult, QuerySingletonState, QueryState, RenderInterpolationHandle, RenderInterpolationOptions, RevertResult, SelectedFile, SharedEntityStore, SharedEntityStoreContext, SharedEntitySubscriber, SharedEntityWriter, SwipeGestureOptions, SwipeGestureResult, SwipeHandlers, TapRevealOptions, TapRevealResult, TraitListenSpec, TranslateFunction, UseCanvasGesturesOptions, UseCompileResult, UseDraggableOptions, UseDraggableResult, UseDropZoneOptions, UseDropZoneResult, UseExtensionsOptions, UseExtensionsResult, UseFileEditorOptions, UseFileEditorResult, UseFileSystemResult, UseOrbitalHistoryOptions, UseOrbitalHistoryResult, createSharedEntityStore, createTranslate, parseQueryBinding, runTickFrame, useAgentChat, useAuthContext, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInfiniteScroll, useLongPress, useMediaQuery, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate, useUIEvents, useValidation } from '../hooks/index.cjs';
@@ -4367,6 +4367,8 @@ interface MenuItem {
4367
4367
  onClick?: () => void;
4368
4368
  /** Event name for pattern compatibility */
4369
4369
  event?: string;
4370
+ /** File URL this item downloads on pick (gesture-driven, `DocumentViewer` precedent). The item's `event` still emits on the bus. */
4371
+ url?: string;
4370
4372
  /** Variant for styling (pattern compatibility) */
4371
4373
  variant?: "default" | "danger";
4372
4374
  /** Sub-menu items */
@@ -6,11 +6,11 @@ import { LucideIcon } from 'lucide-react';
6
6
  import { C as ColorToken, U as UiError, P as Point, L as LinkAction, I as ImageSource } from '../GameAudioProvider-CPGwD49P.js';
7
7
  export { A as AudioManifest, G as GameAudioContext, a as GameAudioContextValue, e as GameAudioControls, b as GameAudioProvider, c as GameAudioProviderProps, R as Rect, S as SoundEntry, f as UseGameAudioOptions, g as useGameAudio, u as useGameAudioContext } from '../GameAudioProvider-CPGwD49P.js';
8
8
  import { SExpr } from '@almadar/evaluator';
9
- import { U as UnitAnimationState, F as FacingDirection, S as SpriteSheetUrls, g as SpriteFrameDims, R as ResolvedFrame, h as CanvasLighting, i as CanvasPost, a as IsometricUnit, j as CameraState, k as FieldInfo, l as OrbitalTraitInfo, m as OrbitalPageInfo, T as TraitLevelData, E as ExternalLink } from '../avl-schema-parser-0hkiHOq3.js';
10
- export { B as BoardTile, G as GameAction, n as GamePhase, o as GameState, p as GameUnit, b as IsometricFeature, I as IsometricTile, P as Position, q as UnitTrait, r as calculateAttackTargets, s as calculateValidMoves, t as createInitialGameState } from '../avl-schema-parser-0hkiHOq3.js';
11
- import { D as DrawableNode } from '../paintDispatch-D3-5_cOb.js';
12
- import { C as ContentSegment, b as DomLayoutData, d as DomStateNode, V as VisualizerConfig, e as DomTransitionLabel } from '../cn-DryTiahe.js';
13
- export { n as cn } from '../cn-DryTiahe.js';
9
+ import { U as UnitAnimationState, F as FacingDirection, S as SpriteSheetUrls, g as SpriteFrameDims, R as ResolvedFrame, h as CanvasLighting, i as CanvasPost, a as IsometricUnit, j as CameraState, k as FieldInfo, l as OrbitalTraitInfo, m as OrbitalPageInfo, T as TraitLevelData, E as ExternalLink } from '../avl-schema-parser-BRJ77Yze.js';
10
+ export { B as BoardTile, G as GameAction, n as GamePhase, o as GameState, p as GameUnit, b as IsometricFeature, I as IsometricTile, P as Position, q as UnitTrait, r as calculateAttackTargets, s as calculateValidMoves, t as createInitialGameState } from '../avl-schema-parser-BRJ77Yze.js';
11
+ import { D as DrawableNode } from '../paintDispatch-Cb_hQj4Y.js';
12
+ import { C as ContentSegment, b as DomLayoutData, d as DomStateNode, V as VisualizerConfig, e as DomTransitionLabel } from '../cn-DNkqAWZK.js';
13
+ export { n as cn } from '../cn-DNkqAWZK.js';
14
14
  import { b as SlotContent } from '../useUISlots-BesZYMks.js';
15
15
  export { D as DEFAULT_SLOTS, S as SlotAnimation, a as SlotChangeCallback, c as SlotRenderConfig, U as UISlotManager, u as useUISlotManager } from '../useUISlots-BesZYMks.js';
16
16
  export { ALMADAR_DND_MIME, AuthContextValue, AuthUser, CanvasGestureCallbacks, CanvasGestureHandlers, CompileResult, CompileStage, DragReorderResult, DraggablePayload, Extension, ExtensionManifest, FileSystemFile, FileSystemStatus, GitHubRepo, GitHubStatus, HistoryChangeSummary, HistoryTimelineItem, I18nContextValue, I18nProvider, InfiniteScrollOptions, InfiniteScrollResult, LongPressHandlers, LongPressOptions, OpenFile, Positioned, PullToRefreshOptions, PullToRefreshResult, QuerySingletonEntity, QuerySingletonResult, QuerySingletonState, QueryState, RenderInterpolationHandle, RenderInterpolationOptions, RevertResult, SelectedFile, SharedEntityStore, SharedEntityStoreContext, SharedEntitySubscriber, SharedEntityWriter, SwipeGestureOptions, SwipeGestureResult, SwipeHandlers, TapRevealOptions, TapRevealResult, TraitListenSpec, TranslateFunction, UseCanvasGesturesOptions, UseCompileResult, UseDraggableOptions, UseDraggableResult, UseDropZoneOptions, UseDropZoneResult, UseExtensionsOptions, UseExtensionsResult, UseFileEditorOptions, UseFileEditorResult, UseFileSystemResult, UseOrbitalHistoryOptions, UseOrbitalHistoryResult, createSharedEntityStore, createTranslate, parseQueryBinding, runTickFrame, useAgentChat, useAuthContext, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInfiniteScroll, useLongPress, useMediaQuery, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSharedEntityStoreContext, useSwipeGesture, useTapReveal, useTraitListens, useTranslate, useUIEvents, useValidation } from '../hooks/index.js';
@@ -4367,6 +4367,8 @@ interface MenuItem {
4367
4367
  onClick?: () => void;
4368
4368
  /** Event name for pattern compatibility */
4369
4369
  event?: string;
4370
+ /** File URL this item downloads on pick (gesture-driven, `DocumentViewer` precedent). The item's `event` still emits on the bus. */
4371
+ url?: string;
4370
4372
  /** Variant for styling (pattern compatibility) */
4371
4373
  variant?: "default" | "danger";
4372
4374
  /** Sub-menu items */