@nice2dev/ui-graphics 1.1.0 → 1.1.1

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 (391) hide show
  1. package/dist/cjs/animation/AnimatedPerson.js +69 -63
  2. package/dist/cjs/animation/AnimatedPerson.js.map +1 -1
  3. package/dist/cjs/animation/AnimationEditor.js +27 -20
  4. package/dist/cjs/animation/AnimationEditor.js.map +1 -1
  5. package/dist/cjs/animation/Audience.js +17 -11
  6. package/dist/cjs/animation/Audience.js.map +1 -1
  7. package/dist/cjs/animation/BodyRenderer.js +7 -7
  8. package/dist/cjs/animation/BodyRenderer.js.map +1 -1
  9. package/dist/cjs/animation/animationHelper.js +83 -52
  10. package/dist/cjs/animation/animationHelper.js.map +1 -1
  11. package/dist/cjs/animation/characterTypes.js +171 -30
  12. package/dist/cjs/animation/characterTypes.js.map +1 -1
  13. package/dist/cjs/animation/choreoDSL.js +114 -62
  14. package/dist/cjs/animation/choreoDSL.js.map +1 -1
  15. package/dist/cjs/animation/karaokeIntegration.js +10 -11
  16. package/dist/cjs/animation/karaokeIntegration.js.map +1 -1
  17. package/dist/cjs/animation/lottieExport.js +15 -9
  18. package/dist/cjs/animation/lottieExport.js.map +1 -1
  19. package/dist/cjs/animation/motionPath.js +125 -30
  20. package/dist/cjs/animation/motionPath.js.map +1 -1
  21. package/dist/cjs/animation/physics.js +157 -57
  22. package/dist/cjs/animation/physics.js.map +1 -1
  23. package/dist/cjs/animation/rig/RigPlayer.js +7 -6
  24. package/dist/cjs/animation/rig/RigPlayer.js.map +1 -1
  25. package/dist/cjs/animation/rig/RiggedBody.js +7 -7
  26. package/dist/cjs/animation/rig/RiggedBody.js.map +1 -1
  27. package/dist/cjs/animation/rig/choreoRigBridge.js +52 -29
  28. package/dist/cjs/animation/rig/choreoRigBridge.js.map +1 -1
  29. package/dist/cjs/animation/rig/poseOps.js +6 -3
  30. package/dist/cjs/animation/rig/poseOps.js.map +1 -1
  31. package/dist/cjs/animation/shapes/arms.js +7 -6
  32. package/dist/cjs/animation/shapes/arms.js.map +1 -1
  33. package/dist/cjs/animation/shapes/eyes.js +31 -18
  34. package/dist/cjs/animation/shapes/eyes.js.map +1 -1
  35. package/dist/cjs/animation/shapes/hair.js +39 -23
  36. package/dist/cjs/animation/shapes/hair.js.map +1 -1
  37. package/dist/cjs/animation/shapes/heads.js +47 -29
  38. package/dist/cjs/animation/shapes/heads.js.map +1 -1
  39. package/dist/cjs/animation/shapes/headwear.js +26 -14
  40. package/dist/cjs/animation/shapes/headwear.js.map +1 -1
  41. package/dist/cjs/animation/shapes/legs.js +7 -6
  42. package/dist/cjs/animation/shapes/legs.js.map +1 -1
  43. package/dist/cjs/animation/shapes/mouths.js +28 -18
  44. package/dist/cjs/animation/shapes/mouths.js.map +1 -1
  45. package/dist/cjs/animation/shapes/noses.js +18 -9
  46. package/dist/cjs/animation/shapes/noses.js.map +1 -1
  47. package/dist/cjs/animation/shapes/outfits.js +25 -14
  48. package/dist/cjs/animation/shapes/outfits.js.map +1 -1
  49. package/dist/cjs/animation/shapes/torsos.js +5 -4
  50. package/dist/cjs/animation/shapes/torsos.js.map +1 -1
  51. package/dist/cjs/animation/spineExport.js +33 -26
  52. package/dist/cjs/animation/spineExport.js.map +1 -1
  53. package/dist/cjs/core/LocalUI.js +16 -16
  54. package/dist/cjs/core/LocalUI.js.map +1 -1
  55. package/dist/cjs/core/NiceBrushEngine.js +205 -69
  56. package/dist/cjs/core/NiceBrushEngine.js.map +1 -1
  57. package/dist/cjs/core/collaboration.js +35 -21
  58. package/dist/cjs/core/collaboration.js.map +1 -1
  59. package/dist/cjs/core/colorBlindness.js +64 -24
  60. package/dist/cjs/core/colorBlindness.js.map +1 -1
  61. package/dist/cjs/core/dragDrop.js +34 -26
  62. package/dist/cjs/core/dragDrop.js.map +1 -1
  63. package/dist/cjs/core/fixes.js +26 -14
  64. package/dist/cjs/core/fixes.js.map +1 -1
  65. package/dist/cjs/core/gridGuides.js +24 -16
  66. package/dist/cjs/core/gridGuides.js.map +1 -1
  67. package/dist/cjs/core/historyVisual.js +42 -23
  68. package/dist/cjs/core/historyVisual.js.map +1 -1
  69. package/dist/cjs/core/integrations.js +65 -48
  70. package/dist/cjs/core/integrations.js.map +1 -1
  71. package/dist/cjs/core/minimap.js +40 -24
  72. package/dist/cjs/core/minimap.js.map +1 -1
  73. package/dist/cjs/core/plugins.js +10 -6
  74. package/dist/cjs/core/plugins.js.map +1 -1
  75. package/dist/cjs/core/rtl.js +32 -27
  76. package/dist/cjs/core/rtl.js.map +1 -1
  77. package/dist/cjs/core/shortcuts.js +77 -39
  78. package/dist/cjs/core/shortcuts.js.map +1 -1
  79. package/dist/cjs/core/theme.js +68 -61
  80. package/dist/cjs/core/theme.js.map +1 -1
  81. package/dist/cjs/core/yjsCollaboration.js +61 -28
  82. package/dist/cjs/core/yjsCollaboration.js.map +1 -1
  83. package/dist/cjs/font/NiceFontEditor.js +160 -57
  84. package/dist/cjs/font/NiceFontEditor.js.map +1 -1
  85. package/dist/cjs/font/fontFormatUtils.js +37 -24
  86. package/dist/cjs/font/fontFormatUtils.js.map +1 -1
  87. package/dist/cjs/game/GameAsset2dEditor.js +73 -60
  88. package/dist/cjs/game/GameAsset2dEditor.js.map +1 -1
  89. package/dist/cjs/game/gameAssetUtils.js +18 -13
  90. package/dist/cjs/game/gameAssetUtils.js.map +1 -1
  91. package/dist/cjs/game/useGameAssetEditor.js +160 -143
  92. package/dist/cjs/game/useGameAssetEditor.js.map +1 -1
  93. package/dist/cjs/icon/NiceIconEditor.js +329 -106
  94. package/dist/cjs/icon/NiceIconEditor.js.map +1 -1
  95. package/dist/cjs/packages/ui/dist/NiceErrorBoundary-D75yr_WE.js +572 -0
  96. package/dist/cjs/packages/ui/dist/NiceErrorBoundary-D75yr_WE.js.map +1 -0
  97. package/dist/cjs/packages/ui/dist/NiceForm-CKoJA6NG.js +4979 -0
  98. package/dist/cjs/packages/ui/dist/NiceForm-CKoJA6NG.js.map +1 -0
  99. package/dist/cjs/packages/ui/dist/NiceModal-1QX7NhyH.js +98 -0
  100. package/dist/cjs/packages/ui/dist/NiceModal-1QX7NhyH.js.map +1 -0
  101. package/dist/cjs/packages/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js +5244 -0
  102. package/dist/cjs/packages/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js.map +1 -0
  103. package/dist/cjs/packages/ui/dist/NicePagination-DbE-uOkl.js +174 -0
  104. package/dist/cjs/packages/ui/dist/NicePagination-DbE-uOkl.js.map +1 -0
  105. package/dist/cjs/packages/ui/dist/NicePinCodeInput-B8cI8zu8.js +10459 -0
  106. package/dist/cjs/packages/ui/dist/NicePinCodeInput-B8cI8zu8.js.map +1 -0
  107. package/dist/cjs/packages/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js +6313 -0
  108. package/dist/cjs/packages/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js.map +1 -0
  109. package/dist/cjs/packages/ui/dist/NiceTabs-DzLHzwuA.js +1639 -0
  110. package/dist/cjs/packages/ui/dist/NiceTabs-DzLHzwuA.js.map +1 -0
  111. package/dist/cjs/packages/ui/dist/NiceWindow-DeC83yfE.js +807 -0
  112. package/dist/cjs/packages/ui/dist/NiceWindow-DeC83yfE.js.map +1 -0
  113. package/dist/cjs/packages/ui/dist/charts-BAS21jkC.js +3833 -0
  114. package/dist/cjs/packages/ui/dist/charts-BAS21jkC.js.map +1 -0
  115. package/dist/cjs/packages/ui/dist/core-Da43q-pO.js +11683 -0
  116. package/dist/cjs/packages/ui/dist/core-Da43q-pO.js.map +1 -0
  117. package/dist/cjs/packages/ui/dist/index-pAuGTbuB.js +28876 -0
  118. package/dist/cjs/packages/ui/dist/index-pAuGTbuB.js.map +1 -0
  119. package/dist/cjs/photo/FilterThumb.js +7 -5
  120. package/dist/cjs/photo/FilterThumb.js.map +1 -1
  121. package/dist/cjs/photo/NiceAITools.js +78 -32
  122. package/dist/cjs/photo/NiceAITools.js.map +1 -1
  123. package/dist/cjs/photo/PhotoEditor.js +4 -4
  124. package/dist/cjs/photo/PhotoEditor.js.map +1 -1
  125. package/dist/cjs/photo/PhotoEditorCanvas.js +56 -22
  126. package/dist/cjs/photo/PhotoEditorCanvas.js.map +1 -1
  127. package/dist/cjs/photo/PhotoEditorLeftPanel.js +106 -48
  128. package/dist/cjs/photo/PhotoEditorLeftPanel.js.map +1 -1
  129. package/dist/cjs/photo/PhotoEditorToolbar.js +2 -2
  130. package/dist/cjs/photo/PhotoEditorToolbar.js.map +1 -1
  131. package/dist/cjs/photo/photoEditorActions.js +27 -18
  132. package/dist/cjs/photo/photoEditorActions.js.map +1 -1
  133. package/dist/cjs/photo/photoFilters.js +316 -81
  134. package/dist/cjs/photo/photoFilters.js.map +1 -1
  135. package/dist/cjs/photo/photoOverlays.js +521 -165
  136. package/dist/cjs/photo/photoOverlays.js.map +1 -1
  137. package/dist/cjs/photo/photoSelection.js +69 -35
  138. package/dist/cjs/photo/photoSelection.js.map +1 -1
  139. package/dist/cjs/photo/usePhotoEditor.js +203 -97
  140. package/dist/cjs/photo/usePhotoEditor.js.map +1 -1
  141. package/dist/cjs/pixel/HSVPicker.js +32 -19
  142. package/dist/cjs/pixel/HSVPicker.js.map +1 -1
  143. package/dist/cjs/pixel/PixelEditor.js +25 -14
  144. package/dist/cjs/pixel/PixelEditor.js.map +1 -1
  145. package/dist/cjs/pixel/PixelEditorCanvas.js +2 -2
  146. package/dist/cjs/pixel/PixelEditorCanvas.js.map +1 -1
  147. package/dist/cjs/pixel/PixelEditorMenuBar.js +3 -3
  148. package/dist/cjs/pixel/PixelEditorMenuBar.js.map +1 -1
  149. package/dist/cjs/pixel/PixelEditorRightPanel.js +28 -8
  150. package/dist/cjs/pixel/PixelEditorRightPanel.js.map +1 -1
  151. package/dist/cjs/pixel/PixelEditorStatusBar.js +2 -2
  152. package/dist/cjs/pixel/PixelEditorStatusBar.js.map +1 -1
  153. package/dist/cjs/pixel/PixelEditorTimeline.js +3 -4
  154. package/dist/cjs/pixel/PixelEditorTimeline.js.map +1 -1
  155. package/dist/cjs/pixel/PixelEditorToolbar.js +3 -3
  156. package/dist/cjs/pixel/PixelEditorToolbar.js.map +1 -1
  157. package/dist/cjs/pixel/SpriteGeneratorPanel.js +136 -54
  158. package/dist/cjs/pixel/SpriteGeneratorPanel.js.map +1 -1
  159. package/dist/cjs/pixel/asepriteFormat.js +122 -38
  160. package/dist/cjs/pixel/asepriteFormat.js.map +1 -1
  161. package/dist/cjs/pixel/characterGeneratorPresets.js +208 -54
  162. package/dist/cjs/pixel/characterGeneratorPresets.js.map +1 -1
  163. package/dist/cjs/pixel/pixelEditorExports.js +42 -35
  164. package/dist/cjs/pixel/pixelEditorExports.js.map +1 -1
  165. package/dist/cjs/pixel/pixelEditorTypes.js +67 -33
  166. package/dist/cjs/pixel/pixelEditorTypes.js.map +1 -1
  167. package/dist/cjs/pixel/pixelEditorUtils.js +62 -38
  168. package/dist/cjs/pixel/pixelEditorUtils.js.map +1 -1
  169. package/dist/cjs/pixel/spriteGeneratorCore.js +47 -24
  170. package/dist/cjs/pixel/spriteGeneratorCore.js.map +1 -1
  171. package/dist/cjs/pixel/usePixelEditor.js +475 -213
  172. package/dist/cjs/pixel/usePixelEditor.js.map +1 -1
  173. package/dist/cjs/texture/Nice3DTexturePainter.js +201 -71
  174. package/dist/cjs/texture/Nice3DTexturePainter.js.map +1 -1
  175. package/dist/cjs/ui/NiceUIDesigner.js +280 -91
  176. package/dist/cjs/ui/NiceUIDesigner.js.map +1 -1
  177. package/dist/cjs/vector/NiceSvgToCode.js +96 -34
  178. package/dist/cjs/vector/NiceSvgToCode.js.map +1 -1
  179. package/dist/cjs/vector/VectorEditor.js +14 -13
  180. package/dist/cjs/vector/VectorEditor.js.map +1 -1
  181. package/dist/cjs/vector/VectorEditorMenuBar.js +7 -6
  182. package/dist/cjs/vector/VectorEditorMenuBar.js.map +1 -1
  183. package/dist/cjs/vector/VectorEditorRightPanel.js +87 -32
  184. package/dist/cjs/vector/VectorEditorRightPanel.js.map +1 -1
  185. package/dist/cjs/vector/VectorEditorShapeRenderer.js +17 -15
  186. package/dist/cjs/vector/VectorEditorShapeRenderer.js.map +1 -1
  187. package/dist/cjs/vector/VectorEditorStatusBar.js.map +1 -1
  188. package/dist/cjs/vector/useVectorEditor.js +312 -122
  189. package/dist/cjs/vector/useVectorEditor.js.map +1 -1
  190. package/dist/cjs/vector/vectorBooleanOps.js +60 -42
  191. package/dist/cjs/vector/vectorBooleanOps.js.map +1 -1
  192. package/dist/cjs/vector/vectorEditorExport.js +40 -34
  193. package/dist/cjs/vector/vectorEditorExport.js.map +1 -1
  194. package/dist/cjs/vector/vectorGradients.js +41 -40
  195. package/dist/cjs/vector/vectorGradients.js.map +1 -1
  196. package/dist/esm/animation/AnimatedPerson.js +69 -63
  197. package/dist/esm/animation/AnimatedPerson.js.map +1 -1
  198. package/dist/esm/animation/AnimationEditor.js +27 -20
  199. package/dist/esm/animation/AnimationEditor.js.map +1 -1
  200. package/dist/esm/animation/Audience.js +17 -11
  201. package/dist/esm/animation/Audience.js.map +1 -1
  202. package/dist/esm/animation/BodyRenderer.js +7 -7
  203. package/dist/esm/animation/BodyRenderer.js.map +1 -1
  204. package/dist/esm/animation/animationHelper.js +83 -52
  205. package/dist/esm/animation/animationHelper.js.map +1 -1
  206. package/dist/esm/animation/characterTypes.js +171 -30
  207. package/dist/esm/animation/characterTypes.js.map +1 -1
  208. package/dist/esm/animation/choreoDSL.js +114 -62
  209. package/dist/esm/animation/choreoDSL.js.map +1 -1
  210. package/dist/esm/animation/karaokeIntegration.js +10 -11
  211. package/dist/esm/animation/karaokeIntegration.js.map +1 -1
  212. package/dist/esm/animation/lottieExport.js +15 -9
  213. package/dist/esm/animation/lottieExport.js.map +1 -1
  214. package/dist/esm/animation/motionPath.js +125 -30
  215. package/dist/esm/animation/motionPath.js.map +1 -1
  216. package/dist/esm/animation/physics.js +157 -57
  217. package/dist/esm/animation/physics.js.map +1 -1
  218. package/dist/esm/animation/rig/RigPlayer.js +7 -6
  219. package/dist/esm/animation/rig/RigPlayer.js.map +1 -1
  220. package/dist/esm/animation/rig/RiggedBody.js +7 -7
  221. package/dist/esm/animation/rig/RiggedBody.js.map +1 -1
  222. package/dist/esm/animation/rig/choreoRigBridge.js +52 -29
  223. package/dist/esm/animation/rig/choreoRigBridge.js.map +1 -1
  224. package/dist/esm/animation/rig/poseOps.js +6 -3
  225. package/dist/esm/animation/rig/poseOps.js.map +1 -1
  226. package/dist/esm/animation/shapes/arms.js +7 -6
  227. package/dist/esm/animation/shapes/arms.js.map +1 -1
  228. package/dist/esm/animation/shapes/eyes.js +31 -18
  229. package/dist/esm/animation/shapes/eyes.js.map +1 -1
  230. package/dist/esm/animation/shapes/hair.js +39 -23
  231. package/dist/esm/animation/shapes/hair.js.map +1 -1
  232. package/dist/esm/animation/shapes/heads.js +47 -29
  233. package/dist/esm/animation/shapes/heads.js.map +1 -1
  234. package/dist/esm/animation/shapes/headwear.js +26 -14
  235. package/dist/esm/animation/shapes/headwear.js.map +1 -1
  236. package/dist/esm/animation/shapes/legs.js +7 -6
  237. package/dist/esm/animation/shapes/legs.js.map +1 -1
  238. package/dist/esm/animation/shapes/mouths.js +28 -18
  239. package/dist/esm/animation/shapes/mouths.js.map +1 -1
  240. package/dist/esm/animation/shapes/noses.js +18 -9
  241. package/dist/esm/animation/shapes/noses.js.map +1 -1
  242. package/dist/esm/animation/shapes/outfits.js +25 -14
  243. package/dist/esm/animation/shapes/outfits.js.map +1 -1
  244. package/dist/esm/animation/shapes/torsos.js +5 -4
  245. package/dist/esm/animation/shapes/torsos.js.map +1 -1
  246. package/dist/esm/animation/spineExport.js +33 -26
  247. package/dist/esm/animation/spineExport.js.map +1 -1
  248. package/dist/esm/core/LocalUI.js +16 -16
  249. package/dist/esm/core/LocalUI.js.map +1 -1
  250. package/dist/esm/core/NiceBrushEngine.js +205 -69
  251. package/dist/esm/core/NiceBrushEngine.js.map +1 -1
  252. package/dist/esm/core/collaboration.js +35 -21
  253. package/dist/esm/core/collaboration.js.map +1 -1
  254. package/dist/esm/core/colorBlindness.js +64 -24
  255. package/dist/esm/core/colorBlindness.js.map +1 -1
  256. package/dist/esm/core/dragDrop.js +34 -26
  257. package/dist/esm/core/dragDrop.js.map +1 -1
  258. package/dist/esm/core/fixes.js +26 -14
  259. package/dist/esm/core/fixes.js.map +1 -1
  260. package/dist/esm/core/gridGuides.js +24 -16
  261. package/dist/esm/core/gridGuides.js.map +1 -1
  262. package/dist/esm/core/historyVisual.js +42 -23
  263. package/dist/esm/core/historyVisual.js.map +1 -1
  264. package/dist/esm/core/integrations.js +65 -48
  265. package/dist/esm/core/integrations.js.map +1 -1
  266. package/dist/esm/core/minimap.js +40 -24
  267. package/dist/esm/core/minimap.js.map +1 -1
  268. package/dist/esm/core/plugins.js +10 -6
  269. package/dist/esm/core/plugins.js.map +1 -1
  270. package/dist/esm/core/rtl.js +32 -27
  271. package/dist/esm/core/rtl.js.map +1 -1
  272. package/dist/esm/core/shortcuts.js +77 -39
  273. package/dist/esm/core/shortcuts.js.map +1 -1
  274. package/dist/esm/core/theme.js +68 -61
  275. package/dist/esm/core/theme.js.map +1 -1
  276. package/dist/esm/core/yjsCollaboration.js +61 -28
  277. package/dist/esm/core/yjsCollaboration.js.map +1 -1
  278. package/dist/esm/font/NiceFontEditor.js +160 -57
  279. package/dist/esm/font/NiceFontEditor.js.map +1 -1
  280. package/dist/esm/font/fontFormatUtils.js +37 -24
  281. package/dist/esm/font/fontFormatUtils.js.map +1 -1
  282. package/dist/esm/game/GameAsset2dEditor.js +73 -60
  283. package/dist/esm/game/GameAsset2dEditor.js.map +1 -1
  284. package/dist/esm/game/gameAssetUtils.js +18 -13
  285. package/dist/esm/game/gameAssetUtils.js.map +1 -1
  286. package/dist/esm/game/useGameAssetEditor.js +160 -143
  287. package/dist/esm/game/useGameAssetEditor.js.map +1 -1
  288. package/dist/esm/icon/NiceIconEditor.js +329 -106
  289. package/dist/esm/icon/NiceIconEditor.js.map +1 -1
  290. package/dist/esm/packages/ui/dist/NiceErrorBoundary-D75yr_WE.js +563 -0
  291. package/dist/esm/packages/ui/dist/NiceErrorBoundary-D75yr_WE.js.map +1 -0
  292. package/dist/esm/packages/ui/dist/NiceForm-CKoJA6NG.js +4960 -0
  293. package/dist/esm/packages/ui/dist/NiceForm-CKoJA6NG.js.map +1 -0
  294. package/dist/esm/packages/ui/dist/NiceModal-1QX7NhyH.js +96 -0
  295. package/dist/esm/packages/ui/dist/NiceModal-1QX7NhyH.js.map +1 -0
  296. package/dist/esm/packages/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js +5201 -0
  297. package/dist/esm/packages/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js.map +1 -0
  298. package/dist/esm/packages/ui/dist/NicePagination-DbE-uOkl.js +172 -0
  299. package/dist/esm/packages/ui/dist/NicePagination-DbE-uOkl.js.map +1 -0
  300. package/dist/esm/packages/ui/dist/NicePinCodeInput-B8cI8zu8.js +10408 -0
  301. package/dist/esm/packages/ui/dist/NicePinCodeInput-B8cI8zu8.js.map +1 -0
  302. package/dist/esm/packages/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js +6296 -0
  303. package/dist/esm/packages/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js.map +1 -0
  304. package/dist/esm/packages/ui/dist/NiceTabs-DzLHzwuA.js +1630 -0
  305. package/dist/esm/packages/ui/dist/NiceTabs-DzLHzwuA.js.map +1 -0
  306. package/dist/esm/packages/ui/dist/NiceWindow-DeC83yfE.js +796 -0
  307. package/dist/esm/packages/ui/dist/NiceWindow-DeC83yfE.js.map +1 -0
  308. package/dist/esm/packages/ui/dist/charts-BAS21jkC.js +3809 -0
  309. package/dist/esm/packages/ui/dist/charts-BAS21jkC.js.map +1 -0
  310. package/dist/esm/packages/ui/dist/core-Da43q-pO.js +11502 -0
  311. package/dist/esm/packages/ui/dist/core-Da43q-pO.js.map +1 -0
  312. package/dist/esm/packages/ui/dist/index-pAuGTbuB.js +28792 -0
  313. package/dist/esm/packages/ui/dist/index-pAuGTbuB.js.map +1 -0
  314. package/dist/esm/photo/FilterThumb.js +7 -5
  315. package/dist/esm/photo/FilterThumb.js.map +1 -1
  316. package/dist/esm/photo/NiceAITools.js +78 -32
  317. package/dist/esm/photo/NiceAITools.js.map +1 -1
  318. package/dist/esm/photo/PhotoEditor.js +4 -4
  319. package/dist/esm/photo/PhotoEditor.js.map +1 -1
  320. package/dist/esm/photo/PhotoEditorCanvas.js +56 -22
  321. package/dist/esm/photo/PhotoEditorCanvas.js.map +1 -1
  322. package/dist/esm/photo/PhotoEditorLeftPanel.js +106 -48
  323. package/dist/esm/photo/PhotoEditorLeftPanel.js.map +1 -1
  324. package/dist/esm/photo/PhotoEditorToolbar.js +2 -2
  325. package/dist/esm/photo/PhotoEditorToolbar.js.map +1 -1
  326. package/dist/esm/photo/photoEditorActions.js +27 -18
  327. package/dist/esm/photo/photoEditorActions.js.map +1 -1
  328. package/dist/esm/photo/photoFilters.js +316 -81
  329. package/dist/esm/photo/photoFilters.js.map +1 -1
  330. package/dist/esm/photo/photoOverlays.js +521 -165
  331. package/dist/esm/photo/photoOverlays.js.map +1 -1
  332. package/dist/esm/photo/photoSelection.js +69 -35
  333. package/dist/esm/photo/photoSelection.js.map +1 -1
  334. package/dist/esm/photo/usePhotoEditor.js +203 -97
  335. package/dist/esm/photo/usePhotoEditor.js.map +1 -1
  336. package/dist/esm/pixel/HSVPicker.js +32 -19
  337. package/dist/esm/pixel/HSVPicker.js.map +1 -1
  338. package/dist/esm/pixel/PixelEditor.js +25 -14
  339. package/dist/esm/pixel/PixelEditor.js.map +1 -1
  340. package/dist/esm/pixel/PixelEditorCanvas.js +2 -2
  341. package/dist/esm/pixel/PixelEditorCanvas.js.map +1 -1
  342. package/dist/esm/pixel/PixelEditorMenuBar.js +3 -3
  343. package/dist/esm/pixel/PixelEditorMenuBar.js.map +1 -1
  344. package/dist/esm/pixel/PixelEditorRightPanel.js +28 -8
  345. package/dist/esm/pixel/PixelEditorRightPanel.js.map +1 -1
  346. package/dist/esm/pixel/PixelEditorStatusBar.js +2 -2
  347. package/dist/esm/pixel/PixelEditorStatusBar.js.map +1 -1
  348. package/dist/esm/pixel/PixelEditorTimeline.js +3 -4
  349. package/dist/esm/pixel/PixelEditorTimeline.js.map +1 -1
  350. package/dist/esm/pixel/PixelEditorToolbar.js +3 -3
  351. package/dist/esm/pixel/PixelEditorToolbar.js.map +1 -1
  352. package/dist/esm/pixel/SpriteGeneratorPanel.js +136 -54
  353. package/dist/esm/pixel/SpriteGeneratorPanel.js.map +1 -1
  354. package/dist/esm/pixel/asepriteFormat.js +122 -38
  355. package/dist/esm/pixel/asepriteFormat.js.map +1 -1
  356. package/dist/esm/pixel/characterGeneratorPresets.js +208 -54
  357. package/dist/esm/pixel/characterGeneratorPresets.js.map +1 -1
  358. package/dist/esm/pixel/pixelEditorExports.js +42 -35
  359. package/dist/esm/pixel/pixelEditorExports.js.map +1 -1
  360. package/dist/esm/pixel/pixelEditorTypes.js +67 -33
  361. package/dist/esm/pixel/pixelEditorTypes.js.map +1 -1
  362. package/dist/esm/pixel/pixelEditorUtils.js +62 -38
  363. package/dist/esm/pixel/pixelEditorUtils.js.map +1 -1
  364. package/dist/esm/pixel/spriteGeneratorCore.js +47 -24
  365. package/dist/esm/pixel/spriteGeneratorCore.js.map +1 -1
  366. package/dist/esm/pixel/usePixelEditor.js +475 -213
  367. package/dist/esm/pixel/usePixelEditor.js.map +1 -1
  368. package/dist/esm/texture/Nice3DTexturePainter.js +201 -71
  369. package/dist/esm/texture/Nice3DTexturePainter.js.map +1 -1
  370. package/dist/esm/ui/NiceUIDesigner.js +280 -91
  371. package/dist/esm/ui/NiceUIDesigner.js.map +1 -1
  372. package/dist/esm/vector/NiceSvgToCode.js +96 -34
  373. package/dist/esm/vector/NiceSvgToCode.js.map +1 -1
  374. package/dist/esm/vector/VectorEditor.js +14 -13
  375. package/dist/esm/vector/VectorEditor.js.map +1 -1
  376. package/dist/esm/vector/VectorEditorMenuBar.js +7 -6
  377. package/dist/esm/vector/VectorEditorMenuBar.js.map +1 -1
  378. package/dist/esm/vector/VectorEditorRightPanel.js +87 -32
  379. package/dist/esm/vector/VectorEditorRightPanel.js.map +1 -1
  380. package/dist/esm/vector/VectorEditorShapeRenderer.js +17 -15
  381. package/dist/esm/vector/VectorEditorShapeRenderer.js.map +1 -1
  382. package/dist/esm/vector/VectorEditorStatusBar.js.map +1 -1
  383. package/dist/esm/vector/useVectorEditor.js +312 -122
  384. package/dist/esm/vector/useVectorEditor.js.map +1 -1
  385. package/dist/esm/vector/vectorBooleanOps.js +60 -42
  386. package/dist/esm/vector/vectorBooleanOps.js.map +1 -1
  387. package/dist/esm/vector/vectorEditorExport.js +40 -34
  388. package/dist/esm/vector/vectorEditorExport.js.map +1 -1
  389. package/dist/esm/vector/vectorGradients.js +41 -40
  390. package/dist/esm/vector/vectorGradients.js.map +1 -1
  391. package/package.json +2 -2
