react-screenshots 0.5.21 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +145 -145
  2. package/dist/electron.html +1 -0
  3. package/dist/index.html +1 -0
  4. package/dist/static/css/electron.7eee95c8.css +1 -0
  5. package/dist/static/css/index.7eee95c8.css +1 -0
  6. package/dist/static/image/image.1ca17a04.jpg +0 -0
  7. package/dist/static/js/589.5602a0fa.js +12 -0
  8. package/dist/static/js/electron.1c6ab61b.js +1 -0
  9. package/dist/static/js/index.fbe72af7.js +1 -0
  10. package/dist/static/js/lib-react.6d1aa3cf.js +2 -0
  11. package/dist/static/js/lib-react.6d1aa3cf.js.LICENSE.txt +39 -0
  12. package/lib/{types → Screenshots}/ScreenshotsBackground/getBoundsByPoints.d.ts +1 -1
  13. package/lib/Screenshots/ScreenshotsBackground/getBoundsByPoints.js +21 -0
  14. package/lib/Screenshots/ScreenshotsBackground/index.d.ts +3 -0
  15. package/lib/Screenshots/ScreenshotsBackground/index.js +100 -0
  16. package/lib/{types → Screenshots}/ScreenshotsButton/index.d.ts +2 -2
  17. package/lib/Screenshots/ScreenshotsButton/index.js +31 -0
  18. package/lib/{types → Screenshots}/ScreenshotsCanvas/getBoundsByPoints.d.ts +1 -1
  19. package/lib/Screenshots/ScreenshotsCanvas/getBoundsByPoints.js +33 -0
  20. package/lib/{types → Screenshots}/ScreenshotsCanvas/getPoints.d.ts +1 -1
  21. package/lib/Screenshots/ScreenshotsCanvas/getPoints.js +57 -0
  22. package/lib/{types → Screenshots}/ScreenshotsCanvas/index.d.ts +1 -2
  23. package/lib/Screenshots/ScreenshotsCanvas/index.js +199 -0
  24. package/lib/{types → Screenshots}/ScreenshotsCanvas/isPointInDraw.d.ts +1 -1
  25. package/lib/Screenshots/ScreenshotsCanvas/isPointInDraw.js +24 -0
  26. package/lib/{types → Screenshots}/ScreenshotsColor/index.d.ts +1 -2
  27. package/lib/Screenshots/ScreenshotsColor/index.js +30 -0
  28. package/lib/{types → Screenshots}/ScreenshotsContext.d.ts +4 -3
  29. package/lib/Screenshots/ScreenshotsContext.js +32 -0
  30. package/lib/{types → Screenshots}/ScreenshotsMagnifier/index.d.ts +1 -2
  31. package/lib/Screenshots/ScreenshotsMagnifier/index.js +99 -0
  32. package/lib/{types → Screenshots}/ScreenshotsOperations/index.d.ts +1 -1
  33. package/lib/Screenshots/ScreenshotsOperations/index.js +64 -0
  34. package/lib/{types → Screenshots}/ScreenshotsOption/index.d.ts +3 -3
  35. package/lib/Screenshots/ScreenshotsOption/index.js +94 -0
  36. package/lib/{types → Screenshots}/ScreenshotsSize/index.d.ts +1 -2
  37. package/lib/Screenshots/ScreenshotsSize/index.js +31 -0
  38. package/lib/{types → Screenshots}/ScreenshotsSizeColor/index.d.ts +2 -3
  39. package/lib/Screenshots/ScreenshotsSizeColor/index.js +21 -0
  40. package/lib/Screenshots/ScreenshotsTextarea/calculateNodeSize.js +69 -0
  41. package/lib/{types → Screenshots}/ScreenshotsTextarea/index.d.ts +2 -2
  42. package/lib/Screenshots/ScreenshotsTextarea/index.js +54 -0
  43. package/lib/{types → Screenshots}/composeImage.d.ts +1 -1
  44. package/lib/Screenshots/composeImage.js +27 -0
  45. package/lib/Screenshots/exports.d.ts +4 -0
  46. package/lib/Screenshots/exports.js +2 -0
  47. package/lib/{types → Screenshots}/hooks/useBounds.d.ts +1 -1
  48. package/lib/Screenshots/hooks/useBounds.js +25 -0
  49. package/lib/Screenshots/hooks/useCall.js +12 -0
  50. package/lib/{types → Screenshots}/hooks/useCanvasContextRef.d.ts +1 -1
  51. package/lib/Screenshots/hooks/useCanvasContextRef.js +6 -0
  52. package/lib/Screenshots/hooks/useCanvasMousedown.js +15 -0
  53. package/lib/Screenshots/hooks/useCanvasMousemove.js +15 -0
  54. package/lib/Screenshots/hooks/useCanvasMouseup.js +15 -0
  55. package/lib/Screenshots/hooks/useCursor.js +25 -0
  56. package/lib/Screenshots/hooks/useDispatcher.d.ts +2 -0
  57. package/lib/Screenshots/hooks/useDispatcher.js +7 -0
  58. package/lib/{types → Screenshots}/hooks/useDrawSelect.d.ts +1 -1
  59. package/lib/Screenshots/hooks/useDrawSelect.js +15 -0
  60. package/lib/{types → Screenshots}/hooks/useEmiter.d.ts +1 -1
  61. package/lib/Screenshots/hooks/useEmiter.js +41 -0
  62. package/lib/{types → Screenshots}/hooks/useHistory.d.ts +1 -1
  63. package/lib/Screenshots/hooks/useHistory.js +122 -0
  64. package/lib/{types → Screenshots}/hooks/useLang.d.ts +1 -1
  65. package/lib/Screenshots/hooks/useLang.js +6 -0
  66. package/lib/Screenshots/hooks/useOperation.js +25 -0
  67. package/lib/Screenshots/hooks/useReset.js +28 -0
  68. package/lib/Screenshots/hooks/useStore.d.ts +2 -0
  69. package/lib/Screenshots/hooks/useStore.js +7 -0
  70. package/lib/{types → Screenshots}/index.d.ts +2 -2
  71. package/lib/Screenshots/index.js +140 -0
  72. package/lib/{types → Screenshots}/operations/Arrow/draw.d.ts +2 -2
  73. package/lib/Screenshots/operations/Arrow/draw.js +51 -0
  74. package/lib/{types → Screenshots}/operations/Arrow/index.d.ts +1 -1
  75. package/lib/Screenshots/operations/Arrow/index.js +153 -0
  76. package/lib/{types → Screenshots}/operations/Brush/draw.d.ts +2 -2
  77. package/lib/Screenshots/operations/Brush/draw.js +31 -0
  78. package/lib/{types → Screenshots}/operations/Brush/index.d.ts +2 -2
  79. package/lib/Screenshots/operations/Brush/index.js +138 -0
  80. package/lib/{types → Screenshots}/operations/Cancel/index.d.ts +1 -1
  81. package/lib/Screenshots/operations/Cancel/index.js +24 -0
  82. package/lib/{types → Screenshots}/operations/Ellipse/draw.d.ts +2 -2
  83. package/lib/Screenshots/operations/Ellipse/draw.js +81 -0
  84. package/lib/{types → Screenshots}/operations/Ellipse/index.d.ts +1 -1
  85. package/lib/Screenshots/operations/Ellipse/index.js +185 -0
  86. package/lib/{types → Screenshots}/operations/Mosaic/index.d.ts +1 -1
  87. package/lib/Screenshots/operations/Mosaic/index.js +174 -0
  88. package/lib/{types → Screenshots}/operations/Ok/index.d.ts +1 -1
  89. package/lib/Screenshots/operations/Ok/index.js +48 -0
  90. package/lib/{types → Screenshots}/operations/Rectangle/draw.d.ts +2 -2
  91. package/lib/Screenshots/operations/Rectangle/draw.js +66 -0
  92. package/lib/{types → Screenshots}/operations/Rectangle/index.d.ts +1 -1
  93. package/lib/Screenshots/operations/Rectangle/index.js +186 -0
  94. package/lib/{types → Screenshots}/operations/Redo/index.d.ts +1 -1
  95. package/lib/Screenshots/operations/Redo/index.js +21 -0
  96. package/lib/{types → Screenshots}/operations/Save/index.d.ts +1 -1
  97. package/lib/Screenshots/operations/Save/index.js +48 -0
  98. package/lib/{types → Screenshots}/operations/Text/index.d.ts +1 -1
  99. package/lib/Screenshots/operations/Text/index.js +220 -0
  100. package/lib/{types → Screenshots}/operations/Undo/index.d.ts +1 -1
  101. package/lib/Screenshots/operations/Undo/index.js +21 -0
  102. package/lib/Screenshots/operations/index.js +27 -0
  103. package/lib/{types → Screenshots}/operations/utils.d.ts +1 -1
  104. package/lib/Screenshots/operations/utils.js +23 -0
  105. package/lib/{types → Screenshots}/types.d.ts +1 -1
  106. package/lib/Screenshots/types.js +6 -0
  107. package/lib/Screenshots/useGetLoadedImage.js +22 -0
  108. package/lib/Screenshots/zh_CN.js +16 -0
  109. package/lib/electron/app.d.ts +10 -0
  110. package/lib/electron/app.js +80 -0
  111. package/lib/electron/index.d.ts +1 -0
  112. package/lib/electron/index.js +7 -0
  113. package/lib/web/app.d.ts +3 -0
  114. package/lib/web/app.js +41 -0
  115. package/lib/web/index.d.ts +1 -0
  116. package/lib/web/index.js +7 -0
  117. package/package.json +35 -41
  118. package/LICENSE +0 -21
  119. package/electron/assets/electron-ed141e06.css +0 -1
  120. package/electron/assets/index-73f470f6.js +0 -53
  121. package/electron/electron.html +0 -14
  122. package/lib/react-screenshots.cjs.js +0 -14
  123. package/lib/react-screenshots.es.js +0 -1716
  124. package/lib/style.css +0 -1
  125. package/lib/types/ScreenshotsBackground/index.d.ts +0 -4
  126. package/lib/types/exports.d.ts +0 -3
  127. package/lib/types/hooks/useDispatcher.d.ts +0 -2
  128. package/lib/types/hooks/useStore.d.ts +0 -2
  129. /package/lib/{types → Screenshots}/ScreenshotsTextarea/calculateNodeSize.d.ts +0 -0
  130. /package/lib/{types → Screenshots}/hooks/useCall.d.ts +0 -0
  131. /package/lib/{types → Screenshots}/hooks/useCanvasMousedown.d.ts +0 -0
  132. /package/lib/{types → Screenshots}/hooks/useCanvasMousemove.d.ts +0 -0
  133. /package/lib/{types → Screenshots}/hooks/useCanvasMouseup.d.ts +0 -0
  134. /package/lib/{types → Screenshots}/hooks/useCursor.d.ts +0 -0
  135. /package/lib/{types → Screenshots}/hooks/useOperation.d.ts +0 -0
  136. /package/lib/{types → Screenshots}/hooks/useReset.d.ts +0 -0
  137. /package/lib/{types → Screenshots}/operations/index.d.ts +0 -0
  138. /package/lib/{types → Screenshots}/useGetLoadedImage.d.ts +0 -0
  139. /package/lib/{types → Screenshots}/zh_CN.d.ts +0 -0
