sa2kit 1.6.30 → 1.6.32

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 (251) hide show
  1. package/dist/AliyunOSSProvider-4W47OFEK.mjs +6 -0
  2. package/dist/{AliyunOSSProvider-KJYRIZES.mjs.map → AliyunOSSProvider-4W47OFEK.mjs.map} +1 -1
  3. package/dist/AliyunOSSProvider-HCNGDJL7.js +15 -0
  4. package/dist/{AliyunOSSProvider-FWAKUB2T.js.map → AliyunOSSProvider-HCNGDJL7.js.map} +1 -1
  5. package/dist/ConfigService-3DIC6C3Q.js +21 -0
  6. package/dist/{ConfigService-7MEZXKJ5.js.map → ConfigService-3DIC6C3Q.js.map} +1 -1
  7. package/dist/ConfigService-V6ZK273Z.mjs +4 -0
  8. package/dist/{ConfigService-BV57YYFW.mjs.map → ConfigService-V6ZK273Z.mjs.map} +1 -1
  9. package/dist/LocalStorageProvider-3RVPCQB3.mjs +6 -0
  10. package/dist/{LocalStorageProvider-RTPMUOZ2.mjs.map → LocalStorageProvider-3RVPCQB3.mjs.map} +1 -1
  11. package/dist/LocalStorageProvider-PP7MA5OT.js +15 -0
  12. package/dist/{LocalStorageProvider-XSRCUXOU.js.map → LocalStorageProvider-PP7MA5OT.js.map} +1 -1
  13. package/dist/PMXParser-2VTA737I.js +13 -0
  14. package/dist/{PMXParser-YBS3B6HM.js.map → PMXParser-2VTA737I.js.map} +1 -1
  15. package/dist/PMXParser-RNVQL76A.mjs +4 -0
  16. package/dist/{PMXParser-L6IWHL4I.mjs.map → PMXParser-RNVQL76A.mjs.map} +1 -1
  17. package/dist/analytics/index.js +46 -45
  18. package/dist/analytics/index.js.map +1 -1
  19. package/dist/analytics/index.mjs +45 -44
  20. package/dist/analytics/index.mjs.map +1 -1
  21. package/dist/analytics/server/index.js +4 -4
  22. package/dist/analytics/server/index.js.map +1 -1
  23. package/dist/analytics/server/index.mjs +4 -4
  24. package/dist/analytics/server/index.mjs.map +1 -1
  25. package/dist/api/index.js +5 -5
  26. package/dist/api/index.js.map +1 -1
  27. package/dist/api/index.mjs +5 -5
  28. package/dist/api/index.mjs.map +1 -1
  29. package/dist/audioDetection/index.js +17 -16
  30. package/dist/audioDetection/index.js.map +1 -1
  31. package/dist/audioDetection/index.mjs +17 -16
  32. package/dist/audioDetection/index.mjs.map +1 -1
  33. package/dist/auth/client/index.js +4 -4
  34. package/dist/auth/client/index.mjs +1 -1
  35. package/dist/auth/components/index.js +3 -3
  36. package/dist/auth/components/index.js.map +1 -1
  37. package/dist/auth/components/index.mjs +3 -3
  38. package/dist/auth/components/index.mjs.map +1 -1
  39. package/dist/auth/index.js +29 -29
  40. package/dist/auth/index.mjs +5 -5
  41. package/dist/auth/middleware/index.js +3 -3
  42. package/dist/auth/middleware/index.mjs +2 -2
  43. package/dist/auth/routes/index.js +14 -14
  44. package/dist/auth/routes/index.mjs +2 -2
  45. package/dist/auth/services/index.js +7 -7
  46. package/dist/auth/services/index.mjs +1 -1
  47. package/dist/calendar/index.js +146 -182
  48. package/dist/calendar/index.js.map +1 -1
  49. package/dist/calendar/index.mjs +139 -175
  50. package/dist/calendar/index.mjs.map +1 -1
  51. package/dist/calendar/routes/index.js +1 -1
  52. package/dist/calendar/routes/index.js.map +1 -1
  53. package/dist/calendar/routes/index.mjs +1 -1
  54. package/dist/calendar/routes/index.mjs.map +1 -1
  55. package/dist/{chunk-5YQ5B7IZ.js → chunk-24HGREE6.js} +5 -5
  56. package/dist/{chunk-5YQ5B7IZ.js.map → chunk-24HGREE6.js.map} +1 -1
  57. package/dist/{chunk-6PRFP5EG.js → chunk-25OFOKNF.js} +6 -6
  58. package/dist/chunk-25OFOKNF.js.map +1 -0
  59. package/dist/{chunk-KQGP6BTS.mjs → chunk-3DXPQ4YV.mjs} +6 -6
  60. package/dist/chunk-3DXPQ4YV.mjs.map +1 -0
  61. package/dist/{chunk-3BGPZN4X.mjs → chunk-3NHAT7D4.mjs} +12 -12
  62. package/dist/chunk-3NHAT7D4.mjs.map +1 -0
  63. package/dist/{chunk-MW4BCIZC.mjs → chunk-4HC6M7FK.mjs} +3 -3
  64. package/dist/chunk-4HC6M7FK.mjs.map +1 -0
  65. package/dist/{chunk-ESRCX5TQ.mjs → chunk-52TN2QSS.mjs} +3 -3
  66. package/dist/{chunk-ESRCX5TQ.mjs.map → chunk-52TN2QSS.mjs.map} +1 -1
  67. package/dist/{chunk-CNTILN5J.mjs → chunk-5YQ62BKX.mjs} +20 -19
  68. package/dist/chunk-5YQ62BKX.mjs.map +1 -0
  69. package/dist/{chunk-6W5BMXJG.js → chunk-6OWNMJKG.js} +4 -4
  70. package/dist/{chunk-6W5BMXJG.js.map → chunk-6OWNMJKG.js.map} +1 -1
  71. package/dist/{chunk-DUHZ7VZP.js → chunk-7VRT55ZD.js} +3 -3
  72. package/dist/chunk-7VRT55ZD.js.map +1 -0
  73. package/dist/{chunk-3WOAPLEG.mjs → chunk-EB4NR623.mjs} +27 -26
  74. package/dist/chunk-EB4NR623.mjs.map +1 -0
  75. package/dist/chunk-EI27JKND.mjs +1988 -0
  76. package/dist/chunk-EI27JKND.mjs.map +1 -0
  77. package/dist/{chunk-CD77U7LZ.js → chunk-GBPLX42J.js} +9 -9
  78. package/dist/chunk-GBPLX42J.js.map +1 -0
  79. package/dist/{chunk-TFQF2HDO.mjs → chunk-HDEOCX2L.mjs} +12 -12
  80. package/dist/chunk-HDEOCX2L.mjs.map +1 -0
  81. package/dist/{chunk-TV3VKRJK.mjs → chunk-HDMIOOZY.mjs} +38 -68
  82. package/dist/chunk-HDMIOOZY.mjs.map +1 -0
  83. package/dist/{chunk-OPPF3326.js → chunk-HJ6MH7J7.js} +39 -69
  84. package/dist/chunk-HJ6MH7J7.js.map +1 -0
  85. package/dist/chunk-KO73EBUT.js +80 -0
  86. package/dist/chunk-KO73EBUT.js.map +1 -0
  87. package/dist/{chunk-6YKMCPQI.mjs → chunk-KZKIH4AS.mjs} +4 -4
  88. package/dist/chunk-KZKIH4AS.mjs.map +1 -0
  89. package/dist/{chunk-LX4XX6W7.js → chunk-L47ZOYHL.js} +15 -89
  90. package/dist/chunk-L47ZOYHL.js.map +1 -0
  91. package/dist/{chunk-6MQUBPKB.mjs → chunk-LJ4CCSSY.mjs} +3 -3
  92. package/dist/{chunk-6MQUBPKB.mjs.map → chunk-LJ4CCSSY.mjs.map} +1 -1
  93. package/dist/{chunk-TOC5FSHP.js → chunk-NJ2SNXBJ.js} +12 -12
  94. package/dist/chunk-NJ2SNXBJ.js.map +1 -0
  95. package/dist/{chunk-OCR5DS4C.mjs → chunk-PE5EAHZK.mjs} +3 -3
  96. package/dist/chunk-PE5EAHZK.mjs.map +1 -0
  97. package/dist/{chunk-LZHMNOED.js → chunk-Q5EDCKQA.js} +26 -26
  98. package/dist/chunk-Q5EDCKQA.js.map +1 -0
  99. package/dist/{chunk-CLKKZSPZ.js → chunk-RBKGYWME.js} +20 -19
  100. package/dist/chunk-RBKGYWME.js.map +1 -0
  101. package/dist/{chunk-VRTRSEEH.mjs → chunk-RSJSZ7QH.mjs} +11 -11
  102. package/dist/chunk-RSJSZ7QH.mjs.map +1 -0
  103. package/dist/{chunk-E7RGBAYJ.js → chunk-TDCDEBGP.js} +30 -29
  104. package/dist/chunk-TDCDEBGP.js.map +1 -0
  105. package/dist/{chunk-JZXJQMVE.js → chunk-UIFFDRTE.js} +11 -11
  106. package/dist/chunk-UIFFDRTE.js.map +1 -0
  107. package/dist/{chunk-T5OZHYVM.mjs → chunk-UKT3PLON.mjs} +13 -85
  108. package/dist/chunk-UKT3PLON.mjs.map +1 -0
  109. package/dist/{chunk-UOFTHYIH.js → chunk-UL6XJGUZ.js} +4 -4
  110. package/dist/chunk-UL6XJGUZ.js.map +1 -0
  111. package/dist/chunk-VVWQTO4Y.mjs +77 -0
  112. package/dist/chunk-VVWQTO4Y.mjs.map +1 -0
  113. package/dist/{chunk-A3UP56MS.js → chunk-WA67GZSZ.js} +3 -3
  114. package/dist/chunk-WA67GZSZ.js.map +1 -0
  115. package/dist/{chunk-OLHGZXN3.mjs → chunk-WEEXCPSE.mjs} +5 -5
  116. package/dist/chunk-WEEXCPSE.mjs.map +1 -0
  117. package/dist/chunk-XGBE4SUV.js +2093 -0
  118. package/dist/chunk-XGBE4SUV.js.map +1 -0
  119. package/dist/{chunk-QU5OT4DF.js → chunk-XJ7ZAGC5.js} +5 -5
  120. package/dist/chunk-XJ7ZAGC5.js.map +1 -0
  121. package/dist/{chunk-ZI25QCHD.mjs → chunk-YOTQG4NP.mjs} +25 -25
  122. package/dist/chunk-YOTQG4NP.mjs.map +1 -0
  123. package/dist/{chunk-QAT2RWAO.mjs → chunk-Z36R3P62.mjs} +7 -7
  124. package/dist/chunk-Z36R3P62.mjs.map +1 -0
  125. package/dist/{chunk-7Z5LLJ3A.js → chunk-ZWQJSZEY.js} +13 -13
  126. package/dist/chunk-ZWQJSZEY.js.map +1 -0
  127. package/dist/config/index.js +6 -6
  128. package/dist/config/index.js.map +1 -1
  129. package/dist/config/index.mjs +6 -6
  130. package/dist/config/index.mjs.map +1 -1
  131. package/dist/config/server/index.js +37 -37
  132. package/dist/config/server/index.js.map +1 -1
  133. package/dist/config/server/index.mjs +37 -37
  134. package/dist/config/server/index.mjs.map +1 -1
  135. package/dist/i18n/index.d.mts +2 -2
  136. package/dist/i18n/index.d.ts +2 -2
  137. package/dist/i18n/index.js +16 -17
  138. package/dist/i18n/index.js.map +1 -1
  139. package/dist/i18n/index.mjs +16 -17
  140. package/dist/i18n/index.mjs.map +1 -1
  141. package/dist/imageCrop/index.js +11 -10
  142. package/dist/imageCrop/index.js.map +1 -1
  143. package/dist/imageCrop/index.mjs +11 -10
  144. package/dist/imageCrop/index.mjs.map +1 -1
  145. package/dist/index.d.mts +185 -100
  146. package/dist/index.d.ts +185 -100
  147. package/dist/index.js +225 -249
  148. package/dist/index.js.map +1 -1
  149. package/dist/index.mjs +80 -104
  150. package/dist/index.mjs.map +1 -1
  151. package/dist/logger/index.js +6 -6
  152. package/dist/logger/index.mjs +1 -1
  153. package/dist/mikuFusionGame/index.d.mts +112 -0
  154. package/dist/mikuFusionGame/index.d.ts +112 -0
  155. package/dist/mikuFusionGame/index.js +680 -0
  156. package/dist/mikuFusionGame/index.js.map +1 -0
  157. package/dist/mikuFusionGame/index.mjs +667 -0
  158. package/dist/mikuFusionGame/index.mjs.map +1 -0
  159. package/dist/mmd/admin/index.js +11 -10
  160. package/dist/mmd/admin/index.js.map +1 -1
  161. package/dist/mmd/admin/index.mjs +11 -10
  162. package/dist/mmd/admin/index.mjs.map +1 -1
  163. package/dist/mmd/index.js +223 -241
  164. package/dist/mmd/index.js.map +1 -1
  165. package/dist/mmd/index.mjs +220 -238
  166. package/dist/mmd/index.mjs.map +1 -1
  167. package/dist/mmd/server/index.js +6 -6
  168. package/dist/mmd/server/index.js.map +1 -1
  169. package/dist/mmd/server/index.mjs +6 -6
  170. package/dist/mmd/server/index.mjs.map +1 -1
  171. package/dist/music/index.js +16 -16
  172. package/dist/music/index.mjs +2 -2
  173. package/dist/music/server/index.js +8 -8
  174. package/dist/music/server/index.mjs +1 -1
  175. package/dist/request/index.js +2 -2
  176. package/dist/request/index.js.map +1 -1
  177. package/dist/request/index.mjs +2 -2
  178. package/dist/request/index.mjs.map +1 -1
  179. package/dist/storage/index.js +15 -14
  180. package/dist/storage/index.mjs +3 -2
  181. package/dist/testYourself/admin/index.js +3 -3
  182. package/dist/testYourself/admin/index.mjs +1 -1
  183. package/dist/testYourself/index.js +22 -22
  184. package/dist/testYourself/index.js.map +1 -1
  185. package/dist/testYourself/index.mjs +14 -14
  186. package/dist/testYourself/index.mjs.map +1 -1
  187. package/dist/testYourself/server/index.js +4 -4
  188. package/dist/testYourself/server/index.mjs +1 -1
  189. package/dist/universalExport/index.d.mts +3 -3
  190. package/dist/universalExport/index.d.ts +3 -3
  191. package/dist/universalExport/index.js +48 -47
  192. package/dist/universalExport/index.js.map +1 -1
  193. package/dist/universalExport/index.mjs +48 -47
  194. package/dist/universalExport/index.mjs.map +1 -1
  195. package/dist/universalExport/server/index.js +29 -29
  196. package/dist/universalExport/server/index.js.map +1 -1
  197. package/dist/universalExport/server/index.mjs +28 -28
  198. package/dist/universalExport/server/index.mjs.map +1 -1
  199. package/dist/universalFile/index.d.mts +3 -3
  200. package/dist/universalFile/index.d.ts +3 -3
  201. package/dist/universalFile/index.js +73 -72
  202. package/dist/universalFile/index.js.map +1 -1
  203. package/dist/universalFile/index.mjs +73 -72
  204. package/dist/universalFile/index.mjs.map +1 -1
  205. package/dist/universalFile/server/index.js +258 -260
  206. package/dist/universalFile/server/index.js.map +1 -1
  207. package/dist/universalFile/server/index.mjs +244 -246
  208. package/dist/universalFile/server/index.mjs.map +1 -1
  209. package/dist/utils/index.js +11 -11
  210. package/dist/utils/index.mjs +2 -2
  211. package/package.json +25 -31
  212. package/dist/AliyunOSSProvider-FWAKUB2T.js +0 -15
  213. package/dist/AliyunOSSProvider-KJYRIZES.mjs +0 -6
  214. package/dist/ConfigService-7MEZXKJ5.js +0 -21
  215. package/dist/ConfigService-BV57YYFW.mjs +0 -4
  216. package/dist/LocalStorageProvider-RTPMUOZ2.mjs +0 -6
  217. package/dist/LocalStorageProvider-XSRCUXOU.js +0 -15
  218. package/dist/PMXParser-L6IWHL4I.mjs +0 -4
  219. package/dist/PMXParser-YBS3B6HM.js +0 -13
  220. package/dist/chunk-3BGPZN4X.mjs.map +0 -1
  221. package/dist/chunk-3WOAPLEG.mjs.map +0 -1
  222. package/dist/chunk-6PRFP5EG.js.map +0 -1
  223. package/dist/chunk-6YKMCPQI.mjs.map +0 -1
  224. package/dist/chunk-7Z5LLJ3A.js.map +0 -1
  225. package/dist/chunk-A3UP56MS.js.map +0 -1
  226. package/dist/chunk-CD77U7LZ.js.map +0 -1
  227. package/dist/chunk-CLKKZSPZ.js.map +0 -1
  228. package/dist/chunk-CNTILN5J.mjs.map +0 -1
  229. package/dist/chunk-DUHZ7VZP.js.map +0 -1
  230. package/dist/chunk-DW2ZTOCV.js +0 -1727
  231. package/dist/chunk-DW2ZTOCV.js.map +0 -1
  232. package/dist/chunk-E7RGBAYJ.js.map +0 -1
  233. package/dist/chunk-JZXJQMVE.js.map +0 -1
  234. package/dist/chunk-KQGP6BTS.mjs.map +0 -1
  235. package/dist/chunk-LFG6FPM5.mjs +0 -1597
  236. package/dist/chunk-LFG6FPM5.mjs.map +0 -1
  237. package/dist/chunk-LX4XX6W7.js.map +0 -1
  238. package/dist/chunk-LZHMNOED.js.map +0 -1
  239. package/dist/chunk-MW4BCIZC.mjs.map +0 -1
  240. package/dist/chunk-OCR5DS4C.mjs.map +0 -1
  241. package/dist/chunk-OLHGZXN3.mjs.map +0 -1
  242. package/dist/chunk-OPPF3326.js.map +0 -1
  243. package/dist/chunk-QAT2RWAO.mjs.map +0 -1
  244. package/dist/chunk-QU5OT4DF.js.map +0 -1
  245. package/dist/chunk-T5OZHYVM.mjs.map +0 -1
  246. package/dist/chunk-TFQF2HDO.mjs.map +0 -1
  247. package/dist/chunk-TOC5FSHP.js.map +0 -1
  248. package/dist/chunk-TV3VKRJK.mjs.map +0 -1
  249. package/dist/chunk-UOFTHYIH.js.map +0 -1
  250. package/dist/chunk-VRTRSEEH.mjs.map +0 -1
  251. package/dist/chunk-ZI25QCHD.mjs.map +0 -1
