@almadar/ui 5.28.5 → 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.
Files changed (55) hide show
  1. package/dist/avl/index.cjs +178 -113
  2. package/dist/avl/index.js +178 -113
  3. package/dist/components/core/molecules/DocumentViewer.d.ts +0 -2
  4. package/dist/components/core/molecules/Header.d.ts +0 -4
  5. package/dist/components/core/molecules/Navigation.d.ts +0 -2
  6. package/dist/components/core/molecules/PageHeader.d.ts +0 -2
  7. package/dist/components/core/molecules/PropertyInspector.d.ts +8 -1
  8. package/dist/components/core/organisms/index.d.ts +1 -1
  9. package/dist/components/core/templates/index.d.ts +3 -0
  10. package/dist/components/game/{organisms → molecules}/GameCanvas3D.d.ts +1 -3
  11. package/dist/components/game/molecules/index.d.ts +1 -0
  12. package/dist/components/game/{organisms → molecules}/three/hooks/useGameCanvas3DEvents.d.ts +1 -1
  13. package/dist/components/game/{organisms → molecules}/three/index.cjs +29 -4
  14. package/dist/components/game/{organisms → molecules}/three/index.css +3 -3
  15. package/dist/components/game/{organisms → molecules}/three/index.js +29 -4
  16. package/dist/components/game/{organisms → molecules}/three/renderers/FeatureRenderer.d.ts +1 -1
  17. package/dist/components/game/{organisms → molecules}/three/renderers/FeatureRenderer3D.d.ts +1 -1
  18. package/dist/components/game/{organisms → molecules}/three/renderers/TileRenderer.d.ts +1 -1
  19. package/dist/components/game/{organisms → molecules}/three/renderers/UnitRenderer.d.ts +1 -1
  20. package/dist/components/game/organisms/TraitSlot.d.ts +3 -1
  21. package/dist/components/game/organisms/index.d.ts +0 -9
  22. package/dist/components/game/organisms/types/isometric.d.ts +2 -0
  23. package/dist/components/index.cjs +786 -692
  24. package/dist/components/index.js +788 -694
  25. package/dist/providers/index.cjs +178 -113
  26. package/dist/providers/index.js +178 -113
  27. package/dist/renderer/pattern-resolver.d.ts +2 -5
  28. package/dist/runtime/index.cjs +178 -113
  29. package/dist/runtime/index.js +178 -113
  30. package/package.json +9 -4
  31. package/dist/components/game/organisms/CombatLog.d.ts +0 -2
  32. package/dist/components/game/organisms/DialogueBox.d.ts +0 -2
  33. package/dist/components/game/organisms/GameHud.d.ts +0 -2
  34. package/dist/components/game/organisms/GameMenu.d.ts +0 -2
  35. package/dist/components/game/organisms/GameOverScreen.d.ts +0 -2
  36. package/dist/components/game/organisms/InventoryPanel.d.ts +0 -2
  37. package/dist/components/game/organisms/IsometricCanvas.d.ts +0 -3
  38. package/dist/components/game/organisms/PlatformerCanvas.d.ts +0 -2
  39. /package/dist/components/game/{organisms → molecules}/three/Camera3D.d.ts +0 -0
  40. /package/dist/components/game/{organisms → molecules}/three/Lighting3D.d.ts +0 -0
  41. /package/dist/components/game/{organisms → molecules}/three/Scene3D.d.ts +0 -0
  42. /package/dist/components/game/{organisms → molecules}/three/components/Canvas3DErrorBoundary.d.ts +0 -0
  43. /package/dist/components/game/{organisms → molecules}/three/components/Canvas3DLoadingState.d.ts +0 -0
  44. /package/dist/components/game/{organisms → molecules}/three/components/ModelLoader.d.ts +0 -0
  45. /package/dist/components/game/{organisms → molecules}/three/components/PhysicsObject3D.d.ts +0 -0
  46. /package/dist/components/game/{organisms → molecules}/three/components/index.d.ts +0 -0
  47. /package/dist/components/game/{organisms → molecules}/three/hooks/useAssetLoader.d.ts +0 -0
  48. /package/dist/components/game/{organisms → molecules}/three/hooks/useRaycaster.d.ts +0 -0
  49. /package/dist/components/game/{organisms → molecules}/three/hooks/useSceneGraph.d.ts +0 -0
  50. /package/dist/components/game/{organisms → molecules}/three/hooks/useThree.d.ts +0 -0
  51. /package/dist/components/game/{organisms → molecules}/three/index.d.ts +0 -0
  52. /package/dist/components/game/{organisms → molecules}/three/loaders/AssetLoader.d.ts +0 -0
  53. /package/dist/components/game/{organisms → molecules}/three/renderers/index.d.ts +0 -0
  54. /package/dist/components/game/{organisms → molecules}/three/utils/culling.d.ts +0 -0
  55. /package/dist/components/game/{organisms → molecules}/three/utils/grid3D.d.ts +0 -0
package/dist/avl/index.js CHANGED
@@ -14750,13 +14750,6 @@ var init_IsometricCanvas = __esm({
14750
14750
  }
14751
14751
  });
14752
14752
 
14753
- // components/game/organisms/IsometricCanvas.tsx
14754
- var init_IsometricCanvas2 = __esm({
14755
- "components/game/organisms/IsometricCanvas.tsx"() {
14756
- init_IsometricCanvas();
14757
- }
14758
- });
14759
-
14760
14753
  // components/game/organisms/boardEntity.ts
14761
14754
  function boardEntity(entity) {
14762
14755
  if (!entity) return void 0;
@@ -15152,7 +15145,7 @@ var init_BattleBoard = __esm({
15152
15145
  init_Button();
15153
15146
  init_Typography();
15154
15147
  init_Stack();
15155
- init_IsometricCanvas2();
15148
+ init_IsometricCanvas();
15156
15149
  init_boardEntity();
15157
15150
  init_isometric();
15158
15151
  BattleBoard.displayName = "BattleBoard";
@@ -22238,7 +22231,7 @@ var init_CastleBoard = __esm({
22238
22231
  "use client";
22239
22232
  init_cn();
22240
22233
  init_useEventBus();
22241
- init_IsometricCanvas2();
22234
+ init_IsometricCanvas();
22242
22235
  init_boardEntity();
22243
22236
  init_isometric();
22244
22237
  CastleBoard.displayName = "CastleBoard";
@@ -24412,7 +24405,84 @@ var init_DashboardLayout = __esm({
24412
24405
  NavLinkBottom.displayName = "NavLinkBottom";
24413
24406
  }
24414
24407
  });
24415
- var Menu;
24408
+ function computeMenuStyle(position, triggerRect) {
24409
+ const isTop = position.startsWith("top");
24410
+ const isRight = position.endsWith("right") || position.endsWith("end");
24411
+ if (isTop) {
24412
+ return {
24413
+ top: triggerRect.top - MENU_GAP,
24414
+ transform: "translateY(-100%)",
24415
+ ...isRight ? { right: window.innerWidth - triggerRect.right } : { left: triggerRect.left }
24416
+ };
24417
+ }
24418
+ return {
24419
+ top: triggerRect.bottom + MENU_GAP,
24420
+ ...isRight ? { right: window.innerWidth - triggerRect.right } : { left: triggerRect.left }
24421
+ };
24422
+ }
24423
+ function SubMenu({
24424
+ items,
24425
+ itemRef,
24426
+ direction,
24427
+ eventBus
24428
+ }) {
24429
+ const [rect, setRect] = useState(null);
24430
+ useEffect(() => {
24431
+ if (itemRef) {
24432
+ setRect(itemRef.getBoundingClientRect());
24433
+ }
24434
+ }, [itemRef]);
24435
+ if (!rect) return null;
24436
+ const isRtl = direction === "rtl";
24437
+ const style = {
24438
+ top: rect.top,
24439
+ ...isRtl ? { right: window.innerWidth - rect.left } : { left: rect.right }
24440
+ };
24441
+ const panel = /* @__PURE__ */ jsx(
24442
+ "div",
24443
+ {
24444
+ className: cn("fixed z-50", menuContainerStyles),
24445
+ style,
24446
+ children: items.map((item, index) => {
24447
+ const isDivider = item.id === "divider" || item.label === "divider";
24448
+ const itemId = item.id ?? `item-${item.label.toLowerCase().replace(/\s+/g, "-")}-${index}`;
24449
+ const isDanger = item.variant === "danger";
24450
+ if (isDivider) {
24451
+ return /* @__PURE__ */ jsx(Divider, { className: "my-1" }, `divider-${index}`);
24452
+ }
24453
+ return /* @__PURE__ */ jsxs(
24454
+ Box,
24455
+ {
24456
+ as: "button",
24457
+ onClick: () => {
24458
+ if (item.disabled) return;
24459
+ if (item.event) eventBus.emit(`UI:${item.event}`, { itemId, label: item.label });
24460
+ item.onClick?.();
24461
+ },
24462
+ "aria-disabled": item.disabled || void 0,
24463
+ "data-testid": item.event ? `action-${item.event}` : void 0,
24464
+ className: cn(
24465
+ "w-full flex items-center gap-3 px-4 py-2 text-start",
24466
+ "text-sm transition-colors",
24467
+ "hover:bg-muted focus:outline-none focus:bg-muted",
24468
+ "disabled:opacity-50 disabled:cursor-not-allowed",
24469
+ item.disabled && "cursor-not-allowed",
24470
+ isDanger && "text-error hover:bg-error/10"
24471
+ ),
24472
+ children: [
24473
+ item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm", className: "flex-shrink-0" })),
24474
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: cn("flex-1", isDanger && "text-red-600"), children: item.label }),
24475
+ item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs font-medium", children: item.badge })
24476
+ ]
24477
+ },
24478
+ itemId
24479
+ );
24480
+ })
24481
+ }
24482
+ );
24483
+ return typeof document !== "undefined" ? createPortal(panel, document.body) : panel;
24484
+ }
24485
+ var MENU_GAP, menuContainerStyles, Menu;
24416
24486
  var init_Menu = __esm({
24417
24487
  "components/core/molecules/Menu.tsx"() {
24418
24488
  "use client";
@@ -24423,6 +24493,14 @@ var init_Menu = __esm({
24423
24493
  init_Badge();
24424
24494
  init_cn();
24425
24495
  init_useEventBus();
24496
+ MENU_GAP = 4;
24497
+ menuContainerStyles = cn(
24498
+ "bg-card",
24499
+ "border-[length:var(--border-width)] border-border",
24500
+ "shadow-elevation-popover",
24501
+ "rounded-sm",
24502
+ "min-w-0 sm:min-w-[200px] max-w-[calc(100vw-1rem)] py-1"
24503
+ );
24426
24504
  Menu = ({
24427
24505
  trigger,
24428
24506
  items,
@@ -24430,9 +24508,10 @@ var init_Menu = __esm({
24430
24508
  className
24431
24509
  }) => {
24432
24510
  const eventBus = useEventBus();
24433
- const { t, direction } = useTranslate();
24511
+ const { direction } = useTranslate();
24434
24512
  const [isOpen, setIsOpen] = useState(false);
24435
24513
  const [activeSubMenu, setActiveSubMenu] = useState(null);
24514
+ const [activeSubMenuRef, setActiveSubMenuRef] = useState(null);
24436
24515
  const [triggerRect, setTriggerRect] = useState(null);
24437
24516
  const triggerRef = useRef(null);
24438
24517
  const menuRef = useRef(null);
@@ -24447,13 +24526,14 @@ var init_Menu = __esm({
24447
24526
  }
24448
24527
  setIsOpen(!isOpen);
24449
24528
  setActiveSubMenu(null);
24529
+ setActiveSubMenuRef(null);
24450
24530
  };
24451
- const handleItemClick = (item) => {
24531
+ const handleItemClick = (item, itemId) => {
24452
24532
  if (item.disabled) return;
24453
24533
  if (item.subMenu && item.subMenu.length > 0) {
24454
- setActiveSubMenu(item.id ?? null);
24534
+ setActiveSubMenu(itemId);
24455
24535
  } else {
24456
- if (item.event) eventBus.emit(`UI:${item.event}`, { itemId: item.id, label: item.label });
24536
+ if (item.event) eventBus.emit(`UI:${item.event}`, { itemId, label: item.label });
24457
24537
  item.onClick?.();
24458
24538
  setIsOpen(false);
24459
24539
  }
@@ -24468,22 +24548,12 @@ var init_Menu = __esm({
24468
24548
  if (isOpen && menuRef.current && !menuRef.current.contains(e.target) && triggerRef.current && !triggerRef.current.contains(e.target)) {
24469
24549
  setIsOpen(false);
24470
24550
  setActiveSubMenu(null);
24551
+ setActiveSubMenuRef(null);
24471
24552
  }
24472
24553
  };
24473
24554
  document.addEventListener("mousedown", handleClickOutside);
24474
24555
  return () => document.removeEventListener("mousedown", handleClickOutside);
24475
24556
  }, [isOpen]);
24476
- const positionClasses = {
24477
- "top-left": "bottom-full left-0 mb-2",
24478
- "top-right": "bottom-full right-0 mb-2",
24479
- "bottom-left": "top-full left-0 mt-2",
24480
- "bottom-right": "top-full right-0 mt-2",
24481
- // Aliases for pattern compatibility
24482
- "top-start": "bottom-full left-0 mb-2",
24483
- "top-end": "bottom-full right-0 mb-2",
24484
- "bottom-start": "top-full left-0 mt-2",
24485
- "bottom-end": "top-full right-0 mt-2"
24486
- };
24487
24557
  const rtlMirror = {
24488
24558
  "top-left": "top-right",
24489
24559
  "top-right": "top-left",
@@ -24495,7 +24565,6 @@ var init_Menu = __esm({
24495
24565
  "bottom-end": "bottom-start"
24496
24566
  };
24497
24567
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
24498
- const subMenuSideClass = direction === "rtl" ? "right-full mr-2" : "left-full ml-2";
24499
24568
  const triggerChild = React88__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
24500
24569
  const triggerElement = React88__default.cloneElement(
24501
24570
  triggerChild,
@@ -24504,94 +24573,83 @@ var init_Menu = __esm({
24504
24573
  onClick: handleToggle
24505
24574
  }
24506
24575
  );
24507
- const menuContainerStyles = cn(
24508
- "bg-card",
24509
- "border-[length:var(--border-width)] border-border",
24510
- "shadow-elevation-popover",
24511
- "rounded-sm",
24512
- "min-w-0 sm:min-w-[200px] max-w-[calc(100vw-1rem)] py-1"
24513
- );
24514
- const renderMenuItem = (item, hasSubMenu, index) => {
24576
+ const renderMenuItems = (menuItems) => menuItems.map((item, index) => {
24577
+ const isDivider = item.id === "divider" || item.label === "divider";
24515
24578
  const itemId = item.id ?? `item-${item.label.toLowerCase().replace(/\s+/g, "-")}-${index}`;
24579
+ const hasSubMenu = !!(item.subMenu && item.subMenu.length > 0);
24516
24580
  const isDanger = item.variant === "danger";
24517
- return /* @__PURE__ */ jsx(
24518
- Box,
24519
- {
24520
- as: "button",
24521
- onClick: () => !item.disabled && handleItemClick({ ...item, id: itemId }),
24522
- "aria-disabled": item.disabled || void 0,
24523
- onMouseEnter: () => hasSubMenu && setActiveSubMenu(itemId),
24524
- "data-testid": item.event ? `action-${item.event}` : void 0,
24525
- className: cn(
24526
- "w-full flex items-center justify-between gap-3 px-4 py-2 text-start",
24527
- "text-sm transition-colors",
24528
- "hover:bg-muted",
24529
- "focus:outline-none focus:bg-muted",
24530
- "disabled:opacity-50 disabled:cursor-not-allowed",
24531
- item.disabled && "cursor-not-allowed",
24532
- isDanger && "text-error hover:bg-error/10"
24533
- ),
24534
- children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-1 min-w-0", children: [
24535
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm", className: "flex-shrink-0" })),
24536
- /* @__PURE__ */ jsx(
24537
- Typography,
24538
- {
24539
- variant: "small",
24540
- className: cn("flex-1", isDanger && "text-red-600"),
24541
- children: item.label
24581
+ if (isDivider) {
24582
+ return /* @__PURE__ */ jsx(Divider, { className: "my-1" }, `divider-${index}`);
24583
+ }
24584
+ return /* @__PURE__ */ jsxs(Box, { children: [
24585
+ /* @__PURE__ */ jsx(
24586
+ Box,
24587
+ {
24588
+ as: "button",
24589
+ onClick: () => handleItemClick({ ...item, id: itemId }, itemId),
24590
+ "aria-disabled": item.disabled || void 0,
24591
+ onMouseEnter: (e) => {
24592
+ if (hasSubMenu) {
24593
+ setActiveSubMenu(itemId);
24594
+ setActiveSubMenuRef(e.currentTarget);
24542
24595
  }
24596
+ },
24597
+ "data-testid": item.event ? `action-${item.event}` : void 0,
24598
+ className: cn(
24599
+ "w-full flex items-center justify-between gap-3 px-4 py-2 text-start",
24600
+ "text-sm transition-colors",
24601
+ "hover:bg-muted",
24602
+ "focus:outline-none focus:bg-muted",
24603
+ "disabled:opacity-50 disabled:cursor-not-allowed",
24604
+ item.disabled && "cursor-not-allowed",
24605
+ isDanger && "text-error hover:bg-error/10"
24543
24606
  ),
24544
- item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge }),
24545
- hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: direction === "rtl" ? "chevron-left" : "chevron-right", size: "sm", className: "flex-shrink-0" })
24546
- ] })
24547
- },
24548
- itemId
24549
- );
24550
- };
24551
- const renderMenuItems = (menuItems) => {
24552
- return menuItems.map((item, index) => {
24553
- const hasSubMenu = item.subMenu && item.subMenu.length > 0;
24554
- const isDivider = item.id === "divider" || item.label === "divider";
24555
- const itemId = item.id ?? `item-${item.label.toLowerCase().replace(/\s+/g, "-")}-${index}`;
24556
- if (isDivider) {
24557
- return /* @__PURE__ */ jsx(Divider, { className: "my-1" }, `divider-${index}`);
24558
- }
24559
- return /* @__PURE__ */ jsxs(Box, { children: [
24560
- renderMenuItem(item, !!hasSubMenu, index),
24561
- hasSubMenu && activeSubMenu === itemId && item.subMenu && /* @__PURE__ */ jsx(
24562
- Box,
24563
- {
24564
- className: cn(
24565
- "absolute top-0 z-50",
24566
- subMenuSideClass,
24567
- menuContainerStyles
24607
+ children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-1 min-w-0", children: [
24608
+ item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm", className: "flex-shrink-0" })),
24609
+ /* @__PURE__ */ jsx(
24610
+ Typography,
24611
+ {
24612
+ variant: "small",
24613
+ className: cn("flex-1", isDanger && "text-red-600"),
24614
+ children: item.label
24615
+ }
24568
24616
  ),
24569
- children: renderMenuItems(item.subMenu)
24570
- }
24571
- )
24572
- ] }, itemId);
24573
- });
24574
- };
24575
- return /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
24617
+ item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge }),
24618
+ hasSubMenu && /* @__PURE__ */ jsx(
24619
+ Icon,
24620
+ {
24621
+ name: direction === "rtl" ? "chevron-left" : "chevron-right",
24622
+ size: "sm",
24623
+ className: "flex-shrink-0"
24624
+ }
24625
+ )
24626
+ ] })
24627
+ }
24628
+ ),
24629
+ hasSubMenu && activeSubMenu === itemId && item.subMenu && /* @__PURE__ */ jsx(
24630
+ SubMenu,
24631
+ {
24632
+ items: item.subMenu,
24633
+ itemRef: activeSubMenuRef,
24634
+ direction,
24635
+ eventBus
24636
+ }
24637
+ )
24638
+ ] }, itemId);
24639
+ });
24640
+ const panel = isOpen && triggerRect ? /* @__PURE__ */ jsx(
24641
+ "div",
24642
+ {
24643
+ ref: menuRef,
24644
+ className: cn("fixed z-50", menuContainerStyles, className),
24645
+ style: computeMenuStyle(effectivePosition, triggerRect),
24646
+ role: "menu",
24647
+ children: renderMenuItems(items)
24648
+ }
24649
+ ) : null;
24650
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
24576
24651
  triggerElement,
24577
- isOpen && triggerRect && /* @__PURE__ */ jsx(
24578
- Box,
24579
- {
24580
- ref: menuRef,
24581
- className: cn(
24582
- "absolute z-50",
24583
- menuContainerStyles,
24584
- positionClasses[effectivePosition],
24585
- className
24586
- ),
24587
- style: {
24588
- left: effectivePosition.includes("left") ? 0 : "auto",
24589
- right: effectivePosition.includes("right") ? 0 : "auto"
24590
- },
24591
- role: "menu",
24592
- children: renderMenuItems(items)
24593
- }
24594
- )
24652
+ panel && typeof document !== "undefined" ? createPortal(panel, document.body) : panel
24595
24653
  ] });
24596
24654
  };
24597
24655
  Menu.displayName = "Menu";
@@ -38588,7 +38646,6 @@ var init_DocumentViewer = __esm({
38588
38646
  showPrint = false,
38589
38647
  actions,
38590
38648
  documents,
38591
- entity,
38592
38649
  isLoading = false,
38593
38650
  error,
38594
38651
  className
@@ -45403,7 +45460,7 @@ function TraitSlot({
45403
45460
  size = "md",
45404
45461
  showTooltip = true,
45405
45462
  categoryColors,
45406
- tooltipFrameUrl,
45463
+ tooltipFrameUrl = "",
45407
45464
  className,
45408
45465
  feedback,
45409
45466
  onItemDrop,
@@ -48259,7 +48316,7 @@ var init_WorldMapBoard = __esm({
48259
48316
  init_useEventBus();
48260
48317
  init_Stack();
48261
48318
  init_LoadingState();
48262
- init_IsometricCanvas2();
48319
+ init_IsometricCanvas();
48263
48320
  init_boardEntity();
48264
48321
  init_isometric();
48265
48322
  WorldMapBoard.displayName = "WorldMapBoard";
@@ -48315,7 +48372,7 @@ function lazyThree(name, loader) {
48315
48372
  ThreeWrapper.displayName = `Lazy(${name})`;
48316
48373
  return ThreeWrapper;
48317
48374
  }
48318
- var FeatureRenderer, COMPONENT_REGISTRY;
48375
+ var FeatureRenderer, GameCanvas3D, GameCanvas3DBattleTemplate, GameCanvas3DCastleTemplate, GameCanvas3DWorldMapTemplate, COMPONENT_REGISTRY;
48319
48376
  var init_component_registry_generated = __esm({
48320
48377
  "components/core/organisms/component-registry.generated.ts"() {
48321
48378
  init_AboutPageTemplate();
@@ -48601,7 +48658,11 @@ var init_component_registry_generated = __esm({
48601
48658
  init_WorldMapBoard();
48602
48659
  init_WorldMapTemplate();
48603
48660
  init_XPBar();
48604
- FeatureRenderer = lazyThree("FeatureRenderer", () => import('@almadar/ui/components/organisms/game/three'));
48661
+ FeatureRenderer = lazyThree("FeatureRenderer", () => import('@almadar/ui/components/molecules/game/three'));
48662
+ GameCanvas3D = lazyThree("GameCanvas3D", () => import('@almadar/ui/components/molecules/game/three'));
48663
+ GameCanvas3DBattleTemplate = lazyThree("GameCanvas3DBattleTemplate", () => import('@almadar/ui/components/molecules/game/three'));
48664
+ GameCanvas3DCastleTemplate = lazyThree("GameCanvas3DCastleTemplate", () => import('@almadar/ui/components/molecules/game/three'));
48665
+ GameCanvas3DWorldMapTemplate = lazyThree("GameCanvas3DWorldMapTemplate", () => import('@almadar/ui/components/molecules/game/three'));
48605
48666
  COMPONENT_REGISTRY = {
48606
48667
  "AboutPageTemplate": AboutPageTemplate,
48607
48668
  "Accordion": Accordion,
@@ -48714,6 +48775,10 @@ var init_component_registry_generated = __esm({
48714
48775
  "GameAudioProvider": GameAudioProvider,
48715
48776
  "GameAudioToggle": GameAudioToggle,
48716
48777
  "GameCanvas2D": GameCanvas2D,
48778
+ "GameCanvas3D": GameCanvas3D,
48779
+ "GameCanvas3DBattleTemplate": GameCanvas3DBattleTemplate,
48780
+ "GameCanvas3DCastleTemplate": GameCanvas3DCastleTemplate,
48781
+ "GameCanvas3DWorldMapTemplate": GameCanvas3DWorldMapTemplate,
48717
48782
  "GameHud": GameHud,
48718
48783
  "GameMenu": GameMenu,
48719
48784
  "GameOverScreen": GameOverScreen,
@@ -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>;
@@ -26,4 +26,4 @@ export { StepFlowOrganism, type StepFlowOrganismProps, } from "../../marketing/o
26
26
  export { ShowcaseOrganism, type ShowcaseOrganismProps, } from "../../marketing/organisms/ShowcaseOrganism";
27
27
  export { TeamOrganism, type TeamOrganismProps, } from "../../marketing/organisms/TeamOrganism";
28
28
  export { CaseStudyOrganism, type CaseStudyOrganismProps, } from "../../marketing/organisms/CaseStudyOrganism";
29
- export { FeatureRenderer, type FeatureRendererProps } from '../../game/organisms/three/renderers/FeatureRenderer';
29
+ export { FeatureRenderer, type FeatureRendererProps } from '../../game/molecules/three/renderers/FeatureRenderer';
@@ -12,3 +12,6 @@ export { LandingPageTemplate, type LandingPageTemplateProps, type LandingPageEnt
12
12
  export { PricingPageTemplate, type PricingPageTemplateProps, type PricingPageEntity, } from '../../marketing/templates/PricingPageTemplate';
13
13
  export { FeatureDetailPageTemplate, type FeatureDetailPageTemplateProps, type FeatureDetailPageEntity, type FeatureDetailSection, } from '../../marketing/templates/FeatureDetailPageTemplate';
14
14
  export { AboutPageTemplate, type AboutPageTemplateProps, type AboutPageEntity, } from '../../marketing/templates/AboutPageTemplate';
15
+ export type { GameCanvas3DBattleTemplate, GameCanvas3DBattleTemplateProps } from '../../game/templates/GameCanvas3DBattleTemplate';
16
+ export type { GameCanvas3DCastleTemplate, GameCanvas3DCastleTemplateProps } from '../../game/templates/GameCanvas3DCastleTemplate';
17
+ export type { GameCanvas3DWorldMapTemplate, GameCanvas3DWorldMapTemplateProps } from '../../game/templates/GameCanvas3DWorldMapTemplate';
@@ -17,7 +17,7 @@ import React from 'react';
17
17
  import type { EventEmit } from '@almadar/core';
18
18
  import * as THREE from 'three';
19
19
  import { AssetLoader } from './three/loaders/AssetLoader';
20
- import type { IsometricTile, IsometricUnit, IsometricFeature } from './types/isometric';
20
+ import type { IsometricTile, IsometricUnit, IsometricFeature } from '../organisms/types/isometric';
21
21
  import './GameCanvas3D.css';
22
22
  export type { IsometricTile, IsometricUnit, IsometricFeature };
23
23
  /** Game event for canvas display */
@@ -35,8 +35,6 @@ export type CameraMode = 'isometric' | 'perspective' | 'top-down';
35
35
  export type MapOrientation = 'standard' | 'rotated';
36
36
  /** Overlay control */
37
37
  export type OverlayControl = 'default' | 'hidden' | 'minimap';
38
- /** Unit animation state */
39
- export type UnitAnimationState = 'idle' | 'walk' | 'attack' | 'hurt' | 'die';
40
38
  /** Props for GameCanvas3D component */
41
39
  export interface GameCanvas3DProps {
42
40
  /** Additional CSS classes */
@@ -5,6 +5,7 @@
5
5
  *
6
6
  * @packageDocumentation
7
7
  */
8
+ export type { GameCanvas3D, GameCanvas3DProps, GameCanvas3DHandle, GameEvent, CameraMode, MapOrientation, OverlayControl } from './GameCanvas3D';
8
9
  export { DPad, type DPadProps, type DPadDirection } from './DPad';
9
10
  export { ActionButtons, type ActionButtonsProps, type ActionButtonConfig } from './ActionButtons';
10
11
  export { StatBadge, type StatBadgeProps } from './StatBadge';
@@ -1,5 +1,5 @@
1
1
  import type { EventEmit } from '@almadar/core';
2
- import type { IsometricTile, IsometricUnit, IsometricFeature } from '../../types/isometric';
2
+ import type { IsometricTile, IsometricUnit, IsometricFeature } from '../../../organisms/types/isometric';
3
3
  export interface GameCanvas3DEventConfig {
4
4
  /** Event name for tile clicks */
5
5
  tileClickEvent?: EventEmit<{
@@ -780,7 +780,7 @@ var AssetLoader = class {
780
780
  };
781
781
  var assetLoader = new AssetLoader();
782
782
 
783
- // components/game/organisms/three/hooks/useThree.ts
783
+ // components/game/molecules/three/hooks/useThree.ts
784
784
  var DEFAULT_OPTIONS = {
785
785
  cameraMode: "isometric",
786
786
  cameraPosition: [10, 10, 10],
@@ -1500,7 +1500,7 @@ function useEmitEvent() {
1500
1500
  );
1501
1501
  }
1502
1502
 
1503
- // components/game/organisms/three/hooks/useGameCanvas3DEvents.ts
1503
+ // components/game/molecules/three/hooks/useGameCanvas3DEvents.ts
1504
1504
  function useGameCanvas3DEvents(options) {
1505
1505
  const {
1506
1506
  tileClickEvent,
@@ -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
  {
@@ -1,4 +1,4 @@
1
- /* components/game/organisms/three/components/Canvas3DLoadingState.css */
1
+ /* components/game/molecules/three/components/Canvas3DLoadingState.css */
2
2
  .canvas-3d-loading {
3
3
  position: absolute;
4
4
  inset: 0;
@@ -151,7 +151,7 @@
151
151
  }
152
152
  }
153
153
 
154
- /* components/game/organisms/three/components/Canvas3DErrorBoundary.css */
154
+ /* components/game/molecules/three/components/Canvas3DErrorBoundary.css */
155
155
  .canvas-3d-error {
156
156
  position: absolute;
157
157
  inset: 0;
@@ -314,7 +314,7 @@
314
314
  }
315
315
  }
316
316
 
317
- /* components/game/organisms/GameCanvas3D.css */
317
+ /* components/game/molecules/GameCanvas3D.css */
318
318
  .game-canvas-3d {
319
319
  position: relative;
320
320
  width: 100%;