@nice2dev/ui-graphics 1.3.15 → 1.3.16

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 (294) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/animation/AnimatedPerson.js +470 -143
  3. package/dist/cjs/animation/AnimationEditor.js +289 -101
  4. package/dist/cjs/animation/Audience.js +83 -61
  5. package/dist/cjs/animation/BodyRenderer.js +69 -28
  6. package/dist/cjs/animation/animationHelper.js +281 -288
  7. package/dist/cjs/animation/characterTypes.js +200 -203
  8. package/dist/cjs/animation/choreoDSL.js +205 -219
  9. package/dist/cjs/animation/choreography.js +4 -32
  10. package/dist/cjs/animation/karaokeIntegration.js +68 -77
  11. package/dist/cjs/animation/lottieExport.js +108 -114
  12. package/dist/cjs/animation/motionPath.js +225 -248
  13. package/dist/cjs/animation/physics.js +227 -254
  14. package/dist/cjs/animation/rig/RigPlayer.js +53 -56
  15. package/dist/cjs/animation/rig/RiggedBody.js +71 -26
  16. package/dist/cjs/animation/rig/choreoRigBridge.js +72 -77
  17. package/dist/cjs/animation/rig/ik.js +13 -18
  18. package/dist/cjs/animation/rig/poseOps.js +34 -41
  19. package/dist/cjs/animation/rig/presets.js +64 -72
  20. package/dist/cjs/animation/rig/rigMath.js +25 -32
  21. package/dist/cjs/animation/rig/rigTypes.js +59 -63
  22. package/dist/cjs/animation/shapes/arms.js +31 -13
  23. package/dist/cjs/animation/shapes/eyes.js +129 -47
  24. package/dist/cjs/animation/shapes/hair.js +72 -45
  25. package/dist/cjs/animation/shapes/heads.js +131 -57
  26. package/dist/cjs/animation/shapes/headwear.js +47 -38
  27. package/dist/cjs/animation/shapes/legs.js +31 -13
  28. package/dist/cjs/animation/shapes/mouths.js +120 -44
  29. package/dist/cjs/animation/shapes/noses.js +80 -25
  30. package/dist/cjs/animation/shapes/outfits.js +101 -39
  31. package/dist/cjs/animation/shapes/torsos.js +15 -11
  32. package/dist/cjs/animation/spineExport.js +103 -121
  33. package/dist/cjs/core/LocalUI.js +108 -43
  34. package/dist/cjs/core/NiceBrushEngine.js +758 -552
  35. package/dist/cjs/core/collaboration.js +249 -251
  36. package/dist/cjs/core/colorBlindness.js +100 -115
  37. package/dist/cjs/core/dragDrop.js +155 -158
  38. package/dist/cjs/core/editorAsk.js +51 -41
  39. package/dist/cjs/core/fixes.js +140 -171
  40. package/dist/cjs/core/gridGuides.js +166 -201
  41. package/dist/cjs/core/historyVisual.js +156 -135
  42. package/dist/cjs/core/i18n.js +13 -14
  43. package/dist/cjs/core/integrations.js +238 -249
  44. package/dist/cjs/core/minimap.js +149 -151
  45. package/dist/cjs/core/plugins.js +98 -113
  46. package/dist/cjs/core/rtl.js +71 -83
  47. package/dist/cjs/core/shortcuts.js +196 -225
  48. package/dist/cjs/core/theme.js +142 -149
  49. package/dist/cjs/core/yjsCollaboration.js +232 -293
  50. package/dist/cjs/design/design-tools.js +12 -22
  51. package/dist/cjs/font/NiceFontEditor.js +877 -316
  52. package/dist/cjs/font/fontFormatUtils.js +388 -448
  53. package/dist/cjs/game/GameAsset2dEditor.js +1201 -392
  54. package/dist/cjs/game/GameAsset2dEditor.module.css.js +146 -5
  55. package/dist/cjs/game/gameAssetTypes.js +7 -16
  56. package/dist/cjs/game/gameAssetUtils.js +390 -413
  57. package/dist/cjs/game/useGameAssetEditor.js +820 -763
  58. package/dist/cjs/index.js +81 -84
  59. package/dist/cjs/nice2dev-ui-graphics.css +1 -1
  60. package/dist/cjs/node_modules/lib0/array.js +8 -70
  61. package/dist/cjs/node_modules/lib0/binary.js +3 -20
  62. package/dist/cjs/node_modules/lib0/broadcastchannel.js +24 -86
  63. package/dist/cjs/node_modules/lib0/buffer.js +15 -82
  64. package/dist/cjs/node_modules/lib0/conditions.js +3 -16
  65. package/dist/cjs/node_modules/lib0/decoding.js +108 -287
  66. package/dist/cjs/node_modules/lib0/dom.js +14 -44
  67. package/dist/cjs/node_modules/lib0/encoding.js +68 -418
  68. package/dist/cjs/node_modules/lib0/environment.js +26 -92
  69. package/dist/cjs/node_modules/lib0/error.js +5 -29
  70. package/dist/cjs/node_modules/lib0/function.js +27 -66
  71. package/dist/cjs/node_modules/lib0/iterator.js +8 -33
  72. package/dist/cjs/node_modules/lib0/logging.common.js +12 -22
  73. package/dist/cjs/node_modules/lib0/logging.js +32 -71
  74. package/dist/cjs/node_modules/lib0/map.js +16 -86
  75. package/dist/cjs/node_modules/lib0/math.js +3 -32
  76. package/dist/cjs/node_modules/lib0/number.js +4 -15
  77. package/dist/cjs/node_modules/lib0/object.js +14 -88
  78. package/dist/cjs/node_modules/lib0/observable.js +38 -78
  79. package/dist/cjs/node_modules/lib0/pair.js +3 -20
  80. package/dist/cjs/node_modules/lib0/prng.js +8 -77
  81. package/dist/cjs/node_modules/lib0/promise.js +6 -30
  82. package/dist/cjs/node_modules/lib0/random.js +8 -23
  83. package/dist/cjs/node_modules/lib0/schema.js +313 -687
  84. package/dist/cjs/node_modules/lib0/set.js +3 -10
  85. package/dist/cjs/node_modules/lib0/storage.js +20 -55
  86. package/dist/cjs/node_modules/lib0/string.js +17 -72
  87. package/dist/cjs/node_modules/lib0/symbol.js +2 -12
  88. package/dist/cjs/node_modules/lib0/time.js +2 -15
  89. package/dist/cjs/node_modules/lib0/trait/equality.js +3 -28
  90. package/dist/cjs/node_modules/lib0/url.js +4 -18
  91. package/dist/cjs/node_modules/lib0/webcrypto.js +2 -5
  92. package/dist/cjs/node_modules/y-protocols/auth.js +5 -19
  93. package/dist/cjs/node_modules/y-protocols/awareness.js +53 -116
  94. package/dist/cjs/node_modules/y-protocols/sync.js +16 -103
  95. package/dist/cjs/node_modules/y-websocket/src/y-websocket.js +77 -219
  96. package/dist/cjs/node_modules/yjs/dist/yjs.js +2128 -4868
  97. package/dist/cjs/photo/FilterThumb.js +37 -25
  98. package/dist/cjs/photo/NiceAITools.js +679 -467
  99. package/dist/cjs/photo/PhotoEditor.js +34 -20
  100. package/dist/cjs/photo/PhotoEditor.module.css.js +296 -5
  101. package/dist/cjs/photo/PhotoEditorCanvas.js +250 -91
  102. package/dist/cjs/photo/PhotoEditorLeftPanel.js +1086 -224
  103. package/dist/cjs/photo/PhotoEditorToolbar.js +135 -19
  104. package/dist/cjs/photo/photoEditorActions.js +89 -72
  105. package/dist/cjs/photo/photoEditorTypes.js +29 -32
  106. package/dist/cjs/photo/photoFilters.js +959 -985
  107. package/dist/cjs/photo/photoOverlays.js +899 -945
  108. package/dist/cjs/photo/photoSelection.js +427 -499
  109. package/dist/cjs/photo/usePhotoEditor.js +739 -741
  110. package/dist/cjs/pixel/HSVPicker.js +191 -175
  111. package/dist/cjs/pixel/PixelEditor.js +159 -48
  112. package/dist/cjs/pixel/PixelEditor.module.css.js +209 -5
  113. package/dist/cjs/pixel/PixelEditorCanvas.js +29 -16
  114. package/dist/cjs/pixel/PixelEditorMenuBar.js +160 -162
  115. package/dist/cjs/pixel/PixelEditorRightPanel.js +377 -45
  116. package/dist/cjs/pixel/PixelEditorStatusBar.js +47 -20
  117. package/dist/cjs/pixel/PixelEditorTimeline.js +106 -23
  118. package/dist/cjs/pixel/PixelEditorToolbar.js +99 -21
  119. package/dist/cjs/pixel/SpriteGeneratorPanel.js +483 -303
  120. package/dist/cjs/pixel/animalGeneratorPresets.js +776 -601
  121. package/dist/cjs/pixel/asepriteFormat.js +511 -560
  122. package/dist/cjs/pixel/buildingGeneratorPresets.js +693 -520
  123. package/dist/cjs/pixel/characterGeneratorPresets.js +644 -544
  124. package/dist/cjs/pixel/pixel-pro.js +52 -63
  125. package/dist/cjs/pixel/pixelEditorExports.js +388 -428
  126. package/dist/cjs/pixel/pixelEditorTypes.js +91 -108
  127. package/dist/cjs/pixel/pixelEditorUtils.js +519 -561
  128. package/dist/cjs/pixel/spriteGeneratorCore.js +206 -257
  129. package/dist/cjs/pixel/usePixelEditor.js +1321 -1343
  130. package/dist/cjs/texture/Nice3DTexturePainter.js +707 -440
  131. package/dist/cjs/ui/NiceUIDesigner.js +954 -527
  132. package/dist/cjs/vector/NiceSvgToCode.js +586 -446
  133. package/dist/cjs/vector/VectorEditor.js +290 -117
  134. package/dist/cjs/vector/VectorEditor.module.css.js +86 -5
  135. package/dist/cjs/vector/VectorEditorMenuBar.js +333 -275
  136. package/dist/cjs/vector/VectorEditorRightPanel.js +1094 -371
  137. package/dist/cjs/vector/VectorEditorShapeRenderer.js +198 -60
  138. package/dist/cjs/vector/VectorEditorStatusBar.js +39 -13
  139. package/dist/cjs/vector/useVectorEditor.js +848 -889
  140. package/dist/cjs/vector/vectorAnimation.js +110 -137
  141. package/dist/cjs/vector/vectorBooleanOps.js +398 -485
  142. package/dist/cjs/vector/vectorEditorExport.js +201 -203
  143. package/dist/cjs/vector/vectorEditorImport.js +173 -189
  144. package/dist/cjs/vector/vectorEditorTypes.js +42 -49
  145. package/dist/cjs/vector/vectorGradients.js +151 -174
  146. package/dist/cjs/vector/vectorIconExport.js +52 -59
  147. package/dist/cjs/vector/vectorIconImport.js +169 -219
  148. package/dist/esm/animation/AnimatedPerson.js +470 -141
  149. package/dist/esm/animation/AnimationEditor.js +290 -100
  150. package/dist/esm/animation/Audience.js +83 -59
  151. package/dist/esm/animation/BodyRenderer.js +71 -25
  152. package/dist/esm/animation/animationHelper.js +284 -287
  153. package/dist/esm/animation/characterTypes.js +204 -202
  154. package/dist/esm/animation/choreoDSL.js +212 -218
  155. package/dist/esm/animation/choreography.js +8 -31
  156. package/dist/esm/animation/karaokeIntegration.js +74 -76
  157. package/dist/esm/animation/lottieExport.js +112 -113
  158. package/dist/esm/animation/motionPath.js +235 -247
  159. package/dist/esm/animation/physics.js +235 -253
  160. package/dist/esm/animation/rig/RigPlayer.js +53 -54
  161. package/dist/esm/animation/rig/RiggedBody.js +71 -24
  162. package/dist/esm/animation/rig/choreoRigBridge.js +74 -76
  163. package/dist/esm/animation/rig/ik.js +14 -17
  164. package/dist/esm/animation/rig/poseOps.js +37 -40
  165. package/dist/esm/animation/rig/presets.js +70 -71
  166. package/dist/esm/animation/rig/rigMath.js +28 -31
  167. package/dist/esm/animation/rig/rigTypes.js +62 -62
  168. package/dist/esm/animation/shapes/arms.js +32 -12
  169. package/dist/esm/animation/shapes/eyes.js +135 -46
  170. package/dist/esm/animation/shapes/hair.js +80 -44
  171. package/dist/esm/animation/shapes/heads.js +140 -56
  172. package/dist/esm/animation/shapes/headwear.js +54 -37
  173. package/dist/esm/animation/shapes/legs.js +32 -12
  174. package/dist/esm/animation/shapes/mouths.js +127 -43
  175. package/dist/esm/animation/shapes/noses.js +87 -24
  176. package/dist/esm/animation/shapes/outfits.js +106 -38
  177. package/dist/esm/animation/shapes/torsos.js +16 -10
  178. package/dist/esm/animation/spineExport.js +106 -120
  179. package/dist/esm/core/LocalUI.js +111 -42
  180. package/dist/esm/core/NiceBrushEngine.js +761 -551
  181. package/dist/esm/core/collaboration.js +255 -250
  182. package/dist/esm/core/colorBlindness.js +106 -114
  183. package/dist/esm/core/dragDrop.js +157 -157
  184. package/dist/esm/core/editorAsk.js +53 -40
  185. package/dist/esm/core/fixes.js +145 -170
  186. package/dist/esm/core/gridGuides.js +178 -200
  187. package/dist/esm/core/historyVisual.js +158 -134
  188. package/dist/esm/core/i18n.js +15 -13
  189. package/dist/esm/core/integrations.js +244 -248
  190. package/dist/esm/core/minimap.js +151 -150
  191. package/dist/esm/core/plugins.js +102 -112
  192. package/dist/esm/core/rtl.js +77 -82
  193. package/dist/esm/core/shortcuts.js +200 -224
  194. package/dist/esm/core/theme.js +150 -148
  195. package/dist/esm/core/yjsCollaboration.js +240 -292
  196. package/dist/esm/design/design-tools.js +13 -21
  197. package/dist/esm/font/NiceFontEditor.js +880 -315
  198. package/dist/esm/font/fontFormatUtils.js +394 -447
  199. package/dist/esm/game/GameAsset2dEditor.js +1202 -391
  200. package/dist/esm/game/GameAsset2dEditor.module.css.js +146 -3
  201. package/dist/esm/game/gameAssetTypes.js +8 -15
  202. package/dist/esm/game/gameAssetUtils.js +408 -412
  203. package/dist/esm/game/useGameAssetEditor.js +821 -762
  204. package/dist/esm/index.js +332 -69
  205. package/dist/esm/nice2dev-ui-graphics.css +1 -1
  206. package/dist/esm/node_modules/lib0/array.js +15 -69
  207. package/dist/esm/node_modules/lib0/binary.js +14 -19
  208. package/dist/esm/node_modules/lib0/broadcastchannel.js +27 -85
  209. package/dist/esm/node_modules/lib0/buffer.js +20 -80
  210. package/dist/esm/node_modules/lib0/conditions.js +4 -15
  211. package/dist/esm/node_modules/lib0/decoding.js +128 -286
  212. package/dist/esm/node_modules/lib0/dom.js +20 -43
  213. package/dist/esm/node_modules/lib0/encoding.js +90 -415
  214. package/dist/esm/node_modules/lib0/environment.js +33 -91
  215. package/dist/esm/node_modules/lib0/error.js +8 -28
  216. package/dist/esm/node_modules/lib0/function.js +31 -65
  217. package/dist/esm/node_modules/lib0/iterator.js +11 -32
  218. package/dist/esm/node_modules/lib0/logging.common.js +22 -21
  219. package/dist/esm/node_modules/lib0/logging.js +44 -70
  220. package/dist/esm/node_modules/lib0/map.js +21 -85
  221. package/dist/esm/node_modules/lib0/math.js +9 -31
  222. package/dist/esm/node_modules/lib0/number.js +7 -14
  223. package/dist/esm/node_modules/lib0/object.js +26 -87
  224. package/dist/esm/node_modules/lib0/observable.js +40 -77
  225. package/dist/esm/node_modules/lib0/pair.js +5 -19
  226. package/dist/esm/node_modules/lib0/prng.js +15 -76
  227. package/dist/esm/node_modules/lib0/promise.js +7 -29
  228. package/dist/esm/node_modules/lib0/random.js +10 -22
  229. package/dist/esm/node_modules/lib0/schema.js +367 -686
  230. package/dist/esm/node_modules/lib0/set.js +4 -9
  231. package/dist/esm/node_modules/lib0/storage.js +23 -54
  232. package/dist/esm/node_modules/lib0/string.js +26 -71
  233. package/dist/esm/node_modules/lib0/symbol.js +3 -11
  234. package/dist/esm/node_modules/lib0/time.js +3 -14
  235. package/dist/esm/node_modules/lib0/trait/equality.js +5 -27
  236. package/dist/esm/node_modules/lib0/url.js +5 -17
  237. package/dist/esm/node_modules/lib0/webcrypto.js +3 -4
  238. package/dist/esm/node_modules/y-protocols/auth.js +7 -18
  239. package/dist/esm/node_modules/y-protocols/awareness.js +58 -115
  240. package/dist/esm/node_modules/y-protocols/sync.js +26 -102
  241. package/dist/esm/node_modules/y-websocket/src/y-websocket.js +82 -218
  242. package/dist/esm/node_modules/yjs/dist/yjs.js +2263 -4899
  243. package/dist/esm/photo/FilterThumb.js +37 -23
  244. package/dist/esm/photo/NiceAITools.js +685 -466
  245. package/dist/esm/photo/PhotoEditor.js +34 -18
  246. package/dist/esm/photo/PhotoEditor.module.css.js +296 -3
  247. package/dist/esm/photo/PhotoEditorCanvas.js +250 -89
  248. package/dist/esm/photo/PhotoEditorLeftPanel.js +1086 -222
  249. package/dist/esm/photo/PhotoEditorToolbar.js +135 -17
  250. package/dist/esm/photo/photoEditorActions.js +93 -71
  251. package/dist/esm/photo/photoEditorTypes.js +32 -31
  252. package/dist/esm/photo/photoFilters.js +967 -984
  253. package/dist/esm/photo/photoOverlays.js +913 -944
  254. package/dist/esm/photo/photoSelection.js +438 -498
  255. package/dist/esm/photo/usePhotoEditor.js +740 -740
  256. package/dist/esm/pixel/HSVPicker.js +192 -174
  257. package/dist/esm/pixel/PixelEditor.js +160 -47
  258. package/dist/esm/pixel/PixelEditor.module.css.js +209 -3
  259. package/dist/esm/pixel/PixelEditorCanvas.js +29 -14
  260. package/dist/esm/pixel/PixelEditorMenuBar.js +160 -160
  261. package/dist/esm/pixel/PixelEditorRightPanel.js +377 -43
  262. package/dist/esm/pixel/PixelEditorStatusBar.js +47 -18
  263. package/dist/esm/pixel/PixelEditorTimeline.js +106 -21
  264. package/dist/esm/pixel/PixelEditorToolbar.js +99 -19
  265. package/dist/esm/pixel/SpriteGeneratorPanel.js +483 -301
  266. package/dist/esm/pixel/animalGeneratorPresets.js +782 -600
  267. package/dist/esm/pixel/asepriteFormat.js +517 -559
  268. package/dist/esm/pixel/buildingGeneratorPresets.js +699 -519
  269. package/dist/esm/pixel/characterGeneratorPresets.js +650 -543
  270. package/dist/esm/pixel/pixel-pro.js +53 -62
  271. package/dist/esm/pixel/pixelEditorExports.js +397 -427
  272. package/dist/esm/pixel/pixelEditorTypes.js +103 -107
  273. package/dist/esm/pixel/pixelEditorUtils.js +551 -560
  274. package/dist/esm/pixel/spriteGeneratorCore.js +223 -256
  275. package/dist/esm/pixel/usePixelEditor.js +1322 -1342
  276. package/dist/esm/texture/Nice3DTexturePainter.js +709 -439
  277. package/dist/esm/ui/NiceUIDesigner.js +957 -526
  278. package/dist/esm/vector/NiceSvgToCode.js +589 -445
  279. package/dist/esm/vector/VectorEditor.js +291 -116
  280. package/dist/esm/vector/VectorEditor.module.css.js +86 -3
  281. package/dist/esm/vector/VectorEditorMenuBar.js +333 -273
  282. package/dist/esm/vector/VectorEditorRightPanel.js +1094 -369
  283. package/dist/esm/vector/VectorEditorShapeRenderer.js +199 -59
  284. package/dist/esm/vector/VectorEditorStatusBar.js +39 -11
  285. package/dist/esm/vector/useVectorEditor.js +849 -888
  286. package/dist/esm/vector/vectorAnimation.js +115 -136
  287. package/dist/esm/vector/vectorBooleanOps.js +401 -484
  288. package/dist/esm/vector/vectorEditorExport.js +207 -202
  289. package/dist/esm/vector/vectorEditorImport.js +174 -188
  290. package/dist/esm/vector/vectorEditorTypes.js +50 -48
  291. package/dist/esm/vector/vectorGradients.js +158 -173
  292. package/dist/esm/vector/vectorIconExport.js +53 -58
  293. package/dist/esm/vector/vectorIconImport.js +171 -218
  294. package/package.json +9 -15
