@almadar/ui 5.28.3 → 5.28.5

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.
@@ -15211,14 +15211,22 @@ function BattleTemplate({
15211
15211
  entity,
15212
15212
  scale = 0.45,
15213
15213
  unitScale = 1,
15214
+ tiles,
15215
+ units,
15216
+ features,
15217
+ assetManifest,
15214
15218
  className
15215
15219
  }) {
15216
15220
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
15217
- if (!resolved) return null;
15221
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
15218
15222
  return /* @__PURE__ */ jsxRuntime.jsx(
15219
15223
  BattleBoard,
15220
15224
  {
15221
15225
  entity: resolved,
15226
+ tiles,
15227
+ units,
15228
+ features,
15229
+ assetManifest,
15222
15230
  scale,
15223
15231
  unitScale,
15224
15232
  tileClickEvent: "TILE_CLICK",
@@ -47969,7 +47977,14 @@ var init_useBattleState = __esm({
47969
47977
  init_boardEntity();
47970
47978
  }
47971
47979
  });
47972
- function UncontrolledBattleBoard({ entity, ...rest }) {
47980
+ function UncontrolledBattleBoard({
47981
+ entity,
47982
+ tiles,
47983
+ units,
47984
+ features,
47985
+ assetManifest,
47986
+ ...rest
47987
+ }) {
47973
47988
  const resolved = boardEntity(entity);
47974
47989
  const battleState = useBattleState(
47975
47990
  rows(resolved?.initialUnits),
@@ -47989,19 +48004,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
47989
48004
  calculateDamage: rest.calculateDamage
47990
48005
  }
47991
48006
  );
47992
- if (!resolved) return null;
48007
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
47993
48008
  return /* @__PURE__ */ jsxRuntime.jsx(
47994
48009
  BattleBoard,
47995
48010
  {
47996
48011
  ...rest,
47997
- entity: {
48012
+ tiles,
48013
+ units,
48014
+ features,
48015
+ assetManifest,
48016
+ entity: resolved ? {
47998
48017
  ...resolved,
47999
48018
  units: battleState.units,
48000
48019
  phase: battleState.phase,
48001
48020
  turn: battleState.turn,
48002
48021
  gameResult: battleState.gameResult,
48003
48022
  selectedUnitId: battleState.selectedUnitId
48004
- }
48023
+ } : void 0
48005
48024
  }
48006
48025
  );
48007
48026
  }
@@ -49532,6 +49551,24 @@ function renderPatternProps(props, onDismiss) {
49532
49551
  priority: 0
49533
49552
  };
49534
49553
  rendered[key] = /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss });
49554
+ } else if (Array.isArray(value)) {
49555
+ rendered[key] = value.map((item, i) => {
49556
+ const el = item;
49557
+ if (isPatternConfig(el)) {
49558
+ const nestedProps = {};
49559
+ for (const [k, v] of Object.entries(el)) {
49560
+ if (k !== "type") nestedProps[k] = v;
49561
+ }
49562
+ const childContent = {
49563
+ id: `prop-${key}-${i}`,
49564
+ pattern: el.type,
49565
+ props: nestedProps,
49566
+ priority: 0
49567
+ };
49568
+ return /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss }, i);
49569
+ }
49570
+ return substituteTraitRefsDeep(el, `prop:${key}[${i}]`);
49571
+ });
49535
49572
  } else {
49536
49573
  rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
49537
49574
  }
package/dist/avl/index.js CHANGED
@@ -15162,14 +15162,22 @@ function BattleTemplate({
15162
15162
  entity,
15163
15163
  scale = 0.45,
15164
15164
  unitScale = 1,
15165
+ tiles,
15166
+ units,
15167
+ features,
15168
+ assetManifest,
15165
15169
  className
15166
15170
  }) {
15167
15171
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
15168
- if (!resolved) return null;
15172
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
15169
15173
  return /* @__PURE__ */ jsx(
15170
15174
  BattleBoard,
15171
15175
  {
15172
15176
  entity: resolved,
15177
+ tiles,
15178
+ units,
15179
+ features,
15180
+ assetManifest,
15173
15181
  scale,
15174
15182
  unitScale,
15175
15183
  tileClickEvent: "TILE_CLICK",
@@ -47920,7 +47928,14 @@ var init_useBattleState = __esm({
47920
47928
  init_boardEntity();
47921
47929
  }
47922
47930
  });
47923
- function UncontrolledBattleBoard({ entity, ...rest }) {
47931
+ function UncontrolledBattleBoard({
47932
+ entity,
47933
+ tiles,
47934
+ units,
47935
+ features,
47936
+ assetManifest,
47937
+ ...rest
47938
+ }) {
47924
47939
  const resolved = boardEntity(entity);
47925
47940
  const battleState = useBattleState(
47926
47941
  rows(resolved?.initialUnits),
@@ -47940,19 +47955,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
47940
47955
  calculateDamage: rest.calculateDamage
47941
47956
  }
47942
47957
  );
47943
- if (!resolved) return null;
47958
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
47944
47959
  return /* @__PURE__ */ jsx(
47945
47960
  BattleBoard,
47946
47961
  {
47947
47962
  ...rest,
47948
- entity: {
47963
+ tiles,
47964
+ units,
47965
+ features,
47966
+ assetManifest,
47967
+ entity: resolved ? {
47949
47968
  ...resolved,
47950
47969
  units: battleState.units,
47951
47970
  phase: battleState.phase,
47952
47971
  turn: battleState.turn,
47953
47972
  gameResult: battleState.gameResult,
47954
47973
  selectedUnitId: battleState.selectedUnitId
47955
- }
47974
+ } : void 0
47956
47975
  }
47957
47976
  );
47958
47977
  }
@@ -49483,6 +49502,24 @@ function renderPatternProps(props, onDismiss) {
49483
49502
  priority: 0
49484
49503
  };
49485
49504
  rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
49505
+ } else if (Array.isArray(value)) {
49506
+ rendered[key] = value.map((item, i) => {
49507
+ const el = item;
49508
+ if (isPatternConfig(el)) {
49509
+ const nestedProps = {};
49510
+ for (const [k, v] of Object.entries(el)) {
49511
+ if (k !== "type") nestedProps[k] = v;
49512
+ }
49513
+ const childContent = {
49514
+ id: `prop-${key}-${i}`,
49515
+ pattern: el.type,
49516
+ props: nestedProps,
49517
+ priority: 0
49518
+ };
49519
+ return /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss }, i);
49520
+ }
49521
+ return substituteTraitRefsDeep(el, `prop:${key}[${i}]`);
49522
+ });
49486
49523
  } else {
49487
49524
  rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
49488
49525
  }
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import type { TraitConfigValue } from '@almadar/core';
3
+ export interface NodeSlotEditorProps {
4
+ /** Current node-slot value (a render-ui pattern config, or nothing). */
5
+ value: TraitConfigValue | undefined;
6
+ /** Fired with the next value. */
7
+ onChange: (next: TraitConfigValue) => void;
8
+ /** Additional CSS classes. */
9
+ className?: string;
10
+ }
11
+ /**
12
+ * NodeSlotEditor — edits a `node` config slot (e.g. `children`/`hud`/`debugPanel`).
13
+ * A node slot renders a nested render-ui pattern, so this picks the pattern TYPE
14
+ * from the known-pattern registry and edits that pattern's props as a tree — instead
15
+ * of the read-only "edit in source" fallback. Self-contained `@almadar/ui` atoms.
16
+ */
17
+ export declare const NodeSlotEditor: React.FC<NodeSlotEditorProps>;
@@ -1,5 +1,6 @@
1
1
  export { ErrorBoundary, type ErrorBoundaryProps } from './ErrorBoundary';
