react-screenshots 0.5.16 → 0.5.18

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