@@ -1,427 +1,1236 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var ui = require('@nice2dev/ui');
5
- var uiCore = require('@nice2dev/ui-core');
6
- var React = require('react');
7
- var i18n = require('../core/i18n.js');
8
- var GameAsset2dEditor_module = require('./GameAsset2dEditor.module.css.js');
9
- var useGameAssetEditor = require('./useGameAssetEditor.js');
10
-
11
- /* ────────────────────────────────────────────────────────────────
12
- MENU BAR
13
- ──────────────────────────────────────────────────────────────── */
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const ui = require("@nice2dev/ui");
5
+ const uiCore = require("@nice2dev/ui-core");
6
+ const React = require("react");
7
+ const i18n = require("../core/i18n.js");
8
+ const GameAsset2dEditor_module = require("./GameAsset2dEditor.module.css.js");
9
+ const useGameAssetEditor = require("./useGameAssetEditor.js");
14
10
  const MenuBar = ({ api }) => {
15
- const { t } = i18n.useNiceTranslation();
16
- const fileInputRef = React.useRef(null);
17
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.menuBar, children: [jsxRuntime.jsxs("h3", { children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "gamepad", size: 16 }), ' ', t('gameAsset2dEditor.gameAssetEditor', 'Game Asset Editor')] }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.menuGroup, children: [jsxRuntime.jsxs(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: () => api.newProject('New Project'), children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "file", size: 14 }), " ", t('gameAsset2dEditor.new', 'New')] }), jsxRuntime.jsxs(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "folder", size: 14 }), " ", t('gameAsset2dEditor.open', 'Open')] }), jsxRuntime.jsxs(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: api.saveProject, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "save", size: 14 }), " ", t('gameAsset2dEditor.save', 'Save')] })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.spacer }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.menuGroup, children: [jsxRuntime.jsxs(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: api.undo, disabled: !api.canUndo, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-left", size: 14 }), " ", t('gameAsset2dEditor.undo', 'Undo')] }), jsxRuntime.jsxs(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: api.redo, disabled: !api.canRedo, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-right", size: 14 }), " ", t('gameAsset2dEditor.redo', 'Redo')] })] }), jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", accept: ".json", style: { display: 'none' }, onChange: (e) => {
18
- var _a;
19
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
20
- if (file) {
21
- api.loadProject(file);
22
- }
23
- e.target.value = '';
24
- } })] }));
11
+ const { t } = i18n.useNiceTranslation();
12
+ const fileInputRef = React.useRef(null);
13
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.menuBar, children: [
14
+ /* @__PURE__ */ jsxRuntime.jsxs("h3", { children: [
15
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "gamepad", size: 16 }),
16
+ " ",
17
+ t("gameAsset2dEditor.gameAssetEditor", "Game Asset Editor")
18
+ ] }),
19
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.menuGroup, children: [
20
+ /* @__PURE__ */ jsxRuntime.jsxs(
21
+ ui.NiceButton,
22
+ {
23
+ className: GameAsset2dEditor_module.default.menuBtn,
24
+ variant: "ghost",
25
+ size: "sm",
26
+ onClick: () => api.newProject("New Project"),
27
+ children: [
28
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "file", size: 14 }),
29
+ " ",
30
+ t("gameAsset2dEditor.new", "New")
31
+ ]
32
+ }
33
+ ),
34
+ /* @__PURE__ */ jsxRuntime.jsxs(
35
+ ui.NiceButton,
36
+ {
37
+ className: GameAsset2dEditor_module.default.menuBtn,
38
+ variant: "ghost",
39
+ size: "sm",
40
+ onClick: () => fileInputRef.current?.click(),
41
+ children: [
42
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "folder", size: 14 }),
43
+ " ",
44
+ t("gameAsset2dEditor.open", "Open")
45
+ ]
46
+ }
47
+ ),
48
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.NiceButton, { className: GameAsset2dEditor_module.default.menuBtn, variant: "ghost", size: "sm", onClick: api.saveProject, children: [
49
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "save", size: 14 }),
50
+ " ",
51
+ t("gameAsset2dEditor.save", "Save")
52
+ ] })
53
+ ] }),
54
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.spacer }),
55
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.menuGroup, children: [
56
+ /* @__PURE__ */ jsxRuntime.jsxs(
57
+ ui.NiceButton,
58
+ {
59
+ className: GameAsset2dEditor_module.default.menuBtn,
60
+ variant: "ghost",
61
+ size: "sm",
62
+ onClick: api.undo,
63
+ disabled: !api.canUndo,
64
+ children: [
65
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-left", size: 14 }),
66
+ " ",
67
+ t("gameAsset2dEditor.undo", "Undo")
68
+ ]
69
+ }
70
+ ),
71
+ /* @__PURE__ */ jsxRuntime.jsxs(
72
+ ui.NiceButton,
73
+ {
74
+ className: GameAsset2dEditor_module.default.menuBtn,
75
+ variant: "ghost",
76
+ size: "sm",
77
+ onClick: api.redo,
78
+ disabled: !api.canRedo,
79
+ children: [
80
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-right", size: 14 }),
81
+ " ",
82
+ t("gameAsset2dEditor.redo", "Redo")
83
+ ]
84
+ }
85
+ )
86
+ ] }),
87
+ /* @__PURE__ */ jsxRuntime.jsx(
88
+ "input",
89
+ {
90
+ ref: fileInputRef,
91
+ type: "file",
92
+ accept: ".json",
93
+ style: { display: "none" },
94
+ onChange: (e) => {
95
+ const file = e.target.files?.[0];
96
+ if (file) {
97
+ api.loadProject(file);
98
+ }
99
+ e.target.value = "";
100
+ }
101
+ }
102
+ )
103
+ ] });
25
104
  };
26
- /* ────────────────────────────────────────────────────────────────
27
- MODE TABS
28
- ──────────────────────────────────────────────────────────────── */
29
105
  const ModeTabs = ({ api }) => {
30
- const { t } = i18n.useNiceTranslation();
31
- const modes = [
32
- { id: 'tilemap', label: t('gameAsset2dEditor.tileMap', 'Tile Map'), icon: 'grid' },
33
- { id: 'spritesheet', label: t('gameAsset2dEditor.spriteSheet', 'Sprite Sheet'), icon: 'image' },
34
- { id: 'animation', label: t('gameAsset2dEditor.animation', 'Animation'), icon: 'video' },
35
- { id: 'effects', label: t('gameAsset2dEditor.effects2', 'Effects'), icon: 'wand' },
36
- ];
37
- return (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.modeTabs, children: modes.map((mode) => (jsxRuntime.jsxs(ui.NiceButton, { className: `${GameAsset2dEditor_module.modeTab} ${api.editorState.mode === mode.id ? GameAsset2dEditor_module.active : ''}`, variant: api.editorState.mode === mode.id ? 'primary' : 'ghost', onClick: () => api.setMode(mode.id), children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: mode.icon, size: 16 }), " ", mode.label] }, mode.id))) }));
106
+ const { t } = i18n.useNiceTranslation();
107
+ const modes = [
108
+ { id: "tilemap", label: t("gameAsset2dEditor.tileMap", "Tile Map"), icon: "grid" },
109
+ { id: "spritesheet", label: t("gameAsset2dEditor.spriteSheet", "Sprite Sheet"), icon: "image" },
110
+ { id: "animation", label: t("gameAsset2dEditor.animation", "Animation"), icon: "video" },
111
+ { id: "effects", label: t("gameAsset2dEditor.effects2", "Effects"), icon: "wand" }
112
+ ];
113
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.modeTabs, children: modes.map((mode) => /* @__PURE__ */ jsxRuntime.jsxs(
114
+ ui.NiceButton,
115
+ {
116
+ className: `${GameAsset2dEditor_module.default.modeTab} ${api.editorState.mode === mode.id ? GameAsset2dEditor_module.default.active : ""}`,
117
+ variant: api.editorState.mode === mode.id ? "primary" : "ghost",
118
+ onClick: () => api.setMode(mode.id),
119
+ children: [
120
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: mode.icon, size: 16 }),
121
+ " ",
122
+ mode.label
123
+ ]
124
+ },
125
+ mode.id
126
+ )) });
38
127
  };
