react-screenshots 0.5.15 → 0.5.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/package.json +2 -2
  2. package/electron/assets/index.7793f29e.js +0 -222
  3. package/electron/assets/index.78c5dcbf.css +0 -1
  4. package/electron/electron.html +0 -14
  5. package/lib/react-screenshots.cjs.js +0 -14
  6. package/lib/react-screenshots.es.js +0 -3166
  7. package/lib/style.css +0 -1
  8. package/lib/types/ScreenshotsBackground/getBoundsByPoints.d.ts +0 -2
  9. package/lib/types/ScreenshotsBackground/index.d.ts +0 -4
  10. package/lib/types/ScreenshotsButton/index.d.ts +0 -12
  11. package/lib/types/ScreenshotsCanvas/getBoundsByPoints.d.ts +0 -2
  12. package/lib/types/ScreenshotsCanvas/getPoints.d.ts +0 -2
  13. package/lib/types/ScreenshotsCanvas/index.d.ts +0 -15
  14. package/lib/types/ScreenshotsCanvas/isPointInDraw.d.ts +0 -2
  15. package/lib/types/ScreenshotsColor/index.d.ts +0 -8
  16. package/lib/types/ScreenshotsContext.d.ts +0 -29
  17. package/lib/types/ScreenshotsMagnifier/index.d.ts +0 -8
  18. package/lib/types/ScreenshotsOperations/index.d.ts +0 -6
  19. package/lib/types/ScreenshotsOption/index.d.ts +0 -15
  20. package/lib/types/ScreenshotsSize/index.d.ts +0 -8
  21. package/lib/types/ScreenshotsSizeColor/index.d.ts +0 -10
  22. package/lib/types/ScreenshotsTextarea/calculateNodeSize.d.ts +0 -17
  23. package/lib/types/ScreenshotsTextarea/index.d.ts +0 -15
  24. package/lib/types/composeImage.d.ts +0 -10
  25. package/lib/types/exports.d.ts +0 -3
  26. package/lib/types/hooks/useBounds.d.ts +0 -7
  27. package/lib/types/hooks/useCall.d.ts +0 -2
  28. package/lib/types/hooks/useCanvasContextRef.d.ts +0 -2
  29. package/lib/types/hooks/useCanvasMousedown.d.ts +0 -1
  30. package/lib/types/hooks/useCanvasMousemove.d.ts +0 -1
  31. package/lib/types/hooks/useCanvasMouseup.d.ts +0 -1
  32. package/lib/types/hooks/useCursor.d.ts +0 -6
  33. package/lib/types/hooks/useDispatcher.d.ts +0 -2
  34. package/lib/types/hooks/useDrawSelect.d.ts +0 -2
  35. package/lib/types/hooks/useEmiter.d.ts +0 -8
  36. package/lib/types/hooks/useHistory.d.ts +0 -16
  37. package/lib/types/hooks/useLang.d.ts +0 -2
  38. package/lib/types/hooks/useOperation.d.ts +0 -6
  39. package/lib/types/hooks/useReset.d.ts +0 -2
  40. package/lib/types/hooks/useStore.d.ts +0 -2
  41. package/lib/types/index.d.ts +0 -13
  42. package/lib/types/operations/Arrow/draw.d.ts +0 -11
  43. package/lib/types/operations/Arrow/index.d.ts +0 -22
  44. package/lib/types/operations/Brush/draw.d.ts +0 -3
  45. package/lib/types/operations/Brush/index.d.ts +0 -14
  46. package/lib/types/operations/Cancel/index.d.ts +0 -2
  47. package/lib/types/operations/Ellipse/draw.d.ts +0 -11
  48. package/lib/types/operations/Ellipse/index.d.ts +0 -28
  49. package/lib/types/operations/Mosaic/index.d.ts +0 -11
  50. package/lib/types/operations/Ok/index.d.ts +0 -2
  51. package/lib/types/operations/Rectangle/draw.d.ts +0 -11
  52. package/lib/types/operations/Rectangle/index.d.ts +0 -28
  53. package/lib/types/operations/Redo/index.d.ts +0 -2
  54. package/lib/types/operations/Save/index.d.ts +0 -2
  55. package/lib/types/operations/Text/index.d.ts +0 -22
  56. package/lib/types/operations/Undo/index.d.ts +0 -2
  57. package/lib/types/operations/index.d.ts +0 -3
  58. package/lib/types/operations/utils.d.ts +0 -4
  59. package/lib/types/types.d.ts +0 -39
  60. package/lib/types/useGetLoadedImage.d.ts +0 -1
  61. package/lib/types/zh_CN.d.ts +0 -16
@@ -1,3166 +0,0 @@
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
- }), 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 };