@@ -2,9 +2,9 @@
2
2
 
3
3
  var React = require('react');
4
4
  var asepriteFormat = require('./asepriteFormat.js');
5
- var pixelEditorUtils = require('./pixelEditorUtils.js');
6
- var pixelEditorTypes = require('./pixelEditorTypes.js');
7
5
  var pixelEditorExports = require('./pixelEditorExports.js');
6
+ var pixelEditorTypes = require('./pixelEditorTypes.js');
7
+ var pixelEditorUtils = require('./pixelEditorUtils.js');
8
8
 
9
9
  /**
10
10
  * usePixelEditor — custom hook encapsulating ALL state, refs, callbacks,
@@ -19,15 +19,22 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
19
19
  const [dw, setDw] = React.useState(initialWidth);
20
20
  const [dh, setDh] = React.useState(initialHeight);
21
21
  const [layers, setLayers] = React.useState(() => [
22
- { id: pixelEditorTypes.lid(), name: "Background", visible: true, opacity: 255, locked: false, blendMode: "normal" },
22
+ {
23
+ id: pixelEditorTypes.lid(),
24
+ name: 'Background',
25
+ visible: true,
26
+ opacity: 255,
27
+ locked: false,
28
+ blendMode: 'normal',
29
+ },
23
30
  ]);
24
31
  const [aLi, setALi] = React.useState(0);
25
32
  const [fc, setFc] = React.useState(1);
26
33
  const [afi, setAfi] = React.useState(0);
27
34
  const [fDur, setFDur] = React.useState([100]);
28
- const [tool, setTool] = React.useState("pencil");
29
- const [col1, setCol1] = React.useState("#000000");
30
- const [col2, setCol2] = React.useState("#ffffff");
35
+ const [tool, setTool] = React.useState('pencil');
36
+ const [col1, setCol1] = React.useState('#000000');
37
+ const [col2, setCol2] = React.useState('#ffffff');
31
38
  const [brush, setBrush] = React.useState({ ...pixelEditorUtils.DEFAULT_BRUSH });
32
39
  const [zoom, setZoom] = React.useState(8);
33
40
  const [px, setPx] = React.useState(0);
@@ -43,7 +50,7 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
43
50
  const [nh, setNh] = React.useState(64);
44
51
  const [sel, setSel] = React.useState(null);
45
52
  const [tick, setTick] = React.useState(0);
46
- const [symmetry, setSymmetry] = React.useState("none");
53
+ const [symmetry, setSymmetry] = React.useState('none');
47
54
  const [shapeFilled, setShapeFilled] = React.useState(false);
48
55
  const [pressure, setPressure] = React.useState(0.5);
49
56
  const [showHSV, setShowHSV] = React.useState(false);
@@ -79,8 +86,9 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
79
86
  const scr2art = React.useCallback((cx, cy) => {
80
87
  var _a;
81
88
  const r = (_a = boxRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
82
- if (!r)
89
+ if (!r) {
83
90
  return { x: 0, y: 0 };
91
+ }
84
92
  return {
85
93
  x: Math.floor((cx - r.left - px - r.width / 2) / zoom + dw / 2),
86
94
  y: Math.floor((cy - r.top - py - r.height / 2) / zoom + dh / 2),
@@ -97,8 +105,9 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
97
105
  layers: JSON.parse(JSON.stringify(layers)),
98
106
  frameCount: fc,
99
107
  });
100
- if (hist.current.length > 50)
108
+ if (hist.current.length > 50) {
101
109
  hist.current.shift();
110
+ }
102
111
  hIdx.current = hist.current.length - 1;
103
112
  }, [layers, fc]);
104
113
  const restoreEntry = React.useCallback((e) => {
@@ -109,61 +118,66 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
109
118
  setTick((t) => t + 1);
110
119
  }, []);
111
120
  const undo = React.useCallback(() => {
112
- if (hIdx.current <= 0)
121
+ if (hIdx.current <= 0) {
113
122
  return;
123
+ }
114
124
  hIdx.current--;
115
125
  restoreEntry(hist.current[hIdx.current]);
116
126
  }, [restoreEntry]);
117
127
  const redo = React.useCallback(() => {
118
- if (hIdx.current >= hist.current.length - 1)
128
+ if (hIdx.current >= hist.current.length - 1) {
119
129
  return;
130
+ }
120
131
  hIdx.current++;
121
132
  restoreEntry(hist.current[hIdx.current]);
122
133
  }, [restoreEntry]);
123
134
  /* Push initial snapshot so first undo works */