39
- /* ────────────────────────────────────────────────────────────────
40
- TILE MAP TOOLBAR
41
- ──────────────────────────────────────────────────────────────── */
42
128
  const TileMapToolbar = ({ api }) => {
43
- const { t } = i18n.useNiceTranslation();
44
- const tools = [
45
- { id: 'select', icon: 'square', label: t('gameAsset2dEditor.select', 'Select') },
46
- { id: 'brush', icon: 'brush', label: t('gameAsset2dEditor.brush', 'Brush') },
47
- { id: 'eraser', icon: 'eraser', label: t('gameAsset2dEditor.eraser', 'Eraser') },
48
- { id: 'fill', icon: 'bucket', label: t('gameAsset2dEditor.fill', 'Fill') },
49
- { id: 'rectangle', icon: 'square', label: t('gameAsset2dEditor.rectangle', 'Rectangle') },
50
- { id: 'line', icon: 'line', label: t('gameAsset2dEditor.line', 'Line') },
51
- {
52
- id: 'eyedropper',
53
- icon: 'eyedropper',
54
- label: t('gameAsset2dEditor.eyedropper', 'Eyedropper'),
55
- },
56
- ];
57
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.toolbar, children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.toolGroup, children: tools.map((tool) => (jsxRuntime.jsx(ui.NiceButton, { className: `${GameAsset2dEditor_module.toolBtn} ${api.editorState.tileMapTool === tool.id ? GameAsset2dEditor_module.active : ''}`, variant: api.editorState.tileMapTool === tool.id ? 'primary' : 'ghost', size: "sm", onClick: () => api.setTileMapTool(tool.id), title: tool.label, children: jsxRuntime.jsx(uiCore.NiceIcon, { name: tool.icon, size: 16 }) }, tool.id))) }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.spacer }), jsxRuntime.jsx(ui.NiceButton, { className: `${GameAsset2dEditor_module.toolBtn} ${api.editorState.showGrid ? GameAsset2dEditor_module.active : ''}`, variant: api.editorState.showGrid ? 'primary' : 'ghost', size: "sm", onClick: api.toggleGrid, title: t('gameAsset2dEditor.toggleGrid', 'Toggle Grid'), "aria-label": t('gameAsset2dEditor.toggleGrid', 'Toggle Grid'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "grid", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: `${GameAsset2dEditor_module.toolBtn} ${api.editorState.showCollision ? GameAsset2dEditor_module.active : ''}`, variant: api.editorState.showCollision ? 'primary' : 'ghost', size: "sm", onClick: api.toggleCollision, title: t('gameAsset2dEditor.showCollision', 'Show Collision'), "aria-label": t('gameAsset2dEditor.showCollision', 'Show Collision'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "square", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: `${GameAsset2dEditor_module.toolBtn} ${api.editorState.snapToGrid ? GameAsset2dEditor_module.active : ''}`, variant: api.editorState.snapToGrid ? 'primary' : 'ghost', size: "sm", onClick: api.toggleSnap, title: t('gameAsset2dEditor.snapToGrid', 'Snap to Grid'), "aria-label": t('gameAsset2dEditor.snapToGrid', 'Snap to Grid'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "grid", size: 16 }) })] }));
129
+ const { t } = i18n.useNiceTranslation();
130
+ const tools = [
131
+ { id: "select", icon: "square", label: t("gameAsset2dEditor.select", "Select") },
132
+ { id: "brush", icon: "brush", label: t("gameAsset2dEditor.brush", "Brush") },
133
+ { id: "eraser", icon: "eraser", label: t("gameAsset2dEditor.eraser", "Eraser") },
134
+ { id: "fill", icon: "bucket", label: t("gameAsset2dEditor.fill", "Fill") },
135
+ { id: "rectangle", icon: "square", label: t("gameAsset2dEditor.rectangle", "Rectangle") },
136
+ { id: "line", icon: "line", label: t("gameAsset2dEditor.line", "Line") },
137
+ {
138
+ id: "eyedropper",
139
+ icon: "eyedropper",
140
+ label: t("gameAsset2dEditor.eyedropper", "Eyedropper")
141
+ }
142
+ ];
143
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.toolbar, children: [
144
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.toolGroup, children: tools.map((tool) => /* @__PURE__ */ jsxRuntime.jsx(
145
+ ui.NiceButton,
146
+ {
147
+ className: `${GameAsset2dEditor_module.default.toolBtn} ${api.editorState.tileMapTool === tool.id ? GameAsset2dEditor_module.default.active : ""}`,
148
+ variant: api.editorState.tileMapTool === tool.id ? "primary" : "ghost",
149
+ size: "sm",
150
+ onClick: () => api.setTileMapTool(tool.id),
151
+ title: tool.label,
152
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: tool.icon, size: 16 })
153
+ },
154
+ tool.id
155
+ )) }),
156
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.spacer }),
157
+ /* @__PURE__ */ jsxRuntime.jsx(
158
+ ui.NiceButton,
159
+ {
160
+ className: `${GameAsset2dEditor_module.default.toolBtn} ${api.editorState.showGrid ? GameAsset2dEditor_module.default.active : ""}`,
161
+ variant: api.editorState.showGrid ? "primary" : "ghost",
162
+ size: "sm",
163
+ onClick: api.toggleGrid,
164
+ title: t("gameAsset2dEditor.toggleGrid", "Toggle Grid"),
165
+ "aria-label": t("gameAsset2dEditor.toggleGrid", "Toggle Grid"),
166
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "grid", size: 16 })
167
+ }
168
+ ),
169
+ /* @__PURE__ */ jsxRuntime.jsx(
170
+ ui.NiceButton,
171
+ {
172
+ className: `${GameAsset2dEditor_module.default.toolBtn} ${api.editorState.showCollision ? GameAsset2dEditor_module.default.active : ""}`,
173
+ variant: api.editorState.showCollision ? "primary" : "ghost",
174
+ size: "sm",
175
+ onClick: api.toggleCollision,
176
+ title: t("gameAsset2dEditor.showCollision", "Show Collision"),
177
+ "aria-label": t("gameAsset2dEditor.showCollision", "Show Collision"),
178
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "square", size: 16 })
179
+ }
180
+ ),
181
+ /* @__PURE__ */ jsxRuntime.jsx(
182
+ ui.NiceButton,
183
+ {
184
+ className: `${GameAsset2dEditor_module.default.toolBtn} ${api.editorState.snapToGrid ? GameAsset2dEditor_module.default.active : ""}`,
185
+ variant: api.editorState.snapToGrid ? "primary" : "ghost",
186
+ size: "sm",
187
+ onClick: api.toggleSnap,
188
+ title: t("gameAsset2dEditor.snapToGrid", "Snap to Grid"),
189
+ "aria-label": t("gameAsset2dEditor.snapToGrid", "Snap to Grid"),
190
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "grid", size: 16 })
191
+ }
192
+ )
193
+ ] });
58
194
  };
