react-screenshots 0.0.17 → 0.2.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +97 -88
  2. package/electron/assets/index.6377aa3e.css +1 -0
  3. package/electron/assets/index.fbe41cdd.js +14 -0
  4. package/electron/assets/vendor.ea3156d9.js +209 -0
  5. package/electron/electron.html +15 -0
  6. package/lib/react-screenshots.cjs.js +14 -0
  7. package/lib/react-screenshots.es.js +3058 -0
  8. package/lib/style.css +1 -0
  9. package/lib/types/Screenshots/index.d.ts +13 -0
  10. package/lib/types/ScreenshotsBackground/getBoundsByPoints.d.ts +2 -0
  11. package/lib/types/ScreenshotsBackground/index.d.ts +3 -0
  12. package/lib/types/ScreenshotsButton/index.d.ts +11 -0
  13. package/lib/types/ScreenshotsCanvas/getBoundsByPoints.d.ts +2 -0
  14. package/lib/types/ScreenshotsCanvas/getPoints.d.ts +2 -0
  15. package/lib/types/ScreenshotsCanvas/index.d.ts +15 -0
  16. package/lib/types/ScreenshotsCanvas/isPointInDraw.d.ts +2 -0
  17. package/lib/types/ScreenshotsColor/index.d.ts +7 -0
  18. package/lib/types/ScreenshotsContext.d.ts +29 -0
  19. package/lib/types/ScreenshotsMagnifier/index.d.ts +7 -0
  20. package/lib/types/ScreenshotsOperations/index.d.ts +5 -0
  21. package/lib/types/ScreenshotsOption/index.d.ts +14 -0
  22. package/lib/types/ScreenshotsSize/index.d.ts +7 -0
  23. package/lib/types/ScreenshotsSizeColor/index.d.ts +9 -0
  24. package/lib/types/ScreenshotsTextarea/calculateNodeSize.d.ts +17 -0
  25. package/lib/types/ScreenshotsTextarea/index.d.ts +14 -0
  26. package/lib/types/dpr.d.ts +2 -0
  27. package/lib/types/exports.d.ts +3 -0
  28. package/lib/types/hooks/useBounds.d.ts +7 -0
  29. package/lib/types/hooks/useCall.d.ts +2 -0
  30. package/lib/types/hooks/useCanvasContextRef.d.ts +2 -0
  31. package/lib/types/hooks/useCanvasMousedown.d.ts +1 -0
  32. package/lib/types/hooks/useCanvasMousemove.d.ts +1 -0
  33. package/lib/types/hooks/useCanvasMouseup.d.ts +1 -0
  34. package/lib/types/hooks/useCursor.d.ts +6 -0
  35. package/lib/types/hooks/useDispatcher.d.ts +2 -0
  36. package/lib/types/hooks/useDrawSelect.d.ts +2 -0
  37. package/lib/types/hooks/useEmiter.d.ts +8 -0
  38. package/lib/types/hooks/useHistory.d.ts +16 -0
  39. package/lib/types/hooks/useLang.d.ts +2 -0
  40. package/lib/types/hooks/useOperation.d.ts +6 -0
  41. package/lib/types/hooks/useReset.d.ts +2 -0
  42. package/lib/types/hooks/useStore.d.ts +2 -0
  43. package/lib/types/index.d.ts +13 -0
  44. package/lib/types/operations/Arrow/draw.d.ts +11 -0
  45. package/lib/types/operations/Arrow/index.d.ts +22 -0
  46. package/lib/types/operations/Brush/draw.d.ts +3 -0
  47. package/lib/types/operations/Brush/index.d.ts +14 -0
  48. package/lib/types/operations/Cancel/index.d.ts +2 -0
  49. package/lib/types/operations/Ellipse/draw.d.ts +11 -0
  50. package/lib/types/operations/Ellipse/index.d.ts +28 -0
  51. package/lib/types/operations/Mosaic/index.d.ts +11 -0
  52. package/lib/types/operations/Ok/index.d.ts +2 -0
  53. package/lib/types/operations/Rectangle/draw.d.ts +11 -0
  54. package/lib/types/operations/Rectangle/index.d.ts +28 -0
  55. package/lib/types/operations/Redo/index.d.ts +2 -0
  56. package/lib/types/operations/Save/index.d.ts +2 -0
  57. package/lib/types/operations/Text/index.d.ts +22 -0
  58. package/lib/types/operations/Undo/index.d.ts +2 -0
  59. package/lib/types/operations/index.d.ts +3 -0
  60. package/lib/types/operations/utils.d.ts +4 -0
  61. package/lib/types/types.d.ts +39 -0
  62. package/lib/types/useGetLoadedImage.d.ts +1 -0
  63. package/lib/types/zh_CN.d.ts +16 -0
  64. package/package.json +40 -59
  65. package/dist/css/app.1c781f1bca03bf3517f6.css +0 -3
  66. package/dist/css/app.e66743f7e9bb7f4c3202.css +0 -3
  67. package/dist/index.html +0 -1
  68. package/dist/js/app.01b47f81a1286d89a7d9.js +0 -2
  69. package/dist/js/app.01b47f81a1286d89a7d9.js.LICENSE.txt +0 -32
  70. package/dist/js/app.047c8c22ccf49ba2b1d7.js +0 -2
  71. package/dist/js/app.047c8c22ccf49ba2b1d7.js.LICENSE.txt +0 -32
  72. package/dist/js/app.0910cea9128463e9f0d2.js +0 -2
  73. package/dist/js/app.0910cea9128463e9f0d2.js.LICENSE.txt +0 -32
  74. package/dist/js/app.1c0d0d80e583c32ef2db.js +0 -2
  75. package/dist/js/app.1c0d0d80e583c32ef2db.js.LICENSE.txt +0 -32
  76. package/dist/js/app.23a83e5bf2ca4a292ad6.js +0 -2
  77. package/dist/js/app.23a83e5bf2ca4a292ad6.js.LICENSE.txt +0 -32
  78. package/dist/js/app.267d13079b8af7e1dd76.js +0 -2
  79. package/dist/js/app.267d13079b8af7e1dd76.js.LICENSE.txt +0 -32
  80. package/dist/js/app.2735150c87ae453ee439.js +0 -2
  81. package/dist/js/app.2735150c87ae453ee439.js.LICENSE.txt +0 -32
  82. package/dist/js/app.2e6ada7ebe29d78de07b.js +0 -2
  83. package/dist/js/app.2e6ada7ebe29d78de07b.js.LICENSE.txt +0 -32
  84. package/dist/js/app.34635b43ca0307bf4615.js +0 -2
  85. package/dist/js/app.34635b43ca0307bf4615.js.LICENSE.txt +0 -32
  86. package/dist/js/app.3a5f376b2dae7284878b.js +0 -2
  87. package/dist/js/app.3a5f376b2dae7284878b.js.LICENSE.txt +0 -32
  88. package/dist/js/app.6856f1c4d4c6846705ff.js +0 -2
  89. package/dist/js/app.6856f1c4d4c6846705ff.js.LICENSE.txt +0 -32
  90. package/dist/js/app.758c8b2f2a8ccf6b1c3c.js +0 -2
  91. package/dist/js/app.758c8b2f2a8ccf6b1c3c.js.LICENSE.txt +0 -32
  92. package/dist/js/app.7cbd97e8ce1d08f1bd80.js +0 -2
  93. package/dist/js/app.7cbd97e8ce1d08f1bd80.js.LICENSE.txt +0 -32
  94. package/dist/js/app.7e24d295c7128703cf2b.js +0 -2
  95. package/dist/js/app.7e24d295c7128703cf2b.js.LICENSE.txt +0 -32
  96. package/dist/js/app.912ce3a16854e72bccb3.js +0 -2
  97. package/dist/js/app.912ce3a16854e72bccb3.js.LICENSE.txt +0 -32
  98. package/dist/js/app.9e2b61e62399f65fd600.js +0 -2
  99. package/dist/js/app.9e2b61e62399f65fd600.js.LICENSE.txt +0 -32
  100. package/dist/js/app.a2217b046f549c529f48.js +0 -2
  101. package/dist/js/app.a2217b046f549c529f48.js.LICENSE.txt +0 -32
  102. package/dist/js/app.a8d205b093abb2929de9.js +0 -2
  103. package/dist/js/app.a8d205b093abb2929de9.js.LICENSE.txt +0 -32
  104. package/dist/js/app.a9a7577692d56038a7dc.js +0 -2
  105. package/dist/js/app.a9a7577692d56038a7dc.js.LICENSE.txt +0 -32
  106. package/dist/js/app.aed9a05fb8f84df41483.js +0 -2
  107. package/dist/js/app.aed9a05fb8f84df41483.js.LICENSE.txt +0 -32
  108. package/dist/js/app.b7af6e629134f9201f64.js +0 -2
  109. package/dist/js/app.b7af6e629134f9201f64.js.LICENSE.txt +0 -32
  110. package/dist/js/app.c03bf2bbdb513f9c8452.js +0 -2
  111. package/dist/js/app.c03bf2bbdb513f9c8452.js.LICENSE.txt +0 -32
  112. package/dist/js/app.c37b7d9d42ab1e25882c.js +0 -2
  113. package/dist/js/app.c37b7d9d42ab1e25882c.js.LICENSE.txt +0 -32
  114. package/dist/js/app.ccfceab7eaf11230369d.js +0 -2
  115. package/dist/js/app.ccfceab7eaf11230369d.js.LICENSE.txt +0 -32
  116. package/dist/screenshots.css +0 -1
  117. package/dist/screenshots.js +0 -2
  118. package/dist/screenshots.js.LICENSE.txt +0 -23