@@ -2,6 +2,7 @@
2
2
 
3
3
  require('../chunk-DGUM43GV.js');
4
4
  var React2 = require('react');
5
+ var clsx = require('clsx');
5
6
  var lucideReact = require('lucide-react');
6
7
  var JSZip = require('jszip');
7
8
 
@@ -83,7 +84,7 @@ async function cropGridCell(imageInfo, cell, cellWidth, cellHeight, options = {}
83
84
  );
84
85
  });
85
86
  const extension = format.split("/")[1] || "png";
86
- const filename = `${filenamePrefix}_r${cell.row}_c${cell.column}.${extension}`;
87
+ const filename = filenamePrefix + "_r" + cell.row + "_c" + cell.column + "." + extension;
87
88
  return {
88
89
  blob,
89
90
  dataUrl: canvas.toDataURL(format, quality),
@@ -107,7 +108,7 @@ async function cropMultipleCells(imageInfo, cells, cellWidth, cellHeight, option
107
108
  onProgress(i + 1, cells.length);
108
109
  }
109
110
  } catch (error) {
110
- console.error(`\u88C1\u526A\u5355\u5143\u683C (${cell.row}, ${cell.column}) \u5931\u8D25:`, error);
111
+ console.error("\u88C1\u526A\u5355\u5143\u683C (" + cell.row + ", " + cell.column + ") \u5931\u8D25:", error);
111
112
  }
112
113
  }
113
114
  return results;
@@ -151,7 +152,7 @@ async function downloadAsZip(results, zipFilename = "cropped_images.zip") {
151
152
  }
152
153
  const zip = new JSZip__default.default();
153
154
  results.forEach((result, idx) => {
154
- const filename = result.filename || `crop_${idx}.png`;
155
+ const filename = result.filename || "crop_" + idx + ".png";
155
156
  zip.file(filename, result.blob);
156
157
  });