59
- /* ────────────────────────────────────────────────────────────────
60
- SPRITE SHEET TOOLBAR
61
- ──────────────────────────────────────────────────────────────── */
62
195
  const SpriteSheetToolbar = ({ api }) => {
63
- const { t } = i18n.useNiceTranslation();
64
- const [sliceWidth, setSliceWidth] = React.useState(16);
65
- const [sliceHeight, setSliceHeight] = React.useState(16);
66
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.toolbar, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.toolGroup, children: [jsxRuntime.jsx(ui.NiceButton, { className: `${GameAsset2dEditor_module.toolBtn} ${api.editorState.spriteSheetTool === 'select' ? GameAsset2dEditor_module.active : ''}`, variant: api.editorState.spriteSheetTool === 'select' ? 'primary' : 'ghost', size: "sm", onClick: () => api.setSpriteSheetTool('select'), title: t('gameAsset2dEditor.select', 'Select'), "aria-label": t('gameAsset2dEditor.select', 'Select'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "square", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: `${GameAsset2dEditor_module.toolBtn} ${api.editorState.spriteSheetTool === 'slice' ? GameAsset2dEditor_module.active : ''}`, variant: api.editorState.spriteSheetTool === 'slice' ? 'primary' : 'ghost', size: "sm", onClick: () => api.setSpriteSheetTool('slice'), title: t('gameAsset2dEditor.manualSlice', 'Manual Slice'), "aria-label": t('gameAsset2dEditor.manualSlice', 'Manual Slice'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "scissors", size: 16 }) })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.spacer }), jsxRuntime.jsxs("label", { style: { fontSize: 11, color: 'var(--nice-text-secondary, #8892a8)' }, children: [t('gameAsset2dEditor.frameSize', 'Frame size:'), jsxRuntime.jsx(ui.NiceNumberInput, { value: sliceWidth, onChange: (val) => setSliceWidth(val !== null && val !== void 0 ? val : 16), style: { width: 40, margin: '0 4px' }, className: GameAsset2dEditor_module.panelInput }), "\u00D7", jsxRuntime.jsx(ui.NiceNumberInput, { value: sliceHeight, onChange: (val) => setSliceHeight(val !== null && val !== void 0 ? val : 16), style: { width: 40, marginLeft: 4 }, className: GameAsset2dEditor_module.panelInput })] }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.btnSecondary, variant: "ghost", onClick: () => api.autoSlice(sliceWidth, sliceHeight), style: { marginLeft: 8 }, children: t('gameAsset2dEditor.autoSlice', 'Auto Slice') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.btnSecondary, variant: "ghost", onClick: api.detectSprites, style: { marginLeft: 4 }, children: t('gameAsset2dEditor.detectSprites', 'Detect Sprites') })] }));
67
- };
68
- /* ────────────────────────────────────────────────────────────────
69
- TILE PALETTE (LEFT PANEL)
70
- ──────────────────────────────────────────────────────────────── */
71
- const TilePalette = ({ api }) => {
72
- const { t } = i18n.useNiceTranslation();
73
- const fileInputRef = React.useRef(null);
74
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.leftPanel, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelHeader, children: [jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.tiles', 'Tiles') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: t('gameAsset2dEditor.add', '+ Add') })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, children: api.project.tileSets.length === 0 ? (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.emptyState, children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyStateText, children: t('gameAsset2dEditor.noTilesYet', 'No tiles yet') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.btnSecondary, variant: "ghost", onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: t('gameAsset2dEditor.importTiles', 'Import Tiles') })] })) : (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.tilePalette, children: api.project.tileSets.map((tile) => (jsxRuntime.jsx("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: `${GameAsset2dEditor_module.tileItem} ${api.editorState.selectedTileId === tile.id ? GameAsset2dEditor_module.selected : ''}`, onClick: () => api.selectTile(tile.id), title: tile.name, children: jsxRuntime.jsx("img", { src: tile.thumbnail, alt: tile.name }) }, tile.id))) })) }), jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: (e) => {
75
- var _a;
76
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
77
- if (file) {
78
- api.importTileSet(file);
79
- }
80
- e.target.value = '';
81
- } })] }));
82
- };
83
- /* ────────────────────────────────────────────────────────────────
84
- LAYERS PANEL (RIGHT PANEL)
85
- ──────────────────────────────────────────────────────────────── */
86
- const LayersPanel = ({ api }) => {
87
- const { t } = i18n.useNiceTranslation();
88
- const activeMap = api.project.tileMaps.find((m) => m.id === api.editorState.activeTileMapId);
89
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.rightPanel, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelHeader, children: [jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.layers', 'Layers') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: api.addLayer, disabled: !activeMap, children: t('gameAsset2dEditor.add', '+ Add') })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, children: activeMap ? (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.layersList, children: [...activeMap.layers].reverse().map((layer) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: `${GameAsset2dEditor_module.layerItem} ${api.editorState.activeLayerId === layer.id ? GameAsset2dEditor_module.selected : ''}`, onClick: () => api.selectLayer(layer.id), children: [jsxRuntime.jsx(ui.NiceButton, { className: `${GameAsset2dEditor_module.layerVisibility} ${!layer.visible ? GameAsset2dEditor_module.hidden : ''}`, variant: "ghost", size: "sm", onClick: (e) => {
90
- e.stopPropagation();
91
- api.toggleLayerVisibility(layer.id);
92
- }, "aria-label": layer.visible
93
- ? t('gameAsset2dEditor.hideLayer', 'Hide layer')
94
- : t('gameAsset2dEditor.showLayer', 'Show layer'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: layer.visible ? 'eye' : 'eye-off', size: 16 }) }), jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: layer.name }), jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.layerOpacity, children: [Math.round(layer.opacity * 100), "%"] })] }, layer.id))) })) : (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyState, children: jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyStateText, children: t('gameAsset2dEditor.noTileMapSelected', 'No tile map selected') }) })) }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelHeader, children: [jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.maps', 'Maps') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: () => api.createTileMap('New Map', 32, 32), children: t('gameAsset2dEditor.new2', '+ New') })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, children: api.project.tileMaps.map((map) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: `${GameAsset2dEditor_module.layerItem} ${api.editorState.activeTileMapId === map.id ? GameAsset2dEditor_module.selected : ''}`, onClick: () => api.selectTileMap(map.id), children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: map.name }), jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.layerOpacity, children: [map.width, "\u00D7", map.height] })] }, map.id))) })] }));
95
- };
96
- /* ────────────────────────────────────────────────────────────────
97
- TILE MAP CANVAS
98
- ──────────────────────────────────────────────────────────────── */
99
- const TileMapCanvas = ({ api }) => {
100
- const { t } = i18n.useNiceTranslation();
101
- const canvasRef = React.useRef(null);
102
- const containerRef = React.useRef(null);
103
- const [isDragging, setIsDragging] = React.useState(false);
104
- const activeMap = api.project.tileMaps.find((m) => m.id === api.editorState.activeTileMapId);
105
- // Render the tile map
106
- React.useEffect(() => {
107
- var _a;
108
- const canvas = canvasRef.current;
109
- if (!canvas || !activeMap) {
110
- return;
111
- }
112
- const ctx = canvas.getContext('2d');
113
- if (!ctx) {
114
- return;
115
- }
116
- canvas.width = activeMap.width * activeMap.tileWidth;
117
- canvas.height = activeMap.height * activeMap.tileHeight;
118
- // Background
119
- ctx.fillStyle = activeMap.backgroundColor;
120
- ctx.fillRect(0, 0, canvas.width, canvas.height);
121
- // Render layers
122
- for (const layer of activeMap.layers.filter((l) => l.visible)) {
123
- ctx.globalAlpha = layer.opacity;
124
- for (let y = 0; y < activeMap.height; y++) {
125
- for (let x = 0; x < activeMap.width; x++) {
126
- const tileId = (_a = layer.tiles[y]) === null || _a === void 0 ? void 0 : _a[x];
127
- if (tileId) {
128
- const tile = api.project.tileSets.find((t) => t.id === tileId);
129
- if (tile === null || tile === void 0 ? void 0 : tile.thumbnail) {
130
- const img = new Image();
131
- img.src = tile.thumbnail;
132
- ctx.drawImage(img, x * activeMap.tileWidth, y * activeMap.tileHeight, activeMap.tileWidth, activeMap.tileHeight);
133
- }
134
- }
135
- }
136
- }
196
+ const { t } = i18n.useNiceTranslation();
197
+ const [sliceWidth, setSliceWidth] = React.useState(16);
198
+ const [sliceHeight, setSliceHeight] = React.useState(16);
199
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.toolbar, children: [
200
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.toolGroup, children: [
201
+ /* @__PURE__ */ jsxRuntime.jsx(
202
+ ui.NiceButton,
203
+ {
204
+ className: `${GameAsset2dEditor_module.default.toolBtn} ${api.editorState.spriteSheetTool === "select" ? GameAsset2dEditor_module.default.active : ""}`,
205
+ variant: api.editorState.spriteSheetTool === "select" ? "primary" : "ghost",
206
+ size: "sm",
207
+ onClick: () => api.setSpriteSheetTool("select"),
208
+ title: t("gameAsset2dEditor.select", "Select"),
209
+ "aria-label": t("gameAsset2dEditor.select", "Select"),
210
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "square", size: 16 })
137
211
  }
138
- // Grid overlay
139
- if (api.editorState.showGrid) {
140
- ctx.globalAlpha = 0.3;
141
- ctx.strokeStyle = uiCore.resolveCssColor('var(--nice-bg, #fff)', ctx.canvas);
142
- ctx.lineWidth = 1;
143
- for (let x = 0; x <= activeMap.width; x++) {
144
- ctx.beginPath();
145
- ctx.moveTo(x * activeMap.tileWidth, 0);
146
- ctx.lineTo(x * activeMap.tileWidth, canvas.height);
147
- ctx.stroke();
148
- }
149
- for (let y = 0; y <= activeMap.height; y++) {
150
- ctx.beginPath();
151
- ctx.moveTo(0, y * activeMap.tileHeight);
152
- ctx.lineTo(canvas.width, y * activeMap.tileHeight);
153
- ctx.stroke();
154
- }
212
+ ),
213
+ /* @__PURE__ */ jsxRuntime.jsx(
214
+ ui.NiceButton,
215
+ {
216
+ className: `${GameAsset2dEditor_module.default.toolBtn} ${api.editorState.spriteSheetTool === "slice" ? GameAsset2dEditor_module.default.active : ""}`,
217
+ variant: api.editorState.spriteSheetTool === "slice" ? "primary" : "ghost",
218
+ size: "sm",
219
+ onClick: () => api.setSpriteSheetTool("slice"),
220
+ title: t("gameAsset2dEditor.manualSlice", "Manual Slice"),
221
+ "aria-label": t("gameAsset2dEditor.manualSlice", "Manual Slice"),
222
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "scissors", size: 16 })
155
223
  }
156
- ctx.globalAlpha = 1;
157
- }, [activeMap, api.project.tileSets, api.editorState.showGrid]);
158
- const handleCanvasClick = React.useCallback((e) => {
159
- if (!activeMap || !api.editorState.activeLayerId || !api.editorState.selectedTileId) {
160
- return;
224
+ )
225
+ ] }),
226
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.spacer }),
227
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { fontSize: 11, color: "var(--nice-text-secondary, #8892a8)" }, children: [
228
+ t("gameAsset2dEditor.frameSize", "Frame size:"),
229
+ /* @__PURE__ */ jsxRuntime.jsx(
230
+ ui.NiceNumberInput,
231
+ {
232
+ value: sliceWidth,
233
+ onChange: (val) => setSliceWidth(val ?? 16),
234
+ style: { width: 40, margin: "0 4px" },
235
+ className: GameAsset2dEditor_module.default.panelInput
161
236
  }
162
- const canvas = canvasRef.current;
163
- if (!canvas) {
164
- return;
237
+ ),
238
+ "×",
239
+ /* @__PURE__ */ jsxRuntime.jsx(
240
+ ui.NiceNumberInput,
241
+ {
242
+ value: sliceHeight,
243
+ onChange: (val) => setSliceHeight(val ?? 16),
244
+ style: { width: 40, marginLeft: 4 },
245
+ className: GameAsset2dEditor_module.default.panelInput
165
246
  }
166
- const rect = canvas.getBoundingClientRect();
167
- const scaleX = canvas.width / rect.width;
168
- const scaleY = canvas.height / rect.height;
169
- const x = Math.floor(((e.clientX - rect.left) * scaleX) / activeMap.tileWidth);
170
- const y = Math.floor(((e.clientY - rect.top) * scaleY) / activeMap.tileHeight);
171
- if (api.editorState.tileMapTool === 'brush') {
172
- api.setTile(api.editorState.activeLayerId, x, y, api.editorState.selectedTileId);
247
+ )
248
+ ] }),
249
+ /* @__PURE__ */ jsxRuntime.jsx(
250
+ ui.NiceButton,
251
+ {
252
+ className: GameAsset2dEditor_module.default.btnSecondary,
253
+ variant: "ghost",
254
+ onClick: () => api.autoSlice(sliceWidth, sliceHeight),
255
+ style: { marginLeft: 8 },
256
+ children: t("gameAsset2dEditor.autoSlice", "Auto Slice")
257
+ }
258
+ ),
259
+ /* @__PURE__ */ jsxRuntime.jsx(
260
+ ui.NiceButton,
261
+ {
262
+ className: GameAsset2dEditor_module.default.btnSecondary,
263
+ variant: "ghost",
264
+ onClick: api.detectSprites,
265
+ style: { marginLeft: 4 },
266
+ children: t("gameAsset2dEditor.detectSprites", "Detect Sprites")
267
+ }
268
+ )
269
+ ] });
270
+ };
271
+ const TilePalette = ({ api }) => {
272
+ const { t } = i18n.useNiceTranslation();
273
+ const fileInputRef = React.useRef(null);
274
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.leftPanel, children: [
275
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelHeader, children: [
276
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.tiles", "Tiles") }),
277
+ /* @__PURE__ */ jsxRuntime.jsx(
278
+ ui.NiceButton,
279
+ {
280
+ className: GameAsset2dEditor_module.default.menuBtn,
281
+ variant: "ghost",
282
+ size: "sm",
283
+ onClick: () => fileInputRef.current?.click(),
284
+ children: t("gameAsset2dEditor.add", "+ Add")
173
285
  }
174
- else if (api.editorState.tileMapTool === 'eraser') {
175
- api.setTile(api.editorState.activeLayerId, x, y, null);
286
+ )
287
+ ] }),
288
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, children: api.project.tileSets.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.emptyState, children: [
289
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyStateText, children: t("gameAsset2dEditor.noTilesYet", "No tiles yet") }),
290
+ /* @__PURE__ */ jsxRuntime.jsx(
291
+ ui.NiceButton,
292
+ {
293
+ className: GameAsset2dEditor_module.default.btnSecondary,
294
+ variant: "ghost",
295
+ onClick: () => fileInputRef.current?.click(),
296
+ children: t("gameAsset2dEditor.importTiles", "Import Tiles")
176
297
  }
177
- else if (api.editorState.tileMapTool === 'fill') {
178
- api.fillTiles(api.editorState.activeLayerId, x, y, api.editorState.selectedTileId);
298
+ )
299
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.tilePalette, children: api.project.tileSets.map((tile) => /* @__PURE__ */ jsxRuntime.jsx(
300
+ "div",
301
+ {
302
+ role: "button",
303
+ tabIndex: 0,
304
+ onKeyDown: uiCore.clickOnActivationKey,
305
+ className: `${GameAsset2dEditor_module.default.tileItem} ${api.editorState.selectedTileId === tile.id ? GameAsset2dEditor_module.default.selected : ""}`,
306
+ onClick: () => api.selectTile(tile.id),
307
+ title: tile.name,
308
+ children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: tile.thumbnail, alt: tile.name })
309
+ },
310
+ tile.id
311
+ )) }) }),
312
+ /* @__PURE__ */ jsxRuntime.jsx(
313
+ "input",
314
+ {
315
+ ref: fileInputRef,
316
+ type: "file",
317
+ accept: "image/*",
318
+ style: { display: "none" },
319
+ onChange: (e) => {
320
+ const file = e.target.files?.[0];
321
+ if (file) {
322
+ api.importTileSet(file);
323
+ }
324
+ e.target.value = "";
179
325
  }
180
- }, [activeMap, api]);
181
- return (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.viewport, ref: containerRef, children: activeMap ? (jsxRuntime.jsx("canvas", { ref: canvasRef, className: GameAsset2dEditor_module.viewportCanvas, style: {
182
- transform: `translate(-50%, -50%) scale(${api.editorState.zoom})`,
183
- }, onClick: handleCanvasClick, onMouseDown: () => setIsDragging(true), onMouseUp: () => setIsDragging(false), onMouseMove: (e) => {
184
- if (isDragging &&
185
- (api.editorState.tileMapTool === 'brush' || api.editorState.tileMapTool === 'eraser')) {
186
- handleCanvasClick(e);
187
- }
188
- } })) : (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.emptyState, children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyStateText, children: t('gameAsset2dEditor.createOrSelectATile', 'Create or select a tile map to start editing') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.btnPrimary, variant: "primary", onClick: () => api.createTileMap('New Map', 32, 32), children: t('gameAsset2dEditor.createTileMap', 'Create Tile Map') })] })) }));
326
+ }
327
+ )
328
+ ] });
189
329
  };
