@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,228 +1,1090 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var uiCore = require('@nice2dev/ui-core');
5
- var React = require('react');
6
- var LocalUI = require('../core/LocalUI.js');
7
- var FilterThumb = require('./FilterThumb.js');
8
- var PhotoEditor_module = require('./PhotoEditor.module.css.js');
9
- var photoEditorTypes = require('./photoEditorTypes.js');
10
- var photoFilters = require('./photoFilters.js');
11
- var photoOverlays = require('./photoOverlays.js');
12
-
13
- // ── Overlay Toolbar (extracted from the original inline function) ──
1
+ "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const uiCore = require("@nice2dev/ui-core");
5
+ const React = require("react");
6
+ const LocalUI = require("../core/LocalUI.js");
7
+ const FilterThumb = require("./FilterThumb.js");
8
+ const PhotoEditor_module = require("./PhotoEditor.module.css.js");
9
+ const photoEditorTypes = require("./photoEditorTypes.js");
10
+ const photoFilters = require("./photoFilters.js");
11
+ const photoOverlays = require("./photoOverlays.js");
14
12
  const OverlayToolbar = ({ api }) => {
15
- var _a, _b, _c, _d, _e;
16
- const { selectedOverlay, accent, t, updateOverlay, pushHistory, moveOverlayBack, moveOverlayForward, deleteOverlay, } = api;
17
- if (!selectedOverlay) {
18
- return null;
19
- }
20
- return (jsxRuntime.jsxs("div", { className: PhotoEditor_module.overlayToolbar, children: [jsxRuntime.jsxs("span", { className: PhotoEditor_module.overlayToolbarLabel, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "box", size: 14, style: { marginRight: 4 } }), t('photoEditor.layer', 'Layer')] }), jsxRuntime.jsx(LocalUI.RangeInput, { min: 0, max: 100, value: ((_a = selectedOverlay.opacity) !== null && _a !== void 0 ? _a : 1) * 100, onChange: (e) => updateOverlay(selectedOverlay.id, { opacity: Number(e.target.value) / 100 }), onMouseUp: pushHistory, accentColor: accent, style: { maxWidth: 70 }, title: t('photoEditor.opacity', 'Opacity') }), jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderValueSm, style: { color: accent }, children: [Math.round(((_b = selectedOverlay.opacity) !== null && _b !== void 0 ? _b : 1) * 100), "%"] }), selectedOverlay.type !== 'drawing' && selectedOverlay.type !== 'frame' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(LocalUI.RangeInput, { min: 20, max: 500, value: ((_c = selectedOverlay.scaleX) !== null && _c !== void 0 ? _c : 1) * 100, onChange: (e) => {
21
- const s = Number(e.target.value) / 100;
22
- updateOverlay(selectedOverlay.id, { scaleX: s, scaleY: s });
23
- }, onMouseUp: pushHistory, accentColor: accent, style: { maxWidth: 60 }, title: t('photoEditor.scale', 'Scale') }), jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderValueSm, style: { color: 'var(--nice-text-muted, #aaa)' }, children: [Math.round(((_d = selectedOverlay.scaleX) !== null && _d !== void 0 ? _d : 1) * 100), "%"] })] })), selectedOverlay.type !== 'drawing' && selectedOverlay.type !== 'frame' && (jsxRuntime.jsx(LocalUI.RangeInput, { min: -180, max: 180, value: (_e = selectedOverlay.rotation) !== null && _e !== void 0 ? _e : 0, onChange: (e) => updateOverlay(selectedOverlay.id, { rotation: Number(e.target.value) }), onMouseUp: pushHistory, accentColor: accent, style: { maxWidth: 60 }, title: t('photoEditor.rotation', 'Rotation') })), jsxRuntime.jsx(LocalUI.Button, { variant: "dark", size: "sm", onClick: () => moveOverlayBack(selectedOverlay.id), title: t('photoEditor.moveBack', 'Move back'), className: PhotoEditor_module.overlayToolbarBtn, children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-down", size: 14 }) }), jsxRuntime.jsx(LocalUI.Button, { variant: "dark", size: "sm", onClick: () => moveOverlayForward(selectedOverlay.id), title: t('photoEditor.moveForward', 'Move forward'), className: PhotoEditor_module.overlayToolbarBtn, children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-up", size: 14 }) }), jsxRuntime.jsx(LocalUI.Button, { variant: "outline-danger", size: "sm", onClick: () => deleteOverlay(selectedOverlay.id), className: PhotoEditor_module.overlayToolbarBtn, title: t('photoEditor.deleteLayer', 'Delete layer'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "trash", size: 14 }) })] }));
13
+ const {
14
+ selectedOverlay,
15
+ accent,
16
+ t,
17
+ updateOverlay,
18
+ pushHistory,
19
+ moveOverlayBack,
20
+ moveOverlayForward,
21
+ deleteOverlay
22
+ } = api;
23
+ if (!selectedOverlay) {
24
+ return null;
25
+ }
26
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.overlayToolbar, children: [
27
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.overlayToolbarLabel, children: [
28
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "box", size: 14, style: { marginRight: 4 } }),
29
+ t("photoEditor.layer", "Layer")
30
+ ] }),
31
+ /* @__PURE__ */ jsxRuntime.jsx(
32
+ LocalUI.RangeInput,
33
+ {
34
+ min: 0,
35
+ max: 100,
36
+ value: (selectedOverlay.opacity ?? 1) * 100,
37
+ onChange: (e) => updateOverlay(selectedOverlay.id, { opacity: Number(e.target.value) / 100 }),
38
+ onMouseUp: pushHistory,
39
+ accentColor: accent,
40
+ style: { maxWidth: 70 },
41
+ title: t("photoEditor.opacity", "Opacity")
42
+ }
43
+ ),
44
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderValueSm, style: { color: accent }, children: [
45
+ Math.round((selectedOverlay.opacity ?? 1) * 100),
46
+ "%"
47
+ ] }),
48
+ selectedOverlay.type !== "drawing" && selectedOverlay.type !== "frame" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
49
+ /* @__PURE__ */ jsxRuntime.jsx(
50
+ LocalUI.RangeInput,
51
+ {
52
+ min: 20,
53
+ max: 500,
54
+ value: (selectedOverlay.scaleX ?? 1) * 100,
55
+ onChange: (e) => {
56
+ const s = Number(e.target.value) / 100;
57
+ updateOverlay(selectedOverlay.id, { scaleX: s, scaleY: s });
58
+ },
59
+ onMouseUp: pushHistory,
60
+ accentColor: accent,
61
+ style: { maxWidth: 60 },
62
+ title: t("photoEditor.scale", "Scale")
63
+ }
64
+ ),
65
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderValueSm, style: { color: "var(--nice-text-muted, #aaa)" }, children: [
66
+ Math.round((selectedOverlay.scaleX ?? 1) * 100),
67
+ "%"
68
+ ] })
69
+ ] }),
70
+ selectedOverlay.type !== "drawing" && selectedOverlay.type !== "frame" && /* @__PURE__ */ jsxRuntime.jsx(
71
+ LocalUI.RangeInput,
72
+ {
73
+ min: -180,
74
+ max: 180,
75
+ value: selectedOverlay.rotation ?? 0,
76
+ onChange: (e) => updateOverlay(selectedOverlay.id, { rotation: Number(e.target.value) }),
77
+ onMouseUp: pushHistory,
78
+ accentColor: accent,
79
+ style: { maxWidth: 60 },
80
+ title: t("photoEditor.rotation", "Rotation")
81
+ }
82
+ ),
83
+ /* @__PURE__ */ jsxRuntime.jsx(
84
+ LocalUI.Button,
85
+ {
86
+ variant: "dark",
87
+ size: "sm",
88
+ onClick: () => moveOverlayBack(selectedOverlay.id),
89
+ title: t("photoEditor.moveBack", "Move back"),
90
+ className: PhotoEditor_module.default.overlayToolbarBtn,
91
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-down", size: 14 })
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsxRuntime.jsx(
95
+ LocalUI.Button,
96
+ {
97
+ variant: "dark",
98
+ size: "sm",
99
+ onClick: () => moveOverlayForward(selectedOverlay.id),
100
+ title: t("photoEditor.moveForward", "Move forward"),
101
+ className: PhotoEditor_module.default.overlayToolbarBtn,
102
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "arrow-up", size: 14 })
103
+ }
104
+ ),
105
+ /* @__PURE__ */ jsxRuntime.jsx(
106
+ LocalUI.Button,
107
+ {
108
+ variant: "outline-danger",
109
+ size: "sm",
110
+ onClick: () => deleteOverlay(selectedOverlay.id),
111
+ className: PhotoEditor_module.default.overlayToolbarBtn,
112
+ title: t("photoEditor.deleteLayer", "Delete layer"),
113
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "trash", size: 14 })
114
+ }
115
+ )
116
+ ] });
24
117
  };