157
158
  const zipBlob = await zip.generateAsync({
@@ -179,7 +180,7 @@ async function downloadMultipleFiles(results, delay = 100) {
179
180
  for (let i = 0; i < results.length; i++) {
180
181
  const result = results[i];
181
182
  if (!result) continue;
182
- const filename = result.filename || `crop_${i}.png`;
183
+ const filename = result.filename || "crop_" + i + ".png";
183
184
  downloadBlob(result.blob, filename);
184
185
  if (i < results.length - 1) {
185
186
  await new Promise((resolve) => setTimeout(resolve, delay));
@@ -194,7 +195,7 @@ function formatFileSize(bytes) {
194
195
  const k = 1024;
195
196
  const sizes = ["B", "KB", "MB", "GB"];
196
197
  const i = Math.floor(Math.log(bytes) / Math.log(k));
197
- return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
198
+ return (bytes / Math.pow(k, i)).toFixed(2) + " " + sizes[i];
198
199
  }
199
200
  var GridControls = ({
200
201
  config,
@@ -338,7 +339,7 @@ var ImageGridCropper = ({
338
339
  const offsetX = col * cellWidth;
339
340
  const offsetY = row * cellHeight;
340
341
  cells.push({
341
- id: `cell_${row}_${col}`,
342
+ id: "cell_" + row + "_" + col,
342
343
  row,
343
344
  column: col,
344
345
  x: offsetX,
@@ -408,7 +409,7 @@ var ImageGridCropper = ({
408
409
  ctx.strokeRect(x, y, w, h);
409
410
  ctx.fillStyle = cell.selected ? "rgba(34, 197, 94, 0.9)" : "rgba(156, 163, 175, 0.7)";
410
411
  ctx.font = "12px sans-serif";
411
- ctx.fillText(`R${cell.row}C${cell.column}`, x + 5, y + 15);
412
+ ctx.fillText("R" + cell.row + "C" + cell.column, x + 5, y + 15);
412
413
  });
413
414
  }, [imageInfo, gridConfig, gridCells]);
414
415
  const toggleCellSelection = (cellId) => {
@@ -449,7 +450,7 @@ var ImageGridCropper = ({
449
450
  if (results.length === 0) {
450
451
  throw new Error("\u6CA1\u6709\u6210\u529F\u88C1\u526A\u7684\u56FE\u7247");
451
452
  }
452
- const zipFilename = options.zipFilename || `cropped_${Date.now()}.zip`;
453
+ const zipFilename = options.zipFilename || "cropped_" + Date.now() + ".zip";
453
454
  await downloadAsZip(results, zipFilename);
454
455
  onExportSuccess?.(results);
455
456
  } catch (err) {
@@ -478,7 +479,7 @@ var ImageGridCropper = ({
478
479
  drawPreview();
479
480
  }, [drawPreview]);
480
481
  const selectedCount = gridCells.filter((cell) => cell.selected).length;
481
- return /* @__PURE__ */ React2__default.default.createElement("div", { className: `w-full space-y-6 ${className}` }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React2__default.default.createElement(lucideReact.Scissors, { className: "w-7 h-7 text-blue-500" }), /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("h2", { className: "text-2xl font-bold text-gray-800 dark:text-gray-200" }, "\u7F51\u683C\u5F0F\u56FE\u7247\u88C1\u526A\u5DE5\u5177"), /* @__PURE__ */ React2__default.default.createElement("p", { className: "text-sm text-gray-600 dark:text-gray-400" }, "\u4E0A\u4F20\u56FE\u7247\uFF0C\u8BBE\u7F6E\u7F51\u683C\uFF0C\u88C1\u526A\u5E76\u5BFC\u51FA")))), error && /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center gap-2 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg" }, /* @__PURE__ */ React2__default.default.createElement(lucideReact.AlertCircle, { className: "w-5 h-5 text-red-500" }), /* @__PURE__ */ React2__default.default.createElement("p", { className: "text-sm text-red-700 dark:text-red-400" }, error)), /* @__PURE__ */ React2__default.default.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React2__default.default.createElement("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300" }, "\u4E0A\u4F20\u56FE\u7247"), /* @__PURE__ */ React2__default.default.createElement(
482
+ return /* @__PURE__ */ React2__default.default.createElement("div", { className: clsx.clsx("w-full space-y-6", className) }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React2__default.default.createElement(lucideReact.Scissors, { className: "w-7 h-7 text-blue-500" }), /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("h2", { className: "text-2xl font-bold text-gray-800 dark:text-gray-200" }, "\u7F51\u683C\u5F0F\u56FE\u7247\u88C1\u526A\u5DE5\u5177"), /* @__PURE__ */ React2__default.default.createElement("p", { className: "text-sm text-gray-600 dark:text-gray-400" }, "\u4E0A\u4F20\u56FE\u7247\uFF0C\u8BBE\u7F6E\u7F51\u683C\uFF0C\u88C1\u526A\u5E76\u5BFC\u51FA")))), error && /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center gap-2 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg" }, /* @__PURE__ */ React2__default.default.createElement(lucideReact.AlertCircle, { className: "w-5 h-5 text-red-500" }), /* @__PURE__ */ React2__default.default.createElement("p", { className: "text-sm text-red-700 dark:text-red-400" }, error)), /* @__PURE__ */ React2__default.default.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React2__default.default.createElement("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300" }, "\u4E0A\u4F20\u56FE\u7247"), /* @__PURE__ */ React2__default.default.createElement(
482
483
  "div",
483
484
  {
484
485
  className: "border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-8 text-center cursor-pointer hover:border-blue-400 dark:hover:border-blue-500 transition-colors",
@@ -526,7 +527,7 @@ var ImageGridCropper = ({
526
527
  "div",
527
528
  {
528
529
  key: cell.id,
529
- className: `p-3 rounded border ${cell.selected ? "border-green-500 bg-green-50 dark:bg-green-900/20" : "border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800"} cursor-pointer transition-colors`,
530
+ className: clsx.clsx("p-3 rounded border", cell.selected ? "border-green-500 bg-green-50 dark:bg-green-900/20" : "border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800", "cursor-pointer transition-colors"),
530
531
  onClick: () => toggleCellSelection(cell.id)
531
532
  },
532
533
  /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React2__default.default.createElement("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300" }, "R", cell.row, " C", cell.column), cell.selected ? /* @__PURE__ */ React2__default.default.createElement(lucideReact.CheckCircle2, { className: "w-4 h-4 text-green-500" }) : /* @__PURE__ */ React2__default.default.createElement(lucideReact.XCircle, { className: "w-4 h-4 text-gray-400" })),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/imageCrop/utils/cropUtils.ts","../../src/imageCrop/utils/downloadUtils.ts","../../src/imageCrop/components/GridControls.tsx","../../src/imageCrop/components/ImageGridCropper.tsx"],"names":["blob","JSZip","React","Grid","RefreshCw","Maximize2","useState","useRef","useCallback","useEffect","Scissors","AlertCircle","ImageIcon","CheckCircle2","XCircle","Loader2","Download"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 图片裁剪工具函数\n * Image Cropping Utilities\n */\n\nimport type { GridCell, ImageInfo, CropResult, CropOptions } from '../types';\n\n/**\n * 从文件加载图片\n */\nexport async function loadImageFromFile(file: File): Promise<ImageInfo> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n \n reader.onload = (e) => {\n const dataUrl = e.target?.result as string;\n const img = new Image();\n \n img.onload = () => {\n resolve({\n width: img.naturalWidth,\n height: img.naturalHeight,\n naturalWidth: img.naturalWidth,\n naturalHeight: img.naturalHeight,\n image: img,\n file,\n });\n };\n \n img.onerror = () => {\n reject(new Error('图片加载失败'));\n };\n \n img.src = dataUrl;\n };\n \n reader.onerror = () => {\n reject(new Error('文件读取失败'));\n };\n \n reader.readAsDataURL(file);\n });\n}\n\n/**\n * 裁剪单个网格单元格\n */\nexport async function cropGridCell(\n imageInfo: ImageInfo,\n cell: GridCell,\n cellWidth: number,\n cellHeight: number,\n options: CropOptions = {}\n): Promise<CropResult> {\n const {\n format = 'image/png',\n quality = 0.92,\n filenamePrefix = 'crop',\n } = options;\n\n if (!imageInfo.image) {\n throw new Error('图片资源未加载');\n }\n\n // 创建离屏canvas\n const canvas = document.createElement('canvas');\n canvas.width = cellWidth;\n canvas.height = cellHeight;\n \n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas context 创建失败');\n }\n\n // 计算源图片裁剪区域\n const sourceX = cell.offsetX;\n const sourceY = cell.offsetY;\n const sourceWidth = cellWidth;\n const sourceHeight = cellHeight;\n\n // 绘制裁剪区域\n ctx.drawImage(\n imageInfo.image,\n sourceX,\n sourceY,\n sourceWidth,\n sourceHeight,\n 0,\n 0,\n cellWidth,\n cellHeight\n );\n\n // 转换为Blob\n const blob = await new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('图片转换失败'));\n }\n },\n format,\n quality\n );\n });\n\n // 生成文件名\n const extension = format.split('/')[1] || 'png';\n const filename = `${filenamePrefix}_r${cell.row}_c${cell.column}.${extension}`;\n\n return {\n blob,\n dataUrl: canvas.toDataURL(format, quality),\n index: cell.row * 1000 + cell.column, // 简单的索引生成\n row: cell.row,\n column: cell.column,\n cell,\n filename,\n };\n}\n\n/**\n * 批量裁剪多个网格单元格\n */\nexport async function cropMultipleCells(\n imageInfo: ImageInfo,\n cells: GridCell[],\n cellWidth: number,\n cellHeight: number,\n options: CropOptions = {},\n onProgress?: (current: number, total: number) => void\n): Promise<CropResult[]> {\n const results: CropResult[] = [];\n \n for (let i = 0; i < cells.length; i++) {\n const cell = cells[i];\n if (!cell || !cell.selected) continue;\n \n try {\n const result = await cropGridCell(imageInfo, cell, cellWidth, cellHeight, options);\n results.push(result);\n \n if (onProgress) {\n onProgress(i + 1, cells.length);\n }\n } catch (error) {\n console.error(`裁剪单元格 (${cell.row}, ${cell.column}) 失败:`, error);\n }\n }\n \n return results;\n}\n\n/**\n * 生成网格单元格预览\n */\nexport async function generateCellPreview(\n imageInfo: ImageInfo,\n cell: GridCell,\n cellWidth: number,\n cellHeight: number,\n previewSize: number = 100\n): Promise<string> {\n const canvas = document.createElement('canvas');\n const scale = Math.min(previewSize / cellWidth, previewSize / cellHeight);\n \n canvas.width = cellWidth * scale;\n canvas.height = cellHeight * scale;\n \n const ctx = canvas.getContext('2d');\n if (!ctx || !imageInfo.image) {\n throw new Error('Canvas context 创建失败或图片未加载');\n }\n\n ctx.drawImage(\n imageInfo.image,\n cell.offsetX,\n cell.offsetY,\n cellWidth,\n cellHeight,\n 0,\n 0,\n canvas.width,\n canvas.height\n );\n\n return canvas.toDataURL('image/png');\n}\n\n/**\n * 验证裁剪区域是否在图片范围内\n */\nexport function validateCropArea(\n imageWidth: number,\n imageHeight: number,\n offsetX: number,\n offsetY: number,\n cropWidth: number,\n cropHeight: number\n): boolean {\n return (\n offsetX >= 0 &&\n offsetY >= 0 &&\n offsetX + cropWidth <= imageWidth &&\n offsetY + cropHeight <= imageHeight\n );\n}\n\n/**\n * 自动调整偏移量以保持在图片范围内\n */\nexport function constrainOffset(\n imageWidth: number,\n imageHeight: number,\n offsetX: number,\n offsetY: number,\n cropWidth: number,\n cropHeight: number\n): { offsetX: number; offsetY: number } {\n const constrainedX = Math.max(0, Math.min(offsetX, imageWidth - cropWidth));\n const constrainedY = Math.max(0, Math.min(offsetY, imageHeight - cropHeight));\n \n return {\n offsetX: constrainedX,\n offsetY: constrainedY,\n };\n}\n\n\n\n\n\n\n","/**\n * 下载工具函数\n * Download Utilities\n */\n\nimport JSZip from 'jszip';\nimport type { CropResult } from '../types';\n\n/**\n * 创建ZIP压缩包并下载\n */\nexport async function downloadAsZip(\n results: CropResult[],\n zipFilename: string = 'cropped_images.zip'\n): Promise<void> {\n if (results.length === 0) {\n throw new Error('没有可下载的图片');\n }\n\n const zip = new JSZip();\n \n // 添加所有裁剪结果到ZIP\n results.forEach((result, idx) => {\n const filename = result.filename || `crop_${idx}.png`;\n zip.file(filename, result.blob);\n });\n\n // 生成ZIP文件\n const zipBlob = await zip.generateAsync({\n type: 'blob',\n compression: 'DEFLATE',\n compressionOptions: {\n level: 6,\n },\n });\n\n // 触发下载\n downloadBlob(zipBlob, zipFilename);\n}\n\n/**\n * 下载单个Blob文件\n */\nexport function downloadBlob(blob: Blob, filename: string): void {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n \n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n \n // 释放URL对象\n setTimeout(() => {\n URL.revokeObjectURL(url);\n }, 100);\n}\n\n/**\n * 批量下载多个文件(不压缩)\n */\nexport async function downloadMultipleFiles(\n results: CropResult[],\n delay: number = 100\n): Promise<void> {\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (!result) continue;\n \n const filename = result.filename || `crop_${i}.png`;\n downloadBlob(result.blob, filename);\n \n // 添加延迟避免浏览器阻止多个下载\n if (i < results.length - 1) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n}\n\n/**\n * 计算压缩包大小\n */\nexport function calculateTotalSize(results: CropResult[]): number {\n return results.reduce((total, result) => total + result.blob.size, 0);\n}\n\n/**\n * 格式化文件大小\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n \n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n \n return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;\n}\n\n\n\n\n\n\n","/**\n * 网格控制组件\n * Grid Controls Component\n */\n\n'use client';\n\nimport React from 'react';\nimport { Grid, Maximize2, RefreshCw } from 'lucide-react';\nimport type { GridConfig } from '../types';\n\nexport interface GridControlsProps {\n /** 网格配置 */\n config: GridConfig;\n /** 配置变更回调 */\n onChange: (config: GridConfig) => void;\n /** 是否禁用 */\n disabled?: boolean;\n /** 最大行列数 */\n maxRows?: number;\n maxColumns?: number;\n /** 最大最小单元格尺寸 */\n maxCellSize?: number;\n minCellSize?: number;\n /** 是否显示重置按钮 */\n showReset?: boolean;\n /** 重置回调 */\n onReset?: () => void;\n}\n\nexport const GridControls: React.FC<GridControlsProps> = ({\n config,\n onChange,\n disabled = false,\n maxRows = 20,\n maxColumns = 20,\n maxCellSize = 2000,\n minCellSize = 10,\n showReset = true,\n onReset,\n}) => {\n const handleChange = (field: keyof GridConfig, value: number) => {\n // 确保值在有效范围内\n let constrainedValue = value;\n \n if (field === 'rows') {\n constrainedValue = Math.max(1, Math.min(maxRows, value));\n } else if (field === 'columns') {\n constrainedValue = Math.max(1, Math.min(maxColumns, value));\n } else if (field === 'cellWidth' || field === 'cellHeight') {\n constrainedValue = Math.max(minCellSize, Math.min(maxCellSize, value));\n }\n \n onChange({\n ...config,\n [field]: constrainedValue,\n });\n };\n\n return (\n <div className=\"space-y-4 p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700\">\n {/* 标题 */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Grid className=\"w-5 h-5 text-blue-500\" />\n <h3 className=\"text-lg font-semibold text-gray-800 dark:text-gray-200\">\n 网格设置\n </h3>\n </div>\n \n {showReset && (\n <button\n onClick={onReset}\n disabled={disabled}\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm text-gray-600 dark:text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title=\"重置为默认值\"\n >\n <RefreshCw className=\"w-4 h-4\" />\n 重置\n </button>\n )}\n </div>\n\n {/* 网格行列控制 */}\n <div className=\"grid grid-cols-2 gap-4\">\n {/* 行数 */}\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n 行数\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n min={1}\n max={maxRows}\n value={config.rows}\n onChange={(e) => handleChange('rows', parseInt(e.target.value) || 1)}\n disabled={disabled}\n className=\"flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <input\n type=\"range\"\n min={1}\n max={maxRows}\n value={config.rows}\n onChange={(e) => handleChange('rows', parseInt(e.target.value))}\n disabled={disabled}\n className=\"flex-1 h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n </div>\n </div>\n\n {/* 列数 */}\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n 列数\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n min={1}\n max={maxColumns}\n value={config.columns}\n onChange={(e) => handleChange('columns', parseInt(e.target.value) || 1)}\n disabled={disabled}\n className=\"flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <input\n type=\"range\"\n min={1}\n max={maxColumns}\n value={config.columns}\n onChange={(e) => handleChange('columns', parseInt(e.target.value))}\n disabled={disabled}\n className=\"flex-1 h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n </div>\n </div>\n </div>\n\n {/* 单元格尺寸控制 */}\n <div className=\"grid grid-cols-2 gap-4\">\n {/* 单元格宽度 */}\n <div className=\"space-y-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium text-gray-700 dark:text-gray-300\">\n <Maximize2 className=\"w-4 h-4\" />\n 单元格宽度 (px)\n </label>\n <input\n type=\"number\"\n min={minCellSize}\n max={maxCellSize}\n value={config.cellWidth}\n onChange={(e) => handleChange('cellWidth', parseInt(e.target.value) || minCellSize)}\n disabled={disabled}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n </div>\n\n {/* 单元格高度 */}\n <div className=\"space-y-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium text-gray-700 dark:text-gray-300\">\n <Maximize2 className=\"w-4 h-4\" />\n 单元格高度 (px)\n </label>\n <input\n type=\"number\"\n min={minCellSize}\n max={maxCellSize}\n value={config.cellHeight}\n onChange={(e) => handleChange('cellHeight', parseInt(e.target.value) || minCellSize)}\n disabled={disabled}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n </div>\n </div>\n\n {/* 统计信息 */}\n <div className=\"pt-3 border-t border-gray-200 dark:border-gray-700\">\n <div className=\"grid grid-cols-2 gap-4 text-sm text-gray-600 dark:text-gray-400\">\n <div className=\"flex justify-between\">\n <span>总单元格数:</span>\n <span className=\"font-medium text-gray-900 dark:text-gray-100\">\n {config.rows * config.columns}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span>总尺寸:</span>\n <span className=\"font-medium text-gray-900 dark:text-gray-100\">\n {config.cellWidth * config.columns} × {config.cellHeight * config.rows}\n </span>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default GridControls;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","/**\n * 图片网格裁剪器主组件\n * Image Grid Cropper Main Component\n */\n\n'use client';\n\nimport React, { useState, useEffect, useCallback, useRef } from 'react';\nimport {\n Download,\n Scissors,\n CheckCircle2,\n XCircle,\n Loader2,\n Image as ImageIcon,\n AlertCircle,\n Move,\n} from 'lucide-react';\n\nimport type {\n GridConfig,\n GridCell,\n ImageInfo,\n CropResult,\n ExportOptions,\n ImageGridCropperConfig,\n} from '../types';\nimport {\n loadImageFromFile,\n cropMultipleCells,\n constrainOffset,\n validateCropArea,\n} from '../utils/cropUtils';\nimport { downloadAsZip, formatFileSize, calculateTotalSize } from '../utils/downloadUtils';\nimport { GridControls } from './GridControls';\n\n// ============= 主组件属性 =============\n\nexport interface ImageGridCropperProps {\n /** 初始配置 */\n config?: ImageGridCropperConfig;\n /** 导出成功回调 */\n onExportSuccess?: (results: CropResult[]) => void;\n /** 导出失败回调 */\n onExportError?: (error: string) => void;\n /** 自定义样式类名 */\n className?: string;\n}\n\n// ============= 主组件 =============\n\nexport const ImageGridCropper: React.FC<ImageGridCropperProps> = ({\n config = {},\n onExportSuccess,\n onExportError,\n className = '',\n}) => {\n // ============= 配置 =============\n const {\n defaultRows = 3,\n defaultColumns = 3,\n defaultCellWidth = 256,\n defaultCellHeight = 256,\n maxRows = 20,\n maxColumns = 20,\n maxCellSize = 2000,\n minCellSize = 10,\n } = config;\n\n // ============= 状态管理 =============\n const [imageInfo, setImageInfo] = useState<ImageInfo | null>(null);\n const [gridConfig, setGridConfig] = useState<GridConfig>({\n rows: defaultRows,\n columns: defaultColumns,\n cellWidth: defaultCellWidth,\n cellHeight: defaultCellHeight,\n });\n const [gridCells, setGridCells] = useState<GridCell[]>([]);\n const [isProcessing, setIsProcessing] = useState(false);\n const [progress, setProgress] = useState({ current: 0, total: 0 });\n const [error, setError] = useState<string | null>(null);\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // ============= 生成网格单元格 =============\n const generateGridCells = useCallback(() => {\n const cells: GridCell[] = [];\n const { rows, columns, cellWidth, cellHeight } = gridConfig;\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < columns; col++) {\n const offsetX = col * cellWidth;\n const offsetY = row * cellHeight;\n\n cells.push({\n id: `cell_${row}_${col}`,\n row,\n column: col,\n x: offsetX,\n y: offsetY,\n offsetX,\n offsetY,\n width: cellWidth,\n height: cellHeight,\n selected: true, // 默认全选\n });\n }\n }\n\n setGridCells(cells);\n }, [gridConfig]);\n\n // ============= 图片加载 =============\n const handleFileSelect = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n if (!file) return;\n\n // 验证文件类型\n if (!file.type.startsWith('image/')) {\n setError('请选择图片文件');\n return;\n }\n\n try {\n setError(null);\n setIsProcessing(true);\n\n const info = await loadImageFromFile(file);\n setImageInfo(info);\n generateGridCells();\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : '图片加载失败';\n setError(errorMsg);\n onExportError?.(errorMsg);\n } finally {\n setIsProcessing(false);\n }\n\n // 清空input以允许重复选择同一文件\n event.target.value = '';\n };\n\n // ============= 绘制预览 =============\n const drawPreview = useCallback(() => {\n if (!imageInfo || !canvasRef.current) return;\n\n const canvas = canvasRef.current;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n // 设置canvas尺寸\n const maxWidth = 800;\n const maxHeight = 600;\n const scale = Math.min(\n maxWidth / imageInfo.width,\n maxHeight / imageInfo.height,\n 1\n );\n\n canvas.width = imageInfo.width * scale;\n canvas.height = imageInfo.height * scale;\n\n if (!imageInfo.image) return;\n\n // 绘制图片\n ctx.drawImage(imageInfo.image, 0, 0, canvas.width, canvas.height);\n\n // 绘制网格线\n ctx.strokeStyle = 'rgba(59, 130, 246, 0.6)'; // 蓝色\n ctx.lineWidth = 2;\n\n const { cellWidth, cellHeight } = gridConfig;\n\n gridCells.forEach((cell) => {\n const x = cell.offsetX * scale;\n const y = cell.offsetY * scale;\n const w = cellWidth * scale;\n const h = cellHeight * scale;\n\n // 绘制边框\n if (cell.selected) {\n ctx.strokeStyle = 'rgba(34, 197, 94, 0.8)'; // 绿色表示选中\n } else {\n ctx.strokeStyle = 'rgba(156, 163, 175, 0.5)'; // 灰色表示未选中\n }\n \n ctx.strokeRect(x, y, w, h);\n\n // 绘制单元格编号\n ctx.fillStyle = cell.selected ? 'rgba(34, 197, 94, 0.9)' : 'rgba(156, 163, 175, 0.7)';\n ctx.font = '12px sans-serif';\n ctx.fillText(`R${cell.row}C${cell.column}`, x + 5, y + 15);\n });\n }, [imageInfo, gridConfig, gridCells]);\n\n // ============= 单元格选择切换 =============\n const toggleCellSelection = (cellId: string) => {\n setGridCells((prev) =>\n prev.map((cell) =>\n cell.id === cellId ? { ...cell, selected: !cell.selected } : cell\n )\n );\n };\n\n // ============= 全选/取消全选 =============\n const toggleSelectAll = () => {\n const allSelected = gridCells.every((cell) => cell.selected);\n setGridCells((prev) =>\n prev.map((cell) => ({ ...cell, selected: !allSelected }))\n );\n };\n\n // ============= 调整单元格偏移 =============\n const adjustCellOffset = (cellId: string, deltaX: number, deltaY: number) => {\n if (!imageInfo) return;\n\n setGridCells((prev) =>\n prev.map((cell) => {\n if (cell.id !== cellId) return cell;\n\n const newOffsetX = cell.offsetX + deltaX;\n const newOffsetY = cell.offsetY + deltaY;\n\n const constrained = constrainOffset(\n imageInfo.width,\n imageInfo.height,\n newOffsetX,\n newOffsetY,\n gridConfig.cellWidth,\n gridConfig.cellHeight\n );\n\n return {\n ...cell,\n offsetX: constrained.offsetX,\n offsetY: constrained.offsetY,\n };\n })\n );\n };\n\n // ============= 导出裁剪图片 =============\n const handleExport = async (options: ExportOptions = {}) => {\n if (!imageInfo) {\n setError('请先上传图片');\n return;\n }\n\n const selectedCells = gridCells.filter((cell) => cell.selected);\n if (selectedCells.length === 0) {\n setError('请至少选择一个单元格');\n return;\n }\n\n try {\n setError(null);\n setIsProcessing(true);\n setProgress({ current: 0, total: selectedCells.length });\n\n const results = await cropMultipleCells(\n imageInfo,\n selectedCells,\n gridConfig.cellWidth,\n gridConfig.cellHeight,\n options.cropOptions,\n (current, total) => setProgress({ current, total })\n );\n\n if (results.length === 0) {\n throw new Error('没有成功裁剪的图片');\n }\n\n // 下载为ZIP\n const zipFilename = options.zipFilename || `cropped_${Date.now()}.zip`;\n await downloadAsZip(results, zipFilename);\n\n onExportSuccess?.(results);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : '导出失败';\n setError(errorMsg);\n onExportError?.(errorMsg);\n } finally {\n setIsProcessing(false);\n setProgress({ current: 0, total: 0 });\n }\n };\n\n // ============= 重置配置 =============\n const handleReset = () => {\n setGridConfig({\n rows: defaultRows,\n columns: defaultColumns,\n cellWidth: defaultCellWidth,\n cellHeight: defaultCellHeight,\n });\n };\n\n // ============= 效果 =============\n useEffect(() => {\n if (imageInfo) {\n generateGridCells();\n }\n }, [imageInfo, generateGridCells]);\n\n useEffect(() => {\n drawPreview();\n }, [drawPreview]);\n\n // ============= 渲染 =============\n const selectedCount = gridCells.filter((cell) => cell.selected).length;\n\n return (\n <div className={`w-full space-y-6 ${className}`}>\n {/* 头部 */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Scissors className=\"w-7 h-7 text-blue-500\" />\n <div>\n <h2 className=\"text-2xl font-bold text-gray-800 dark:text-gray-200\">\n 网格式图片裁剪工具\n </h2>\n <p className=\"text-sm text-gray-600 dark:text-gray-400\">\n 上传图片,设置网格,裁剪并导出\n </p>\n </div>\n </div>\n </div>\n\n {/* 错误提示 */}\n {error && (\n <div className=\"flex items-center gap-2 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg\">\n <AlertCircle className=\"w-5 h-5 text-red-500\" />\n <p className=\"text-sm text-red-700 dark:text-red-400\">{error}</p>\n </div>\n )}\n\n {/* 上传区域 */}\n <div className=\"space-y-4\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n 上传图片\n </label>\n <div\n className=\"border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-8 text-center cursor-pointer hover:border-blue-400 dark:hover:border-blue-500 transition-colors\"\n onClick={() => fileInputRef.current?.click()}\n >\n <ImageIcon className=\"w-12 h-12 mx-auto mb-4 text-gray-400\" />\n <p className=\"text-gray-600 dark:text-gray-400 mb-2\">\n 点击选择图片或拖拽文件到这里\n </p>\n <p className=\"text-sm text-gray-500\">支持 PNG, JPG, WEBP 等格式</p>\n {imageInfo && imageInfo.file && (\n <p className=\"mt-4 text-sm text-green-600 dark:text-green-400\">\n ✓ 已上传: {imageInfo.file.name} ({imageInfo.width} × {imageInfo.height})\n </p>\n )}\n </div>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n className=\"hidden\"\n />\n </div>\n\n {/* 网格配置 */}\n {imageInfo && (\n <GridControls\n config={gridConfig}\n onChange={setGridConfig}\n disabled={isProcessing}\n maxRows={maxRows}\n maxColumns={maxColumns}\n maxCellSize={maxCellSize}\n minCellSize={minCellSize}\n onReset={handleReset}\n />\n )}\n\n {/* 预览区域 */}\n {imageInfo && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-lg font-semibold text-gray-800 dark:text-gray-200\">\n 预览与调整\n </h3>\n <button\n onClick={toggleSelectAll}\n className=\"px-4 py-2 text-sm text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded-md transition-colors\"\n >\n {gridCells.every((cell) => cell.selected) ? '取消全选' : '全选'}\n </button>\n </div>\n\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden bg-gray-50 dark:bg-gray-900 p-4\">\n <canvas\n ref={canvasRef}\n className=\"max-w-full mx-auto border border-gray-300 dark:border-gray-600\"\n />\n </div>\n\n {/* 单元格列表 */}\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n 单元格列表 ({selectedCount}/{gridCells.length} 已选中)\n </h4>\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 max-h-64 overflow-y-auto\">\n {gridCells.map((cell) => (\n <div\n key={cell.id}\n className={`p-3 rounded border ${\n cell.selected\n ? 'border-green-500 bg-green-50 dark:bg-green-900/20'\n : 'border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800'\n } cursor-pointer transition-colors`}\n onClick={() => toggleCellSelection(cell.id)}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n R{cell.row} C{cell.column}\n </span>\n {cell.selected ? (\n <CheckCircle2 className=\"w-4 h-4 text-green-500\" />\n ) : (\n <XCircle className=\"w-4 h-4 text-gray-400\" />\n )}\n </div>\n <div className=\"text-xs text-gray-500 space-y-1\">\n <p>X: {cell.offsetX}px</p>\n <p>Y: {cell.offsetY}px</p>\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n )}\n\n {/* 导出按钮 */}\n {imageInfo && (\n <div className=\"flex items-center justify-between p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800\">\n <div className=\"text-sm text-gray-700 dark:text-gray-300\">\n <p className=\"font-medium\">准备导出 {selectedCount} 个裁剪图片</p>\n {isProcessing && (\n <p className=\"text-xs text-gray-600 dark:text-gray-400 mt-1\">\n 进度: {progress.current}/{progress.total}\n </p>\n )}\n </div>\n <button\n onClick={() => handleExport()}\n disabled={isProcessing || selectedCount === 0}\n className=\"flex items-center gap-2 px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isProcessing ? (\n <>\n <Loader2 className=\"w-5 h-5 animate-spin\" />\n 处理中...\n </>\n ) : (\n <>\n <Download className=\"w-5 h-5\" />\n 导出为 ZIP\n </>\n )}\n </button>\n </div>\n )}\n </div>\n );\n};\n\nexport default ImageGridCropper;\n\n\n\n\n\n\n"]}
1
+ {"version":3,"sources":["../../src/imageCrop/utils/cropUtils.ts","../../src/imageCrop/utils/downloadUtils.ts","../../src/imageCrop/components/GridControls.tsx","../../src/imageCrop/components/ImageGridCropper.tsx"],"names":["blob","JSZip","React","Grid","RefreshCw","Maximize2","useState","useRef","useCallback","useEffect","clsx","Scissors","AlertCircle","ImageIcon","CheckCircle2","XCircle","Loader2","Download"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * 图片裁剪工具函数\n * Image Cropping Utilities\n */\n\nimport type { GridCell, ImageInfo, CropResult, CropOptions } from '../types';\n\n/**\n * 从文件加载图片\n */\nexport async function loadImageFromFile(file: File): Promise<ImageInfo> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n \n reader.onload = (e) => {\n const dataUrl = e.target?.result as string;\n const img = new Image();\n \n img.onload = () => {\n resolve({\n width: img.naturalWidth,\n height: img.naturalHeight,\n naturalWidth: img.naturalWidth,\n naturalHeight: img.naturalHeight,\n image: img,\n file,\n });\n };\n \n img.onerror = () => {\n reject(new Error('图片加载失败'));\n };\n \n img.src = dataUrl;\n };\n \n reader.onerror = () => {\n reject(new Error('文件读取失败'));\n };\n \n reader.readAsDataURL(file);\n });\n}\n\n/**\n * 裁剪单个网格单元格\n */\nexport async function cropGridCell(\n imageInfo: ImageInfo,\n cell: GridCell,\n cellWidth: number,\n cellHeight: number,\n options: CropOptions = {}\n): Promise<CropResult> {\n const {\n format = 'image/png',\n quality = 0.92,\n filenamePrefix = 'crop',\n } = options;\n\n if (!imageInfo.image) {\n throw new Error('图片资源未加载');\n }\n\n // 创建离屏canvas\n const canvas = document.createElement('canvas');\n canvas.width = cellWidth;\n canvas.height = cellHeight;\n \n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas context 创建失败');\n }\n\n // 计算源图片裁剪区域\n const sourceX = cell.offsetX;\n const sourceY = cell.offsetY;\n const sourceWidth = cellWidth;\n const sourceHeight = cellHeight;\n\n // 绘制裁剪区域\n ctx.drawImage(\n imageInfo.image,\n sourceX,\n sourceY,\n sourceWidth,\n sourceHeight,\n 0,\n 0,\n cellWidth,\n cellHeight\n );\n\n // 转换为Blob\n const blob = await new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('图片转换失败'));\n }\n },\n format,\n quality\n );\n });\n\n // 生成文件名\n const extension = format.split('/')[1] || 'png';\n const filename = (filenamePrefix) + '_r' + (cell.row) + '_c' + (cell.column) + '.' + (extension);\n\n return {\n blob,\n dataUrl: canvas.toDataURL(format, quality),\n index: cell.row * 1000 + cell.column, // 简单的索引生成\n row: cell.row,\n column: cell.column,\n cell,\n filename,\n };\n}\n\n/**\n * 批量裁剪多个网格单元格\n */\nexport async function cropMultipleCells(\n imageInfo: ImageInfo,\n cells: GridCell[],\n cellWidth: number,\n cellHeight: number,\n options: CropOptions = {},\n onProgress?: (current: number, total: number) => void\n): Promise<CropResult[]> {\n const results: CropResult[] = [];\n \n for (let i = 0; i < cells.length; i++) {\n const cell = cells[i];\n if (!cell || !cell.selected) continue;\n \n try {\n const result = await cropGridCell(imageInfo, cell, cellWidth, cellHeight, options);\n results.push(result);\n \n if (onProgress) {\n onProgress(i + 1, cells.length);\n }\n } catch (error) {\n console.error('裁剪单元格 (' + (cell.row) + ', ' + (cell.column) + ') 失败:', error);\n }\n }\n \n return results;\n}\n\n/**\n * 生成网格单元格预览\n */\nexport async function generateCellPreview(\n imageInfo: ImageInfo,\n cell: GridCell,\n cellWidth: number,\n cellHeight: number,\n previewSize: number = 100\n): Promise<string> {\n const canvas = document.createElement('canvas');\n const scale = Math.min(previewSize / cellWidth, previewSize / cellHeight);\n \n canvas.width = cellWidth * scale;\n canvas.height = cellHeight * scale;\n \n const ctx = canvas.getContext('2d');\n if (!ctx || !imageInfo.image) {\n throw new Error('Canvas context 创建失败或图片未加载');\n }\n\n ctx.drawImage(\n imageInfo.image,\n cell.offsetX,\n cell.offsetY,\n cellWidth,\n cellHeight,\n 0,\n 0,\n canvas.width,\n canvas.height\n );\n\n return canvas.toDataURL('image/png');\n}\n\n/**\n * 验证裁剪区域是否在图片范围内\n */\nexport function validateCropArea(\n imageWidth: number,\n imageHeight: number,\n offsetX: number,\n offsetY: number,\n cropWidth: number,\n cropHeight: number\n): boolean {\n return (\n offsetX >= 0 &&\n offsetY >= 0 &&\n offsetX + cropWidth <= imageWidth &&\n offsetY + cropHeight <= imageHeight\n );\n}\n\n/**\n * 自动调整偏移量以保持在图片范围内\n */\nexport function constrainOffset(\n imageWidth: number,\n imageHeight: number,\n offsetX: number,\n offsetY: number,\n cropWidth: number,\n cropHeight: number\n): { offsetX: number; offsetY: number } {\n const constrainedX = Math.max(0, Math.min(offsetX, imageWidth - cropWidth));\n const constrainedY = Math.max(0, Math.min(offsetY, imageHeight - cropHeight));\n \n return {\n offsetX: constrainedX,\n offsetY: constrainedY,\n };\n}\n\n\n\n\n\n\n","/**\n * 下载工具函数\n * Download Utilities\n */\n\nimport JSZip from 'jszip';\nimport type { CropResult } from '../types';\n\n/**\n * 创建ZIP压缩包并下载\n */\nexport async function downloadAsZip(\n results: CropResult[],\n zipFilename: string = 'cropped_images.zip'\n): Promise<void> {\n if (results.length === 0) {\n throw new Error('没有可下载的图片');\n }\n\n const zip = new JSZip();\n \n // 添加所有裁剪结果到ZIP\n results.forEach((result, idx) => {\n const filename = result.filename || 'crop_' + (idx) + '.png';\n zip.file(filename, result.blob);\n });\n\n // 生成ZIP文件\n const zipBlob = await zip.generateAsync({\n type: 'blob',\n compression: 'DEFLATE',\n compressionOptions: {\n level: 6,\n },\n });\n\n // 触发下载\n downloadBlob(zipBlob, zipFilename);\n}\n\n/**\n * 下载单个Blob文件\n */\nexport function downloadBlob(blob: Blob, filename: string): void {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n \n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n \n // 释放URL对象\n setTimeout(() => {\n URL.revokeObjectURL(url);\n }, 100);\n}\n\n/**\n * 批量下载多个文件(不压缩)\n */\nexport async function downloadMultipleFiles(\n results: CropResult[],\n delay: number = 100\n): Promise<void> {\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (!result) continue;\n \n const filename = result.filename || 'crop_' + (i) + '.png';\n downloadBlob(result.blob, filename);\n \n // 添加延迟避免浏览器阻止多个下载\n if (i < results.length - 1) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n}\n\n/**\n * 计算压缩包大小\n */\nexport function calculateTotalSize(results: CropResult[]): number {\n return results.reduce((total, result) => total + result.blob.size, 0);\n}\n\n/**\n * 格式化文件大小\n */\nexport function formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 B';\n \n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n \n return ((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + (sizes[i]);\n}\n\n\n\n\n\n\n","/**\n * 网格控制组件\n * Grid Controls Component\n */\n\n'use client';\n\nimport React from 'react';\nimport { Grid, Maximize2, RefreshCw } from 'lucide-react';\nimport type { GridConfig } from '../types';\n\nexport interface GridControlsProps {\n /** 网格配置 */\n config: GridConfig;\n /** 配置变更回调 */\n onChange: (config: GridConfig) => void;\n /** 是否禁用 */\n disabled?: boolean;\n /** 最大行列数 */\n maxRows?: number;\n maxColumns?: number;\n /** 最大最小单元格尺寸 */\n maxCellSize?: number;\n minCellSize?: number;\n /** 是否显示重置按钮 */\n showReset?: boolean;\n /** 重置回调 */\n onReset?: () => void;\n}\n\nexport const GridControls: React.FC<GridControlsProps> = ({\n config,\n onChange,\n disabled = false,\n maxRows = 20,\n maxColumns = 20,\n maxCellSize = 2000,\n minCellSize = 10,\n showReset = true,\n onReset,\n}) => {\n const handleChange = (field: keyof GridConfig, value: number) => {\n // 确保值在有效范围内\n let constrainedValue = value;\n \n if (field === 'rows') {\n constrainedValue = Math.max(1, Math.min(maxRows, value));\n } else if (field === 'columns') {\n constrainedValue = Math.max(1, Math.min(maxColumns, value));\n } else if (field === 'cellWidth' || field === 'cellHeight') {\n constrainedValue = Math.max(minCellSize, Math.min(maxCellSize, value));\n }\n \n onChange({\n ...config,\n [field]: constrainedValue,\n });\n };\n\n return (\n <div className=\"space-y-4 p-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700\">\n {/* 标题 */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Grid className=\"w-5 h-5 text-blue-500\" />\n <h3 className=\"text-lg font-semibold text-gray-800 dark:text-gray-200\">\n 网格设置\n </h3>\n </div>\n \n {showReset && (\n <button\n onClick={onReset}\n disabled={disabled}\n className=\"flex items-center gap-1 px-3 py-1.5 text-sm text-gray-600 dark:text-gray-400 hover:text-blue-500 dark:hover:text-blue-400 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n title=\"重置为默认值\"\n >\n <RefreshCw className=\"w-4 h-4\" />\n 重置\n </button>\n )}\n </div>\n\n {/* 网格行列控制 */}\n <div className=\"grid grid-cols-2 gap-4\">\n {/* 行数 */}\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n 行数\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n min={1}\n max={maxRows}\n value={config.rows}\n onChange={(e) => handleChange('rows', parseInt(e.target.value) || 1)}\n disabled={disabled}\n className=\"flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <input\n type=\"range\"\n min={1}\n max={maxRows}\n value={config.rows}\n onChange={(e) => handleChange('rows', parseInt(e.target.value))}\n disabled={disabled}\n className=\"flex-1 h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n </div>\n </div>\n\n {/* 列数 */}\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n 列数\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"number\"\n min={1}\n max={maxColumns}\n value={config.columns}\n onChange={(e) => handleChange('columns', parseInt(e.target.value) || 1)}\n disabled={disabled}\n className=\"flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <input\n type=\"range\"\n min={1}\n max={maxColumns}\n value={config.columns}\n onChange={(e) => handleChange('columns', parseInt(e.target.value))}\n disabled={disabled}\n className=\"flex-1 h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n </div>\n </div>\n </div>\n\n {/* 单元格尺寸控制 */}\n <div className=\"grid grid-cols-2 gap-4\">\n {/* 单元格宽度 */}\n <div className=\"space-y-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium text-gray-700 dark:text-gray-300\">\n <Maximize2 className=\"w-4 h-4\" />\n 单元格宽度 (px)\n </label>\n <input\n type=\"number\"\n min={minCellSize}\n max={maxCellSize}\n value={config.cellWidth}\n onChange={(e) => handleChange('cellWidth', parseInt(e.target.value) || minCellSize)}\n disabled={disabled}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n </div>\n\n {/* 单元格高度 */}\n <div className=\"space-y-2\">\n <label className=\"flex items-center gap-2 text-sm font-medium text-gray-700 dark:text-gray-300\">\n <Maximize2 className=\"w-4 h-4\" />\n 单元格高度 (px)\n </label>\n <input\n type=\"number\"\n min={minCellSize}\n max={maxCellSize}\n value={config.cellHeight}\n onChange={(e) => handleChange('cellHeight', parseInt(e.target.value) || minCellSize)}\n disabled={disabled}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n </div>\n </div>\n\n {/* 统计信息 */}\n <div className=\"pt-3 border-t border-gray-200 dark:border-gray-700\">\n <div className=\"grid grid-cols-2 gap-4 text-sm text-gray-600 dark:text-gray-400\">\n <div className=\"flex justify-between\">\n <span>总单元格数:</span>\n <span className=\"font-medium text-gray-900 dark:text-gray-100\">\n {config.rows * config.columns}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span>总尺寸:</span>\n <span className=\"font-medium text-gray-900 dark:text-gray-100\">\n {config.cellWidth * config.columns} × {config.cellHeight * config.rows}\n </span>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default GridControls;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","/**\n * 图片网格裁剪器主组件\n * Image Grid Cropper Main Component\n */\n\n'use client';\n\nimport React, { useState, useEffect, useCallback, useRef } from 'react';\nimport { clsx } from 'clsx';\nimport {\n Download,\n Scissors,\n CheckCircle2,\n XCircle,\n Loader2,\n Image as ImageIcon,\n AlertCircle,\n Move,\n} from 'lucide-react';\n\nimport type {\n GridConfig,\n GridCell,\n ImageInfo,\n CropResult,\n ExportOptions,\n ImageGridCropperConfig,\n} from '../types';\nimport {\n loadImageFromFile,\n cropMultipleCells,\n constrainOffset,\n validateCropArea,\n} from '../utils/cropUtils';\nimport { downloadAsZip, formatFileSize, calculateTotalSize } from '../utils/downloadUtils';\nimport { GridControls } from './GridControls';\n\n// ============= 主组件属性 =============\n\nexport interface ImageGridCropperProps {\n /** 初始配置 */\n config?: ImageGridCropperConfig;\n /** 导出成功回调 */\n onExportSuccess?: (results: CropResult[]) => void;\n /** 导出失败回调 */\n onExportError?: (error: string) => void;\n /** 自定义样式类名 */\n className?: string;\n}\n\n// ============= 主组件 =============\n\nexport const ImageGridCropper: React.FC<ImageGridCropperProps> = ({\n config = {},\n onExportSuccess,\n onExportError,\n className = '',\n}) => {\n // ============= 配置 =============\n const {\n defaultRows = 3,\n defaultColumns = 3,\n defaultCellWidth = 256,\n defaultCellHeight = 256,\n maxRows = 20,\n maxColumns = 20,\n maxCellSize = 2000,\n minCellSize = 10,\n } = config;\n\n // ============= 状态管理 =============\n const [imageInfo, setImageInfo] = useState<ImageInfo | null>(null);\n const [gridConfig, setGridConfig] = useState<GridConfig>({\n rows: defaultRows,\n columns: defaultColumns,\n cellWidth: defaultCellWidth,\n cellHeight: defaultCellHeight,\n });\n const [gridCells, setGridCells] = useState<GridCell[]>([]);\n const [isProcessing, setIsProcessing] = useState(false);\n const [progress, setProgress] = useState({ current: 0, total: 0 });\n const [error, setError] = useState<string | null>(null);\n\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // ============= 生成网格单元格 =============\n const generateGridCells = useCallback(() => {\n const cells: GridCell[] = [];\n const { rows, columns, cellWidth, cellHeight } = gridConfig;\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < columns; col++) {\n const offsetX = col * cellWidth;\n const offsetY = row * cellHeight;\n\n cells.push({\n id: 'cell_' + (row) + '_' + (col),\n row,\n column: col,\n x: offsetX,\n y: offsetY,\n offsetX,\n offsetY,\n width: cellWidth,\n height: cellHeight,\n selected: true, // 默认全选\n });\n }\n }\n\n setGridCells(cells);\n }, [gridConfig]);\n\n // ============= 图片加载 =============\n const handleFileSelect = async (event: React.ChangeEvent<HTMLInputElement>) => {\n const file = event.target.files?.[0];\n if (!file) return;\n\n // 验证文件类型\n if (!file.type.startsWith('image/')) {\n setError('请选择图片文件');\n return;\n }\n\n try {\n setError(null);\n setIsProcessing(true);\n\n const info = await loadImageFromFile(file);\n setImageInfo(info);\n generateGridCells();\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : '图片加载失败';\n setError(errorMsg);\n onExportError?.(errorMsg);\n } finally {\n setIsProcessing(false);\n }\n\n // 清空input以允许重复选择同一文件\n event.target.value = '';\n };\n\n // ============= 绘制预览 =============\n const drawPreview = useCallback(() => {\n if (!imageInfo || !canvasRef.current) return;\n\n const canvas = canvasRef.current;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n // 设置canvas尺寸\n const maxWidth = 800;\n const maxHeight = 600;\n const scale = Math.min(\n maxWidth / imageInfo.width,\n maxHeight / imageInfo.height,\n 1\n );\n\n canvas.width = imageInfo.width * scale;\n canvas.height = imageInfo.height * scale;\n\n if (!imageInfo.image) return;\n\n // 绘制图片\n ctx.drawImage(imageInfo.image, 0, 0, canvas.width, canvas.height);\n\n // 绘制网格线\n ctx.strokeStyle = 'rgba(59, 130, 246, 0.6)'; // 蓝色\n ctx.lineWidth = 2;\n\n const { cellWidth, cellHeight } = gridConfig;\n\n gridCells.forEach((cell) => {\n const x = cell.offsetX * scale;\n const y = cell.offsetY * scale;\n const w = cellWidth * scale;\n const h = cellHeight * scale;\n\n // 绘制边框\n if (cell.selected) {\n ctx.strokeStyle = 'rgba(34, 197, 94, 0.8)'; // 绿色表示选中\n } else {\n ctx.strokeStyle = 'rgba(156, 163, 175, 0.5)'; // 灰色表示未选中\n }\n \n ctx.strokeRect(x, y, w, h);\n\n // 绘制单元格编号\n ctx.fillStyle = cell.selected ? 'rgba(34, 197, 94, 0.9)' : 'rgba(156, 163, 175, 0.7)';\n ctx.font = '12px sans-serif';\n ctx.fillText('R' + (cell.row) + 'C' + (cell.column), x + 5, y + 15);\n });\n }, [imageInfo, gridConfig, gridCells]);\n\n // ============= 单元格选择切换 =============\n const toggleCellSelection = (cellId: string) => {\n setGridCells((prev) =>\n prev.map((cell) =>\n cell.id === cellId ? { ...cell, selected: !cell.selected } : cell\n )\n );\n };\n\n // ============= 全选/取消全选 =============\n const toggleSelectAll = () => {\n const allSelected = gridCells.every((cell) => cell.selected);\n setGridCells((prev) =>\n prev.map((cell) => ({ ...cell, selected: !allSelected }))\n );\n };\n\n // ============= 调整单元格偏移 =============\n const adjustCellOffset = (cellId: string, deltaX: number, deltaY: number) => {\n if (!imageInfo) return;\n\n setGridCells((prev) =>\n prev.map((cell) => {\n if (cell.id !== cellId) return cell;\n\n const newOffsetX = cell.offsetX + deltaX;\n const newOffsetY = cell.offsetY + deltaY;\n\n const constrained = constrainOffset(\n imageInfo.width,\n imageInfo.height,\n newOffsetX,\n newOffsetY,\n gridConfig.cellWidth,\n gridConfig.cellHeight\n );\n\n return {\n ...cell,\n offsetX: constrained.offsetX,\n offsetY: constrained.offsetY,\n };\n })\n );\n };\n\n // ============= 导出裁剪图片 =============\n const handleExport = async (options: ExportOptions = {}) => {\n if (!imageInfo) {\n setError('请先上传图片');\n return;\n }\n\n const selectedCells = gridCells.filter((cell) => cell.selected);\n if (selectedCells.length === 0) {\n setError('请至少选择一个单元格');\n return;\n }\n\n try {\n setError(null);\n setIsProcessing(true);\n setProgress({ current: 0, total: selectedCells.length });\n\n const results = await cropMultipleCells(\n imageInfo,\n selectedCells,\n gridConfig.cellWidth,\n gridConfig.cellHeight,\n options.cropOptions,\n (current, total) => setProgress({ current, total })\n );\n\n if (results.length === 0) {\n throw new Error('没有成功裁剪的图片');\n }\n\n // 下载为ZIP\n const zipFilename = options.zipFilename || 'cropped_' + (Date.now()) + '.zip';\n await downloadAsZip(results, zipFilename);\n\n onExportSuccess?.(results);\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : '导出失败';\n setError(errorMsg);\n onExportError?.(errorMsg);\n } finally {\n setIsProcessing(false);\n setProgress({ current: 0, total: 0 });\n }\n };\n\n // ============= 重置配置 =============\n const handleReset = () => {\n setGridConfig({\n rows: defaultRows,\n columns: defaultColumns,\n cellWidth: defaultCellWidth,\n cellHeight: defaultCellHeight,\n });\n };\n\n // ============= 效果 =============\n useEffect(() => {\n if (imageInfo) {\n generateGridCells();\n }\n }, [imageInfo, generateGridCells]);\n\n useEffect(() => {\n drawPreview();\n }, [drawPreview]);\n\n // ============= 渲染 =============\n const selectedCount = gridCells.filter((cell) => cell.selected).length;\n\n return (\n <div className={clsx('w-full space-y-6', className)}>\n {/* 头部 */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Scissors className=\"w-7 h-7 text-blue-500\" />\n <div>\n <h2 className=\"text-2xl font-bold text-gray-800 dark:text-gray-200\">\n 网格式图片裁剪工具\n </h2>\n <p className=\"text-sm text-gray-600 dark:text-gray-400\">\n 上传图片,设置网格,裁剪并导出\n </p>\n </div>\n </div>\n </div>\n\n {/* 错误提示 */}\n {error && (\n <div className=\"flex items-center gap-2 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg\">\n <AlertCircle className=\"w-5 h-5 text-red-500\" />\n <p className=\"text-sm text-red-700 dark:text-red-400\">{error}</p>\n </div>\n )}\n\n {/* 上传区域 */}\n <div className=\"space-y-4\">\n <label className=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\n 上传图片\n </label>\n <div\n className=\"border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-8 text-center cursor-pointer hover:border-blue-400 dark:hover:border-blue-500 transition-colors\"\n onClick={() => fileInputRef.current?.click()}\n >\n <ImageIcon className=\"w-12 h-12 mx-auto mb-4 text-gray-400\" />\n <p className=\"text-gray-600 dark:text-gray-400 mb-2\">\n 点击选择图片或拖拽文件到这里\n </p>\n <p className=\"text-sm text-gray-500\">支持 PNG, JPG, WEBP 等格式</p>\n {imageInfo && imageInfo.file && (\n <p className=\"mt-4 text-sm text-green-600 dark:text-green-400\">\n ✓ 已上传: {imageInfo.file.name} ({imageInfo.width} × {imageInfo.height})\n </p>\n )}\n </div>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n className=\"hidden\"\n />\n </div>\n\n {/* 网格配置 */}\n {imageInfo && (\n <GridControls\n config={gridConfig}\n onChange={setGridConfig}\n disabled={isProcessing}\n maxRows={maxRows}\n maxColumns={maxColumns}\n maxCellSize={maxCellSize}\n minCellSize={minCellSize}\n onReset={handleReset}\n />\n )}\n\n {/* 预览区域 */}\n {imageInfo && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-lg font-semibold text-gray-800 dark:text-gray-200\">\n 预览与调整\n </h3>\n <button\n onClick={toggleSelectAll}\n className=\"px-4 py-2 text-sm text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded-md transition-colors\"\n >\n {gridCells.every((cell) => cell.selected) ? '取消全选' : '全选'}\n </button>\n </div>\n\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden bg-gray-50 dark:bg-gray-900 p-4\">\n <canvas\n ref={canvasRef}\n className=\"max-w-full mx-auto border border-gray-300 dark:border-gray-600\"\n />\n </div>\n\n {/* 单元格列表 */}\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n 单元格列表 ({selectedCount}/{gridCells.length} 已选中)\n </h4>\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 max-h-64 overflow-y-auto\">\n {gridCells.map((cell) => (\n <div\n key={cell.id}\n className={clsx('p-3 rounded border', cell.selected\n ? 'border-green-500 bg-green-50 dark:bg-green-900/20'\n : 'border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800', 'cursor-pointer transition-colors')}\n onClick={() => toggleCellSelection(cell.id)}\n >\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium text-gray-700 dark:text-gray-300\">\n R{cell.row} C{cell.column}\n </span>\n {cell.selected ? (\n <CheckCircle2 className=\"w-4 h-4 text-green-500\" />\n ) : (\n <XCircle className=\"w-4 h-4 text-gray-400\" />\n )}\n </div>\n <div className=\"text-xs text-gray-500 space-y-1\">\n <p>X: {cell.offsetX}px</p>\n <p>Y: {cell.offsetY}px</p>\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n )}\n\n {/* 导出按钮 */}\n {imageInfo && (\n <div className=\"flex items-center justify-between p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800\">\n <div className=\"text-sm text-gray-700 dark:text-gray-300\">\n <p className=\"font-medium\">准备导出 {selectedCount} 个裁剪图片</p>\n {isProcessing && (\n <p className=\"text-xs text-gray-600 dark:text-gray-400 mt-1\">\n 进度: {progress.current}/{progress.total}\n </p>\n )}\n </div>\n <button\n onClick={() => handleExport()}\n disabled={isProcessing || selectedCount === 0}\n className=\"flex items-center gap-2 px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isProcessing ? (\n <>\n <Loader2 className=\"w-5 h-5 animate-spin\" />\n 处理中...\n </>\n ) : (\n <>\n <Download className=\"w-5 h-5\" />\n 导出为 ZIP\n </>\n )}\n </button>\n </div>\n )}\n </div>\n );\n};\n\nexport default ImageGridCropper;\n\n\n\n\n\n\n"]}
@@ -1,5 +1,6 @@
1
1
  import '../chunk-BJTO5JO5.mjs';
2
2
  import React2, { useState, useRef, useCallback, useEffect } from 'react';
3
+ import { clsx } from 'clsx';
3
4
  import { Grid, RefreshCw, Maximize2, Scissors, AlertCircle, Image as Image$1, CheckCircle2, XCircle, Loader2, Download } from 'lucide-react';
4
5
  import JSZip from 'jszip';
5
6
 
@@ -76,7 +77,7 @@ async function cropGridCell(imageInfo, cell, cellWidth, cellHeight, options = {}
76
77
  );
77
78
  });
78
79
  const extension = format.split("/")[1] || "png";
79
- const filename = `${filenamePrefix}_r${cell.row}_c${cell.column}.${extension}`;
80
+ const filename = filenamePrefix + "_r" + cell.row + "_c" + cell.column + "." + extension;
80
81
  return {
81
82
  blob,
82
83
  dataUrl: canvas.toDataURL(format, quality),
@@ -100,7 +101,7 @@ async function cropMultipleCells(imageInfo, cells, cellWidth, cellHeight, option
100
101
  onProgress(i + 1, cells.length);
101
102
  }
102
103
  } catch (error) {
103
- console.error(`\u88C1\u526A\u5355\u5143\u683C (${cell.row}, ${cell.column}) \u5931\u8D25:`, error);
104
+ console.error("\u88C1\u526A\u5355\u5143\u683C (" + cell.row + ", " + cell.column + ") \u5931\u8D25:", error);
104
105
  }
105
106
  }
106
107
  return results;
@@ -144,7 +145,7 @@ async function downloadAsZip(results, zipFilename = "cropped_images.zip") {
144
145
  }
145
146
  const zip = new JSZip();
146
147
  results.forEach((result, idx) => {
147
- const filename = result.filename || `crop_${idx}.png`;
148
+ const filename = result.filename || "crop_" + idx + ".png";
148
149
  zip.file(filename, result.blob);
149
150
  });
150
151
  const zipBlob = await zip.generateAsync({
@@ -172,7 +173,7 @@ async function downloadMultipleFiles(results, delay = 100) {
172
173
  for (let i = 0; i < results.length; i++) {
173
174
  const result = results[i];
174
175
  if (!result) continue;
175
- const filename = result.filename || `crop_${i}.png`;
176
+ const filename = result.filename || "crop_" + i + ".png";
176
177
  downloadBlob(result.blob, filename);
177
178
  if (i < results.length - 1) {
178
179
  await new Promise((resolve) => setTimeout(resolve, delay));
@@ -187,7 +188,7 @@ function formatFileSize(bytes) {
187
188
  const k = 1024;
188
189
  const sizes = ["B", "KB", "MB", "GB"];
189
190
  const i = Math.floor(Math.log(bytes) / Math.log(k));
190
- return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
191
+ return (bytes / Math.pow(k, i)).toFixed(2) + " " + sizes[i];
191
192
  }
192
193
  var GridControls = ({
193
194
  config,
@@ -331,7 +332,7 @@ var ImageGridCropper = ({
331
332
  const offsetX = col * cellWidth;
332
333
  const offsetY = row * cellHeight;
333
334
  cells.push({
334
- id: `cell_${row}_${col}`,
335
+ id: "cell_" + row + "_" + col,
335
336
  row,
336
337
  column: col,
337
338
  x: offsetX,
@@ -401,7 +402,7 @@ var ImageGridCropper = ({
401
402
  ctx.strokeRect(x, y, w, h);
402
403
  ctx.fillStyle = cell.selected ? "rgba(34, 197, 94, 0.9)" : "rgba(156, 163, 175, 0.7)";
403
404
  ctx.font = "12px sans-serif";
404
- ctx.fillText(`R${cell.row}C${cell.column}`, x + 5, y + 15);
405
+ ctx.fillText("R" + cell.row + "C" + cell.column, x + 5, y + 15);
405
406
  });
406
407
  }, [imageInfo, gridConfig, gridCells]);
407
408
  const toggleCellSelection = (cellId) => {
@@ -442,7 +443,7 @@ var ImageGridCropper = ({
442
443
  if (results.length === 0) {
443
444
  throw new Error("\u6CA1\u6709\u6210\u529F\u88C1\u526A\u7684\u56FE\u7247");
444
445
  }
445
- const zipFilename = options.zipFilename || `cropped_${Date.now()}.zip`;
446
+ const zipFilename = options.zipFilename || "cropped_" + Date.now() + ".zip";
446
447
  await downloadAsZip(results, zipFilename);
447
448
  onExportSuccess?.(results);
448
449
  } catch (err) {
@@ -471,7 +472,7 @@ var ImageGridCropper = ({
471
472
  drawPreview();
472
473
  }, [drawPreview]);
473
474
  const selectedCount = gridCells.filter((cell) => cell.selected).length;
474
- return /* @__PURE__ */ React2.createElement("div", { className: `w-full space-y-6 ${className}` }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React2.createElement(Scissors, { className: "w-7 h-7 text-blue-500" }), /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("h2", { className: "text-2xl font-bold text-gray-800 dark:text-gray-200" }, "\u7F51\u683C\u5F0F\u56FE\u7247\u88C1\u526A\u5DE5\u5177"), /* @__PURE__ */ React2.createElement("p", { className: "text-sm text-gray-600 dark:text-gray-400" }, "\u4E0A\u4F20\u56FE\u7247\uFF0C\u8BBE\u7F6E\u7F51\u683C\uFF0C\u88C1\u526A\u5E76\u5BFC\u51FA")))), error && /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-2 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg" }, /* @__PURE__ */ React2.createElement(AlertCircle, { className: "w-5 h-5 text-red-500" }), /* @__PURE__ */ React2.createElement("p", { className: "text-sm text-red-700 dark:text-red-400" }, error)), /* @__PURE__ */ React2.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React2.createElement("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300" }, "\u4E0A\u4F20\u56FE\u7247"), /* @__PURE__ */ React2.createElement(
475
+ return /* @__PURE__ */ React2.createElement("div", { className: clsx("w-full space-y-6", className) }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React2.createElement(Scissors, { className: "w-7 h-7 text-blue-500" }), /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("h2", { className: "text-2xl font-bold text-gray-800 dark:text-gray-200" }, "\u7F51\u683C\u5F0F\u56FE\u7247\u88C1\u526A\u5DE5\u5177"), /* @__PURE__ */ React2.createElement("p", { className: "text-sm text-gray-600 dark:text-gray-400" }, "\u4E0A\u4F20\u56FE\u7247\uFF0C\u8BBE\u7F6E\u7F51\u683C\uFF0C\u88C1\u526A\u5E76\u5BFC\u51FA")))), error && /* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-2 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg" }, /* @__PURE__ */ React2.createElement(AlertCircle, { className: "w-5 h-5 text-red-500" }), /* @__PURE__ */ React2.createElement("p", { className: "text-sm text-red-700 dark:text-red-400" }, error)), /* @__PURE__ */ React2.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React2.createElement("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300" }, "\u4E0A\u4F20\u56FE\u7247"), /* @__PURE__ */ React2.createElement(
475
476
  "div",
476
477
  {
477
478
  className: "border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg p-8 text-center cursor-pointer hover:border-blue-400 dark:hover:border-blue-500 transition-colors",
@@ -519,7 +520,7 @@ var ImageGridCropper = ({
519
520
  "div",
520
521
  {
521
522
  key: cell.id,
522
- className: `p-3 rounded border ${cell.selected ? "border-green-500 bg-green-50 dark:bg-green-900/20" : "border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800"} cursor-pointer transition-colors`,
523
+ className: clsx("p-3 rounded border", cell.selected ? "border-green-500 bg-green-50 dark:bg-green-900/20" : "border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800", "cursor-pointer transition-colors"),
523
524
  onClick: () => toggleCellSelection(cell.id)
524
525
  },
525
526
  /* @__PURE__ */ React2.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React2.createElement("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300" }, "R", cell.row, " C", cell.column), cell.selected ? /* @__PURE__ */ React2.createElement(CheckCircle2, { className: "w-4 h-4 text-green-500" }) : /* @__PURE__ */ React2.createElement(XCircle, { className: "w-4 h-4 text-gray-400" })),