190
- /* ────────────────────────────────────────────────────────────────
191
- SPRITE SHEET CANVAS
192
- ──────────────────────────────────────────────────────────────── */
193
- const SpriteSheetCanvas = ({ api }) => {
194
- const { t } = i18n.useNiceTranslation();
195
- const canvasRef = React.useRef(null);
196
- const fileInputRef = React.useRef(null);
197
- const activeSheet = api.project.spriteSheets.find((s) => s.id === api.editorState.activeSpriteSheetId);
198
- // Render sprite sheet with frame overlays
199
- React.useEffect(() => {
200
- const canvas = canvasRef.current;
201
- if (!canvas || !(activeSheet === null || activeSheet === void 0 ? void 0 : activeSheet.image)) {
202
- return;
203
- }
204
- const ctx = canvas.getContext('2d');
205
- if (!ctx) {
206
- return;
330
+ const LayersPanel = ({ api }) => {
331
+ const { t } = i18n.useNiceTranslation();
332
+ const activeMap = api.project.tileMaps.find((m) => m.id === api.editorState.activeTileMapId);
333
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.rightPanel, children: [
334
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelHeader, children: [
335
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.layers", "Layers") }),
336
+ /* @__PURE__ */ jsxRuntime.jsx(
337
+ ui.NiceButton,
338
+ {
339
+ className: GameAsset2dEditor_module.default.menuBtn,
340
+ variant: "ghost",
341
+ size: "sm",
342
+ onClick: api.addLayer,
343
+ disabled: !activeMap,
344
+ children: t("gameAsset2dEditor.add", "+ Add")
207
345
  }
208
- canvas.width = activeSheet.width;
209
- canvas.height = activeSheet.height;
210
- // Draw image
211
- ctx.drawImage(activeSheet.image, 0, 0);
212
- // Draw frame overlays
213
- ctx.strokeStyle = uiCore.resolveCssColor('var(--nice-warning, #ffd369)', ctx.canvas);
214
- ctx.lineWidth = 2;
215
- for (const frame of activeSheet.frames) {
216
- const isSelected = api.editorState.selectedFrameIds.includes(frame.id);
217
- ctx.strokeStyle = uiCore.resolveCssColor(isSelected ? 'var(--nice-warning, #ffd369)' : 'var(--nice-text-secondary, #4a5a7e)', ctx.canvas);
218
- ctx.strokeRect(frame.x, frame.y, frame.width, frame.height);
219
- // Draw pivot point
220
- const pivotX = frame.x + frame.width * frame.pivotX;
221
- const pivotY = frame.y + frame.height * frame.pivotY;
222
- ctx.fillStyle = uiCore.resolveCssColor(isSelected ? 'var(--nice-warning, #ffd369)' : 'var(--nice-text-secondary, #4a5a7e)', ctx.canvas);
223
- ctx.beginPath();
224
- ctx.arc(pivotX, pivotY, 3, 0, Math.PI * 2);
225
- ctx.fill();
346
+ )
347
+ ] }),
348
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, children: activeMap ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.layersList, children: [...activeMap.layers].reverse().map((layer) => /* @__PURE__ */ jsxRuntime.jsxs(
349
+ "div",
350
+ {
351
+ role: "button",
352
+ tabIndex: 0,
353
+ onKeyDown: uiCore.clickOnActivationKey,
354
+ className: `${GameAsset2dEditor_module.default.layerItem} ${api.editorState.activeLayerId === layer.id ? GameAsset2dEditor_module.default.selected : ""}`,
355
+ onClick: () => api.selectLayer(layer.id),
356
+ children: [
357
+ /* @__PURE__ */ jsxRuntime.jsx(
358
+ ui.NiceButton,
359
+ {
360
+ className: `${GameAsset2dEditor_module.default.layerVisibility} ${!layer.visible ? GameAsset2dEditor_module.default.hidden : ""}`,
361
+ variant: "ghost",
362
+ size: "sm",
363
+ onClick: (e) => {
364
+ e.stopPropagation();
365
+ api.toggleLayerVisibility(layer.id);
366
+ },
367
+ "aria-label": layer.visible ? t("gameAsset2dEditor.hideLayer", "Hide layer") : t("gameAsset2dEditor.showLayer", "Show layer"),
368
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: layer.visible ? "eye" : "eye-off", size: 16 })
369
+ }
370
+ ),
371
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: layer.name }),
372
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.default.layerOpacity, children: [
373
+ Math.round(layer.opacity * 100),
374
+ "%"
375
+ ] })
376
+ ]
377
+ },
378
+ layer.id
379
+ )) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyState, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyStateText, children: t("gameAsset2dEditor.noTileMapSelected", "No tile map selected") }) }) }),
380
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelHeader, children: [
381
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.maps", "Maps") }),
382
+ /* @__PURE__ */ jsxRuntime.jsx(
383
+ ui.NiceButton,
384
+ {
385
+ className: GameAsset2dEditor_module.default.menuBtn,
386
+ variant: "ghost",
387
+ size: "sm",
388
+ onClick: () => api.createTileMap("New Map", 32, 32),
389
+ children: t("gameAsset2dEditor.new2", "+ New")
226
390
  }
227
- }, [activeSheet, api.editorState.selectedFrameIds]);
228
- const handleFrameClick = React.useCallback((e) => {
229
- if (!activeSheet) {
230
- return;
391
+ )
392
+ ] }),
393
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, children: api.project.tileMaps.map((map) => /* @__PURE__ */ jsxRuntime.jsxs(
394
+ "div",
395
+ {
396
+ role: "button",
397
+ tabIndex: 0,
398
+ onKeyDown: uiCore.clickOnActivationKey,
399
+ className: `${GameAsset2dEditor_module.default.layerItem} ${api.editorState.activeTileMapId === map.id ? GameAsset2dEditor_module.default.selected : ""}`,
400
+ onClick: () => api.selectTileMap(map.id),
401
+ children: [
402
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: map.name }),
403
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.default.layerOpacity, children: [
404
+ map.width,
405
+ "×",
406
+ map.height
407
+ ] })
408
+ ]
409
+ },
410
+ map.id
411
+ )) })
412
+ ] });
413
+ };
414
+ const TileMapCanvas = ({ api }) => {
415
+ const { t } = i18n.useNiceTranslation();
416
+ const canvasRef = React.useRef(null);
417
+ const containerRef = React.useRef(null);
418
+ const [isDragging, setIsDragging] = React.useState(false);
419
+ const activeMap = api.project.tileMaps.find((m) => m.id === api.editorState.activeTileMapId);
420
+ React.useEffect(() => {
421
+ const canvas = canvasRef.current;
422
+ if (!canvas || !activeMap) {
423
+ return;
424
+ }
425
+ const ctx = canvas.getContext("2d");
426
+ if (!ctx) {
427
+ return;
428
+ }
429
+ canvas.width = activeMap.width * activeMap.tileWidth;
430
+ canvas.height = activeMap.height * activeMap.tileHeight;
431
+ ctx.fillStyle = activeMap.backgroundColor;
432
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
433
+ for (const layer of activeMap.layers.filter((l) => l.visible)) {
434
+ ctx.globalAlpha = layer.opacity;
435
+ for (let y = 0; y < activeMap.height; y++) {
436
+ for (let x = 0; x < activeMap.width; x++) {
437
+ const tileId = layer.tiles[y]?.[x];
438
+ if (tileId) {
439
+ const tile = api.project.tileSets.find((t2) => t2.id === tileId);
440
+ if (tile?.thumbnail) {
441
+ const img = new Image();
442
+ img.src = tile.thumbnail;
443
+ ctx.drawImage(
444
+ img,
445
+ x * activeMap.tileWidth,
446
+ y * activeMap.tileHeight,
447
+ activeMap.tileWidth,
448
+ activeMap.tileHeight
449
+ );
450
+ }
451
+ }
231
452
  }
232
- const canvas = canvasRef.current;
233
- if (!canvas) {
234
- return;
453
+ }
454
+ }
455
+ if (api.editorState.showGrid) {
456
+ ctx.globalAlpha = 0.3;
457
+ ctx.strokeStyle = uiCore.resolveCssColor("var(--nice-bg, #fff)", ctx.canvas);
458
+ ctx.lineWidth = 1;
459
+ for (let x = 0; x <= activeMap.width; x++) {
460
+ ctx.beginPath();
461
+ ctx.moveTo(x * activeMap.tileWidth, 0);
462
+ ctx.lineTo(x * activeMap.tileWidth, canvas.height);
463
+ ctx.stroke();
464
+ }
465
+ for (let y = 0; y <= activeMap.height; y++) {
466
+ ctx.beginPath();
467
+ ctx.moveTo(0, y * activeMap.tileHeight);
468
+ ctx.lineTo(canvas.width, y * activeMap.tileHeight);
469
+ ctx.stroke();
470
+ }
471
+ }
472
+ ctx.globalAlpha = 1;
473
+ }, [activeMap, api.project.tileSets, api.editorState.showGrid]);
474
+ const handleCanvasClick = React.useCallback(
475
+ (e) => {
476
+ if (!activeMap || !api.editorState.activeLayerId || !api.editorState.selectedTileId) {
477
+ return;
478
+ }
479
+ const canvas = canvasRef.current;
480
+ if (!canvas) {
481
+ return;
482
+ }
483
+ const rect = canvas.getBoundingClientRect();
484
+ const scaleX = canvas.width / rect.width;
485
+ const scaleY = canvas.height / rect.height;
486
+ const x = Math.floor((e.clientX - rect.left) * scaleX / activeMap.tileWidth);
487
+ const y = Math.floor((e.clientY - rect.top) * scaleY / activeMap.tileHeight);
488
+ if (api.editorState.tileMapTool === "brush") {
489
+ api.setTile(api.editorState.activeLayerId, x, y, api.editorState.selectedTileId);
490
+ } else if (api.editorState.tileMapTool === "eraser") {
491
+ api.setTile(api.editorState.activeLayerId, x, y, null);
492
+ } else if (api.editorState.tileMapTool === "fill") {
493
+ api.fillTiles(api.editorState.activeLayerId, x, y, api.editorState.selectedTileId);
494
+ }
495
+ },
496
+ [activeMap, api]
497
+ );
498
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.viewport, ref: containerRef, children: activeMap ? /* @__PURE__ */ jsxRuntime.jsx(
499
+ "canvas",
500
+ {
501
+ ref: canvasRef,
502
+ className: GameAsset2dEditor_module.default.viewportCanvas,
503
+ style: {
504
+ transform: `translate(-50%, -50%) scale(${api.editorState.zoom})`
505
+ },
506
+ onClick: handleCanvasClick,
507
+ onMouseDown: () => setIsDragging(true),
508
+ onMouseUp: () => setIsDragging(false),
509
+ onMouseMove: (e) => {
510
+ if (isDragging && (api.editorState.tileMapTool === "brush" || api.editorState.tileMapTool === "eraser")) {
511
+ handleCanvasClick(e);
235
512
  }
236
- const rect = canvas.getBoundingClientRect();
237
- const scaleX = canvas.width / rect.width;
238
- const scaleY = canvas.height / rect.height;
239
- const x = (e.clientX - rect.left) * scaleX;
240
- const y = (e.clientY - rect.top) * scaleY;
241
- // Find clicked frame
242
- const clickedFrame = activeSheet.frames.find((f) => x >= f.x && x <= f.x + f.width && y >= f.y && y <= f.y + f.height);
243
- if (clickedFrame) {
244
- if (e.ctrlKey || e.metaKey) {
245
- // Toggle selection
246
- const newSelection = api.editorState.selectedFrameIds.includes(clickedFrame.id)
247
- ? api.editorState.selectedFrameIds.filter((id) => id !== clickedFrame.id)
248
- : [...api.editorState.selectedFrameIds, clickedFrame.id];
249
- api.selectFrames(newSelection);
250
- }
251
- else {
252
- api.selectFrames([clickedFrame.id]);
253
- }
513
+ }
514
+ }
515
+ ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.emptyState, children: [
516
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyStateText, children: t(
517
+ "gameAsset2dEditor.createOrSelectATile",
518
+ "Create or select a tile map to start editing"
519
+ ) }),
520
+ /* @__PURE__ */ jsxRuntime.jsx(
521
+ ui.NiceButton,
522
+ {
523
+ className: GameAsset2dEditor_module.default.btnPrimary,
524
+ variant: "primary",
525
+ onClick: () => api.createTileMap("New Map", 32, 32),
526
+ children: t("gameAsset2dEditor.createTileMap", "Create Tile Map")
527
+ }
528
+ )
529
+ ] }) });
530
+ };
531
+ const SpriteSheetCanvas = ({ api }) => {
532
+ const { t } = i18n.useNiceTranslation();
533
+ const canvasRef = React.useRef(null);
534
+ const fileInputRef = React.useRef(null);
535
+ const activeSheet = api.project.spriteSheets.find(
536
+ (s) => s.id === api.editorState.activeSpriteSheetId
537
+ );
538
+ React.useEffect(() => {
539
+ const canvas = canvasRef.current;
540
+ if (!canvas || !activeSheet?.image) {
541
+ return;
542
+ }
543
+ const ctx = canvas.getContext("2d");
544
+ if (!ctx) {
545
+ return;
546
+ }
547
+ canvas.width = activeSheet.width;
548
+ canvas.height = activeSheet.height;
549
+ ctx.drawImage(activeSheet.image, 0, 0);
550
+ ctx.strokeStyle = uiCore.resolveCssColor("var(--nice-warning, #ffd369)", ctx.canvas);
551
+ ctx.lineWidth = 2;
552
+ for (const frame of activeSheet.frames) {
553
+ const isSelected = api.editorState.selectedFrameIds.includes(frame.id);
554
+ ctx.strokeStyle = uiCore.resolveCssColor(
555
+ isSelected ? "var(--nice-warning, #ffd369)" : "var(--nice-text-secondary, #4a5a7e)",
556
+ ctx.canvas
557
+ );
558
+ ctx.strokeRect(frame.x, frame.y, frame.width, frame.height);
559
+ const pivotX = frame.x + frame.width * frame.pivotX;
560
+ const pivotY = frame.y + frame.height * frame.pivotY;
561
+ ctx.fillStyle = uiCore.resolveCssColor(
562
+ isSelected ? "var(--nice-warning, #ffd369)" : "var(--nice-text-secondary, #4a5a7e)",
563
+ ctx.canvas
564
+ );
565
+ ctx.beginPath();
566
+ ctx.arc(pivotX, pivotY, 3, 0, Math.PI * 2);
567
+ ctx.fill();
568
+ }
569
+ }, [activeSheet, api.editorState.selectedFrameIds]);
570
+ const handleFrameClick = React.useCallback(
571
+ (e) => {
572
+ if (!activeSheet) {
573
+ return;
574
+ }
575
+ const canvas = canvasRef.current;
576
+ if (!canvas) {
577
+ return;
578
+ }
579
+ const rect = canvas.getBoundingClientRect();
580
+ const scaleX = canvas.width / rect.width;
581
+ const scaleY = canvas.height / rect.height;
582
+ const x = (e.clientX - rect.left) * scaleX;
583
+ const y = (e.clientY - rect.top) * scaleY;
584
+ const clickedFrame = activeSheet.frames.find(
585
+ (f) => x >= f.x && x <= f.x + f.width && y >= f.y && y <= f.y + f.height
586
+ );
587
+ if (clickedFrame) {
588
+ if (e.ctrlKey || e.metaKey) {
589
+ const newSelection = api.editorState.selectedFrameIds.includes(clickedFrame.id) ? api.editorState.selectedFrameIds.filter((id) => id !== clickedFrame.id) : [...api.editorState.selectedFrameIds, clickedFrame.id];
590
+ api.selectFrames(newSelection);
591
+ } else {
592
+ api.selectFrames([clickedFrame.id]);
254
593
  }
255
- else {
256
- api.selectFrames([]);
594
+ } else {
595
+ api.selectFrames([]);
596
+ }
597
+ },
598
+ [activeSheet, api]
599
+ );
600
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.viewport, children: activeSheet ? /* @__PURE__ */ jsxRuntime.jsx(
601
+ "canvas",
602
+ {
603
+ ref: canvasRef,
604
+ className: GameAsset2dEditor_module.default.viewportCanvas,
605
+ style: {
606
+ transform: `translate(-50%, -50%) scale(${api.editorState.zoom})`
607
+ },
608
+ onClick: handleFrameClick
609
+ }
610
+ ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.emptyState, children: [
611
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyStateText, children: t("gameAsset2dEditor.importASpriteSheetTo", "Import a sprite sheet to start") }),
612
+ /* @__PURE__ */ jsxRuntime.jsx(
613
+ ui.NiceButton,
614
+ {
615
+ className: GameAsset2dEditor_module.default.btnPrimary,
616
+ variant: "primary",
617
+ onClick: () => fileInputRef.current?.click(),
618
+ children: t("gameAsset2dEditor.importSpriteSheet", "Import Sprite Sheet")
619
+ }
620
+ ),
621
+ /* @__PURE__ */ jsxRuntime.jsx(
622
+ "input",
623
+ {
624
+ ref: fileInputRef,
625
+ type: "file",
626
+ accept: "image/*",
627
+ style: { display: "none" },
628
+ onChange: (e) => {
629
+ const file = e.target.files?.[0];
630
+ if (file) {
631
+ api.importSpriteSheet(file);
632
+ }
633
+ e.target.value = "";
257
634
  }
258
- }, [activeSheet, api]);
259
- return (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.viewport, children: activeSheet ? (jsxRuntime.jsx("canvas", { ref: canvasRef, className: GameAsset2dEditor_module.viewportCanvas, style: {
260
- transform: `translate(-50%, -50%) scale(${api.editorState.zoom})`,
261
- }, onClick: handleFrameClick })) : (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.emptyState, children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyStateText, children: t('gameAsset2dEditor.importASpriteSheetTo', 'Import a sprite sheet to start') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.btnPrimary, variant: "primary", onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: t('gameAsset2dEditor.importSpriteSheet', 'Import Sprite Sheet') }), jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: (e) => {
262
- var _a;
263
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
264
- if (file) {
265
- api.importSpriteSheet(file);
266
- }
267
- e.target.value = '';
268
- } })] })) }));
635
+ }
636
+ )
637
+ ] }) });
269
638
  };
270
- /* ────────────────────────────────────────────────────────────────
271
- SPRITE SHEETS LIST
272
- ──────────────────────────────────────────────────────────────── */
273
639
  const SpriteSheetsList = ({ api }) => {
274
- const { t } = i18n.useNiceTranslation();
275
- const fileInputRef = React.useRef(null);
276
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.leftPanel, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelHeader, children: [jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.spriteSheets', 'Sprite Sheets') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: t('gameAsset2dEditor.import', '+ Import') })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, children: api.project.spriteSheets.length === 0 ? (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyState, children: jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyStateText, children: t('gameAsset2dEditor.noSpriteSheets', 'No sprite sheets') }) })) : (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.layersList, children: api.project.spriteSheets.map((sheet) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: `${GameAsset2dEditor_module.layerItem} ${api.editorState.activeSpriteSheetId === sheet.id ? GameAsset2dEditor_module.selected : ''}`, onClick: () => api.selectSpriteSheet(sheet.id), children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: sheet.name }), jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerOpacity, children: t('gameAsset2dEditor.frames', '{frames} frames').replace('{frames}', String(sheet.frames.length)) })] }, sheet.id))) })) }), jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: (e) => {
277
- var _a;
278
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
279
- if (file) {
280
- api.importSpriteSheet(file);
281
- }
282
- e.target.value = '';
283
- } })] }));
640
+ const { t } = i18n.useNiceTranslation();
641
+ const fileInputRef = React.useRef(null);
642
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.leftPanel, children: [
643
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelHeader, children: [
644
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.spriteSheets", "Sprite Sheets") }),
645
+ /* @__PURE__ */ jsxRuntime.jsx(
646
+ ui.NiceButton,
647
+ {
648
+ className: GameAsset2dEditor_module.default.menuBtn,
649
+ variant: "ghost",
650
+ size: "sm",
651
+ onClick: () => fileInputRef.current?.click(),
652
+ children: t("gameAsset2dEditor.import", "+ Import")
653
+ }
654
+ )
655
+ ] }),
656
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, children: api.project.spriteSheets.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyState, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyStateText, children: t("gameAsset2dEditor.noSpriteSheets", "No sprite sheets") }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.layersList, children: api.project.spriteSheets.map((sheet) => /* @__PURE__ */ jsxRuntime.jsxs(
657
+ "div",
658
+ {
659
+ role: "button",
660
+ tabIndex: 0,
661
+ onKeyDown: uiCore.clickOnActivationKey,
662
+ className: `${GameAsset2dEditor_module.default.layerItem} ${api.editorState.activeSpriteSheetId === sheet.id ? GameAsset2dEditor_module.default.selected : ""}`,
663
+ onClick: () => api.selectSpriteSheet(sheet.id),
664
+ children: [
665
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: sheet.name }),
666
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerOpacity, children: t("gameAsset2dEditor.frames", "{frames} frames").replace(
667
+ "{frames}",
668
+ String(sheet.frames.length)
669
+ ) })
670
+ ]
671
+ },
672
+ sheet.id
673
+ )) }) }),
674
+ /* @__PURE__ */ jsxRuntime.jsx(
675
+ "input",
676
+ {
677
+ ref: fileInputRef,
678
+ type: "file",
679
+ accept: "image/*",
680
+ style: { display: "none" },
681
+ onChange: (e) => {
682
+ const file = e.target.files?.[0];
683
+ if (file) {
684
+ api.importSpriteSheet(file);
685
+ }
686
+ e.target.value = "";
687
+ }
688
+ }
689
+ )
690
+ ] });
284
691
  };