124
135
  React.useEffect(() => {
125
136
  if (hist.current.length === 0) {
126
- snap("initial");
137
+ snap('initial');
127
138
  }
128
139
  }, [snap]);
129
140
  /* ── composite a frame ── */
130
141
  const compFrame = React.useCallback((fi) => {
131
142
  const cv = new OffscreenCanvas(dw, dh);
132
- const ctx = cv.getContext("2d");
143
+ const ctx = cv.getContext('2d');
133
144
  for (let li = 0; li < layers.length; li++) {
134
- if (!layers[li].visible)
145
+ if (!layers[li].visible) {
135
146
  continue;
147
+ }
136
148
  const c = cels.current.get(pixelEditorTypes.celKey(fi, li));
137
- if (!c)
149
+ if (!c) {
138
150
  continue;
151
+ }
139
152
  const t = new OffscreenCanvas(dw, dh);
140
- t.getContext("2d").putImageData(c, 0, 0);
153
+ t.getContext('2d').putImageData(c, 0, 0);
141
154
  ctx.globalAlpha = layers[li].opacity / 255;
142
155
  const bm = layers[li].blendMode;
143
- if (bm !== "normal") {
156
+ if (bm !== 'normal') {
144
157
  ctx.globalCompositeOperation = bm;
145
158
  }
146
159
  else {
147
- ctx.globalCompositeOperation = "source-over";
160
+ ctx.globalCompositeOperation = 'source-over';
148
161
  }
149
162
  ctx.drawImage(t, 0, 0);
150
163
  }
151
- ctx.globalCompositeOperation = "source-over";
164
+ ctx.globalCompositeOperation = 'source-over';
152
165
  return ctx.getImageData(0, 0, dw, dh);
153
166
  }, [dw, dh, layers]);
154
167
  /* ── rendering ── */
155
168
  const render = React.useCallback(() => {
156
169
  const canvas = cvRef.current;
157
170
  const box = boxRef.current;
158
- if (!canvas || !box)
171
+ if (!canvas || !box) {
159
172
  return;
173
+ }
160
174
  const cw = box.clientWidth;
161
175
  const ch = box.clientHeight;
162
176
  if (canvas.width !== cw || canvas.height !== ch) {
163
177
  canvas.width = cw;
164
178
  canvas.height = ch;
165
179
  }
166
- const ctx = canvas.getContext("2d");
180
+ const ctx = canvas.getContext('2d');
167
181
  ctx.clearRect(0, 0, cw, ch);
168
182
  ctx.imageSmoothingEnabled = false;
169
183
  ctx.save();
@@ -171,23 +185,26 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
171
185
  ctx.scale(zoom, zoom);
172
186
  ctx.translate(-dw / 2, -dh / 2);
173
187
  // checkerboard
174
- for (let y = 0; y < dh; y++)
188
+ for (let y = 0; y < dh; y++) {
175
189
  for (let x = 0; x < dw; x++) {
176
- ctx.fillStyle = (x + y) % 2 === 0 ? "#3c3c3c" : "#2c2c2c";
190
+ ctx.fillStyle = (x + y) % 2 === 0 ? '#3c3c3c' : '#2c2c2c';
177
191
  ctx.fillRect(x, y, 1, 1);
178
192
  }
193
+ }
179
194
  // onion skin (prev frame)
180
195
  if (onion && afi > 0) {
181
196
  const oc = new OffscreenCanvas(dw, dh);
182
- const ox = oc.getContext("2d");
197
+ const ox = oc.getContext('2d');
183
198
  for (let li = 0; li < layers.length; li++) {
184
- if (!layers[li].visible)
199
+ if (!layers[li].visible) {
185
200
  continue;
201
+ }
186
202
  const c = cels.current.get(pixelEditorTypes.celKey(afi - 1, li));
187
- if (!c)
203
+ if (!c) {
188
204
  continue;
205
+ }
189
206
  const t = new OffscreenCanvas(dw, dh);
190
- t.getContext("2d").putImageData(c, 0, 0);
207
+ t.getContext('2d').putImageData(c, 0, 0);
191
208
  ox.globalAlpha = (layers[li].opacity / 255) * 0.25;
192
209
  ox.drawImage(t, 0, 0);
193
210
  }
@@ -195,95 +212,105 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
195
212
  }
196
213
  // current frame composite
197
214
  const comp = new OffscreenCanvas(dw, dh);
198
- const cc = comp.getContext("2d");
215
+ const cc = comp.getContext('2d');
199
216
  for (let li = 0; li < layers.length; li++) {
200
- if (!layers[li].visible)
217
+ if (!layers[li].visible) {
201
218
  continue;
219
+ }
202
220
  const c = cels.current.get(pixelEditorTypes.celKey(afi, li));
203
- if (!c)
221
+ if (!c) {
204
222
  continue;
223
+ }
205
224
  const t = new OffscreenCanvas(dw, dh);
206
- t.getContext("2d").putImageData(c, 0, 0);
225
+ t.getContext('2d').putImageData(c, 0, 0);
207
226
  cc.globalAlpha = layers[li].opacity / 255;
208
227
  const bm = layers[li].blendMode;
209
- if (bm !== "normal") {
228
+ if (bm !== 'normal') {
210
229
  cc.globalCompositeOperation = bm;
211
230
  }
212
231
  else {
213
- cc.globalCompositeOperation = "source-over";
232
+ cc.globalCompositeOperation = 'source-over';
214
233
  }
215
234
  cc.drawImage(t, 0, 0);
216
235
  }
217
- cc.globalCompositeOperation = "source-over";
236
+ cc.globalCompositeOperation = 'source-over';
218
237
  ctx.drawImage(comp, 0, 0);
219
238
  // tool preview (line / rect / ellipse while dragging)
220
239
  if (preview.current && drawing.current) {
221
240
  const pv = preview.current;
222
241
  const clr = btn.current === 2 ? pixelEditorTypes.hex2t(col2) : pixelEditorTypes.hex2t(col1);
223
242
  const pvData = pixelEditorUtils.cloneImageData(getCel(afi, aLi));
224
- if (tool === "line") {
243
+ if (tool === 'line') {
225
244
  pixelEditorUtils.bresenhamLine(pv.fr.x, pv.fr.y, pv.to.x, pv.to.y, (bx, by) => {
226
- if (pixelEditorTypes.inB(bx, by, dw, dh))
245
+ if (pixelEditorTypes.inB(bx, by, dw, dh)) {
227
246
  pixelEditorUtils.setPixel(pvData, bx, by, clr);
247
+ }
228
248
  });
229
249
  }
230
- else if (tool === "rect") {
250
+ else if (tool === 'rect') {
231
251
  const x1 = Math.min(pv.fr.x, pv.to.x), y1 = Math.min(pv.fr.y, pv.to.y);
232
252
  const x2 = Math.max(pv.fr.x, pv.to.x), y2 = Math.max(pv.fr.y, pv.to.y);
233
253
  if (shapeFilled) {
234
- for (let y = y1; y <= y2; y++)
235
- for (let x = x1; x <= x2; x++)
236
- if (pixelEditorTypes.inB(x, y, dw, dh))
254
+ for (let y = y1; y <= y2; y++) {
255
+ for (let x = x1; x <= x2; x++) {
256
+ if (pixelEditorTypes.inB(x, y, dw, dh)) {
237
257
  pixelEditorUtils.setPixel(pvData, x, y, clr);
258
+ }
259
+ }
260
+ }
238
261
  }
239
262
  else {
240
263
  for (let x = x1; x <= x2; x++) {
241
- if (pixelEditorTypes.inB(x, y1, dw, dh))
264
+ if (pixelEditorTypes.inB(x, y1, dw, dh)) {
242
265
  pixelEditorUtils.setPixel(pvData, x, y1, clr);
243
- if (pixelEditorTypes.inB(x, y2, dw, dh))
266
+ }
267
+ if (pixelEditorTypes.inB(x, y2, dw, dh)) {
244
268
  pixelEditorUtils.setPixel(pvData, x, y2, clr);
269
+ }
245
270
  }
246
271
  for (let y = y1 + 1; y < y2; y++) {
247
- if (pixelEditorTypes.inB(x1, y, dw, dh))
272
+ if (pixelEditorTypes.inB(x1, y, dw, dh)) {
248
273
  pixelEditorUtils.setPixel(pvData, x1, y, clr);
249
- if (pixelEditorTypes.inB(x2, y, dw, dh))
274
+ }
275
+ if (pixelEditorTypes.inB(x2, y, dw, dh)) {
250
276
  pixelEditorUtils.setPixel(pvData, x2, y, clr);
277
+ }
251
278
  }
252
279
  }
253
280
  }
254
- else if (tool === "ellipse") {
281
+ else if (tool === 'ellipse') {
255
282
  const cx2 = (pv.fr.x + pv.to.x) / 2, cy2 = (pv.fr.y + pv.to.y) / 2;
256
283
  const rx = Math.abs(pv.to.x - pv.fr.x) / 2, ry = Math.abs(pv.to.y - pv.fr.y) / 2;
257
284
  pixelEditorTypes.plotEllipse(pvData, cx2, cy2, rx, ry, clr, dw, dh, shapeFilled);
258
285
  }
259
- else if (tool === "gradient") {
286
+ else if (tool === 'gradient') {
260
287
  const c2 = btn.current === 2 ? pixelEditorTypes.hex2t(col1) : pixelEditorTypes.hex2t(col2);
261
288
  pixelEditorUtils.drawGradient(pvData, pv.fr.x, pv.fr.y, pv.to.x, pv.to.y, clr, c2, sel);
262
289
  }
263
290
  const pcv = new OffscreenCanvas(dw, dh);
264
- pcv.getContext("2d").putImageData(pvData, 0, 0);
291
+ pcv.getContext('2d').putImageData(pvData, 0, 0);
265
292
  ctx.globalAlpha = layers[aLi].opacity / 255;
266
293
  ctx.drawImage(pcv, 0, 0);
267
294
  ctx.globalAlpha = 1;
268
295
  }
269
296
  // symmetry guides
270
- if (symmetry !== "none") {
271
- ctx.strokeStyle = "rgba(255,100,100,0.3)";
297
+ if (symmetry !== 'none') {
298
+ ctx.strokeStyle = 'rgba(255,100,100,0.3)';
272
299
  ctx.lineWidth = 1 / zoom;
273
300
  ctx.setLineDash([4 / zoom, 4 / zoom]);
274
- if (symmetry === "h" || symmetry === "both") {
301
+ if (symmetry === 'h' || symmetry === 'both') {
275
302
  ctx.beginPath();
276
303
  ctx.moveTo(dw / 2, 0);
277
304
  ctx.lineTo(dw / 2, dh);
278
305
  ctx.stroke();
279
306
  }
280
- if (symmetry === "v" || symmetry === "both") {
307
+ if (symmetry === 'v' || symmetry === 'both') {
281
308
  ctx.beginPath();
282
309
  ctx.moveTo(0, dh / 2);
283
310
  ctx.lineTo(dw, dh / 2);
284
311
  ctx.stroke();
285
312
  }
286
- if (symmetry === "radial4") {
313
+ if (symmetry === 'radial4') {
287
314
  ctx.beginPath();
288
315
  ctx.moveTo(dw / 2, 0);
289
316
  ctx.lineTo(dw / 2, dh);
@@ -295,7 +322,7 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
295
322
  }
296
323
  // selection marching ants
297
324
  if (sel) {
298
- ctx.strokeStyle = "rgba(255,255,255,0.8)";
325
+ ctx.strokeStyle = 'rgba(255,255,255,0.8)';
299
326
  ctx.lineWidth = 1 / zoom;
300
327
  ctx.setLineDash([4 / zoom, 4 / zoom]);
301
328
  ctx.strokeRect(sel.x, sel.y, sel.w, sel.h);
@@ -303,7 +330,7 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
303
330
  }
304
331
  // grid
305
332
  if (grid && zoom >= 4) {
306
- ctx.strokeStyle = "rgba(255,255,255,0.07)";
333
+ ctx.strokeStyle = 'rgba(255,255,255,0.07)';
307
334
  ctx.lineWidth = 1 / zoom;
308
335
  for (let x = 0; x <= dw; x++) {
309
336
  ctx.beginPath();
@@ -319,16 +346,20 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
319
346
  }
320
347
  }
321
348
  // border
322
- ctx.strokeStyle = "rgba(80,100,200,0.4)";
349
+ ctx.strokeStyle = 'rgba(80,100,200,0.4)';
323
350
  ctx.lineWidth = 1 / zoom;
324
351
  ctx.strokeRect(-0.5 / zoom, -0.5 / zoom, dw + 1 / zoom, dh + 1 / zoom);
325
352
  // brush cursor preview
326
- if (cursor && pixelEditorTypes.inB(cursor.x, cursor.y, dw, dh) && (tool === "pencil" || tool === "eraser" || tool === "dither")) {
327
- const sz = brush.pressureSize ? Math.max(1, Math.round(brush.size * curPressure.current)) : brush.size;
353
+ if (cursor &&
354
+ pixelEditorTypes.inB(cursor.x, cursor.y, dw, dh) &&
355
+ (tool === 'pencil' || tool === 'eraser' || tool === 'dither')) {
356
+ const sz = brush.pressureSize
357
+ ? Math.max(1, Math.round(brush.size * curPressure.current))
358
+ : brush.size;
328
359
  const half = Math.floor(sz / 2);
329
- ctx.strokeStyle = "rgba(255,255,255,0.5)";
360
+ ctx.strokeStyle = 'rgba(255,255,255,0.5)';
330
361
  ctx.lineWidth = 1 / zoom;
331
- if (brush.shape === "circle") {
362
+ if (brush.shape === 'circle') {
332
363
  ctx.beginPath();
333
364
  ctx.arc(cursor.x + 0.5, cursor.y + 0.5, half + 0.5, 0, Math.PI * 2);
334
365
  ctx.stroke();
@@ -338,14 +369,34 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
338
369
  }
339
370
  }
340
371
  ctx.restore();
341
- }, [dw, dh, zoom, px, py, layers, afi, aLi, grid, onion, tool, col1, col2, sel, getCel, symmetry, shapeFilled, brush, cursor]);
372
+ }, [
373
+ dw,
374
+ dh,
375
+ zoom,
376
+ px,
377
+ py,
378
+ layers,
379
+ afi,
380
+ aLi,
381
+ grid,
382
+ onion,
383
+ tool,
384
+ col1,
385
+ col2,
386
+ sel,
387
+ getCel,
388
+ symmetry,
389
+ shapeFilled,
390
+ brush,
391
+ cursor,
392
+ ]);
342
393
  /* ── brush drawing with symmetry ── */
343
394
  const applyBrushAt = React.useCallback((x, y, erase, pr) => {
344
395
  const cel = getCel(afi, aLi);
345
396
  const clr = erase ? [0, 0, 0, 0] : pixelEditorTypes.hex2t(btn.current === 2 ? col2 : col1);
346
397
  const pts = pixelEditorUtils.getSymmetryPoints(x, y, dw, dh, symmetry);
347
398
  for (const pt of pts) {
348
- if (tool === "dither") {
399
+ if (tool === 'dither') {
349
400
  pixelEditorUtils.applyDitherStamp(cel, pt.x, pt.y, clr, brush.size, pr);
350
401
  }
351
402
  else {
@@ -369,22 +420,23 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
369
420
  }
370
421
  const p = scr2art(e.clientX, e.clientY);
371
422
  setCursor(p);
372
- if ((_c = layers[aLi]) === null || _c === void 0 ? void 0 : _c.locked)
423
+ if ((_c = layers[aLi]) === null || _c === void 0 ? void 0 : _c.locked) {
373
424
  return;
425
+ }
374
426
  switch (tool) {
375
- case "pencil":
376
- case "eraser":
377
- case "dither":
378
- snap(tool === "pencil" ? "Draw" : tool === "eraser" ? "Erase" : "Dither");
427
+ case 'pencil':
428
+ case 'eraser':
429
+ case 'dither':
430
+ snap(tool === 'pencil' ? 'Draw' : tool === 'eraser' ? 'Erase' : 'Dither');
379
431
  drawing.current = true;
380
432
  lastPx.current = p;
381
433
  brushDist.current = 0;
382
- applyBrushAt(p.x, p.y, tool === "eraser", pr);
434
+ applyBrushAt(p.x, p.y, tool === 'eraser', pr);
383
435
  setTick((t) => t + 1);
384
436
  break;
385
- case "fill":
437
+ case 'fill':
386
438
  if (pixelEditorTypes.inB(p.x, p.y, dw, dh)) {
387
- snap("Fill");
439
+ snap('Fill');
388
440
  const clr = pixelEditorTypes.hex2t(e.button === 2 ? col2 : col1);
389
441
  const pts = pixelEditorUtils.getSymmetryPoints(p.x, p.y, dw, dh, symmetry);
390
442
  const cel = getCel(afi, aLi);
@@ -396,36 +448,54 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
396
448
  setTick((t) => t + 1);
397
449
  }
398
450
  break;
399
- case "eyedropper": {
451
+ case 'eyedropper': {
400
452
  if (pixelEditorTypes.inB(p.x, p.y, dw, dh)) {
401
453
  const c = pixelEditorUtils.getPixel(getCel(afi, aLi), p.x, p.y);
402
454
  const hex = pixelEditorUtils.rgbaToHex(c);
403
- if (e.button === 2)
455
+ if (e.button === 2) {
404
456
  setCol2(hex);
405
- else
457
+ }
458
+ else {
406
459
  setCol1(hex);
460
+ }
407
461
  }
408
462
  break;
409
463
  }
410
- case "line":
411
- case "rect":
412
- case "ellipse":
413
- case "gradient":
464
+ case 'line':
465
+ case 'rect':
466
+ case 'ellipse':
467
+ case 'gradient':
414
468
  snap(tool[0].toUpperCase() + tool.slice(1));
415
469
  drawing.current = true;
416
470
  tStart.current = p;
417
471
  preview.current = { fr: p, to: p };
418
472
  break;
419
- case "select":
473
+ case 'select':
420
474
  drawing.current = true;
421
475
  tStart.current = p;
422
476
  break;
423
- case "move":
477
+ case 'move':
424
478
  drawing.current = true;
425
479
  lastPx.current = p;
426
480
  break;
427
481
  }
428
- }, [tool, aLi, layers, px, py, scr2art, snap, applyBrushAt, getCel, afi, col1, col2, dw, dh, symmetry]);
482
+ }, [
483
+ tool,
484
+ aLi,
485
+ layers,
486
+ px,
487
+ py,
488
+ scr2art,
489
+ snap,
490
+ applyBrushAt,
491
+ getCel,
492
+ afi,
493
+ col1,
494
+ col2,
495
+ dw,
496
+ dh,
497
+ symmetry,
498
+ ]);
429
499
  const onMove = React.useCallback((e) => {
430
500
  const pr = e.pressure > 0 ? e.pressure : 0.5;
431
501
  curPressure.current = pr;
@@ -437,30 +507,32 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
437
507
  }
438
508
  const p = scr2art(e.clientX, e.clientY);
439
509
  setCursor(p);
440
- if (!drawing.current)
510
+ if (!drawing.current) {
441
511
  return;
442
- if (tool === "pencil" || tool === "eraser" || tool === "dither") {
512
+ }
513
+ if (tool === 'pencil' || tool === 'eraser' || tool === 'dither') {
443
514
  const last = lastPx.current || p;
444
515
  const spacing = Math.max(1, brush.size * (brush.spacing / 100));
445
516
  const ddx = p.x - last.x, ddy = p.y - last.y;
446
517
  const dist = Math.sqrt(ddx * ddx + ddy * ddy);
447
- if (dist < 0.5)
518
+ if (dist < 0.5) {
448
519
  return;
520
+ }
449
521
  brushDist.current += dist;
450
522
  if (brushDist.current >= spacing) {
451
523
  pixelEditorUtils.bresenhamLine(last.x, last.y, p.x, p.y, (bx, by) => {
452
- applyBrushAt(bx, by, tool === "eraser", pr);
524
+ applyBrushAt(bx, by, tool === 'eraser', pr);
453
525
  });
454
526
  brushDist.current = 0;
455
527
  }
456
528
  lastPx.current = p;
457
529
  setTick((t) => t + 1);
458
530
  }
459
- else if (tool === "line" || tool === "rect" || tool === "ellipse" || tool === "gradient") {
531
+ else if (tool === 'line' || tool === 'rect' || tool === 'ellipse' || tool === 'gradient') {
460
532
  preview.current = { fr: tStart.current, to: p };
461
533
  setTick((t) => t + 1);
462
534
  }
463
- else if (tool === "select") {
535
+ else if (tool === 'select') {
464
536
  const s = tStart.current;
465
537
  setSel({
466
538
  x: Math.min(s.x, p.x),
@@ -469,7 +541,7 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
469
541
  h: Math.abs(p.y - s.y) + 1,
470
542
  });
471
543
  }
472
- else if (tool === "move" && sel) {
544
+ else if (tool === 'move' && sel) {
473
545
  const last2 = lastPx.current || p;
474
546
  const ddx = p.x - last2.x, ddy = p.y - last2.y;
475
547
  if (ddx !== 0 || ddy !== 0) {
@@ -483,18 +555,20 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
483
555
  panning.current = false;
484
556
  return;
485
557
  }
486
- if (!drawing.current)
558
+ if (!drawing.current) {
487
559
  return;
560
+ }
488
561
  drawing.current = false;
489
562
  const p = scr2art(e.clientX, e.clientY);
490
563
  const clr = btn.current === 2 ? pixelEditorTypes.hex2t(col2) : pixelEditorTypes.hex2t(col1);
491
- if (tool === "line" && tStart.current) {
564
+ if (tool === 'line' && tStart.current) {
492
565
  const cel = getCel(afi, aLi);
493
566
  pixelEditorUtils.getSymmetryPoints(0, 0, dw, dh, symmetry);
494
- if (symmetry === "none") {
567
+ if (symmetry === 'none') {
495
568
  pixelEditorUtils.bresenhamLine(tStart.current.x, tStart.current.y, p.x, p.y, (bx, by) => {
496
- if (pixelEditorTypes.inB(bx, by, dw, dh))
569
+ if (pixelEditorTypes.inB(bx, by, dw, dh)) {
497
570
  pixelEditorUtils.setPixel(cel, bx, by, clr);
571
+ }
498
572
  });
499
573
  }
500
574
  else {
@@ -502,42 +576,50 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
502
576
  const toPts = pixelEditorUtils.getSymmetryPoints(p.x, p.y, dw, dh, symmetry);
503
577
  for (let i = 0; i < fromPts.length; i++) {
504
578
  pixelEditorUtils.bresenhamLine(fromPts[i].x, fromPts[i].y, toPts[i].x, toPts[i].y, (bx, by) => {
505
- if (pixelEditorTypes.inB(bx, by, dw, dh))
579
+ if (pixelEditorTypes.inB(bx, by, dw, dh)) {
506
580
  pixelEditorUtils.setPixel(cel, bx, by, clr);
581
+ }
507
582
  });
508
583
  }
509
584
  }
510
585
  preview.current = null;
511
586
  setTick((t) => t + 1);
512
587
  }
513
- else if (tool === "rect" && tStart.current) {
588
+ else if (tool === 'rect' && tStart.current) {
514
589
  const cel = getCel(afi, aLi);
515
590
  const x1 = Math.min(tStart.current.x, p.x), y1 = Math.min(tStart.current.y, p.y);
516
591
  const x2 = Math.max(tStart.current.x, p.x), y2 = Math.max(tStart.current.y, p.y);
517
592
  if (shapeFilled) {
518
- for (let y = y1; y <= y2; y++)
519
- for (let x = x1; x <= x2; x++)
520
- if (pixelEditorTypes.inB(x, y, dw, dh))
593
+ for (let y = y1; y <= y2; y++) {
594
+ for (let x = x1; x <= x2; x++) {
595
+ if (pixelEditorTypes.inB(x, y, dw, dh)) {
521
596
  pixelEditorUtils.setPixel(cel, x, y, clr);
597
+ }
598
+ }
599
+ }
522
600
  }
523
601
  else {
524
602
  for (let x = x1; x <= x2; x++) {
525
- if (pixelEditorTypes.inB(x, y1, dw, dh))
603
+ if (pixelEditorTypes.inB(x, y1, dw, dh)) {
526
604
  pixelEditorUtils.setPixel(cel, x, y1, clr);
527
- if (pixelEditorTypes.inB(x, y2, dw, dh))
605
+ }
606
+ if (pixelEditorTypes.inB(x, y2, dw, dh)) {
528
607
  pixelEditorUtils.setPixel(cel, x, y2, clr);
608
+ }
529
609
  }
530
610
  for (let y = y1 + 1; y < y2; y++) {
531
- if (pixelEditorTypes.inB(x1, y, dw, dh))
611
+ if (pixelEditorTypes.inB(x1, y, dw, dh)) {
532
612
  pixelEditorUtils.setPixel(cel, x1, y, clr);
533
- if (pixelEditorTypes.inB(x2, y, dw, dh))
613
+ }
614
+ if (pixelEditorTypes.inB(x2, y, dw, dh)) {
534
615
  pixelEditorUtils.setPixel(cel, x2, y, clr);
616
+ }
535
617
  }
536
618
  }
537
619
  preview.current = null;
538
620
  setTick((t) => t + 1);
539
621
  }
540
- else if (tool === "ellipse" && tStart.current) {
622
+ else if (tool === 'ellipse' && tStart.current) {
541
623
  const cel = getCel(afi, aLi);
542
624
  const cx2 = (tStart.current.x + p.x) / 2;
543
625
  const cy2 = (tStart.current.y + p.y) / 2;
@@ -547,7 +629,7 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
547
629
  preview.current = null;
548
630
  setTick((t) => t + 1);
549
631
  }
550
- else if (tool === "gradient" && tStart.current) {
632
+ else if (tool === 'gradient' && tStart.current) {
551
633
  const cel = getCel(afi, aLi);
552
634
  const c2 = btn.current === 2 ? pixelEditorTypes.hex2t(col1) : pixelEditorTypes.hex2t(col2);
553
635
  pixelEditorUtils.drawGradient(cel, tStart.current.x, tStart.current.y, p.x, p.y, clr, c2, sel);
@@ -558,22 +640,32 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
558
640
  tStart.current = null;
559
641
  }, [tool, scr2art, getCel, afi, aLi, col1, col2, dw, dh, shapeFilled, symmetry, sel]);
560
642
  const onWheel = React.useCallback((e) => {
561
- e.preventDefault();
562
643
  setZoom((z) => {
563
644
  const n = e.deltaY < 0 ? z * 1.2 : z / 1.2;
564
645
  return Math.max(0.5, Math.min(64, n));
565
646
  });
566
647
  }, []);
648
+ React.useEffect(() => {
649
+ const el = cvRef.current;
650
+ if (!el) {
651
+ return;
652
+ }
653
+ const handler = (e) => e.preventDefault();
654
+ el.addEventListener('wheel', handler, { passive: false });
655
+ return () => el.removeEventListener('wheel', handler);
656
+ }, []);
567
657
  /* ── clipboard operations ── */
568
658
  const doCopy = React.useCallback(() => {
569
- if (!sel)
659
+ if (!sel) {
570
660
  return;
661
+ }
571
662
  clipboard.current = pixelEditorUtils.copySelection(getCel(afi, aLi), sel);
572
663
  }, [sel, getCel, afi, aLi]);
573
664
  const doCut = React.useCallback(() => {
574
- if (!sel)
665
+ if (!sel) {
575
666
  return;
576
- snap("Cut");
667
+ }
668
+ snap('Cut');
577
669
  const cel = getCel(afi, aLi);
578
670
  clipboard.current = pixelEditorUtils.copySelection(cel, sel);
579
671
  pixelEditorUtils.clearSelection(cel, sel);
@@ -581,17 +673,19 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
581
673
  }, [sel, getCel, afi, aLi, snap]);
582
674
  const doPaste = React.useCallback(() => {
583
675
  var _a, _b;
584
- if (!clipboard.current)
676
+ if (!clipboard.current) {
585
677
  return;
586
- snap("Paste");
678
+ }
679
+ snap('Paste');
587
680
  const cel = getCel(afi, aLi);
588
681
  pixelEditorUtils.pasteAt(cel, clipboard.current, (_a = sel === null || sel === void 0 ? void 0 : sel.x) !== null && _a !== void 0 ? _a : 0, (_b = sel === null || sel === void 0 ? void 0 : sel.y) !== null && _b !== void 0 ? _b : 0);
589
682
  setTick((t) => t + 1);
590
683
  }, [getCel, afi, aLi, snap, sel]);
591
684
  const doDeleteSel = React.useCallback(() => {
592
- if (!sel)
685
+ if (!sel) {
593
686
  return;
594
- snap("Delete Selection");
687
+ }
688
+ snap('Delete Selection');
595
689
  pixelEditorUtils.clearSelection(getCel(afi, aLi), sel);
596
690
  setTick((t) => t + 1);
597
691
  }, [sel, getCel, afi, aLi, snap]);
@@ -612,11 +706,20 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
612
706
  visible: l.visible,
613
707
  opacity: l.opacity,
614
708
  locked: false,
615
- blendMode: "normal",
709
+ blendMode: 'normal',
616
710
  }));
617
711
  setLayers(lrs.length
618
712
  ? lrs
619
- : [{ id: pixelEditorTypes.lid(), name: "Layer 1", visible: true, opacity: 255, locked: false, blendMode: "normal" }]);
713
+ : [
714
+ {
715
+ id: pixelEditorTypes.lid(),
716
+ name: 'Layer 1',
717
+ visible: true,
718
+ opacity: 255,
719
+ locked: false,
720
+ blendMode: 'normal',
721
+ },
722
+ ]);
620
723
  setALi(0);
621
724
  setFc(doc.frames.length || 1);
622
725
  setAfi(0);
@@ -625,22 +728,27 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
625
728
  frame.cels.forEach((cel) => {
626
729
  const data = pixelEditorUtils.createBlankImageData(doc.width, doc.height);
627
730
  if (cel.pixels && cel.width > 0 && cel.height > 0) {
628
- for (let y = 0; y < cel.height; y++)
731
+ for (let y = 0; y < cel.height; y++) {
629
732
  for (let x = 0; x < cel.width; x++) {
630
733
  const dx = cel.x + x, dy = cel.y + y;
631
734
  if (dx >= 0 && dy >= 0 && dx < doc.width && dy < doc.height) {
632
735
  const si = (y * cel.width + x) * 4;
633
736
  pixelEditorUtils.setPixel(data, dx, dy, [
634
- cel.pixels[si], cel.pixels[si + 1], cel.pixels[si + 2], cel.pixels[si + 3],
737
+ cel.pixels[si],
738
+ cel.pixels[si + 1],
739
+ cel.pixels[si + 2],
740
+ cel.pixels[si + 3],
635
741
  ]);
636
742
  }
637
743
  }
744
+ }
638
745
  }
639
746
  cels.current.set(pixelEditorTypes.celKey(fi, cel.layerIndex), data);
640
747
  });
641
748
  });
642
- if (doc.palette.length)
749
+ if (doc.palette.length) {
643
750
  setPal(doc.palette.map(asepriteFormat.aseColorToHex));
751
+ }
644
752
  setZoom(Math.max(1, Math.floor(Math.min(512 / doc.width, 512 / doc.height))));
645
753
  setPx(0);
646
754
  setPy(0);
@@ -655,8 +763,8 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
655
763
  loadAseDoc(doc);
656
764
  }
657
765
  catch (err) {
658
- log.error("ASE parse error", err);
659
- alert("Failed to parse Aseprite file.");
766
+ log.error('ASE parse error', err);
767
+ console.warn('[PixelEditor] Failed to parse Aseprite file.');
660
768
  }
661
769
  }
662
770
  else {
@@ -664,12 +772,21 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
664
772
  img.onload = () => {
665
773
  const w2 = img.naturalWidth, h2 = img.naturalHeight;
666
774
  const cv = new OffscreenCanvas(w2, h2);
667
- cv.getContext("2d").drawImage(img, 0, 0);
668
- const data = cv.getContext("2d").getImageData(0, 0, w2, h2);
775
+ cv.getContext('2d').drawImage(img, 0, 0);
776
+ const data = cv.getContext('2d').getImageData(0, 0, w2, h2);
669
777
  setDw(w2);
670
778
  setDh(h2);
671
779
  cels.current = new Map([[pixelEditorTypes.celKey(0, 0), data]]);
672
- setLayers([{ id: pixelEditorTypes.lid(), name: "Layer 1", visible: true, opacity: 255, locked: false, blendMode: "normal" }]);
780
+ setLayers([
781
+ {
782
+ id: pixelEditorTypes.lid(),
783
+ name: 'Layer 1',
784
+ visible: true,
785
+ opacity: 255,
786
+ locked: false,
787
+ blendMode: 'normal',
788
+ },
789
+ ]);
673
790
  setALi(0);
674
791
  setFc(1);
675
792
  setAfi(0);
@@ -707,34 +824,44 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
707
824
  }, [dw, dh, fc, compFrame]);
708
825
  /* ── save to library ── */
709
826
  const saveToLibrary = React.useCallback(() => {
710
- if (!onSaveToLibrary)
827
+ if (!onSaveToLibrary) {
711
828
  return;
829
+ }
712
830
  const data = compFrame(afi);
713
- const cv = document.createElement("canvas");
831
+ const cv = document.createElement('canvas');
714
832
  cv.width = dw;
715
833
  cv.height = dh;
716
- cv.getContext("2d").putImageData(data, 0, 0);
717
- const dataUrl = cv.toDataURL("image/png");
834
+ cv.getContext('2d').putImageData(data, 0, 0);
835
+ const dataUrl = cv.toDataURL('image/png');
718
836
  const defaultName = `sprite-${dw}x${dh}.png`;
719
- const name = window.prompt("Save to library as:", defaultName);
720
- if (!name || !name.trim())
837
+ const name = window.prompt('Save to library as:', defaultName);
838
+ if (!name || !name.trim()) {
721
839
  return;
722
- onSaveToLibrary(dataUrl, name.trim(), "image/png");
840
+ }
841
+ onSaveToLibrary(dataUrl, name.trim(), 'image/png');
723
842
  }, [onSaveToLibrary, afi, dw, dh, compFrame]);
724
843
  /* ── layer management ── */
725
844
  const addLayer = React.useCallback(() => {
726
- snap("Add Layer");
845
+ snap('Add Layer');
727
846
  setLayers((ls) => [
728
847
  ...ls,
729
- { id: pixelEditorTypes.lid(), name: `Layer ${ls.length + 1}`, visible: true, opacity: 255, locked: false, blendMode: "normal" },
848
+ {
849
+ id: pixelEditorTypes.lid(),
850
+ name: `Layer ${ls.length + 1}`,
851
+ visible: true,
852
+ opacity: 255,
853
+ locked: false,
854
+ blendMode: 'normal',
855
+ },
730
856
  ]);
731
857
  setALi(layers.length);
732
858
  setTick((t) => t + 1);
733
859
  }, [layers, snap]);
734
860
  const rmLayer = React.useCallback(() => {
735
- if (layers.length <= 1)
861
+ if (layers.length <= 1) {
736
862
  return;
737
- snap("Remove Layer");
863
+ }
864
+ snap('Remove Layer');
738
865
  const idx = aLi;
739
866
  for (let fi = 0; fi < fc; fi++) {
740
867
  cels.current.delete(pixelEditorTypes.celKey(fi, idx));
@@ -769,9 +896,10 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
769
896
  setLayers((ls) => ls.map((l, j) => (j === i ? { ...l, name } : l)));
770
897
  }, []);
771
898
  const moveLayerUp = React.useCallback(() => {
772
- if (aLi >= layers.length - 1)
899
+ if (aLi >= layers.length - 1) {
773
900
  return;
774
- snap("Move Layer Up");
901
+ }
902
+ snap('Move Layer Up');
775
903
  setLayers((ls) => {
776
904
  const n = [...ls];
777
905
  [n[aLi], n[aLi + 1]] = [n[aLi + 1], n[aLi]];
@@ -780,22 +908,27 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
780
908
  for (let fi = 0; fi < fc; fi++) {
781
909
  const a = cels.current.get(pixelEditorTypes.celKey(fi, aLi));
782
910
  const b = cels.current.get(pixelEditorTypes.celKey(fi, aLi + 1));
783
- if (a)
911
+ if (a) {
784
912
  cels.current.set(pixelEditorTypes.celKey(fi, aLi + 1), a);
785
- else
913
+ }
914
+ else {
786
915
  cels.current.delete(pixelEditorTypes.celKey(fi, aLi + 1));
787
- if (b)
916
+ }
917
+ if (b) {
788
918
  cels.current.set(pixelEditorTypes.celKey(fi, aLi), b);
789
- else
919
+ }
920
+ else {
790
921
  cels.current.delete(pixelEditorTypes.celKey(fi, aLi));
922
+ }
791
923
  }
792
924
  setALi(aLi + 1);
793
925
  setTick((t) => t + 1);
794
926
  }, [aLi, layers, fc, snap]);
795
927
  const moveLayerDown = React.useCallback(() => {
796
- if (aLi <= 0)
928
+ if (aLi <= 0) {
797
929
  return;
798
- snap("Move Layer Down");
930
+ }
931
+ snap('Move Layer Down');
799
932
  setLayers((ls) => {
800
933
  const n = [...ls];
801
934
  [n[aLi], n[aLi - 1]] = [n[aLi - 1], n[aLi]];
@@ -804,31 +937,36 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
804
937
  for (let fi = 0; fi < fc; fi++) {
805
938
  const a = cels.current.get(pixelEditorTypes.celKey(fi, aLi));
806
939
  const b = cels.current.get(pixelEditorTypes.celKey(fi, aLi - 1));
807
- if (a)
940
+ if (a) {
808
941
  cels.current.set(pixelEditorTypes.celKey(fi, aLi - 1), a);
809
- else
942
+ }
943
+ else {
810
944
  cels.current.delete(pixelEditorTypes.celKey(fi, aLi - 1));
811
- if (b)
945
+ }
946
+ if (b) {
812
947
  cels.current.set(pixelEditorTypes.celKey(fi, aLi), b);
813
- else
948
+ }
949
+ else {
814
950
  cels.current.delete(pixelEditorTypes.celKey(fi, aLi));
951
+ }
815
952
  }
816
953
  setALi(aLi - 1);
817
954
  setTick((t) => t + 1);
818
955
  }, [aLi, fc, snap]);
819
956
  const mergeDown = React.useCallback(() => {
820
- if (aLi <= 0)
957
+ if (aLi <= 0) {
821
958
  return;
822
- snap("Merge Down");
959
+ }
960
+ snap('Merge Down');
823
961
  for (let fi = 0; fi < fc; fi++) {
824
962
  const top = cels.current.get(pixelEditorTypes.celKey(fi, aLi));
825
963
  const bot = getCel(fi, aLi - 1);
826
964
  if (top) {
827
965
  const cv = new OffscreenCanvas(dw, dh);
828
- const ctx = cv.getContext("2d");
966
+ const ctx = cv.getContext('2d');
829
967
  ctx.putImageData(bot, 0, 0);
830
968
  const t = new OffscreenCanvas(dw, dh);
831
- t.getContext("2d").putImageData(top, 0, 0);
969
+ t.getContext('2d').putImageData(top, 0, 0);
832
970
  ctx.globalAlpha = layers[aLi].opacity / 255;
833
971
  ctx.drawImage(t, 0, 0);
834
972
  cels.current.set(pixelEditorTypes.celKey(fi, aLi - 1), ctx.getImageData(0, 0, dw, dh));
@@ -849,8 +987,8 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
849
987
  setTick((t) => t + 1);
850
988
  }, [aLi, fc, layers, getCel, dw, dh, snap]);
851
989
  const dupLayer = React.useCallback(() => {
852
- snap("Duplicate Layer");
853
- const newL = { ...layers[aLi], id: pixelEditorTypes.lid(), name: layers[aLi].name + " copy" };
990
+ snap('Duplicate Layer');
991
+ const newL = { ...layers[aLi], id: pixelEditorTypes.lid(), name: layers[aLi].name + ' copy' };
854
992
  setLayers((ls) => [...ls.slice(0, aLi + 1), newL, ...ls.slice(aLi + 1)]);
855
993
  for (let fi = 0; fi < fc; fi++) {
856
994
  for (let li = layers.length; li > aLi; li--) {
@@ -861,27 +999,29 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
861
999
  }
862
1000
  }
863
1001
  const src = cels.current.get(pixelEditorTypes.celKey(fi, aLi));
864
- if (src)
1002
+ if (src) {
865
1003
  cels.current.set(pixelEditorTypes.celKey(fi, aLi + 1), pixelEditorUtils.cloneImageData(src));
1004
+ }
866
1005
  }
867
1006
  setALi(aLi + 1);
868
1007
  setTick((t) => t + 1);
869
1008
  }, [aLi, layers, fc, snap]);
870
1009
  /* ── frame management ── */
871
1010
  const addFrame = React.useCallback(() => {
872
- snap("Add Frame");
1011
+ snap('Add Frame');
873
1012
  setFc((n) => n + 1);
874
1013
  setFDur((d) => [...d, 100]);
875
1014
  setAfi(fc);
876
1015
  setTick((t) => t + 1);
877
1016
  }, [fc, snap]);
878
1017
  const dupFrame = React.useCallback(() => {
879
- snap("Dup Frame");
1018
+ snap('Dup Frame');
880
1019
  const ni = fc;
881
1020
  for (let li = 0; li < layers.length; li++) {
882
1021
  const c = cels.current.get(pixelEditorTypes.celKey(afi, li));
883
- if (c)
1022
+ if (c) {
884
1023
  cels.current.set(pixelEditorTypes.celKey(ni, li), pixelEditorUtils.cloneImageData(c));
1024
+ }
885
1025
  }
886
1026
  setFc((n) => n + 1);
887
1027
  setFDur((d) => [...d, fDur[afi] || 100]);
@@ -889,9 +1029,10 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
889
1029
  setTick((t) => t + 1);
890
1030
  }, [fc, afi, layers, fDur, snap]);
891
1031
  const rmFrame = React.useCallback(() => {
892
- if (fc <= 1)
1032
+ if (fc <= 1) {
893
1033
  return;
894
- snap("Remove Frame");
1034
+ }
1035
+ snap('Remove Frame');
895
1036
  for (let li = 0; li < layers.length; li++) {
896
1037
  cels.current.delete(pixelEditorTypes.celKey(afi, li));
897
1038
  for (let f = afi + 1; f < fc; f++) {
@@ -909,12 +1050,12 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
909
1050
  }, [fc, afi, layers, snap]);
910
1051
  /* ── canvas ops ── */
911
1052
  const flipCv = React.useCallback((dir) => {
912
- snap(`Flip ${dir === "h" ? "H" : "V"}`);
913
- cels.current.forEach((c, k) => cels.current.set(k, dir === "h" ? pixelEditorUtils.flipH(c) : pixelEditorUtils.flipV(c)));
1053
+ snap(`Flip ${dir === 'h' ? 'H' : 'V'}`);
1054
+ cels.current.forEach((c, k) => cels.current.set(k, dir === 'h' ? pixelEditorUtils.flipH(c) : pixelEditorUtils.flipV(c)));
914
1055
  setTick((t) => t + 1);
915
1056
  }, [snap]);
916
1057
  const rotateCv = React.useCallback(() => {
917
- snap("Rotate 90°");
1058
+ snap('Rotate 90°');
918
1059
  const n = new Map();
919
1060
  cels.current.forEach((c, k) => n.set(k, pixelEditorUtils.rotateCW(c)));
920
1061
  cels.current = n;
@@ -923,7 +1064,7 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
923
1064
  setTick((t) => t + 1);
924
1065
  }, [dw, dh, snap]);
925
1066
  const clearCv = React.useCallback(() => {
926
- snap("Clear");
1067
+ snap('Clear');
927
1068
  cels.current.set(pixelEditorTypes.celKey(afi, aLi), pixelEditorUtils.createBlankImageData(dw, dh));
928
1069
  setTick((t) => t + 1);
929
1070
  }, [afi, aLi, dw, dh, snap]);
@@ -931,7 +1072,16 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
931
1072
  setDw(w);
932
1073
  setDh(h);
933
1074
  cels.current = new Map();
934
- setLayers([{ id: pixelEditorTypes.lid(), name: "Background", visible: true, opacity: 255, locked: false, blendMode: "normal" }]);
1075
+ setLayers([
1076
+ {
1077
+ id: pixelEditorTypes.lid(),
1078
+ name: 'Background',
1079
+ visible: true,
1080
+ opacity: 255,
1081
+ locked: false,
1082
+ blendMode: 'normal',
1083
+ },
1084
+ ]);
935
1085
  setALi(0);
936
1086
  setFc(1);
937
1087
  setAfi(0);
@@ -953,49 +1103,60 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
953
1103
  // keyboard shortcuts
954
1104
  React.useEffect(() => {
955
1105
  const h = (e) => {
956
- if (dlgNew)
1106
+ if (dlgNew) {
957
1107
  return;
1108
+ }
958
1109
  const tgt = e.target;
959
- if (tgt.tagName === "INPUT" || tgt.tagName === "TEXTAREA" || tgt.tagName === "SELECT")
1110
+ if (tgt.tagName === 'INPUT' || tgt.tagName === 'TEXTAREA' || tgt.tagName === 'SELECT') {
960
1111
  return;
961
- if (e.ctrlKey && e.key === "z") {
1112
+ }
1113
+ if (e.ctrlKey && e.key === 'z') {
962
1114
  e.preventDefault();
963
1115
  undo();
964
1116
  return;
965
1117
  }
966
- if (e.ctrlKey && (e.key === "y" || (e.shiftKey && e.key === "Z"))) {
1118
+ if (e.ctrlKey && (e.key === 'y' || (e.shiftKey && e.key === 'Z'))) {
967
1119
  e.preventDefault();
968
1120
  redo();
969
1121
  return;
970
1122
  }
971
- if (e.ctrlKey && e.key === "c") {
1123
+ if (e.ctrlKey && e.key === 'c') {
972
1124
  e.preventDefault();
973
1125
  doCopy();
974
1126
  return;
975
1127
  }
976
- if (e.ctrlKey && e.key === "x") {
1128
+ if (e.ctrlKey && e.key === 'x') {
977
1129
  e.preventDefault();
978
1130
  doCut();
979
1131
  return;
980
1132
  }
981
- if (e.ctrlKey && e.key === "v") {
1133
+ if (e.ctrlKey && e.key === 'v') {
982
1134
  e.preventDefault();
983
1135
  doPaste();
984
1136
  return;
985
1137
  }
986
- if (e.ctrlKey && e.key === "a") {
1138
+ if (e.ctrlKey && e.key === 'a') {
987
1139
  e.preventDefault();
988
1140
  doSelectAll();
989
1141
  return;
990
1142
  }
991
- if (e.ctrlKey && e.key === "d") {
1143
+ if (e.ctrlKey && e.key === 'd') {
992
1144
  e.preventDefault();
993
1145
  doDeselectAll();
994
1146
  return;
995
1147
  }
996
1148
  const km = {
997
- b: "pencil", e: "eraser", g: "fill", l: "line", u: "rect",
998
- o: "ellipse", i: "eyedropper", m: "select", v: "move", h: "gradient", d: "dither",
1149
+ b: 'pencil',
1150
+ e: 'eraser',
1151
+ g: 'fill',
1152
+ l: 'line',
1153
+ u: 'rect',
1154
+ o: 'ellipse',
1155
+ i: 'eyedropper',
1156
+ m: 'select',
1157
+ v: 'move',
1158
+ h: 'gradient',
1159
+ d: 'dither',
999
1160
  };
1000
1161
  const k = e.key.toLowerCase();
1001
1162
  if (km[k]) {
@@ -1003,59 +1164,82 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
1003
1164
  return;
1004
1165
  }
1005
1166
  switch (k) {
1006
- case "+":
1007
- case "=":
1167
+ case '+':
1168
+ case '=':
1008
1169
  setZoom((z) => Math.min(64, z * 1.5));
1009
1170
  break;
1010
- case "-":
1171
+ case '-':
1011
1172
  setZoom((z) => Math.max(0.5, z / 1.5));
1012
1173
  break;
1013
- case "arrowleft":
1174
+ case 'arrowleft':
1014
1175
  setAfi((f) => Math.max(0, f - 1));
1015
1176
  break;
1016
- case "arrowright":
1177
+ case 'arrowright':
1017
1178
  setAfi((f) => Math.min(fc - 1, f + 1));
1018
1179
  break;
1019
- case "n":
1020
- if (!e.ctrlKey)
1180
+ case 'n':
1181
+ if (!e.ctrlKey) {
1021
1182
  addFrame();
1183
+ }
1022
1184
  break;
1023
- case "delete":
1024
- if (sel)
1185
+ case 'delete':
1186
+ if (sel) {
1025
1187
  doDeleteSel();
1026
- else
1188
+ }
1189
+ else {
1027
1190
  clearCv();
1191
+ }
1028
1192
  break;
1029
- case "x": {
1030
- setCol1((c) => { setCol2(c); return col2; });
1193
+ case 'x': {
1194
+ setCol1((c) => {
1195
+ setCol2(c);
1196
+ return col2;
1197
+ });
1031
1198
  break;
1032
1199
  }
1033
- case "[":
1200
+ case '[':
1034
1201
  setBrush((b) => ({ ...b, size: Math.max(1, b.size - 1) }));
1035
1202
  break;
1036
- case "]":
1203
+ case ']':
1037
1204
  setBrush((b) => ({ ...b, size: Math.min(64, b.size + 1) }));
1038
1205
  break;
1039
- case "f":
1206
+ case 'f':
1040
1207
  setShapeFilled((f) => !f);
1041
1208
  break;
1042
1209
  }
1043
1210
  };
1044
- window.addEventListener("keydown", h);
1045
- return () => window.removeEventListener("keydown", h);
1046
- }, [dlgNew, undo, redo, fc, addFrame, clearCv, col2, doCopy, doCut, doPaste, doSelectAll, doDeselectAll, doDeleteSel, sel]);
1211
+ window.addEventListener('keydown', h);
1212
+ return () => window.removeEventListener('keydown', h);
1213
+ }, [
1214
+ dlgNew,
1215
+ undo,
1216
+ redo,
1217
+ fc,
1218
+ addFrame,
1219
+ clearCv,
1220
+ col2,
1221
+ doCopy,
1222
+ doCut,
1223
+ doPaste,
1224
+ doSelectAll,
1225
+ doDeselectAll,
1226
+ doDeleteSel,
1227
+ sel,
1228
+ ]);
1047
1229
  // animation playback
1048
1230
  React.useEffect(() => {
1049
- if (!playing)
1231
+ if (!playing) {
1050
1232
  return;
1233
+ }
1051
1234
  const iv = setInterval(() => setAfi((f) => (f + 1) % fc), 1000 / fps);
1052
1235
  return () => clearInterval(iv);
1053
1236
  }, [playing, fc, fps]);
1054
1237
  // resize observer
1055
1238
  React.useEffect(() => {
1056
1239
  const el = boxRef.current;
1057
- if (!el)
1240
+ if (!el) {
1058
1241
  return;
1242
+ }
1059
1243
  const obs = new ResizeObserver(() => setTick((t) => t + 1));
1060
1244
  obs.observe(el);
1061
1245
  return () => obs.disconnect();
@@ -1064,20 +1248,22 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
1064
1248
  const thumbs = React.useMemo(() => {
1065
1249
  const out = [];
1066
1250
  for (let fi = 0; fi < fc; fi++) {
1067
- const cv = document.createElement("canvas");
1251
+ const cv = document.createElement('canvas');
1068
1252
  cv.width = dw;
1069
1253
  cv.height = dh;
1070
- const ctx = cv.getContext("2d");
1254
+ const ctx = cv.getContext('2d');
1071
1255
  for (let li = 0; li < layers.length; li++) {
1072
- if (!layers[li].visible)
1256
+ if (!layers[li].visible) {
1073
1257
  continue;
1258
+ }
1074
1259
  const c = cels.current.get(pixelEditorTypes.celKey(fi, li));
1075
- if (!c)
1260
+ if (!c) {
1076
1261
  continue;
1077
- const t = document.createElement("canvas");
1262
+ }
1263
+ const t = document.createElement('canvas');
1078
1264
  t.width = dw;
1079
1265
  t.height = dh;
1080
- t.getContext("2d").putImageData(c, 0, 0);
1266
+ t.getContext('2d').putImageData(c, 0, 0);
1081
1267
  ctx.globalAlpha = layers[li].opacity / 255;
1082
1268
  ctx.drawImage(t, 0, 0);
1083
1269
  }
@@ -1087,23 +1273,99 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
1087
1273
  }, [fc, dw, dh, layers, tick]);
1088
1274
  /* ── return API ── */
1089
1275
  return {
1090
- dw, dh, layers, aLi, setALi, fc, afi, setAfi, fDur,
1091
- tool, setTool, col1, setCol1, col2, setCol2,
1092
- brush, setBrush, zoom, setZoom, grid, setGrid, onion, setOnion,
1093
- fps, setFps, playing, setPlaying, pal, setPal,
1094
- cursor, setCursor, dlgNew, setDlgNew, nw, setNw, nh, setNh,
1095
- sel, setSel, symmetry, setSymmetry, shapeFilled, setShapeFilled,
1096
- pressure, showHSV, setShowHSV, editingLayerName, setEditingLayerName,
1097
- cvRef, boxRef, fInp, clipboard, drawing, panning,
1098
- undo, redo, openFile,
1099
- exportAse, exportPNG, exportJPG, exportWebP, exportBMP, exportSVG, exportSheet,
1276
+ dw,
1277
+ dh,
1278
+ layers,
1279
+ aLi,
1280
+ setALi,
1281
+ fc,
1282
+ afi,
1283
+ setAfi,
1284
+ fDur,
1285
+ tool,
1286
+ setTool,
1287
+ col1,
1288
+ setCol1,
1289
+ col2,
1290
+ setCol2,
1291
+ brush,
1292
+ setBrush,
1293
+ zoom,
1294
+ setZoom,
1295
+ grid,
1296
+ setGrid,
1297
+ onion,
1298
+ setOnion,
1299
+ fps,
1300
+ setFps,
1301
+ playing,
1302
+ setPlaying,
1303
+ pal,
1304
+ setPal,
1305
+ cursor,
1306
+ setCursor,
1307
+ dlgNew,
1308
+ setDlgNew,
1309
+ nw,
1310
+ setNw,
1311
+ nh,
1312
+ setNh,
1313
+ sel,
1314
+ setSel,
1315
+ symmetry,
1316
+ setSymmetry,
1317
+ shapeFilled,
1318
+ setShapeFilled,
1319
+ pressure,
1320
+ showHSV,
1321
+ setShowHSV,
1322
+ editingLayerName,
1323
+ setEditingLayerName,
1324
+ cvRef,
1325
+ boxRef,
1326
+ fInp,
1327
+ clipboard,
1328
+ drawing,
1329
+ panning,
1330
+ undo,
1331
+ redo,
1332
+ openFile,
1333
+ exportAse,
1334
+ exportPNG,
1335
+ exportJPG,
1336
+ exportWebP,
1337
+ exportBMP,
1338
+ exportSVG,
1339
+ exportSheet,
1100
1340
  saveToLibrary,
1101
- addLayer, rmLayer, toggleVis, toggleLock, setLayerOpacity, setLayerBlendMode,
1102
- renameLayer, moveLayerUp, moveLayerDown, mergeDown, dupLayer,
1103
- addFrame, dupFrame, rmFrame,
1104
- flipCv, rotateCv, clearCv, newDoc,
1105
- doCopy, doCut, doPaste, doDeleteSel, doSelectAll, doDeselectAll,
1106
- onDown, onMove, onUp, onWheel,
1341
+ addLayer,
1342
+ rmLayer,
1343
+ toggleVis,
1344
+ toggleLock,
1345
+ setLayerOpacity,
1346
+ setLayerBlendMode,
1347
+ renameLayer,
1348
+ moveLayerUp,
1349
+ moveLayerDown,
1350
+ mergeDown,
1351
+ dupLayer,
1352
+ addFrame,
1353
+ dupFrame,
1354
+ rmFrame,
1355
+ flipCv,
1356
+ rotateCv,
1357
+ clearCv,
1358
+ newDoc,
1359
+ doCopy,
1360
+ doCut,
1361
+ doPaste,
1362
+ doDeleteSel,
1363
+ doSelectAll,
1364
+ doDeselectAll,
1365
+ onDown,
1366
+ onMove,
1367
+ onUp,
1368
+ onWheel,
1107
1369
  thumbs,
1108
1370
  importImageData: React.useCallback((img) => {
1109
1371
  snap('import generator');
@@ -1119,7 +1381,7 @@ function usePixelEditor({ initialWidth = 64, initialHeight = 64, onSaveToLibrary
1119
1381
  ctx.drawImage(src, 0, 0);
1120
1382
  const merged = ctx.getImageData(0, 0, dw, dh);
1121
1383
  cel.data.set(merged.data);
1122
- setTick(t => t + 1);
1384
+ setTick((t) => t + 1);
1123
1385
  }, [snap, getCel, afi, aLi, dw, dh]),
1124
1386
  };
1125
1387
  }