@almadar/ui 5.29.0 → 5.30.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.
@@ -51,8 +51,6 @@ export interface DocumentViewerProps {
51
51
  actions?: readonly DocumentAction[];
52
52
  /** Multiple documents (tabbed view) */
53
53
  documents?: readonly DocumentItem[];
54
- /** Entity name for schema-driven auto-fetch */
55
- entity?: string;
56
54
  /** Loading state */
57
55
  isLoading?: boolean;
58
56
  /** Error state */
@@ -109,9 +109,5 @@ export interface HeaderProps {
109
109
  * Error state (closed circuit)
110
110
  */
111
111
  error?: UiError | null;
112
- /**
113
- * Entity name for schema-driven auto-fetch (closed circuit)
114
- */
115
- entity?: string;
116
112
  }
117
113
  export declare const Header: React.FC<HeaderProps>;
@@ -63,7 +63,5 @@ export interface NavigationProps {
63
63
  isLoading?: boolean;
64
64
  /** Error state */
65
65
  error?: UiError | null;
66
- /** Entity name for schema-driven auto-fetch */
67
- entity?: string;
68
66
  }
69
67
  export declare const Navigation: React.FC<NavigationProps>;
@@ -45,8 +45,6 @@ export interface PageHeaderProps {
45
45
  isLoading?: boolean;
46
46
  /** Error state */
47
47
  error?: UiError | null;
48
- /** Entity name for schema-driven auto-fetch */
49
- entity?: string;
50
48
  /** Tabs for sub-navigation */
51
49
  tabs?: ReadonlyArray<{
52
50
  label: string;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { DeclaredTraitConfig, TraitConfig, TraitConfigValue, AssetCatalog } from '@almadar/core';
2
+ import type { DeclaredTraitConfig, ConfigFieldDeclaration, TraitConfig, TraitConfigValue, AssetCatalog } from '@almadar/core';
3
3
  import type { DisplayStateProps } from '../organisms/types';
4
4
  /**
5
5
  * PropertyInspector — Storybook-style controls panel for a trait's `config`.
@@ -26,4 +26,11 @@ export interface PropertyInspectorProps extends DisplayStateProps {
26
26
  /** Browsable asset catalog supplied to `asset`-typed fields' AssetPicker. */
27
27
  assets?: AssetCatalog;
28
28
  }
29
+ export declare function FieldControl({ name, decl, value, onChange, assets, }: {
30
+ name: string;
31
+ decl: ConfigFieldDeclaration;
32
+ value: TraitConfigValue | undefined;
33
+ onChange: (field: string, value: TraitConfigValue) => void;
34
+ assets?: AssetCatalog;
35
+ }): React.ReactElement;
29
36
  export declare const PropertyInspector: React.FC<PropertyInspectorProps>;
@@ -1756,6 +1756,30 @@ function TileRenderer({
1756
1756
  const x = (tile.x - offsetX) * cellSize;
1757
1757
  const z = ((tile.z ?? tile.y ?? 0) - offsetZ) * cellSize;
1758
1758
  const y = (tile.elevation ?? 0) * 0.1;
1759
+ const position = [x, y, z];
1760
+ if (tile.modelUrl) {
1761
+ return /* @__PURE__ */ jsxRuntime.jsx(
1762
+ "group",
1763
+ {
1764
+ userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
1765
+ onClick: () => onTileClick?.(tile),
1766
+ onPointerEnter: () => onTileHover?.(tile),
1767
+ onPointerLeave: () => onTileHover?.(null),
1768
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1769
+ ModelLoader,
1770
+ {
1771
+ url: tile.modelUrl,
1772
+ position,
1773
+ scale: cellSize * 0.9,
1774
+ fallbackGeometry: "box",
1775
+ castShadow: true,
1776
+ receiveShadow: true
1777
+ }
1778
+ )
1779
+ },
1780
+ tile.id ?? `tile-${tile.x}-${tile.y}`
1781
+ );
1782
+ }
1759
1783
  const colorHex = terrainColors[tile.type || ""] || terrainColors[tile.terrain || ""] || "#808080";
1760
1784
  const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
1761
1785
  const isValidMove = validMoves.some(
@@ -1771,7 +1795,7 @@ function TileRenderer({
1771
1795
  return /* @__PURE__ */ jsxRuntime.jsxs(
1772
1796
  "mesh",
1773
1797
  {
1774
- position: [x, y, z],
1798
+ position,
1775
1799
  userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
1776
1800
  onClick: () => onTileClick?.(tile),
1777
1801
  onPointerEnter: () => onTileHover?.(tile),
@@ -1793,7 +1817,8 @@ function TileRenderer({
1793
1817
  );
1794
1818
  });
1795
1819
  };
1796
- if (useInstancing && tiles.length > 0) {
1820
+ const hasModelTiles = tiles.some((t) => t.modelUrl);
1821
+ if (useInstancing && tiles.length > 0 && !hasModelTiles) {
1797
1822
  return /* @__PURE__ */ jsxRuntime.jsx(
1798
1823
  "instancedMesh",
1799
1824
  {
@@ -1732,6 +1732,30 @@ function TileRenderer({
1732
1732
  const x = (tile.x - offsetX) * cellSize;
1733
1733
  const z = ((tile.z ?? tile.y ?? 0) - offsetZ) * cellSize;
1734
1734
  const y = (tile.elevation ?? 0) * 0.1;
1735
+ const position = [x, y, z];
1736
+ if (tile.modelUrl) {
1737
+ return /* @__PURE__ */ jsx(
1738
+ "group",
1739
+ {
1740
+ userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
1741
+ onClick: () => onTileClick?.(tile),
1742
+ onPointerEnter: () => onTileHover?.(tile),
1743
+ onPointerLeave: () => onTileHover?.(null),
1744
+ children: /* @__PURE__ */ jsx(
1745
+ ModelLoader,
1746
+ {
1747
+ url: tile.modelUrl,
1748
+ position,
1749
+ scale: cellSize * 0.9,
1750
+ fallbackGeometry: "box",
1751
+ castShadow: true,
1752
+ receiveShadow: true
1753
+ }
1754
+ )
1755
+ },
1756
+ tile.id ?? `tile-${tile.x}-${tile.y}`
1757
+ );
1758
+ }
1735
1759
  const colorHex = terrainColors[tile.type || ""] || terrainColors[tile.terrain || ""] || "#808080";
1736
1760
  const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
1737
1761
  const isValidMove = validMoves.some(
@@ -1747,7 +1771,7 @@ function TileRenderer({
1747
1771
  return /* @__PURE__ */ jsxs(
1748
1772
  "mesh",
1749
1773
  {
1750
- position: [x, y, z],
1774
+ position,
1751
1775
  userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
1752
1776
  onClick: () => onTileClick?.(tile),
1753
1777
  onPointerEnter: () => onTileHover?.(tile),
@@ -1769,7 +1793,8 @@ function TileRenderer({
1769
1793
  );
1770
1794
  });
1771
1795
  };
1772
- if (useInstancing && tiles.length > 0) {
1796
+ const hasModelTiles = tiles.some((t) => t.modelUrl);
1797
+ if (useInstancing && tiles.length > 0 && !hasModelTiles) {
1773
1798
  return /* @__PURE__ */ jsx(
1774
1799
  "instancedMesh",
1775
1800
  {
@@ -29,7 +29,9 @@ export type SlotItemData = {
29
29
  description?: string;
30
30
  /** Emoji or text icon */
31
31
  iconEmoji?: string;
32
- /** Image URL icon (takes precedence over iconEmoji) */
32
+ /** Image URL icon (takes precedence over iconEmoji)
33
+ * @default https://almadar-kflow-assets.web.app/shared/platformer/items/platformPack_item001.png
34
+ */
33
35
  iconUrl?: AssetUrl;
34
36
  /** Optional state machine for tooltip display */
35
37
  stateMachine?: TraitStateMachineDefinition;
@@ -31,6 +31,8 @@ export interface IsometricTile {
31
31
  tileType?: string;
32
32
  /** Elevation offset for 3D rendering */
33
33
  elevation?: number;
34
+ /** 3D model URL (GLB format) for GameCanvas3D — rendered via ModelLoader with box fallback */
35
+ modelUrl?: AssetUrl;
34
36
  }
35
37
  /** A unit positioned on the isometric grid */
36
38
  export type IsometricUnit = {