285
- /* ────────────────────────────────────────────────────────────────
286
- FRAMES & ANIMATIONS PANEL
287
- ──────────────────────────────────────────────────────────────── */
288
692
  const FramesPanel = ({ api }) => {
289
- var _a;
290
- const { t } = i18n.useNiceTranslation();
291
- const [animName, setAnimName] = React.useState('');
292
- const activeSheet = api.project.spriteSheets.find((s) => s.id === api.editorState.activeSpriteSheetId);
293
- const createAnimationFromSelection = React.useCallback(() => {
294
- if (animName && api.editorState.selectedFrameIds.length > 0) {
295
- api.createAnimation(animName, api.editorState.selectedFrameIds);
296
- setAnimName('');
297
- }
298
- }, [animName, api]);
299
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.rightPanel, children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelHeader, children: jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.frames2', 'Frames ({frames})').replace('{frames}', String((_a = activeSheet === null || activeSheet === void 0 ? void 0 : activeSheet.frames.length) !== null && _a !== void 0 ? _a : 0)) }) }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, style: { maxHeight: 200 }, children: activeSheet === null || activeSheet === void 0 ? void 0 : activeSheet.frames.map((frame) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: `${GameAsset2dEditor_module.layerItem} ${api.editorState.selectedFrameIds.includes(frame.id) ? GameAsset2dEditor_module.selected : ''}`, onClick: () => api.selectFrames([frame.id]), children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: frame.name }), jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.layerOpacity, children: [frame.width, "\u00D7", frame.height] })] }, frame.id))) }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelHeader, children: jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.animations', 'Animations') }) }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelContent, children: [api.editorState.selectedFrameIds.length > 0 && (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelSection, children: [jsxRuntime.jsx(ui.NiceTextInput, { className: GameAsset2dEditor_module.panelInput, placeholder: t('gameAsset2dEditor.animationName', 'Animation name...'), value: animName, onChange: (val) => setAnimName(val) }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.btnPrimary, variant: "primary", onClick: createAnimationFromSelection, style: { marginTop: 8, width: '100%' }, disabled: !animName, children: t('gameAsset2dEditor.createFromFrames', 'Create from {count} frames').replace('{count}', String(api.editorState.selectedFrameIds.length)) })] })), activeSheet === null || activeSheet === void 0 ? void 0 : activeSheet.animations.map((anim) => (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.layerItem, children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: anim.name }), jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.layerOpacity, children: [anim.frameIds.length, "f"] }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.effectRemove, variant: "ghost", size: "sm", onClick: () => api.removeAnimation(anim.id), "aria-label": t('gameAsset2dEditor.removeAnimation', 'Remove animation'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 }) })] }, anim.id)))] })] }));
693
+ const { t } = i18n.useNiceTranslation();
694
+ const [animName, setAnimName] = React.useState("");
695
+ const activeSheet = api.project.spriteSheets.find(
696
+ (s) => s.id === api.editorState.activeSpriteSheetId
697
+ );
698
+ const createAnimationFromSelection = React.useCallback(() => {
699
+ if (animName && api.editorState.selectedFrameIds.length > 0) {
700
+ api.createAnimation(animName, api.editorState.selectedFrameIds);
701
+ setAnimName("");
702
+ }
703
+ }, [animName, api]);
704
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.rightPanel, children: [
705
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelHeader, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.frames2", "Frames ({frames})").replace(
706
+ "{frames}",
707
+ String(activeSheet?.frames.length ?? 0)
708
+ ) }) }),
709
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, style: { maxHeight: 200 }, children: activeSheet?.frames.map((frame) => /* @__PURE__ */ jsxRuntime.jsxs(
710
+ "div",
711
+ {
712
+ role: "button",
713
+ tabIndex: 0,
714
+ onKeyDown: uiCore.clickOnActivationKey,
715
+ className: `${GameAsset2dEditor_module.default.layerItem} ${api.editorState.selectedFrameIds.includes(frame.id) ? GameAsset2dEditor_module.default.selected : ""}`,
716
+ onClick: () => api.selectFrames([frame.id]),
717
+ children: [
718
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: frame.name }),
719
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.default.layerOpacity, children: [
720
+ frame.width,
721
+ "×",
722
+ frame.height
723
+ ] })
724
+ ]
725
+ },
726
+ frame.id
727
+ )) }),
728
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelHeader, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.animations", "Animations") }) }),
729
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelContent, children: [
730
+ api.editorState.selectedFrameIds.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelSection, children: [
731
+ /* @__PURE__ */ jsxRuntime.jsx(
732
+ ui.NiceTextInput,
733
+ {
734
+ className: GameAsset2dEditor_module.default.panelInput,
735
+ placeholder: t("gameAsset2dEditor.animationName", "Animation name..."),
736
+ value: animName,
737
+ onChange: (val) => setAnimName(val)
738
+ }
739
+ ),
740
+ /* @__PURE__ */ jsxRuntime.jsx(
741
+ ui.NiceButton,
742
+ {
743
+ className: GameAsset2dEditor_module.default.btnPrimary,
744
+ variant: "primary",
745
+ onClick: createAnimationFromSelection,
746
+ style: { marginTop: 8, width: "100%" },
747
+ disabled: !animName,
748
+ children: t("gameAsset2dEditor.createFromFrames", "Create from {count} frames").replace(
749
+ "{count}",
750
+ String(api.editorState.selectedFrameIds.length)
751
+ )
752
+ }
753
+ )
754
+ ] }),
755
+ activeSheet?.animations.map((anim) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.layerItem, children: [
756
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: anim.name }),
757
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.default.layerOpacity, children: [
758
+ anim.frameIds.length,
759
+ "f"
760
+ ] }),
761
+ /* @__PURE__ */ jsxRuntime.jsx(
762
+ ui.NiceButton,
763
+ {
764
+ className: GameAsset2dEditor_module.default.effectRemove,
765
+ variant: "ghost",
766
+ size: "sm",
767
+ onClick: () => api.removeAnimation(anim.id),
768
+ "aria-label": t("gameAsset2dEditor.removeAnimation", "Remove animation"),
769
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 })
770
+ }
771
+ )
772
+ ] }, anim.id))
773
+ ] })
774
+ ] });
300
775
  };