25
- // ── Left Panel ──
26
118
  const PhotoEditorLeftPanel = /* @__PURE__ */ Object.assign(
27
- /* @__PURE__ */ React.memo(({ api }) => {
28
- var _a;
29
- const { t, accent, accentDim, activeTab, setActiveTab, setCropMode,
30
- // Filters
31
- selectedFilter, setSelectedFilter, filterIntensity, setFilterIntensity, filterCategory, setFilterCategory, filteredList, generateThumbnail, pushHistory,
32
- // Adjustments
33
- adjustments, handleAdjChange, handleAdjChangeEnd,
34
- // Crop
35
- image, cropRect, setCropRect, cropAspect, setCropAspect,
36
- // Transform
37
- rotation, setRotation, flipH, setFlipH, flipV, setFlipV, zoom, setZoom,
38
- // Overlays
39
- overlays, setOverlays, selectedOverlayId, setSelectedOverlayId, addOverlay, deleteOverlay, mainCanvasRef,
40
- // Stickers / Emoji
41
- emojiCat, setEmojiCat,
42
- // Text
43
- textDraft, setTextDraft, textColor, setTextColor, textBold, setTextBold, textItalic, setTextItalic, textOutline, setTextOutline, textFontSize, setTextFontSize, textBg, setTextBg, selectedOverlay, updateOverlay,
44
- // Shapes
45
- shapeStroke, setShapeStroke, shapeFill, setShapeFill, shapeStrokeW, setShapeStrokeW,
46
- // Frame
47
- frameColor, setFrameColor, frameThick, setFrameThick,
48
- // Drawing
49
- drawColor, setDrawColor, drawWidth, setDrawWidth, drawingOverlayRef,
50
- // Creators
51
- createEmojiOverlay, createTextOverlay, createShapeOverlay, createFrameOverlay, } = api;
52
- return (jsxRuntime.jsxs("div", { className: PhotoEditor_module.leftPanel, children: [jsxRuntime.jsx("div", { className: PhotoEditor_module.tabBar, children: photoEditorTypes.TAB_DEFS.map((tab) => (jsxRuntime.jsxs("button", { onClick: () => {
53
- setActiveTab(tab.key);
54
- if (tab.key === 'crop') {
55
- setCropMode(true);
119
+ /* @__PURE__ */ React.memo(({ api }) => {
120
+ const {
121
+ t,
122
+ accent,
123
+ accentDim,
124
+ activeTab,
125
+ setActiveTab,
126
+ setCropMode,
127
+ // Filters
128
+ selectedFilter,
129
+ setSelectedFilter,
130
+ filterIntensity,
131
+ setFilterIntensity,
132
+ filterCategory,
133
+ setFilterCategory,
134
+ filteredList,
135
+ generateThumbnail,
136
+ pushHistory,
137
+ // Adjustments
138
+ adjustments,
139
+ handleAdjChange,
140
+ handleAdjChangeEnd,
141
+ // Crop
142
+ image,
143
+ cropRect,
144
+ setCropRect,
145
+ cropAspect,
146
+ setCropAspect,
147
+ // Transform
148
+ rotation,
149
+ setRotation,
150
+ flipH,
151
+ setFlipH,
152
+ flipV,
153
+ setFlipV,
154
+ zoom,
155
+ setZoom,
156
+ // Overlays
157
+ overlays,
158
+ setOverlays,
159
+ selectedOverlayId,
160
+ setSelectedOverlayId,
161
+ addOverlay,
162
+ deleteOverlay,
163
+ mainCanvasRef,
164
+ // Stickers / Emoji
165
+ emojiCat,
166
+ setEmojiCat,
167
+ // Text
168
+ textDraft,
169
+ setTextDraft,
170
+ textColor,
171
+ setTextColor,
172
+ textBold,
173
+ setTextBold,
174
+ textItalic,
175
+ setTextItalic,
176
+ textOutline,
177
+ setTextOutline,
178
+ textFontSize,
179
+ setTextFontSize,
180
+ textBg,
181
+ setTextBg,
182
+ selectedOverlay,
183
+ updateOverlay,
184
+ // Shapes
185
+ shapeStroke,
186
+ setShapeStroke,
187
+ shapeFill,
188
+ setShapeFill,
189
+ shapeStrokeW,
190
+ setShapeStrokeW,
191
+ // Frame
192
+ frameColor,
193
+ setFrameColor,
194
+ frameThick,
195
+ setFrameThick,
196
+ // Drawing
197
+ drawColor,
198
+ setDrawColor,
199
+ drawWidth,
200
+ setDrawWidth,
201
+ drawingOverlayRef,
202
+ // Creators
203
+ createEmojiOverlay,
204
+ createTextOverlay,
205
+ createShapeOverlay,
206
+ createFrameOverlay
207
+ } = api;
208
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.leftPanel, children: [
209
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.tabBar, children: photoEditorTypes.TAB_DEFS.map((tab) => /* @__PURE__ */ jsxRuntime.jsxs(
210
+ "button",
211
+ {
212
+ onClick: () => {
213
+ setActiveTab(tab.key);
214
+ if (tab.key === "crop") {
215
+ setCropMode(true);
216
+ } else {
217
+ setCropMode(false);
218
+ }
219
+ },
220
+ title: tab.label,
221
+ className: activeTab === tab.key ? PhotoEditor_module.default.tabButtonActive : PhotoEditor_module.default.tabButton,
222
+ style: {
223
+ color: activeTab === tab.key ? accent : void 0,
224
+ borderBottomColor: activeTab === tab.key ? accent : void 0
225
+ },
226
+ children: [
227
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: tab.icon, size: 14 }),
228
+ tab.label
229
+ ]
230
+ },
231
+ tab.key
232
+ )) }),
233
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.panelContent, children: [
234
+ activeTab === "filters" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
235
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.pillRow, children: [
236
+ { key: "all", label: t("photoEditor.all", "All") },
237
+ { key: "color", label: t("photoEditor.color", "Color") },
238
+ { key: "light", label: t("photoEditor.light", "Light") },
239
+ { key: "vintage", label: t("photoEditor.vintage", "Vintage") },
240
+ { key: "artistic", label: t("photoEditor.artistic", "Artistic") },
241
+ { key: "fun", label: t("photoEditor.fun", "Fun") }
242
+ ].map((cat) => /* @__PURE__ */ jsxRuntime.jsx(
243
+ "button",
244
+ {
245
+ onClick: () => setFilterCategory(cat.key),
246
+ className: filterCategory === cat.key ? PhotoEditor_module.default.pillActive : PhotoEditor_module.default.pill,
247
+ style: {
248
+ borderColor: filterCategory === cat.key ? accent : void 0,
249
+ background: filterCategory === cat.key ? accentDim : void 0
250
+ },
251
+ children: cat.label
252
+ },
253
+ cat.key
254
+ )) }),
255
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.filterGrid, children: filteredList.map((filter) => /* @__PURE__ */ jsxRuntime.jsx(
256
+ FilterThumb.default,
257
+ {
258
+ filter,
259
+ selected: selectedFilter === filter.id,
260
+ accent,
261
+ onSelect: () => {
262
+ setSelectedFilter(filter.id);
263
+ pushHistory();
264
+ },
265
+ generateThumbnail
266
+ },
267
+ filter.id
268
+ )) }),
269
+ selectedFilter !== "none" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.intensitySection, children: [
270
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.intensityHeader, children: [
271
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderLabel, children: [
272
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "bar-chart", size: 14, style: { marginRight: 4 } }),
273
+ t("photoEditor.intensity", "Intensity")
274
+ ] }),
275
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderValue, style: { color: accent }, children: [
276
+ Math.round(filterIntensity * 100),
277
+ "%"
278
+ ] })
279
+ ] }),
280
+ /* @__PURE__ */ jsxRuntime.jsx(
281
+ LocalUI.RangeInput,
282
+ {
283
+ min: 0,
284
+ max: 100,
285
+ value: filterIntensity * 100,
286
+ onChange: (e) => setFilterIntensity(Number(e.target.value) / 100),
287
+ onMouseUp: () => pushHistory(),
288
+ accentColor: accent
289
+ }
290
+ )
291
+ ] })
292
+ ] }),
293
+ activeTab === "adjust" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.adjustColumn, children: [
294
+ photoEditorTypes.ADJUSTMENT_SLIDERS.map((sl) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
295
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.adjustHeader, children: [
296
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderLabel, children: [
297
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: sl.icon, size: 14, style: { marginRight: 4 } }),
298
+ sl.label
299
+ ] }),
300
+ /* @__PURE__ */ jsxRuntime.jsx(
301
+ "span",
302
+ {
303
+ role: "button",
304
+ tabIndex: 0,
305
+ "aria-label": t("photoEditor.reset", "Reset"),
306
+ onKeyDown: uiCore.clickOnActivationKey,
307
+ className: PhotoEditor_module.default.adjustValue,
308
+ style: {
309
+ color: adjustments[sl.key] !== 0 ? accent : "var(--nice-text-secondary, #666)"
310
+ },
311
+ onClick: () => handleAdjChange(sl.key, sl.key === "blur" ? 0 : 0),
312
+ title: t("photoEditor.reset", "Reset"),
313
+ children: adjustments[sl.key]
314
+ }
315
+ )
316
+ ] }),
317
+ /* @__PURE__ */ jsxRuntime.jsx(
318
+ LocalUI.RangeInput,
319
+ {
320
+ min: sl.min,
321
+ max: sl.max,
322
+ value: adjustments[sl.key],
323
+ onChange: (e) => handleAdjChange(sl.key, Number(e.target.value)),
324
+ onMouseUp: handleAdjChangeEnd,
325
+ accentColor: accent
326
+ }
327
+ )
328
+ ] }, sl.key)),
329
+ /* @__PURE__ */ jsxRuntime.jsxs(
330
+ LocalUI.Button,
331
+ {
332
+ variant: "outline-secondary",
333
+ size: "sm",
334
+ className: "mt-2",
335
+ onClick: () => {
336
+ handleAdjChange("brightness", 0);
337
+ const defaults = { ...photoFilters.DEFAULT_ADJUSTMENTS };
338
+ for (const key of Object.keys(defaults)) {
339
+ handleAdjChange(key, defaults[key]);
340
+ }
341
+ pushHistory();
342
+ },
343
+ children: [
344
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "refresh", size: 14, style: { marginRight: 4 } }),
345
+ t("photoEditor.resetAdjustments", "Reset adjustments")
346
+ ]
347
+ }
348
+ )
349
+ ] }),
350
+ activeTab === "crop" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
351
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.cropInfo, children: [
352
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "info", size: 14, style: { marginRight: 4 } }),
353
+ t("photoEditor.dragCornersOrEdgesTo", "Drag corners or edges to crop the photo.")
354
+ ] }),
355
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.cropAspectLabel, children: t("photoEditor.aspectRatio", "Aspect ratio") }),
356
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.cropAspectRow, children: photoEditorTypes.ASPECT_RATIOS.map((ar) => /* @__PURE__ */ jsxRuntime.jsx(
357
+ "button",
358
+ {
359
+ onClick: () => {
360
+ setCropAspect(ar.value);
361
+ if (ar.value && cropRect && image) {
362
+ let newW = cropRect.w;
363
+ let newH = cropRect.w / ar.value;
364
+ if (newH > image.naturalHeight) {
365
+ newH = image.naturalHeight;
366
+ newW = newH * ar.value;
367
+ }
368
+ setCropRect({
369
+ x: Math.max(0, cropRect.x),
370
+ y: Math.max(0, cropRect.y),
371
+ w: Math.min(newW, image.naturalWidth),
372
+ h: Math.min(newH, image.naturalHeight)
373
+ });
374
+ }
375
+ },
376
+ className: cropAspect === ar.value ? PhotoEditor_module.default.pillCropActive : PhotoEditor_module.default.pillCrop,
377
+ style: {
378
+ borderColor: cropAspect === ar.value ? accent : void 0,
379
+ background: cropAspect === ar.value ? accentDim : void 0
380
+ },
381
+ children: ar.label
382
+ },
383
+ ar.label
384
+ )) }),
385
+ /* @__PURE__ */ jsxRuntime.jsxs(
386
+ LocalUI.Button,
387
+ {
388
+ variant: "outline-secondary",
389
+ size: "sm",
390
+ className: "mt-3",
391
+ onClick: () => {
392
+ if (image) {
393
+ setCropRect({ x: 0, y: 0, w: image.naturalWidth, h: image.naturalHeight });
394
+ setCropAspect(null);
395
+ pushHistory();
396
+ }
397
+ },
398
+ children: [
399
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "expand", size: 14, style: { marginRight: 4 } }),
400
+ t("photoEditor.resetCrop", "Reset crop")
401
+ ]
402
+ }
403
+ )
404
+ ] }),
405
+ activeTab === "transform" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
406
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.sectionTitleMb8, children: t("photoEditor.rotation", "Rotation") }),
407
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.transformRow, children: [
408
+ /* @__PURE__ */ jsxRuntime.jsxs(
409
+ LocalUI.Button,
410
+ {
411
+ variant: "dark",
412
+ size: "sm",
413
+ onClick: () => {
414
+ setRotation((rotation - 90 + 360) % 360);
415
+ pushHistory();
416
+ },
417
+ children: [
418
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "reply", size: 14, style: { marginRight: 4 } }),
419
+ " -90°"
420
+ ]
421
+ }
422
+ ),
423
+ /* @__PURE__ */ jsxRuntime.jsxs(
424
+ LocalUI.Button,
425
+ {
426
+ variant: "dark",
427
+ size: "sm",
428
+ onClick: () => {
429
+ setRotation((rotation + 90) % 360);
430
+ pushHistory();
431
+ },
432
+ children: [
433
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "forward", size: 14, style: { marginRight: 4 } }),
434
+ " +90°"
435
+ ]
436
+ }
437
+ ),
438
+ /* @__PURE__ */ jsxRuntime.jsx(
439
+ LocalUI.Button,
440
+ {
441
+ variant: "dark",
442
+ size: "sm",
443
+ onClick: () => {
444
+ setRotation(0);
445
+ pushHistory();
446
+ },
447
+ children: "0°"
448
+ }
449
+ )
450
+ ] }),
451
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.sectionTitleMb8, children: t("photoEditor.flip", "Flip") }),
452
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.transformRow, children: [
453
+ /* @__PURE__ */ jsxRuntime.jsxs(
454
+ LocalUI.Button,
455
+ {
456
+ variant: flipH ? "outline-info" : "dark",
457
+ size: "sm",
458
+ onClick: () => {
459
+ setFlipH(!flipH);
460
+ pushHistory();
461
+ },
462
+ children: [
463
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "move", size: 14, style: { marginRight: 4 } }),
464
+ " ",
465
+ t("photoEditor.horizontal", "Horizontal")
466
+ ]
467
+ }
468
+ ),
469
+ /* @__PURE__ */ jsxRuntime.jsxs(
470
+ LocalUI.Button,
471
+ {
472
+ variant: flipV ? "outline-info" : "dark",
473
+ size: "sm",
474
+ onClick: () => {
475
+ setFlipV(!flipV);
476
+ pushHistory();
477
+ },
478
+ children: [
479
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "move", size: 14, style: { marginRight: 4 } }),
480
+ " ",
481
+ t("photoEditor.vertical", "Vertical")
482
+ ]
483
+ }
484
+ )
485
+ ] }),
486
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.sectionTitleMb8, children: t("photoEditor.previewZoom", "Preview zoom") }),
487
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.transformZoomRow, children: [
488
+ /* @__PURE__ */ jsxRuntime.jsx(
489
+ LocalUI.RangeInput,
490
+ {
491
+ min: 50,
492
+ max: 300,
493
+ value: zoom * 100,
494
+ onChange: (e) => setZoom(Number(e.target.value) / 100),
495
+ accentColor: accent
496
+ }
497
+ ),
498
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.transformZoomValue, style: { color: accent }, children: [
499
+ Math.round(zoom * 100),
500
+ "%"
501
+ ] })
502
+ ] }),
503
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.transformInfo, children: [
504
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
505
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: t("photoEditor.rotation2", "Rotation:") }),
506
+ " ",
507
+ rotation,
508
+ "°"
509
+ ] }),
510
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
511
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: t("photoEditor.flipH", "Flip H:") }),
512
+ " ",
513
+ flipH ? t("photoEditor.yes", "Yes") : t("photoEditor.no", "No")
514
+ ] }),
515
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
516
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: t("photoEditor.flipV", "Flip V:") }),
517
+ " ",
518
+ flipV ? t("photoEditor.yes", "Yes") : t("photoEditor.no", "No")
519
+ ] }),
520
+ cropRect && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
521
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: t("photoEditor.crop", "Crop:") }),
522
+ " ",
523
+ Math.round(cropRect.w),
524
+ " ×",
525
+ " ",
526
+ Math.round(cropRect.h),
527
+ " (",
528
+ "x:",
529
+ Math.round(cropRect.x),
530
+ ", y:",
531
+ Math.round(cropRect.y),
532
+ ")"
533
+ ] })
534
+ ] })
535
+ ] }),
536
+ activeTab === "stickers" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
537
+ /* @__PURE__ */ jsxRuntime.jsx(OverlayToolbar, { api }),
538
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sectionTitle, children: [
539
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "circle", size: 14, style: { marginRight: 4 } }),
540
+ " ",
541
+ t("photoEditor.stickersEmoji", "Stickers / Emoji")
542
+ ] }),
543
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.pillRowGap3, children: photoOverlays.EMOJI_CATALOG.map((cat) => /* @__PURE__ */ jsxRuntime.jsxs(
544
+ "button",
545
+ {
546
+ onClick: () => setEmojiCat(cat.id),
547
+ className: emojiCat === cat.id ? PhotoEditor_module.default.pillEmojiActive : PhotoEditor_module.default.pillEmoji,
548
+ style: {
549
+ borderColor: emojiCat === cat.id ? accent : void 0,
550
+ background: emojiCat === cat.id ? accentDim : void 0
551
+ },
552
+ children: [
553
+ cat.icon,
554
+ " ",
555
+ cat.label
556
+ ]
557
+ },
558
+ cat.id
559
+ )) }),
560
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.emojiGrid, children: photoOverlays.EMOJI_CATALOG.find((c) => c.id === emojiCat)?.emojis.map((em, idx) => /* @__PURE__ */ jsxRuntime.jsx(
561
+ "button",
562
+ {
563
+ onClick: () => {
564
+ const cw = mainCanvasRef.current?.width ?? 400;
565
+ const ch = mainCanvasRef.current?.height ?? 400;
566
+ addOverlay(createEmojiOverlay(em, cw, ch));
567
+ },
568
+ className: PhotoEditor_module.default.emojiBtn,
569
+ title: em,
570
+ children: em
571
+ },
572
+ idx
573
+ )) }),
574
+ overlays.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.overlaySection, children: [
575
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.overlaySectionTitle, children: t("photoEditor.layers", "Layers ({overlays})").replace(
576
+ "{overlays}",
577
+ String(overlays.length)
578
+ ) }),
579
+ overlays.map((ov) => /* @__PURE__ */ jsxRuntime.jsxs(
580
+ "div",
581
+ {
582
+ role: "button",
583
+ tabIndex: 0,
584
+ onKeyDown: uiCore.clickOnActivationKey,
585
+ onClick: () => setSelectedOverlayId(ov.id),
586
+ className: PhotoEditor_module.default.overlayItem,
587
+ style: { background: selectedOverlayId === ov.id ? accentDim : void 0 },
588
+ children: [
589
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.overlayIcon, children: ov.type === "emoji" ? ov.emoji : ov.type === "text" ? "T" : ov.type === "shape" ? /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "star", size: 14 }) : ov.type === "drawing" ? /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "pen", size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "square", size: 14 }) }),
590
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.overlayName, children: ov.type === "text" ? ov.text.slice(0, 20) : ov.type === "emoji" ? t("photoEditor.emoji", "Emoji") : ov.type === "shape" ? ov.shapeKind : ov.type === "drawing" ? t("photoEditor.drawing", "Drawing ({strokes})").replace(
591
+ "{strokes}",
592
+ String(ov.strokes.length)
593
+ ) : ov.type === "frame" ? ov.frameStyle : "" }),
594
+ /* @__PURE__ */ jsxRuntime.jsx(
595
+ "button",
596
+ {
597
+ onClick: (e) => {
598
+ e.stopPropagation();
599
+ deleteOverlay(ov.id);
600
+ },
601
+ className: PhotoEditor_module.default.overlayDeleteBtn,
602
+ "aria-label": t("photoEditor.deleteLayer", "Delete layer"),
603
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 })
604
+ }
605
+ )
606
+ ]
607
+ },
608
+ ov.id
609
+ ))
610
+ ] })
611
+ ] }),
612
+ activeTab === "text" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
613
+ /* @__PURE__ */ jsxRuntime.jsx(OverlayToolbar, { api }),
614
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sectionTitleMb8, children: [
615
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "type", size: 14, style: { marginRight: 4 } }),
616
+ " ",
617
+ t("photoEditor.addCaption", "Add caption")
618
+ ] }),
619
+ /* @__PURE__ */ jsxRuntime.jsx(
620
+ LocalUI.TextArea,
621
+ {
622
+ rows: 2,
623
+ value: textDraft,
624
+ onChange: (e) => setTextDraft(e.target.value),
625
+ placeholder: t("photoEditor.textPlaceholder", "Enter text…"),
626
+ className: PhotoEditor_module.default.textArea
627
+ }
628
+ ),
629
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.textBtnRow, children: [
630
+ /* @__PURE__ */ jsxRuntime.jsx(
631
+ LocalUI.Button,
632
+ {
633
+ variant: textBold ? "light" : "dark",
634
+ size: "sm",
635
+ onClick: () => setTextBold(!textBold),
636
+ title: t("photoEditor.bold", "Bold"),
637
+ className: PhotoEditor_module.default.textFormatBtn,
638
+ style: { fontWeight: 700 },
639
+ children: "B"
640
+ }
641
+ ),
642
+ /* @__PURE__ */ jsxRuntime.jsx(
643
+ LocalUI.Button,
644
+ {
645
+ variant: textItalic ? "light" : "dark",
646
+ size: "sm",
647
+ onClick: () => setTextItalic(!textItalic),
648
+ title: t("photoEditor.italic", "Italic"),
649
+ className: PhotoEditor_module.default.textFormatBtn,
650
+ style: { fontStyle: "italic" },
651
+ children: "I"
652
+ }
653
+ ),
654
+ /* @__PURE__ */ jsxRuntime.jsx(
655
+ LocalUI.Button,
656
+ {
657
+ variant: textOutline ? "light" : "dark",
658
+ size: "sm",
659
+ onClick: () => setTextOutline(!textOutline),
660
+ title: t("photoEditor.outline", "Outline"),
661
+ className: PhotoEditor_module.default.textFormatBtn,
662
+ children: "O"
663
+ }
664
+ ),
665
+ /* @__PURE__ */ jsxRuntime.jsx(
666
+ LocalUI.Button,
667
+ {
668
+ variant: textBg ? "light" : "dark",
669
+ size: "sm",
670
+ onClick: () => setTextBg(!textBg),
671
+ title: t("photoEditor.background", "Background"),
672
+ className: PhotoEditor_module.default.textFormatBtn,
673
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "square", size: 14 })
674
+ }
675
+ ),
676
+ /* @__PURE__ */ jsxRuntime.jsx(
677
+ "input",
678
+ {
679
+ type: "color",
680
+ value: textColor,
681
+ onChange: (e) => setTextColor(e.target.value),
682
+ className: PhotoEditor_module.default.colorInputLg,
683
+ title: t("photoEditor.textColour", "Text colour")
684
+ }
685
+ )
686
+ ] }),
687
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sliderRow, children: [
688
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderLabel, children: [
689
+ t("photoEditor.size", "Size"),
690
+ ":"
691
+ ] }),
692
+ /* @__PURE__ */ jsxRuntime.jsx(
693
+ LocalUI.RangeInput,
694
+ {
695
+ min: 12,
696
+ max: 120,
697
+ value: textFontSize,
698
+ onChange: (e) => setTextFontSize(Number(e.target.value)),
699
+ accentColor: accent,
700
+ style: { flex: 1 }
701
+ }
702
+ ),
703
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderValue, style: { color: accent }, children: [
704
+ textFontSize,
705
+ "px"
706
+ ] })
707
+ ] }),
708
+ /* @__PURE__ */ jsxRuntime.jsxs(
709
+ LocalUI.Button,
710
+ {
711
+ size: "sm",
712
+ className: PhotoEditor_module.default.accentBtn,
713
+ style: { background: accent, borderColor: accent },
714
+ disabled: !textDraft.trim(),
715
+ onClick: () => {
716
+ const ov = createTextOverlay(textDraft);
717
+ ov.color = textColor;
718
+ ov.bold = textBold;
719
+ ov.italic = textItalic;
720
+ ov.fontSize = textFontSize;
721
+ ov.outlineColor = textOutline ? "#000000" : null;
722
+ ov.outlineWidth = textOutline ? 2 : 0;
723
+ ov.background = textBg ? "rgba(0, 0, 0, 0.5)" : null;
724
+ addOverlay(ov);
725
+ },
726
+ children: [
727
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "plus", size: 14, style: { marginRight: 4 } }),
728
+ " ",
729
+ t("photoEditor.addText", "Add text")
730
+ ]
731
+ }
732
+ ),
733
+ selectedOverlay?.type === "text" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.editSelectedSection, children: [
734
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.editSelectedLabel, children: t("photoEditor.editSelectedText", "Edit selected text:") }),
735
+ /* @__PURE__ */ jsxRuntime.jsx(
736
+ LocalUI.TextArea,
737
+ {
738
+ rows: 2,
739
+ value: selectedOverlay.text,
740
+ onChange: (e) => updateOverlay(selectedOverlay.id, { text: e.target.value }),
741
+ onBlur: pushHistory,
742
+ className: PhotoEditor_module.default.textAreaSm
743
+ }
744
+ ),
745
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.textGapRow, children: [
746
+ /* @__PURE__ */ jsxRuntime.jsx(
747
+ "input",
748
+ {
749
+ type: "color",
750
+ value: selectedOverlay.color,
751
+ onChange: (e) => {
752
+ updateOverlay(selectedOverlay.id, { color: e.target.value });
753
+ },
754
+ onBlur: pushHistory,
755
+ className: PhotoEditor_module.default.colorInput,
756
+ "aria-label": t("photoEditor.textColor", "Text overlay color")
757
+ }
758
+ ),
759
+ /* @__PURE__ */ jsxRuntime.jsx(
760
+ LocalUI.Button,
761
+ {
762
+ variant: selectedOverlay.bold ? "light" : "dark",
763
+ size: "sm",
764
+ onClick: () => {
765
+ updateOverlay(selectedOverlay.id, {
766
+ bold: !selectedOverlay.bold
767
+ });
768
+ pushHistory();
769
+ },
770
+ className: PhotoEditor_module.default.textFormatBtnSm,
771
+ style: { fontWeight: 700 },
772
+ children: "B"
773
+ }
774
+ ),
775
+ /* @__PURE__ */ jsxRuntime.jsx(
776
+ LocalUI.Button,
777
+ {
778
+ variant: selectedOverlay.italic ? "light" : "dark",
779
+ size: "sm",
780
+ onClick: () => {
781
+ updateOverlay(selectedOverlay.id, {
782
+ italic: !selectedOverlay.italic
783
+ });
784
+ pushHistory();
785
+ },
786
+ className: PhotoEditor_module.default.textFormatBtnSm,
787
+ style: { fontStyle: "italic" },
788
+ children: "I"
789
+ }
790
+ )
791
+ ] })
792
+ ] })
793
+ ] }),
794
+ activeTab === "shapes" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
795
+ /* @__PURE__ */ jsxRuntime.jsx(OverlayToolbar, { api }),
796
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sectionTitle, children: [
797
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "star", size: 14, style: { marginRight: 4 } }),
798
+ " ",
799
+ t("photoEditor.shapes", "Shapes")
800
+ ] }),
801
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.shapeColorRow, children: [
802
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.shapeColorLabel, children: t("photoEditor.stroke", "Stroke:") }),
803
+ /* @__PURE__ */ jsxRuntime.jsx(
804
+ "input",
805
+ {
806
+ type: "color",
807
+ value: shapeStroke,
808
+ onChange: (e) => setShapeStroke(e.target.value),
809
+ className: PhotoEditor_module.default.colorInput,
810
+ title: t("photoEditor.strokeColor", "Stroke color")
811
+ }
812
+ ),
813
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.shapeColorLabelMl, children: t("photoEditor.fill", "Fill:") }),
814
+ /* @__PURE__ */ jsxRuntime.jsx(
815
+ "input",
816
+ {
817
+ type: "color",
818
+ value: shapeFill || "#ffffff",
819
+ onChange: (e) => setShapeFill(e.target.value),
820
+ className: PhotoEditor_module.default.colorInput,
821
+ title: t("photoEditor.fillColor", "Fill color")
822
+ }
823
+ ),
824
+ /* @__PURE__ */ jsxRuntime.jsx(
825
+ LocalUI.Button,
826
+ {
827
+ variant: shapeFill ? "light" : "dark",
828
+ size: "sm",
829
+ onClick: () => setShapeFill(shapeFill ? "" : "#ffffff"),
830
+ className: PhotoEditor_module.default.shapeFillToggle,
831
+ children: shapeFill ? t("photoEditor.off", "Off") : t("photoEditor.on", "On")
832
+ }
833
+ )
834
+ ] }),
835
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sliderRow, children: [
836
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.sliderLabel, children: t("photoEditor.width", "Width:") }),
837
+ /* @__PURE__ */ jsxRuntime.jsx(
838
+ LocalUI.RangeInput,
839
+ {
840
+ min: 1,
841
+ max: 20,
842
+ value: shapeStrokeW,
843
+ onChange: (e) => setShapeStrokeW(Number(e.target.value)),
844
+ accentColor: accent,
845
+ style: { flex: 1 }
846
+ }
847
+ ),
848
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderValue, style: { color: accent }, children: [
849
+ shapeStrokeW,
850
+ "px"
851
+ ] })
852
+ ] }),
853
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.shapeGrid, children: photoOverlays.SHAPE_CATALOG.map((sh) => /* @__PURE__ */ jsxRuntime.jsx(
854
+ "button",
855
+ {
856
+ title: sh.label,
857
+ onClick: () => {
858
+ const ov = createShapeOverlay(sh.id);
859
+ ov.strokeColor = shapeStroke;
860
+ ov.fillColor = shapeFill || null;
861
+ ov.strokeWidth = shapeStrokeW;
862
+ addOverlay(ov);
863
+ },
864
+ className: PhotoEditor_module.default.shapeBtn,
865
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: sh.icon, size: 18 })
866
+ },
867
+ sh.id
868
+ )) }),
869
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sectionTitle, children: [
870
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "image", size: 14, style: { marginRight: 4 } }),
871
+ " ",
872
+ t("photoEditor.frames", "Frames")
873
+ ] }),
874
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.frameColorRow, children: [
875
+ /* @__PURE__ */ jsxRuntime.jsx(
876
+ "input",
877
+ {
878
+ type: "color",
879
+ value: frameColor,
880
+ onChange: (e) => setFrameColor(e.target.value),
881
+ className: PhotoEditor_module.default.colorInput,
882
+ "aria-label": t("photoEditor.frameColor", "Frame color")
883
+ }
884
+ ),
885
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.frameThicknessWrap, children: [
886
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.sliderLabel, children: t("photoEditor.thickness", "Thickness:") }),
887
+ /* @__PURE__ */ jsxRuntime.jsx(
888
+ LocalUI.RangeInput,
889
+ {
890
+ min: 1,
891
+ max: 10,
892
+ value: frameThick,
893
+ onChange: (e) => setFrameThick(Number(e.target.value)),
894
+ accentColor: accent,
895
+ style: { flex: 1 }
896
+ }
897
+ ),
898
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.frameThicknessValue, style: { color: accent }, children: frameThick })
899
+ ] })
900
+ ] }),
901
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.frameGrid, children: [
902
+ photoOverlays.FRAME_CATALOG.map((fr) => /* @__PURE__ */ jsxRuntime.jsx(
903
+ "button",
904
+ {
905
+ title: fr.label,
906
+ onClick: () => {
907
+ setOverlays((prev) => prev.filter((o) => o.type !== "frame"));
908
+ const ov = createFrameOverlay(fr.id, frameColor);
909
+ ov.thickness = frameThick / 100;
910
+ addOverlay(ov);
911
+ },
912
+ className: PhotoEditor_module.default.frameBtn,
913
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: fr.icon, size: 18 })
914
+ },
915
+ fr.id
916
+ )),
917
+ /* @__PURE__ */ jsxRuntime.jsx(
918
+ "button",
919
+ {
920
+ title: t("photoEditor.removeFrame", "Remove frame"),
921
+ "aria-label": t("photoEditor.removeFrame", "Remove frame"),
922
+ onClick: () => {
923
+ setOverlays((prev) => prev.filter((o) => o.type !== "frame"));
924
+ pushHistory();
925
+ },
926
+ className: PhotoEditor_module.default.removeFrameBtn,
927
+ children: /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 })
928
+ }
929
+ )
930
+ ] })
931
+ ] }),
932
+ activeTab === "draw" && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
933
+ /* @__PURE__ */ jsxRuntime.jsx(OverlayToolbar, { api }),
934
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sectionTitleMb8, children: [
935
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "brush", size: 14, style: { marginRight: 4 } }),
936
+ " ",
937
+ t("photoEditor.freehandDrawing", "Freehand drawing")
938
+ ] }),
939
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sectionInfoMb, children: [
940
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "info", size: 14, style: { marginRight: 4 } }),
941
+ t(
942
+ "photoEditor.drawDirectlyOnThePhoto",
943
+ "Draw directly on the photo by holding the left mouse button."
944
+ )
945
+ ] }),
946
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.quickColorRow, children: [
947
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.sliderLabel, children: t("photoEditor.color2", "Color:") }),
948
+ /* @__PURE__ */ jsxRuntime.jsx(
949
+ "input",
950
+ {
951
+ type: "color",
952
+ value: drawColor,
953
+ onChange: (e) => setDrawColor(e.target.value),
954
+ className: PhotoEditor_module.default.colorInputDraw,
955
+ "aria-label": t("photoEditor.drawColor", "Drawing color")
956
+ }
957
+ ),
958
+ [
959
+ "#ff0000",
960
+ "#ff8800",
961
+ "#ffff00",
962
+ "#00cc00",
963
+ "#0088ff",
964
+ "#8800ff",
965
+ "#ff00ff",
966
+ "#ffffff",
967
+ "#000000"
968
+ ].map((c) => /* @__PURE__ */ jsxRuntime.jsx(
969
+ "div",
970
+ {
971
+ role: "button",
972
+ tabIndex: 0,
973
+ "aria-label": c,
974
+ "aria-pressed": drawColor === c,
975
+ onKeyDown: uiCore.clickOnActivationKey,
976
+ onClick: () => setDrawColor(c),
977
+ className: PhotoEditor_module.default.quickColorSwatch,
978
+ style: {
979
+ background: c,
980
+ border: drawColor === c ? `2px solid ${accent}` : void 0
981
+ }
982
+ },
983
+ c
984
+ ))
985
+ ] }),
986
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.sliderRow, style: { marginBottom: 12 }, children: [
987
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: PhotoEditor_module.default.sliderLabel, children: t("photoEditor.width", "Width:") }),
988
+ /* @__PURE__ */ jsxRuntime.jsx(
989
+ LocalUI.RangeInput,
990
+ {
991
+ min: 1,
992
+ max: 30,
993
+ value: drawWidth,
994
+ onChange: (e) => setDrawWidth(Number(e.target.value)),
995
+ accentColor: accent,
996
+ style: { flex: 1 }
997
+ }
998
+ ),
999
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: PhotoEditor_module.default.sliderValue, style: { color: accent }, children: [
1000
+ drawWidth,
1001
+ "px"
1002
+ ] })
1003
+ ] }),
1004
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: PhotoEditor_module.default.drawPreview, children: /* @__PURE__ */ jsxRuntime.jsx(
1005
+ "div",
1006
+ {
1007
+ style: {
1008
+ width: Math.max(drawWidth, 4),
1009
+ height: Math.max(drawWidth, 4),
1010
+ borderRadius: "50%",
1011
+ background: drawColor,
1012
+ border: "1px solid var(--nice-border-color, #555)"
1013
+ }
1014
+ }
1015
+ ) }),
1016
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PhotoEditor_module.default.drawActionRow, children: [
1017
+ /* @__PURE__ */ jsxRuntime.jsxs(
1018
+ LocalUI.Button,
1019
+ {
1020
+ variant: "outline-warning",
1021
+ size: "sm",
1022
+ onClick: () => {
1023
+ if (drawingOverlayRef.current) {
1024
+ const id = drawingOverlayRef.current.id;
1025
+ setOverlays(
1026
+ (prev) => prev.map((o) => {
1027
+ if (o.id === id && o.type === "drawing") {
1028
+ const d = o;
1029
+ if (d.strokes.length <= 1) {
1030
+ return o;
1031
+ }
1032
+ return { ...d, strokes: d.strokes.slice(0, -1) };
56
1033
  }
57
- else {
58
- setCropMode(false);
59
- }
60
- }, title: tab.label, className: activeTab === tab.key ? PhotoEditor_module.tabButtonActive : PhotoEditor_module.tabButton, style: {
61
- color: activeTab === tab.key ? accent : undefined,
62
- borderBottomColor: activeTab === tab.key ? accent : undefined,
63
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: tab.icon, size: 14 }), tab.label] }, tab.key))) }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.panelContent, children: [activeTab === 'filters' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: PhotoEditor_module.pillRow, children: [
64
- { key: 'all', label: t('photoEditor.all', 'All') },
65
- { key: 'color', label: t('photoEditor.color', 'Color') },
66
- { key: 'light', label: t('photoEditor.light', 'Light') },
67
- { key: 'vintage', label: t('photoEditor.vintage', 'Vintage') },
68
- { key: 'artistic', label: t('photoEditor.artistic', 'Artistic') },
69
- { key: 'fun', label: t('photoEditor.fun', 'Fun') },
70
- ].map((cat) => (jsxRuntime.jsx("button", { onClick: () => setFilterCategory(cat.key), className: filterCategory === cat.key ? PhotoEditor_module.pillActive : PhotoEditor_module.pill, style: {
71
- borderColor: filterCategory === cat.key ? accent : undefined,
72
- background: filterCategory === cat.key ? accentDim : undefined,
73
- }, children: cat.label }, cat.key))) }), jsxRuntime.jsx("div", { className: PhotoEditor_module.filterGrid, children: filteredList.map((filter) => (jsxRuntime.jsx(FilterThumb, { filter: filter, selected: selectedFilter === filter.id, accent: accent, onSelect: () => {
74
- setSelectedFilter(filter.id);
75
- pushHistory();
76
- }, generateThumbnail: generateThumbnail }, filter.id))) }), selectedFilter !== 'none' && (jsxRuntime.jsxs("div", { className: PhotoEditor_module.intensitySection, children: [jsxRuntime.jsxs("div", { className: PhotoEditor_module.intensityHeader, children: [jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderLabel, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "bar-chart", size: 14, style: { marginRight: 4 } }), t('photoEditor.intensity', 'Intensity')] }), jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderValue, style: { color: accent }, children: [Math.round(filterIntensity * 100), "%"] })] }), jsxRuntime.jsx(LocalUI.RangeInput, { min: 0, max: 100, value: filterIntensity * 100, onChange: (e) => setFilterIntensity(Number(e.target.value) / 100), onMouseUp: () => pushHistory(), accentColor: accent })] }))] })), activeTab === 'adjust' && (jsxRuntime.jsxs("div", { className: PhotoEditor_module.adjustColumn, children: [photoEditorTypes.ADJUSTMENT_SLIDERS.map((sl) => (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: PhotoEditor_module.adjustHeader, children: [jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderLabel, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: sl.icon, size: 14, style: { marginRight: 4 } }), sl.label] }), jsxRuntime.jsx("span", { role: "button", tabIndex: 0, "aria-label": t('photoEditor.reset', 'Reset'), onKeyDown: uiCore.clickOnActivationKey, className: PhotoEditor_module.adjustValue, style: {
77
- color: adjustments[sl.key] !== 0 ? accent : 'var(--nice-text-secondary, #666)',
78
- }, onClick: () => handleAdjChange(sl.key, sl.key === 'blur' ? 0 : 0), title: t('photoEditor.reset', 'Reset'), children: adjustments[sl.key] })] }), jsxRuntime.jsx(LocalUI.RangeInput, { min: sl.min, max: sl.max, value: adjustments[sl.key], onChange: (e) => handleAdjChange(sl.key, Number(e.target.value)), onMouseUp: handleAdjChangeEnd, accentColor: accent })] }, sl.key))), jsxRuntime.jsxs(LocalUI.Button, { variant: "outline-secondary", size: "sm", className: "mt-2", onClick: () => {
79
- handleAdjChange('brightness', 0);
80
- const defaults = { ...photoFilters.DEFAULT_ADJUSTMENTS };
81
- for (const key of Object.keys(defaults)) {
82
- handleAdjChange(key, defaults[key]);
83
- }
84
- pushHistory();
85
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "refresh", size: 14, style: { marginRight: 4 } }), t('photoEditor.resetAdjustments', 'Reset adjustments')] })] })), activeTab === 'crop' && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: PhotoEditor_module.cropInfo, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "info", size: 14, style: { marginRight: 4 } }), t('photoEditor.dragCornersOrEdgesTo', 'Drag corners or edges to crop the photo.')] }), jsxRuntime.jsx("div", { className: PhotoEditor_module.cropAspectLabel, children: t('photoEditor.aspectRatio', 'Aspect ratio') }), jsxRuntime.jsx("div", { className: PhotoEditor_module.cropAspectRow, children: photoEditorTypes.ASPECT_RATIOS.map((ar) => (jsxRuntime.jsx("button", { onClick: () => {
86
- setCropAspect(ar.value);
87
- if (ar.value && cropRect && image) {
88
- let newW = cropRect.w;
89
- let newH = cropRect.w / ar.value;
90
- if (newH > image.naturalHeight) {
91
- newH = image.naturalHeight;
92
- newW = newH * ar.value;
93
- }
94
- setCropRect({
95
- x: Math.max(0, cropRect.x),
96
- y: Math.max(0, cropRect.y),
97
- w: Math.min(newW, image.naturalWidth),
98
- h: Math.min(newH, image.naturalHeight),
99
- });
100
- }
101
- }, className: cropAspect === ar.value ? PhotoEditor_module.pillCropActive : PhotoEditor_module.pillCrop, style: {
102
- borderColor: cropAspect === ar.value ? accent : undefined,
103
- background: cropAspect === ar.value ? accentDim : undefined,
104
- }, children: ar.label }, ar.label))) }), jsxRuntime.jsxs(LocalUI.Button, { variant: "outline-secondary", size: "sm", className: "mt-3", onClick: () => {
105
- if (image) {
106
- setCropRect({ x: 0, y: 0, w: image.naturalWidth, h: image.naturalHeight });
107
- setCropAspect(null);
108
- pushHistory();
109
- }
110
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "expand", size: 14, style: { marginRight: 4 } }), t('photoEditor.resetCrop', 'Reset crop')] })] })), activeTab === 'transform' && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("div", { className: PhotoEditor_module.sectionTitleMb8, children: t('photoEditor.rotation', 'Rotation') }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.transformRow, children: [jsxRuntime.jsxs(LocalUI.Button, { variant: "dark", size: "sm", onClick: () => {
111
- setRotation((rotation - 90 + 360) % 360);
112
- pushHistory();
113
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "reply", size: 14, style: { marginRight: 4 } }), " -90\u00B0"] }), jsxRuntime.jsxs(LocalUI.Button, { variant: "dark", size: "sm", onClick: () => {
114
- setRotation((rotation + 90) % 360);
115
- pushHistory();
116
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "forward", size: 14, style: { marginRight: 4 } }), " +90\u00B0"] }), jsxRuntime.jsx(LocalUI.Button, { variant: "dark", size: "sm", onClick: () => {
117
- setRotation(0);
118
- pushHistory();
119
- }, children: "0\u00B0" })] }), jsxRuntime.jsx("div", { className: PhotoEditor_module.sectionTitleMb8, children: t('photoEditor.flip', 'Flip') }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.transformRow, children: [jsxRuntime.jsxs(LocalUI.Button, { variant: flipH ? 'outline-info' : 'dark', size: "sm", onClick: () => {
120
- setFlipH(!flipH);
121
- pushHistory();
122
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "move", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.horizontal', 'Horizontal')] }), jsxRuntime.jsxs(LocalUI.Button, { variant: flipV ? 'outline-info' : 'dark', size: "sm", onClick: () => {
123
- setFlipV(!flipV);
124
- pushHistory();
125
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "move", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.vertical', 'Vertical')] })] }), jsxRuntime.jsx("div", { className: PhotoEditor_module.sectionTitleMb8, children: t('photoEditor.previewZoom', 'Preview zoom') }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.transformZoomRow, children: [jsxRuntime.jsx(LocalUI.RangeInput, { min: 50, max: 300, value: zoom * 100, onChange: (e) => setZoom(Number(e.target.value) / 100), accentColor: accent }), jsxRuntime.jsxs("span", { className: PhotoEditor_module.transformZoomValue, style: { color: accent }, children: [Math.round(zoom * 100), "%"] })] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.transformInfo, children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: t('photoEditor.rotation2', 'Rotation:') }), " ", rotation, "\u00B0"] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: t('photoEditor.flipH', 'Flip H:') }), ' ', flipH ? t('photoEditor.yes', 'Yes') : t('photoEditor.no', 'No')] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: t('photoEditor.flipV', 'Flip V:') }), ' ', flipV ? t('photoEditor.yes', 'Yes') : t('photoEditor.no', 'No')] }), cropRect && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: t('photoEditor.crop', 'Crop:') }), " ", Math.round(cropRect.w), " \u00D7", ' ', Math.round(cropRect.h), ' (', "x:", Math.round(cropRect.x), ", y:", Math.round(cropRect.y), ")"] }))] })] })), activeTab === 'stickers' && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(OverlayToolbar, { api: api }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sectionTitle, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "circle", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.stickersEmoji', 'Stickers / Emoji')] }), jsxRuntime.jsx("div", { className: PhotoEditor_module.pillRowGap3, children: photoOverlays.EMOJI_CATALOG.map((cat) => (jsxRuntime.jsxs("button", { onClick: () => setEmojiCat(cat.id), className: emojiCat === cat.id ? PhotoEditor_module.pillEmojiActive : PhotoEditor_module.pillEmoji, style: {
126
- borderColor: emojiCat === cat.id ? accent : undefined,
127
- background: emojiCat === cat.id ? accentDim : undefined,
128
- }, children: [cat.icon, " ", cat.label] }, cat.id))) }), jsxRuntime.jsx("div", { className: PhotoEditor_module.emojiGrid, children: (_a = photoOverlays.EMOJI_CATALOG.find((c) => c.id === emojiCat)) === null || _a === void 0 ? void 0 : _a.emojis.map((em, idx) => (jsxRuntime.jsx("button", { onClick: () => {
129
- var _a, _b, _c, _d;
130
- const cw = (_b = (_a = mainCanvasRef.current) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : 400;
131
- const ch = (_d = (_c = mainCanvasRef.current) === null || _c === void 0 ? void 0 : _c.height) !== null && _d !== void 0 ? _d : 400;
132
- addOverlay(createEmojiOverlay(em, cw, ch));
133
- }, className: PhotoEditor_module.emojiBtn, title: em, children: em }, idx))) }), overlays.length > 0 && (jsxRuntime.jsxs("div", { className: PhotoEditor_module.overlaySection, children: [jsxRuntime.jsx("div", { className: PhotoEditor_module.overlaySectionTitle, children: t('photoEditor.layers', 'Layers ({overlays})').replace('{overlays}', String(overlays.length)) }), overlays.map((ov) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: uiCore.clickOnActivationKey, onClick: () => setSelectedOverlayId(ov.id), className: PhotoEditor_module.overlayItem, style: { background: selectedOverlayId === ov.id ? accentDim : undefined }, children: [jsxRuntime.jsx("span", { className: PhotoEditor_module.overlayIcon, children: ov.type === 'emoji' ? (ov.emoji) : ov.type === 'text' ? ('T') : ov.type === 'shape' ? (jsxRuntime.jsx(uiCore.NiceIcon, { name: "star", size: 14 })) : ov.type === 'drawing' ? (jsxRuntime.jsx(uiCore.NiceIcon, { name: "pen", size: 14 })) : (jsxRuntime.jsx(uiCore.NiceIcon, { name: "square", size: 14 })) }), jsxRuntime.jsx("span", { className: PhotoEditor_module.overlayName, children: ov.type === 'text'
134
- ? ov.text.slice(0, 20)
135
- : ov.type === 'emoji'
136
- ? t('photoEditor.emoji', 'Emoji')
137
- : ov.type === 'shape'
138
- ? ov.shapeKind
139
- : ov.type === 'drawing'
140
- ? t('photoEditor.drawing', 'Drawing ({strokes})').replace('{strokes}', String(ov.strokes.length))
141
- : ov.type === 'frame'
142
- ? ov.frameStyle
143
- : '' }), jsxRuntime.jsx("button", { onClick: (e) => {
144
- e.stopPropagation();
145
- deleteOverlay(ov.id);
146
- }, className: PhotoEditor_module.overlayDeleteBtn, "aria-label": t('photoEditor.deleteLayer', 'Delete layer'), children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 }) })] }, ov.id)))] }))] })), activeTab === 'text' && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(OverlayToolbar, { api: api }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sectionTitleMb8, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "type", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.addCaption', 'Add caption')] }), jsxRuntime.jsx(LocalUI.TextArea, { rows: 2, value: textDraft, onChange: (e) => setTextDraft(e.target.value), placeholder: t('photoEditor.textPlaceholder', 'Enter text…'), className: PhotoEditor_module.textArea }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.textBtnRow, children: [jsxRuntime.jsx(LocalUI.Button, { variant: textBold ? 'light' : 'dark', size: "sm", onClick: () => setTextBold(!textBold), title: t('photoEditor.bold', 'Bold'), className: PhotoEditor_module.textFormatBtn, style: { fontWeight: 700 }, children: "B" }), jsxRuntime.jsx(LocalUI.Button, { variant: textItalic ? 'light' : 'dark', size: "sm", onClick: () => setTextItalic(!textItalic), title: t('photoEditor.italic', 'Italic'), className: PhotoEditor_module.textFormatBtn, style: { fontStyle: 'italic' }, children: "I" }), jsxRuntime.jsx(LocalUI.Button, { variant: textOutline ? 'light' : 'dark', size: "sm", onClick: () => setTextOutline(!textOutline), title: t('photoEditor.outline', 'Outline'), className: PhotoEditor_module.textFormatBtn, children: "O" }), jsxRuntime.jsx(LocalUI.Button, { variant: textBg ? 'light' : 'dark', size: "sm", onClick: () => setTextBg(!textBg), title: t('photoEditor.background', 'Background'), className: PhotoEditor_module.textFormatBtn, children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "square", size: 14 }) }), jsxRuntime.jsx("input", { type: "color", value: textColor, onChange: (e) => setTextColor(e.target.value), className: PhotoEditor_module.colorInputLg, title: t('photoEditor.textColour', 'Text colour') })] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sliderRow, children: [jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderLabel, children: [t('photoEditor.size', 'Size'), ":"] }), jsxRuntime.jsx(LocalUI.RangeInput, { min: 12, max: 120, value: textFontSize, onChange: (e) => setTextFontSize(Number(e.target.value)), accentColor: accent, style: { flex: 1 } }), jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderValue, style: { color: accent }, children: [textFontSize, "px"] })] }), jsxRuntime.jsxs(LocalUI.Button, { size: "sm", className: PhotoEditor_module.accentBtn, style: { background: accent, borderColor: accent }, disabled: !textDraft.trim(), onClick: () => {
147
- const ov = createTextOverlay(textDraft);
148
- ov.color = textColor;
149
- ov.bold = textBold;
150
- ov.italic = textItalic;
151
- ov.fontSize = textFontSize;
152
- // Drawn into the photo on canvas (which ignores var()).
153
- ov.outlineColor = textOutline ? '#000000' : null;
154
- ov.outlineWidth = textOutline ? 2 : 0;
155
- // audit-allow: literal-color — caption box drawn into the photo
156
- ov.background = textBg ? 'rgba(0, 0, 0, 0.5)' : null;
157
- addOverlay(ov);
158
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "plus", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.addText', 'Add text')] }), (selectedOverlay === null || selectedOverlay === void 0 ? void 0 : selectedOverlay.type) === 'text' && (jsxRuntime.jsxs("div", { className: PhotoEditor_module.editSelectedSection, children: [jsxRuntime.jsx("div", { className: PhotoEditor_module.editSelectedLabel, children: t('photoEditor.editSelectedText', 'Edit selected text:') }), jsxRuntime.jsx(LocalUI.TextArea, { rows: 2, value: selectedOverlay.text, onChange: (e) => updateOverlay(selectedOverlay.id, { text: e.target.value }), onBlur: pushHistory, className: PhotoEditor_module.textAreaSm }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.textGapRow, children: [jsxRuntime.jsx("input", { type: "color", value: selectedOverlay.color, onChange: (e) => {
159
- updateOverlay(selectedOverlay.id, { color: e.target.value });
160
- }, onBlur: pushHistory, className: PhotoEditor_module.colorInput, "aria-label": t('photoEditor.textColor', 'Text overlay color') }), jsxRuntime.jsx(LocalUI.Button, { variant: selectedOverlay.bold ? 'light' : 'dark', size: "sm", onClick: () => {
161
- updateOverlay(selectedOverlay.id, {
162
- bold: !selectedOverlay.bold,
163
- });
164
- pushHistory();
165
- }, className: PhotoEditor_module.textFormatBtnSm, style: { fontWeight: 700 }, children: "B" }), jsxRuntime.jsx(LocalUI.Button, { variant: selectedOverlay.italic ? 'light' : 'dark', size: "sm", onClick: () => {
166
- updateOverlay(selectedOverlay.id, {
167
- italic: !selectedOverlay.italic,
168
- });
169
- pushHistory();
170
- }, className: PhotoEditor_module.textFormatBtnSm, style: { fontStyle: 'italic' }, children: "I" })] })] }))] })), activeTab === 'shapes' && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(OverlayToolbar, { api: api }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sectionTitle, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "star", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.shapes', 'Shapes')] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.shapeColorRow, children: [jsxRuntime.jsx("span", { className: PhotoEditor_module.shapeColorLabel, children: t('photoEditor.stroke', 'Stroke:') }), jsxRuntime.jsx("input", { type: "color", value: shapeStroke, onChange: (e) => setShapeStroke(e.target.value), className: PhotoEditor_module.colorInput, title: t('photoEditor.strokeColor', 'Stroke color') }), jsxRuntime.jsx("span", { className: PhotoEditor_module.shapeColorLabelMl, children: t('photoEditor.fill', 'Fill:') }), jsxRuntime.jsx("input", { type: "color", value: shapeFill || '#ffffff', onChange: (e) => setShapeFill(e.target.value), className: PhotoEditor_module.colorInput, title: t('photoEditor.fillColor', 'Fill color') }), jsxRuntime.jsx(LocalUI.Button, { variant: shapeFill ? 'light' : 'dark', size: "sm", onClick: () => setShapeFill(shapeFill ? '' : '#ffffff'), className: PhotoEditor_module.shapeFillToggle, children: shapeFill ? t('photoEditor.off', 'Off') : t('photoEditor.on', 'On') })] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sliderRow, children: [jsxRuntime.jsx("span", { className: PhotoEditor_module.sliderLabel, children: t('photoEditor.width', 'Width:') }), jsxRuntime.jsx(LocalUI.RangeInput, { min: 1, max: 20, value: shapeStrokeW, onChange: (e) => setShapeStrokeW(Number(e.target.value)), accentColor: accent, style: { flex: 1 } }), jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderValue, style: { color: accent }, children: [shapeStrokeW, "px"] })] }), jsxRuntime.jsx("div", { className: PhotoEditor_module.shapeGrid, children: photoOverlays.SHAPE_CATALOG.map((sh) => (jsxRuntime.jsx("button", { title: sh.label, onClick: () => {
171
- const ov = createShapeOverlay(sh.id);
172
- ov.strokeColor = shapeStroke;
173
- ov.fillColor = shapeFill || null;
174
- ov.strokeWidth = shapeStrokeW;
175
- addOverlay(ov);
176
- }, className: PhotoEditor_module.shapeBtn, children: jsxRuntime.jsx(uiCore.NiceIcon, { name: sh.icon, size: 18 }) }, sh.id))) }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sectionTitle, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "image", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.frames', 'Frames')] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.frameColorRow, children: [jsxRuntime.jsx("input", { type: "color", value: frameColor, onChange: (e) => setFrameColor(e.target.value), className: PhotoEditor_module.colorInput, "aria-label": t('photoEditor.frameColor', 'Frame color') }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.frameThicknessWrap, children: [jsxRuntime.jsx("span", { className: PhotoEditor_module.sliderLabel, children: t('photoEditor.thickness', 'Thickness:') }), jsxRuntime.jsx(LocalUI.RangeInput, { min: 1, max: 10, value: frameThick, onChange: (e) => setFrameThick(Number(e.target.value)), accentColor: accent, style: { flex: 1 } }), jsxRuntime.jsx("span", { className: PhotoEditor_module.frameThicknessValue, style: { color: accent }, children: frameThick })] })] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.frameGrid, children: [photoOverlays.FRAME_CATALOG.map((fr) => (jsxRuntime.jsx("button", { title: fr.label, onClick: () => {
177
- setOverlays((prev) => prev.filter((o) => o.type !== 'frame'));
178
- const ov = createFrameOverlay(fr.id, frameColor);
179
- ov.thickness = frameThick / 100;
180
- addOverlay(ov);
181
- }, className: PhotoEditor_module.frameBtn, children: jsxRuntime.jsx(uiCore.NiceIcon, { name: fr.icon, size: 18 }) }, fr.id))), jsxRuntime.jsx("button", { title: t('photoEditor.removeFrame', 'Remove frame'), "aria-label": t('photoEditor.removeFrame', 'Remove frame'), onClick: () => {
182
- setOverlays((prev) => prev.filter((o) => o.type !== 'frame'));
183
- pushHistory();
184
- }, className: PhotoEditor_module.removeFrameBtn, children: jsxRuntime.jsx(uiCore.NiceIcon, { name: "close", size: 14 }) })] })] })), activeTab === 'draw' && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(OverlayToolbar, { api: api }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sectionTitleMb8, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "brush", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.freehandDrawing', 'Freehand drawing')] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sectionInfoMb, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "info", size: 14, style: { marginRight: 4 } }), t('photoEditor.drawDirectlyOnThePhoto', 'Draw directly on the photo by holding the left mouse button.')] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.quickColorRow, children: [jsxRuntime.jsx("span", { className: PhotoEditor_module.sliderLabel, children: t('photoEditor.color2', 'Color:') }), jsxRuntime.jsx("input", { type: "color", value: drawColor, onChange: (e) => setDrawColor(e.target.value), className: PhotoEditor_module.colorInputDraw, "aria-label": t('photoEditor.drawColor', 'Drawing color') }), [
185
- '#ff0000',
186
- '#ff8800',
187
- '#ffff00',
188
- '#00cc00',
189
- '#0088ff',
190
- '#8800ff',
191
- '#ff00ff',
192
- '#ffffff',
193
- '#000000',
194
- ].map((c) => (jsxRuntime.jsx("div", { role: "button", tabIndex: 0, "aria-label": c, "aria-pressed": drawColor === c, onKeyDown: uiCore.clickOnActivationKey, onClick: () => setDrawColor(c), className: PhotoEditor_module.quickColorSwatch, style: {
195
- background: c,
196
- border: drawColor === c ? `2px solid ${accent}` : undefined,
197
- } }, c)))] }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.sliderRow, style: { marginBottom: 12 }, children: [jsxRuntime.jsx("span", { className: PhotoEditor_module.sliderLabel, children: t('photoEditor.width', 'Width:') }), jsxRuntime.jsx(LocalUI.RangeInput, { min: 1, max: 30, value: drawWidth, onChange: (e) => setDrawWidth(Number(e.target.value)), accentColor: accent, style: { flex: 1 } }), jsxRuntime.jsxs("span", { className: PhotoEditor_module.sliderValue, style: { color: accent }, children: [drawWidth, "px"] })] }), jsxRuntime.jsx("div", { className: PhotoEditor_module.drawPreview, children: jsxRuntime.jsx("div", { style: {
198
- width: Math.max(drawWidth, 4),
199
- height: Math.max(drawWidth, 4),
200
- borderRadius: '50%',
201
- background: drawColor,
202
- border: '1px solid var(--nice-border-color, #555)',
203
- } }) }), jsxRuntime.jsxs("div", { className: PhotoEditor_module.drawActionRow, children: [jsxRuntime.jsxs(LocalUI.Button, { variant: "outline-warning", size: "sm", onClick: () => {
204
- if (drawingOverlayRef.current) {
205
- const id = drawingOverlayRef.current.id;
206
- setOverlays((prev) => prev.map((o) => {
207
- if (o.id === id && o.type === 'drawing') {
208
- const d = o;
209
- if (d.strokes.length <= 1) {
210
- return o;
211
- }
212
- return { ...d, strokes: d.strokes.slice(0, -1) };
213
- }
214
- return o;
215
- }));
216
- pushHistory();
217
- }
218
- }, className: PhotoEditor_module.drawActionBtn, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "reply", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.undoStroke', 'Undo stroke')] }), jsxRuntime.jsxs(LocalUI.Button, { variant: "outline-danger", size: "sm", onClick: () => {
219
- if (drawingOverlayRef.current) {
220
- deleteOverlay(drawingOverlayRef.current.id);
221
- drawingOverlayRef.current = null;
222
- }
223
- }, className: PhotoEditor_module.drawActionBtn, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "trash", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.clear', 'Clear')] })] }), jsxRuntime.jsxs(LocalUI.Button, { variant: "dark", size: "sm", className: "mt-2 w-100", onClick: () => {
224
- drawingOverlayRef.current = null;
225
- }, children: [jsxRuntime.jsx(uiCore.NiceIcon, { name: "plus", size: 14, style: { marginRight: 4 } }), ' ', t('photoEditor.newDrawingLayer', 'New drawing layer')] })] }))] })] }));
226
- }), { displayName: 'PhotoEditorLeftPanel' });
227
-
228
- module.exports = PhotoEditorLeftPanel;
1034
+ return o;
1035
+ })
1036
+ );
1037
+ pushHistory();
1038
+ }
1039
+ },
1040
+ className: PhotoEditor_module.default.drawActionBtn,
1041
+ children: [
1042
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "reply", size: 14, style: { marginRight: 4 } }),
1043
+ " ",
1044
+ t("photoEditor.undoStroke", "Undo stroke")
1045
+ ]
1046
+ }
1047
+ ),
1048
+ /* @__PURE__ */ jsxRuntime.jsxs(
1049
+ LocalUI.Button,
1050
+ {
1051
+ variant: "outline-danger",
1052
+ size: "sm",
1053
+ onClick: () => {
1054
+ if (drawingOverlayRef.current) {
1055
+ deleteOverlay(drawingOverlayRef.current.id);
1056
+ drawingOverlayRef.current = null;
1057
+ }
1058
+ },
1059
+ className: PhotoEditor_module.default.drawActionBtn,
1060
+ children: [
1061
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "trash", size: 14, style: { marginRight: 4 } }),
1062
+ " ",
1063
+ t("photoEditor.clear", "Clear")
1064
+ ]
1065
+ }
1066
+ )
1067
+ ] }),
1068
+ /* @__PURE__ */ jsxRuntime.jsxs(
1069
+ LocalUI.Button,
1070
+ {
1071
+ variant: "dark",
1072
+ size: "sm",
1073
+ className: "mt-2 w-100",
1074
+ onClick: () => {
1075
+ drawingOverlayRef.current = null;
1076
+ },
1077
+ children: [
1078
+ /* @__PURE__ */ jsxRuntime.jsx(uiCore.NiceIcon, { name: "plus", size: 14, style: { marginRight: 4 } }),
1079
+ " ",
1080
+ t("photoEditor.newDrawingLayer", "New drawing layer")
1081
+ ]
1082
+ }
1083
+ )
1084
+ ] })
1085
+ ] })
1086
+ ] });
1087
+ }),
1088
+ { displayName: "PhotoEditorLeftPanel" }
1089
+ );
1090
+ exports.default = PhotoEditorLeftPanel;