@@ -0,0 +1,138 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback, useRef, useState } from "react";
3
+ import useCanvasMousedown from "../../hooks/useCanvasMousedown.js";
4
+ import useCanvasMousemove from "../../hooks/useCanvasMousemove.js";
5
+ import useCanvasMouseup from "../../hooks/useCanvasMouseup.js";
6
+ import ScreenshotsButton from "../../ScreenshotsButton/index.js";
7
+ import ScreenshotsSizeColor from "../../ScreenshotsSizeColor/index.js";
8
+ import useCursor from "../../hooks/useCursor.js";
9
+ import useOperation from "../../hooks/useOperation.js";
10
+ import useHistory from "../../hooks/useHistory.js";
11
+ import useCanvasContextRef from "../../hooks/useCanvasContextRef.js";
12
+ import { HistoryItemType } from "../../types.js";
13
+ import useDrawSelect from "../../hooks/useDrawSelect.js";
14
+ import { isHit } from "../utils.js";
15
+ import draw from "./draw.js";
16
+ import useLang from "../../hooks/useLang.js";
17
+ function Brush() {
18
+ const lang = useLang();
19
+ const [, cursorDispatcher] = useCursor();
20
+ const [operation, operationDispatcher] = useOperation();
21
+ const canvasContextRef = useCanvasContextRef();
22
+ const [history, historyDispatcher] = useHistory();
23
+ const [size, setSize] = useState(3);
24
+ const [color, setColor] = useState('#ee5126');
25
+ const brushRef = useRef(null);
26
+ const brushEditRef = useRef(null);
27
+ const checked = 'Brush' === operation;
28
+ const selectBrush = useCallback(()=>{
29
+ operationDispatcher.set('Brush');
30
+ cursorDispatcher.set('default');
31
+ }, [
32
+ operationDispatcher,
33
+ cursorDispatcher
34
+ ]);
35
+ const onSelectBrush = useCallback(()=>{
36
+ if (checked) return;
37
+ selectBrush();
38
+ historyDispatcher.clearSelect();
39
+ }, [
40
+ checked,
41
+ selectBrush,
42
+ historyDispatcher
43
+ ]);
44
+ const onDrawSelect = useCallback((action, e)=>{
45
+ if ('Brush' !== action.name) return;
46
+ selectBrush();
47
+ brushEditRef.current = {
48
+ type: HistoryItemType.Edit,
49
+ data: {
50
+ x1: e.clientX,
51
+ y1: e.clientY,
52
+ x2: e.clientX,
53
+ y2: e.clientY
54
+ },
55
+ source: action
56
+ };
57
+ historyDispatcher.select(action);
58
+ }, [
59
+ selectBrush,
60
+ historyDispatcher
61
+ ]);
62
+ const onMousedown = useCallback((e)=>{
63
+ if (!checked || brushRef.current || !canvasContextRef.current) return;
64
+ const { left, top } = canvasContextRef.current.canvas.getBoundingClientRect();
65
+ brushRef.current = {
66
+ name: 'Brush',
67
+ type: HistoryItemType.Source,
68
+ data: {
69
+ size,
70
+ color,
71
+ points: [
72
+ {
73
+ x: e.clientX - left,
74
+ y: e.clientY - top
75
+ }
76
+ ]
77
+ },
78
+ editHistory: [],
79
+ draw: draw,
80
+ isHit: isHit
81
+ };
82
+ }, [
83
+ checked,
84
+ canvasContextRef,
85
+ size,
86
+ color
87
+ ]);
88
+ const onMousemove = useCallback((e)=>{
89
+ if (!checked || !canvasContextRef.current) return;
90
+ if (brushEditRef.current) {
91
+ brushEditRef.current.data.x2 = e.clientX;
92
+ brushEditRef.current.data.y2 = e.clientY;
93
+ if (history.top !== brushEditRef.current) {
94
+ brushEditRef.current.source.editHistory.push(brushEditRef.current);
95
+ historyDispatcher.push(brushEditRef.current);
96
+ } else historyDispatcher.set(history);
97
+ } else if (brushRef.current) {
98
+ const { left, top } = canvasContextRef.current.canvas.getBoundingClientRect();
99
+ brushRef.current.data.points.push({
100
+ x: e.clientX - left,
101
+ y: e.clientY - top
102
+ });
103
+ if (history.top !== brushRef.current) historyDispatcher.push(brushRef.current);
104
+ else historyDispatcher.set(history);
105
+ }
106
+ }, [
107
+ checked,
108
+ history,
109
+ canvasContextRef,
110
+ historyDispatcher
111
+ ]);
112
+ const onMouseup = useCallback(()=>{
113
+ if (!checked) return;
114
+ if (brushRef.current) historyDispatcher.clearSelect();
115
+ brushRef.current = null;
116
+ brushEditRef.current = null;
117
+ }, [
118
+ checked,
119
+ historyDispatcher
120
+ ]);
121
+ useDrawSelect(onDrawSelect);
122
+ useCanvasMousedown(onMousedown);
123
+ useCanvasMousemove(onMousemove);
124
+ useCanvasMouseup(onMouseup);
125
+ return /*#__PURE__*/ jsx(ScreenshotsButton, {
126
+ title: lang.operation_brush_title,
127
+ icon: "icon-brush",
128
+ checked: checked,
129
+ onClick: onSelectBrush,
130
+ option: /*#__PURE__*/ jsx(ScreenshotsSizeColor, {
131
+ size: size,
132
+ color: color,
133
+ onSizeChange: setSize,
134
+ onColorChange: setColor
135
+ })
136
+ });
137
+ }
138
+ export { Brush as default };
@@ -1,2 +1,2 @@
1
- import { ReactElement } from 'react';
1
+ import type { ReactElement } from 'react';
2
2
  export default function Cancel(): ReactElement;