301
- /* ────────────────────────────────────────────────────────────────
302
- ANIMATION STATE MACHINE
303
- ──────────────────────────────────────────────────────────────── */
304
776
  const AnimationStateMachineView = ({ api }) => {
305
- var _a;
306
- const { t } = i18n.useNiceTranslation();
307
- const [newStateName, setNewStateName] = React.useState('');
308
- const activeSM = api.project.stateMachines.find((sm) => sm.id === api.editorState.activeStateMachineId);
309
- // Get all animations from all sprite sheets
310
- const allAnimations = React.useMemo(() => {
311
- const result = [];
312
- for (const sheet of api.project.spriteSheets) {
313
- for (const anim of sheet.animations) {
314
- result.push({ ...anim, sheetName: sheet.name });
315
- }
777
+ const { t } = i18n.useNiceTranslation();
778
+ const [newStateName, setNewStateName] = React.useState("");
779
+ const activeSM = api.project.stateMachines.find(
780
+ (sm) => sm.id === api.editorState.activeStateMachineId
781
+ );
782
+ const allAnimations = React.useMemo(() => {
783
+ const result = [];
784
+ for (const sheet of api.project.spriteSheets) {
785
+ for (const anim of sheet.animations) {
786
+ result.push({ ...anim, sheetName: sheet.name });
787
+ }
788
+ }
789
+ return result;
790
+ }, [api.project.spriteSheets]);
791
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flex: 1, overflow: "hidden" }, children: [
792
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.leftPanel, children: [
793
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelHeader, children: [
794
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.stateMachines", "State Machines") }),
795
+ /* @__PURE__ */ jsxRuntime.jsx(
796
+ "button",
797
+ {
798
+ className: GameAsset2dEditor_module.default.menuBtn,
799
+ onClick: () => api.createStateMachine("New State Machine"),
800
+ children: t("gameAsset2dEditor.new2", "+ New")
801
+ }
802
+ )
803
+ ] }),
804
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, style: { maxHeight: 150 }, children: api.project.stateMachines.map((sm) => /* @__PURE__ */ jsxRuntime.jsxs(
805
+ "div",
806
+ {
807
+ role: "button",
808
+ tabIndex: 0,
809
+ onKeyDown: uiCore.clickOnActivationKey,
810
+ className: `${GameAsset2dEditor_module.default.layerItem} ${api.editorState.activeStateMachineId === sm.id ? GameAsset2dEditor_module.default.selected : ""}`,
811
+ onClick: () => api.selectStateMachine(sm.id),
812
+ children: [
813
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: sm.name }),
814
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerOpacity, children: t("gameAsset2dEditor.states2", "{states} states").replace(
815
+ "{states}",
816
+ String(sm.states.length)
817
+ ) })
818
+ ]
819
+ },
820
+ sm.id
821
+ )) }),
822
+ activeSM && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
823
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelHeader, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.states", "States") }) }),
824
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelContent, children: [
825
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelSection, children: [
826
+ /* @__PURE__ */ jsxRuntime.jsx(
827
+ ui.NiceTextInput,
828
+ {
829
+ className: GameAsset2dEditor_module.default.panelInput,
830
+ placeholder: t("gameAsset2dEditor.stateName", "State name..."),
831
+ value: newStateName,
832
+ onChange: (val) => setNewStateName(val)
833
+ }
834
+ ),
835
+ allAnimations.length > 0 && newStateName && /* @__PURE__ */ jsxRuntime.jsx(
836
+ ui.NiceSelect,
837
+ {
838
+ className: GameAsset2dEditor_module.default.panelInput,
839
+ style: { marginTop: 4 },
840
+ onChange: (val) => {
841
+ if (val) {
842
+ api.addState(newStateName, val);
843
+ setNewStateName("");
844
+ }
845
+ },
846
+ options: [
847
+ {
848
+ value: "",
849
+ label: t("gameAsset2dEditor.selectAnimation", "Select animation...")
850
+ },
851
+ ...allAnimations.map((anim) => ({
852
+ value: anim.id,
853
+ label: `${anim.sheetName}: ${anim.name}`
854
+ }))
855
+ ]
856
+ }
857
+ )
858
+ ] }),
859
+ activeSM.states.map((state) => /* @__PURE__ */ jsxRuntime.jsxs(
860
+ "div",
861
+ {
862
+ role: "button",
863
+ tabIndex: 0,
864
+ onKeyDown: uiCore.clickOnActivationKey,
865
+ className: `${GameAsset2dEditor_module.default.layerItem} ${api.editorState.selectedStateId === state.id ? GameAsset2dEditor_module.default.selected : ""} ${activeSM.entryStateId === state.id ? GameAsset2dEditor_module.default.entry : ""}`,
866
+ onClick: () => api.selectState(state.id),
867
+ children: [
868
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.default.layerName, children: [
869
+ activeSM.entryStateId === state.id && /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "play", size: 12 }),
870
+ " ",
871
+ state.name
872
+ ] }),
873
+ /* @__PURE__ */ jsxRuntime.jsx(
874
+ ui.NiceButton,
875
+ {
876
+ className: GameAsset2dEditor_module.default.effectRemove,
877
+ variant: "ghost",
878
+ size: "sm",
879
+ onClick: (e) => {
880
+ e.stopPropagation();
881
+ api.removeState(state.id);
882
+ },
883
+ "aria-label": t("gameAsset2dEditor.removeState", "Remove state"),
884
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 })
885
+ }
886
+ )
887
+ ]
888
+ },
889
+ state.id
890
+ ))
891
+ ] })
892
+ ] })
893
+ ] }),
894
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.stateGraph, children: activeSM ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "100%", height: "100%", children: [
895
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx(
896
+ "marker",
897
+ {
898
+ id: "arrowhead",
899
+ markerWidth: "10",
900
+ markerHeight: "7",
901
+ refX: "9",
902
+ refY: "3.5",
903
+ orient: "auto",
904
+ children: /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "var(--nice-text-secondary, #4a5a7e)" })
905
+ }
906
+ ) }),
907
+ activeSM.transitions.map((trans) => {
908
+ const from = activeSM.states.find((s) => s.id === trans.fromStateId);
909
+ const to = activeSM.states.find((s) => s.id === trans.toStateId);
910
+ if (!from || !to) {
911
+ return null;
316
912
  }
317
- return result;
318
- }, [api.project.spriteSheets]);
319
- return (jsxRuntime.jsxs("div", { style: { display: 'flex', flex: 1, overflow: 'hidden' }, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.leftPanel, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelHeader, children: [jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.stateMachines', 'State Machines') }), jsxRuntime.jsx("button", { className: GameAsset2dEditor_module.menuBtn, onClick: () => api.createStateMachine('New State Machine'), children: t('gameAsset2dEditor.new2', '+ New') })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, style: { maxHeight: 150 }, children: api.project.stateMachines.map((sm) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: `${GameAsset2dEditor_module.layerItem} ${api.editorState.activeStateMachineId === sm.id ? GameAsset2dEditor_module.selected : ''}`, onClick: () => api.selectStateMachine(sm.id), children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: sm.name }), jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerOpacity, children: t('gameAsset2dEditor.states2', '{states} states').replace('{states}', String(sm.states.length)) })] }, sm.id))) }), activeSM && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelHeader, children: jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.states', 'States') }) }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelContent, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelSection, children: [jsxRuntime.jsx(ui.NiceTextInput, { className: GameAsset2dEditor_module.panelInput, placeholder: t('gameAsset2dEditor.stateName', 'State name...'), value: newStateName, onChange: (val) => setNewStateName(val) }), allAnimations.length > 0 && newStateName && (jsxRuntime.jsx(ui.NiceSelect, { className: GameAsset2dEditor_module.panelInput, style: { marginTop: 4 }, onChange: (val) => {
320
- if (val) {
321
- api.addState(newStateName, val);
322
- setNewStateName('');
323
- }
324
- }, options: [
325
- {
326
- value: '',
327
- label: t('gameAsset2dEditor.selectAnimation', 'Select animation...'),
328
- },
329
- ...allAnimations.map((anim) => ({
330
- value: anim.id,
331
- label: `${anim.sheetName}: ${anim.name}`,
332
- })),
333
- ] }))] }), activeSM.states.map((state) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: `${GameAsset2dEditor_module.layerItem} ${api.editorState.selectedStateId === state.id ? GameAsset2dEditor_module.selected : ''} ${activeSM.entryStateId === state.id ? GameAsset2dEditor_module.entry : ''}`, onClick: () => api.selectState(state.id), children: [jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.layerName, children: [activeSM.entryStateId === state.id && jsxRuntime.jsx(uiCore.NiceIcon, { name: "play", size: 12 }), ' ', state.name] }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.effectRemove, variant: "ghost", size: "sm", onClick: (e) => {
334
- e.stopPropagation();
335
- api.removeState(state.id);
336
- }, "aria-label": t('gameAsset2dEditor.removeState', 'Remove state'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 }) })] }, state.id)))] })] }))] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.stateGraph, children: activeSM ? (jsxRuntime.jsxs("svg", { width: "100%", height: "100%", children: [jsxRuntime.jsx("defs", { children: jsxRuntime.jsx("marker", { id: "arrowhead", markerWidth: "10", markerHeight: "7", refX: "9", refY: "3.5", orient: "auto", children: jsxRuntime.jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "var(--nice-text-secondary, #4a5a7e)" }) }) }), activeSM.transitions.map((trans) => {
337
- const from = activeSM.states.find((s) => s.id === trans.fromStateId);
338
- const to = activeSM.states.find((s) => s.id === trans.toStateId);
339
- if (!from || !to) {
340
- return null;
341
- }
342
- return (jsxRuntime.jsx("line", { x1: from.position.x + 60, y1: from.position.y + 20, x2: to.position.x + 60, y2: to.position.y + 20, className: GameAsset2dEditor_module.transition, onClick: () => api.removeTransition(trans.id) }, trans.id));
343
- }), activeSM.states.map((state) => {
344
- var _a, _b;
345
- return (jsxRuntime.jsx("foreignObject", { x: state.position.x, y: state.position.y, width: 120, height: 50, children: jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: `${GameAsset2dEditor_module.stateNode} ${api.editorState.selectedStateId === state.id ? GameAsset2dEditor_module.selected : ''} ${activeSM.entryStateId === state.id ? GameAsset2dEditor_module.entry : ''}`, onClick: () => api.selectState(state.id), children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.stateNodeName, children: state.name }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.stateNodeAnim, children: (_b = (_a = allAnimations.find((a) => a.id === state.animationId)) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : t('gameAsset2dEditor.noAnimation', 'No animation') })] }) }, state.id));
346
- })] })) : (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyState, children: jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyStateText, children: t('gameAsset2dEditor.createAStateMachineTo', 'Create a state machine to design animation flows') }) })) }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.rightPanel, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelHeader, children: [jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.parameters', 'Parameters') }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.menuBtn, variant: "ghost", size: "sm", onClick: () => api.addParameter('new_param', 'trigger'), disabled: !activeSM, children: t('gameAsset2dEditor.add', '+ Add') })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, children: activeSM === null || activeSM === void 0 ? void 0 : activeSM.parameters.map((param) => (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.layerItem, children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerOpacity, children: param.type }), jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: param.name }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.effectRemove, variant: "ghost", size: "sm", onClick: () => api.removeParameter(param.id), "aria-label": t('gameAsset2dEditor.removeParameter', 'Remove parameter'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 }) })] }, param.id))) }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelHeader, children: jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.transitions', 'Transitions') }) }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelContent, children: [activeSM === null || activeSM === void 0 ? void 0 : activeSM.transitions.map((trans) => {
347
- var _a, _b;
348
- const from = activeSM.states.find((s) => s.id === trans.fromStateId);
349
- const to = activeSM.states.find((s) => s.id === trans.toStateId);
350
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.layerItem, children: [jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.layerName, children: [(_a = from === null || from === void 0 ? void 0 : from.name) !== null && _a !== void 0 ? _a : '?', " ", jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-right", size: 12 }), " ", (_b = to === null || to === void 0 ? void 0 : to.name) !== null && _b !== void 0 ? _b : '?'] }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.effectRemove, variant: "ghost", size: "sm", onClick: () => api.removeTransition(trans.id), "aria-label": t('gameAsset2dEditor.removeTransition', 'Remove transition'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 }) })] }, trans.id));
351
- }), api.editorState.selectedStateId && (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelSection, style: { marginTop: 12 }, children: [jsxRuntime.jsx("label", { className: GameAsset2dEditor_module.panelLabel, children: t('gameAsset2dEditor.addTransitionTo', 'Add transition to:') }), jsxRuntime.jsx(ui.NiceSelect, { className: GameAsset2dEditor_module.panelInput, onChange: (val) => {
352
- if (val && api.editorState.selectedStateId) {
353
- api.addTransition(api.editorState.selectedStateId, val);
354
- }
355
- }, options: [
356
- {
357
- value: '',
358
- label: t('gameAsset2dEditor.selectTargetState', 'Select target state...'),
359
- },
360
- ...((_a = activeSM === null || activeSM === void 0 ? void 0 : activeSM.states.filter((s) => s.id !== api.editorState.selectedStateId).map((s) => ({ value: s.id, label: s.name }))) !== null && _a !== void 0 ? _a : []),
361
- ] })] }))] })] })] }));
913
+ return /* @__PURE__ */ jsxRuntime.jsx(
914
+ "line",
915
+ {
916
+ x1: from.position.x + 60,
917
+ y1: from.position.y + 20,
918
+ x2: to.position.x + 60,
919
+ y2: to.position.y + 20,
920
+ className: GameAsset2dEditor_module.default.transition,
921
+ onClick: () => api.removeTransition(trans.id)
922
+ },
923
+ trans.id
924
+ );
925
+ }),
926
+ activeSM.states.map((state) => /* @__PURE__ */ jsxRuntime.jsx(
927
+ "foreignObject",
928
+ {
929
+ x: state.position.x,
930
+ y: state.position.y,
931
+ width: 120,
932
+ height: 50,
933
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
934
+ "div",
935
+ {
936
+ role: "button",
937
+ tabIndex: 0,
938
+ onKeyDown: uiCore.clickOnActivationKey,
939
+ className: `${GameAsset2dEditor_module.default.stateNode} ${api.editorState.selectedStateId === state.id ? GameAsset2dEditor_module.default.selected : ""} ${activeSM.entryStateId === state.id ? GameAsset2dEditor_module.default.entry : ""}`,
940
+ onClick: () => api.selectState(state.id),
941
+ children: [
942
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.stateNodeName, children: state.name }),
943
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.stateNodeAnim, children: allAnimations.find((a) => a.id === state.animationId)?.name ?? t("gameAsset2dEditor.noAnimation", "No animation") })
944
+ ]
945
+ }
946
+ )
947
+ },
948
+ state.id
949
+ ))
950
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyState, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyStateText, children: t(
951
+ "gameAsset2dEditor.createAStateMachineTo",
952
+ "Create a state machine to design animation flows"
953
+ ) }) }) }),
954
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.rightPanel, children: [
955
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelHeader, children: [
956
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.parameters", "Parameters") }),
957
+ /* @__PURE__ */ jsxRuntime.jsx(
958
+ ui.NiceButton,
959
+ {
960
+ className: GameAsset2dEditor_module.default.menuBtn,
961
+ variant: "ghost",
962
+ size: "sm",
963
+ onClick: () => api.addParameter("new_param", "trigger"),
964
+ disabled: !activeSM,
965
+ children: t("gameAsset2dEditor.add", "+ Add")
966
+ }
967
+ )
968
+ ] }),
969
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, children: activeSM?.parameters.map((param) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.layerItem, children: [
970
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerOpacity, children: param.type }),
971
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: param.name }),
972
+ /* @__PURE__ */ jsxRuntime.jsx(
973
+ ui.NiceButton,
974
+ {
975
+ className: GameAsset2dEditor_module.default.effectRemove,
976
+ variant: "ghost",
977
+ size: "sm",
978
+ onClick: () => api.removeParameter(param.id),
979
+ "aria-label": t("gameAsset2dEditor.removeParameter", "Remove parameter"),
980
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 })
981
+ }
982
+ )
983
+ ] }, param.id)) }),
984
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelHeader, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.transitions", "Transitions") }) }),
985
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelContent, children: [
986
+ activeSM?.transitions.map((trans) => {
987
+ const from = activeSM.states.find((s) => s.id === trans.fromStateId);
988
+ const to = activeSM.states.find((s) => s.id === trans.toStateId);
989
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.layerItem, children: [
990
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: GameAsset2dEditor_module.default.layerName, children: [
991
+ from?.name ?? "?",
992
+ " ",
993
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-right", size: 12 }),
994
+ " ",
995
+ to?.name ?? "?"
996
+ ] }),
997
+ /* @__PURE__ */ jsxRuntime.jsx(
998
+ ui.NiceButton,
999
+ {
1000
+ className: GameAsset2dEditor_module.default.effectRemove,
1001
+ variant: "ghost",
1002
+ size: "sm",
1003
+ onClick: () => api.removeTransition(trans.id),
1004
+ "aria-label": t("gameAsset2dEditor.removeTransition", "Remove transition"),
1005
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 })
1006
+ }
1007
+ )
1008
+ ] }, trans.id);
1009
+ }),
1010
+ api.editorState.selectedStateId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelSection, style: { marginTop: 12 }, children: [
1011
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: GameAsset2dEditor_module.default.panelLabel, children: t("gameAsset2dEditor.addTransitionTo", "Add transition to:") }),
1012
+ /* @__PURE__ */ jsxRuntime.jsx(
1013
+ ui.NiceSelect,
1014
+ {
1015
+ className: GameAsset2dEditor_module.default.panelInput,
1016
+ onChange: (val) => {
1017
+ if (val && api.editorState.selectedStateId) {
1018
+ api.addTransition(api.editorState.selectedStateId, val);
1019
+ }
1020
+ },
1021
+ options: [
1022
+ {
1023
+ value: "",
1024
+ label: t("gameAsset2dEditor.selectTargetState", "Select target state...")
1025
+ },
1026
+ ...activeSM?.states.filter((s) => s.id !== api.editorState.selectedStateId).map((s) => ({ value: s.id, label: s.name })) ?? []
1027
+ ]
1028
+ }
1029
+ )
1030
+ ] })
1031
+ ] })
1032
+ ] })
1033
+ ] });
362
1034
  };