2
2
  export { JsonTreeEditor, type JsonTreeEditorProps } from './JsonTreeEditor';
3
+ export { NodeSlotEditor, type NodeSlotEditorProps } from './NodeSlotEditor';
3
4
  export { FileTree, type FileTreeProps, type FileTreeNode } from './FileTree';
4
5
  export { FormField, type FormFieldProps } from './FormField';
5
6
  export { EmptyState, type EmptyStateProps } from './EmptyState';
@@ -16,10 +16,19 @@
16
16
  import * as React from 'react';
17
17
  import type { EntityRow } from '@almadar/core';
18
18
  import { type BattleBoardProps } from './BattleBoard';
19
+ import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
19
20
  export interface UncontrolledBattleBoardProps extends Omit<BattleBoardProps, 'entity'> {
20
21
  entity?: EntityRow | readonly EntityRow[];
22
+ /** Direct tile data — takes priority over entity-derived tiles. */
23
+ tiles?: IsometricTile[];
24
+ /** Direct unit data — takes priority over entity-derived units. */
25
+ units?: IsometricUnit[];
26
+ /** Direct feature data — takes priority over entity-derived features. */
27
+ features?: IsometricFeature[];
28
+ /** Direct asset manifest — takes priority over entity-derived manifest. */
29
+ assetManifest?: BattleBoardProps['assetManifest'];
21
30
  }
22
- export declare function UncontrolledBattleBoard({ entity, ...rest }: UncontrolledBattleBoardProps): React.JSX.Element | null;
31
+ export declare function UncontrolledBattleBoard({ entity, tiles, units, features, assetManifest, ...rest }: UncontrolledBattleBoardProps): React.JSX.Element | null;
23
32
  export declare namespace UncontrolledBattleBoard {
24
33
  var displayName: string;
25
34
  }
@@ -10,14 +10,24 @@
10
10
  */
11
11
  import React from 'react';
12
12
  import type { TemplateProps } from '../../core/templates/types';
13
+ import type { BattleBoardProps } from '../organisms/BattleBoard';
14
+ import type { IsometricTile, IsometricUnit, IsometricFeature } from '../organisms/types/isometric';
13
15
  export type { BattlePhase, BattleSlotContext, } from '../organisms/BattleBoard';
14
16
  export interface BattleTemplateProps extends TemplateProps {
15
17
  /** Canvas render scale */
16
18
  scale?: number;
17
19
  /** Unit draw-size multiplier */
18
20
  unitScale?: number;
21
+ /** Direct tile data — forwarded to BattleBoard; takes priority over entity. */
22
+ tiles?: IsometricTile[];
23
+ /** Direct unit data — forwarded to BattleBoard; takes priority over entity. */
24
+ units?: IsometricUnit[];
25
+ /** Direct feature data — forwarded to BattleBoard; takes priority over entity. */
26
+ features?: IsometricFeature[];
27
+ /** Direct asset manifest — forwarded to BattleBoard; takes priority over entity. */
28
+ assetManifest?: BattleBoardProps['assetManifest'];
19
29
  }
20
- export declare function BattleTemplate({ entity, scale, unitScale, className, }: BattleTemplateProps): React.JSX.Element | null;
30
+ export declare function BattleTemplate({ entity, scale, unitScale, tiles, units, features, assetManifest, className, }: BattleTemplateProps): React.JSX.Element | null;
21
31
  export declare namespace BattleTemplate {
22
32
  var displayName: string;
23
33
  }
@@ -7126,6 +7126,16 @@ var init_Skeleton = __esm({
7126
7126
  Skeleton.displayName = "Skeleton";
7127
7127
  }
7128
7128
  });
7129
+ function getKnownPatterns() {
7130
+ return Object.keys(componentMapping);
7131
+ }
7132
+ var componentMapping;
7133
+ var init_pattern_resolver = __esm({
7134
+ "renderer/pattern-resolver.ts"() {
7135
+ logger.createLogger("almadar:ui:pattern-resolver");
7136
+ componentMapping = {};
7137
+ }
7138
+ });
7129
7139
 
7130
7140
  // renderer/slot-definitions.ts
7131
7141
  function isPortalSlot(slot) {
@@ -9032,7 +9042,7 @@ function getTraitSnapshots() {
9032
9042
  try {
9033
9043
  snapshots.push(getter());
9034
9044
  } catch (err) {
9035
- log3.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
9045
+ log4.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
9036
9046
  }
9037
9047
  }
9038
9048
  return snapshots;
@@ -9110,10 +9120,10 @@ function updateAssetStatus(url, status) {
9110
9120
  window.__orbitalVerification.assetStatus[url] = status;
9111
9121
  }
9112
9122
  }
9113
- var log3;
9123
+ var log4;
9114
9124
  var init_verificationRegistry = __esm({
9115
9125
  "lib/verificationRegistry.ts"() {
9116
- log3 = logger.createLogger("almadar:bridge");
9126
+ log4 = logger.createLogger("almadar:bridge");
9117
9127
  exposeOnWindow();
9118
9128
  }
9119
9129
  });