@@ -0,0 +1,24 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback } from "react";
3
+ import useCall from "../../hooks/useCall.js";
4
+ import useLang from "../../hooks/useLang.js";
5
+ import useReset from "../../hooks/useReset.js";
6
+ import ScreenshotsButton from "../../ScreenshotsButton/index.js";
7
+ function Cancel() {
8
+ const call = useCall();
9
+ const reset = useReset();
10
+ const lang = useLang();
11
+ const onClick = useCallback(()=>{
12
+ call('onCancel');
13
+ reset();
14
+ }, [
15
+ call,
16
+ reset
17
+ ]);
18
+ return /*#__PURE__*/ jsx(ScreenshotsButton, {
19
+ title: lang.operation_cancel_title,
20
+ icon: "icon-cancel",
21
+ onClick: onClick
22
+ });
23
+ }
24
+ export { Cancel as default };
@@ -1,5 +1,5 @@
1
- import { EllipseData, EllipseEditData } from '.';
2
- import { HistoryItemSource } from '../../types';
1
+ import type { EllipseData, EllipseEditData } from '.';
2
+ import type { HistoryItemSource } from '../../types';
3
3
  export declare function getEditedEllipseData(action: HistoryItemSource<EllipseData, EllipseEditData>): {
4
4
  x1: number;
5
5
  x2: number;
@@ -0,0 +1,81 @@
1
+ import { EllipseEditType } from "./index.js";
2
+ import { drawDragCircle } from "../utils.js";
3
+ function getEditedEllipseData(action) {
4
+ let { x1, y1, x2, y2 } = action.data;
5
+ action.editHistory.forEach(({ data })=>{
6
+ const x = data.x2 - data.x1;
7
+ const y = data.y2 - data.y1;
8
+ if (data.type === EllipseEditType.Move) {
9
+ x1 += x;
10
+ y1 += y;
11
+ x2 += x;
12
+ y2 += y;
13
+ } else if (data.type === EllipseEditType.ResizeTop) y1 += y;
14
+ else if (data.type === EllipseEditType.ResizeRightTop) {
15
+ x2 += x;
16
+ y1 += y;
17
+ } else if (data.type === EllipseEditType.ResizeRight) x2 += x;
18
+ else if (data.type === EllipseEditType.ResizeRightBottom) {
19
+ x2 += x;
20
+ y2 += y;
21
+ } else if (data.type === EllipseEditType.ResizeBottom) y2 += y;
22
+ else if (data.type === EllipseEditType.ResizeLeftBottom) {
23
+ x1 += x;
24
+ y2 += y;
25
+ } else if (data.type === EllipseEditType.ResizeLeft) x1 += x;
26
+ else if (data.type === EllipseEditType.ResizeLeftTop) {
27
+ x1 += x;
28
+ y1 += y;
29
+ }
30
+ });
31
+ return {
32
+ ...action.data,
33
+ x1,
34
+ x2,
35
+ y1,
36
+ y2
37
+ };
38
+ }
39
+ function draw(ctx, action) {
40
+ const { size, color, x1, y1, x2, y2 } = getEditedEllipseData(action);
41
+ ctx.lineCap = 'butt';
42
+ ctx.lineJoin = 'miter';
43
+ ctx.lineWidth = size;
44
+ ctx.strokeStyle = color;
45
+ const x = (x1 + x2) / 2;
46
+ const y = (y1 + y2) / 2;
47
+ const rx = Math.abs(x2 - x1) / 2;
48
+ const ry = Math.abs(y2 - y1) / 2;
49
+ const k = 0.5522848;
50
+ const ox = rx * k;
51
+ const oy = ry * k;
52
+ ctx.beginPath();
53
+ ctx.moveTo(x - rx, y);
54
+ ctx.bezierCurveTo(x - rx, y - oy, x - ox, y - ry, x, y - ry);
55
+ ctx.bezierCurveTo(x + ox, y - ry, x + rx, y - oy, x + rx, y);
56
+ ctx.bezierCurveTo(x + rx, y + oy, x + ox, y + ry, x, y + ry);
57
+ ctx.bezierCurveTo(x - ox, y + ry, x - rx, y + oy, x - rx, y);
58
+ ctx.closePath();
59
+ ctx.stroke();
60
+ if (action.isSelected) {
61
+ ctx.lineWidth = 1;
62
+ ctx.strokeStyle = '#000000';
63
+ ctx.fillStyle = '#ffffff';
64
+ ctx.beginPath();
65
+ ctx.moveTo(x1, y1);
66
+ ctx.lineTo(x2, y1);
67
+ ctx.lineTo(x2, y2);
68
+ ctx.lineTo(x1, y2);
69
+ ctx.closePath();
70
+ ctx.stroke();
71
+ drawDragCircle(ctx, (x1 + x2) / 2, y1);
72
+ drawDragCircle(ctx, x2, y1);
73
+ drawDragCircle(ctx, x2, (y1 + y2) / 2);
74
+ drawDragCircle(ctx, x2, y2);
75
+ drawDragCircle(ctx, (x1 + x2) / 2, y2);
76
+ drawDragCircle(ctx, x1, y2);
77
+ drawDragCircle(ctx, x1, (y1 + y2) / 2);
78
+ drawDragCircle(ctx, x1, y1);
79
+ }
80
+ }
81
+ export { draw as default, getEditedEllipseData };
@@ -1,4 +1,4 @@
1
- import { ReactElement } from 'react';
1
+ import type { ReactElement } from 'react';
2
2
  export interface EllipseData {
3
3
  size: number;
4
4
  color: string;
@@ -0,0 +1,185 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback, useRef, useState } from "react";
3
+ import useCanvasContextRef from "../../hooks/useCanvasContextRef.js";
4
+ import useCanvasMousedown from "../../hooks/useCanvasMousedown.js";
5
+ import useCanvasMousemove from "../../hooks/useCanvasMousemove.js";
6
+ import useCanvasMouseup from "../../hooks/useCanvasMouseup.js";
7
+ import useCursor from "../../hooks/useCursor.js";
8
+ import useDrawSelect from "../../hooks/useDrawSelect.js";
9
+ import useHistory from "../../hooks/useHistory.js";
10
+ import useLang from "../../hooks/useLang.js";
11
+ import useOperation from "../../hooks/useOperation.js";
12
+ import ScreenshotsButton from "../../ScreenshotsButton/index.js";
13
+ import ScreenshotsSizeColor from "../../ScreenshotsSizeColor/index.js";
14
+ import { HistoryItemType } from "../../types.js";
15
+ import { isHit, isHitCircle } from "../utils.js";
16
+ import draw, { getEditedEllipseData } from "./draw.js";
17
+ var Ellipse_EllipseEditType = /*#__PURE__*/ function(EllipseEditType) {
18
+ EllipseEditType[EllipseEditType["Move"] = 0] = "Move";
19
+ EllipseEditType[EllipseEditType["ResizeTop"] = 1] = "ResizeTop";
20
+ EllipseEditType[EllipseEditType["ResizeRightTop"] = 2] = "ResizeRightTop";
21
+ EllipseEditType[EllipseEditType["ResizeRight"] = 3] = "ResizeRight";
22
+ EllipseEditType[EllipseEditType["ResizeRightBottom"] = 4] = "ResizeRightBottom";
23
+ EllipseEditType[EllipseEditType["ResizeBottom"] = 5] = "ResizeBottom";
24
+ EllipseEditType[EllipseEditType["ResizeLeftBottom"] = 6] = "ResizeLeftBottom";
25
+ EllipseEditType[EllipseEditType["ResizeLeft"] = 7] = "ResizeLeft";
26
+ EllipseEditType[EllipseEditType["ResizeLeftTop"] = 8] = "ResizeLeftTop";
27
+ return EllipseEditType;
28
+ }({});
29
+ function Ellipse() {
30
+ const lang = useLang();
31
+ const [history, historyDispatcher] = useHistory();
32
+ const [operation, operationDispatcher] = useOperation();
33
+ const [, cursorDispatcher] = useCursor();
34
+ const canvasContextRef = useCanvasContextRef();
35
+ const [size, setSize] = useState(3);
36
+ const [color, setColor] = useState('#ee5126');
37
+ const ellipseRef = useRef(null);
38
+ const ellipseEditRef = useRef(null);
39
+ const checked = 'Ellipse' === operation;
40
+ const selectEllipse = useCallback(()=>{
41
+ operationDispatcher.set('Ellipse');
42
+ cursorDispatcher.set('crosshair');
43
+ }, [
44
+ operationDispatcher,
45
+ cursorDispatcher
46
+ ]);
47
+ const onSelectEllipse = useCallback(()=>{
48
+ if (checked) return;
49
+ selectEllipse();
50
+ historyDispatcher.clearSelect();
51
+ }, [
52
+ checked,
53
+ selectEllipse,
54
+ historyDispatcher
55
+ ]);
56
+ const onDrawSelect = useCallback((action, e)=>{
57
+ if ('Ellipse' !== action.name || !canvasContextRef.current) return;
58
+ const source = action;
59
+ selectEllipse();
60
+ const { x1, y1, x2, y2 } = getEditedEllipseData(source);
61
+ let type = 0;
62
+ if (isHitCircle(canvasContextRef.current.canvas, e, {
63
+ x: (x1 + x2) / 2,
64
+ y: y1
65
+ })) type = 1;
66
+ else if (isHitCircle(canvasContextRef.current.canvas, e, {
67
+ x: x2,
68
+ y: y1
69
+ })) type = 2;
70
+ else if (isHitCircle(canvasContextRef.current.canvas, e, {
71
+ x: x2,
72
+ y: (y1 + y2) / 2
73
+ })) type = 3;
74
+ else if (isHitCircle(canvasContextRef.current.canvas, e, {
75
+ x: x2,
76
+ y: y2
77
+ })) type = 4;
78
+ else if (isHitCircle(canvasContextRef.current.canvas, e, {
79
+ x: (x1 + x2) / 2,
80
+ y: y2
81
+ })) type = 5;
82
+ else if (isHitCircle(canvasContextRef.current.canvas, e, {
83
+ x: x1,
84
+ y: y2
85
+ })) type = 6;
86
+ else if (isHitCircle(canvasContextRef.current.canvas, e, {
87
+ x: x1,
88
+ y: (y1 + y2) / 2
89
+ })) type = 7;
90
+ else if (isHitCircle(canvasContextRef.current.canvas, e, {
91
+ x: x1,
92
+ y: y1
93
+ })) type = 8;
94
+ ellipseEditRef.current = {
95
+ type: HistoryItemType.Edit,
96
+ data: {
97
+ type,
98
+ x1: e.clientX,
99
+ y1: e.clientY,
100
+ x2: e.clientX,
101
+ y2: e.clientY
102
+ },
103
+ source
104
+ };
105
+ historyDispatcher.select(action);
106
+ }, [
107
+ canvasContextRef,
108
+ selectEllipse,
109
+ historyDispatcher
110
+ ]);
111
+ const onMousedown = useCallback((e)=>{
112
+ if (!checked || !canvasContextRef.current || ellipseRef.current) return;
113
+ const { left, top } = canvasContextRef.current.canvas.getBoundingClientRect();
114
+ const x = e.clientX - left;
115
+ const y = e.clientY - top;
116
+ ellipseRef.current = {
117
+ name: 'Ellipse',
118
+ type: HistoryItemType.Source,
119
+ data: {
120
+ size,
121
+ color,
122
+ x1: x,
123
+ y1: y,
124
+ x2: x,
125
+ y2: y
126
+ },
127
+ editHistory: [],
128
+ draw: draw,
129
+ isHit: isHit
130
+ };
131
+ }, [
132
+ checked,
133
+ size,
134
+ color,
135
+ canvasContextRef
136
+ ]);
137
+ const onMousemove = useCallback((e)=>{
138
+ if (!checked || !canvasContextRef.current) return;
139
+ if (ellipseEditRef.current) {
140
+ ellipseEditRef.current.data.x2 = e.clientX;
141
+ ellipseEditRef.current.data.y2 = e.clientY;
142
+ if (history.top !== ellipseEditRef.current) {
143
+ ellipseEditRef.current.source.editHistory.push(ellipseEditRef.current);
144
+ historyDispatcher.push(ellipseEditRef.current);
145
+ } else historyDispatcher.set(history);
146
+ } else if (ellipseRef.current) {
147
+ const { left, top } = canvasContextRef.current.canvas.getBoundingClientRect();
148
+ ellipseRef.current.data.x2 = e.clientX - left;
149
+ ellipseRef.current.data.y2 = e.clientY - top;
150
+ if (history.top !== ellipseRef.current) historyDispatcher.push(ellipseRef.current);
151
+ else historyDispatcher.set(history);
152
+ }
153
+ }, [
154
+ checked,
155
+ canvasContextRef,
156
+ history,
157
+ historyDispatcher
158
+ ]);
159
+ const onMouseup = useCallback(()=>{
160
+ if (!checked) return;
161
+ if (ellipseRef.current) historyDispatcher.clearSelect();
162
+ ellipseRef.current = null;
163
+ ellipseEditRef.current = null;
164
+ }, [
165
+ checked,
166
+ historyDispatcher
167
+ ]);
168
+ useDrawSelect(onDrawSelect);
169
+ useCanvasMousedown(onMousedown);
170
+ useCanvasMousemove(onMousemove);
171
+ useCanvasMouseup(onMouseup);
172
+ return /*#__PURE__*/ jsx(ScreenshotsButton, {
173
+ title: lang.operation_ellipse_title,
174
+ icon: "icon-ellipse",
175
+ checked: checked,
176
+ onClick: onSelectEllipse,
177
+ option: /*#__PURE__*/ jsx(ScreenshotsSizeColor, {
178
+ size: size,
179
+ color: color,
180
+ onSizeChange: setSize,
181
+ onColorChange: setColor
182
+ })
183
+ });
184
+ }
185
+ export { Ellipse_EllipseEditType as EllipseEditType, Ellipse as default };
@@ -1,4 +1,4 @@
1
- import { ReactElement } from 'react';
1
+ import type { ReactElement } from 'react';
2
2
  export interface MosaicTile {
3
3
  x: number;
4
4
  y: number;
@@ -0,0 +1,174 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ import ScreenshotsButton from "../../ScreenshotsButton/index.js";
4
+ import ScreenshotsSize from "../../ScreenshotsSize/index.js";
5
+ import useCanvasMousedown from "../../hooks/useCanvasMousedown.js";
6
+ import useCanvasMousemove from "../../hooks/useCanvasMousemove.js";
7
+ import useCanvasMouseup from "../../hooks/useCanvasMouseup.js";
8
+ import { HistoryItemType } from "../../types.js";
9
+ import useOperation from "../../hooks/useOperation.js";
10
+ import useCursor from "../../hooks/useCursor.js";
11
+ import useStore from "../../hooks/useStore.js";
12
+ import useBounds from "../../hooks/useBounds.js";
13
+ import useHistory from "../../hooks/useHistory.js";
14
+ import useCanvasContextRef from "../../hooks/useCanvasContextRef.js";
15
+ import useLang from "../../hooks/useLang.js";
16
+ function getColor(x, y, imageData) {
17
+ if (!imageData) return [
18
+ 0,
19
+ 0,
20
+ 0,
21
+ 0
22
+ ];
23
+ const { data, width } = imageData;
24
+ const index = y * width * 4 + 4 * x;
25
+ return Array.from(data.slice(index, index + 4));
26
+ }
27
+ function draw(ctx, action) {
28
+ const { tiles, size } = action.data;
29
+ tiles.forEach((tile)=>{
30
+ const r = Math.round(tile.color[0]);
31
+ const g = Math.round(tile.color[1]);
32
+ const b = Math.round(tile.color[2]);
33
+ const a = tile.color[3] / 255;
34
+ ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${a})`;
35
+ ctx.fillRect(tile.x - size / 2, tile.y - size / 2, size, size);
36
+ });
37
+ }
38
+ function Mosaic() {
39
+ const lang = useLang();
40
+ const { image, width, height } = useStore();
41
+ const [operation, operationDispatcher] = useOperation();
42
+ const canvasContextRef = useCanvasContextRef();
43
+ const [history, historyDispatcher] = useHistory();
44
+ const [bounds] = useBounds();
45
+ const [, cursorDispatcher] = useCursor();
46
+ const [size, setSize] = useState(3);
47
+ const imageDataRef = useRef(null);
48
+ const mosaicRef = useRef(null);
49
+ const checked = 'Mosaic' === operation;
50
+ const selectMosaic = useCallback(()=>{
51
+ operationDispatcher.set('Mosaic');
52
+ cursorDispatcher.set('crosshair');
53
+ }, [
54
+ operationDispatcher,
55
+ cursorDispatcher
56
+ ]);
57
+ const onSelectMosaic = useCallback(()=>{
58
+ if (checked) return;
59
+ selectMosaic();
60
+ historyDispatcher.clearSelect();
61
+ }, [
62
+ checked,
63
+ selectMosaic,
64
+ historyDispatcher
65
+ ]);
66
+ const onMousedown = useCallback((e)=>{
67
+ if (!checked || mosaicRef.current || !imageDataRef.current || !canvasContextRef.current) return;
68
+ const rect = canvasContextRef.current.canvas.getBoundingClientRect();
69
+ const x = e.clientX - rect.x;
70
+ const y = e.clientY - rect.y;
71
+ const mosaicSize = 2 * size;
72
+ mosaicRef.current = {
73
+ name: 'Mosaic',
74
+ type: HistoryItemType.Source,
75
+ data: {
76
+ size: mosaicSize,
77
+ tiles: [
78
+ {
79
+ x,
80
+ y,
81
+ color: getColor(x, y, imageDataRef.current)
82
+ }
83
+ ]
84
+ },
85
+ editHistory: [],
86
+ draw
87
+ };
88
+ }, [
89
+ checked,
90
+ size,
91
+ canvasContextRef
92
+ ]);
93
+ const onMousemove = useCallback((e)=>{
94
+ if (!checked || !mosaicRef.current || !canvasContextRef.current || !imageDataRef.current) return;
95
+ const rect = canvasContextRef.current.canvas.getBoundingClientRect();
96
+ const x = e.clientX - rect.x;
97
+ const y = e.clientY - rect.y;
98
+ const mosaicSize = mosaicRef.current.data.size;
99
+ const mosaicTiles = mosaicRef.current.data.tiles;
100
+ let lastTile = mosaicTiles[mosaicTiles.length - 1];
101
+ if (lastTile) {
102
+ const dx = lastTile.x - x;
103
+ const dy = lastTile.y - y;
104
+ let length = Math.sqrt(dx ** 2 + dy ** 2);
105
+ const sin = -dy / length;
106
+ const cos = -dx / length;
107
+ while(length > mosaicSize){
108
+ const cx = Math.floor(lastTile.x + mosaicSize * cos);
109
+ const cy = Math.floor(lastTile.y + mosaicSize * sin);
110
+ lastTile = {
111
+ x: cx,
112
+ y: cy,
113
+ color: getColor(cx, cy, imageDataRef.current)
114
+ };
115
+ mosaicTiles.push(lastTile);
116
+ length -= mosaicSize;
117
+ }
118
+ if (length > mosaicSize / 2) mosaicTiles.push({
119
+ x,
120
+ y,
121
+ color: getColor(x, y, imageDataRef.current)
122
+ });
123
+ } else mosaicTiles.push({
124
+ x,
125
+ y,
126
+ color: getColor(x, y, imageDataRef.current)
127
+ });
128
+ if (history.top !== mosaicRef.current) historyDispatcher.push(mosaicRef.current);
129
+ else historyDispatcher.set(history);
130
+ }, [
131
+ checked,
132
+ canvasContextRef,
133
+ history,
134
+ historyDispatcher
135
+ ]);
136
+ const onMouseup = useCallback(()=>{
137
+ if (!checked) return;
138
+ mosaicRef.current = null;
139
+ }, [
140
+ checked
141
+ ]);
142
+ useCanvasMousedown(onMousedown);
143
+ useCanvasMousemove(onMousemove);
144
+ useCanvasMouseup(onMouseup);
145
+ useEffect(()=>{
146
+ if (!bounds || !image || !checked) return;
147
+ const $canvas = document.createElement('canvas');
148
+ const canvasContext = $canvas.getContext('2d');
149
+ if (!canvasContext) return;
150
+ $canvas.width = bounds.width;
151
+ $canvas.height = bounds.height;
152
+ const rx = image.naturalWidth / width;
153
+ const ry = image.naturalHeight / height;
154
+ canvasContext.drawImage(image, bounds.x * rx, bounds.y * ry, bounds.width * rx, bounds.height * ry, 0, 0, bounds.width, bounds.height);
155
+ imageDataRef.current = canvasContext.getImageData(0, 0, bounds.width, bounds.height);
156
+ }, [
157
+ width,
158
+ height,
159
+ bounds,
160
+ image,
161
+ checked
162
+ ]);
163
+ return /*#__PURE__*/ jsx(ScreenshotsButton, {
164
+ title: lang.operation_mosaic_title,
165
+ icon: "icon-mosaic",
166
+ checked: checked,
167
+ onClick: onSelectMosaic,
168
+ option: /*#__PURE__*/ jsx(ScreenshotsSize, {
169
+ value: size,
170
+ onChange: setSize
171
+ })
172
+ });
173
+ }
174
+ export { Mosaic as default };
@@ -1,2 +1,2 @@
1
- import { ReactElement } from 'react';
1
+ import type { ReactElement } from 'react';
2
2
  export default function Ok(): ReactElement;
@@ -0,0 +1,48 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback } from "react";
3
+ import useStore from "../../hooks/useStore.js";
4
+ import useCall from "../../hooks/useCall.js";
5
+ import useCanvasContextRef from "../../hooks/useCanvasContextRef.js";
6
+ import useHistory from "../../hooks/useHistory.js";
7
+ import useReset from "../../hooks/useReset.js";
8
+ import ScreenshotsButton from "../../ScreenshotsButton/index.js";
9
+ import composeImage from "../../composeImage.js";
10
+ function Ok() {
11
+ const { image, width, height, history, bounds, lang } = useStore();
12
+ const canvasContextRef = useCanvasContextRef();
13
+ const [, historyDispatcher] = useHistory();
14
+ const call = useCall();
15
+ const reset = useReset();
16
+ const onClick = useCallback(()=>{
17
+ historyDispatcher.clearSelect();
18
+ setTimeout(()=>{
19
+ if (!canvasContextRef.current || !image || !bounds) return;
20
+ composeImage({
21
+ image,
22
+ width,
23
+ height,
24
+ history,
25
+ bounds
26
+ }).then((blob)=>{
27
+ call('onOk', blob, bounds);
28
+ reset();
29
+ });
30
+ });
31
+ }, [
32
+ canvasContextRef,
33
+ historyDispatcher,
34
+ image,
35
+ width,
36
+ height,
37
+ history,
38
+ bounds,
39
+ call,
40
+ reset
41
+ ]);
42
+ return /*#__PURE__*/ jsx(ScreenshotsButton, {
43
+ title: lang.operation_ok_title,
44
+ icon: "icon-ok",
45
+ onClick: onClick
46
+ });
47
+ }
48
+ export { Ok as default };