363
- /* ────────────────────────────────────────────────────────────────
364
- EFFECTS PANEL
365
- ──────────────────────────────────────────────────────────────── */
366
1035
  const EffectsView = ({ api }) => {
367
- const { t } = i18n.useNiceTranslation();
368
- const [_currentEffects, _setCurrentEffects] = React.useState([]);
369
- const [presetName, setPresetName] = React.useState('');
370
- const effectTypes = [
371
- { type: 'brightness', label: t('gameAsset2dEditor.brightness', 'Brightness') },
372
- { type: 'contrast', label: t('gameAsset2dEditor.contrast', 'Contrast') },
373
- { type: 'saturation', label: t('gameAsset2dEditor.saturation', 'Saturation') },
374
- { type: 'hue-shift', label: t('gameAsset2dEditor.hueShift', 'Hue Shift') },
375
- { type: 'invert', label: t('gameAsset2dEditor.invert', 'Invert') },
376
- { type: 'pixelate', label: t('gameAsset2dEditor.pixelate', 'Pixelate') },
377
- { type: 'outline', label: t('gameAsset2dEditor.outline', 'Outline') },
378
- { type: 'tint', label: t('gameAsset2dEditor.tint', 'Tint') },
379
- { type: 'blur', label: t('gameAsset2dEditor.blur', 'Blur') },
380
- { type: 'glow', label: t('gameAsset2dEditor.glow', 'Glow') },
381
- { type: 'shadow', label: t('gameAsset2dEditor.shadow', 'Shadow') },
382
- { type: 'palette-swap', label: t('gameAsset2dEditor.paletteSwap', 'Palette Swap') },
383
- ];
384
- return (jsxRuntime.jsxs("div", { style: { display: 'flex', flex: 1, overflow: 'hidden' }, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.leftPanel, children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelHeader, children: jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.addEffect', 'Add Effect') }) }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, children: effectTypes.map(({ type, label }) => (jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.layerItem, variant: "ghost", onClick: () => api.addEffect(type), style: { cursor: 'pointer', border: 'none', textAlign: 'left' }, children: jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: label }) }, type))) }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelHeader, children: jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.presets', 'Presets') }) }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelContent, children: [jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.panelSection, children: [jsxRuntime.jsx(ui.NiceTextInput, { className: GameAsset2dEditor_module.panelInput, placeholder: t('gameAsset2dEditor.presetName', 'Preset name...'), value: presetName, onChange: (val) => setPresetName(val) }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.btnSecondary, variant: "ghost", style: { marginTop: 4, width: '100%' }, onClick: () => {
385
- if (presetName) {
386
- api.saveEffectPreset(presetName);
387
- setPresetName('');
388
- }
389
- }, disabled: !presetName, children: t('gameAsset2dEditor.saveCurrentEffects', 'Save Current Effects') })] }), api.project.effectPresets.map((preset) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, className: GameAsset2dEditor_module.layerItem, onClick: () => api.loadEffectPreset(preset.id), style: { cursor: 'pointer' }, children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerName, children: preset.name }), jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.layerOpacity, children: t('gameAsset2dEditor.effects', '{effects} effects').replace('{effects}', String(preset.effects.length)) })] }, preset.id)))] })] }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.viewport, children: jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyState, children: jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyStateText, children: t('gameAsset2dEditor.selectASpriteOrTile', 'Select a sprite or tile to preview effects') }) }) }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.rightPanel, children: [jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelHeader, children: jsxRuntime.jsx("span", { children: t('gameAsset2dEditor.activeEffects', 'Active Effects') }) }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.panelContent, children: jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.effectsList, children: jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyState, children: jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.emptyStateText, children: t('gameAsset2dEditor.addEffectsFromTheLeft', 'Add effects from the left panel') }) }) }) })] })] }));
1036
+ const { t } = i18n.useNiceTranslation();
1037
+ const [_currentEffects, _setCurrentEffects] = React.useState([]);
1038
+ const [presetName, setPresetName] = React.useState("");
1039
+ const effectTypes = [
1040
+ { type: "brightness", label: t("gameAsset2dEditor.brightness", "Brightness") },
1041
+ { type: "contrast", label: t("gameAsset2dEditor.contrast", "Contrast") },
1042
+ { type: "saturation", label: t("gameAsset2dEditor.saturation", "Saturation") },
1043
+ { type: "hue-shift", label: t("gameAsset2dEditor.hueShift", "Hue Shift") },
1044
+ { type: "invert", label: t("gameAsset2dEditor.invert", "Invert") },
1045
+ { type: "pixelate", label: t("gameAsset2dEditor.pixelate", "Pixelate") },
1046
+ { type: "outline", label: t("gameAsset2dEditor.outline", "Outline") },
1047
+ { type: "tint", label: t("gameAsset2dEditor.tint", "Tint") },
1048
+ { type: "blur", label: t("gameAsset2dEditor.blur", "Blur") },
1049
+ { type: "glow", label: t("gameAsset2dEditor.glow", "Glow") },
1050
+ { type: "shadow", label: t("gameAsset2dEditor.shadow", "Shadow") },
1051
+ { type: "palette-swap", label: t("gameAsset2dEditor.paletteSwap", "Palette Swap") }
1052
+ ];
1053
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flex: 1, overflow: "hidden" }, children: [
1054
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.leftPanel, children: [
1055
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelHeader, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.addEffect", "Add Effect") }) }),
1056
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, children: effectTypes.map(({ type, label }) => /* @__PURE__ */ jsxRuntime.jsx(
1057
+ ui.NiceButton,
1058
+ {
1059
+ className: GameAsset2dEditor_module.default.layerItem,
1060
+ variant: "ghost",
1061
+ onClick: () => api.addEffect(type),
1062
+ style: { cursor: "pointer", border: "none", textAlign: "left" },
1063
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: label })
1064
+ },
1065
+ type
1066
+ )) }),
1067
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelHeader, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.presets", "Presets") }) }),
1068
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelContent, children: [
1069
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.panelSection, children: [
1070
+ /* @__PURE__ */ jsxRuntime.jsx(
1071
+ ui.NiceTextInput,
1072
+ {
1073
+ className: GameAsset2dEditor_module.default.panelInput,
1074
+ placeholder: t("gameAsset2dEditor.presetName", "Preset name..."),
1075
+ value: presetName,
1076
+ onChange: (val) => setPresetName(val)
1077
+ }
1078
+ ),
1079
+ /* @__PURE__ */ jsxRuntime.jsx(
1080
+ ui.NiceButton,
1081
+ {
1082
+ className: GameAsset2dEditor_module.default.btnSecondary,
1083
+ variant: "ghost",
1084
+ style: { marginTop: 4, width: "100%" },
1085
+ onClick: () => {
1086
+ if (presetName) {
1087
+ api.saveEffectPreset(presetName);
1088
+ setPresetName("");
1089
+ }
1090
+ },
1091
+ disabled: !presetName,
1092
+ children: t("gameAsset2dEditor.saveCurrentEffects", "Save Current Effects")
1093
+ }
1094
+ )
1095
+ ] }),
1096
+ api.project.effectPresets.map((preset) => /* @__PURE__ */ jsxRuntime.jsxs(
1097
+ "div",
1098
+ {
1099
+ role: "button",
1100
+ tabIndex: 0,
1101
+ onKeyDown: uiCore.clickOnActivationKey,
1102
+ className: GameAsset2dEditor_module.default.layerItem,
1103
+ onClick: () => api.loadEffectPreset(preset.id),
1104
+ style: { cursor: "pointer" },
1105
+ children: [
1106
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerName, children: preset.name }),
1107
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.layerOpacity, children: t("gameAsset2dEditor.effects", "{effects} effects").replace(
1108
+ "{effects}",
1109
+ String(preset.effects.length)
1110
+ ) })
1111
+ ]
1112
+ },
1113
+ preset.id
1114
+ ))
1115
+ ] })
1116
+ ] }),
1117
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.viewport, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyState, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyStateText, children: t(
1118
+ "gameAsset2dEditor.selectASpriteOrTile",
1119
+ "Select a sprite or tile to preview effects"
1120
+ ) }) }) }),
1121
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.rightPanel, children: [
1122
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelHeader, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: t("gameAsset2dEditor.activeEffects", "Active Effects") }) }),
1123
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.panelContent, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.effectsList, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyState, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.emptyStateText, children: t("gameAsset2dEditor.addEffectsFromTheLeft", "Add effects from the left panel") }) }) }) })
1124
+ ] })
1125
+ ] });
390
1126
  };
391
- /* ────────────────────────────────────────────────────────────────
392
- STATUS BAR
393
- ──────────────────────────────────────────────────────────────── */
394
1127
  const StatusBar = ({ api }) => {
395
- const { t } = i18n.useNiceTranslation();
396
- const activeMap = api.project.tileMaps.find((m) => m.id === api.editorState.activeTileMapId);
397
- const activeSheet = api.project.spriteSheets.find((s) => s.id === api.editorState.activeSpriteSheetId);
398
- return (jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.statusBar, children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.statusItem, children: t('gameAsset2dEditor.mode', 'Mode: {mode}').replace('{mode}', String(api.editorState.mode)) }), api.editorState.mode === 'tilemap' && activeMap && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.statusItem, children: t('gameAsset2dEditor.map', 'Map: {name} ({width}×{height})')
399
- .replace('{name}', String(activeMap.name))
400
- .replace('{width}', String(activeMap.width))
401
- .replace('{height}', String(activeMap.height)) }), jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.statusItem, children: t('gameAsset2dEditor.tilePx', 'Tile: {tileWidth}×{tileHeight}px')
402
- .replace('{tileWidth}', String(activeMap.tileWidth))
403
- .replace('{tileHeight}', String(activeMap.tileHeight)) })] })), api.editorState.mode === 'spritesheet' && activeSheet && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.statusItem, children: t('gameAsset2dEditor.sheet', 'Sheet: {name}').replace('{name}', String(activeSheet.name)) }), jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.statusItem, children: t('gameAsset2dEditor.selectedFrames', 'Selected: {selectedFrameIds} frames').replace('{selectedFrameIds}', String(api.editorState.selectedFrameIds.length)) })] })), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.zoomControl, children: [jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.zoomBtn, variant: "ghost", size: "sm", onClick: () => api.setZoom(api.editorState.zoom - 0.25), children: "\u2212" }), jsxRuntime.jsxs("span", { children: [Math.round(api.editorState.zoom * 100), "%"] }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.zoomBtn, variant: "ghost", size: "sm", onClick: () => api.setZoom(api.editorState.zoom + 0.25), children: "+" }), jsxRuntime.jsx(ui.NiceButton, { className: GameAsset2dEditor_module.zoomBtn, variant: "ghost", size: "sm", onClick: () => api.setZoom(1), children: "\u2299" })] })] }));
404
- };
405
- /* ────────────────────────────────────────────────────────────────
406
- MAIN COMPONENT
407
- ──────────────────────────────────────────────────────────────── */
408
- const NiceGameAsset2dEditor = ({ className, onSave, onExport, }) => {
409
- const api = useGameAssetEditor.useGameAssetEditor({ onSave, onExport });
410
- const renderModeContent = () => {
411
- switch (api.editorState.mode) {
412
- case 'tilemap':
413
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(TileMapToolbar, { api: api }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.mainArea, children: [jsxRuntime.jsx(TilePalette, { api: api }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.centerArea, children: jsxRuntime.jsx(TileMapCanvas, { api: api }) }), jsxRuntime.jsx(LayersPanel, { api: api })] })] }));
414
- case 'spritesheet':
415
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(SpriteSheetToolbar, { api: api }), jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.mainArea, children: [jsxRuntime.jsx(SpriteSheetsList, { api: api }), jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.centerArea, children: jsxRuntime.jsx(SpriteSheetCanvas, { api: api }) }), jsxRuntime.jsx(FramesPanel, { api: api })] })] }));
416
- case 'animation':
417
- return (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.mainArea, children: jsxRuntime.jsx(AnimationStateMachineView, { api: api }) }));
418
- case 'effects':
419
- return (jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.mainArea, children: jsxRuntime.jsx(EffectsView, { api: api }) }));
420
- default:
421
- return null;
1128
+ const { t } = i18n.useNiceTranslation();
1129
+ const activeMap = api.project.tileMaps.find((m) => m.id === api.editorState.activeTileMapId);
1130
+ const activeSheet = api.project.spriteSheets.find(
1131
+ (s) => s.id === api.editorState.activeSpriteSheetId
1132
+ );
1133
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.statusBar, children: [
1134
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.statusItem, children: t("gameAsset2dEditor.mode", "Mode: {mode}").replace(
1135
+ "{mode}",
1136
+ String(api.editorState.mode)
1137
+ ) }),
1138
+ api.editorState.mode === "tilemap" && activeMap && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1139
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.statusItem, children: t("gameAsset2dEditor.map", "Map: {name} ({width}×{height})").replace("{name}", String(activeMap.name)).replace("{width}", String(activeMap.width)).replace("{height}", String(activeMap.height)) }),
1140
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.statusItem, children: t("gameAsset2dEditor.tilePx", "Tile: {tileWidth}×{tileHeight}px").replace("{tileWidth}", String(activeMap.tileWidth)).replace("{tileHeight}", String(activeMap.tileHeight)) })
1141
+ ] }),
1142
+ api.editorState.mode === "spritesheet" && activeSheet && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1143
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.statusItem, children: t("gameAsset2dEditor.sheet", "Sheet: {name}").replace(
1144
+ "{name}",
1145
+ String(activeSheet.name)
1146
+ ) }),
1147
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: GameAsset2dEditor_module.default.statusItem, children: t("gameAsset2dEditor.selectedFrames", "Selected: {selectedFrameIds} frames").replace(
1148
+ "{selectedFrameIds}",
1149
+ String(api.editorState.selectedFrameIds.length)
1150
+ ) })
1151
+ ] }),
1152
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.zoomControl, children: [
1153
+ /* @__PURE__ */ jsxRuntime.jsx(
1154
+ ui.NiceButton,
1155
+ {
1156
+ className: GameAsset2dEditor_module.default.zoomBtn,
1157
+ variant: "ghost",
1158
+ size: "sm",
1159
+ onClick: () => api.setZoom(api.editorState.zoom - 0.25),
1160
+ children: "−"
1161
+ }
1162
+ ),
1163
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1164
+ Math.round(api.editorState.zoom * 100),
1165
+ "%"
1166
+ ] }),
1167
+ /* @__PURE__ */ jsxRuntime.jsx(
1168
+ ui.NiceButton,
1169
+ {
1170
+ className: GameAsset2dEditor_module.default.zoomBtn,
1171
+ variant: "ghost",
1172
+ size: "sm",
1173
+ onClick: () => api.setZoom(api.editorState.zoom + 0.25),
1174
+ children: "+"
1175
+ }
1176
+ ),
1177
+ /* @__PURE__ */ jsxRuntime.jsx(
1178
+ ui.NiceButton,
1179
+ {
1180
+ className: GameAsset2dEditor_module.default.zoomBtn,
1181
+ variant: "ghost",
1182
+ size: "sm",
1183
+ onClick: () => api.setZoom(1),
1184
+ children: "⊙"
422
1185
  }
423
- };
424
- return (jsxRuntime.jsx(ui.NiceAppShell, { className: `${GameAsset2dEditor_module.root} ${className || ''}`, flush: true, menubar: jsxRuntime.jsx(MenuBar, { api: api }), toolbar: jsxRuntime.jsx(ModeTabs, { api: api }), statusBar: jsxRuntime.jsx(StatusBar, { api: api }), children: jsxRuntime.jsx("div", { style: { display: 'flex', flexDirection: 'column', minHeight: 0, height: '100%' }, children: renderModeContent() }) }));
1186
+ )
1187
+ ] })
1188
+ ] });
1189
+ };
1190
+ const NiceGameAsset2dEditor = ({
1191
+ className,
1192
+ onSave,
1193
+ onExport
1194
+ }) => {
1195
+ const api = useGameAssetEditor.useGameAssetEditor({ onSave, onExport });
1196
+ const renderModeContent = () => {
1197
+ switch (api.editorState.mode) {
1198
+ case "tilemap":
1199
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1200
+ /* @__PURE__ */ jsxRuntime.jsx(TileMapToolbar, { api }),
1201
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.mainArea, children: [
1202
+ /* @__PURE__ */ jsxRuntime.jsx(TilePalette, { api }),
1203
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.centerArea, children: /* @__PURE__ */ jsxRuntime.jsx(TileMapCanvas, { api }) }),
1204
+ /* @__PURE__ */ jsxRuntime.jsx(LayersPanel, { api })
1205
+ ] })
1206
+ ] });
1207
+ case "spritesheet":
1208
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1209
+ /* @__PURE__ */ jsxRuntime.jsx(SpriteSheetToolbar, { api }),
1210
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: GameAsset2dEditor_module.default.mainArea, children: [
1211
+ /* @__PURE__ */ jsxRuntime.jsx(SpriteSheetsList, { api }),
1212
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.centerArea, children: /* @__PURE__ */ jsxRuntime.jsx(SpriteSheetCanvas, { api }) }),
1213
+ /* @__PURE__ */ jsxRuntime.jsx(FramesPanel, { api })
1214
+ ] })
1215
+ ] });
1216
+ case "animation":
1217
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.mainArea, children: /* @__PURE__ */ jsxRuntime.jsx(AnimationStateMachineView, { api }) });
1218
+ case "effects":
1219
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: GameAsset2dEditor_module.default.mainArea, children: /* @__PURE__ */ jsxRuntime.jsx(EffectsView, { api }) });
1220
+ default:
1221
+ return null;
1222
+ }
1223
+ };
1224
+ return /* @__PURE__ */ jsxRuntime.jsx(
1225
+ ui.NiceAppShell,
1226
+ {
1227
+ className: `${GameAsset2dEditor_module.default.root} ${className || ""}`,
1228
+ flush: true,
1229
+ menubar: /* @__PURE__ */ jsxRuntime.jsx(MenuBar, { api }),
1230
+ toolbar: /* @__PURE__ */ jsxRuntime.jsx(ModeTabs, { api }),
1231
+ statusBar: /* @__PURE__ */ jsxRuntime.jsx(StatusBar, { api }),
1232
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", minHeight: 0, height: "100%" }, children: renderModeContent() })
1233
+ }
1234
+ );
425
1235
  };
426
-
427
1236
  exports.NiceGameAsset2dEditor = NiceGameAsset2dEditor;