@@ -0,0 +1,3058 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
32
+ var _a;
33
+ import React, { useContext, useState, useRef, useLayoutEffect, useEffect, useCallback, forwardRef, useImperativeHandle, cloneElement } from "react";
34
+ import { createPortal } from "react-dom";
35
+ const zhCN = {
36
+ magnifier_position_label: "\u5750\u6807",
37
+ operation_ok_title: "\u786E\u5B9A",
38
+ operation_cancel_title: "\u53D6\u6D88",
39
+ operation_save_title: "\u4FDD\u5B58",
40
+ operation_redo_title: "\u91CD\u505A",
41
+ operation_undo_title: "\u64A4\u9500",
42
+ operation_mosaic_title: "\u9A6C\u8D5B\u514B",
43
+ operation_text_title: "\u6587\u672C",
44
+ operation_brush_title: "\u753B\u7B14",
45
+ operation_arrow_title: "\u7BAD\u5934",
46
+ operation_ellipse_title: "\u692D\u5706",
47
+ operation_rectangle_title: "\u77E9\u5F62"
48
+ };
49
+ var ScreenshotsContext = React.createContext({
50
+ store: {
51
+ url: void 0,
52
+ image: null,
53
+ width: 0,
54
+ height: 0,
55
+ lang: zhCN,
56
+ emiterRef: { current: {} },
57
+ canvasContextRef: { current: null },
58
+ history: {
59
+ index: -1,
60
+ stack: []
61
+ },
62
+ bounds: null,
63
+ cursor: "move",
64
+ operation: void 0
65
+ },
66
+ dispatcher: {
67
+ call: void 0,
68
+ setHistory: void 0,
69
+ setBounds: void 0,
70
+ setCursor: void 0,
71
+ setOperation: void 0
72
+ }
73
+ });
74
+ function useStore() {
75
+ const { store } = useContext(ScreenshotsContext);
76
+ return store;
77
+ }
78
+ function useLang() {
79
+ const { lang } = useStore();
80
+ return lang;
81
+ }
82
+ var index$9 = "";
83
+ var _jsxFileName$l = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsMagnifier/index.tsx";
84
+ const magnifierWidth = 100;
85
+ const magnifierHeight = 80;
86
+ function ScreenshotsMagnifier({
87
+ x,
88
+ y
89
+ }) {
90
+ const {
91
+ width,
92
+ height,
93
+ image
94
+ } = useStore();
95
+ const lang = useLang();
96
+ const [position, setPosition] = useState(null);
97
+ const elRef = useRef(null);
98
+ const canvasRef = useRef(null);
99
+ const ctxRef = useRef(null);
100
+ const [rgb, setRgb] = useState("000000");
101
+ useLayoutEffect(() => {
102
+ if (!elRef.current) {
103
+ return;
104
+ }
105
+ const elRect = elRef.current.getBoundingClientRect();
106
+ let tx = x + 20;
107
+ let ty = y + 20;
108
+ if (tx + elRect.width > width) {
109
+ tx = x - elRect.width - 20;
110
+ }
111
+ if (ty + elRect.height > height) {
112
+ ty = y - elRect.height - 20;
113
+ }
114
+ if (tx < 0) {
115
+ tx = 0;
116
+ }
117
+ if (ty < 0) {
118
+ ty = 0;
119
+ }
120
+ setPosition({
121
+ x: tx,
122
+ y: ty
123
+ });
124
+ }, [width, height, x, y]);
125
+ useEffect(() => {
126
+ if (!image || !canvasRef.current) {
127
+ ctxRef.current = null;
128
+ return;
129
+ }
130
+ if (!ctxRef.current) {
131
+ ctxRef.current = canvasRef.current.getContext("2d");
132
+ }
133
+ if (!ctxRef.current) {
134
+ return;
135
+ }
136
+ const ctx = ctxRef.current;
137
+ ctx.clearRect(0, 0, magnifierWidth, magnifierHeight);
138
+ const rx = image.naturalWidth / width;
139
+ const ry = image.naturalHeight / height;
140
+ ctx.drawImage(image, x * rx - magnifierWidth / 2, y * ry - magnifierHeight / 2, magnifierWidth, magnifierHeight, 0, 0, magnifierWidth, magnifierHeight);
141
+ const {
142
+ data
143
+ } = ctx.getImageData(Math.floor(magnifierWidth / 2), Math.floor(magnifierHeight / 2), 1, 1);
144
+ const hex = Array.from(data.slice(0, 3)).map((val) => val >= 16 ? val.toString(16) : `0${val.toString(16)}`).join("").toUpperCase();
145
+ setRgb(hex);
146
+ }, [width, height, image, x, y]);
147
+ return /* @__PURE__ */ React.createElement("div", {
148
+ ref: elRef,
149
+ className: "screenshots-magnifier",
150
+ style: {
151
+ transform: `translate(${position == null ? void 0 : position.x}px, ${position == null ? void 0 : position.y}px)`
152
+ },
153
+ __self: this,
154
+ __source: {
155
+ fileName: _jsxFileName$l,
156
+ lineNumber: 89,
157
+ columnNumber: 5
158
+ }
159
+ }, /* @__PURE__ */ React.createElement("div", {
160
+ className: "screenshots-magnifier-body",
161
+ __self: this,
162
+ __source: {
163
+ fileName: _jsxFileName$l,
164
+ lineNumber: 96,
165
+ columnNumber: 7
166
+ }
167
+ }, /* @__PURE__ */ React.createElement("canvas", {
168
+ ref: canvasRef,
169
+ className: "screenshots-magnifier-body-canvas",
170
+ width: magnifierWidth,
171
+ height: magnifierHeight,
172
+ __self: this,
173
+ __source: {
174
+ fileName: _jsxFileName$l,
175
+ lineNumber: 97,
176
+ columnNumber: 9
177
+ }
178
+ })), /* @__PURE__ */ React.createElement("div", {
179
+ className: "screenshots-magnifier-footer",
180
+ __self: this,
181
+ __source: {
182
+ fileName: _jsxFileName$l,
183
+ lineNumber: 104,
184
+ columnNumber: 7
185
+ }
186
+ }, /* @__PURE__ */ React.createElement("div", {
187
+ className: "screenshots-magnifier-footer-item",
188
+ __self: this,
189
+ __source: {
190
+ fileName: _jsxFileName$l,
191
+ lineNumber: 105,
192
+ columnNumber: 9
193
+ }
194
+ }, lang.magnifier_position_label, ": (", x, ",", y, ")"), /* @__PURE__ */ React.createElement("div", {
195
+ className: "screenshots-magnifier-footer-item",
196
+ __self: this,
197
+ __source: {
198
+ fileName: _jsxFileName$l,
199
+ lineNumber: 108,
200
+ columnNumber: 9
201
+ }
202
+ }, "RGB: #", rgb)));
203
+ }
204
+ var index$8 = "";
205
+ function getBoundsByPoints$2({ x: x1, y: y1 }, { x: x2, y: y2 }, width, height) {
206
+ if (x1 > x2) {
207
+ [x1, x2] = [x2, x1];
208
+ }
209
+ if (y1 > y2) {
210
+ [y1, y2] = [y2, y1];
211
+ }
212
+ if (x1 < 0) {
213
+ x1 = 0;
214
+ }
215
+ if (x2 > width) {
216
+ x2 = width;
217
+ }
218
+ if (y1 < 0) {
219
+ y1 = 0;
220
+ }
221
+ if (y2 > height) {
222
+ y2 = height;
223
+ }
224
+ return {
225
+ x: x1,
226
+ y: y1,
227
+ width: x2 - x1,
228
+ height: y2 - y1
229
+ };
230
+ }
231
+ function useDispatcher() {
232
+ const { dispatcher } = useContext(ScreenshotsContext);
233
+ return dispatcher;
234
+ }
235
+ function useBounds() {
236
+ const { bounds } = useStore();
237
+ const { setBounds } = useDispatcher();
238
+ const set = useCallback((bounds2) => {
239
+ setBounds == null ? void 0 : setBounds(bounds2);
240
+ }, [setBounds]);
241
+ const reset = useCallback(() => {
242
+ setBounds == null ? void 0 : setBounds(null);
243
+ }, [setBounds]);
244
+ return [
245
+ bounds,
246
+ {
247
+ set,
248
+ reset
249
+ }
250
+ ];
251
+ }
252
+ var _jsxFileName$k = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsBackground/index.tsx";
253
+ function ScreenshotsBackground() {
254
+ const {
255
+ url,
256
+ width,
257
+ height
258
+ } = useStore();
259
+ const [bounds, boundsDispatcher] = useBounds();
260
+ const elRef = useRef(null);
261
+ const pointRef = useRef(null);
262
+ const [position, setPosition] = useState(null);
263
+ const updateBounds = useCallback((p1, p2) => {
264
+ if (!elRef.current) {
265
+ return;
266
+ }
267
+ const {
268
+ x,
269
+ y
270
+ } = elRef.current.getBoundingClientRect();
271
+ boundsDispatcher.set(getBoundsByPoints$2({
272
+ x: p1.x - x,
273
+ y: p1.y - y
274
+ }, {
275
+ x: p2.x - x,
276
+ y: p2.y - y
277
+ }, width, height));
278
+ }, [width, height, boundsDispatcher]);
279
+ const onMouseDown = useCallback((e) => {
280
+ if (pointRef.current || bounds || e.button !== 0) {
281
+ return;
282
+ }
283
+ pointRef.current = {
284
+ x: e.clientX,
285
+ y: e.clientY
286
+ };
287
+ }, [bounds]);
288
+ useEffect(() => {
289
+ const onMouseMove = (e) => {
290
+ if (elRef.current) {
291
+ const rect = elRef.current.getBoundingClientRect();
292
+ if (e.clientX < rect.left || e.clientY < rect.top || e.clientX > rect.right || e.clientY > rect.bottom) {
293
+ setPosition(null);
294
+ } else {
295
+ setPosition({
296
+ x: e.clientX - rect.x,
297
+ y: e.clientY - rect.y
298
+ });
299
+ }
300
+ }
301
+ if (!pointRef.current) {
302
+ return;
303
+ }
304
+ updateBounds(pointRef.current, {
305
+ x: e.clientX,
306
+ y: e.clientY
307
+ });
308
+ };
309
+ const onMouseUp = (e) => {
310
+ if (!pointRef.current) {
311
+ return;
312
+ }
313
+ updateBounds(pointRef.current, {
314
+ x: e.clientX,
315
+ y: e.clientY
316
+ });
317
+ pointRef.current = null;
318
+ };
319
+ window.addEventListener("mousemove", onMouseMove);
320
+ window.addEventListener("mouseup", onMouseUp);
321
+ return () => {
322
+ window.removeEventListener("mousemove", onMouseMove);
323
+ window.removeEventListener("mouseup", onMouseUp);
324
+ };
325
+ }, [updateBounds]);
326
+ if (!url) {
327
+ return null;
328
+ }
329
+ return /* @__PURE__ */ React.createElement("div", {
330
+ ref: elRef,
331
+ className: "screenshots-background",
332
+ style: {
333
+ backgroundImage: `url("${url}")`
334
+ },
335
+ onMouseDown,
336
+ __self: this,
337
+ __source: {
338
+ fileName: _jsxFileName$k,
339
+ lineNumber: 104,
340
+ columnNumber: 5
341
+ }
342
+ }, /* @__PURE__ */ React.createElement("div", {
343
+ className: "screenshots-background-mask",
344
+ __self: this,
345
+ __source: {
346
+ fileName: _jsxFileName$k,
347
+ lineNumber: 112,
348
+ columnNumber: 7
349
+ }
350
+ }), position && !bounds && /* @__PURE__ */ React.createElement(ScreenshotsMagnifier, {
351
+ x: position == null ? void 0 : position.x,
352
+ y: position == null ? void 0 : position.y,
353
+ __self: this,
354
+ __source: {
355
+ fileName: _jsxFileName$k,
356
+ lineNumber: 113,
357
+ columnNumber: 31
358
+ }
359
+ }));
360
+ }
361
+ const dpr = (_a = window.devicePixelRatio) != null ? _a : 2;
362
+ var dpr$1 = dpr < 2 ? 2 : dpr;
363
+ function getBoundsByPoints$1(e, resizeOrMove, point, bounds) {
364
+ const x = e.clientX - point.x;
365
+ const y = e.clientY - point.y;
366
+ let x1 = bounds.x;
367
+ let y1 = bounds.y;
368
+ let x2 = bounds.x + bounds.width;
369
+ let y2 = bounds.y + bounds.height;
370
+ switch (resizeOrMove) {
371
+ case "top":
372
+ y1 += y;
373
+ break;
374
+ case "top-right":
375
+ x2 += x;
376
+ y1 += y;
377
+ break;
378
+ case "right":
379
+ x2 += x;
380
+ break;
381
+ case "right-bottom":
382
+ x2 += x;
383
+ y2 += y;
384
+ break;
385
+ case "bottom":
386
+ y2 += y;
387
+ break;
388
+ case "bottom-left":
389
+ x1 += x;
390
+ y2 += y;
391
+ break;
392
+ case "left":
393
+ x1 += x;
394
+ break;
395
+ case "left-top":
396
+ x1 += x;
397
+ y1 += y;
398
+ break;
399
+ case "move":
400
+ x1 += x;
401
+ y1 += y;
402
+ x2 += x;
403
+ y2 += y;
404
+ break;
405
+ }
406
+ return [
407
+ {
408
+ x: x1,
409
+ y: y1
410
+ },
411
+ {
412
+ x: x2,
413
+ y: y2
414
+ }
415
+ ];
416
+ }
417
+ function getBoundsByPoints({ x: x1, y: y1 }, { x: x2, y: y2 }, bounds, width, height, resizeOrMove) {
418
+ if (x1 > x2) {
419
+ [x1, x2] = [x2, x1];
420
+ }
421
+ if (y1 > y2) {
422
+ [y1, y2] = [y2, y1];
423
+ }
424
+ if (x1 < 0) {
425
+ x1 = 0;
426
+ if (resizeOrMove === "move") {
427
+ x2 = bounds.width;
428
+ }
429
+ }
430
+ if (x2 > width) {
431
+ x2 = width;
432
+ if (resizeOrMove === "move") {
433
+ x1 = x2 - bounds.width;
434
+ }
435
+ }
436
+ if (y1 < 0) {
437
+ y1 = 0;
438
+ if (resizeOrMove === "move") {
439
+ y2 = bounds.height;
440
+ }
441
+ }
442
+ if (y2 > height) {
443
+ y2 = height;
444
+ if (resizeOrMove === "move") {
445
+ y1 = y2 - bounds.height;
446
+ }
447
+ }
448
+ return {
449
+ x: x1,
450
+ y: y1,
451
+ width: Math.max(x2 - x1, 1),
452
+ height: Math.max(y2 - y1, 1)
453
+ };
454
+ }
455
+ var HistoryItemType;
456
+ (function(HistoryItemType2) {
457
+ HistoryItemType2[HistoryItemType2["Edit"] = 0] = "Edit";
458
+ HistoryItemType2[HistoryItemType2["Source"] = 1] = "Source";
459
+ })(HistoryItemType || (HistoryItemType = {}));
460
+ function useEmiter() {
461
+ const { emiterRef } = useStore();
462
+ const on = useCallback((event, listener) => {
463
+ const emiter = emiterRef.current;
464
+ if (Array.isArray(emiter[event])) {
465
+ emiter[event].push(listener);
466
+ } else {
467
+ emiter[event] = [listener];
468
+ }
469
+ }, [emiterRef]);
470
+ const off = useCallback((event, listener) => {
471
+ const emiter = emiterRef.current;
472
+ if (Array.isArray(emiter[event])) {
473
+ const index2 = emiter[event].findIndex((item) => item === listener);
474
+ if (index2 !== -1) {
475
+ emiter[event].splice(index2, 1);
476
+ }
477
+ }
478
+ }, [emiterRef]);
479
+ const emit = useCallback((event, ...args) => {
480
+ const emiter = emiterRef.current;
481
+ if (Array.isArray(emiter[event])) {
482
+ emiter[event].forEach((listener) => listener(...args));
483
+ }
484
+ }, [emiterRef]);
485
+ const reset = useCallback(() => {
486
+ emiterRef.current = {};
487
+ }, [emiterRef]);
488
+ return {
489
+ on,
490
+ off,
491
+ emit,
492
+ reset
493
+ };
494
+ }
495
+ function useHistory() {
496
+ const { history } = useStore();
497
+ const { setHistory } = useDispatcher();
498
+ const push = useCallback((action) => {
499
+ const { index: index2, stack } = history;
500
+ stack.forEach((item) => {
501
+ if (item.type === HistoryItemType.Source) {
502
+ item.isSelected = false;
503
+ }
504
+ });
505
+ if (action.type === HistoryItemType.Source) {
506
+ action.isSelected = true;
507
+ } else if (action.type === HistoryItemType.Edit) {
508
+ action.source.isSelected = true;
509
+ }
510
+ stack.splice(index2 + 1);
511
+ stack.push(action);
512
+ setHistory == null ? void 0 : setHistory({
513
+ index: stack.length - 1,
514
+ stack
515
+ });
516
+ }, [history, setHistory]);
517
+ const pop = useCallback(() => {
518
+ const { stack } = history;
519
+ stack.pop();
520
+ setHistory == null ? void 0 : setHistory({
521
+ index: stack.length - 1,
522
+ stack
523
+ });
524
+ }, [history, setHistory]);
525
+ const undo = useCallback(() => {
526
+ const { index: index2, stack } = history;
527
+ const item = stack[index2];
528
+ if (item) {
529
+ if (item.type === HistoryItemType.Source) {
530
+ item.isSelected = false;
531
+ } else if (item.type === HistoryItemType.Edit) {
532
+ item.source.editHistory.pop();
533
+ }
534
+ }
535
+ setHistory == null ? void 0 : setHistory({
536
+ index: index2 <= 0 ? -1 : index2 - 1,
537
+ stack
538
+ });
539
+ }, [history, setHistory]);
540
+ const redo = useCallback(() => {
541
+ const { index: index2, stack } = history;
542
+ const item = stack[index2 + 1];
543
+ if (item) {
544
+ if (item.type === HistoryItemType.Source) {
545
+ item.isSelected = false;
546
+ } else if (item.type === HistoryItemType.Edit) {
547
+ item.source.editHistory.push(item);
548
+ }
549
+ }
550
+ setHistory == null ? void 0 : setHistory({
551
+ index: index2 >= stack.length - 1 ? stack.length - 1 : index2 + 1,
552
+ stack
553
+ });
554
+ }, [history, setHistory]);
555
+ const set = useCallback((history2) => {
556
+ setHistory == null ? void 0 : setHistory(__spreadValues({}, history2));
557
+ }, [setHistory]);
558
+ const select = useCallback((action) => {
559
+ history.stack.forEach((item) => {
560
+ if (item.type === HistoryItemType.Source) {
561
+ if (item === action) {
562
+ item.isSelected = true;
563
+ } else {
564
+ item.isSelected = false;
565
+ }
566
+ }
567
+ });
568
+ setHistory == null ? void 0 : setHistory(__spreadValues({}, history));
569
+ }, [history, setHistory]);
570
+ const clearSelect = useCallback(() => {
571
+ history.stack.forEach((item) => {
572
+ if (item.type === HistoryItemType.Source) {
573
+ item.isSelected = false;
574
+ }
575
+ });
576
+ setHistory == null ? void 0 : setHistory(__spreadValues({}, history));
577
+ }, [history, setHistory]);
578
+ const reset = useCallback(() => {
579
+ setHistory == null ? void 0 : setHistory({
580
+ index: -1,
581
+ stack: []
582
+ });
583
+ }, [setHistory]);
584
+ return [
585
+ {
586
+ index: history.index,
587
+ stack: history.stack,
588
+ top: history.stack.slice(history.index, history.index + 1)[0]
589
+ },
590
+ {
591
+ push,
592
+ pop,
593
+ undo,
594
+ redo,
595
+ set,
596
+ select,
597
+ clearSelect,
598
+ reset
599
+ }
600
+ ];
601
+ }
602
+ function useCursor() {
603
+ const { cursor } = useStore();
604
+ const { setCursor } = useDispatcher();
605
+ const set = useCallback((cursor2) => {
606
+ setCursor == null ? void 0 : setCursor(cursor2);
607
+ }, [setCursor]);
608
+ const reset = useCallback(() => {
609
+ setCursor == null ? void 0 : setCursor("move");
610
+ }, [setCursor]);
611
+ return [
612
+ cursor,
613
+ {
614
+ set,
615
+ reset
616
+ }
617
+ ];
618
+ }
619
+ function useOperation() {
620
+ const { operation } = useStore();
621
+ const { setOperation } = useDispatcher();
622
+ const set = useCallback((operation2) => {
623
+ setOperation == null ? void 0 : setOperation(operation2);
624
+ }, [setOperation]);
625
+ const reset = useCallback(() => {
626
+ setOperation == null ? void 0 : setOperation(void 0);
627
+ }, [setOperation]);
628
+ return [
629
+ operation,
630
+ {
631
+ set,
632
+ reset
633
+ }
634
+ ];
635
+ }
636
+ var index$7 = "";
637
+ function isPointInDraw(bounds, canvas, history, e) {
638
+ if (!canvas) {
639
+ return false;
640
+ }
641
+ const $canvas = document.createElement("canvas");
642
+ $canvas.width = bounds.width;
643
+ $canvas.height = bounds.height;
644
+ const ctx = $canvas.getContext("2d");
645
+ if (!ctx) {
646
+ return false;
647
+ }
648
+ const { left, top } = canvas.getBoundingClientRect();
649
+ const x = e.clientX - left;
650
+ const y = e.clientY - top;
651
+ const stack = [...history.stack.slice(0, history.index + 1)];
652
+ return stack.reverse().find((item) => {
653
+ var _a2;
654
+ if (item.type !== HistoryItemType.Source) {
655
+ return false;
656
+ }
657
+ ctx.clearRect(0, 0, bounds.width, bounds.height);
658
+ return (_a2 = item.isHit) == null ? void 0 : _a2.call(item, ctx, item, { x, y });
659
+ });
660
+ }
661
+ var _jsxFileName$j = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsCanvas/index.tsx";
662
+ const borders = ["top", "right", "bottom", "left"];
663
+ var ResizePoints;
664
+ (function(ResizePoints2) {
665
+ ResizePoints2["ResizeTop"] = "top";
666
+ ResizePoints2["ResizetopRight"] = "top-right";
667
+ ResizePoints2["ResizeRight"] = "right";
668
+ ResizePoints2["ResizeRightBottom"] = "right-bottom";
669
+ ResizePoints2["ResizeBottom"] = "bottom";
670
+ ResizePoints2["ResizeBottomLeft"] = "bottom-left";
671
+ ResizePoints2["ResizeLeft"] = "left";
672
+ ResizePoints2["ResizeLeftTop"] = "left-top";
673
+ ResizePoints2["Move"] = "move";
674
+ })(ResizePoints || (ResizePoints = {}));
675
+ const resizePoints = [ResizePoints.ResizeTop, ResizePoints.ResizetopRight, ResizePoints.ResizeRight, ResizePoints.ResizeRightBottom, ResizePoints.ResizeBottom, ResizePoints.ResizeBottomLeft, ResizePoints.ResizeLeft, ResizePoints.ResizeLeftTop];
676
+ var ScreenshotsCanvas = forwardRef(function ScreenshotsCanvas2(props, ref) {
677
+ const {
678
+ image,
679
+ width,
680
+ height
681
+ } = useStore();
682
+ const emiter = useEmiter();
683
+ const [history] = useHistory();
684
+ const [cursor] = useCursor();
685
+ const [bounds, boundsDispatcher] = useBounds();
686
+ const [operation] = useOperation();
687
+ const resizeOrMoveRef = useRef();
688
+ const pointRef = useRef(null);
689
+ const boundsRef = useRef(null);
690
+ const canvasRef = useRef(null);
691
+ const ctxRef = useRef(null);
692
+ const draw2 = useCallback(() => {
693
+ if (!image || !bounds || !ctxRef.current) {
694
+ return;
695
+ }
696
+ const rx = image.naturalWidth / width;
697
+ const ry = image.naturalHeight / height;
698
+ const ctx = ctxRef.current;
699
+ ctx.imageSmoothingEnabled = true;
700
+ ctx.imageSmoothingQuality = "high";
701
+ ctx.setTransform(dpr$1, 0, 0, dpr$1, 0, 0);
702
+ ctx.clearRect(0, 0, bounds.width, bounds.height);
703
+ ctx.drawImage(image, bounds.x * rx, bounds.y * ry, bounds.width * rx, bounds.height * ry, 0, 0, bounds.width, bounds.height);
704
+ history.stack.slice(0, history.index + 1).forEach((item) => {
705
+ if (item.type === HistoryItemType.Source) {
706
+ item.draw(ctx, item);
707
+ }
708
+ });
709
+ }, [image, width, height, bounds, ctxRef, history]);
710
+ const onMouseDown = useCallback((e, resizeOrMove) => {
711
+ if (e.button !== 0 || !bounds) {
712
+ return;
713
+ }
714
+ if (!operation) {
715
+ resizeOrMoveRef.current = resizeOrMove;
716
+ pointRef.current = {
717
+ x: e.clientX,
718
+ y: e.clientY
719
+ };
720
+ boundsRef.current = {
721
+ x: bounds.x,
722
+ y: bounds.y,
723
+ width: bounds.width,
724
+ height: bounds.height
725
+ };
726
+ } else {
727
+ const draw22 = isPointInDraw(bounds, canvasRef.current, history, e.nativeEvent);
728
+ if (draw22) {
729
+ emiter.emit("drawselect", draw22, e.nativeEvent);
730
+ } else {
731
+ emiter.emit("mousedown", e.nativeEvent);
732
+ }
733
+ }
734
+ }, [bounds, operation, emiter, history]);
735
+ const updateBounds = useCallback((e) => {
736
+ if (!resizeOrMoveRef.current || !pointRef.current || !boundsRef.current || !bounds) {
737
+ return;
738
+ }
739
+ const points = getBoundsByPoints$1(e, resizeOrMoveRef.current, pointRef.current, boundsRef.current);
740
+ boundsDispatcher.set(getBoundsByPoints(points[0], points[1], bounds, width, height, resizeOrMoveRef.current));
741
+ }, [width, height, bounds, boundsDispatcher]);
742
+ useLayoutEffect(() => {
743
+ if (!image || !bounds || !canvasRef.current) {
744
+ ctxRef.current = null;
745
+ return;
746
+ }
747
+ if (!ctxRef.current) {
748
+ ctxRef.current = canvasRef.current.getContext("2d");
749
+ }
750
+ draw2();
751
+ }, [image, bounds, draw2]);
752
+ useEffect(() => {
753
+ const onMouseMove = (e) => {
754
+ if (!operation) {
755
+ if (!resizeOrMoveRef.current || !pointRef.current || !boundsRef.current) {
756
+ return;
757
+ }
758
+ updateBounds(e);
759
+ } else {
760
+ emiter.emit("mousemove", e);
761
+ }
762
+ };
763
+ const onMouseUp = (e) => {
764
+ if (!operation) {
765
+ if (!resizeOrMoveRef.current || !pointRef.current || !boundsRef.current) {
766
+ return;
767
+ }
768
+ updateBounds(e);
769
+ resizeOrMoveRef.current = void 0;
770
+ pointRef.current = null;
771
+ boundsRef.current = null;
772
+ } else {
773
+ emiter.emit("mouseup", e);
774
+ }
775
+ };
776
+ window.addEventListener("mousemove", onMouseMove);
777
+ window.addEventListener("mouseup", onMouseUp);
778
+ return () => {
779
+ window.removeEventListener("mousemove", onMouseMove);
780
+ window.removeEventListener("mouseup", onMouseUp);
781
+ };
782
+ }, [updateBounds, operation, emiter]);
783
+ useImperativeHandle(ref, () => ctxRef.current);
784
+ if (!bounds) {
785
+ return null;
786
+ }
787
+ return /* @__PURE__ */ React.createElement("div", {
788
+ className: "screenshots-canvas",
789
+ style: {
790
+ left: bounds.x,
791
+ top: bounds.y,
792
+ width: bounds.width,
793
+ height: bounds.height
794
+ },
795
+ __self: this,
796
+ __source: {
797
+ fileName: _jsxFileName$j,
798
+ lineNumber: 190,
799
+ columnNumber: 5
800
+ }
801
+ }, /* @__PURE__ */ React.createElement("canvas", {
802
+ ref: canvasRef,
803
+ width: bounds.width * dpr$1,
804
+ height: bounds.height * dpr$1,
805
+ style: {
806
+ width: bounds.width,
807
+ height: bounds.height
808
+ },
809
+ __self: this,
810
+ __source: {
811
+ fileName: _jsxFileName$j,
812
+ lineNumber: 199,
813
+ columnNumber: 7
814
+ }
815
+ }), /* @__PURE__ */ React.createElement("div", {
816
+ className: "screenshots-canvas-body",
817
+ style: {
818
+ cursor
819
+ },
820
+ onMouseDown: (e) => onMouseDown(e, "move"),
821
+ __self: this,
822
+ __source: {
823
+ fileName: _jsxFileName$j,
824
+ lineNumber: 208,
825
+ columnNumber: 7
826
+ }
827
+ }), borders.map((border) => {
828
+ return /* @__PURE__ */ React.createElement("div", {
829
+ key: border,
830
+ className: `screenshots-canvas-border-${border}`,
831
+ __self: this,
832
+ __source: {
833
+ fileName: _jsxFileName$j,
834
+ lineNumber: 216,
835
+ columnNumber: 16
836
+ }
837
+ });
838
+ }), resizePoints.map((resizePoint) => {
839
+ return /* @__PURE__ */ React.createElement("div", {
840
+ key: resizePoint,
841
+ className: `screenshots-canvas-point-${resizePoint}`,
842
+ onMouseDown: (e) => onMouseDown(e, resizePoint),
843
+ __self: this,
844
+ __source: {
845
+ fileName: _jsxFileName$j,
846
+ lineNumber: 220,
847
+ columnNumber: 11
848
+ }
849
+ });
850
+ }));
851
+ });
852
+ function useCall() {
853
+ const dispatcher = useDispatcher();
854
+ const call = useCallback((funcName, ...args) => {
855
+ var _a2;
856
+ (_a2 = dispatcher.call) == null ? void 0 : _a2.call(dispatcher, funcName, ...args);
857
+ }, [dispatcher]);
858
+ return call;
859
+ }
860
+ function useCanvasContextRef() {
861
+ const { canvasContextRef } = useStore();
862
+ return canvasContextRef;
863
+ }
864
+ function useReset() {
865
+ const emiter = useEmiter();
866
+ const [, boundsDispatcher] = useBounds();
867
+ const [, cursorDispatcher] = useCursor();
868
+ const [, historyDispatcher] = useHistory();
869
+ const [, operatioDispatcher] = useOperation();
870
+ const reset = useCallback(() => {
871
+ emiter.reset();
872
+ historyDispatcher.reset();
873
+ boundsDispatcher.reset();
874
+ cursorDispatcher.reset();
875
+ operatioDispatcher.reset();
876
+ }, [emiter, historyDispatcher, boundsDispatcher, cursorDispatcher, operatioDispatcher]);
877
+ return reset;
878
+ }
879
+ var index$6 = "";
880
+ var _jsxFileName$i = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsOption/index.tsx";
881
+ var Placement;
882
+ (function(Placement2) {
883
+ Placement2["Bottom"] = "bottom";
884
+ Placement2["Top"] = "top";
885
+ })(Placement || (Placement = {}));
886
+ function ScreenshotsOption({
887
+ open,
888
+ content,
889
+ children
890
+ }) {
891
+ const childrenRef = useRef(null);
892
+ const popoverRef = useRef(null);
893
+ const contentRef = useRef(null);
894
+ const operationsRect = useContext(ScreenshotsOperationsCtx);
895
+ const [placement, setPlacement] = useState(Placement.Bottom);
896
+ const [position, setPosition] = useState(null);
897
+ const [offsetX, setOffsetX] = useState(0);
898
+ const getPopoverEl = () => {
899
+ if (!popoverRef.current) {
900
+ popoverRef.current = document.createElement("div");
901
+ }
902
+ return popoverRef.current;
903
+ };
904
+ useEffect(() => {
905
+ const $el = getPopoverEl();
906
+ if (open) {
907
+ document.body.appendChild($el);
908
+ }
909
+ return () => {
910
+ $el.remove();
911
+ };
912
+ }, [open]);
913
+ useEffect(() => {
914
+ if (!open || !operationsRect || !childrenRef.current || !contentRef.current) {
915
+ return;
916
+ }
917
+ const childrenRect = childrenRef.current.getBoundingClientRect();
918
+ const contentRect = contentRef.current.getBoundingClientRect();
919
+ let currentPlacement = placement;
920
+ let x = childrenRect.left + childrenRect.width / 2;
921
+ let y = childrenRect.top + childrenRect.height;
922
+ let currentOffsetX = offsetX;
923
+ if (x + contentRect.width / 2 > operationsRect.x + operationsRect.width) {
924
+ const ox = x;
925
+ x = operationsRect.x + operationsRect.width - contentRect.width / 2;
926
+ currentOffsetX = ox - x;
927
+ }
928
+ if (x < operationsRect.x + contentRect.width / 2) {
929
+ const ox = x;
930
+ x = operationsRect.x + contentRect.width / 2;
931
+ currentOffsetX = ox - x;
932
+ }
933
+ if (y > window.innerHeight - contentRect.height) {
934
+ if (currentPlacement === Placement.Bottom) {
935
+ currentPlacement = Placement.Top;
936
+ }
937
+ y = childrenRect.top - contentRect.height;
938
+ }
939
+ if (y < 0) {
940
+ if (currentPlacement === Placement.Top) {
941
+ currentPlacement = Placement.Bottom;
942
+ }
943
+ y = childrenRect.top + childrenRect.height;
944
+ }
945
+ if (currentPlacement !== placement) {
946
+ setPlacement(currentPlacement);
947
+ }
948
+ if ((position == null ? void 0 : position.x) !== x || position.y !== y) {
949
+ setPosition({
950
+ x,
951
+ y
952
+ });
953
+ }
954
+ if (currentOffsetX !== offsetX) {
955
+ setOffsetX(currentOffsetX);
956
+ }
957
+ });
958
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, cloneElement(children, {
959
+ ref: childrenRef
960
+ }), open && content && createPortal(/* @__PURE__ */ React.createElement("div", {
961
+ ref: contentRef,
962
+ className: "screenshots-option",
963
+ style: {
964
+ visibility: position ? "visible" : "hidden",
965
+ left: position == null ? void 0 : position.x,
966
+ top: position == null ? void 0 : position.y
967
+ },
968
+ "data-placement": placement,
969
+ __self: this,
970
+ __source: {
971
+ fileName: _jsxFileName$i,
972
+ lineNumber: 111,
973
+ columnNumber: 11
974
+ }
975
+ }, /* @__PURE__ */ React.createElement("div", {
976
+ className: "screenshots-option-container",
977
+ __self: this,
978
+ __source: {
979
+ fileName: _jsxFileName$i,
980
+ lineNumber: 121,
981
+ columnNumber: 13
982
+ }
983
+ }, content), /* @__PURE__ */ React.createElement("div", {
984
+ className: "screenshots-option-arrow",
985
+ style: {
986
+ marginLeft: offsetX
987
+ },
988
+ __self: this,
989
+ __source: {
990
+ fileName: _jsxFileName$i,
991
+ lineNumber: 122,
992
+ columnNumber: 13
993
+ }
994
+ })), getPopoverEl()));
995
+ }
996
+ var index$5 = "";
997
+ var _jsxFileName$h = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsButton/index.tsx";
998
+ function ScreenshotsButton({
999
+ title,
1000
+ icon,
1001
+ checked,
1002
+ disabled,
1003
+ option,
1004
+ onClick
1005
+ }) {
1006
+ const classNames = ["screenshots-button"];
1007
+ const onButtonClick = useCallback((e) => {
1008
+ if (disabled || !onClick) {
1009
+ return;
1010
+ }
1011
+ onClick(e);
1012
+ }, [disabled, onClick]);
1013
+ if (checked) {
1014
+ classNames.push("screenshots-button-checked");
1015
+ }
1016
+ if (disabled) {
1017
+ classNames.push("screenshots-button-disabled");
1018
+ }
1019
+ return /* @__PURE__ */ React.createElement(ScreenshotsOption, {
1020
+ open: checked,
1021
+ content: option,
1022
+ __self: this,
1023
+ __source: {
1024
+ fileName: _jsxFileName$h,
1025
+ lineNumber: 42,
1026
+ columnNumber: 5
1027
+ }
1028
+ }, /* @__PURE__ */ React.createElement("div", {
1029
+ className: classNames.join(" "),
1030
+ title,
1031
+ onClick: onButtonClick,
1032
+ __self: this,
1033
+ __source: {
1034
+ fileName: _jsxFileName$h,
1035
+ lineNumber: 43,
1036
+ columnNumber: 7
1037
+ }
1038
+ }, /* @__PURE__ */ React.createElement("span", {
1039
+ className: icon,
1040
+ __self: this,
1041
+ __source: {
1042
+ fileName: _jsxFileName$h,
1043
+ lineNumber: 44,
1044
+ columnNumber: 9
1045
+ }
1046
+ })));
1047
+ }
1048
+ var _jsxFileName$g = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Ok/index.tsx";
1049
+ function Ok() {
1050
+ const lang = useLang();
1051
+ const canvasContextRef = useCanvasContextRef();
1052
+ const [, historyDispatcher] = useHistory();
1053
+ const call = useCall();
1054
+ const [bounds] = useBounds();
1055
+ const reset = useReset();
1056
+ const onClick = useCallback(() => {
1057
+ historyDispatcher.clearSelect();
1058
+ setTimeout(() => {
1059
+ if (!canvasContextRef.current) {
1060
+ return;
1061
+ }
1062
+ canvasContextRef.current.canvas.toBlob((blob) => {
1063
+ call("onOk", blob, bounds);
1064
+ reset();
1065
+ }, "image/png");
1066
+ });
1067
+ }, [canvasContextRef, historyDispatcher, call, bounds, reset]);
1068
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
1069
+ title: lang.operation_ok_title,
1070
+ icon: "icon-ok",
1071
+ onClick,
1072
+ __self: this,
1073
+ __source: {
1074
+ fileName: _jsxFileName$g,
1075
+ lineNumber: 31,
1076
+ columnNumber: 10
1077
+ }
1078
+ });
1079
+ }
1080
+ var _jsxFileName$f = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Cancel/index.tsx";
1081
+ function Cancel() {
1082
+ const call = useCall();
1083
+ const reset = useReset();
1084
+ const lang = useLang();
1085
+ const onClick = useCallback(() => {
1086
+ call("onCancel");
1087
+ reset();
1088
+ }, [call, reset]);
1089
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
1090
+ title: lang.operation_cancel_title,
1091
+ icon: "icon-cancel",
1092
+ onClick,
1093
+ __self: this,
1094
+ __source: {
1095
+ fileName: _jsxFileName$f,
1096
+ lineNumber: 17,
1097
+ columnNumber: 10
1098
+ }
1099
+ });
1100
+ }
1101
+ var _jsxFileName$e = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Save/index.tsx";
1102
+ function Save() {
1103
+ const lang = useLang();
1104
+ const canvasContextRef = useCanvasContextRef();
1105
+ const [, historyDispatcher] = useHistory();
1106
+ const [bounds] = useBounds();
1107
+ const call = useCall();
1108
+ const reset = useReset();
1109
+ const onClick = useCallback(() => {
1110
+ historyDispatcher.clearSelect();
1111
+ setTimeout(() => {
1112
+ if (!canvasContextRef.current) {
1113
+ return;
1114
+ }
1115
+ canvasContextRef.current.canvas.toBlob((blob) => {
1116
+ call("onSave", blob, bounds);
1117
+ reset();
1118
+ }, "image/png");
1119
+ });
1120
+ }, [canvasContextRef, historyDispatcher, bounds, call, reset]);
1121
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
1122
+ title: lang.operation_save_title,
1123
+ icon: "icon-save",
1124
+ onClick,
1125
+ __self: this,
1126
+ __source: {
1127
+ fileName: _jsxFileName$e,
1128
+ lineNumber: 31,
1129
+ columnNumber: 10
1130
+ }
1131
+ });
1132
+ }
1133
+ var _jsxFileName$d = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Redo/index.tsx";
1134
+ function Redo() {
1135
+ const lang = useLang();
1136
+ const [history, historyDispatcher] = useHistory();
1137
+ const onClick = useCallback(() => {
1138
+ historyDispatcher.redo();
1139
+ }, [historyDispatcher]);
1140
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
1141
+ title: lang.operation_redo_title,
1142
+ icon: "icon-redo",
1143
+ disabled: !history.stack.length || history.stack.length - 1 === history.index,
1144
+ onClick,
1145
+ __self: this,
1146
+ __source: {
1147
+ fileName: _jsxFileName$d,
1148
+ lineNumber: 15,
1149
+ columnNumber: 5
1150
+ }
1151
+ });
1152
+ }
1153
+ var _jsxFileName$c = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Undo/index.tsx";
1154
+ function Undo() {
1155
+ const lang = useLang();
1156
+ const [history, historyDispatcher] = useHistory();
1157
+ const onClick = useCallback(() => {
1158
+ historyDispatcher.undo();
1159
+ }, [historyDispatcher]);
1160
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
1161
+ title: lang.operation_undo_title,
1162
+ icon: "icon-undo",
1163
+ disabled: history.index === -1,
1164
+ onClick,
1165
+ __self: this,
1166
+ __source: {
1167
+ fileName: _jsxFileName$c,
1168
+ lineNumber: 15,
1169
+ columnNumber: 5
1170
+ }
1171
+ });
1172
+ }
1173
+ var index$4 = "";
1174
+ var _jsxFileName$b = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsSize/index.tsx";
1175
+ function ScreenshotsSize({
1176
+ value,
1177
+ onChange
1178
+ }) {
1179
+ const sizes2 = [3, 6, 9];
1180
+ return /* @__PURE__ */ React.createElement("div", {
1181
+ className: "screenshots-size",
1182
+ __self: this,
1183
+ __source: {
1184
+ fileName: _jsxFileName$b,
1185
+ lineNumber: 12,
1186
+ columnNumber: 5
1187
+ }
1188
+ }, sizes2.map((size) => {
1189
+ const classNames = ["screenshots-size-item"];
1190
+ if (size === value) {
1191
+ classNames.push("screenshots-size-active");
1192
+ }
1193
+ return /* @__PURE__ */ React.createElement("div", {
1194
+ key: size,
1195
+ className: classNames.join(" "),
1196
+ onClick: () => onChange && onChange(size),
1197
+ __self: this,
1198
+ __source: {
1199
+ fileName: _jsxFileName$b,
1200
+ lineNumber: 21,
1201
+ columnNumber: 11
1202
+ }
1203
+ }, /* @__PURE__ */ React.createElement("div", {
1204
+ className: "screenshots-size-pointer",
1205
+ style: {
1206
+ width: size * 1.8,
1207
+ height: size * 1.8
1208
+ },
1209
+ __self: this,
1210
+ __source: {
1211
+ fileName: _jsxFileName$b,
1212
+ lineNumber: 22,
1213
+ columnNumber: 13
1214
+ }
1215
+ }));
1216
+ }));
1217
+ }
1218
+ function useCanvasMousedown(onMousedown) {
1219
+ const emiter = useEmiter();
1220
+ useEffect(() => {
1221
+ emiter.on("mousedown", onMousedown);
1222
+ return () => {
1223
+ emiter.off("mousedown", onMousedown);
1224
+ };
1225
+ }, [onMousedown, emiter]);
1226
+ }
1227
+ function useCanvasMousemove(onMousemove) {
1228
+ const emiter = useEmiter();
1229
+ useEffect(() => {
1230
+ emiter.on("mousemove", onMousemove);
1231
+ return () => {
1232
+ emiter.off("mousemove", onMousemove);
1233
+ };
1234
+ }, [onMousemove, emiter]);
1235
+ }
1236
+ function useCanvasMouseup(onMouseup) {
1237
+ const emiter = useEmiter();
1238
+ useEffect(() => {
1239
+ emiter.on("mouseup", onMouseup);
1240
+ return () => {
1241
+ emiter.off("mouseup", onMouseup);
1242
+ };
1243
+ }, [onMouseup, emiter]);
1244
+ }
1245
+ var _jsxFileName$a = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Mosaic/index.tsx";
1246
+ function getColor(x, y, imageData) {
1247
+ if (!imageData) {
1248
+ return [0, 0, 0, 0];
1249
+ }
1250
+ const {
1251
+ data,
1252
+ width
1253
+ } = imageData;
1254
+ const index2 = y * width * 4 + x * 4;
1255
+ return Array.from(data.slice(index2, index2 + 4));
1256
+ }
1257
+ function draw$5(ctx, action) {
1258
+ const {
1259
+ tiles,
1260
+ size
1261
+ } = action.data;
1262
+ tiles.forEach((tile) => {
1263
+ const r = Math.round(tile.color[0]);
1264
+ const g = Math.round(tile.color[1]);
1265
+ const b = Math.round(tile.color[2]);
1266
+ const a = tile.color[3] / 255;
1267
+ ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${a})`;
1268
+ ctx.fillRect(tile.x - size / 2, tile.y - size / 2, size, size);
1269
+ });
1270
+ }
1271
+ function Mosaic() {
1272
+ const lang = useLang();
1273
+ const {
1274
+ image,
1275
+ width,
1276
+ height
1277
+ } = useStore();
1278
+ const [operation, operationDispatcher] = useOperation();
1279
+ const canvasContextRef = useCanvasContextRef();
1280
+ const [history, historyDispatcher] = useHistory();
1281
+ const [bounds] = useBounds();
1282
+ const [, cursorDispatcher] = useCursor();
1283
+ const [size, setSize] = useState(3);
1284
+ const imageDataRef = useRef(null);
1285
+ const mosaicRef = useRef(null);
1286
+ const checked = operation === "Mosaic";
1287
+ const selectMosaic = useCallback(() => {
1288
+ operationDispatcher.set("Mosaic");
1289
+ cursorDispatcher.set("crosshair");
1290
+ }, [operationDispatcher, cursorDispatcher]);
1291
+ const onSelectMosaic = useCallback(() => {
1292
+ if (checked) {
1293
+ return;
1294
+ }
1295
+ selectMosaic();
1296
+ historyDispatcher.clearSelect();
1297
+ }, [checked, selectMosaic, historyDispatcher]);
1298
+ const onMousedown = useCallback((e) => {
1299
+ if (!checked || mosaicRef.current || !imageDataRef.current || !canvasContextRef.current) {
1300
+ return;
1301
+ }
1302
+ const rect = canvasContextRef.current.canvas.getBoundingClientRect();
1303
+ const x = e.clientX - rect.x;
1304
+ const y = e.clientY - rect.y;
1305
+ const mosaicSize = size * 2;
1306
+ mosaicRef.current = {
1307
+ name: "Mosaic",
1308
+ type: HistoryItemType.Source,
1309
+ data: {
1310
+ size: mosaicSize,
1311
+ tiles: [{
1312
+ x,
1313
+ y,
1314
+ color: getColor(x, y, imageDataRef.current)
1315
+ }]
1316
+ },
1317
+ editHistory: [],
1318
+ draw: draw$5
1319
+ };
1320
+ }, [checked, size, canvasContextRef]);
1321
+ const onMousemove = useCallback((e) => {
1322
+ if (!checked || !mosaicRef.current || !canvasContextRef.current || !imageDataRef.current) {
1323
+ return;
1324
+ }
1325
+ const rect = canvasContextRef.current.canvas.getBoundingClientRect();
1326
+ const x = e.clientX - rect.x;
1327
+ const y = e.clientY - rect.y;
1328
+ const mosaicSize = mosaicRef.current.data.size;
1329
+ const mosaicTiles = mosaicRef.current.data.tiles;
1330
+ let lastTile = mosaicTiles[mosaicTiles.length - 1];
1331
+ if (!lastTile) {
1332
+ mosaicTiles.push({
1333
+ x,
1334
+ y,
1335
+ color: getColor(x, y, imageDataRef.current)
1336
+ });
1337
+ } else {
1338
+ const dx = lastTile.x - x;
1339
+ const dy = lastTile.y - y;
1340
+ let length = Math.sqrt(dx ** 2 + dy ** 2);
1341
+ const sin = -dy / length;
1342
+ const cos = -dx / length;
1343
+ while (length > mosaicSize) {
1344
+ const cx = Math.floor(lastTile.x + mosaicSize * cos);
1345
+ const cy = Math.floor(lastTile.y + mosaicSize * sin);
1346
+ lastTile = {
1347
+ x: cx,
1348
+ y: cy,
1349
+ color: getColor(cx, cy, imageDataRef.current)
1350
+ };
1351
+ mosaicTiles.push(lastTile);
1352
+ length -= mosaicSize;
1353
+ }
1354
+ if (length > mosaicSize / 2) {
1355
+ mosaicTiles.push({
1356
+ x,
1357
+ y,
1358
+ color: getColor(x, y, imageDataRef.current)
1359
+ });
1360
+ }
1361
+ }
1362
+ if (history.top !== mosaicRef.current) {
1363
+ historyDispatcher.push(mosaicRef.current);
1364
+ } else {
1365
+ historyDispatcher.set(history);
1366
+ }
1367
+ }, [checked, canvasContextRef, history, historyDispatcher]);
1368
+ const onMouseup = useCallback(() => {
1369
+ if (!checked) {
1370
+ return;
1371
+ }
1372
+ mosaicRef.current = null;
1373
+ }, [checked]);
1374
+ useCanvasMousedown(onMousedown);
1375
+ useCanvasMousemove(onMousemove);
1376
+ useCanvasMouseup(onMouseup);
1377
+ useEffect(() => {
1378
+ if (!bounds || !image || !checked) {
1379
+ return;
1380
+ }
1381
+ const $canvas = document.createElement("canvas");
1382
+ const canvasContext = $canvas.getContext("2d");
1383
+ if (!canvasContext) {
1384
+ return;
1385
+ }
1386
+ $canvas.width = bounds.width;
1387
+ $canvas.height = bounds.height;
1388
+ const rx = image.naturalWidth / width;
1389
+ const ry = image.naturalHeight / height;
1390
+ canvasContext.drawImage(image, bounds.x * rx, bounds.y * ry, bounds.width * rx, bounds.height * ry, 0, 0, bounds.width, bounds.height);
1391
+ imageDataRef.current = canvasContext.getImageData(0, 0, bounds.width, bounds.height);
1392
+ }, [width, height, bounds, image, checked]);
1393
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
1394
+ title: lang.operation_mosaic_title,
1395
+ icon: "icon-mosaic",
1396
+ checked,
1397
+ onClick: onSelectMosaic,
1398
+ option: /* @__PURE__ */ React.createElement(ScreenshotsSize, {
1399
+ value: size,
1400
+ onChange: setSize,
1401
+ __self: this,
1402
+ __source: {
1403
+ fileName: _jsxFileName$a,
1404
+ lineNumber: 220,
1405
+ columnNumber: 15
1406
+ }
1407
+ }),
1408
+ __self: this,
1409
+ __source: {
1410
+ fileName: _jsxFileName$a,
1411
+ lineNumber: 215,
1412
+ columnNumber: 5
1413
+ }
1414
+ });
1415
+ }
1416
+ var index$3 = "";
1417
+ var _jsxFileName$9 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsColor/index.tsx";
1418
+ function ScreenshotsColor({
1419
+ value,
1420
+ onChange
1421
+ }) {
1422
+ const colors = ["#ee5126", "#fceb4d", "#90e746", "#51c0fa", "#7a7a7a", "#ffffff"];
1423
+ return /* @__PURE__ */ React.createElement("div", {
1424
+ className: "screenshots-color",
1425
+ __self: this,
1426
+ __source: {
1427
+ fileName: _jsxFileName$9,
1428
+ lineNumber: 12,
1429
+ columnNumber: 5
1430
+ }
1431
+ }, colors.map((color) => {
1432
+ const classNames = ["screenshots-color-item"];
1433
+ if (color === value) {
1434
+ classNames.push("screenshots-color-active");
1435
+ }
1436
+ return /* @__PURE__ */ React.createElement("div", {
1437
+ key: color,
1438
+ className: classNames.join(" "),
1439
+ style: {
1440
+ backgroundColor: color
1441
+ },
1442
+ onClick: () => onChange && onChange(color),
1443
+ __self: this,
1444
+ __source: {
1445
+ fileName: _jsxFileName$9,
1446
+ lineNumber: 19,
1447
+ columnNumber: 11
1448
+ }
1449
+ });
1450
+ }));
1451
+ }
1452
+ var index$2 = "";
1453
+ var _jsxFileName$8 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsSizeColor/index.tsx";
1454
+ function ScreenshotsSizeColor({
1455
+ size,
1456
+ color,
1457
+ onSizeChange,
1458
+ onColorChange
1459
+ }) {
1460
+ return /* @__PURE__ */ React.createElement("div", {
1461
+ className: "screenshots-sizecolor",
1462
+ __self: this,
1463
+ __source: {
1464
+ fileName: _jsxFileName$8,
1465
+ lineNumber: 15,
1466
+ columnNumber: 5
1467
+ }
1468
+ }, /* @__PURE__ */ React.createElement(ScreenshotsSize, {
1469
+ value: size,
1470
+ onChange: onSizeChange,
1471
+ __self: this,
1472
+ __source: {
1473
+ fileName: _jsxFileName$8,
1474
+ lineNumber: 16,
1475
+ columnNumber: 7
1476
+ }
1477
+ }), /* @__PURE__ */ React.createElement(ScreenshotsColor, {
1478
+ value: color,
1479
+ onChange: onColorChange,
1480
+ __self: this,
1481
+ __source: {
1482
+ fileName: _jsxFileName$8,
1483
+ lineNumber: 17,
1484
+ columnNumber: 7
1485
+ }
1486
+ }));
1487
+ }
1488
+ const hiddenTextareaStyle = `
1489
+ min-width: 0 !important;
1490
+ width: 0 !important;
1491
+ min-height: 0 !important;
1492
+ height:0 !important;
1493
+ visibility: hidden !important;
1494
+ overflow: hidden !important;
1495
+ position: absolute !important;
1496
+ z-index: -1000 !important;
1497
+ top:0 !important;
1498
+ right:0 !important;
1499
+ `;
1500
+ const sizeStyle = [
1501
+ "letter-spacing",
1502
+ "line-height",
1503
+ "padding-top",
1504
+ "padding-bottom",
1505
+ "font-family",
1506
+ "font-weight",
1507
+ "font-size",
1508
+ "font-variant",
1509
+ "text-rendering",
1510
+ "text-transform",
1511
+ "text-indent",
1512
+ "padding-left",
1513
+ "padding-right",
1514
+ "border-width",
1515
+ "box-sizing",
1516
+ "white-space",
1517
+ "word-break"
1518
+ ];
1519
+ let hiddenTextarea;
1520
+ function getComputedSizeInfo(node) {
1521
+ const style = window.getComputedStyle(node);
1522
+ const boxSizing = style.getPropertyValue("box-sizing") || style.getPropertyValue("-moz-box-sizing") || style.getPropertyValue("-webkit-box-sizing");
1523
+ const paddingSize = parseFloat(style.getPropertyValue("padding-bottom")) + parseFloat(style.getPropertyValue("padding-top"));
1524
+ const borderSize = parseFloat(style.getPropertyValue("border-bottom-width")) + parseFloat(style.getPropertyValue("border-top-width"));
1525
+ const sizingStyle = sizeStyle.map((name) => `${name}:${style.getPropertyValue(name)}`).join(";");
1526
+ return {
1527
+ sizingStyle,
1528
+ paddingSize,
1529
+ borderSize,
1530
+ boxSizing
1531
+ };
1532
+ }
1533
+ function calculateNodeSize(textarea, value, maxWidth, maxHeight) {
1534
+ if (!hiddenTextarea) {
1535
+ hiddenTextarea = document.createElement("textarea");
1536
+ hiddenTextarea.setAttribute("tab-index", "-1");
1537
+ document.body.appendChild(hiddenTextarea);
1538
+ }
1539
+ const { paddingSize, borderSize, boxSizing, sizingStyle } = getComputedSizeInfo(textarea);
1540
+ hiddenTextarea.setAttribute("style", `${sizingStyle};${hiddenTextareaStyle};max-width:${maxWidth}px;max-height:${maxHeight}px`);
1541
+ hiddenTextarea.value = value || " ";
1542
+ let width = hiddenTextarea.scrollWidth;
1543
+ let height = hiddenTextarea.scrollHeight;
1544
+ if (boxSizing === "border-box") {
1545
+ width += borderSize;
1546
+ height += borderSize;
1547
+ } else if (boxSizing === "content-box") {
1548
+ width -= paddingSize;
1549
+ height -= paddingSize;
1550
+ }
1551
+ return {
1552
+ width: Math.min(width, maxWidth),
1553
+ height: Math.min(height, maxHeight)
1554
+ };
1555
+ }
1556
+ var index$1 = "";
1557
+ var _jsxFileName$7 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsTextarea/index.tsx";
1558
+ function ScreenshotsTextarea({
1559
+ x,
1560
+ y,
1561
+ maxWidth,
1562
+ maxHeight,
1563
+ size,
1564
+ color,
1565
+ value,
1566
+ onChange,
1567
+ onBlur
1568
+ }) {
1569
+ const popoverRef = useRef(null);
1570
+ const textareaRef = useRef(null);
1571
+ const [width, setWidth] = useState(0);
1572
+ const [height, setHeight] = useState(0);
1573
+ const getPopoverEl = () => {
1574
+ if (!popoverRef.current) {
1575
+ popoverRef.current = document.createElement("div");
1576
+ }
1577
+ return popoverRef.current;
1578
+ };
1579
+ useLayoutEffect(() => {
1580
+ if (popoverRef.current) {
1581
+ document.body.appendChild(popoverRef.current);
1582
+ requestAnimationFrame(() => {
1583
+ var _a2;
1584
+ (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
1585
+ });
1586
+ }
1587
+ return () => {
1588
+ var _a2;
1589
+ (_a2 = popoverRef.current) == null ? void 0 : _a2.remove();
1590
+ };
1591
+ }, []);
1592
+ useLayoutEffect(() => {
1593
+ if (!textareaRef.current) {
1594
+ return;
1595
+ }
1596
+ const {
1597
+ width: width2,
1598
+ height: height2
1599
+ } = calculateNodeSize(textareaRef.current, value, maxWidth, maxHeight);
1600
+ setWidth(width2);
1601
+ setHeight(height2);
1602
+ }, [value, maxWidth, maxHeight]);
1603
+ return createPortal(/* @__PURE__ */ React.createElement("textarea", {
1604
+ ref: textareaRef,
1605
+ className: "screenshots-textarea",
1606
+ style: {
1607
+ left: x,
1608
+ top: y,
1609
+ color,
1610
+ width,
1611
+ height,
1612
+ maxWidth,
1613
+ maxHeight,
1614
+ fontSize: size,
1615
+ lineHeight: `${size}px`
1616
+ },
1617
+ value,
1618
+ onChange: (e) => onChange && onChange(e.target.value),
1619
+ onBlur: (e) => onBlur && onBlur(e),
1620
+ __self: this,
1621
+ __source: {
1622
+ fileName: _jsxFileName$7,
1623
+ lineNumber: 65,
1624
+ columnNumber: 5
1625
+ }
1626
+ }), getPopoverEl());
1627
+ }
1628
+ function useDrawSelect(onDrawSelect) {
1629
+ const emiter = useEmiter();
1630
+ useEffect(() => {
1631
+ emiter.on("drawselect", onDrawSelect);
1632
+ return () => {
1633
+ emiter.off("drawselect", onDrawSelect);
1634
+ };
1635
+ }, [onDrawSelect, emiter]);
1636
+ }
1637
+ var _jsxFileName$6 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Text/index.tsx";
1638
+ const sizes = {
1639
+ 3: 18,
1640
+ 6: 32,
1641
+ 9: 46
1642
+ };
1643
+ function draw$4(ctx, action) {
1644
+ const {
1645
+ size,
1646
+ color,
1647
+ fontFamily,
1648
+ x,
1649
+ y,
1650
+ text
1651
+ } = action.data;
1652
+ ctx.fillStyle = color;
1653
+ ctx.textAlign = "left";
1654
+ ctx.textBaseline = "top";
1655
+ ctx.font = `${size}px ${fontFamily}`;
1656
+ const distance = action.editHistory.reduce((distance2, {
1657
+ data
1658
+ }) => ({
1659
+ x: distance2.x + data.x2 - data.x1,
1660
+ y: distance2.y + data.y2 - data.y1
1661
+ }), {
1662
+ x: 0,
1663
+ y: 0
1664
+ });
1665
+ text.split("\n").forEach((item, index2) => {
1666
+ ctx.fillText(item, x + distance.x, y + distance.y + index2 * size);
1667
+ });
1668
+ }
1669
+ function isHit$1(ctx, action, point) {
1670
+ ctx.textAlign = "left";
1671
+ ctx.textBaseline = "top";
1672
+ ctx.font = `${action.data.size}px ${action.data.fontFamily}`;
1673
+ let width = 0;
1674
+ let height = 0;
1675
+ action.data.text.split("\n").forEach((item) => {
1676
+ const measured = ctx.measureText(item);
1677
+ if (width < measured.width) {
1678
+ width = measured.width;
1679
+ }
1680
+ height += action.data.size;
1681
+ });
1682
+ const {
1683
+ x,
1684
+ y
1685
+ } = action.editHistory.reduce((distance, {
1686
+ data
1687
+ }) => ({
1688
+ x: distance.x + data.x2 - data.x1,
1689
+ y: distance.y + data.y2 - data.y1
1690
+ }), {
1691
+ x: 0,
1692
+ y: 0
1693
+ });
1694
+ const left = action.data.x + x;
1695
+ const top = action.data.y + y;
1696
+ const right = left + width;
1697
+ const bottom = top + height;
1698
+ return point.x >= left && point.x <= right && point.y >= top && point.y <= bottom;
1699
+ }
1700
+ function Text() {
1701
+ const lang = useLang();
1702
+ const [history, historyDispatcher] = useHistory();
1703
+ const [bounds] = useBounds();
1704
+ const [operation, operationDispatcher] = useOperation();
1705
+ const [, cursorDispatcher] = useCursor();
1706
+ const canvasContextRef = useCanvasContextRef();
1707
+ const [size, setSize] = useState(3);
1708
+ const [color, setColor] = useState("#ee5126");
1709
+ const textRef = useRef(null);
1710
+ const textEditRef = useRef(null);
1711
+ const [textareaBounds, setTextareaBounds] = useState(null);
1712
+ const [text, setText] = useState("");
1713
+ const checked = operation === "Text";
1714
+ const selectText = useCallback(() => {
1715
+ operationDispatcher.set("Text");
1716
+ cursorDispatcher.set("default");
1717
+ }, [operationDispatcher, cursorDispatcher]);
1718
+ const onSelectText = useCallback(() => {
1719
+ if (checked) {
1720
+ return;
1721
+ }
1722
+ selectText();
1723
+ historyDispatcher.clearSelect();
1724
+ }, [checked, selectText, historyDispatcher]);
1725
+ const onSizeChange = useCallback((size2) => {
1726
+ if (textRef.current) {
1727
+ textRef.current.data.size = sizes[size2];
1728
+ }
1729
+ setSize(size2);
1730
+ }, []);
1731
+ const onColorChange = useCallback((color2) => {
1732
+ if (textRef.current) {
1733
+ textRef.current.data.color = color2;
1734
+ }
1735
+ setColor(color2);
1736
+ }, []);
1737
+ const onTextareaChange = useCallback((value) => {
1738
+ setText(value);
1739
+ if (checked && textRef.current) {
1740
+ textRef.current.data.text = value;
1741
+ }
1742
+ }, [checked]);
1743
+ const onTextareaBlur = useCallback(() => {
1744
+ if (textRef.current && textRef.current.data.text) {
1745
+ historyDispatcher.push(textRef.current);
1746
+ }
1747
+ textRef.current = null;
1748
+ setText("");
1749
+ setTextareaBounds(null);
1750
+ }, [historyDispatcher]);
1751
+ const onDrawSelect = useCallback((action, e) => {
1752
+ if (action.name !== "Text") {
1753
+ return;
1754
+ }
1755
+ selectText();
1756
+ textEditRef.current = {
1757
+ type: HistoryItemType.Edit,
1758
+ data: {
1759
+ x1: e.clientX,
1760
+ y1: e.clientY,
1761
+ x2: e.clientX,
1762
+ y2: e.clientY
1763
+ },
1764
+ source: action
1765
+ };
1766
+ historyDispatcher.select(action);
1767
+ }, [selectText, historyDispatcher]);
1768
+ const onMousedown = useCallback((e) => {
1769
+ if (!checked || !canvasContextRef.current || textRef.current || !bounds) {
1770
+ return;
1771
+ }
1772
+ const {
1773
+ left,
1774
+ top
1775
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
1776
+ const fontFamily = window.getComputedStyle(canvasContextRef.current.canvas).fontFamily;
1777
+ const x = e.clientX - left;
1778
+ const y = e.clientY - top;
1779
+ textRef.current = {
1780
+ name: "Text",
1781
+ type: HistoryItemType.Source,
1782
+ data: {
1783
+ size: sizes[size],
1784
+ color,
1785
+ fontFamily,
1786
+ x,
1787
+ y,
1788
+ text: ""
1789
+ },
1790
+ editHistory: [],
1791
+ draw: draw$4,
1792
+ isHit: isHit$1
1793
+ };
1794
+ setTextareaBounds({
1795
+ x: e.clientX,
1796
+ y: e.clientY,
1797
+ maxWidth: bounds.width - x,
1798
+ maxHeight: bounds.height - y
1799
+ });
1800
+ }, [checked, size, color, bounds, canvasContextRef]);
1801
+ const onMousemove = useCallback((e) => {
1802
+ if (!checked) {
1803
+ return;
1804
+ }
1805
+ if (textEditRef.current) {
1806
+ textEditRef.current.data.x2 = e.clientX;
1807
+ textEditRef.current.data.y2 = e.clientY;
1808
+ if (history.top !== textEditRef.current) {
1809
+ textEditRef.current.source.editHistory.push(textEditRef.current);
1810
+ historyDispatcher.push(textEditRef.current);
1811
+ } else {
1812
+ historyDispatcher.set(history);
1813
+ }
1814
+ }
1815
+ }, [checked, history, historyDispatcher]);
1816
+ const onMouseup = useCallback(() => {
1817
+ if (!checked) {
1818
+ return;
1819
+ }
1820
+ textEditRef.current = null;
1821
+ }, [checked]);
1822
+ useDrawSelect(onDrawSelect);
1823
+ useCanvasMousedown(onMousedown);
1824
+ useCanvasMousemove(onMousemove);
1825
+ useCanvasMouseup(onMouseup);
1826
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ScreenshotsButton, {
1827
+ title: lang.operation_text_title,
1828
+ icon: "icon-text",
1829
+ checked,
1830
+ onClick: onSelectText,
1831
+ option: /* @__PURE__ */ React.createElement(ScreenshotsSizeColor, {
1832
+ size,
1833
+ color,
1834
+ onSizeChange,
1835
+ onColorChange,
1836
+ __self: this,
1837
+ __source: {
1838
+ fileName: _jsxFileName$6,
1839
+ lineNumber: 261,
1840
+ columnNumber: 11
1841
+ }
1842
+ }),
1843
+ __self: this,
1844
+ __source: {
1845
+ fileName: _jsxFileName$6,
1846
+ lineNumber: 255,
1847
+ columnNumber: 7
1848
+ }
1849
+ }), checked && textareaBounds && /* @__PURE__ */ React.createElement(ScreenshotsTextarea, {
1850
+ x: textareaBounds.x,
1851
+ y: textareaBounds.y,
1852
+ maxWidth: textareaBounds.maxWidth,
1853
+ maxHeight: textareaBounds.maxHeight,
1854
+ size: sizes[size],
1855
+ color,
1856
+ value: text,
1857
+ onChange: onTextareaChange,
1858
+ onBlur: onTextareaBlur,
1859
+ __self: this,
1860
+ __source: {
1861
+ fileName: _jsxFileName$6,
1862
+ lineNumber: 265,
1863
+ columnNumber: 9
1864
+ }
1865
+ }));
1866
+ }
1867
+ const CircleRadius = 4;
1868
+ function drawDragCircle(ctx, x, y) {
1869
+ ctx.lineWidth = 1;
1870
+ ctx.strokeStyle = "#000000";
1871
+ ctx.fillStyle = "#ffffff";
1872
+ ctx.beginPath();
1873
+ ctx.arc(x, y, CircleRadius, 0, 2 * Math.PI);
1874
+ ctx.fill();
1875
+ ctx.stroke();
1876
+ }
1877
+ function isHit(ctx, action, point) {
1878
+ action.draw(ctx, action);
1879
+ const { data } = ctx.getImageData(point.x, point.y, 1, 1);
1880
+ return data.some((val) => val !== 0);
1881
+ }
1882
+ function isHitCircle(canvas, e, point) {
1883
+ if (!canvas) {
1884
+ return false;
1885
+ }
1886
+ const { left, top } = canvas.getBoundingClientRect();
1887
+ const x = e.clientX - left;
1888
+ const y = e.clientY - top;
1889
+ return (point.x - x) ** 2 + (point.y - y) ** 2 < CircleRadius ** 2;
1890
+ }
1891
+ function draw$3(ctx, action) {
1892
+ const { size, color, points } = action.data;
1893
+ ctx.lineCap = "round";
1894
+ ctx.lineJoin = "round";
1895
+ ctx.lineWidth = size;
1896
+ ctx.strokeStyle = color;
1897
+ const distance = action.editHistory.reduce((distance2, { data }) => ({
1898
+ x: distance2.x + data.x2 - data.x1,
1899
+ y: distance2.y + data.y2 - data.y1
1900
+ }), { x: 0, y: 0 });
1901
+ ctx.beginPath();
1902
+ points.forEach((item, index2) => {
1903
+ if (index2 === 0) {
1904
+ ctx.moveTo(item.x + distance.x, item.y + distance.y);
1905
+ } else {
1906
+ ctx.lineTo(item.x + distance.x, item.y + distance.y);
1907
+ }
1908
+ });
1909
+ ctx.stroke();
1910
+ if (action.isSelected) {
1911
+ ctx.lineWidth = 1;
1912
+ ctx.strokeStyle = "#000000";
1913
+ ctx.beginPath();
1914
+ points.forEach((item, index2) => {
1915
+ if (index2 === 0) {
1916
+ ctx.moveTo(item.x + distance.x, item.y + distance.y);
1917
+ } else {
1918
+ ctx.lineTo(item.x + distance.x, item.y + distance.y);
1919
+ }
1920
+ });
1921
+ ctx.stroke();
1922
+ }
1923
+ }
1924
+ var _jsxFileName$5 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Brush/index.tsx";
1925
+ function Brush() {
1926
+ const lang = useLang();
1927
+ const [, cursorDispatcher] = useCursor();
1928
+ const [operation, operationDispatcher] = useOperation();
1929
+ const canvasContextRef = useCanvasContextRef();
1930
+ const [history, historyDispatcher] = useHistory();
1931
+ const [size, setSize] = useState(3);
1932
+ const [color, setColor] = useState("#ee5126");
1933
+ const brushRef = useRef(null);
1934
+ const brushEditRef = useRef(null);
1935
+ const checked = operation === "Brush";
1936
+ const selectBrush = useCallback(() => {
1937
+ operationDispatcher.set("Brush");
1938
+ cursorDispatcher.set("default");
1939
+ }, [operationDispatcher, cursorDispatcher]);
1940
+ const onSelectBrush = useCallback(() => {
1941
+ if (checked) {
1942
+ return;
1943
+ }
1944
+ selectBrush();
1945
+ historyDispatcher.clearSelect();
1946
+ }, [checked, selectBrush, historyDispatcher]);
1947
+ const onDrawSelect = useCallback((action, e) => {
1948
+ if (action.name !== "Brush") {
1949
+ return;
1950
+ }
1951
+ selectBrush();
1952
+ brushEditRef.current = {
1953
+ type: HistoryItemType.Edit,
1954
+ data: {
1955
+ x1: e.clientX,
1956
+ y1: e.clientY,
1957
+ x2: e.clientX,
1958
+ y2: e.clientY
1959
+ },
1960
+ source: action
1961
+ };
1962
+ historyDispatcher.select(action);
1963
+ }, [selectBrush, historyDispatcher]);
1964
+ const onMousedown = useCallback((e) => {
1965
+ if (!checked || brushRef.current || !canvasContextRef.current) {
1966
+ return;
1967
+ }
1968
+ const {
1969
+ left,
1970
+ top
1971
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
1972
+ brushRef.current = {
1973
+ name: "Brush",
1974
+ type: HistoryItemType.Source,
1975
+ data: {
1976
+ size,
1977
+ color,
1978
+ points: [{
1979
+ x: e.clientX - left,
1980
+ y: e.clientY - top
1981
+ }]
1982
+ },
1983
+ editHistory: [],
1984
+ draw: draw$3,
1985
+ isHit
1986
+ };
1987
+ }, [checked, canvasContextRef, size, color]);
1988
+ const onMousemove = useCallback((e) => {
1989
+ if (!checked || !canvasContextRef.current) {
1990
+ return;
1991
+ }
1992
+ if (brushEditRef.current) {
1993
+ brushEditRef.current.data.x2 = e.clientX;
1994
+ brushEditRef.current.data.y2 = e.clientY;
1995
+ if (history.top !== brushEditRef.current) {
1996
+ brushEditRef.current.source.editHistory.push(brushEditRef.current);
1997
+ historyDispatcher.push(brushEditRef.current);
1998
+ } else {
1999
+ historyDispatcher.set(history);
2000
+ }
2001
+ } else if (brushRef.current) {
2002
+ const {
2003
+ left,
2004
+ top
2005
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
2006
+ brushRef.current.data.points.push({
2007
+ x: e.clientX - left,
2008
+ y: e.clientY - top
2009
+ });
2010
+ if (history.top !== brushRef.current) {
2011
+ historyDispatcher.push(brushRef.current);
2012
+ } else {
2013
+ historyDispatcher.set(history);
2014
+ }
2015
+ }
2016
+ }, [checked, history, canvasContextRef, historyDispatcher]);
2017
+ const onMouseup = useCallback(() => {
2018
+ if (!checked) {
2019
+ return;
2020
+ }
2021
+ if (brushRef.current) {
2022
+ historyDispatcher.clearSelect();
2023
+ }
2024
+ brushRef.current = null;
2025
+ brushEditRef.current = null;
2026
+ }, [checked, historyDispatcher]);
2027
+ useDrawSelect(onDrawSelect);
2028
+ useCanvasMousedown(onMousedown);
2029
+ useCanvasMousemove(onMousemove);
2030
+ useCanvasMouseup(onMouseup);
2031
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
2032
+ title: lang.operation_brush_title,
2033
+ icon: "icon-brush",
2034
+ checked,
2035
+ onClick: onSelectBrush,
2036
+ option: /* @__PURE__ */ React.createElement(ScreenshotsSizeColor, {
2037
+ size,
2038
+ color,
2039
+ onSizeChange: setSize,
2040
+ onColorChange: setColor,
2041
+ __self: this,
2042
+ __source: {
2043
+ fileName: _jsxFileName$5,
2044
+ lineNumber: 166,
2045
+ columnNumber: 15
2046
+ }
2047
+ }),
2048
+ __self: this,
2049
+ __source: {
2050
+ fileName: _jsxFileName$5,
2051
+ lineNumber: 161,
2052
+ columnNumber: 5
2053
+ }
2054
+ });
2055
+ }
2056
+ function getEditedArrowData(action) {
2057
+ let { x1, y1, x2, y2 } = action.data;
2058
+ action.editHistory.forEach(({ data }) => {
2059
+ const x = data.x2 - data.x1;
2060
+ const y = data.y2 - data.y1;
2061
+ if (data.type === ArrowEditType.Move) {
2062
+ x1 += x;
2063
+ y1 += y;
2064
+ x2 += x;
2065
+ y2 += y;
2066
+ } else if (data.type === ArrowEditType.MoveStart) {
2067
+ x1 += x;
2068
+ y1 += y;
2069
+ } else if (data.type === ArrowEditType.MoveEnd) {
2070
+ x2 += x;
2071
+ y2 += y;
2072
+ }
2073
+ });
2074
+ return __spreadProps(__spreadValues({}, action.data), {
2075
+ x1,
2076
+ x2,
2077
+ y1,
2078
+ y2
2079
+ });
2080
+ }
2081
+ function draw$2(ctx, action) {
2082
+ const { size, color, x1, x2, y1, y2 } = getEditedArrowData(action);
2083
+ ctx.lineCap = "round";
2084
+ ctx.lineJoin = "bevel";
2085
+ ctx.lineWidth = size;
2086
+ ctx.strokeStyle = color;
2087
+ const dx = x2 - x1;
2088
+ const dy = y2 - y1;
2089
+ const length = size * 3;
2090
+ const angle = Math.atan2(dy, dx);
2091
+ ctx.beginPath();
2092
+ ctx.moveTo(x1, y1);
2093
+ ctx.lineTo(x2, y2);
2094
+ ctx.lineTo(x2 - length * Math.cos(angle - Math.PI / 6), y2 - length * Math.sin(angle - Math.PI / 6));
2095
+ ctx.moveTo(x2, y2);
2096
+ ctx.lineTo(x2 - length * Math.cos(angle + Math.PI / 6), y2 - length * Math.sin(angle + Math.PI / 6));
2097
+ ctx.stroke();
2098
+ if (action.isSelected) {
2099
+ drawDragCircle(ctx, x1, y1);
2100
+ drawDragCircle(ctx, x2, y2);
2101
+ }
2102
+ }
2103
+ var _jsxFileName$4 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Arrow/index.tsx";
2104
+ var ArrowEditType;
2105
+ (function(ArrowEditType2) {
2106
+ ArrowEditType2[ArrowEditType2["Move"] = 0] = "Move";
2107
+ ArrowEditType2[ArrowEditType2["MoveStart"] = 1] = "MoveStart";
2108
+ ArrowEditType2[ArrowEditType2["MoveEnd"] = 2] = "MoveEnd";
2109
+ })(ArrowEditType || (ArrowEditType = {}));
2110
+ function Arrow() {
2111
+ const lang = useLang();
2112
+ const [, cursorDispatcher] = useCursor();
2113
+ const [operation, operationDispatcher] = useOperation();
2114
+ const [history, historyDispatcher] = useHistory();
2115
+ const canvasContextRef = useCanvasContextRef();
2116
+ const [size, setSize] = useState(3);
2117
+ const [color, setColor] = useState("#ee5126");
2118
+ const arrowRef = useRef(null);
2119
+ const arrowEditRef = useRef(null);
2120
+ const checked = operation === "Arrow";
2121
+ const selectArrow = useCallback(() => {
2122
+ operationDispatcher.set("Arrow");
2123
+ cursorDispatcher.set("default");
2124
+ }, [operationDispatcher, cursorDispatcher]);
2125
+ const onSelectArrow = useCallback(() => {
2126
+ if (checked) {
2127
+ return;
2128
+ }
2129
+ selectArrow();
2130
+ historyDispatcher.clearSelect();
2131
+ }, [checked, selectArrow, historyDispatcher]);
2132
+ const onDrawSelect = useCallback((action, e) => {
2133
+ if (action.name !== "Arrow" || !canvasContextRef.current) {
2134
+ return;
2135
+ }
2136
+ const source = action;
2137
+ selectArrow();
2138
+ const {
2139
+ x1,
2140
+ y1,
2141
+ x2,
2142
+ y2
2143
+ } = getEditedArrowData(source);
2144
+ let type = 0;
2145
+ if (isHitCircle(canvasContextRef.current.canvas, e, {
2146
+ x: x1,
2147
+ y: y1
2148
+ })) {
2149
+ type = 1;
2150
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2151
+ x: x2,
2152
+ y: y2
2153
+ })) {
2154
+ type = 2;
2155
+ }
2156
+ arrowEditRef.current = {
2157
+ type: HistoryItemType.Edit,
2158
+ data: {
2159
+ type,
2160
+ x1: e.clientX,
2161
+ y1: e.clientY,
2162
+ x2: e.clientX,
2163
+ y2: e.clientY
2164
+ },
2165
+ source
2166
+ };
2167
+ historyDispatcher.select(action);
2168
+ }, [canvasContextRef, selectArrow, historyDispatcher]);
2169
+ const onMousedown = useCallback((e) => {
2170
+ if (!checked || arrowRef.current || !canvasContextRef.current) {
2171
+ return;
2172
+ }
2173
+ const {
2174
+ left,
2175
+ top
2176
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
2177
+ arrowRef.current = {
2178
+ name: "Arrow",
2179
+ type: HistoryItemType.Source,
2180
+ data: {
2181
+ size,
2182
+ color,
2183
+ x1: e.clientX - left,
2184
+ y1: e.clientY - top,
2185
+ x2: e.clientX - left,
2186
+ y2: e.clientY - top
2187
+ },
2188
+ editHistory: [],
2189
+ draw: draw$2,
2190
+ isHit
2191
+ };
2192
+ }, [checked, color, size, canvasContextRef]);
2193
+ const onMousemove = useCallback((e) => {
2194
+ if (!checked || !canvasContextRef.current) {
2195
+ return;
2196
+ }
2197
+ if (arrowEditRef.current) {
2198
+ arrowEditRef.current.data.x2 = e.clientX;
2199
+ arrowEditRef.current.data.y2 = e.clientY;
2200
+ if (history.top !== arrowEditRef.current) {
2201
+ arrowEditRef.current.source.editHistory.push(arrowEditRef.current);
2202
+ historyDispatcher.push(arrowEditRef.current);
2203
+ } else {
2204
+ historyDispatcher.set(history);
2205
+ }
2206
+ } else if (arrowRef.current) {
2207
+ const {
2208
+ left,
2209
+ top
2210
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
2211
+ arrowRef.current.data.x2 = e.clientX - left;
2212
+ arrowRef.current.data.y2 = e.clientY - top;
2213
+ if (history.top !== arrowRef.current) {
2214
+ historyDispatcher.push(arrowRef.current);
2215
+ } else {
2216
+ historyDispatcher.set(history);
2217
+ }
2218
+ }
2219
+ }, [checked, history, canvasContextRef, historyDispatcher]);
2220
+ const onMouseup = useCallback(() => {
2221
+ if (!checked) {
2222
+ return;
2223
+ }
2224
+ if (arrowRef.current) {
2225
+ historyDispatcher.clearSelect();
2226
+ }
2227
+ arrowRef.current = null;
2228
+ arrowEditRef.current = null;
2229
+ }, [checked, historyDispatcher]);
2230
+ useDrawSelect(onDrawSelect);
2231
+ useCanvasMousedown(onMousedown);
2232
+ useCanvasMousemove(onMousemove);
2233
+ useCanvasMouseup(onMouseup);
2234
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
2235
+ title: lang.operation_arrow_title,
2236
+ icon: "icon-arrow",
2237
+ checked,
2238
+ onClick: onSelectArrow,
2239
+ option: /* @__PURE__ */ React.createElement(ScreenshotsSizeColor, {
2240
+ size,
2241
+ color,
2242
+ onSizeChange: setSize,
2243
+ onColorChange: setColor,
2244
+ __self: this,
2245
+ __source: {
2246
+ fileName: _jsxFileName$4,
2247
+ lineNumber: 190,
2248
+ columnNumber: 15
2249
+ }
2250
+ }),
2251
+ __self: this,
2252
+ __source: {
2253
+ fileName: _jsxFileName$4,
2254
+ lineNumber: 185,
2255
+ columnNumber: 5
2256
+ }
2257
+ });
2258
+ }
2259
+ function getEditedEllipseData(action) {
2260
+ let { x1, y1, x2, y2 } = action.data;
2261
+ action.editHistory.forEach(({ data }) => {
2262
+ const x = data.x2 - data.x1;
2263
+ const y = data.y2 - data.y1;
2264
+ if (data.type === EllipseEditType.Move) {
2265
+ x1 += x;
2266
+ y1 += y;
2267
+ x2 += x;
2268
+ y2 += y;
2269
+ } else if (data.type === EllipseEditType.ResizeTop) {
2270
+ y1 += y;
2271
+ } else if (data.type === EllipseEditType.ResizeRightTop) {
2272
+ x2 += x;
2273
+ y1 += y;
2274
+ } else if (data.type === EllipseEditType.ResizeRight) {
2275
+ x2 += x;
2276
+ } else if (data.type === EllipseEditType.ResizeRightBottom) {
2277
+ x2 += x;
2278
+ y2 += y;
2279
+ } else if (data.type === EllipseEditType.ResizeBottom) {
2280
+ y2 += y;
2281
+ } else if (data.type === EllipseEditType.ResizeLeftBottom) {
2282
+ x1 += x;
2283
+ y2 += y;
2284
+ } else if (data.type === EllipseEditType.ResizeLeft) {
2285
+ x1 += x;
2286
+ } else if (data.type === EllipseEditType.ResizeLeftTop) {
2287
+ x1 += x;
2288
+ y1 += y;
2289
+ }
2290
+ });
2291
+ return __spreadProps(__spreadValues({}, action.data), {
2292
+ x1,
2293
+ x2,
2294
+ y1,
2295
+ y2
2296
+ });
2297
+ }
2298
+ function draw$1(ctx, action) {
2299
+ const { size, color, x1, y1, x2, y2 } = getEditedEllipseData(action);
2300
+ ctx.lineCap = "butt";
2301
+ ctx.lineJoin = "miter";
2302
+ ctx.lineWidth = size;
2303
+ ctx.strokeStyle = color;
2304
+ const x = (x1 + x2) / 2;
2305
+ const y = (y1 + y2) / 2;
2306
+ const rx = Math.abs(x2 - x1) / 2;
2307
+ const ry = Math.abs(y2 - y1) / 2;
2308
+ const k = 0.5522848;
2309
+ const ox = rx * k;
2310
+ const oy = ry * k;
2311
+ ctx.beginPath();
2312
+ ctx.moveTo(x - rx, y);
2313
+ ctx.bezierCurveTo(x - rx, y - oy, x - ox, y - ry, x, y - ry);
2314
+ ctx.bezierCurveTo(x + ox, y - ry, x + rx, y - oy, x + rx, y);
2315
+ ctx.bezierCurveTo(x + rx, y + oy, x + ox, y + ry, x, y + ry);
2316
+ ctx.bezierCurveTo(x - ox, y + ry, x - rx, y + oy, x - rx, y);
2317
+ ctx.closePath();
2318
+ ctx.stroke();
2319
+ if (action.isSelected) {
2320
+ ctx.lineWidth = 1;
2321
+ ctx.strokeStyle = "#000000";
2322
+ ctx.fillStyle = "#ffffff";
2323
+ ctx.beginPath();
2324
+ ctx.moveTo(x1, y1);
2325
+ ctx.lineTo(x2, y1);
2326
+ ctx.lineTo(x2, y2);
2327
+ ctx.lineTo(x1, y2);
2328
+ ctx.closePath();
2329
+ ctx.stroke();
2330
+ drawDragCircle(ctx, (x1 + x2) / 2, y1);
2331
+ drawDragCircle(ctx, x2, y1);
2332
+ drawDragCircle(ctx, x2, (y1 + y2) / 2);
2333
+ drawDragCircle(ctx, x2, y2);
2334
+ drawDragCircle(ctx, (x1 + x2) / 2, y2);
2335
+ drawDragCircle(ctx, x1, y2);
2336
+ drawDragCircle(ctx, x1, (y1 + y2) / 2);
2337
+ drawDragCircle(ctx, x1, y1);
2338
+ }
2339
+ }
2340
+ var _jsxFileName$3 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Ellipse/index.tsx";
2341
+ var EllipseEditType;
2342
+ (function(EllipseEditType2) {
2343
+ EllipseEditType2[EllipseEditType2["Move"] = 0] = "Move";
2344
+ EllipseEditType2[EllipseEditType2["ResizeTop"] = 1] = "ResizeTop";
2345
+ EllipseEditType2[EllipseEditType2["ResizeRightTop"] = 2] = "ResizeRightTop";
2346
+ EllipseEditType2[EllipseEditType2["ResizeRight"] = 3] = "ResizeRight";
2347
+ EllipseEditType2[EllipseEditType2["ResizeRightBottom"] = 4] = "ResizeRightBottom";
2348
+ EllipseEditType2[EllipseEditType2["ResizeBottom"] = 5] = "ResizeBottom";
2349
+ EllipseEditType2[EllipseEditType2["ResizeLeftBottom"] = 6] = "ResizeLeftBottom";
2350
+ EllipseEditType2[EllipseEditType2["ResizeLeft"] = 7] = "ResizeLeft";
2351
+ EllipseEditType2[EllipseEditType2["ResizeLeftTop"] = 8] = "ResizeLeftTop";
2352
+ })(EllipseEditType || (EllipseEditType = {}));
2353
+ function Ellipse() {
2354
+ const lang = useLang();
2355
+ const [history, historyDispatcher] = useHistory();
2356
+ const [operation, operationDispatcher] = useOperation();
2357
+ const [, cursorDispatcher] = useCursor();
2358
+ const canvasContextRef = useCanvasContextRef();
2359
+ const [size, setSize] = useState(3);
2360
+ const [color, setColor] = useState("#ee5126");
2361
+ const ellipseRef = useRef(null);
2362
+ const ellipseEditRef = useRef(null);
2363
+ const checked = operation === "Ellipse";
2364
+ const selectEllipse = useCallback(() => {
2365
+ operationDispatcher.set("Ellipse");
2366
+ cursorDispatcher.set("crosshair");
2367
+ }, [operationDispatcher, cursorDispatcher]);
2368
+ const onSelectEllipse = useCallback(() => {
2369
+ if (checked) {
2370
+ return;
2371
+ }
2372
+ selectEllipse();
2373
+ historyDispatcher.clearSelect();
2374
+ }, [checked, selectEllipse, historyDispatcher]);
2375
+ const onDrawSelect = useCallback((action, e) => {
2376
+ if (action.name !== "Ellipse" || !canvasContextRef.current) {
2377
+ return;
2378
+ }
2379
+ const source = action;
2380
+ selectEllipse();
2381
+ const {
2382
+ x1,
2383
+ y1,
2384
+ x2,
2385
+ y2
2386
+ } = getEditedEllipseData(source);
2387
+ let type = 0;
2388
+ if (isHitCircle(canvasContextRef.current.canvas, e, {
2389
+ x: (x1 + x2) / 2,
2390
+ y: y1
2391
+ })) {
2392
+ type = 1;
2393
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2394
+ x: x2,
2395
+ y: y1
2396
+ })) {
2397
+ type = 2;
2398
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2399
+ x: x2,
2400
+ y: (y1 + y2) / 2
2401
+ })) {
2402
+ type = 3;
2403
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2404
+ x: x2,
2405
+ y: y2
2406
+ })) {
2407
+ type = 4;
2408
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2409
+ x: (x1 + x2) / 2,
2410
+ y: y2
2411
+ })) {
2412
+ type = 5;
2413
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2414
+ x: x1,
2415
+ y: y2
2416
+ })) {
2417
+ type = 6;
2418
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2419
+ x: x1,
2420
+ y: (y1 + y2) / 2
2421
+ })) {
2422
+ type = 7;
2423
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2424
+ x: x1,
2425
+ y: y1
2426
+ })) {
2427
+ type = 8;
2428
+ }
2429
+ ellipseEditRef.current = {
2430
+ type: HistoryItemType.Edit,
2431
+ data: {
2432
+ type,
2433
+ x1: e.clientX,
2434
+ y1: e.clientY,
2435
+ x2: e.clientX,
2436
+ y2: e.clientY
2437
+ },
2438
+ source
2439
+ };
2440
+ historyDispatcher.select(action);
2441
+ }, [canvasContextRef, selectEllipse, historyDispatcher]);
2442
+ const onMousedown = useCallback((e) => {
2443
+ if (!checked || !canvasContextRef.current || ellipseRef.current) {
2444
+ return;
2445
+ }
2446
+ const {
2447
+ left,
2448
+ top
2449
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
2450
+ const x = e.clientX - left;
2451
+ const y = e.clientY - top;
2452
+ ellipseRef.current = {
2453
+ name: "Ellipse",
2454
+ type: HistoryItemType.Source,
2455
+ data: {
2456
+ size,
2457
+ color,
2458
+ x1: x,
2459
+ y1: y,
2460
+ x2: x,
2461
+ y2: y
2462
+ },
2463
+ editHistory: [],
2464
+ draw: draw$1,
2465
+ isHit
2466
+ };
2467
+ }, [checked, size, color, canvasContextRef]);
2468
+ const onMousemove = useCallback((e) => {
2469
+ if (!checked || !canvasContextRef.current) {
2470
+ return;
2471
+ }
2472
+ if (ellipseEditRef.current) {
2473
+ ellipseEditRef.current.data.x2 = e.clientX;
2474
+ ellipseEditRef.current.data.y2 = e.clientY;
2475
+ if (history.top !== ellipseEditRef.current) {
2476
+ ellipseEditRef.current.source.editHistory.push(ellipseEditRef.current);
2477
+ historyDispatcher.push(ellipseEditRef.current);
2478
+ } else {
2479
+ historyDispatcher.set(history);
2480
+ }
2481
+ } else if (ellipseRef.current) {
2482
+ const {
2483
+ left,
2484
+ top
2485
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
2486
+ ellipseRef.current.data.x2 = e.clientX - left;
2487
+ ellipseRef.current.data.y2 = e.clientY - top;
2488
+ if (history.top !== ellipseRef.current) {
2489
+ historyDispatcher.push(ellipseRef.current);
2490
+ } else {
2491
+ historyDispatcher.set(history);
2492
+ }
2493
+ }
2494
+ }, [checked, canvasContextRef, history, historyDispatcher]);
2495
+ const onMouseup = useCallback(() => {
2496
+ if (!checked) {
2497
+ return;
2498
+ }
2499
+ if (ellipseRef.current) {
2500
+ historyDispatcher.clearSelect();
2501
+ }
2502
+ ellipseRef.current = null;
2503
+ ellipseEditRef.current = null;
2504
+ }, [checked, historyDispatcher]);
2505
+ useDrawSelect(onDrawSelect);
2506
+ useCanvasMousedown(onMousedown);
2507
+ useCanvasMousemove(onMousemove);
2508
+ useCanvasMouseup(onMouseup);
2509
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
2510
+ title: lang.operation_ellipse_title,
2511
+ icon: "icon-ellipse",
2512
+ checked,
2513
+ onClick: onSelectEllipse,
2514
+ option: /* @__PURE__ */ React.createElement(ScreenshotsSizeColor, {
2515
+ size,
2516
+ color,
2517
+ onSizeChange: setSize,
2518
+ onColorChange: setColor,
2519
+ __self: this,
2520
+ __source: {
2521
+ fileName: _jsxFileName$3,
2522
+ lineNumber: 242,
2523
+ columnNumber: 15
2524
+ }
2525
+ }),
2526
+ __self: this,
2527
+ __source: {
2528
+ fileName: _jsxFileName$3,
2529
+ lineNumber: 237,
2530
+ columnNumber: 5
2531
+ }
2532
+ });
2533
+ }
2534
+ function getEditedRectangleData(action) {
2535
+ let { x1, y1, x2, y2 } = action.data;
2536
+ action.editHistory.forEach(({ data }) => {
2537
+ const x = data.x2 - data.x1;
2538
+ const y = data.y2 - data.y1;
2539
+ if (data.type === RectangleEditType.Move) {
2540
+ x1 += x;
2541
+ y1 += y;
2542
+ x2 += x;
2543
+ y2 += y;
2544
+ } else if (data.type === RectangleEditType.ResizeTop) {
2545
+ y1 += y;
2546
+ } else if (data.type === RectangleEditType.ResizeRightTop) {
2547
+ x2 += x;
2548
+ y1 += y;
2549
+ } else if (data.type === RectangleEditType.ResizeRight) {
2550
+ x2 += x;
2551
+ } else if (data.type === RectangleEditType.ResizeRightBottom) {
2552
+ x2 += x;
2553
+ y2 += y;
2554
+ } else if (data.type === RectangleEditType.ResizeBottom) {
2555
+ y2 += y;
2556
+ } else if (data.type === RectangleEditType.ResizeLeftBottom) {
2557
+ x1 += x;
2558
+ y2 += y;
2559
+ } else if (data.type === RectangleEditType.ResizeLeft) {
2560
+ x1 += x;
2561
+ } else if (data.type === RectangleEditType.ResizeLeftTop) {
2562
+ x1 += x;
2563
+ y1 += y;
2564
+ }
2565
+ });
2566
+ return __spreadProps(__spreadValues({}, action.data), {
2567
+ x1,
2568
+ x2,
2569
+ y1,
2570
+ y2
2571
+ });
2572
+ }
2573
+ function draw(ctx, action) {
2574
+ const { size, color, x1, y1, x2, y2 } = getEditedRectangleData(action);
2575
+ ctx.lineCap = "butt";
2576
+ ctx.lineJoin = "miter";
2577
+ ctx.lineWidth = size;
2578
+ ctx.strokeStyle = color;
2579
+ ctx.beginPath();
2580
+ ctx.moveTo(x1, y1);
2581
+ ctx.lineTo(x2, y1);
2582
+ ctx.lineTo(x2, y2);
2583
+ ctx.lineTo(x1, y2);
2584
+ ctx.closePath();
2585
+ ctx.stroke();
2586
+ if (action.isSelected) {
2587
+ ctx.lineWidth = 1;
2588
+ ctx.strokeStyle = "#000000";
2589
+ ctx.fillStyle = "#ffffff";
2590
+ drawDragCircle(ctx, (x1 + x2) / 2, y1);
2591
+ drawDragCircle(ctx, x2, y1);
2592
+ drawDragCircle(ctx, x2, (y1 + y2) / 2);
2593
+ drawDragCircle(ctx, x2, y2);
2594
+ drawDragCircle(ctx, (x1 + x2) / 2, y2);
2595
+ drawDragCircle(ctx, x1, y2);
2596
+ drawDragCircle(ctx, x1, (y1 + y2) / 2);
2597
+ drawDragCircle(ctx, x1, y1);
2598
+ }
2599
+ }
2600
+ var _jsxFileName$2 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/operations/Rectangle/index.tsx";
2601
+ var RectangleEditType;
2602
+ (function(RectangleEditType2) {
2603
+ RectangleEditType2[RectangleEditType2["Move"] = 0] = "Move";
2604
+ RectangleEditType2[RectangleEditType2["ResizeTop"] = 1] = "ResizeTop";
2605
+ RectangleEditType2[RectangleEditType2["ResizeRightTop"] = 2] = "ResizeRightTop";
2606
+ RectangleEditType2[RectangleEditType2["ResizeRight"] = 3] = "ResizeRight";
2607
+ RectangleEditType2[RectangleEditType2["ResizeRightBottom"] = 4] = "ResizeRightBottom";
2608
+ RectangleEditType2[RectangleEditType2["ResizeBottom"] = 5] = "ResizeBottom";
2609
+ RectangleEditType2[RectangleEditType2["ResizeLeftBottom"] = 6] = "ResizeLeftBottom";
2610
+ RectangleEditType2[RectangleEditType2["ResizeLeft"] = 7] = "ResizeLeft";
2611
+ RectangleEditType2[RectangleEditType2["ResizeLeftTop"] = 8] = "ResizeLeftTop";
2612
+ })(RectangleEditType || (RectangleEditType = {}));
2613
+ function Rectangle() {
2614
+ const lang = useLang();
2615
+ const [history, historyDispatcher] = useHistory();
2616
+ const [operation, operationDispatcher] = useOperation();
2617
+ const [, cursorDispatcher] = useCursor();
2618
+ const canvasContextRef = useCanvasContextRef();
2619
+ const [size, setSize] = useState(3);
2620
+ const [color, setColor] = useState("#ee5126");
2621
+ const rectangleRef = useRef(null);
2622
+ const rectangleEditRef = useRef(null);
2623
+ const checked = operation === "Rectangle";
2624
+ const selectRectangle = useCallback(() => {
2625
+ operationDispatcher.set("Rectangle");
2626
+ cursorDispatcher.set("crosshair");
2627
+ }, [operationDispatcher, cursorDispatcher]);
2628
+ const onSelectRectangle = useCallback(() => {
2629
+ if (checked) {
2630
+ return;
2631
+ }
2632
+ selectRectangle();
2633
+ historyDispatcher.clearSelect();
2634
+ }, [checked, selectRectangle, historyDispatcher]);
2635
+ const onDrawSelect = useCallback((action, e) => {
2636
+ if (action.name !== "Rectangle" || !canvasContextRef.current) {
2637
+ return;
2638
+ }
2639
+ const source = action;
2640
+ selectRectangle();
2641
+ const {
2642
+ x1,
2643
+ y1,
2644
+ x2,
2645
+ y2
2646
+ } = getEditedRectangleData(source);
2647
+ let type = 0;
2648
+ if (isHitCircle(canvasContextRef.current.canvas, e, {
2649
+ x: (x1 + x2) / 2,
2650
+ y: y1
2651
+ })) {
2652
+ type = 1;
2653
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2654
+ x: x2,
2655
+ y: y1
2656
+ })) {
2657
+ type = 2;
2658
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2659
+ x: x2,
2660
+ y: (y1 + y2) / 2
2661
+ })) {
2662
+ type = 3;
2663
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2664
+ x: x2,
2665
+ y: y2
2666
+ })) {
2667
+ type = 4;
2668
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2669
+ x: (x1 + x2) / 2,
2670
+ y: y2
2671
+ })) {
2672
+ type = 5;
2673
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2674
+ x: x1,
2675
+ y: y2
2676
+ })) {
2677
+ type = 6;
2678
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2679
+ x: x1,
2680
+ y: (y1 + y2) / 2
2681
+ })) {
2682
+ type = 7;
2683
+ } else if (isHitCircle(canvasContextRef.current.canvas, e, {
2684
+ x: x1,
2685
+ y: y1
2686
+ })) {
2687
+ type = 8;
2688
+ }
2689
+ rectangleEditRef.current = {
2690
+ type: HistoryItemType.Edit,
2691
+ data: {
2692
+ type,
2693
+ x1: e.clientX,
2694
+ y1: e.clientY,
2695
+ x2: e.clientX,
2696
+ y2: e.clientY
2697
+ },
2698
+ source: action
2699
+ };
2700
+ historyDispatcher.select(action);
2701
+ }, [canvasContextRef, selectRectangle, historyDispatcher]);
2702
+ const onMousedown = useCallback((e) => {
2703
+ if (!checked || !canvasContextRef.current || rectangleRef.current) {
2704
+ return;
2705
+ }
2706
+ const {
2707
+ left,
2708
+ top
2709
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
2710
+ const x = e.clientX - left;
2711
+ const y = e.clientY - top;
2712
+ rectangleRef.current = {
2713
+ name: "Rectangle",
2714
+ type: HistoryItemType.Source,
2715
+ data: {
2716
+ size,
2717
+ color,
2718
+ x1: x,
2719
+ y1: y,
2720
+ x2: x,
2721
+ y2: y
2722
+ },
2723
+ editHistory: [],
2724
+ draw,
2725
+ isHit
2726
+ };
2727
+ }, [checked, size, color, canvasContextRef]);
2728
+ const onMousemove = useCallback((e) => {
2729
+ if (!checked || !canvasContextRef.current) {
2730
+ return;
2731
+ }
2732
+ if (rectangleEditRef.current) {
2733
+ rectangleEditRef.current.data.x2 = e.clientX;
2734
+ rectangleEditRef.current.data.y2 = e.clientY;
2735
+ if (history.top !== rectangleEditRef.current) {
2736
+ rectangleEditRef.current.source.editHistory.push(rectangleEditRef.current);
2737
+ historyDispatcher.push(rectangleEditRef.current);
2738
+ } else {
2739
+ historyDispatcher.set(history);
2740
+ }
2741
+ } else if (rectangleRef.current) {
2742
+ const {
2743
+ left,
2744
+ top
2745
+ } = canvasContextRef.current.canvas.getBoundingClientRect();
2746
+ const rectangleData = rectangleRef.current.data;
2747
+ rectangleData.x2 = e.clientX - left;
2748
+ rectangleData.y2 = e.clientY - top;
2749
+ if (history.top !== rectangleRef.current) {
2750
+ historyDispatcher.push(rectangleRef.current);
2751
+ } else {
2752
+ historyDispatcher.set(history);
2753
+ }
2754
+ }
2755
+ }, [checked, canvasContextRef, history, historyDispatcher]);
2756
+ const onMouseup = useCallback(() => {
2757
+ if (!checked) {
2758
+ return;
2759
+ }
2760
+ if (rectangleRef.current) {
2761
+ historyDispatcher.clearSelect();
2762
+ }
2763
+ rectangleRef.current = null;
2764
+ rectangleEditRef.current = null;
2765
+ }, [checked, historyDispatcher]);
2766
+ useDrawSelect(onDrawSelect);
2767
+ useCanvasMousedown(onMousedown);
2768
+ useCanvasMousemove(onMousemove);
2769
+ useCanvasMouseup(onMouseup);
2770
+ return /* @__PURE__ */ React.createElement(ScreenshotsButton, {
2771
+ title: lang.operation_rectangle_title,
2772
+ icon: "icon-rectangle",
2773
+ checked,
2774
+ onClick: onSelectRectangle,
2775
+ option: /* @__PURE__ */ React.createElement(ScreenshotsSizeColor, {
2776
+ size,
2777
+ color,
2778
+ onSizeChange: setSize,
2779
+ onColorChange: setColor,
2780
+ __self: this,
2781
+ __source: {
2782
+ fileName: _jsxFileName$2,
2783
+ lineNumber: 242,
2784
+ columnNumber: 15
2785
+ }
2786
+ }),
2787
+ __self: this,
2788
+ __source: {
2789
+ fileName: _jsxFileName$2,
2790
+ lineNumber: 237,
2791
+ columnNumber: 5
2792
+ }
2793
+ });
2794
+ }
2795
+ var OperationButtons = [Rectangle, Ellipse, Arrow, Brush, Text, Mosaic, "|", Undo, Redo, "|", Save, Cancel, Ok];
2796
+ var index = "";
2797
+ var _jsxFileName$1 = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/ScreenshotsOperations/index.tsx";
2798
+ const ScreenshotsOperationsCtx = React.createContext(null);
2799
+ function ScreenshotsOperations() {
2800
+ const {
2801
+ width,
2802
+ height
2803
+ } = useStore();
2804
+ const [bounds] = useBounds();
2805
+ const [operationsRect, setOperationsRect] = useState(null);
2806
+ const [position, setPosition] = useState(null);
2807
+ const elRef = useRef(null);
2808
+ const onDoubleClick = useCallback((e) => {
2809
+ e.stopPropagation();
2810
+ }, []);
2811
+ const onContextMenu = useCallback((e) => {
2812
+ e.preventDefault();
2813
+ e.stopPropagation();
2814
+ }, []);
2815
+ useEffect(() => {
2816
+ if (!bounds || !elRef.current) {
2817
+ return;
2818
+ }
2819
+ const elRect = elRef.current.getBoundingClientRect();
2820
+ let x = bounds.x + bounds.width - elRect.width;
2821
+ let y = bounds.y + bounds.height + 10;
2822
+ if (x < 0) {
2823
+ x = 0;
2824
+ }
2825
+ if (x > width - elRect.width) {
2826
+ x = width - elRect.width;
2827
+ }
2828
+ if (y > height - elRect.height) {
2829
+ y = height - elRect.height - 10;
2830
+ }
2831
+ if ((position == null ? void 0 : position.x) !== x || position.y !== y) {
2832
+ setPosition({
2833
+ x,
2834
+ y
2835
+ });
2836
+ }
2837
+ if ((operationsRect == null ? void 0 : operationsRect.x) !== elRect.x || operationsRect.y !== elRect.y || operationsRect.width !== elRect.width || operationsRect.height !== elRect.height) {
2838
+ setOperationsRect({
2839
+ x: elRect.x,
2840
+ y: elRect.y,
2841
+ width: elRect.width,
2842
+ height: elRect.height
2843
+ });
2844
+ }
2845
+ });
2846
+ if (!bounds) {
2847
+ return null;
2848
+ }
2849
+ return /* @__PURE__ */ React.createElement(ScreenshotsOperationsCtx.Provider, {
2850
+ value: operationsRect,
2851
+ __self: this,
2852
+ __source: {
2853
+ fileName: _jsxFileName$1,
2854
+ lineNumber: 76,
2855
+ columnNumber: 5
2856
+ }
2857
+ }, /* @__PURE__ */ React.createElement("div", {
2858
+ ref: elRef,
2859
+ className: "screenshots-operations",
2860
+ style: {
2861
+ visibility: position ? "visible" : "hidden",
2862
+ left: position == null ? void 0 : position.x,
2863
+ top: position == null ? void 0 : position.y
2864
+ },
2865
+ onDoubleClick,
2866
+ onContextMenu,
2867
+ __self: this,
2868
+ __source: {
2869
+ fileName: _jsxFileName$1,
2870
+ lineNumber: 77,
2871
+ columnNumber: 7
2872
+ }
2873
+ }, /* @__PURE__ */ React.createElement("div", {
2874
+ className: "screenshots-operations-buttons",
2875
+ __self: this,
2876
+ __source: {
2877
+ fileName: _jsxFileName$1,
2878
+ lineNumber: 88,
2879
+ columnNumber: 9
2880
+ }
2881
+ }, OperationButtons.map((OperationButton, index2) => {
2882
+ if (OperationButton === "|") {
2883
+ return /* @__PURE__ */ React.createElement("div", {
2884
+ key: index2,
2885
+ className: "screenshots-operations-divider",
2886
+ __self: this,
2887
+ __source: {
2888
+ fileName: _jsxFileName$1,
2889
+ lineNumber: 91,
2890
+ columnNumber: 22
2891
+ }
2892
+ });
2893
+ } else {
2894
+ return /* @__PURE__ */ React.createElement(OperationButton, {
2895
+ key: index2,
2896
+ __self: this,
2897
+ __source: {
2898
+ fileName: _jsxFileName$1,
2899
+ lineNumber: 93,
2900
+ columnNumber: 22
2901
+ }
2902
+ });
2903
+ }
2904
+ }))));
2905
+ }
2906
+ var screenshots = "";
2907
+ var iconfont = "";
2908
+ function useGetLoadedImage(url) {
2909
+ const [image, setImage] = useState(null);
2910
+ useEffect(() => {
2911
+ if (url == null) {
2912
+ return;
2913
+ }
2914
+ const $image = document.createElement("img");
2915
+ const onLoad = () => setImage($image);
2916
+ const onError = () => setImage(null);
2917
+ $image.addEventListener("load", onLoad);
2918
+ $image.addEventListener("error", onError);
2919
+ $image.src = url;
2920
+ return () => {
2921
+ $image.removeEventListener("load", onLoad);
2922
+ $image.removeEventListener("error", onError);
2923
+ };
2924
+ }, [url]);
2925
+ return image;
2926
+ }
2927
+ var _jsxFileName = "/Users/nashaofu/Documents/GitHub/screenshots/packages/react-screenshots/src/Screenshots/index.tsx";
2928
+ function Screenshots(_b) {
2929
+ var _c = _b, {
2930
+ url,
2931
+ width,
2932
+ height,
2933
+ lang,
2934
+ className
2935
+ } = _c, props = __objRest(_c, [
2936
+ "url",
2937
+ "width",
2938
+ "height",
2939
+ "lang",
2940
+ "className"
2941
+ ]);
2942
+ const image = useGetLoadedImage(url);
2943
+ const canvasContextRef = useRef(null);
2944
+ const emiterRef = useRef({});
2945
+ const [history, setHistory] = useState({
2946
+ index: -1,
2947
+ stack: []
2948
+ });
2949
+ const [bounds, setBounds] = useState(null);
2950
+ const [cursor, setCursor] = useState("move");
2951
+ const [operation, setOperation] = useState(void 0);
2952
+ const store = {
2953
+ url,
2954
+ width,
2955
+ height,
2956
+ image,
2957
+ lang: __spreadValues(__spreadValues({}, zhCN), lang),
2958
+ emiterRef,
2959
+ canvasContextRef,
2960
+ history,
2961
+ bounds,
2962
+ cursor,
2963
+ operation
2964
+ };
2965
+ const call = useCallback((funcName, ...args) => {
2966
+ const func = props[funcName];
2967
+ if (typeof func === "function") {
2968
+ func(...args);
2969
+ }
2970
+ }, [props]);
2971
+ const dispatcher = {
2972
+ call,
2973
+ setHistory,
2974
+ setBounds,
2975
+ setCursor,
2976
+ setOperation
2977
+ };
2978
+ const classNames = ["screenshots"];
2979
+ if (className) {
2980
+ classNames.push(className);
2981
+ }
2982
+ const reset = () => {
2983
+ emiterRef.current = {};
2984
+ setHistory({
2985
+ index: -1,
2986
+ stack: []
2987
+ });
2988
+ setBounds(null);
2989
+ setCursor("move");
2990
+ setOperation(void 0);
2991
+ };
2992
+ const onDoubleClick = useCallback((e) => {
2993
+ if (e.button !== 0 || !bounds || !canvasContextRef.current) {
2994
+ return;
2995
+ }
2996
+ canvasContextRef.current.canvas.toBlob((blob) => {
2997
+ call("onOk", blob, bounds);
2998
+ reset();
2999
+ }, "image/png");
3000
+ }, [bounds, call]);
3001
+ const onContextMenu = useCallback((e) => {
3002
+ if (e.button !== 2) {
3003
+ return;
3004
+ }
3005
+ e.preventDefault();
3006
+ call("onCancel");
3007
+ reset();
3008
+ }, [call]);
3009
+ return /* @__PURE__ */ React.createElement(ScreenshotsContext.Provider, {
3010
+ value: {
3011
+ store,
3012
+ dispatcher
3013
+ },
3014
+ __self: this,
3015
+ __source: {
3016
+ fileName: _jsxFileName,
3017
+ lineNumber: 111,
3018
+ columnNumber: 5
3019
+ }
3020
+ }, /* @__PURE__ */ React.createElement("div", {
3021
+ className: classNames.join(" "),
3022
+ style: {
3023
+ width,
3024
+ height
3025
+ },
3026
+ onDoubleClick,
3027
+ onContextMenu,
3028
+ __self: this,
3029
+ __source: {
3030
+ fileName: _jsxFileName,
3031
+ lineNumber: 112,
3032
+ columnNumber: 7
3033
+ }
3034
+ }, /* @__PURE__ */ React.createElement(ScreenshotsBackground, {
3035
+ __self: this,
3036
+ __source: {
3037
+ fileName: _jsxFileName,
3038
+ lineNumber: 118,
3039
+ columnNumber: 9
3040
+ }
3041
+ }), /* @__PURE__ */ React.createElement(ScreenshotsCanvas, {
3042
+ ref: canvasContextRef,
3043
+ __self: this,
3044
+ __source: {
3045
+ fileName: _jsxFileName,
3046
+ lineNumber: 119,
3047
+ columnNumber: 9
3048
+ }
3049
+ }), /* @__PURE__ */ React.createElement(ScreenshotsOperations, {
3050
+ __self: this,
3051
+ __source: {
3052
+ fileName: _jsxFileName,
3053
+ lineNumber: 120,
3054
+ columnNumber: 9
3055
+ }
3056
+ })));
3057
+ }
3058
+ export { Screenshots as default };