@@ -10448,14 +10458,22 @@ function BattleTemplate({
10448
10458
  entity,
10449
10459
  scale = 0.45,
10450
10460
  unitScale = 1,
10461
+ tiles,
10462
+ units,
10463
+ features,
10464
+ assetManifest,
10451
10465
  className
10452
10466
  }) {
10453
10467
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
10454
- if (!resolved) return null;
10468
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
10455
10469
  return /* @__PURE__ */ jsxRuntime.jsx(
10456
10470
  BattleBoard,
10457
10471
  {
10458
10472
  entity: resolved,
10473
+ tiles,
10474
+ units,
10475
+ features,
10476
+ assetManifest,
10459
10477
  scale,
10460
10478
  unitScale,
10461
10479
  tileClickEvent: "TILE_CLICK",
@@ -11190,7 +11208,7 @@ var init_avl_elk_layout = __esm({
11190
11208
  elk = new ELK__default.default();
11191
11209
  }
11192
11210
  });
11193
- var log4, SWIM_GUTTER, CENTER_W; exports.BehaviorView = void 0;
11211
+ var log5, SWIM_GUTTER, CENTER_W; exports.BehaviorView = void 0;
11194
11212
  var init_BehaviorView = __esm({
11195
11213
  "components/avl/molecules/BehaviorView.tsx"() {
11196
11214
  "use client";
@@ -11199,7 +11217,7 @@ var init_BehaviorView = __esm({
11199
11217
  init_AvlSwimLane();
11200
11218
  init_types();
11201
11219
  init_avl_elk_layout();
11202
- log4 = logger.createLogger("almadar:ui:avl:behavior-view");
11220
+ log5 = logger.createLogger("almadar:ui:avl:behavior-view");
11203
11221
  SWIM_GUTTER = 120;
11204
11222
  CENTER_W = 360;
11205
11223
  exports.BehaviorView = ({ data }) => {
@@ -11210,7 +11228,7 @@ var init_BehaviorView = __esm({
11210
11228
  const dataKey = React74.useMemo(() => JSON.stringify(traitData), [traitData]);
11211
11229
  React74.useEffect(() => {
11212
11230
  if (!traitData) return;
11213
- computeTraitLayout(traitData).then(setLayout).catch((err) => log4.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
11231
+ computeTraitLayout(traitData).then(setLayout).catch((err) => log5.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
11214
11232
  }, [dataKey]);
11215
11233
  if (!traitData) {
11216
11234
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-[var(--color-border)] bg-[var(--color-card)] p-4 text-center text-[var(--color-muted-foreground)] text-sm", children: t("avl.noTraitData") });
@@ -11717,7 +11735,7 @@ function generateDiff(oldVal, newVal) {
11717
11735
  }
11718
11736
  return diff;
11719
11737
  }
11720
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log5, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS; exports.CodeBlock = void 0;
11738
+ var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS; exports.CodeBlock = void 0;
11721
11739
  var init_CodeBlock = __esm({
11722
11740
  "components/core/molecules/markdown/CodeBlock.tsx"() {
11723
11741
  init_cn();
@@ -11800,7 +11818,7 @@ var init_CodeBlock = __esm({
11800
11818
  "lolo-op-async": { color: syntax.ORB_COLORS.dark.async }
11801
11819
  };
11802
11820
  loloStyle = { ...dark__default.default, ...loloStyleOverrides };
11803
- log5 = logger.createLogger("almadar:ui:markdown-code");
11821
+ log6 = logger.createLogger("almadar:ui:markdown-code");
11804
11822
  CODE_LANGUAGES = [
11805
11823
  "text",
11806
11824
  "json",
@@ -12064,7 +12082,7 @@ var init_CodeBlock = __esm({
12064
12082
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: true });
12065
12083
  setTimeout(() => setCopied(false), 2e3);
12066
12084
  } catch (err) {
12067
- log5.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
12085
+ log6.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
12068
12086
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: false });
12069
12087
  }
12070
12088
  };
@@ -15732,14 +15750,14 @@ function useSafeEventBus2() {
15732
15750
  } };
15733
15751
  }
15734
15752
  }
15735
- var log6, lookStyles4; exports.ButtonGroup = void 0;
15753
+ var log7, lookStyles4; exports.ButtonGroup = void 0;
15736
15754
  var init_ButtonGroup = __esm({
15737
15755
  "components/core/molecules/ButtonGroup.tsx"() {
15738
15756
  "use client";
15739
15757
  init_cn();
15740
15758
  init_atoms2();
15741
15759
  init_useEventBus();
15742
- log6 = logger.createLogger("almadar:ui:button-group");
15760
+ log7 = logger.createLogger("almadar:ui:button-group");
15743
15761
  lookStyles4 = {
15744
15762
  "right-aligned-buttons": "",
15745
15763
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -15820,7 +15838,7 @@ var init_ButtonGroup = __esm({
15820
15838
  {
15821
15839
  variant: "ghost",
15822
15840
  onClick: () => {
15823
- log6.debug("Filter clicked", { field: filter.field });
15841
+ log7.debug("Filter clicked", { field: filter.field });
15824
15842
  },
15825
15843
  children: filter.label
15826
15844
  },
@@ -22513,6 +22531,65 @@ var init_JsonTreeEditor = __esm({
22513
22531
  };
22514
22532
  }
22515
22533
  });
22534
+ function normalize(value) {
22535
+ const wasArray = Array.isArray(value);
22536
+ const pattern = wasArray ? value[0] : value;
22537
+ const type = isObj2(pattern) && typeof pattern["type"] === "string" ? pattern["type"] : "";
22538
+ const props = {};
22539
+ if (isObj2(pattern)) {
22540
+ for (const [k, v] of Object.entries(pattern)) if (k !== "type") props[k] = v;
22541
+ }
22542
+ return { type, props, wasArray };
22543
+ }
22544
+ var isObj2; exports.NodeSlotEditor = void 0;
22545
+ var init_NodeSlotEditor = __esm({
22546
+ "components/core/molecules/NodeSlotEditor.tsx"() {
22547
+ "use client";
22548
+ init_Stack();
22549
+ init_Select();
22550
+ init_Typography();
22551
+ init_JsonTreeEditor();
22552
+ init_pattern_resolver();
22553
+ init_cn();
22554
+ isObj2 = (v) => v !== null && v !== void 0 && typeof v === "object" && !Array.isArray(v);
22555
+ exports.NodeSlotEditor = ({ value, onChange, className }) => {
22556
+ const { type, props, wasArray } = normalize(value);
22557
+ const patterns = React74__namespace.default.useMemo(() => {
22558
+ try {
22559
+ return [...getKnownPatterns()].sort();
22560
+ } catch {
22561
+ return [];
22562
+ }
22563
+ }, []);
22564
+ const options = React74__namespace.default.useMemo(
22565
+ () => [{ value: "", label: "\u2014 none \u2014" }, ...patterns.map((p2) => ({ value: p2, label: p2 }))],
22566
+ [patterns]
22567
+ );
22568
+ const emit = (nextType, nextProps) => {
22569
+ if (!nextType) {
22570
+ onChange(wasArray ? [] : {});
22571
+ return;
22572
+ }
22573
+ const pattern = { type: nextType, ...nextProps };
22574
+ onChange(wasArray || value === void 0 ? [pattern] : pattern);
22575
+ };
22576
+ return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", className: cn("w-full", className), children: [
22577
+ /* @__PURE__ */ jsxRuntime.jsx(
22578
+ exports.Select,
22579
+ {
22580
+ options,
22581
+ value: type,
22582
+ onChange: (e) => emit(e.target.value, props)
22583
+ }
22584
+ ),
22585
+ type !== "" && /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "none", className: "pl-1", children: [
22586
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "muted", children: "props" }),
22587
+ /* @__PURE__ */ jsxRuntime.jsx(exports.JsonTreeEditor, { value: props, onChange: (next) => emit(type, isObj2(next) ? next : {}) })
22588
+ ] })
22589
+ ] });
22590
+ };
22591
+ }
22592
+ });
22516
22593
  function fileIcon(name) {
22517
22594
  const ext = name.split(".").pop()?.toLowerCase() ?? "";
22518
22595
  switch (ext) {
@@ -23861,9 +23938,9 @@ function debug(...args) {
23861
23938
  const [first, ...rest] = args;
23862
23939
  const message = typeof first === "string" ? first : "<debug>";
23863
23940
  if (rest.length === 0 && typeof first === "string") {
23864
- log7.debug(message);
23941
+ log8.debug(message);
23865
23942
  } else {
23866
- log7.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
23943
+ log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
23867
23944
  }
23868
23945
  }
23869
23946
  function debugGroup(label) {
@@ -23891,11 +23968,11 @@ function toLogMetaValue(v) {
23891
23968
  }
23892
23969
  return String(v);
23893
23970
  }
23894
- var NAMESPACE, log7;
23971
+ var NAMESPACE, log8;
23895
23972
  var init_debug = __esm({
23896
23973
  "lib/debug.ts"() {
23897
23974
  NAMESPACE = "almadar:ui:debug";
23898
- log7 = logger.createLogger(NAMESPACE);
23975
+ log8 = logger.createLogger(NAMESPACE);
23899
23976
  logger.createLogger("almadar:ui:debug:input");
23900
23977
  logger.createLogger("almadar:ui:debug:collision");
23901
23978
  logger.createLogger("almadar:ui:debug:physics");
@@ -35276,6 +35353,8 @@ function FieldControl({
35276
35353
  control = /* @__PURE__ */ jsxRuntime.jsx(TextLikeControl, { field: name, numeric: true, value, onCommit: onChange });
35277
35354
  } else if (decl.type === "string") {
35278
35355
  control = /* @__PURE__ */ jsxRuntime.jsx(TextLikeControl, { field: name, numeric: false, value, onCommit: onChange });
35356
+ } else if (decl.type === "node") {
35357
+ control = /* @__PURE__ */ jsxRuntime.jsx(exports.NodeSlotEditor, { value: effectiveValue, onChange: (next) => onChange(name, next) });
35279
35358
  } else if (decl.type.startsWith("[") || Array.isArray(effectiveValue)) {
35280
35359
  const arr = Array.isArray(effectiveValue) ? effectiveValue : [];
35281
35360
  control = /* @__PURE__ */ jsxRuntime.jsx(exports.JsonTreeEditor, { value: arr, onChange: (next) => onChange(name, next) });
@@ -35309,6 +35388,7 @@ var init_PropertyInspector = __esm({
35309
35388
  init_IconPicker();
35310
35389
  init_AssetPicker();
35311
35390
  init_JsonTreeEditor();
35391
+ init_NodeSlotEditor();
35312
35392
  TIER_ORDER = ["presentation", "domain", "policy", "infra", "internal"];
35313
35393
  SCALAR_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "icon", "asset"]);
35314
35394
  exports.PropertyInspector = ({
@@ -37205,6 +37285,7 @@ var init_molecules2 = __esm({
37205
37285
  "components/core/molecules/index.ts"() {
37206
37286
  init_ErrorBoundary();
37207
37287
  init_JsonTreeEditor();
37288
+ init_NodeSlotEditor();
37208
37289
  init_FileTree();
37209
37290
  init_FormField();
37210
37291
  init_EmptyState();
@@ -43406,7 +43487,7 @@ function getAllEvents(traits2) {
43406
43487
  function EventDispatcherTab({ traits: traits2, schema }) {
43407
43488
  const eventBus = useEventBus();
43408
43489
  const { t } = hooks.useTranslate();
43409
- const [log8, setLog] = React74__namespace.useState([]);
43490
+ const [log9, setLog] = React74__namespace.useState([]);
43410
43491
  const prevStatesRef = React74__namespace.useRef(/* @__PURE__ */ new Map());
43411
43492
  React74__namespace.useEffect(() => {
43412
43493
  for (const trait of traits2) {
@@ -43470,9 +43551,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
43470
43551
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
43471
43552
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
43472
43553
  ] }),
43473
- log8.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
43554
+ log9.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
43474
43555
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
43475
- /* @__PURE__ */ jsxRuntime.jsx(exports.Stack, { gap: "xs", children: log8.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "small", className: "font-mono text-xs", children: [
43556
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Stack, { gap: "xs", children: log9.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "small", className: "font-mono text-xs", children: [
43476
43557
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
43477
43558
  " ",
43478
43559
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -46636,7 +46717,14 @@ var init_useBattleState = __esm({
46636
46717
  init_boardEntity();
46637
46718
  }
46638
46719
  });
46639
- function UncontrolledBattleBoard({ entity, ...rest }) {
46720
+ function UncontrolledBattleBoard({
46721
+ entity,
46722
+ tiles,
46723
+ units,
46724
+ features,
46725
+ assetManifest,
46726
+ ...rest
46727
+ }) {
46640
46728
  const resolved = boardEntity(entity);
46641
46729
  const battleState = useBattleState(
46642
46730
  rows(resolved?.initialUnits),
@@ -46656,19 +46744,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
46656
46744
  calculateDamage: rest.calculateDamage
46657
46745
  }
46658
46746
  );
46659
- if (!resolved) return null;
46747
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
46660
46748
  return /* @__PURE__ */ jsxRuntime.jsx(
46661
46749
  BattleBoard,
46662
46750
  {
46663
46751
  ...rest,
46664
- entity: {
46752
+ tiles,
46753
+ units,
46754
+ features,
46755
+ assetManifest,
46756
+ entity: resolved ? {
46665
46757
  ...resolved,
46666
46758
  units: battleState.units,
46667
46759
  phase: battleState.phase,
46668
46760
  turn: battleState.turn,
46669
46761
  gameResult: battleState.gameResult,
46670
46762
  selectedUnitId: battleState.selectedUnitId
46671
- }
46763
+ } : void 0
46672
46764
  }
46673
46765
  );
46674
46766
  }
@@ -48283,6 +48375,24 @@ function renderPatternProps(props, onDismiss) {
48283
48375
  priority: 0
48284
48376
  };
48285
48377
  rendered[key] = /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss });
48378
+ } else if (Array.isArray(value)) {
48379
+ rendered[key] = value.map((item, i) => {
48380
+ const el = item;
48381
+ if (isPatternConfig(el)) {
48382
+ const nestedProps = {};
48383
+ for (const [k, v] of Object.entries(el)) {
48384
+ if (k !== "type") nestedProps[k] = v;
48385
+ }
48386
+ const childContent = {
48387
+ id: `prop-${key}-${i}`,
48388
+ pattern: el.type,
48389
+ props: nestedProps,
48390
+ priority: 0
48391
+ };
48392
+ return /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss }, i);
48393
+ }
48394
+ return substituteTraitRefsDeep(el, `prop:${key}[${i}]`);
48395
+ });
48286
48396
  } else {
48287
48397
  rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
48288
48398
  }
@@ -7078,6 +7078,16 @@ var init_Skeleton = __esm({
7078
7078
  Skeleton.displayName = "Skeleton";
7079
7079
  }
7080
7080
  });
7081
+ function getKnownPatterns() {
7082
+ return Object.keys(componentMapping);
7083
+ }
7084
+ var componentMapping;
7085
+ var init_pattern_resolver = __esm({
7086
+ "renderer/pattern-resolver.ts"() {
7087
+ createLogger("almadar:ui:pattern-resolver");
7088
+ componentMapping = {};
7089
+ }
7090
+ });
7081
7091
 
7082
7092
  // renderer/slot-definitions.ts
7083
7093
  function isPortalSlot(slot) {
@@ -8984,7 +8994,7 @@ function getTraitSnapshots() {
8984
8994
  try {
8985
8995
  snapshots.push(getter());
8986
8996
  } catch (err) {
8987
- log3.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
8997
+ log4.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
8988
8998
  }
8989
8999
  }
8990
9000
  return snapshots;
@@ -9062,10 +9072,10 @@ function updateAssetStatus(url, status) {
9062
9072
  window.__orbitalVerification.assetStatus[url] = status;
9063
9073
  }
9064
9074
  }
9065
- var log3;
9075
+ var log4;
9066
9076
  var init_verificationRegistry = __esm({
9067
9077
  "lib/verificationRegistry.ts"() {
9068
- log3 = createLogger("almadar:bridge");
9078
+ log4 = createLogger("almadar:bridge");
9069
9079
  exposeOnWindow();
9070
9080
  }
9071
9081
  });
@@ -10400,14 +10410,22 @@ function BattleTemplate({
10400
10410
  entity,
10401
10411
  scale = 0.45,
10402
10412
  unitScale = 1,
10413
+ tiles,
10414
+ units,
10415
+ features,
10416
+ assetManifest,
10403
10417
  className
10404
10418
  }) {
10405
10419
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
10406
- if (!resolved) return null;
10420
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
10407
10421
  return /* @__PURE__ */ jsx(
10408
10422
  BattleBoard,
10409
10423
  {
10410
10424
  entity: resolved,
10425
+ tiles,
10426
+ units,
10427
+ features,
10428
+ assetManifest,
10411
10429
  scale,
10412
10430
  unitScale,
10413
10431
  tileClickEvent: "TILE_CLICK",
@@ -11142,7 +11160,7 @@ var init_avl_elk_layout = __esm({
11142
11160
  elk = new ELK();
11143
11161
  }
11144
11162
  });
11145
- var log4, SWIM_GUTTER, CENTER_W, BehaviorView;
11163
+ var log5, SWIM_GUTTER, CENTER_W, BehaviorView;
11146
11164
  var init_BehaviorView = __esm({
11147
11165
  "components/avl/molecules/BehaviorView.tsx"() {
11148
11166
  "use client";
@@ -11151,7 +11169,7 @@ var init_BehaviorView = __esm({
11151
11169
  init_AvlSwimLane();
11152
11170
  init_types();
11153
11171
  init_avl_elk_layout();
11154
- log4 = createLogger("almadar:ui:avl:behavior-view");
11172
+ log5 = createLogger("almadar:ui:avl:behavior-view");
11155
11173
  SWIM_GUTTER = 120;
11156
11174
  CENTER_W = 360;
11157
11175
  BehaviorView = ({ data }) => {
@@ -11162,7 +11180,7 @@ var init_BehaviorView = __esm({
11162
11180
  const dataKey = useMemo(() => JSON.stringify(traitData), [traitData]);
11163
11181
  useEffect(() => {
11164
11182
  if (!traitData) return;
11165
- computeTraitLayout(traitData).then(setLayout).catch((err) => log4.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
11183
+ computeTraitLayout(traitData).then(setLayout).catch((err) => log5.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
11166
11184
  }, [dataKey]);
11167
11185
  if (!traitData) {
11168
11186
  return /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-[var(--color-border)] bg-[var(--color-card)] p-4 text-center text-[var(--color-muted-foreground)] text-sm", children: t("avl.noTraitData") });
@@ -11669,7 +11687,7 @@ function generateDiff(oldVal, newVal) {
11669
11687
  }
11670
11688
  return diff;
11671
11689
  }
11672
- var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log5, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
11690
+ var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
11673
11691
  var init_CodeBlock = __esm({
11674
11692
  "components/core/molecules/markdown/CodeBlock.tsx"() {
11675
11693
  init_cn();
@@ -11752,7 +11770,7 @@ var init_CodeBlock = __esm({
11752
11770
  "lolo-op-async": { color: ORB_COLORS.dark.async }
11753
11771
  };
11754
11772
  loloStyle = { ...dark, ...loloStyleOverrides };
11755
- log5 = createLogger("almadar:ui:markdown-code");
11773
+ log6 = createLogger("almadar:ui:markdown-code");
11756
11774
  CODE_LANGUAGES = [
11757
11775
  "text",
11758
11776
  "json",
@@ -12016,7 +12034,7 @@ var init_CodeBlock = __esm({
12016
12034
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: true });
12017
12035
  setTimeout(() => setCopied(false), 2e3);
12018
12036
  } catch (err) {
12019
- log5.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
12037
+ log6.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
12020
12038
  eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: false });
12021
12039
  }
12022
12040
  };
@@ -15684,14 +15702,14 @@ function useSafeEventBus2() {
15684
15702
  } };
15685
15703
  }
15686
15704
  }
15687
- var log6, lookStyles4, ButtonGroup;
15705
+ var log7, lookStyles4, ButtonGroup;
15688
15706
  var init_ButtonGroup = __esm({
15689
15707
  "components/core/molecules/ButtonGroup.tsx"() {
15690
15708
  "use client";
15691
15709
  init_cn();
15692
15710
  init_atoms2();
15693
15711
  init_useEventBus();
15694
- log6 = createLogger("almadar:ui:button-group");
15712
+ log7 = createLogger("almadar:ui:button-group");
15695
15713
  lookStyles4 = {
15696
15714
  "right-aligned-buttons": "",
15697
15715
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -15772,7 +15790,7 @@ var init_ButtonGroup = __esm({
15772
15790
  {
15773
15791
  variant: "ghost",
15774
15792
  onClick: () => {
15775
- log6.debug("Filter clicked", { field: filter.field });
15793
+ log7.debug("Filter clicked", { field: filter.field });
15776
15794
  },
15777
15795
  children: filter.label
15778
15796
  },
@@ -22465,6 +22483,65 @@ var init_JsonTreeEditor = __esm({
22465
22483
  };
22466
22484
  }
22467
22485
  });
22486
+ function normalize(value) {
22487
+ const wasArray = Array.isArray(value);
22488
+ const pattern = wasArray ? value[0] : value;
22489
+ const type = isObj2(pattern) && typeof pattern["type"] === "string" ? pattern["type"] : "";
22490
+ const props = {};
22491
+ if (isObj2(pattern)) {
22492
+ for (const [k, v] of Object.entries(pattern)) if (k !== "type") props[k] = v;
22493
+ }
22494
+ return { type, props, wasArray };
22495
+ }
22496
+ var isObj2, NodeSlotEditor;
22497
+ var init_NodeSlotEditor = __esm({
22498
+ "components/core/molecules/NodeSlotEditor.tsx"() {
22499
+ "use client";
22500
+ init_Stack();
22501
+ init_Select();
22502
+ init_Typography();
22503
+ init_JsonTreeEditor();
22504
+ init_pattern_resolver();
22505
+ init_cn();
22506
+ isObj2 = (v) => v !== null && v !== void 0 && typeof v === "object" && !Array.isArray(v);
22507
+ NodeSlotEditor = ({ value, onChange, className }) => {
22508
+ const { type, props, wasArray } = normalize(value);
22509
+ const patterns = React74__default.useMemo(() => {
22510
+ try {
22511
+ return [...getKnownPatterns()].sort();
22512
+ } catch {
22513
+ return [];
22514
+ }
22515
+ }, []);
22516
+ const options = React74__default.useMemo(
22517
+ () => [{ value: "", label: "\u2014 none \u2014" }, ...patterns.map((p2) => ({ value: p2, label: p2 }))],
22518
+ [patterns]
22519
+ );
22520
+ const emit = (nextType, nextProps) => {
22521
+ if (!nextType) {
22522
+ onChange(wasArray ? [] : {});
22523
+ return;
22524
+ }
22525
+ const pattern = { type: nextType, ...nextProps };
22526
+ onChange(wasArray || value === void 0 ? [pattern] : pattern);
22527
+ };
22528
+ return /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: cn("w-full", className), children: [
22529
+ /* @__PURE__ */ jsx(
22530
+ Select,
22531
+ {
22532
+ options,
22533
+ value: type,
22534
+ onChange: (e) => emit(e.target.value, props)
22535
+ }
22536
+ ),
22537
+ type !== "" && /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "pl-1", children: [
22538
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: "props" }),
22539
+ /* @__PURE__ */ jsx(JsonTreeEditor, { value: props, onChange: (next) => emit(type, isObj2(next) ? next : {}) })
22540
+ ] })
22541
+ ] });
22542
+ };
22543
+ }
22544
+ });
22468
22545
  function fileIcon(name) {
22469
22546
  const ext = name.split(".").pop()?.toLowerCase() ?? "";
22470
22547
  switch (ext) {
@@ -23813,9 +23890,9 @@ function debug(...args) {
23813
23890
  const [first, ...rest] = args;
23814
23891
  const message = typeof first === "string" ? first : "<debug>";
23815
23892
  if (rest.length === 0 && typeof first === "string") {
23816
- log7.debug(message);
23893
+ log8.debug(message);
23817
23894
  } else {
23818
- log7.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
23895
+ log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
23819
23896
  }
23820
23897
  }
23821
23898
  function debugGroup(label) {
@@ -23843,11 +23920,11 @@ function toLogMetaValue(v) {
23843
23920
  }
23844
23921
  return String(v);
23845
23922
  }
23846
- var NAMESPACE, log7;
23923
+ var NAMESPACE, log8;
23847
23924
  var init_debug = __esm({
23848
23925
  "lib/debug.ts"() {
23849
23926
  NAMESPACE = "almadar:ui:debug";
23850
- log7 = createLogger(NAMESPACE);
23927
+ log8 = createLogger(NAMESPACE);
23851
23928
  createLogger("almadar:ui:debug:input");
23852
23929
  createLogger("almadar:ui:debug:collision");
23853
23930
  createLogger("almadar:ui:debug:physics");
@@ -35228,6 +35305,8 @@ function FieldControl({
35228
35305
  control = /* @__PURE__ */ jsx(TextLikeControl, { field: name, numeric: true, value, onCommit: onChange });
35229
35306
  } else if (decl.type === "string") {
35230
35307
  control = /* @__PURE__ */ jsx(TextLikeControl, { field: name, numeric: false, value, onCommit: onChange });
35308
+ } else if (decl.type === "node") {
35309
+ control = /* @__PURE__ */ jsx(NodeSlotEditor, { value: effectiveValue, onChange: (next) => onChange(name, next) });
35231
35310
  } else if (decl.type.startsWith("[") || Array.isArray(effectiveValue)) {
35232
35311
  const arr = Array.isArray(effectiveValue) ? effectiveValue : [];
35233
35312
  control = /* @__PURE__ */ jsx(JsonTreeEditor, { value: arr, onChange: (next) => onChange(name, next) });
@@ -35261,6 +35340,7 @@ var init_PropertyInspector = __esm({
35261
35340
  init_IconPicker();
35262
35341
  init_AssetPicker();
35263
35342
  init_JsonTreeEditor();
35343
+ init_NodeSlotEditor();
35264
35344
  TIER_ORDER = ["presentation", "domain", "policy", "infra", "internal"];
35265
35345
  SCALAR_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "icon", "asset"]);
35266
35346
  PropertyInspector = ({
@@ -37157,6 +37237,7 @@ var init_molecules2 = __esm({
37157
37237
  "components/core/molecules/index.ts"() {
37158
37238
  init_ErrorBoundary();
37159
37239
  init_JsonTreeEditor();
37240
+ init_NodeSlotEditor();
37160
37241
  init_FileTree();
37161
37242
  init_FormField();
37162
37243
  init_EmptyState();
@@ -43358,7 +43439,7 @@ function getAllEvents(traits2) {
43358
43439
  function EventDispatcherTab({ traits: traits2, schema }) {
43359
43440
  const eventBus = useEventBus();
43360
43441
  const { t } = useTranslate();
43361
- const [log8, setLog] = React74.useState([]);
43442
+ const [log9, setLog] = React74.useState([]);
43362
43443
  const prevStatesRef = React74.useRef(/* @__PURE__ */ new Map());
43363
43444
  React74.useEffect(() => {
43364
43445
  for (const trait of traits2) {
@@ -43422,9 +43503,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
43422
43503
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
43423
43504
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
43424
43505
  ] }),
43425
- log8.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
43506
+ log9.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
43426
43507
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
43427
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log8.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
43508
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log9.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
43428
43509
  /* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
43429
43510
  " ",
43430
43511
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -46588,7 +46669,14 @@ var init_useBattleState = __esm({
46588
46669
  init_boardEntity();
46589
46670
  }
46590
46671
  });
46591
- function UncontrolledBattleBoard({ entity, ...rest }) {
46672
+ function UncontrolledBattleBoard({
46673
+ entity,
46674
+ tiles,
46675
+ units,
46676
+ features,
46677
+ assetManifest,
46678
+ ...rest
46679
+ }) {
46592
46680
  const resolved = boardEntity(entity);
46593
46681
  const battleState = useBattleState(
46594
46682
  rows(resolved?.initialUnits),
@@ -46608,19 +46696,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
46608
46696
  calculateDamage: rest.calculateDamage
46609
46697
  }
46610
46698
  );
46611
- if (!resolved) return null;
46699
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
46612
46700
  return /* @__PURE__ */ jsx(
46613
46701
  BattleBoard,
46614
46702
  {
46615
46703
  ...rest,
46616
- entity: {
46704
+ tiles,
46705
+ units,
46706
+ features,
46707
+ assetManifest,
46708
+ entity: resolved ? {
46617
46709
  ...resolved,
46618
46710
  units: battleState.units,
46619
46711
  phase: battleState.phase,
46620
46712
  turn: battleState.turn,
46621
46713
  gameResult: battleState.gameResult,
46622
46714
  selectedUnitId: battleState.selectedUnitId
46623
- }
46715
+ } : void 0
46624
46716
  }
46625
46717
  );
46626
46718
  }
@@ -48235,6 +48327,24 @@ function renderPatternProps(props, onDismiss) {
48235
48327
  priority: 0
48236
48328
  };
48237
48329
  rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
48330
+ } else if (Array.isArray(value)) {
48331
+ rendered[key] = value.map((item, i) => {
48332
+ const el = item;
48333
+ if (isPatternConfig(el)) {
48334
+ const nestedProps = {};
48335
+ for (const [k, v] of Object.entries(el)) {
48336
+ if (k !== "type") nestedProps[k] = v;
48337
+ }
48338
+ const childContent = {
48339
+ id: `prop-${key}-${i}`,
48340
+ pattern: el.type,
48341
+ props: nestedProps,
48342
+ priority: 0
48343
+ };
48344
+ return /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss }, i);
48345
+ }
48346
+ return substituteTraitRefsDeep(el, `prop:${key}[${i}]`);
48347
+ });
48238
48348
  } else {
48239
48349
  rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
48240
48350
  }
@@ -49798,4 +49908,4 @@ init_AboutPageTemplate();
49798
49908
  // components/index.ts
49799
49909
  init_cn();
49800
49910
 
49801
- export { ALL_PRESETS, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BehaviorView, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CollapsibleSection, CombatLog, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ContentSection, ControlButton, CounterTemplate, CraftingRecipe, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBox, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FeatureRenderer2 as FeatureRenderer, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HealthPanel, HeroOrganism, HeroSection, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, SectionHeader, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, cn, combatAnimations, combatClasses, combatEffects, createInitialGameState, createUnitAnimationState, drawSprite, generateCombatMessage, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, mapBookData, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, springOscillator, tickAnimationState, toCodeLanguage, transitionAnimation, useAnchorRect, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache, usePhysics2D, useSpriteAnimations };
49911
+ export { ALL_PRESETS, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BehaviorView, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CollapsibleSection, CombatLog, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ContentSection, ControlButton, CounterTemplate, CraftingRecipe, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBox, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FeatureRenderer2 as FeatureRenderer, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HealthPanel, HeroOrganism, HeroSection, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, SectionHeader, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, cn, combatAnimations, combatClasses, combatEffects, createInitialGameState, createUnitAnimationState, drawSprite, generateCombatMessage, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, mapBookData, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, springOscillator, tickAnimationState, toCodeLanguage, transitionAnimation, useAnchorRect, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache, usePhysics2D, useSpriteAnimations };
@@ -11905,14 +11905,22 @@ function BattleTemplate({
11905
11905
  entity,
11906
11906
  scale = 0.45,
11907
11907
  unitScale = 1,
11908
+ tiles,
11909
+ units,
11910
+ features,
11911
+ assetManifest,
11908
11912
  className
11909
11913
  }) {
11910
11914
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
11911
- if (!resolved) return null;
11915
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
11912
11916
  return /* @__PURE__ */ jsxRuntime.jsx(
11913
11917
  BattleBoard,
11914
11918
  {
11915
11919
  entity: resolved,
11920
+ tiles,
11921
+ units,
11922
+ features,
11923
+ assetManifest,
11916
11924
  scale,
11917
11925
  unitScale,
11918
11926
  tileClickEvent: "TILE_CLICK",
@@ -45882,7 +45890,14 @@ var init_useBattleState = __esm({
45882
45890
  init_boardEntity();
45883
45891
  }
45884
45892
  });
45885
- function UncontrolledBattleBoard({ entity, ...rest }) {
45893
+ function UncontrolledBattleBoard({
45894
+ entity,
45895
+ tiles,
45896
+ units,
45897
+ features,
45898
+ assetManifest,
45899
+ ...rest
45900
+ }) {
45886
45901
  const resolved = boardEntity(entity);
45887
45902
  const battleState = useBattleState(
45888
45903
  rows(resolved?.initialUnits),
@@ -45902,19 +45917,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
45902
45917
  calculateDamage: rest.calculateDamage
45903
45918
  }
45904
45919
  );
45905
- if (!resolved) return null;
45920
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
45906
45921
  return /* @__PURE__ */ jsxRuntime.jsx(
45907
45922
  BattleBoard,
45908
45923
  {
45909
45924
  ...rest,
45910
- entity: {
45925
+ tiles,
45926
+ units,
45927
+ features,
45928
+ assetManifest,
45929
+ entity: resolved ? {
45911
45930
  ...resolved,
45912
45931
  units: battleState.units,
45913
45932
  phase: battleState.phase,
45914
45933
  turn: battleState.turn,
45915
45934
  gameResult: battleState.gameResult,
45916
45935
  selectedUnitId: battleState.selectedUnitId
45917
- }
45936
+ } : void 0
45918
45937
  }
45919
45938
  );
45920
45939
  }
@@ -47445,6 +47464,24 @@ function renderPatternProps(props, onDismiss) {
47445
47464
  priority: 0
47446
47465
  };
47447
47466
  rendered[key] = /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss });
47467
+ } else if (Array.isArray(value)) {
47468
+ rendered[key] = value.map((item, i) => {
47469
+ const el = item;
47470
+ if (isPatternConfig(el)) {
47471
+ const nestedProps = {};
47472
+ for (const [k, v] of Object.entries(el)) {
47473
+ if (k !== "type") nestedProps[k] = v;
47474
+ }
47475
+ const childContent = {
47476
+ id: `prop-${key}-${i}`,
47477
+ pattern: el.type,
47478
+ props: nestedProps,
47479
+ priority: 0
47480
+ };
47481
+ return /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss }, i);
47482
+ }
47483
+ return substituteTraitRefsDeep(el, `prop:${key}[${i}]`);
47484
+ });
47448
47485
  } else {
47449
47486
  rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
47450
47487
  }
@@ -11856,14 +11856,22 @@ function BattleTemplate({
11856
11856
  entity,
11857
11857
  scale = 0.45,
11858
11858
  unitScale = 1,
11859
+ tiles,
11860
+ units,
11861
+ features,
11862
+ assetManifest,
11859
11863
  className
11860
11864
  }) {
11861
11865
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
11862
- if (!resolved) return null;
11866
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
11863
11867
  return /* @__PURE__ */ jsx(
11864
11868
  BattleBoard,
11865
11869
  {
11866
11870
  entity: resolved,
11871
+ tiles,
11872
+ units,
11873
+ features,
11874
+ assetManifest,
11867
11875
  scale,
11868
11876
  unitScale,
11869
11877
  tileClickEvent: "TILE_CLICK",
@@ -45833,7 +45841,14 @@ var init_useBattleState = __esm({
45833
45841
  init_boardEntity();
45834
45842
  }
45835
45843
  });
45836
- function UncontrolledBattleBoard({ entity, ...rest }) {
45844
+ function UncontrolledBattleBoard({
45845
+ entity,
45846
+ tiles,
45847
+ units,
45848
+ features,
45849
+ assetManifest,
45850
+ ...rest
45851
+ }) {
45837
45852
  const resolved = boardEntity(entity);
45838
45853
  const battleState = useBattleState(
45839
45854
  rows(resolved?.initialUnits),
@@ -45853,19 +45868,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
45853
45868
  calculateDamage: rest.calculateDamage
45854
45869
  }
45855
45870
  );
45856
- if (!resolved) return null;
45871
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
45857
45872
  return /* @__PURE__ */ jsx(
45858
45873
  BattleBoard,
45859
45874
  {
45860
45875
  ...rest,
45861
- entity: {
45876
+ tiles,
45877
+ units,
45878
+ features,
45879
+ assetManifest,
45880
+ entity: resolved ? {
45862
45881
  ...resolved,
45863
45882
  units: battleState.units,
45864
45883
  phase: battleState.phase,
45865
45884
  turn: battleState.turn,
45866
45885
  gameResult: battleState.gameResult,
45867
45886
  selectedUnitId: battleState.selectedUnitId
45868
- }
45887
+ } : void 0
45869
45888
  }
45870
45889
  );
45871
45890
  }
@@ -47396,6 +47415,24 @@ function renderPatternProps(props, onDismiss) {
47396
47415
  priority: 0
47397
47416
  };
47398
47417
  rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
47418
+ } else if (Array.isArray(value)) {
47419
+ rendered[key] = value.map((item, i) => {
47420
+ const el = item;
47421
+ if (isPatternConfig(el)) {
47422
+ const nestedProps = {};
47423
+ for (const [k, v] of Object.entries(el)) {
47424
+ if (k !== "type") nestedProps[k] = v;
47425
+ }
47426
+ const childContent = {
47427
+ id: `prop-${key}-${i}`,
47428
+ pattern: el.type,
47429
+ props: nestedProps,
47430
+ priority: 0
47431
+ };
47432
+ return /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss }, i);
47433
+ }
47434
+ return substituteTraitRefsDeep(el, `prop:${key}[${i}]`);
47435
+ });
47399
47436
  } else {
47400
47437
  rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
47401
47438
  }
@@ -11472,14 +11472,22 @@ function BattleTemplate({
11472
11472
  entity,
11473
11473
  scale = 0.45,
11474
11474
  unitScale = 1,
11475
+ tiles,
11476
+ units,
11477
+ features,
11478
+ assetManifest,
11475
11479
  className
11476
11480
  }) {
11477
11481
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
11478
- if (!resolved) return null;
11482
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
11479
11483
  return /* @__PURE__ */ jsxRuntime.jsx(
11480
11484
  BattleBoard,
11481
11485
  {
11482
11486
  entity: resolved,
11487
+ tiles,
11488
+ units,
11489
+ features,
11490
+ assetManifest,
11483
11491
  scale,
11484
11492
  unitScale,
11485
11493
  tileClickEvent: "TILE_CLICK",
@@ -45468,7 +45476,14 @@ var init_useBattleState = __esm({
45468
45476
  init_boardEntity();
45469
45477
  }
45470
45478
  });
45471
- function UncontrolledBattleBoard({ entity, ...rest }) {
45479
+ function UncontrolledBattleBoard({
45480
+ entity,
45481
+ tiles,
45482
+ units,
45483
+ features,
45484
+ assetManifest,
45485
+ ...rest
45486
+ }) {
45472
45487
  const resolved = boardEntity(entity);
45473
45488
  const battleState = useBattleState(
45474
45489
  rows(resolved?.initialUnits),
@@ -45488,19 +45503,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
45488
45503
  calculateDamage: rest.calculateDamage
45489
45504
  }
45490
45505
  );
45491
- if (!resolved) return null;
45506
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
45492
45507
  return /* @__PURE__ */ jsxRuntime.jsx(
45493
45508
  BattleBoard,
45494
45509
  {
45495
45510
  ...rest,
45496
- entity: {
45511
+ tiles,
45512
+ units,
45513
+ features,
45514
+ assetManifest,
45515
+ entity: resolved ? {
45497
45516
  ...resolved,
45498
45517
  units: battleState.units,
45499
45518
  phase: battleState.phase,
45500
45519
  turn: battleState.turn,
45501
45520
  gameResult: battleState.gameResult,
45502
45521
  selectedUnitId: battleState.selectedUnitId
45503
- }
45522
+ } : void 0
45504
45523
  }
45505
45524
  );
45506
45525
  }
@@ -47031,6 +47050,24 @@ function renderPatternProps(props, onDismiss) {
47031
47050
  priority: 0
47032
47051
  };
47033
47052
  rendered[key] = /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss });
47053
+ } else if (Array.isArray(value)) {
47054
+ rendered[key] = value.map((item, i) => {
47055
+ const el = item;
47056
+ if (isPatternConfig(el)) {
47057
+ const nestedProps = {};
47058
+ for (const [k, v] of Object.entries(el)) {
47059
+ if (k !== "type") nestedProps[k] = v;
47060
+ }
47061
+ const childContent = {
47062
+ id: `prop-${key}-${i}`,
47063
+ pattern: el.type,
47064
+ props: nestedProps,
47065
+ priority: 0
47066
+ };
47067
+ return /* @__PURE__ */ jsxRuntime.jsx(SlotContentRenderer, { content: childContent, onDismiss }, i);
47068
+ }
47069
+ return substituteTraitRefsDeep(el, `prop:${key}[${i}]`);
47070
+ });
47034
47071
  } else {
47035
47072
  rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
47036
47073
  }
@@ -11423,14 +11423,22 @@ function BattleTemplate({
11423
11423
  entity,
11424
11424
  scale = 0.45,
11425
11425
  unitScale = 1,
11426
+ tiles,
11427
+ units,
11428
+ features,
11429
+ assetManifest,
11426
11430
  className
11427
11431
  }) {
11428
11432
  const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
11429
- if (!resolved) return null;
11433
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
11430
11434
  return /* @__PURE__ */ jsx(
11431
11435
  BattleBoard,
11432
11436
  {
11433
11437
  entity: resolved,
11438
+ tiles,
11439
+ units,
11440
+ features,
11441
+ assetManifest,
11434
11442
  scale,
11435
11443
  unitScale,
11436
11444
  tileClickEvent: "TILE_CLICK",
@@ -45419,7 +45427,14 @@ var init_useBattleState = __esm({
45419
45427
  init_boardEntity();
45420
45428
  }
45421
45429
  });
45422
- function UncontrolledBattleBoard({ entity, ...rest }) {
45430
+ function UncontrolledBattleBoard({
45431
+ entity,
45432
+ tiles,
45433
+ units,
45434
+ features,
45435
+ assetManifest,
45436
+ ...rest
45437
+ }) {
45423
45438
  const resolved = boardEntity(entity);
45424
45439
  const battleState = useBattleState(
45425
45440
  rows(resolved?.initialUnits),
@@ -45439,19 +45454,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
45439
45454
  calculateDamage: rest.calculateDamage
45440
45455
  }
45441
45456
  );
45442
- if (!resolved) return null;
45457
+ if (!resolved && !tiles && !units && !features && !assetManifest) return null;
45443
45458
  return /* @__PURE__ */ jsx(
45444
45459
  BattleBoard,
45445
45460
  {
45446
45461
  ...rest,
45447
- entity: {
45462
+ tiles,
45463
+ units,
45464
+ features,
45465
+ assetManifest,
45466
+ entity: resolved ? {
45448
45467
  ...resolved,
45449
45468
  units: battleState.units,
45450
45469
  phase: battleState.phase,
45451
45470
  turn: battleState.turn,
45452
45471
  gameResult: battleState.gameResult,
45453
45472
  selectedUnitId: battleState.selectedUnitId
45454
- }
45473
+ } : void 0
45455
45474
  }
45456
45475
  );
45457
45476
  }
@@ -46982,6 +47001,24 @@ function renderPatternProps(props, onDismiss) {
46982
47001
  priority: 0
46983
47002
  };
46984
47003
  rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
47004
+ } else if (Array.isArray(value)) {
47005
+ rendered[key] = value.map((item, i) => {
47006
+ const el = item;
47007
+ if (isPatternConfig(el)) {
47008
+ const nestedProps = {};
47009
+ for (const [k, v] of Object.entries(el)) {
47010
+ if (k !== "type") nestedProps[k] = v;
47011
+ }
47012
+ const childContent = {
47013
+ id: `prop-${key}-${i}`,
47014
+ pattern: el.type,
47015
+ props: nestedProps,
47016
+ priority: 0
47017
+ };
47018
+ return /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss }, i);
47019
+ }
47020
+ return substituteTraitRefsDeep(el, `prop:${key}[${i}]`);
47021
+ });
46985
47022
  } else {
46986
47023
  rendered[key] = substituteTraitRefsDeep(value, `prop:${key}`);
46987
47024
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.28.3",
3
+ "version": "5.28.5",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [