@almadar/ui 2.13.3 → 2.15.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 (420) hide show
  1. package/dist/{chunk-UNDQO6DL.js → chunk-4KP6IZEQ.js} +3 -3
  2. package/dist/chunk-4N3BAPDB.js +1667 -0
  3. package/dist/{chunk-PERGHHON.js → chunk-IRIGCHP4.js} +2 -12
  4. package/dist/{chunk-Y7IHEYYE.js → chunk-QU2X55WH.js} +11 -1
  5. package/dist/{chunk-4ZBSL37D.js → chunk-XL7WB2O5.js} +415 -58
  6. package/dist/{chunk-MSLMORZK.js → chunk-YPY74G7F.js} +13434 -2264
  7. package/dist/components/atoms/AnimatedCounter.d.ts +20 -0
  8. package/dist/components/atoms/Avatar.d.ts +58 -0
  9. package/dist/components/atoms/Badge.d.ts +14 -0
  10. package/dist/components/atoms/Box.d.ts +57 -0
  11. package/dist/components/atoms/Button.d.ts +24 -0
  12. package/dist/components/atoms/Card.d.ts +18 -0
  13. package/dist/components/atoms/Center.d.ts +33 -0
  14. package/dist/components/atoms/Checkbox.d.ts +9 -0
  15. package/dist/components/atoms/ConditionalWrapper.d.ts +68 -0
  16. package/dist/components/atoms/ConfettiEffect.d.ts +19 -0
  17. package/dist/components/atoms/DayCell.d.ts +21 -0
  18. package/dist/components/atoms/Divider.d.ts +29 -0
  19. package/dist/components/atoms/FlipContainer.d.ts +21 -0
  20. package/dist/components/atoms/Icon.d.ts +39 -0
  21. package/dist/components/atoms/InfiniteScrollSentinel.d.ts +23 -0
  22. package/dist/components/atoms/Input.d.ts +26 -0
  23. package/dist/components/atoms/Label.d.ts +5 -0
  24. package/dist/components/atoms/LawReferenceTooltip.d.ts +48 -0
  25. package/dist/components/atoms/Overlay.d.ts +16 -0
  26. package/dist/components/atoms/ProgressBar.d.ts +63 -0
  27. package/dist/components/atoms/Radio.d.ts +26 -0
  28. package/dist/components/atoms/RangeSlider.d.ts +31 -0
  29. package/dist/components/atoms/Select.d.ts +12 -0
  30. package/dist/components/atoms/Spacer.d.ts +25 -0
  31. package/dist/components/atoms/Spinner.d.ts +6 -0
  32. package/dist/components/atoms/Stack.d.ts +66 -0
  33. package/dist/components/atoms/StatusDot.d.ts +14 -0
  34. package/dist/components/atoms/Switch.d.ts +12 -0
  35. package/dist/components/atoms/TextHighlight.d.ts +53 -0
  36. package/dist/components/atoms/Textarea.d.ts +5 -0
  37. package/dist/components/atoms/ThemeSelector.d.ts +21 -0
  38. package/dist/components/atoms/ThemeToggle.d.ts +33 -0
  39. package/dist/components/atoms/TimeSlotCell.d.ts +23 -0
  40. package/dist/components/atoms/TrendIndicator.d.ts +18 -0
  41. package/dist/components/atoms/TypewriterText.d.ts +20 -0
  42. package/dist/components/atoms/Typography.d.ts +57 -0
  43. package/dist/components/atoms/game/ActionButton.d.ts +25 -0
  44. package/dist/components/atoms/game/ChoiceButton.d.ts +18 -0
  45. package/dist/components/atoms/game/ComboCounter.d.ts +16 -0
  46. package/dist/components/atoms/game/ControlButton.d.ts +31 -0
  47. package/dist/components/atoms/game/DamageNumber.d.ts +14 -0
  48. package/dist/components/atoms/game/DialogueBubble.d.ts +16 -0
  49. package/dist/components/atoms/game/HealthBar.d.ts +18 -0
  50. package/dist/components/atoms/game/ItemSlot.d.ts +25 -0
  51. package/dist/components/atoms/game/MiniMap.d.ts +36 -0
  52. package/dist/components/atoms/game/ResourceCounter.d.ts +21 -0
  53. package/dist/components/atoms/game/ScoreDisplay.d.ts +21 -0
  54. package/dist/components/atoms/game/Sprite.d.ts +63 -0
  55. package/dist/components/atoms/game/StateIndicator.d.ts +31 -0
  56. package/dist/components/atoms/game/StatusEffect.d.ts +21 -0
  57. package/dist/components/atoms/game/TimerDisplay.d.ts +18 -0
  58. package/dist/components/atoms/game/TurnIndicator.d.ts +18 -0
  59. package/dist/components/atoms/game/WaypointMarker.d.ts +19 -0
  60. package/dist/components/atoms/game/XPBar.d.ts +20 -0
  61. package/dist/components/atoms/game/index.d.ts +25 -0
  62. package/dist/components/atoms/index.d.ts +37 -0
  63. package/dist/components/index.css +508 -0
  64. package/dist/components/index.d.ts +6 -9788
  65. package/dist/components/index.js +769 -11187
  66. package/dist/components/molecules/Accordion.d.ts +67 -0
  67. package/dist/components/molecules/Alert.d.ts +24 -0
  68. package/dist/components/molecules/Breadcrumb.d.ts +55 -0
  69. package/dist/components/molecules/ButtonGroup.d.ts +67 -0
  70. package/dist/components/molecules/CalendarGrid.d.ts +43 -0
  71. package/dist/components/molecules/Card.d.ts +56 -0
  72. package/dist/components/molecules/Carousel.d.ts +31 -0
  73. package/dist/components/molecules/ChartLegend.d.ts +20 -0
  74. package/dist/components/molecules/Container.d.ts +30 -0
  75. package/dist/components/molecules/DataGrid.d.ts +75 -0
  76. package/dist/components/molecules/DataList.d.ts +95 -0
  77. package/dist/components/molecules/DateRangeSelector.d.ts +22 -0
  78. package/dist/components/molecules/Drawer.d.ts +46 -0
  79. package/dist/components/molecules/EmptyState.d.ts +25 -0
  80. package/dist/components/molecules/ErrorBoundary.d.ts +55 -0
  81. package/dist/components/molecules/ErrorState.d.ts +13 -0
  82. package/dist/components/molecules/FilterGroup.d.ts +54 -0
  83. package/dist/components/molecules/Flex.d.ts +43 -0
  84. package/dist/components/molecules/FlipCard.d.ts +25 -0
  85. package/dist/components/molecules/FloatingActionButton.d.ts +69 -0
  86. package/dist/components/molecules/FormField.d.ts +16 -0
  87. package/dist/components/molecules/FormSectionHeader.d.ts +30 -0
  88. package/dist/components/molecules/GraphView.d.ts +45 -0
  89. package/dist/components/molecules/Grid.d.ts +54 -0
  90. package/dist/components/molecules/InputGroup.d.ts +24 -0
  91. package/dist/components/molecules/Lightbox.d.ts +25 -0
  92. package/dist/components/molecules/LineChart.d.ts +33 -0
  93. package/dist/components/molecules/LoadingState.d.ts +7 -0
  94. package/dist/components/molecules/MapView.d.ts +40 -0
  95. package/dist/components/molecules/Menu.d.ts +40 -0
  96. package/dist/components/molecules/Meter.d.ts +51 -0
  97. package/dist/components/molecules/Modal.d.ts +28 -0
  98. package/dist/components/molecules/NumberStepper.d.ts +27 -0
  99. package/dist/components/molecules/Pagination.d.ts +66 -0
  100. package/dist/components/molecules/Popover.d.ts +39 -0
  101. package/dist/components/molecules/ProgressDots.d.ts +24 -0
  102. package/dist/components/molecules/PullToRefresh.d.ts +21 -0
  103. package/dist/components/molecules/QuizBlock.d.ts +20 -0
  104. package/dist/components/molecules/RelationSelect.d.ts +48 -0
  105. package/dist/components/molecules/RepeatableFormSection.d.ts +58 -0
  106. package/dist/components/molecules/ScaledDiagram.d.ts +20 -0
  107. package/dist/components/molecules/SearchInput.d.ts +60 -0
  108. package/dist/components/molecules/SidePanel.d.ts +47 -0
  109. package/dist/components/molecules/SimpleGrid.d.ts +27 -0
  110. package/dist/components/molecules/Skeleton.d.ts +35 -0
  111. package/dist/components/molecules/SortableList.d.ts +17 -0
  112. package/dist/components/molecules/StarRating.d.ts +26 -0
  113. package/dist/components/molecules/StatDisplay.d.ts +37 -0
  114. package/dist/components/molecules/SwipeableRow.d.ts +24 -0
  115. package/dist/components/molecules/Tabs.d.ts +45 -0
  116. package/dist/components/molecules/Toast.d.ts +35 -0
  117. package/dist/components/molecules/Tooltip.d.ts +25 -0
  118. package/dist/components/molecules/UploadDropZone.d.ts +26 -0
  119. package/dist/components/molecules/ViolationAlert.d.ts +49 -0
  120. package/dist/components/molecules/WizardNavigation.d.ts +51 -0
  121. package/dist/components/molecules/WizardProgress.d.ts +42 -0
  122. package/dist/components/molecules/game/ActionButtons.d.ts +34 -0
  123. package/dist/components/molecules/game/CombatLog.d.ts +30 -0
  124. package/dist/components/molecules/game/CraftingRecipe.d.ts +33 -0
  125. package/dist/components/molecules/game/DPad.d.ts +22 -0
  126. package/dist/components/molecules/game/DialogueBox.d.ts +78 -0
  127. package/dist/components/molecules/game/EnemyPlate.d.ts +27 -0
  128. package/dist/components/molecules/game/GameCanvas2D.d.ts +18 -0
  129. package/dist/components/molecules/game/GameHud.d.ts +49 -0
  130. package/dist/components/molecules/game/GameMenu.d.ts +43 -0
  131. package/dist/components/molecules/game/GameOverScreen.d.ts +56 -0
  132. package/dist/components/molecules/game/HealthPanel.d.ts +27 -0
  133. package/dist/components/molecules/game/InventoryGrid.d.ts +30 -0
  134. package/dist/components/molecules/game/InventoryPanel.d.ts +67 -0
  135. package/dist/components/molecules/game/IsometricCanvas.d.ts +127 -0
  136. package/dist/components/molecules/game/PlatformerCanvas.d.ts +52 -0
  137. package/dist/components/molecules/game/PowerupSlots.d.ts +23 -0
  138. package/dist/components/molecules/game/QuestTracker.d.ts +20 -0
  139. package/dist/components/molecules/game/ResourceBar.d.ts +23 -0
  140. package/dist/components/molecules/game/ScoreBoard.d.ts +18 -0
  141. package/dist/components/molecules/game/StatBadge.d.ts +27 -0
  142. package/dist/components/molecules/game/TurnPanel.d.ts +29 -0
  143. package/dist/components/molecules/game/UnitCommandBar.d.ts +25 -0
  144. package/dist/components/molecules/game/index.d.ts +30 -0
  145. package/dist/components/molecules/index.d.ts +59 -0
  146. package/dist/components/molecules/markdown/CodeBlock.d.ts +25 -0
  147. package/dist/components/molecules/markdown/MarkdownContent.d.ts +26 -0
  148. package/dist/components/molecules/markdown/index.d.ts +2 -0
  149. package/dist/components/organisms/CardGrid.d.ts +80 -0
  150. package/dist/components/organisms/Chart.d.ts +59 -0
  151. package/dist/components/organisms/CodeViewer.d.ts +67 -0
  152. package/dist/components/organisms/ComponentPatterns.d.ts +453 -0
  153. package/dist/components/organisms/ConfirmDialog.d.ts +50 -0
  154. package/dist/components/organisms/ContentRenderer.d.ts +23 -0
  155. package/dist/components/organisms/CustomPattern.d.ts +104 -0
  156. package/dist/components/organisms/DataTable.d.ts +67 -0
  157. package/dist/components/organisms/DetailPanel.d.ts +78 -0
  158. package/dist/components/organisms/DocumentViewer.d.ts +60 -0
  159. package/dist/components/organisms/DrawerSlot.d.ts +39 -0
  160. package/dist/components/organisms/Form.d.ts +206 -0
  161. package/dist/components/organisms/FormSection.d.ts +41 -0
  162. package/dist/components/organisms/GraphCanvas.d.ts +69 -0
  163. package/dist/components/organisms/Header.d.ts +110 -0
  164. package/dist/components/organisms/JazariStateMachine.d.ts +60 -0
  165. package/dist/components/organisms/LayoutPatterns.d.ts +181 -0
  166. package/dist/components/organisms/List.d.ts +78 -0
  167. package/dist/components/organisms/MasterDetail.d.ts +32 -0
  168. package/dist/components/organisms/MediaGallery.d.ts +57 -0
  169. package/dist/components/organisms/Meter.d.ts +58 -0
  170. package/dist/components/organisms/ModalSlot.d.ts +35 -0
  171. package/dist/components/organisms/Navigation.d.ts +68 -0
  172. package/dist/components/organisms/NotifyListener.d.ts +15 -0
  173. package/dist/components/organisms/OrbitalVisualization.d.ts +48 -0
  174. package/dist/components/organisms/PageHeader.d.ts +59 -0
  175. package/dist/components/organisms/Section.d.ts +44 -0
  176. package/dist/components/organisms/Sidebar.d.ts +63 -0
  177. package/dist/components/organisms/SignaturePad.d.ts +44 -0
  178. package/dist/components/organisms/Split.d.ts +42 -0
  179. package/dist/components/organisms/StatCard.d.ts +62 -0
  180. package/dist/components/organisms/StateMachineView.d.ts +36 -0
  181. package/dist/components/organisms/Table.d.ts +99 -0
  182. package/dist/components/organisms/Timeline.d.ts +49 -0
  183. package/dist/components/organisms/ToastSlot.d.ts +38 -0
  184. package/dist/components/organisms/UISlotRenderer.d.ts +112 -0
  185. package/dist/components/organisms/WizardContainer.d.ts +160 -0
  186. package/dist/components/organisms/book/BookChapterView.d.ts +17 -0
  187. package/dist/components/organisms/book/BookCoverPage.d.ts +20 -0
  188. package/dist/components/organisms/book/BookNavBar.d.ts +19 -0
  189. package/dist/components/organisms/book/BookTableOfContents.d.ts +18 -0
  190. package/dist/components/organisms/book/BookViewer.d.ts +28 -0
  191. package/dist/components/organisms/book/index.d.ts +7 -0
  192. package/dist/components/organisms/book/types.d.ts +77 -0
  193. package/dist/components/organisms/component-registry.generated.d.ts +9 -0
  194. package/dist/components/organisms/debug/RuntimeDebugger.d.ts +19 -0
  195. package/dist/components/organisms/debug/hooks/useDebugData.d.ts +25 -0
  196. package/dist/components/organisms/debug/index.d.ts +13 -0
  197. package/dist/components/organisms/debug/tabs/EntitiesTab.d.ts +13 -0
  198. package/dist/components/organisms/debug/tabs/EventDispatcherTab.d.ts +16 -0
  199. package/dist/components/organisms/debug/tabs/EventFlowTab.d.ts +9 -0
  200. package/dist/components/organisms/debug/tabs/GuardsPanel.d.ts +9 -0
  201. package/dist/components/organisms/debug/tabs/ServerBridgeTab.d.ts +9 -0
  202. package/dist/components/organisms/debug/tabs/TicksTab.d.ts +13 -0
  203. package/dist/components/organisms/debug/tabs/TraitsTab.d.ts +13 -0
  204. package/dist/components/organisms/debug/tabs/TransitionTimeline.d.ts +9 -0
  205. package/dist/components/organisms/debug/tabs/VerificationTab.d.ts +10 -0
  206. package/dist/components/organisms/game/BattleBoard.d.ts +175 -0
  207. package/dist/components/organisms/game/CanvasEffect.d.ts +68 -0
  208. package/dist/components/organisms/game/CastleBoard.d.ts +85 -0
  209. package/dist/components/organisms/game/CombatLog.d.ts +2 -0
  210. package/dist/components/organisms/game/DialogueBox.d.ts +2 -0
  211. package/dist/components/organisms/game/GameAudioProvider.d.ts +47 -0
  212. package/dist/components/organisms/game/GameAudioToggle.d.ts +28 -0
  213. package/dist/components/organisms/game/GameCanvas3D.d.ts +181 -0
  214. package/dist/components/organisms/game/GameHud.d.ts +2 -0
  215. package/dist/components/organisms/game/GameMenu.d.ts +2 -0
  216. package/dist/components/organisms/game/GameOverScreen.d.ts +2 -0
  217. package/dist/components/organisms/game/InventoryPanel.d.ts +2 -0
  218. package/dist/components/organisms/game/IsometricCanvas.d.ts +3 -0
  219. package/dist/components/organisms/game/PlatformerCanvas.d.ts +2 -0
  220. package/dist/components/organisms/game/TraitSlot.d.ts +90 -0
  221. package/dist/components/organisms/game/TraitStateViewer.d.ts +53 -0
  222. package/dist/components/organisms/game/UncontrolledBattleBoard.d.ts +26 -0
  223. package/dist/components/organisms/game/WorldMapBoard.d.ts +156 -0
  224. package/dist/components/organisms/game/editor/editorUtils.d.ts +109 -0
  225. package/dist/components/organisms/game/editor/index.d.ts +9 -0
  226. package/dist/components/organisms/game/hooks/useBattleState.d.ts +35 -0
  227. package/dist/components/organisms/game/hooks/useCamera.d.ts +41 -0
  228. package/dist/components/organisms/game/hooks/useGameAudio.d.ts +47 -0
  229. package/dist/components/organisms/game/hooks/useImageCache.d.ts +16 -0
  230. package/dist/components/organisms/game/hooks/usePhysics2D.d.ts +45 -0
  231. package/dist/components/organisms/game/hooks/useSpriteAnimations.d.ts +43 -0
  232. package/dist/components/organisms/game/index.d.ts +52 -0
  233. package/dist/components/organisms/game/managers/PhysicsManager.d.ts +103 -0
  234. package/dist/components/organisms/game/physics-sim/SimulationCanvas.d.ts +20 -0
  235. package/dist/components/organisms/game/physics-sim/SimulationControls.d.ts +28 -0
  236. package/dist/components/organisms/game/physics-sim/SimulationGraph.d.ts +25 -0
  237. package/dist/components/organisms/game/physics-sim/index.d.ts +7 -0
  238. package/dist/components/organisms/game/physics-sim/presets/index.d.ts +4 -0
  239. package/dist/components/organisms/game/physics-sim/presets/mechanics.d.ts +4 -0
  240. package/dist/components/organisms/game/physics-sim/presets/types.d.ts +43 -0
  241. package/dist/components/organisms/game/puzzles/builder/BuilderBoard.d.ts +52 -0
  242. package/dist/components/organisms/game/puzzles/builder/index.d.ts +2 -0
  243. package/dist/components/organisms/game/puzzles/classifier/ClassifierBoard.d.ts +53 -0
  244. package/dist/components/organisms/game/puzzles/classifier/index.d.ts +2 -0
  245. package/dist/components/organisms/game/puzzles/debugger/DebuggerBoard.d.ts +45 -0
  246. package/dist/components/organisms/game/puzzles/debugger/index.d.ts +2 -0
  247. package/dist/components/organisms/game/puzzles/event-handler/EventHandlerBoard.d.ts +55 -0
  248. package/dist/components/organisms/game/puzzles/event-handler/EventLog.d.ts +31 -0
  249. package/dist/components/organisms/game/puzzles/event-handler/ObjectRulePanel.d.ts +45 -0
  250. package/dist/components/organisms/game/puzzles/event-handler/RuleEditor.d.ts +41 -0
  251. package/dist/components/organisms/game/puzzles/event-handler/index.d.ts +8 -0
  252. package/dist/components/organisms/game/puzzles/negotiator/NegotiatorBoard.d.ts +54 -0
  253. package/dist/components/organisms/game/puzzles/negotiator/index.d.ts +2 -0
  254. package/dist/components/organisms/game/puzzles/sequencer/ActionPalette.d.ts +34 -0
  255. package/dist/components/organisms/game/puzzles/sequencer/ActionTile.d.ts +30 -0
  256. package/dist/components/organisms/game/puzzles/sequencer/SequenceBar.d.ts +41 -0
  257. package/dist/components/organisms/game/puzzles/sequencer/SequencerBoard.d.ts +72 -0
  258. package/dist/components/organisms/game/puzzles/sequencer/index.d.ts +8 -0
  259. package/dist/components/organisms/game/puzzles/simulator/SimulatorBoard.d.ts +54 -0
  260. package/dist/components/organisms/game/puzzles/simulator/index.d.ts +2 -0
  261. package/dist/components/organisms/game/puzzles/state-architect/CodeView.d.ts +24 -0
  262. package/dist/components/organisms/game/puzzles/state-architect/StateArchitectBoard.d.ts +76 -0
  263. package/dist/components/organisms/game/puzzles/state-architect/StateNode.d.ts +33 -0
  264. package/dist/components/organisms/game/puzzles/state-architect/TransitionArrow.d.ts +36 -0
  265. package/dist/components/organisms/game/puzzles/state-architect/VariablePanel.d.ts +28 -0
  266. package/dist/components/organisms/game/puzzles/state-architect/index.d.ts +10 -0
  267. package/dist/components/organisms/game/three/Camera3D.d.ts +60 -0
  268. package/dist/components/organisms/game/three/Lighting3D.d.ts +47 -0
  269. package/dist/components/organisms/game/three/Scene3D.d.ts +37 -0
  270. package/dist/components/organisms/game/three/components/Canvas3DErrorBoundary.d.ts +51 -0
  271. package/dist/components/organisms/game/three/components/Canvas3DLoadingState.d.ts +44 -0
  272. package/dist/components/organisms/game/three/components/ModelLoader.d.ts +44 -0
  273. package/dist/components/organisms/game/three/components/PhysicsObject3D.d.ts +74 -0
  274. package/dist/components/organisms/game/three/components/index.d.ts +10 -0
  275. package/dist/components/organisms/game/three/hooks/useAssetLoader.d.ts +58 -0
  276. package/dist/components/organisms/game/three/hooks/useGameCanvas3DEvents.d.ts +79 -0
  277. package/dist/components/organisms/game/three/hooks/useRaycaster.d.ts +86 -0
  278. package/dist/components/organisms/game/three/hooks/useSceneGraph.d.ts +66 -0
  279. package/dist/components/organisms/game/three/hooks/useThree.d.ts +58 -0
  280. package/dist/components/organisms/game/three/index.d.ts +18 -1228
  281. package/dist/components/organisms/game/three/index.js +49 -1709
  282. package/dist/components/organisms/game/three/loaders/AssetLoader.d.ts +80 -0
  283. package/dist/components/organisms/game/three/renderers/FeatureRenderer.d.ts +44 -0
  284. package/dist/components/organisms/game/three/renderers/FeatureRenderer3D.d.ts +44 -0
  285. package/dist/components/organisms/game/three/renderers/TileRenderer.d.ts +57 -0
  286. package/dist/components/organisms/game/three/renderers/UnitRenderer.d.ts +46 -0
  287. package/dist/components/organisms/game/three/renderers/index.d.ts +11 -0
  288. package/dist/components/organisms/game/three/utils/culling.d.ts +134 -0
  289. package/dist/components/organisms/game/three/utils/grid3D.d.ts +154 -0
  290. package/dist/components/organisms/game/types/effects.d.ts +253 -0
  291. package/dist/components/organisms/game/types/game.d.ts +92 -0
  292. package/dist/{isometric-ynNHVPZx.d.ts → components/organisms/game/types/isometric.d.ts} +4 -6
  293. package/dist/components/organisms/game/types/spriteAnimation.d.ts +73 -0
  294. package/dist/components/organisms/game/useCanvasEffects.d.ts +26 -0
  295. package/dist/components/organisms/game/utils/canvasEffects.d.ts +50 -0
  296. package/dist/components/organisms/game/utils/combatEffects.d.ts +64 -0
  297. package/dist/components/organisms/game/utils/combatPresets.d.ts +15 -0
  298. package/dist/components/organisms/game/utils/isometric.d.ts +61 -0
  299. package/dist/components/organisms/game/utils/spriteAnimation.d.ts +57 -0
  300. package/dist/components/organisms/game/utils/spriteSheetConstants.d.ts +16 -0
  301. package/dist/components/organisms/index.d.ts +38 -0
  302. package/dist/components/organisms/layout/DashboardGrid.d.ts +35 -0
  303. package/dist/components/organisms/layout/MasterDetail.d.ts +32 -0
  304. package/dist/components/organisms/layout/SplitPane.d.ts +34 -0
  305. package/dist/components/organisms/layout/TabbedContainer.d.ts +42 -0
  306. package/dist/components/organisms/layout/index.d.ts +9 -0
  307. package/dist/components/organisms/types.d.ts +63 -0
  308. package/dist/components/templates/AuthLayout.d.ts +14 -0
  309. package/dist/components/templates/BattleTemplate.d.ts +25 -0
  310. package/dist/components/templates/CastleTemplate.d.ts +23 -0
  311. package/dist/components/templates/CounterTemplate.d.ts +44 -0
  312. package/dist/components/templates/DashboardLayout.d.ts +34 -0
  313. package/dist/components/templates/GameCanvas3DBattleTemplate.d.ts +96 -0
  314. package/dist/components/templates/GameCanvas3DCastleTemplate.d.ts +90 -0
  315. package/dist/components/templates/GameCanvas3DWorldMapTemplate.d.ts +96 -0
  316. package/dist/components/templates/GameShell.d.ts +34 -0
  317. package/dist/components/templates/GameTemplate.d.ts +36 -0
  318. package/dist/components/templates/GenericAppTemplate.d.ts +30 -0
  319. package/dist/components/templates/WorldMapTemplate.d.ts +29 -0
  320. package/dist/components/templates/index.d.ts +10 -0
  321. package/dist/components/templates/types.d.ts +22 -0
  322. package/dist/context/DesignThemeContext.d.ts +21 -0
  323. package/dist/{ThemeContext-D9xUORq5.d.ts → context/ThemeContext.d.ts} +15 -16
  324. package/dist/context/UISlotContext.d.ts +75 -0
  325. package/dist/context/UserContext.d.ts +111 -0
  326. package/dist/context/index.d.ts +6 -206
  327. package/dist/{event-bus-types-CjJduURa.d.ts → hooks/event-bus-types.d.ts} +4 -6
  328. package/dist/hooks/index.d.ts +30 -1220
  329. package/dist/hooks/index.js +2 -2
  330. package/dist/hooks/useAgentChat.d.ts +104 -0
  331. package/dist/hooks/useAuthContext.d.ts +25 -0
  332. package/dist/hooks/useCompile.d.ts +22 -0
  333. package/dist/hooks/useDeepAgentGeneration.d.ts +46 -0
  334. package/dist/hooks/useDragReorder.d.ts +26 -0
  335. package/dist/hooks/useEntities.d.ts +52 -0
  336. package/dist/hooks/useEntityData.d.ts +155 -0
  337. package/dist/hooks/useEntityMutations.d.ts +80 -0
  338. package/dist/hooks/useEventBus.d.ts +96 -0
  339. package/dist/hooks/useExtensions.d.ts +32 -0
  340. package/dist/hooks/useFileEditor.d.ts +32 -0
  341. package/dist/hooks/useFileSystem.d.ts +40 -0
  342. package/dist/hooks/useGitHub.d.ts +58 -0
  343. package/dist/hooks/useInfiniteScroll.d.ts +13 -0
  344. package/dist/hooks/useLongPress.d.ts +16 -0
  345. package/dist/hooks/useOrbitalHistory.d.ts +39 -0
  346. package/dist/hooks/useOrbitalMutations.d.ts +95 -0
  347. package/dist/hooks/usePinchZoom.d.ts +22 -0
  348. package/dist/hooks/usePreview.d.ts +57 -0
  349. package/dist/hooks/usePullToRefresh.d.ts +25 -0
  350. package/dist/hooks/useQuerySingleton.d.ts +78 -0
  351. package/dist/hooks/useResolvedEntity.d.ts +32 -0
  352. package/dist/hooks/useSwipeGesture.d.ts +26 -0
  353. package/dist/hooks/useTranslate.d.ts +35 -0
  354. package/dist/hooks/useUIEvents.d.ts +35 -0
  355. package/dist/{useUISlots-BBjNvQtb.d.ts → hooks/useUISlots.d.ts} +8 -9
  356. package/dist/hooks/useValidation.d.ts +46 -0
  357. package/dist/lib/api-client.d.ts +42 -0
  358. package/dist/lib/cn.d.ts +6 -0
  359. package/dist/lib/debug.d.ts +43 -0
  360. package/dist/lib/debugRegistry.d.ts +29 -0
  361. package/dist/lib/debugUtils.d.ts +27 -0
  362. package/dist/lib/entityDebug.d.ts +38 -0
  363. package/dist/lib/getNestedValue.d.ts +33 -0
  364. package/dist/lib/guardRegistry.d.ts +32 -0
  365. package/dist/lib/index.d.ts +17 -319
  366. package/dist/lib/index.js +1 -3
  367. package/dist/lib/jazari/index.d.ts +5 -0
  368. package/dist/lib/jazari/layout.d.ts +30 -0
  369. package/dist/lib/jazari/svg-paths.d.ts +61 -0
  370. package/dist/lib/jazari/types.d.ts +91 -0
  371. package/dist/lib/parseContentSegments.d.ts +41 -0
  372. package/dist/lib/tickRegistry.d.ts +40 -0
  373. package/dist/lib/traitRegistry.d.ts +34 -0
  374. package/dist/lib/verificationRegistry.d.ts +138 -0
  375. package/dist/lib/visualizer/browser.d.ts +47 -0
  376. package/dist/lib/visualizer/index.d.ts +143 -0
  377. package/dist/locales/index.d.ts +5 -7
  378. package/dist/providers/EventBusProvider.d.ts +60 -0
  379. package/dist/providers/FetchedDataProvider.d.ts +105 -0
  380. package/dist/providers/OfflineModeProvider.d.ts +79 -0
  381. package/dist/providers/OrbitalProvider.d.ts +101 -0
  382. package/dist/providers/SelectionProvider.d.ts +81 -0
  383. package/dist/providers/VerificationProvider.d.ts +63 -0
  384. package/dist/providers/index.css +599 -0
  385. package/dist/providers/index.d.ts +16 -464
  386. package/dist/providers/index.js +5 -4
  387. package/dist/renderer/client-effect-executor.d.ts +68 -0
  388. package/dist/renderer/data-resolver.d.ts +68 -0
  389. package/dist/renderer/index.d.ts +22 -519
  390. package/dist/renderer/init.d.ts +14 -0
  391. package/dist/renderer/navigation.d.ts +142 -0
  392. package/dist/{offline-executor-CHr4uAhf.d.ts → renderer/offline-executor.d.ts} +9 -172
  393. package/dist/renderer/pattern-resolver.d.ts +91 -0
  394. package/dist/renderer/slot-definitions.d.ts +45 -0
  395. package/dist/renderer/types.d.ts +160 -0
  396. package/dist/renderer/useClientEffects.d.ts +88 -0
  397. package/dist/runtime/EntitySchemaContext.d.ts +40 -0
  398. package/dist/runtime/TraitProvider.d.ts +52 -0
  399. package/dist/runtime/createClientEffectHandlers.d.ts +23 -0
  400. package/dist/runtime/index.css +599 -0
  401. package/dist/runtime/index.d.ts +10 -275
  402. package/dist/runtime/index.js +6 -6
  403. package/dist/runtime/types.d.ts +10 -0
  404. package/dist/runtime/ui/SlotsContext.d.ts +71 -0
  405. package/dist/runtime/useResolvedSchema.d.ts +45 -0
  406. package/dist/runtime/useTraitStateMachine.d.ts +48 -0
  407. package/dist/scripts/generate-design-system.d.ts +29 -0
  408. package/dist/scripts/generate-theme-from-schema.d.ts +10 -0
  409. package/dist/scripts/generate.d.ts +12 -0
  410. package/dist/scripts/suggest-components.d.ts +31 -0
  411. package/dist/scripts/types.d.ts +129 -0
  412. package/dist/stores/entityStore.d.ts +99 -0
  413. package/dist/stores/filtering.d.ts +51 -0
  414. package/dist/stores/index.d.ts +4 -148
  415. package/dist/tsup.config.d.ts +2 -0
  416. package/dist/vitest.config.d.ts +2 -0
  417. package/package.json +5 -4
  418. package/dist/chunk-42YQ6JVR.js +0 -48
  419. package/dist/chunk-WCTZ7WZX.js +0 -311
  420. package/dist/cn-C_ATNPvi.d.ts +0 -332
@@ -0,0 +1,1667 @@
1
+ import { useEmitEvent } from './chunk-YXZM3WCF.js';
2
+ import { __publicField } from './chunk-PKBMQBKP.js';
3
+ import React8, { forwardRef, useRef, useEffect, useImperativeHandle, Component, useState, useCallback, useMemo } from 'react';
4
+ import { useThree, useFrame } from '@react-three/fiber';
5
+ import { OrbitControls } from '@react-three/drei';
6
+ import * as THREE from 'three';
7
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
+ import { GLTFLoader as GLTFLoader$1 } from 'three/examples/jsm/loaders/GLTFLoader';
9
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
10
+ import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
11
+
12
+ var Camera3D = forwardRef(
13
+ ({
14
+ mode = "isometric",
15
+ position = [10, 10, 10],
16
+ target = [0, 0, 0],
17
+ zoom = 1,
18
+ fov = 45,
19
+ enableOrbit = true,
20
+ minDistance = 2,
21
+ maxDistance = 100,
22
+ onChange
23
+ }, ref) => {
24
+ const { camera, set, viewport } = useThree();
25
+ const controlsRef = useRef(null);
26
+ const initialPosition = useRef(new THREE.Vector3(...position));
27
+ const initialTarget = useRef(new THREE.Vector3(...target));
28
+ useEffect(() => {
29
+ let newCamera;
30
+ if (mode === "isometric") {
31
+ const aspect = viewport.aspect;
32
+ const size = 10 / zoom;
33
+ newCamera = new THREE.OrthographicCamera(
34
+ -size * aspect,
35
+ size * aspect,
36
+ size,
37
+ -size,
38
+ 0.1,
39
+ 1e3
40
+ );
41
+ } else {
42
+ newCamera = new THREE.PerspectiveCamera(fov, viewport.aspect, 0.1, 1e3);
43
+ }
44
+ newCamera.position.copy(initialPosition.current);
45
+ newCamera.lookAt(initialTarget.current);
46
+ set({ camera: newCamera });
47
+ if (mode === "top-down") {
48
+ newCamera.position.set(0, 20 / zoom, 0);
49
+ newCamera.lookAt(0, 0, 0);
50
+ }
51
+ return () => {
52
+ };
53
+ }, [mode, fov, zoom, viewport.aspect, set]);
54
+ useFrame(() => {
55
+ if (onChange) {
56
+ onChange(camera);
57
+ }
58
+ });
59
+ useImperativeHandle(ref, () => ({
60
+ getCamera: () => camera,
61
+ setPosition: (x, y, z) => {
62
+ camera.position.set(x, y, z);
63
+ if (controlsRef.current) {
64
+ controlsRef.current.update();
65
+ }
66
+ },
67
+ lookAt: (x, y, z) => {
68
+ camera.lookAt(x, y, z);
69
+ if (controlsRef.current) {
70
+ controlsRef.current.target.set(x, y, z);
71
+ controlsRef.current.update();
72
+ }
73
+ },
74
+ reset: () => {
75
+ camera.position.copy(initialPosition.current);
76
+ camera.lookAt(initialTarget.current);
77
+ if (controlsRef.current) {
78
+ controlsRef.current.target.copy(initialTarget.current);
79
+ controlsRef.current.update();
80
+ }
81
+ },
82
+ getViewBounds: () => {
83
+ const min = new THREE.Vector3(-10, -10, -10);
84
+ const max = new THREE.Vector3(10, 10, 10);
85
+ return { min, max };
86
+ }
87
+ }));
88
+ const maxPolarAngle = mode === "top-down" ? 0.1 : Math.PI / 2 - 0.1;
89
+ return /* @__PURE__ */ jsx(
90
+ OrbitControls,
91
+ {
92
+ ref: controlsRef,
93
+ camera,
94
+ enabled: enableOrbit,
95
+ target: initialTarget.current,
96
+ minDistance,
97
+ maxDistance,
98
+ maxPolarAngle,
99
+ enableDamping: true,
100
+ dampingFactor: 0.05
101
+ }
102
+ );
103
+ }
104
+ );
105
+ Camera3D.displayName = "Camera3D";
106
+ var Canvas3DErrorBoundary = class extends Component {
107
+ constructor(props) {
108
+ super(props);
109
+ __publicField(this, "handleReset", () => {
110
+ this.setState({
111
+ hasError: false,
112
+ error: null,
113
+ errorInfo: null
114
+ });
115
+ this.props.onReset?.();
116
+ });
117
+ this.state = {
118
+ hasError: false,
119
+ error: null,
120
+ errorInfo: null
121
+ };
122
+ }
123
+ static getDerivedStateFromError(error) {
124
+ return {
125
+ hasError: true,
126
+ error,
127
+ errorInfo: null
128
+ };
129
+ }
130
+ componentDidCatch(error, errorInfo) {
131
+ this.setState({ errorInfo });
132
+ this.props.onError?.(error, errorInfo);
133
+ console.error("[Canvas3DErrorBoundary] Error caught:", error);
134
+ console.error("[Canvas3DErrorBoundary] Component stack:", errorInfo.componentStack);
135
+ }
136
+ render() {
137
+ if (this.state.hasError) {
138
+ if (this.props.fallback) {
139
+ return this.props.fallback;
140
+ }
141
+ return /* @__PURE__ */ jsx("div", { className: "canvas-3d-error", children: /* @__PURE__ */ jsxs("div", { className: "canvas-3d-error__content", children: [
142
+ /* @__PURE__ */ jsx("div", { className: "canvas-3d-error__icon", children: "\u26A0\uFE0F" }),
143
+ /* @__PURE__ */ jsx("h2", { className: "canvas-3d-error__title", children: "3D Scene Error" }),
144
+ /* @__PURE__ */ jsx("p", { className: "canvas-3d-error__message", children: "Something went wrong while rendering the 3D scene." }),
145
+ this.state.error && /* @__PURE__ */ jsxs("details", { className: "canvas-3d-error__details", children: [
146
+ /* @__PURE__ */ jsx("summary", { children: "Error Details" }),
147
+ /* @__PURE__ */ jsxs("pre", { className: "error__stack", children: [
148
+ this.state.error.message,
149
+ "\n",
150
+ this.state.error.stack
151
+ ] }),
152
+ this.state.errorInfo && /* @__PURE__ */ jsx("pre", { className: "error__component-stack", children: this.state.errorInfo.componentStack })
153
+ ] }),
154
+ /* @__PURE__ */ jsxs("div", { className: "canvas-3d-error__actions", children: [
155
+ /* @__PURE__ */ jsx(
156
+ "button",
157
+ {
158
+ className: "error__button error__button--primary",
159
+ onClick: this.handleReset,
160
+ children: "Try Again"
161
+ }
162
+ ),
163
+ /* @__PURE__ */ jsx(
164
+ "button",
165
+ {
166
+ className: "error__button error__button--secondary",
167
+ onClick: () => window.location.reload(),
168
+ children: "Reload Page"
169
+ }
170
+ )
171
+ ] })
172
+ ] }) });
173
+ }
174
+ return this.props.children;
175
+ }
176
+ };
177
+ function Canvas3DLoadingState({
178
+ progress = 0,
179
+ loaded = 0,
180
+ total = 0,
181
+ message = "Loading 3D Scene...",
182
+ details,
183
+ showSpinner = true,
184
+ className
185
+ }) {
186
+ const clampedProgress = Math.max(0, Math.min(100, progress));
187
+ const hasProgress = total > 0;
188
+ return /* @__PURE__ */ jsxs("div", { className: `canvas-3d-loading ${className || ""}`, children: [
189
+ /* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__content", children: [
190
+ showSpinner && /* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__spinner", children: [
191
+ /* @__PURE__ */ jsx("div", { className: "spinner__ring" }),
192
+ /* @__PURE__ */ jsx("div", { className: "spinner__ring spinner__ring--secondary" })
193
+ ] }),
194
+ /* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__message", children: message }),
195
+ details && /* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__details", children: details }),
196
+ hasProgress && /* @__PURE__ */ jsxs("div", { className: "canvas-3d-loading__progress", children: [
197
+ /* @__PURE__ */ jsx("div", { className: "progress__bar", children: /* @__PURE__ */ jsx(
198
+ "div",
199
+ {
200
+ className: "progress__fill",
201
+ style: { width: `${clampedProgress}%` }
202
+ }
203
+ ) }),
204
+ /* @__PURE__ */ jsxs("div", { className: "progress__text", children: [
205
+ /* @__PURE__ */ jsxs("span", { className: "progress__percentage", children: [
206
+ clampedProgress,
207
+ "%"
208
+ ] }),
209
+ /* @__PURE__ */ jsxs("span", { className: "progress__count", children: [
210
+ "(",
211
+ loaded,
212
+ "/",
213
+ total,
214
+ ")"
215
+ ] })
216
+ ] })
217
+ ] })
218
+ ] }),
219
+ /* @__PURE__ */ jsx("div", { className: "canvas-3d-loading__background", children: /* @__PURE__ */ jsx("div", { className: "bg__grid" }) })
220
+ ] });
221
+ }
222
+ var DEFAULT_FEATURE_CONFIGS = {
223
+ tree: { color: 2263842, height: 1.5, scale: 1, geometry: "tree" },
224
+ rock: { color: 8421504, height: 0.5, scale: 0.8, geometry: "rock" },
225
+ bush: { color: 3329330, height: 0.4, scale: 0.6, geometry: "bush" },
226
+ house: { color: 9127187, height: 1.2, scale: 1.2, geometry: "house" },
227
+ tower: { color: 6908265, height: 2.5, scale: 1, geometry: "tower" },
228
+ wall: { color: 8421504, height: 1, scale: 1, geometry: "wall" },
229
+ mountain: { color: 5597999, height: 2, scale: 1.5, geometry: "mountain" },
230
+ hill: { color: 7048739, height: 0.8, scale: 1.2, geometry: "hill" },
231
+ water: { color: 4491468, height: 0.1, scale: 1, geometry: "water" },
232
+ chest: { color: 16766720, height: 0.3, scale: 0.4, geometry: "chest" },
233
+ sign: { color: 9127187, height: 0.8, scale: 0.3, geometry: "sign" },
234
+ portal: { color: 10040012, height: 1.5, scale: 1, geometry: "portal" }
235
+ };
236
+ function TreeFeature({ height, color }) {
237
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
238
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.3, 0], children: [
239
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.08, 0.1, height * 0.6, 6] }),
240
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: 9127187 })
241
+ ] }),
242
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.7, 0], children: [
243
+ /* @__PURE__ */ jsx("coneGeometry", { args: [0.4, height * 0.5, 8] }),
244
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
245
+ ] }),
246
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.9, 0], children: [
247
+ /* @__PURE__ */ jsx("coneGeometry", { args: [0.3, height * 0.4, 8] }),
248
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
249
+ ] }),
250
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 1.05, 0], children: [
251
+ /* @__PURE__ */ jsx("coneGeometry", { args: [0.15, height * 0.25, 8] }),
252
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
253
+ ] })
254
+ ] });
255
+ }
256
+ function RockFeature({ height, color }) {
257
+ return /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.4, 0], children: [
258
+ /* @__PURE__ */ jsx("dodecahedronGeometry", { args: [height * 0.5, 0] }),
259
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color, roughness: 0.9 })
260
+ ] });
261
+ }
262
+ function BushFeature({ height, color }) {
263
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
264
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.3, 0], children: [
265
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [height * 0.4, 8, 8] }),
266
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
267
+ ] }),
268
+ /* @__PURE__ */ jsxs("mesh", { position: [0.1, height * 0.4, 0.1], children: [
269
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [height * 0.25, 8, 8] }),
270
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
271
+ ] })
272
+ ] });
273
+ }
274
+ function HouseFeature({ height, color }) {
275
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
276
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.4, 0], children: [
277
+ /* @__PURE__ */ jsx("boxGeometry", { args: [0.8, height * 0.8, 0.8] }),
278
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: 13808780 })
279
+ ] }),
280
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.9, 0], children: [
281
+ /* @__PURE__ */ jsx("coneGeometry", { args: [0.6, height * 0.4, 4] }),
282
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
283
+ ] }),
284
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.25, 0.41], children: [
285
+ /* @__PURE__ */ jsx("planeGeometry", { args: [0.25, height * 0.5] }),
286
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: 4863784 })
287
+ ] })
288
+ ] });
289
+ }
290
+ function TowerFeature({ height, color }) {
291
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
292
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.5, 0], children: [
293
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.35, height, 8] }),
294
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
295
+ ] }),
296
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height + 0.05, 0], children: [
297
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.35, 0.35, 0.1, 8] }),
298
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
299
+ ] })
300
+ ] });
301
+ }
302
+ function ChestFeature({ height, color }) {
303
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
304
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.5, 0], children: [
305
+ /* @__PURE__ */ jsx("boxGeometry", { args: [0.3, height, 0.2] }),
306
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color, metalness: 0.6, roughness: 0.3 })
307
+ ] }),
308
+ /* @__PURE__ */ jsxs("mesh", { position: [0, height + 0.05, 0], children: [
309
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.15, 0.15, 0.3, 8, 1, false, 0, Math.PI] }),
310
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color, metalness: 0.6, roughness: 0.3 })
311
+ ] })
312
+ ] });
313
+ }
314
+ function DefaultFeature({ height, color }) {
315
+ return /* @__PURE__ */ jsxs("mesh", { position: [0, height * 0.5, 0], children: [
316
+ /* @__PURE__ */ jsx("boxGeometry", { args: [0.5, height, 0.5] }),
317
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color })
318
+ ] });
319
+ }
320
+ function FeatureVisual({
321
+ feature,
322
+ position,
323
+ isSelected,
324
+ onClick,
325
+ onHover
326
+ }) {
327
+ const config = DEFAULT_FEATURE_CONFIGS[feature.type] || {
328
+ color: 8947848,
329
+ height: 0.5,
330
+ scale: 1,
331
+ geometry: "default"
332
+ };
333
+ const color = feature.color ? parseInt(feature.color.replace("#", ""), 16) : config.color;
334
+ const renderGeometry = () => {
335
+ switch (config.geometry) {
336
+ case "tree":
337
+ return /* @__PURE__ */ jsx(TreeFeature, { height: config.height, color });
338
+ case "rock":
339
+ return /* @__PURE__ */ jsx(RockFeature, { height: config.height, color });
340
+ case "bush":
341
+ return /* @__PURE__ */ jsx(BushFeature, { height: config.height, color });
342
+ case "house":
343
+ return /* @__PURE__ */ jsx(HouseFeature, { height: config.height, color });
344
+ case "tower":
345
+ return /* @__PURE__ */ jsx(TowerFeature, { height: config.height, color });
346
+ case "chest":
347
+ return /* @__PURE__ */ jsx(ChestFeature, { height: config.height, color });
348
+ default:
349
+ return /* @__PURE__ */ jsx(DefaultFeature, { height: config.height, color });
350
+ }
351
+ };
352
+ return /* @__PURE__ */ jsxs(
353
+ "group",
354
+ {
355
+ position,
356
+ scale: config.scale,
357
+ onClick,
358
+ onPointerEnter: () => onHover(true),
359
+ onPointerLeave: () => onHover(false),
360
+ userData: { type: "feature", featureId: feature.id, featureType: feature.type },
361
+ children: [
362
+ isSelected && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
363
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
364
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#ffff00", transparent: true, opacity: 0.8 })
365
+ ] }),
366
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 0.01, 0], rotation: [-Math.PI / 2, 0, 0], children: [
367
+ /* @__PURE__ */ jsx("circleGeometry", { args: [0.35, 16] }),
368
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#000000", transparent: true, opacity: 0.2 })
369
+ ] }),
370
+ renderGeometry()
371
+ ]
372
+ }
373
+ );
374
+ }
375
+ function FeatureRenderer({
376
+ features,
377
+ cellSize = 1,
378
+ offsetX = 0,
379
+ offsetZ = 0,
380
+ onFeatureClick,
381
+ onFeatureHover,
382
+ selectedFeatureIds = [],
383
+ featureColors
384
+ }) {
385
+ return /* @__PURE__ */ jsx("group", { children: features.map((feature) => {
386
+ const x = (feature.x - offsetX) * cellSize;
387
+ const z = ((feature.z ?? feature.y ?? 0) - offsetZ) * cellSize;
388
+ const y = (feature.elevation ?? 0) * 0.1;
389
+ const isSelected = feature.id ? selectedFeatureIds.includes(feature.id) : false;
390
+ return /* @__PURE__ */ jsx(
391
+ FeatureVisual,
392
+ {
393
+ feature,
394
+ position: [x, y, z],
395
+ isSelected,
396
+ onClick: () => onFeatureClick?.(feature),
397
+ onHover: (hovered) => onFeatureHover?.(hovered ? feature : null)
398
+ },
399
+ feature.id ?? `feature-${feature.x}-${feature.y}`
400
+ );
401
+ }) });
402
+ }
403
+ function detectAssetRoot(modelUrl) {
404
+ const idx = modelUrl.indexOf("/3d/");
405
+ if (idx !== -1) {
406
+ return modelUrl.substring(0, idx + 4);
407
+ }
408
+ return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
409
+ }
410
+ function useGLTFModel(url) {
411
+ const [model, setModel] = useState(null);
412
+ const [isLoading, setIsLoading] = useState(false);
413
+ const [error, setError] = useState(null);
414
+ useEffect(() => {
415
+ if (!url) {
416
+ setModel(null);
417
+ return;
418
+ }
419
+ setIsLoading(true);
420
+ setError(null);
421
+ const assetRoot = detectAssetRoot(url);
422
+ const loader = new GLTFLoader$1();
423
+ loader.setResourcePath(assetRoot);
424
+ loader.load(
425
+ url,
426
+ (gltf) => {
427
+ setModel(gltf.scene);
428
+ setIsLoading(false);
429
+ },
430
+ void 0,
431
+ (err) => {
432
+ setError(err instanceof Error ? err : new Error(String(err)));
433
+ setIsLoading(false);
434
+ }
435
+ );
436
+ }, [url]);
437
+ return { model, isLoading, error };
438
+ }
439
+ function FeatureModel({
440
+ feature,
441
+ position,
442
+ isSelected,
443
+ onClick,
444
+ onHover
445
+ }) {
446
+ const groupRef = useRef(null);
447
+ const { model: loadedModel, isLoading } = useGLTFModel(feature.assetUrl);
448
+ const model = useMemo(() => {
449
+ if (!loadedModel) return null;
450
+ const cloned = loadedModel.clone();
451
+ cloned.scale.setScalar(0.3);
452
+ cloned.traverse((child) => {
453
+ if (child instanceof THREE.Mesh) {
454
+ child.castShadow = true;
455
+ child.receiveShadow = true;
456
+ }
457
+ });
458
+ return cloned;
459
+ }, [loadedModel]);
460
+ useFrame((state) => {
461
+ if (groupRef.current) {
462
+ const featureRotation = feature.rotation;
463
+ const baseRotation = featureRotation !== void 0 ? featureRotation * Math.PI / 180 - Math.PI / 4 : -Math.PI / 4;
464
+ const wobble = isSelected ? Math.sin(state.clock.elapsedTime * 2) * 0.1 : 0;
465
+ groupRef.current.rotation.y = baseRotation + wobble;
466
+ }
467
+ });
468
+ if (isLoading) {
469
+ return /* @__PURE__ */ jsx("group", { position, children: /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
470
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.3, 0.35, 16] }),
471
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#4a90d9", transparent: true, opacity: 0.8 })
472
+ ] }) });
473
+ }
474
+ if (!model && !feature.assetUrl) {
475
+ return /* @__PURE__ */ jsxs(
476
+ "group",
477
+ {
478
+ position,
479
+ onClick,
480
+ onPointerEnter: () => onHover(true),
481
+ onPointerLeave: () => onHover(false),
482
+ userData: { type: "feature", featureId: feature.id, featureType: feature.type },
483
+ children: [
484
+ isSelected && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
485
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
486
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#ffff00", transparent: true, opacity: 0.8 })
487
+ ] }),
488
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 0.5, 0], children: [
489
+ /* @__PURE__ */ jsx("boxGeometry", { args: [0.4, 0.4, 0.4] }),
490
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: 8947848 })
491
+ ] })
492
+ ]
493
+ }
494
+ );
495
+ }
496
+ return /* @__PURE__ */ jsxs(
497
+ "group",
498
+ {
499
+ ref: groupRef,
500
+ position,
501
+ onClick,
502
+ onPointerEnter: () => onHover(true),
503
+ onPointerLeave: () => onHover(false),
504
+ userData: { type: "feature", featureId: feature.id, featureType: feature.type },
505
+ children: [
506
+ isSelected && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
507
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
508
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#ffff00", transparent: true, opacity: 0.8 })
509
+ ] }),
510
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 0.01, 0], rotation: [-Math.PI / 2, 0, 0], children: [
511
+ /* @__PURE__ */ jsx("circleGeometry", { args: [0.35, 16] }),
512
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#000000", transparent: true, opacity: 0.2 })
513
+ ] }),
514
+ model && /* @__PURE__ */ jsx("primitive", { object: model })
515
+ ]
516
+ }
517
+ );
518
+ }
519
+ function FeatureRenderer3D({
520
+ features,
521
+ cellSize = 1,
522
+ offsetX = 0,
523
+ offsetZ = 0,
524
+ onFeatureClick,
525
+ onFeatureHover,
526
+ selectedFeatureIds = []
527
+ }) {
528
+ return /* @__PURE__ */ jsx("group", { children: features.map((feature) => {
529
+ const x = (feature.x - offsetX) * cellSize;
530
+ const z = ((feature.z ?? feature.y ?? 0) - offsetZ) * cellSize;
531
+ const y = (feature.elevation ?? 0) * 0.1;
532
+ const isSelected = feature.id ? selectedFeatureIds.includes(feature.id) : false;
533
+ return /* @__PURE__ */ jsx(
534
+ FeatureModel,
535
+ {
536
+ feature,
537
+ position: [x, y, z],
538
+ isSelected,
539
+ onClick: () => onFeatureClick?.(feature),
540
+ onHover: (hovered) => onFeatureHover?.(hovered ? feature : null)
541
+ },
542
+ feature.id ?? `feature-${feature.x}-${feature.y}`
543
+ );
544
+ }) });
545
+ }
546
+ function preloadFeatures(urls) {
547
+ urls.forEach((url) => {
548
+ if (url) {
549
+ const loader = new GLTFLoader$1();
550
+ loader.setResourcePath(detectAssetRoot(url));
551
+ loader.load(url, () => {
552
+ console.log("[FeatureRenderer3D] Preloaded:", url);
553
+ });
554
+ }
555
+ });
556
+ }
557
+ function detectAssetRoot2(modelUrl) {
558
+ const idx = modelUrl.indexOf("/3d/");
559
+ if (idx !== -1) {
560
+ return modelUrl.substring(0, idx + 4);
561
+ }
562
+ return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
563
+ }
564
+ function createGLTFLoaderForUrl(url) {
565
+ const loader = new GLTFLoader();
566
+ loader.setResourcePath(detectAssetRoot2(url));
567
+ return loader;
568
+ }
569
+ var AssetLoader = class {
570
+ constructor() {
571
+ __publicField(this, "objLoader");
572
+ __publicField(this, "textureLoader");
573
+ __publicField(this, "modelCache");
574
+ __publicField(this, "textureCache");
575
+ __publicField(this, "loadingPromises");
576
+ this.objLoader = new OBJLoader();
577
+ this.textureLoader = new THREE.TextureLoader();
578
+ this.modelCache = /* @__PURE__ */ new Map();
579
+ this.textureCache = /* @__PURE__ */ new Map();
580
+ this.loadingPromises = /* @__PURE__ */ new Map();
581
+ }
582
+ /**
583
+ * Load a GLB/GLTF model
584
+ * @param url - URL to the .glb or .gltf file
585
+ * @returns Promise with loaded model scene and animations
586
+ */
587
+ async loadModel(url) {
588
+ if (this.modelCache.has(url)) {
589
+ return this.modelCache.get(url);
590
+ }
591
+ if (this.loadingPromises.has(url)) {
592
+ return this.loadingPromises.get(url);
593
+ }
594
+ const loader = createGLTFLoaderForUrl(url);
595
+ const loadPromise = loader.loadAsync(url).then((gltf) => {
596
+ const result = {
597
+ scene: gltf.scene,
598
+ animations: gltf.animations || []
599
+ };
600
+ this.modelCache.set(url, result);
601
+ this.loadingPromises.delete(url);
602
+ return result;
603
+ }).catch((error) => {
604
+ this.loadingPromises.delete(url);
605
+ throw new Error(`Failed to load model ${url}: ${error.message}`);
606
+ });
607
+ this.loadingPromises.set(url, loadPromise);
608
+ return loadPromise;
609
+ }
610
+ /**
611
+ * Load an OBJ model (fallback for non-GLB assets)
612
+ * @param url - URL to the .obj file
613
+ * @returns Promise with loaded object group
614
+ */
615
+ async loadOBJ(url) {
616
+ if (this.modelCache.has(url)) {
617
+ return this.modelCache.get(url).scene;
618
+ }
619
+ if (this.loadingPromises.has(url)) {
620
+ const result = await this.loadingPromises.get(url);
621
+ return result.scene;
622
+ }
623
+ const loadPromise = this.objLoader.loadAsync(url).then((group) => {
624
+ const result = {
625
+ scene: group,
626
+ animations: []
627
+ };
628
+ this.modelCache.set(url, result);
629
+ this.loadingPromises.delete(url);
630
+ return result;
631
+ }).catch((error) => {
632
+ this.loadingPromises.delete(url);
633
+ throw new Error(`Failed to load OBJ ${url}: ${error.message}`);
634
+ });
635
+ this.loadingPromises.set(url, loadPromise);
636
+ return (await loadPromise).scene;
637
+ }
638
+ /**
639
+ * Load a texture
640
+ * @param url - URL to the texture image
641
+ * @returns Promise with loaded texture
642
+ */
643
+ async loadTexture(url) {
644
+ if (this.textureCache.has(url)) {
645
+ return this.textureCache.get(url);
646
+ }
647
+ if (this.loadingPromises.has(`texture:${url}`)) {
648
+ return this.loadingPromises.get(`texture:${url}`);
649
+ }
650
+ const loadPromise = this.textureLoader.loadAsync(url).then((texture) => {
651
+ texture.colorSpace = THREE.SRGBColorSpace;
652
+ this.textureCache.set(url, texture);
653
+ this.loadingPromises.delete(`texture:${url}`);
654
+ return texture;
655
+ }).catch((error) => {
656
+ this.loadingPromises.delete(`texture:${url}`);
657
+ throw new Error(`Failed to load texture ${url}: ${error.message}`);
658
+ });
659
+ this.loadingPromises.set(`texture:${url}`, loadPromise);
660
+ return loadPromise;
661
+ }
662
+ /**
663
+ * Preload multiple assets
664
+ * @param urls - Array of asset URLs to preload
665
+ * @returns Promise that resolves when all assets are loaded
666
+ */
667
+ async preload(urls) {
668
+ const promises = urls.map((url) => {
669
+ if (url.endsWith(".glb") || url.endsWith(".gltf")) {
670
+ return this.loadModel(url).catch(() => null);
671
+ } else if (url.endsWith(".obj")) {
672
+ return this.loadOBJ(url).catch(() => null);
673
+ } else if (/\.(png|jpg|jpeg|webp)$/i.test(url)) {
674
+ return this.loadTexture(url).catch(() => null);
675
+ }
676
+ return Promise.resolve(null);
677
+ });
678
+ await Promise.all(promises);
679
+ }
680
+ /**
681
+ * Check if a model is cached
682
+ * @param url - Model URL
683
+ */
684
+ hasModel(url) {
685
+ return this.modelCache.has(url);
686
+ }
687
+ /**
688
+ * Check if a texture is cached
689
+ * @param url - Texture URL
690
+ */
691
+ hasTexture(url) {
692
+ return this.textureCache.has(url);
693
+ }
694
+ /**
695
+ * Get cached model (throws if not cached)
696
+ * @param url - Model URL
697
+ */
698
+ getModel(url) {
699
+ const model = this.modelCache.get(url);
700
+ if (!model) {
701
+ throw new Error(`Model ${url} not in cache`);
702
+ }
703
+ return model;
704
+ }
705
+ /**
706
+ * Get cached texture (throws if not cached)
707
+ * @param url - Texture URL
708
+ */
709
+ getTexture(url) {
710
+ const texture = this.textureCache.get(url);
711
+ if (!texture) {
712
+ throw new Error(`Texture ${url} not in cache`);
713
+ }
714
+ return texture;
715
+ }
716
+ /**
717
+ * Clear all caches
718
+ */
719
+ clearCache() {
720
+ this.textureCache.forEach((texture) => {
721
+ texture.dispose();
722
+ });
723
+ this.modelCache.forEach((model) => {
724
+ model.scene.traverse((child) => {
725
+ if (child instanceof THREE.Mesh) {
726
+ child.geometry.dispose();
727
+ if (Array.isArray(child.material)) {
728
+ child.material.forEach((m) => m.dispose());
729
+ } else {
730
+ child.material.dispose();
731
+ }
732
+ }
733
+ });
734
+ });
735
+ this.modelCache.clear();
736
+ this.textureCache.clear();
737
+ this.loadingPromises.clear();
738
+ }
739
+ /**
740
+ * Get cache statistics
741
+ */
742
+ getStats() {
743
+ return {
744
+ models: this.modelCache.size,
745
+ textures: this.textureCache.size,
746
+ loading: this.loadingPromises.size
747
+ };
748
+ }
749
+ };
750
+ var assetLoader = new AssetLoader();
751
+ function useAssetLoader(options = {}) {
752
+ const { preloadUrls = [], loader: customLoader } = options;
753
+ const loaderRef = useRef(customLoader || new AssetLoader());
754
+ const [state, setState] = useState({
755
+ isLoading: false,
756
+ progress: 0,
757
+ loaded: 0,
758
+ total: 0,
759
+ errors: []
760
+ });
761
+ useEffect(() => {
762
+ if (preloadUrls.length > 0) {
763
+ preload(preloadUrls);
764
+ }
765
+ }, []);
766
+ const updateProgress = useCallback((loaded, total) => {
767
+ setState((prev) => ({
768
+ ...prev,
769
+ loaded,
770
+ total,
771
+ progress: total > 0 ? Math.round(loaded / total * 100) : 0
772
+ }));
773
+ }, []);
774
+ const loadModel = useCallback(
775
+ async (url) => {
776
+ setState((prev) => ({ ...prev, isLoading: true }));
777
+ try {
778
+ const model = await loaderRef.current.loadModel(url);
779
+ setState((prev) => ({
780
+ ...prev,
781
+ isLoading: false,
782
+ loaded: prev.loaded + 1
783
+ }));
784
+ return model;
785
+ } catch (error) {
786
+ const errorMsg = error instanceof Error ? error.message : String(error);
787
+ setState((prev) => ({
788
+ ...prev,
789
+ isLoading: false,
790
+ errors: [...prev.errors, errorMsg]
791
+ }));
792
+ throw error;
793
+ }
794
+ },
795
+ []
796
+ );
797
+ const loadOBJ = useCallback(
798
+ async (url) => {
799
+ setState((prev) => ({ ...prev, isLoading: true }));
800
+ try {
801
+ const model = await loaderRef.current.loadOBJ(url);
802
+ setState((prev) => ({
803
+ ...prev,
804
+ isLoading: false,
805
+ loaded: prev.loaded + 1
806
+ }));
807
+ return model;
808
+ } catch (error) {
809
+ const errorMsg = error instanceof Error ? error.message : String(error);
810
+ setState((prev) => ({
811
+ ...prev,
812
+ isLoading: false,
813
+ errors: [...prev.errors, errorMsg]
814
+ }));
815
+ throw error;
816
+ }
817
+ },
818
+ []
819
+ );
820
+ const loadTexture = useCallback(
821
+ async (url) => {
822
+ setState((prev) => ({ ...prev, isLoading: true }));
823
+ try {
824
+ const texture = await loaderRef.current.loadTexture(url);
825
+ setState((prev) => ({
826
+ ...prev,
827
+ isLoading: false,
828
+ loaded: prev.loaded + 1
829
+ }));
830
+ return texture;
831
+ } catch (error) {
832
+ const errorMsg = error instanceof Error ? error.message : String(error);
833
+ setState((prev) => ({
834
+ ...prev,
835
+ isLoading: false,
836
+ errors: [...prev.errors, errorMsg]
837
+ }));
838
+ throw error;
839
+ }
840
+ },
841
+ []
842
+ );
843
+ const preload = useCallback(
844
+ async (urls) => {
845
+ setState((prev) => ({
846
+ ...prev,
847
+ isLoading: true,
848
+ total: urls.length,
849
+ loaded: 0,
850
+ errors: []
851
+ }));
852
+ let completed = 0;
853
+ const errors = [];
854
+ await Promise.all(
855
+ urls.map(async (url) => {
856
+ try {
857
+ if (url.endsWith(".glb") || url.endsWith(".gltf")) {
858
+ await loaderRef.current.loadModel(url);
859
+ } else if (url.endsWith(".obj")) {
860
+ await loaderRef.current.loadOBJ(url);
861
+ } else if (/\.(png|jpg|jpeg|webp)$/i.test(url)) {
862
+ await loaderRef.current.loadTexture(url);
863
+ }
864
+ completed++;
865
+ updateProgress(completed, urls.length);
866
+ } catch (error) {
867
+ const errorMsg = error instanceof Error ? error.message : String(error);
868
+ errors.push(`${url}: ${errorMsg}`);
869
+ completed++;
870
+ updateProgress(completed, urls.length);
871
+ }
872
+ })
873
+ );
874
+ setState((prev) => ({
875
+ ...prev,
876
+ isLoading: false,
877
+ errors
878
+ }));
879
+ },
880
+ [updateProgress]
881
+ );
882
+ const hasModel = useCallback((url) => {
883
+ return loaderRef.current.hasModel(url);
884
+ }, []);
885
+ const hasTexture = useCallback((url) => {
886
+ return loaderRef.current.hasTexture(url);
887
+ }, []);
888
+ const getModel = useCallback((url) => {
889
+ try {
890
+ return loaderRef.current.getModel(url);
891
+ } catch {
892
+ return void 0;
893
+ }
894
+ }, []);
895
+ const getTexture = useCallback((url) => {
896
+ try {
897
+ return loaderRef.current.getTexture(url);
898
+ } catch {
899
+ return void 0;
900
+ }
901
+ }, []);
902
+ const clearCache = useCallback(() => {
903
+ loaderRef.current.clearCache();
904
+ setState({
905
+ isLoading: false,
906
+ progress: 0,
907
+ loaded: 0,
908
+ total: 0,
909
+ errors: []
910
+ });
911
+ }, []);
912
+ return {
913
+ ...state,
914
+ loadModel,
915
+ loadOBJ,
916
+ loadTexture,
917
+ preload,
918
+ hasModel,
919
+ hasTexture,
920
+ getModel,
921
+ getTexture,
922
+ clearCache
923
+ };
924
+ }
925
+ function useGameCanvas3DEvents(options) {
926
+ const {
927
+ tileClickEvent,
928
+ unitClickEvent,
929
+ featureClickEvent,
930
+ canvasClickEvent,
931
+ tileHoverEvent,
932
+ tileLeaveEvent,
933
+ unitAnimationEvent,
934
+ cameraChangeEvent,
935
+ onTileClick,
936
+ onUnitClick,
937
+ onFeatureClick,
938
+ onCanvasClick,
939
+ onTileHover,
940
+ onUnitAnimation
941
+ } = options;
942
+ const emit = useEmitEvent();
943
+ const optionsRef = useRef(options);
944
+ optionsRef.current = options;
945
+ const handleTileClick = useCallback(
946
+ (tile, event) => {
947
+ if (tileClickEvent) {
948
+ emit(tileClickEvent, {
949
+ tileId: tile.id,
950
+ x: tile.x,
951
+ z: tile.z ?? tile.y ?? 0,
952
+ type: tile.type,
953
+ terrain: tile.terrain,
954
+ elevation: tile.elevation
955
+ });
956
+ }
957
+ optionsRef.current.onTileClick?.(tile, event);
958
+ },
959
+ [tileClickEvent, emit]
960
+ );
961
+ const handleUnitClick = useCallback(
962
+ (unit, event) => {
963
+ if (unitClickEvent) {
964
+ emit(unitClickEvent, {
965
+ unitId: unit.id,
966
+ x: unit.x,
967
+ z: unit.z ?? unit.y ?? 0,
968
+ unitType: unit.unitType,
969
+ name: unit.name,
970
+ team: unit.team,
971
+ faction: unit.faction,
972
+ health: unit.health,
973
+ maxHealth: unit.maxHealth
974
+ });
975
+ }
976
+ optionsRef.current.onUnitClick?.(unit, event);
977
+ },
978
+ [unitClickEvent, emit]
979
+ );
980
+ const handleFeatureClick = useCallback(
981
+ (feature, event) => {
982
+ if (featureClickEvent) {
983
+ emit(featureClickEvent, {
984
+ featureId: feature.id,
985
+ x: feature.x,
986
+ z: feature.z ?? feature.y ?? 0,
987
+ type: feature.type,
988
+ elevation: feature.elevation
989
+ });
990
+ }
991
+ optionsRef.current.onFeatureClick?.(feature, event);
992
+ },
993
+ [featureClickEvent, emit]
994
+ );
995
+ const handleCanvasClick = useCallback(
996
+ (event) => {
997
+ if (canvasClickEvent) {
998
+ emit(canvasClickEvent, {
999
+ clientX: event.clientX,
1000
+ clientY: event.clientY,
1001
+ button: event.button
1002
+ });
1003
+ }
1004
+ optionsRef.current.onCanvasClick?.(event);
1005
+ },
1006
+ [canvasClickEvent, emit]
1007
+ );
1008
+ const handleTileHover = useCallback(
1009
+ (tile, event) => {
1010
+ if (tile) {
1011
+ if (tileHoverEvent) {
1012
+ emit(tileHoverEvent, {
1013
+ tileId: tile.id,
1014
+ x: tile.x,
1015
+ z: tile.z ?? tile.y ?? 0,
1016
+ type: tile.type
1017
+ });
1018
+ }
1019
+ } else {
1020
+ if (tileLeaveEvent) {
1021
+ emit(tileLeaveEvent, {});
1022
+ }
1023
+ }
1024
+ optionsRef.current.onTileHover?.(tile, event);
1025
+ },
1026
+ [tileHoverEvent, tileLeaveEvent, emit]
1027
+ );
1028
+ const handleUnitAnimation = useCallback(
1029
+ (unitId, state) => {
1030
+ if (unitAnimationEvent) {
1031
+ emit(unitAnimationEvent, {
1032
+ unitId,
1033
+ state,
1034
+ timestamp: Date.now()
1035
+ });
1036
+ }
1037
+ optionsRef.current.onUnitAnimation?.(unitId, state);
1038
+ },
1039
+ [unitAnimationEvent, emit]
1040
+ );
1041
+ const handleCameraChange = useCallback(
1042
+ (position) => {
1043
+ if (cameraChangeEvent) {
1044
+ emit(cameraChangeEvent, {
1045
+ position,
1046
+ timestamp: Date.now()
1047
+ });
1048
+ }
1049
+ },
1050
+ [cameraChangeEvent, emit]
1051
+ );
1052
+ return {
1053
+ handleTileClick,
1054
+ handleUnitClick,
1055
+ handleFeatureClick,
1056
+ handleCanvasClick,
1057
+ handleTileHover,
1058
+ handleUnitAnimation,
1059
+ handleCameraChange
1060
+ };
1061
+ }
1062
+ function detectAssetRoot3(modelUrl) {
1063
+ const idx = modelUrl.indexOf("/3d/");
1064
+ if (idx !== -1) {
1065
+ return modelUrl.substring(0, idx + 4);
1066
+ }
1067
+ return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
1068
+ }
1069
+ function useGLTFModel2(url, resourceBasePath) {
1070
+ const [state, setState] = useState({
1071
+ model: null,
1072
+ isLoading: false,
1073
+ error: null
1074
+ });
1075
+ useEffect(() => {
1076
+ if (!url) {
1077
+ setState({ model: null, isLoading: false, error: null });
1078
+ return;
1079
+ }
1080
+ console.log("[ModelLoader] Loading:", url);
1081
+ setState((prev) => ({ ...prev, isLoading: true, error: null }));
1082
+ const assetRoot = resourceBasePath || detectAssetRoot3(url);
1083
+ const loader = new GLTFLoader$1();
1084
+ loader.setResourcePath(assetRoot);
1085
+ loader.load(
1086
+ url,
1087
+ (gltf) => {
1088
+ console.log("[ModelLoader] Loaded:", url);
1089
+ setState({
1090
+ model: gltf.scene,
1091
+ isLoading: false,
1092
+ error: null
1093
+ });
1094
+ },
1095
+ void 0,
1096
+ (err) => {
1097
+ const errorMsg = err instanceof Error ? err.message : String(err);
1098
+ console.warn("[ModelLoader] Failed:", url, errorMsg);
1099
+ setState({
1100
+ model: null,
1101
+ isLoading: false,
1102
+ error: err instanceof Error ? err : new Error(String(err))
1103
+ });
1104
+ }
1105
+ );
1106
+ }, [url, resourceBasePath]);
1107
+ return state;
1108
+ }
1109
+ function ModelLoader({
1110
+ url,
1111
+ position = [0, 0, 0],
1112
+ scale = 1,
1113
+ rotation = [0, 0, 0],
1114
+ isSelected = false,
1115
+ isHovered = false,
1116
+ onClick,
1117
+ onHover,
1118
+ fallbackGeometry = "box",
1119
+ castShadow = true,
1120
+ receiveShadow = true,
1121
+ resourceBasePath
1122
+ }) {
1123
+ const { model: loadedModel, isLoading, error } = useGLTFModel2(url, resourceBasePath);
1124
+ const model = useMemo(() => {
1125
+ if (!loadedModel) return null;
1126
+ const cloned = loadedModel.clone();
1127
+ cloned.traverse((child) => {
1128
+ if (child instanceof THREE.Mesh) {
1129
+ child.castShadow = castShadow;
1130
+ child.receiveShadow = receiveShadow;
1131
+ }
1132
+ });
1133
+ return cloned;
1134
+ }, [loadedModel, castShadow, receiveShadow]);
1135
+ const scaleArray = useMemo(() => {
1136
+ if (typeof scale === "number") {
1137
+ return [scale, scale, scale];
1138
+ }
1139
+ return scale;
1140
+ }, [scale]);
1141
+ const rotationRad = useMemo(() => {
1142
+ return [
1143
+ rotation[0] * Math.PI / 180,
1144
+ rotation[1] * Math.PI / 180,
1145
+ rotation[2] * Math.PI / 180
1146
+ ];
1147
+ }, [rotation]);
1148
+ if (isLoading) {
1149
+ return /* @__PURE__ */ jsx("group", { position, children: /* @__PURE__ */ jsxs("mesh", { rotation: [Math.PI / 2, 0, 0], children: [
1150
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.3, 0.35, 16] }),
1151
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#4a90d9", transparent: true, opacity: 0.8 })
1152
+ ] }) });
1153
+ }
1154
+ if (error || !model) {
1155
+ if (fallbackGeometry === "none") {
1156
+ return /* @__PURE__ */ jsx("group", { position });
1157
+ }
1158
+ const fallbackProps = {
1159
+ onClick,
1160
+ onPointerOver: () => onHover?.(true),
1161
+ onPointerOut: () => onHover?.(false)
1162
+ };
1163
+ return /* @__PURE__ */ jsxs("group", { position, children: [
1164
+ (isSelected || isHovered) && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
1165
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.6, 0.7, 32] }),
1166
+ /* @__PURE__ */ jsx(
1167
+ "meshBasicMaterial",
1168
+ {
1169
+ color: isSelected ? 16755200 : 16777215,
1170
+ transparent: true,
1171
+ opacity: 0.5
1172
+ }
1173
+ )
1174
+ ] }),
1175
+ fallbackGeometry === "box" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
1176
+ /* @__PURE__ */ jsx("boxGeometry", { args: [0.8, 0.8, 0.8] }),
1177
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
1178
+ ] }),
1179
+ fallbackGeometry === "sphere" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
1180
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [0.4, 16, 16] }),
1181
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
1182
+ ] }),
1183
+ fallbackGeometry === "cylinder" && /* @__PURE__ */ jsxs("mesh", { ...fallbackProps, position: [0, 0.5, 0], children: [
1184
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.3, 0.3, 0.8, 16] }),
1185
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: error ? 16729156 : 8947848 })
1186
+ ] })
1187
+ ] });
1188
+ }
1189
+ return /* @__PURE__ */ jsxs(
1190
+ "group",
1191
+ {
1192
+ position,
1193
+ rotation: rotationRad,
1194
+ onClick,
1195
+ onPointerOver: () => onHover?.(true),
1196
+ onPointerOut: () => onHover?.(false),
1197
+ children: [
1198
+ (isSelected || isHovered) && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.02, 0], rotation: [-Math.PI / 2, 0, 0], children: [
1199
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.6, 0.7, 32] }),
1200
+ /* @__PURE__ */ jsx(
1201
+ "meshBasicMaterial",
1202
+ {
1203
+ color: isSelected ? 16755200 : 16777215,
1204
+ transparent: true,
1205
+ opacity: 0.5
1206
+ }
1207
+ )
1208
+ ] }),
1209
+ /* @__PURE__ */ jsx("primitive", { object: model, scale: scaleArray })
1210
+ ]
1211
+ }
1212
+ );
1213
+ }
1214
+ function Lighting3D({
1215
+ ambientIntensity = 0.6,
1216
+ ambientColor = "#ffffff",
1217
+ directionalIntensity = 0.8,
1218
+ directionalColor = "#ffffff",
1219
+ directionalPosition = [10, 20, 10],
1220
+ shadows = true,
1221
+ shadowMapSize = 2048,
1222
+ shadowCameraSize = 20,
1223
+ showHelpers = false
1224
+ }) {
1225
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1226
+ /* @__PURE__ */ jsx("ambientLight", { intensity: ambientIntensity, color: ambientColor }),
1227
+ /* @__PURE__ */ jsx(
1228
+ "directionalLight",
1229
+ {
1230
+ position: directionalPosition,
1231
+ intensity: directionalIntensity,
1232
+ color: directionalColor,
1233
+ castShadow: shadows,
1234
+ "shadow-mapSize": [shadowMapSize, shadowMapSize],
1235
+ "shadow-camera-left": -shadowCameraSize,
1236
+ "shadow-camera-right": shadowCameraSize,
1237
+ "shadow-camera-top": shadowCameraSize,
1238
+ "shadow-camera-bottom": -shadowCameraSize,
1239
+ "shadow-camera-near": 0.1,
1240
+ "shadow-camera-far": 100,
1241
+ "shadow-bias": -1e-3
1242
+ }
1243
+ ),
1244
+ /* @__PURE__ */ jsx(
1245
+ "hemisphereLight",
1246
+ {
1247
+ intensity: 0.3,
1248
+ color: "#87ceeb",
1249
+ groundColor: "#362d1d"
1250
+ }
1251
+ ),
1252
+ showHelpers && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
1253
+ "directionalLightHelper",
1254
+ {
1255
+ args: [
1256
+ new THREE.DirectionalLight(directionalColor, directionalIntensity),
1257
+ 5
1258
+ ]
1259
+ }
1260
+ ) })
1261
+ ] });
1262
+ }
1263
+ function PhysicsObject3D({
1264
+ entityId,
1265
+ modelUrl,
1266
+ initialPosition = [0, 0, 0],
1267
+ initialVelocity = [0, 0, 0],
1268
+ mass = 1,
1269
+ gravity = 9.8,
1270
+ groundY = 0,
1271
+ scale = 1,
1272
+ onPhysicsUpdate,
1273
+ onGroundHit,
1274
+ onCollision
1275
+ }) {
1276
+ const groupRef = useRef(null);
1277
+ const physicsStateRef = useRef({
1278
+ id: entityId,
1279
+ x: initialPosition[0],
1280
+ y: initialPosition[1],
1281
+ z: initialPosition[2],
1282
+ vx: initialVelocity[0],
1283
+ vy: initialVelocity[1],
1284
+ vz: initialVelocity[2],
1285
+ rx: 0,
1286
+ ry: 0,
1287
+ rz: 0,
1288
+ isGrounded: false,
1289
+ gravity,
1290
+ friction: 0.8,
1291
+ mass,
1292
+ state: "Active"
1293
+ });
1294
+ const groundHitRef = useRef(false);
1295
+ useEffect(() => {
1296
+ if (groupRef.current) {
1297
+ groupRef.current.position.set(
1298
+ initialPosition[0],
1299
+ initialPosition[1],
1300
+ initialPosition[2]
1301
+ );
1302
+ }
1303
+ }, []);
1304
+ useFrame((state, delta) => {
1305
+ const physics = physicsStateRef.current;
1306
+ if (physics.state !== "Active") return;
1307
+ const dt = Math.min(delta, 0.1);
1308
+ if (!physics.isGrounded) {
1309
+ physics.vy -= physics.gravity * dt;
1310
+ }
1311
+ physics.x += physics.vx * dt;
1312
+ physics.y += physics.vy * dt;
1313
+ physics.z += physics.vz * dt;
1314
+ const airResistance = Math.pow(0.99, dt * 60);
1315
+ physics.vx *= airResistance;
1316
+ physics.vz *= airResistance;
1317
+ if (physics.y <= groundY) {
1318
+ physics.y = groundY;
1319
+ if (!physics.isGrounded) {
1320
+ physics.isGrounded = true;
1321
+ groundHitRef.current = true;
1322
+ physics.vx *= physics.friction;
1323
+ physics.vz *= physics.friction;
1324
+ onGroundHit?.();
1325
+ }
1326
+ physics.vy = 0;
1327
+ } else {
1328
+ physics.isGrounded = false;
1329
+ }
1330
+ if (groupRef.current) {
1331
+ groupRef.current.position.set(physics.x, physics.y, physics.z);
1332
+ if (!physics.isGrounded) {
1333
+ physics.rx += physics.vz * dt * 0.5;
1334
+ physics.rz -= physics.vx * dt * 0.5;
1335
+ groupRef.current.rotation.set(physics.rx, physics.ry, physics.rz);
1336
+ }
1337
+ }
1338
+ onPhysicsUpdate?.({ ...physics });
1339
+ });
1340
+ const scaleArray = typeof scale === "number" ? [scale, scale, scale] : scale;
1341
+ return /* @__PURE__ */ jsx("group", { ref: groupRef, scale: scaleArray, children: /* @__PURE__ */ jsx(
1342
+ ModelLoader,
1343
+ {
1344
+ url: modelUrl,
1345
+ fallbackGeometry: "box"
1346
+ }
1347
+ ) });
1348
+ }
1349
+ function usePhysics3DController(entityId) {
1350
+ const applyForce = (fx, fy, fz) => {
1351
+ console.log(`Apply force to ${entityId}:`, { fx, fy, fz });
1352
+ };
1353
+ const setVelocity = (vx, vy, vz) => {
1354
+ console.log(`Set velocity for ${entityId}:`, { vx, vy, vz });
1355
+ };
1356
+ const setPosition = (x, y, z) => {
1357
+ console.log(`Set position for ${entityId}:`, { x, y, z });
1358
+ };
1359
+ const jump = (force = 10) => {
1360
+ applyForce(0, force, 0);
1361
+ };
1362
+ return {
1363
+ applyForce,
1364
+ setVelocity,
1365
+ setPosition,
1366
+ jump
1367
+ };
1368
+ }
1369
+ function Scene3D({ background = "#1a1a2e", fog, children }) {
1370
+ const { scene } = useThree();
1371
+ const initializedRef = useRef(false);
1372
+ useEffect(() => {
1373
+ if (initializedRef.current) return;
1374
+ initializedRef.current = true;
1375
+ if (background.startsWith("#") || background.startsWith("rgb")) {
1376
+ scene.background = new THREE.Color(background);
1377
+ } else {
1378
+ const loader = new THREE.TextureLoader();
1379
+ loader.load(background, (texture) => {
1380
+ scene.background = texture;
1381
+ });
1382
+ }
1383
+ if (fog) {
1384
+ scene.fog = new THREE.Fog(fog.color, fog.near, fog.far);
1385
+ }
1386
+ return () => {
1387
+ scene.background = null;
1388
+ scene.fog = null;
1389
+ };
1390
+ }, [scene, background, fog]);
1391
+ return /* @__PURE__ */ jsx(Fragment, { children });
1392
+ }
1393
+ var DEFAULT_TERRAIN_COLORS = {
1394
+ grass: "#44aa44",
1395
+ dirt: "#8b7355",
1396
+ sand: "#ddcc88",
1397
+ water: "#4488cc",
1398
+ rock: "#888888",
1399
+ snow: "#eeeeee",
1400
+ forest: "#228b22",
1401
+ desert: "#d4a574",
1402
+ mountain: "#696969",
1403
+ swamp: "#556b2f"
1404
+ };
1405
+ function TileRenderer({
1406
+ tiles,
1407
+ cellSize = 1,
1408
+ offsetX = 0,
1409
+ offsetZ = 0,
1410
+ useInstancing = true,
1411
+ terrainColors = DEFAULT_TERRAIN_COLORS,
1412
+ onTileClick,
1413
+ onTileHover,
1414
+ selectedTileIds = [],
1415
+ validMoves = [],
1416
+ attackTargets = []
1417
+ }) {
1418
+ const meshRef = useRef(null);
1419
+ const geometry = useMemo(() => {
1420
+ return new THREE.BoxGeometry(cellSize * 0.95, 0.2, cellSize * 0.95);
1421
+ }, [cellSize]);
1422
+ const material = useMemo(() => {
1423
+ return new THREE.MeshStandardMaterial({
1424
+ roughness: 0.8,
1425
+ metalness: 0.1
1426
+ });
1427
+ }, []);
1428
+ const { positions, colors, tileMap } = useMemo(() => {
1429
+ const pos = [];
1430
+ const cols = [];
1431
+ const map = /* @__PURE__ */ new Map();
1432
+ tiles.forEach((tile) => {
1433
+ const x = (tile.x - offsetX) * cellSize;
1434
+ const z = ((tile.z ?? tile.y ?? 0) - offsetZ) * cellSize;
1435
+ const y = (tile.elevation ?? 0) * 0.1;
1436
+ pos.push(new THREE.Vector3(x, y, z));
1437
+ const colorHex = terrainColors[tile.type || ""] || terrainColors[tile.terrain || ""] || "#808080";
1438
+ const color = new THREE.Color(colorHex);
1439
+ const isValidMove = validMoves.some(
1440
+ (m) => m.x === tile.x && m.z === (tile.z ?? tile.y ?? 0)
1441
+ );
1442
+ const isAttackTarget = attackTargets.some(
1443
+ (m) => m.x === tile.x && m.z === (tile.z ?? tile.y ?? 0)
1444
+ );
1445
+ const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
1446
+ if (isSelected) {
1447
+ color.addScalar(0.3);
1448
+ } else if (isAttackTarget) {
1449
+ color.setHex(16729156);
1450
+ } else if (isValidMove) {
1451
+ color.setHex(4521796);
1452
+ }
1453
+ cols.push(color);
1454
+ map.set(`${tile.x},${tile.z ?? tile.y ?? 0}`, tile);
1455
+ });
1456
+ return { positions: pos, colors: cols, tileMap: map };
1457
+ }, [tiles, cellSize, offsetX, offsetZ, terrainColors, selectedTileIds, validMoves, attackTargets]);
1458
+ useEffect(() => {
1459
+ if (!meshRef.current || !useInstancing) return;
1460
+ const mesh = meshRef.current;
1461
+ mesh.count = positions.length;
1462
+ const dummy = new THREE.Object3D();
1463
+ positions.forEach((pos, i) => {
1464
+ dummy.position.copy(pos);
1465
+ dummy.updateMatrix();
1466
+ mesh.setMatrixAt(i, dummy.matrix);
1467
+ if (mesh.setColorAt) {
1468
+ mesh.setColorAt(i, colors[i]);
1469
+ }
1470
+ });
1471
+ mesh.instanceMatrix.needsUpdate = true;
1472
+ if (mesh.instanceColor) {
1473
+ mesh.instanceColor.needsUpdate = true;
1474
+ }
1475
+ }, [positions, colors, useInstancing]);
1476
+ const handlePointerMove = (e) => {
1477
+ if (!onTileHover) return;
1478
+ const instanceId = e.instanceId;
1479
+ if (instanceId !== void 0) {
1480
+ const pos = positions[instanceId];
1481
+ if (pos) {
1482
+ const gridX = Math.round(pos.x / cellSize + offsetX);
1483
+ const gridZ = Math.round(pos.z / cellSize + offsetZ);
1484
+ const tile = tileMap.get(`${gridX},${gridZ}`);
1485
+ if (tile) {
1486
+ onTileHover(tile);
1487
+ }
1488
+ }
1489
+ }
1490
+ };
1491
+ const handleClick = (e) => {
1492
+ if (!onTileClick) return;
1493
+ const instanceId = e.instanceId;
1494
+ if (instanceId !== void 0) {
1495
+ const pos = positions[instanceId];
1496
+ if (pos) {
1497
+ const gridX = Math.round(pos.x / cellSize + offsetX);
1498
+ const gridZ = Math.round(pos.z / cellSize + offsetZ);
1499
+ const tile = tileMap.get(`${gridX},${gridZ}`);
1500
+ if (tile) {
1501
+ onTileClick(tile);
1502
+ }
1503
+ }
1504
+ }
1505
+ };
1506
+ const renderIndividualTiles = () => {
1507
+ return tiles.map((tile) => {
1508
+ const x = (tile.x - offsetX) * cellSize;
1509
+ const z = ((tile.z ?? tile.y ?? 0) - offsetZ) * cellSize;
1510
+ const y = (tile.elevation ?? 0) * 0.1;
1511
+ const colorHex = terrainColors[tile.type || ""] || terrainColors[tile.terrain || ""] || "#808080";
1512
+ const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
1513
+ const isValidMove = validMoves.some(
1514
+ (m) => m.x === tile.x && m.z === (tile.z ?? tile.y ?? 0)
1515
+ );
1516
+ const isAttackTarget = attackTargets.some(
1517
+ (m) => m.x === tile.x && m.z === (tile.z ?? tile.y ?? 0)
1518
+ );
1519
+ let emissive = "#000000";
1520
+ if (isSelected) emissive = "#444444";
1521
+ else if (isAttackTarget) emissive = "#440000";
1522
+ else if (isValidMove) emissive = "#004400";
1523
+ return /* @__PURE__ */ jsxs(
1524
+ "mesh",
1525
+ {
1526
+ position: [x, y, z],
1527
+ userData: { type: "tile", tileId: tile.id, gridX: tile.x, gridZ: tile.z ?? tile.y },
1528
+ onClick: () => onTileClick?.(tile),
1529
+ onPointerEnter: () => onTileHover?.(tile),
1530
+ onPointerLeave: () => onTileHover?.(null),
1531
+ children: [
1532
+ /* @__PURE__ */ jsx("boxGeometry", { args: [cellSize * 0.95, 0.2, cellSize * 0.95] }),
1533
+ /* @__PURE__ */ jsx(
1534
+ "meshStandardMaterial",
1535
+ {
1536
+ color: colorHex,
1537
+ emissive,
1538
+ roughness: 0.8,
1539
+ metalness: 0.1
1540
+ }
1541
+ )
1542
+ ]
1543
+ },
1544
+ tile.id ?? `tile-${tile.x}-${tile.y}`
1545
+ );
1546
+ });
1547
+ };
1548
+ if (useInstancing && tiles.length > 0) {
1549
+ return /* @__PURE__ */ jsx(
1550
+ "instancedMesh",
1551
+ {
1552
+ ref: meshRef,
1553
+ args: [geometry, material, tiles.length],
1554
+ onPointerMove: handlePointerMove,
1555
+ onClick: handleClick
1556
+ }
1557
+ );
1558
+ }
1559
+ return /* @__PURE__ */ jsx("group", { children: renderIndividualTiles() });
1560
+ }
1561
+ function UnitVisual({ unit, position, isSelected, onClick }) {
1562
+ const groupRef = useRef(null);
1563
+ const [animationState, setAnimationState] = useState("idle");
1564
+ const [isHovered, setIsHovered] = useState(false);
1565
+ const teamColor = useMemo(() => {
1566
+ if (unit.faction === "player" || unit.team === "player") return 4491519;
1567
+ if (unit.faction === "enemy" || unit.team === "enemy") return 16729156;
1568
+ if (unit.faction === "neutral" || unit.team === "neutral") return 16777028;
1569
+ return 8947848;
1570
+ }, [unit.faction, unit.team]);
1571
+ useFrame((state) => {
1572
+ if (groupRef.current && animationState === "idle") {
1573
+ const y = position[1] + Math.sin(state.clock.elapsedTime * 2 + position[0]) * 0.05;
1574
+ groupRef.current.position.y = y;
1575
+ }
1576
+ });
1577
+ const healthPercent = useMemo(() => {
1578
+ if (unit.health === void 0 || unit.maxHealth === void 0) return 1;
1579
+ return Math.max(0, Math.min(1, unit.health / unit.maxHealth));
1580
+ }, [unit.health, unit.maxHealth]);
1581
+ const healthColor = useMemo(() => {
1582
+ if (healthPercent > 0.5) return "#44aa44";
1583
+ if (healthPercent > 0.25) return "#aaaa44";
1584
+ return "#ff4444";
1585
+ }, [healthPercent]);
1586
+ return /* @__PURE__ */ jsxs(
1587
+ "group",
1588
+ {
1589
+ ref: groupRef,
1590
+ position,
1591
+ onClick,
1592
+ onPointerEnter: () => setIsHovered(true),
1593
+ onPointerLeave: () => setIsHovered(false),
1594
+ userData: { type: "unit", unitId: unit.id },
1595
+ children: [
1596
+ isSelected && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.05, 0], rotation: [-Math.PI / 2, 0, 0], children: [
1597
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
1598
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#ffff00", transparent: true, opacity: 0.8 })
1599
+ ] }),
1600
+ isHovered && !isSelected && /* @__PURE__ */ jsxs("mesh", { position: [0, 0.05, 0], rotation: [-Math.PI / 2, 0, 0], children: [
1601
+ /* @__PURE__ */ jsx("ringGeometry", { args: [0.4, 0.5, 32] }),
1602
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#ffffff", transparent: true, opacity: 0.5 })
1603
+ ] }),
1604
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 0.1, 0], children: [
1605
+ /* @__PURE__ */ jsx("cylinderGeometry", { args: [0.25, 0.25, 0.1, 8] }),
1606
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: teamColor })
1607
+ ] }),
1608
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 0.5, 0], children: [
1609
+ /* @__PURE__ */ jsx("capsuleGeometry", { args: [0.15, 0.5, 4, 8] }),
1610
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: teamColor })
1611
+ ] }),
1612
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 0.9, 0], children: [
1613
+ /* @__PURE__ */ jsx("sphereGeometry", { args: [0.12, 8, 8] }),
1614
+ /* @__PURE__ */ jsx("meshStandardMaterial", { color: teamColor })
1615
+ ] }),
1616
+ /* @__PURE__ */ jsxs("mesh", { position: [0, 1.3, 0], children: [
1617
+ /* @__PURE__ */ jsx("planeGeometry", { args: [0.5, 0.06] }),
1618
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#333333" })
1619
+ ] }),
1620
+ /* @__PURE__ */ jsxs("mesh", { position: [-0.25 + 0.25 * healthPercent, 1.3, 0.01], children: [
1621
+ /* @__PURE__ */ jsx("planeGeometry", { args: [0.5 * healthPercent, 0.04] }),
1622
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: healthColor })
1623
+ ] }),
1624
+ unit.name && /* @__PURE__ */ jsxs("mesh", { position: [0, 1.5, 0], children: [
1625
+ /* @__PURE__ */ jsx("planeGeometry", { args: [0.4, 0.1] }),
1626
+ /* @__PURE__ */ jsx("meshBasicMaterial", { color: "#000000", transparent: true, opacity: 0.5 })
1627
+ ] })
1628
+ ]
1629
+ }
1630
+ );
1631
+ }
1632
+ function UnitRenderer({
1633
+ units,
1634
+ cellSize = 1,
1635
+ offsetX = 0,
1636
+ offsetZ = 0,
1637
+ selectedUnitId,
1638
+ onUnitClick,
1639
+ onAnimationStateChange,
1640
+ animationSpeed = 1
1641
+ }) {
1642
+ const handleUnitClick = React8.useCallback(
1643
+ (unit) => {
1644
+ onUnitClick?.(unit);
1645
+ },
1646
+ [onUnitClick]
1647
+ );
1648
+ return /* @__PURE__ */ jsx("group", { children: units.map((unit) => {
1649
+ const unitX = unit.x ?? unit.position?.x ?? 0;
1650
+ const unitY = unit.z ?? unit.y ?? unit.position?.y ?? 0;
1651
+ const x = (unitX - offsetX) * cellSize;
1652
+ const z = (unitY - offsetZ) * cellSize;
1653
+ const y = (unit.elevation ?? 0) * 0.1 + 0.5;
1654
+ return /* @__PURE__ */ jsx(
1655
+ UnitVisual,
1656
+ {
1657
+ unit,
1658
+ position: [x, y, z],
1659
+ isSelected: selectedUnitId === unit.id,
1660
+ onClick: () => handleUnitClick(unit)
1661
+ },
1662
+ unit.id
1663
+ );
1664
+ }) });
1665
+ }
1666
+
1667
+ export { AssetLoader, Camera3D, Canvas3DErrorBoundary, Canvas3DLoadingState, FeatureRenderer, FeatureRenderer3D, Lighting3D, ModelLoader, PhysicsObject3D, Scene3D, TileRenderer, UnitRenderer, assetLoader, preloadFeatures, useAssetLoader, useGameCanvas3DEvents, usePhysics3DController };