react-native-image-editor-skia 0.1.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.
- package/LICENSE +21 -0
- package/README.md +202 -0
- package/lib/commonjs/ImageEditor.js +141 -0
- package/lib/commonjs/ImageEditor.js.map +1 -0
- package/lib/commonjs/annotations/AnnotationView.js +42 -0
- package/lib/commonjs/annotations/AnnotationView.js.map +1 -0
- package/lib/commonjs/annotations/ArrowAnnotation.js +29 -0
- package/lib/commonjs/annotations/ArrowAnnotation.js.map +1 -0
- package/lib/commonjs/annotations/CircleAnnotation.js +31 -0
- package/lib/commonjs/annotations/CircleAnnotation.js.map +1 -0
- package/lib/commonjs/annotations/FreehandAnnotation.js +29 -0
- package/lib/commonjs/annotations/FreehandAnnotation.js.map +1 -0
- package/lib/commonjs/annotations/MarkerAnnotation.js +27 -0
- package/lib/commonjs/annotations/MarkerAnnotation.js.map +1 -0
- package/lib/commonjs/annotations/RotatedGroup.js +34 -0
- package/lib/commonjs/annotations/RotatedGroup.js.map +1 -0
- package/lib/commonjs/annotations/TextAnnotation.js +40 -0
- package/lib/commonjs/annotations/TextAnnotation.js.map +1 -0
- package/lib/commonjs/annotations/geometry.js +73 -0
- package/lib/commonjs/annotations/geometry.js.map +1 -0
- package/lib/commonjs/annotations/geometryPure.js +104 -0
- package/lib/commonjs/annotations/geometryPure.js.map +1 -0
- package/lib/commonjs/canvas/AnnotationLayer.js +58 -0
- package/lib/commonjs/canvas/AnnotationLayer.js.map +1 -0
- package/lib/commonjs/canvas/BaseImageLayer.js +27 -0
- package/lib/commonjs/canvas/BaseImageLayer.js.map +1 -0
- package/lib/commonjs/canvas/CropOverlay.js +135 -0
- package/lib/commonjs/canvas/CropOverlay.js.map +1 -0
- package/lib/commonjs/canvas/EditorCanvas.js +91 -0
- package/lib/commonjs/canvas/EditorCanvas.js.map +1 -0
- package/lib/commonjs/canvas/InFlightLayer.js +152 -0
- package/lib/commonjs/canvas/InFlightLayer.js.map +1 -0
- package/lib/commonjs/canvas/SelectionOverlay.js +90 -0
- package/lib/commonjs/canvas/SelectionOverlay.js.map +1 -0
- package/lib/commonjs/constants.js +56 -0
- package/lib/commonjs/constants.js.map +1 -0
- package/lib/commonjs/context/EditorContext.js +132 -0
- package/lib/commonjs/context/EditorContext.js.map +1 -0
- package/lib/commonjs/export/drawScene.js +97 -0
- package/lib/commonjs/export/drawScene.js.map +1 -0
- package/lib/commonjs/export/exportImage.js +92 -0
- package/lib/commonjs/export/exportImage.js.map +1 -0
- package/lib/commonjs/gestures/applyTransform.js +79 -0
- package/lib/commonjs/gestures/applyTransform.js.map +1 -0
- package/lib/commonjs/gestures/createAnnotation.js +73 -0
- package/lib/commonjs/gestures/createAnnotation.js.map +1 -0
- package/lib/commonjs/gestures/handles.js +53 -0
- package/lib/commonjs/gestures/handles.js.map +1 -0
- package/lib/commonjs/gestures/hitTest.js +72 -0
- package/lib/commonjs/gestures/hitTest.js.map +1 -0
- package/lib/commonjs/gestures/useCropGesture.js +149 -0
- package/lib/commonjs/gestures/useCropGesture.js.map +1 -0
- package/lib/commonjs/gestures/useEditorGestures.js +289 -0
- package/lib/commonjs/gestures/useEditorGestures.js.map +1 -0
- package/lib/commonjs/image/disposeRegistry.js +63 -0
- package/lib/commonjs/image/disposeRegistry.js.map +1 -0
- package/lib/commonjs/image/useLoadedImage.js +121 -0
- package/lib/commonjs/image/useLoadedImage.js.map +1 -0
- package/lib/commonjs/index.js +52 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/state/history.js +85 -0
- package/lib/commonjs/state/history.js.map +1 -0
- package/lib/commonjs/state/selectors.js +19 -0
- package/lib/commonjs/state/selectors.js.map +1 -0
- package/lib/commonjs/state/useEditorReducer.js +83 -0
- package/lib/commonjs/state/useEditorReducer.js.map +1 -0
- package/lib/commonjs/toolbar/ColorPicker.js +84 -0
- package/lib/commonjs/toolbar/ColorPicker.js.map +1 -0
- package/lib/commonjs/toolbar/CropControls.js +65 -0
- package/lib/commonjs/toolbar/CropControls.js.map +1 -0
- package/lib/commonjs/toolbar/RotationSlider.js +73 -0
- package/lib/commonjs/toolbar/RotationSlider.js.map +1 -0
- package/lib/commonjs/toolbar/TextInputOverlay.js +108 -0
- package/lib/commonjs/toolbar/TextInputOverlay.js.map +1 -0
- package/lib/commonjs/toolbar/ToolButton.js +56 -0
- package/lib/commonjs/toolbar/ToolButton.js.map +1 -0
- package/lib/commonjs/toolbar/Toolbar.js +137 -0
- package/lib/commonjs/toolbar/Toolbar.js.map +1 -0
- package/lib/commonjs/types.js +47 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils/color.js +37 -0
- package/lib/commonjs/utils/color.js.map +1 -0
- package/lib/commonjs/utils/id.js +14 -0
- package/lib/commonjs/utils/id.js.map +1 -0
- package/lib/commonjs/utils/math.js +277 -0
- package/lib/commonjs/utils/math.js.map +1 -0
- package/lib/module/ImageEditor.js +138 -0
- package/lib/module/ImageEditor.js.map +1 -0
- package/lib/module/annotations/AnnotationView.js +39 -0
- package/lib/module/annotations/AnnotationView.js.map +1 -0
- package/lib/module/annotations/ArrowAnnotation.js +26 -0
- package/lib/module/annotations/ArrowAnnotation.js.map +1 -0
- package/lib/module/annotations/CircleAnnotation.js +27 -0
- package/lib/module/annotations/CircleAnnotation.js.map +1 -0
- package/lib/module/annotations/FreehandAnnotation.js +25 -0
- package/lib/module/annotations/FreehandAnnotation.js.map +1 -0
- package/lib/module/annotations/MarkerAnnotation.js +23 -0
- package/lib/module/annotations/MarkerAnnotation.js.map +1 -0
- package/lib/module/annotations/RotatedGroup.js +29 -0
- package/lib/module/annotations/RotatedGroup.js.map +1 -0
- package/lib/module/annotations/TextAnnotation.js +37 -0
- package/lib/module/annotations/TextAnnotation.js.map +1 -0
- package/lib/module/annotations/geometry.js +56 -0
- package/lib/module/annotations/geometry.js.map +1 -0
- package/lib/module/annotations/geometryPure.js +100 -0
- package/lib/module/annotations/geometryPure.js.map +1 -0
- package/lib/module/canvas/AnnotationLayer.js +55 -0
- package/lib/module/canvas/AnnotationLayer.js.map +1 -0
- package/lib/module/canvas/BaseImageLayer.js +23 -0
- package/lib/module/canvas/BaseImageLayer.js.map +1 -0
- package/lib/module/canvas/CropOverlay.js +131 -0
- package/lib/module/canvas/CropOverlay.js.map +1 -0
- package/lib/module/canvas/EditorCanvas.js +88 -0
- package/lib/module/canvas/EditorCanvas.js.map +1 -0
- package/lib/module/canvas/InFlightLayer.js +149 -0
- package/lib/module/canvas/InFlightLayer.js.map +1 -0
- package/lib/module/canvas/SelectionOverlay.js +85 -0
- package/lib/module/canvas/SelectionOverlay.js.map +1 -0
- package/lib/module/constants.js +52 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/context/EditorContext.js +126 -0
- package/lib/module/context/EditorContext.js.map +1 -0
- package/lib/module/export/drawScene.js +93 -0
- package/lib/module/export/drawScene.js.map +1 -0
- package/lib/module/export/exportImage.js +88 -0
- package/lib/module/export/exportImage.js.map +1 -0
- package/lib/module/gestures/applyTransform.js +75 -0
- package/lib/module/gestures/applyTransform.js.map +1 -0
- package/lib/module/gestures/createAnnotation.js +65 -0
- package/lib/module/gestures/createAnnotation.js.map +1 -0
- package/lib/module/gestures/handles.js +49 -0
- package/lib/module/gestures/handles.js.map +1 -0
- package/lib/module/gestures/hitTest.js +69 -0
- package/lib/module/gestures/hitTest.js.map +1 -0
- package/lib/module/gestures/useCropGesture.js +145 -0
- package/lib/module/gestures/useCropGesture.js.map +1 -0
- package/lib/module/gestures/useEditorGestures.js +285 -0
- package/lib/module/gestures/useEditorGestures.js.map +1 -0
- package/lib/module/image/disposeRegistry.js +57 -0
- package/lib/module/image/disposeRegistry.js.map +1 -0
- package/lib/module/image/useLoadedImage.js +117 -0
- package/lib/module/image/useLoadedImage.js.map +1 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/state/history.js +76 -0
- package/lib/module/state/history.js.map +1 -0
- package/lib/module/state/selectors.js +14 -0
- package/lib/module/state/selectors.js.map +1 -0
- package/lib/module/state/useEditorReducer.js +79 -0
- package/lib/module/state/useEditorReducer.js.map +1 -0
- package/lib/module/toolbar/ColorPicker.js +80 -0
- package/lib/module/toolbar/ColorPicker.js.map +1 -0
- package/lib/module/toolbar/CropControls.js +62 -0
- package/lib/module/toolbar/CropControls.js.map +1 -0
- package/lib/module/toolbar/RotationSlider.js +69 -0
- package/lib/module/toolbar/RotationSlider.js.map +1 -0
- package/lib/module/toolbar/TextInputOverlay.js +105 -0
- package/lib/module/toolbar/TextInputOverlay.js.map +1 -0
- package/lib/module/toolbar/ToolButton.js +52 -0
- package/lib/module/toolbar/ToolButton.js.map +1 -0
- package/lib/module/toolbar/Toolbar.js +133 -0
- package/lib/module/toolbar/Toolbar.js.map +1 -0
- package/lib/module/types.js +43 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/color.js +33 -0
- package/lib/module/utils/color.js.map +1 -0
- package/lib/module/utils/id.js +10 -0
- package/lib/module/utils/id.js.map +1 -0
- package/lib/module/utils/math.js +258 -0
- package/lib/module/utils/math.js.map +1 -0
- package/lib/typescript/src/ImageEditor.d.ts +9 -0
- package/lib/typescript/src/ImageEditor.d.ts.map +1 -0
- package/lib/typescript/src/annotations/AnnotationView.d.ts +6 -0
- package/lib/typescript/src/annotations/AnnotationView.d.ts.map +1 -0
- package/lib/typescript/src/annotations/ArrowAnnotation.d.ts +5 -0
- package/lib/typescript/src/annotations/ArrowAnnotation.d.ts.map +1 -0
- package/lib/typescript/src/annotations/CircleAnnotation.d.ts +5 -0
- package/lib/typescript/src/annotations/CircleAnnotation.d.ts.map +1 -0
- package/lib/typescript/src/annotations/FreehandAnnotation.d.ts +5 -0
- package/lib/typescript/src/annotations/FreehandAnnotation.d.ts.map +1 -0
- package/lib/typescript/src/annotations/MarkerAnnotation.d.ts +5 -0
- package/lib/typescript/src/annotations/MarkerAnnotation.d.ts.map +1 -0
- package/lib/typescript/src/annotations/RotatedGroup.d.ts +13 -0
- package/lib/typescript/src/annotations/RotatedGroup.d.ts.map +1 -0
- package/lib/typescript/src/annotations/TextAnnotation.d.ts +10 -0
- package/lib/typescript/src/annotations/TextAnnotation.d.ts.map +1 -0
- package/lib/typescript/src/annotations/geometry.d.ts +11 -0
- package/lib/typescript/src/annotations/geometry.d.ts.map +1 -0
- package/lib/typescript/src/annotations/geometryPure.d.ts +14 -0
- package/lib/typescript/src/annotations/geometryPure.d.ts.map +1 -0
- package/lib/typescript/src/canvas/AnnotationLayer.d.ts +11 -0
- package/lib/typescript/src/canvas/AnnotationLayer.d.ts.map +1 -0
- package/lib/typescript/src/canvas/BaseImageLayer.d.ts +12 -0
- package/lib/typescript/src/canvas/BaseImageLayer.d.ts.map +1 -0
- package/lib/typescript/src/canvas/CropOverlay.d.ts +10 -0
- package/lib/typescript/src/canvas/CropOverlay.d.ts.map +1 -0
- package/lib/typescript/src/canvas/EditorCanvas.d.ts +18 -0
- package/lib/typescript/src/canvas/EditorCanvas.d.ts.map +1 -0
- package/lib/typescript/src/canvas/InFlightLayer.d.ts +12 -0
- package/lib/typescript/src/canvas/InFlightLayer.d.ts.map +1 -0
- package/lib/typescript/src/canvas/SelectionOverlay.d.ts +11 -0
- package/lib/typescript/src/canvas/SelectionOverlay.d.ts.map +1 -0
- package/lib/typescript/src/constants.d.ts +25 -0
- package/lib/typescript/src/constants.d.ts.map +1 -0
- package/lib/typescript/src/context/EditorContext.d.ts +66 -0
- package/lib/typescript/src/context/EditorContext.d.ts.map +1 -0
- package/lib/typescript/src/export/drawScene.d.ts +10 -0
- package/lib/typescript/src/export/drawScene.d.ts.map +1 -0
- package/lib/typescript/src/export/exportImage.d.ts +23 -0
- package/lib/typescript/src/export/exportImage.d.ts.map +1 -0
- package/lib/typescript/src/gestures/applyTransform.d.ts +17 -0
- package/lib/typescript/src/gestures/applyTransform.d.ts.map +1 -0
- package/lib/typescript/src/gestures/createAnnotation.d.ts +11 -0
- package/lib/typescript/src/gestures/createAnnotation.d.ts.map +1 -0
- package/lib/typescript/src/gestures/handles.d.ts +17 -0
- package/lib/typescript/src/gestures/handles.d.ts.map +1 -0
- package/lib/typescript/src/gestures/hitTest.d.ts +9 -0
- package/lib/typescript/src/gestures/hitTest.d.ts.map +1 -0
- package/lib/typescript/src/gestures/useCropGesture.d.ts +7 -0
- package/lib/typescript/src/gestures/useCropGesture.d.ts.map +1 -0
- package/lib/typescript/src/gestures/useEditorGestures.d.ts +8 -0
- package/lib/typescript/src/gestures/useEditorGestures.d.ts.map +1 -0
- package/lib/typescript/src/image/disposeRegistry.d.ts +25 -0
- package/lib/typescript/src/image/disposeRegistry.d.ts.map +1 -0
- package/lib/typescript/src/image/useLoadedImage.d.ts +23 -0
- package/lib/typescript/src/image/useLoadedImage.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +6 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/state/history.d.ts +23 -0
- package/lib/typescript/src/state/history.d.ts.map +1 -0
- package/lib/typescript/src/state/selectors.d.ts +5 -0
- package/lib/typescript/src/state/selectors.d.ts.map +1 -0
- package/lib/typescript/src/state/useEditorReducer.d.ts +32 -0
- package/lib/typescript/src/state/useEditorReducer.d.ts.map +1 -0
- package/lib/typescript/src/toolbar/ColorPicker.d.ts +7 -0
- package/lib/typescript/src/toolbar/ColorPicker.d.ts.map +1 -0
- package/lib/typescript/src/toolbar/CropControls.d.ts +3 -0
- package/lib/typescript/src/toolbar/CropControls.d.ts.map +1 -0
- package/lib/typescript/src/toolbar/RotationSlider.d.ts +8 -0
- package/lib/typescript/src/toolbar/RotationSlider.d.ts.map +1 -0
- package/lib/typescript/src/toolbar/TextInputOverlay.d.ts +9 -0
- package/lib/typescript/src/toolbar/TextInputOverlay.d.ts.map +1 -0
- package/lib/typescript/src/toolbar/ToolButton.d.ts +7 -0
- package/lib/typescript/src/toolbar/ToolButton.d.ts.map +1 -0
- package/lib/typescript/src/toolbar/Toolbar.d.ts +4 -0
- package/lib/typescript/src/toolbar/Toolbar.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +170 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils/color.d.ts +8 -0
- package/lib/typescript/src/utils/color.d.ts.map +1 -0
- package/lib/typescript/src/utils/id.d.ts +3 -0
- package/lib/typescript/src/utils/id.d.ts.map +1 -0
- package/lib/typescript/src/utils/math.d.ts +68 -0
- package/lib/typescript/src/utils/math.d.ts.map +1 -0
- package/package.json +90 -0
- package/src/ImageEditor.tsx +133 -0
- package/src/annotations/AnnotationView.tsx +24 -0
- package/src/annotations/ArrowAnnotation.tsx +26 -0
- package/src/annotations/CircleAnnotation.tsx +22 -0
- package/src/annotations/FreehandAnnotation.tsx +22 -0
- package/src/annotations/MarkerAnnotation.tsx +20 -0
- package/src/annotations/RotatedGroup.tsx +28 -0
- package/src/annotations/TextAnnotation.tsx +42 -0
- package/src/annotations/geometry.ts +62 -0
- package/src/annotations/geometryPure.ts +73 -0
- package/src/canvas/AnnotationLayer.tsx +43 -0
- package/src/canvas/BaseImageLayer.tsx +28 -0
- package/src/canvas/CropOverlay.tsx +92 -0
- package/src/canvas/EditorCanvas.tsx +70 -0
- package/src/canvas/InFlightLayer.tsx +140 -0
- package/src/canvas/SelectionOverlay.tsx +92 -0
- package/src/constants.ts +46 -0
- package/src/context/EditorContext.tsx +229 -0
- package/src/export/drawScene.ts +120 -0
- package/src/export/exportImage.ts +111 -0
- package/src/gestures/applyTransform.ts +76 -0
- package/src/gestures/createAnnotation.ts +92 -0
- package/src/gestures/handles.ts +50 -0
- package/src/gestures/hitTest.ts +79 -0
- package/src/gestures/useCropGesture.ts +123 -0
- package/src/gestures/useEditorGestures.ts +308 -0
- package/src/image/disposeRegistry.ts +59 -0
- package/src/image/useLoadedImage.ts +131 -0
- package/src/index.ts +32 -0
- package/src/state/history.ts +71 -0
- package/src/state/selectors.ts +16 -0
- package/src/state/useEditorReducer.ts +93 -0
- package/src/toolbar/ColorPicker.tsx +72 -0
- package/src/toolbar/CropControls.tsx +46 -0
- package/src/toolbar/RotationSlider.tsx +56 -0
- package/src/toolbar/TextInputOverlay.tsx +104 -0
- package/src/toolbar/ToolButton.tsx +46 -0
- package/src/toolbar/Toolbar.tsx +110 -0
- package/src/types.ts +203 -0
- package/src/utils/color.ts +34 -0
- package/src/utils/id.ts +7 -0
- package/src/utils/math.ts +222 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { Gesture } from 'react-native-gesture-handler';
|
|
5
|
+
import { runOnJS, useSharedValue } from 'react-native-reanimated';
|
|
6
|
+
import { useEditor } from '../context/EditorContext';
|
|
7
|
+
import { FREEHAND_MIN_DISTANCE, HANDLE_SIZE, HIT_SLOP } from '../constants';
|
|
8
|
+
import { applyToPoint, distance, invert } from '../utils/math';
|
|
9
|
+
import { annotationCenter } from '../annotations/geometry';
|
|
10
|
+
import { hitTest } from './hitTest';
|
|
11
|
+
import { selectionHandles } from './handles';
|
|
12
|
+
import { applyTransformToAnnotation } from './applyTransform';
|
|
13
|
+
import { makeArrow, makeCircle, makeFreehand, makeMarker, makeText } from './createAnnotation';
|
|
14
|
+
function isDrawTool(tool) {
|
|
15
|
+
'worklet';
|
|
16
|
+
|
|
17
|
+
return tool === 'circle' || tool === 'arrow' || tool === 'marker' || tool === 'freehand';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A single composed Pan gesture over the canvas. It branches on the active tool
|
|
22
|
+
* and, in select mode, on where the touch began (rotate handle → rotate, corner
|
|
23
|
+
* handle → resize, body → move, empty → (de)select). All geometry math runs on
|
|
24
|
+
* the UI thread; only final commits hop to JS via runOnJS.
|
|
25
|
+
*/
|
|
26
|
+
export function useEditorGestures() {
|
|
27
|
+
const editor = useEditor();
|
|
28
|
+
const {
|
|
29
|
+
tool,
|
|
30
|
+
selectedId,
|
|
31
|
+
annotations,
|
|
32
|
+
matrix,
|
|
33
|
+
draw,
|
|
34
|
+
live,
|
|
35
|
+
strokeColor,
|
|
36
|
+
strokeWidth,
|
|
37
|
+
dispatch,
|
|
38
|
+
setSelectedId,
|
|
39
|
+
setEditingTextId
|
|
40
|
+
} = editor;
|
|
41
|
+
const invMatrix = useMemo(() => invert(matrix), [matrix]);
|
|
42
|
+
const scaleFactor = useMemo(() => Math.hypot(matrix.a, matrix.b) || 1, [matrix]);
|
|
43
|
+
const slopImage = HIT_SLOP / scaleFactor;
|
|
44
|
+
|
|
45
|
+
// Per-gesture UI-thread scratch state.
|
|
46
|
+
const mode = useSharedValue('none');
|
|
47
|
+
const startImg = useSharedValue({
|
|
48
|
+
x: 0,
|
|
49
|
+
y: 0
|
|
50
|
+
});
|
|
51
|
+
const startDist = useSharedValue(0);
|
|
52
|
+
const startAngle = useSharedValue(0);
|
|
53
|
+
const activeId = useSharedValue(null);
|
|
54
|
+
|
|
55
|
+
// ---- JS-thread commit callbacks --------------------------------------
|
|
56
|
+
const selectId = id => setSelectedId(id);
|
|
57
|
+
const commitCircle = (center, radius) => dispatch({
|
|
58
|
+
type: 'ADD_ANNOTATION',
|
|
59
|
+
annotation: makeCircle(center, radius, {
|
|
60
|
+
strokeColor,
|
|
61
|
+
strokeWidth
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
const commitArrow = (start, end) => dispatch({
|
|
65
|
+
type: 'ADD_ANNOTATION',
|
|
66
|
+
annotation: makeArrow(start, end, {
|
|
67
|
+
strokeColor,
|
|
68
|
+
strokeWidth
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
const commitMarker = rect => dispatch({
|
|
72
|
+
type: 'ADD_ANNOTATION',
|
|
73
|
+
annotation: makeMarker(rect, strokeColor)
|
|
74
|
+
});
|
|
75
|
+
const commitFreehand = points => dispatch({
|
|
76
|
+
type: 'ADD_ANNOTATION',
|
|
77
|
+
annotation: makeFreehand(points, {
|
|
78
|
+
strokeColor,
|
|
79
|
+
strokeWidth
|
|
80
|
+
})
|
|
81
|
+
});
|
|
82
|
+
const placeText = origin => {
|
|
83
|
+
const annotation = makeText(origin, editor.textColor);
|
|
84
|
+
dispatch({
|
|
85
|
+
type: 'ADD_ANNOTATION',
|
|
86
|
+
annotation
|
|
87
|
+
});
|
|
88
|
+
setSelectedId(annotation.id);
|
|
89
|
+
setEditingTextId(annotation.id);
|
|
90
|
+
};
|
|
91
|
+
const commitTransform = (id, vals) => {
|
|
92
|
+
if (!id) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Skip no-op transforms (a plain tap) so they don't pollute history.
|
|
96
|
+
const identity = vals.tx === 0 && vals.ty === 0 && vals.rotate === 0 && vals.scale === 1;
|
|
97
|
+
if (identity) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const target = annotations.find(a => a.id === id);
|
|
101
|
+
if (!target) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const updated = applyTransformToAnnotation(target, vals);
|
|
105
|
+
dispatch({
|
|
106
|
+
type: 'UPDATE_ANNOTATION',
|
|
107
|
+
id,
|
|
108
|
+
changes: updated
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
const resetLive = () => {
|
|
112
|
+
live.active.value = false;
|
|
113
|
+
live.tx.value = 0;
|
|
114
|
+
live.ty.value = 0;
|
|
115
|
+
live.rotate.value = 0;
|
|
116
|
+
live.scale.value = 1;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// ---- The gesture ------------------------------------------------------
|
|
120
|
+
const pan = useMemo(() => {
|
|
121
|
+
return Gesture.Pan().maxPointers(1).onBegin(e => {
|
|
122
|
+
'worklet';
|
|
123
|
+
|
|
124
|
+
if (tool === 'crop') {
|
|
125
|
+
mode.value = 'none';
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const screen = {
|
|
129
|
+
x: e.x,
|
|
130
|
+
y: e.y
|
|
131
|
+
};
|
|
132
|
+
const img = applyToPoint(invMatrix, screen);
|
|
133
|
+
startImg.value = img;
|
|
134
|
+
activeId.value = selectedId;
|
|
135
|
+
if (isDrawTool(tool)) {
|
|
136
|
+
mode.value = 'draw';
|
|
137
|
+
draw.active.value = true;
|
|
138
|
+
draw.start.value = img;
|
|
139
|
+
draw.current.value = img;
|
|
140
|
+
if (tool === 'freehand') {
|
|
141
|
+
draw.points.value = [img];
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (tool === 'text') {
|
|
146
|
+
mode.value = 'text';
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// select tool: figure out what was grabbed.
|
|
151
|
+
const sel = selectedId ? annotations.find(a => a.id === selectedId) : undefined;
|
|
152
|
+
if (sel) {
|
|
153
|
+
const h = selectionHandles(sel, matrix);
|
|
154
|
+
const center = annotationCenter(sel);
|
|
155
|
+
if (distance(screen, h.rotate) <= HANDLE_SIZE * 1.5) {
|
|
156
|
+
mode.value = 'rotate';
|
|
157
|
+
live.origin.value = center;
|
|
158
|
+
live.active.value = true;
|
|
159
|
+
startAngle.value = Math.atan2(img.y - center.y, img.x - center.x);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
for (let i = 0; i < h.corners.length; i++) {
|
|
163
|
+
if (distance(screen, h.corners[i]) <= HANDLE_SIZE * 1.5) {
|
|
164
|
+
mode.value = 'resize';
|
|
165
|
+
live.origin.value = center;
|
|
166
|
+
live.active.value = true;
|
|
167
|
+
startDist.value = distance(center, img);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Body of the selected annotation → move it.
|
|
172
|
+
if (hitTest([sel], img, slopImage) === sel.id) {
|
|
173
|
+
mode.value = 'move';
|
|
174
|
+
live.origin.value = center;
|
|
175
|
+
live.active.value = true;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Otherwise (de)select whatever is under the touch.
|
|
181
|
+
const hitId = hitTest(annotations, img, slopImage);
|
|
182
|
+
runOnJS(selectId)(hitId);
|
|
183
|
+
activeId.value = hitId;
|
|
184
|
+
if (hitId) {
|
|
185
|
+
const target = annotations.find(a => a.id === hitId);
|
|
186
|
+
mode.value = 'move';
|
|
187
|
+
live.origin.value = annotationCenter(target);
|
|
188
|
+
live.active.value = true;
|
|
189
|
+
} else {
|
|
190
|
+
mode.value = 'none';
|
|
191
|
+
}
|
|
192
|
+
}).onChange(e => {
|
|
193
|
+
'worklet';
|
|
194
|
+
|
|
195
|
+
const screen = {
|
|
196
|
+
x: e.x,
|
|
197
|
+
y: e.y
|
|
198
|
+
};
|
|
199
|
+
const img = applyToPoint(invMatrix, screen);
|
|
200
|
+
switch (mode.value) {
|
|
201
|
+
case 'draw':
|
|
202
|
+
if (tool === 'freehand') {
|
|
203
|
+
const pts = draw.points.value;
|
|
204
|
+
const last = pts[pts.length - 1];
|
|
205
|
+
if (!last || distance(last, img) >= FREEHAND_MIN_DISTANCE) {
|
|
206
|
+
draw.points.value = [...pts, img];
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
draw.current.value = img;
|
|
210
|
+
}
|
|
211
|
+
break;
|
|
212
|
+
case 'move':
|
|
213
|
+
live.tx.value = img.x - startImg.value.x;
|
|
214
|
+
live.ty.value = img.y - startImg.value.y;
|
|
215
|
+
break;
|
|
216
|
+
case 'resize':
|
|
217
|
+
live.scale.value = startDist.value > 0 ? distance(live.origin.value, img) / startDist.value : 1;
|
|
218
|
+
break;
|
|
219
|
+
case 'rotate':
|
|
220
|
+
{
|
|
221
|
+
const ang = Math.atan2(img.y - live.origin.value.y, img.x - live.origin.value.x);
|
|
222
|
+
live.rotate.value = ang - startAngle.value;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
default:
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}).onEnd(() => {
|
|
229
|
+
'worklet';
|
|
230
|
+
|
|
231
|
+
if (mode.value === 'draw') {
|
|
232
|
+
draw.active.value = false;
|
|
233
|
+
const s = draw.start.value;
|
|
234
|
+
const c = draw.current.value;
|
|
235
|
+
if (tool === 'circle') {
|
|
236
|
+
const r = distance(s, c);
|
|
237
|
+
if (r > 2) runOnJS(commitCircle)(s, r);
|
|
238
|
+
} else if (tool === 'arrow') {
|
|
239
|
+
if (distance(s, c) > 2) runOnJS(commitArrow)(s, c);
|
|
240
|
+
} else if (tool === 'marker') {
|
|
241
|
+
const rect = {
|
|
242
|
+
x: Math.min(s.x, c.x),
|
|
243
|
+
y: Math.min(s.y, c.y),
|
|
244
|
+
width: Math.abs(c.x - s.x),
|
|
245
|
+
height: Math.abs(c.y - s.y)
|
|
246
|
+
};
|
|
247
|
+
if (rect.width > 2 && rect.height > 2) runOnJS(commitMarker)(rect);
|
|
248
|
+
} else if (tool === 'freehand') {
|
|
249
|
+
const pts = draw.points.value;
|
|
250
|
+
if (pts.length > 1) runOnJS(commitFreehand)(pts);
|
|
251
|
+
draw.points.value = [];
|
|
252
|
+
}
|
|
253
|
+
mode.value = 'none';
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (mode.value === 'text') {
|
|
257
|
+
runOnJS(placeText)(startImg.value);
|
|
258
|
+
mode.value = 'none';
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (mode.value === 'move' || mode.value === 'resize' || mode.value === 'rotate') {
|
|
262
|
+
const vals = {
|
|
263
|
+
tx: live.tx.value,
|
|
264
|
+
ty: live.ty.value,
|
|
265
|
+
rotate: live.rotate.value,
|
|
266
|
+
scale: live.scale.value,
|
|
267
|
+
origin: live.origin.value
|
|
268
|
+
};
|
|
269
|
+
runOnJS(commitTransform)(activeId.value, vals);
|
|
270
|
+
runOnJS(resetLive)();
|
|
271
|
+
mode.value = 'none';
|
|
272
|
+
}
|
|
273
|
+
}).onFinalize(() => {
|
|
274
|
+
'worklet';
|
|
275
|
+
|
|
276
|
+
// Safety: ensure draw preview is cleared if the gesture is cancelled.
|
|
277
|
+
if (draw.active.value && mode.value !== 'draw') {
|
|
278
|
+
draw.active.value = false;
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
282
|
+
}, [tool, selectedId, annotations, matrix, strokeColor, strokeWidth]);
|
|
283
|
+
return pan;
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=useEditorGestures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useMemo","Gesture","runOnJS","useSharedValue","useEditor","FREEHAND_MIN_DISTANCE","HANDLE_SIZE","HIT_SLOP","applyToPoint","distance","invert","annotationCenter","hitTest","selectionHandles","applyTransformToAnnotation","makeArrow","makeCircle","makeFreehand","makeMarker","makeText","isDrawTool","tool","useEditorGestures","editor","selectedId","annotations","matrix","draw","live","strokeColor","strokeWidth","dispatch","setSelectedId","setEditingTextId","invMatrix","scaleFactor","Math","hypot","a","b","slopImage","mode","startImg","x","y","startDist","startAngle","activeId","selectId","id","commitCircle","center","radius","type","annotation","commitArrow","start","end","commitMarker","rect","commitFreehand","points","placeText","origin","textColor","commitTransform","vals","identity","tx","ty","rotate","scale","target","find","updated","changes","resetLive","active","value","pan","Pan","maxPointers","onBegin","e","screen","img","current","sel","undefined","h","atan2","i","corners","length","hitId","onChange","pts","last","ang","onEnd","s","c","r","min","width","abs","height","onFinalize"],"sourceRoot":"..\\..\\..\\src","sources":["gestures/useEditorGestures.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tracks Skia native objects (SkImage / SkData / SkSurface / SkParagraph …) so
|
|
5
|
+
* they can be released deterministically. Skia objects are JSI HostObjects; the
|
|
6
|
+
* Hermes GC under-counts their native footprint and may never collect them, so
|
|
7
|
+
* we must call `.dispose()` explicitly. This registry is a safety net: register
|
|
8
|
+
* anything created imperatively, and `flush()` on unmount to guarantee cleanup.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export class DisposeRegistry {
|
|
12
|
+
items = new Set();
|
|
13
|
+
|
|
14
|
+
/** Track an object and return it for convenient chaining. */
|
|
15
|
+
add(item) {
|
|
16
|
+
this.items.add(item);
|
|
17
|
+
return item;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Stop tracking without disposing (e.g. ownership handed elsewhere). */
|
|
21
|
+
forget(item) {
|
|
22
|
+
this.items.delete(item);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Dispose a single tracked object now. */
|
|
26
|
+
release(item) {
|
|
27
|
+
if (!item) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.items.delete(item);
|
|
31
|
+
safeDispose(item);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Dispose everything still tracked. Call on unmount. */
|
|
35
|
+
flush() {
|
|
36
|
+
for (const item of this.items) {
|
|
37
|
+
safeDispose(item);
|
|
38
|
+
}
|
|
39
|
+
this.items.clear();
|
|
40
|
+
}
|
|
41
|
+
get size() {
|
|
42
|
+
return this.items.size;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Dispose without throwing if the object was already released. */
|
|
47
|
+
export function safeDispose(item) {
|
|
48
|
+
if (!item) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
item.dispose();
|
|
53
|
+
} catch {
|
|
54
|
+
// Already disposed or not a real disposable — ignore.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=disposeRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DisposeRegistry","items","Set","add","item","forget","delete","release","safeDispose","flush","clear","size","dispose"],"sourceRoot":"..\\..\\..\\src","sources":["image/disposeRegistry.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAMA,OAAO,MAAMA,eAAe,CAAC;EACnBC,KAAK,GAAG,IAAIC,GAAG,CAAa,CAAC;;EAErC;EACAC,GAAGA,CAAuBC,IAAO,EAAK;IACpC,IAAI,CAACH,KAAK,CAACE,GAAG,CAACC,IAAI,CAAC;IACpB,OAAOA,IAAI;EACb;;EAEA;EACAC,MAAMA,CAACD,IAAgB,EAAQ;IAC7B,IAAI,CAACH,KAAK,CAACK,MAAM,CAACF,IAAI,CAAC;EACzB;;EAEA;EACAG,OAAOA,CAACH,IAAmC,EAAQ;IACjD,IAAI,CAACA,IAAI,EAAE;MACT;IACF;IACA,IAAI,CAACH,KAAK,CAACK,MAAM,CAACF,IAAI,CAAC;IACvBI,WAAW,CAACJ,IAAI,CAAC;EACnB;;EAEA;EACAK,KAAKA,CAAA,EAAS;IACZ,KAAK,MAAML,IAAI,IAAI,IAAI,CAACH,KAAK,EAAE;MAC7BO,WAAW,CAACJ,IAAI,CAAC;IACnB;IACA,IAAI,CAACH,KAAK,CAACS,KAAK,CAAC,CAAC;EACpB;EAEA,IAAIC,IAAIA,CAAA,EAAW;IACjB,OAAO,IAAI,CAACV,KAAK,CAACU,IAAI;EACxB;AACF;;AAEA;AACA,OAAO,SAASH,WAAWA,CAACJ,IAAmC,EAAQ;EACrE,IAAI,CAACA,IAAI,EAAE;IACT;EACF;EACA,IAAI;IACFA,IAAI,CAACQ,OAAO,CAAC,CAAC;EAChB,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ","ignoreList":[]}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { Skia } from '@shopify/react-native-skia';
|
|
5
|
+
import { safeDispose } from './disposeRegistry';
|
|
6
|
+
function stripDataUri(base64) {
|
|
7
|
+
const comma = base64.indexOf(',');
|
|
8
|
+
if (base64.startsWith('data:') && comma !== -1) {
|
|
9
|
+
return base64.slice(comma + 1);
|
|
10
|
+
}
|
|
11
|
+
return base64;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Decode an {@link ImageSource} into an `SkImage`, managing native memory.
|
|
16
|
+
*
|
|
17
|
+
* Memory rules enforced here:
|
|
18
|
+
* - The encoded `SkData` is disposed immediately after `MakeImageFromEncoded`;
|
|
19
|
+
* the decoded `SkImage` owns its pixels, so retaining the encoded bytes would
|
|
20
|
+
* roughly double memory usage.
|
|
21
|
+
* - When `source` changes (or the component unmounts) the previous `SkImage` is
|
|
22
|
+
* disposed before the next one is created.
|
|
23
|
+
* - The input base64 string is consumed inside the effect and never copied into
|
|
24
|
+
* state, so a large payload is not retained by this hook.
|
|
25
|
+
*/
|
|
26
|
+
export function useLoadedImage(source) {
|
|
27
|
+
const [state, setState] = useState({
|
|
28
|
+
image: null,
|
|
29
|
+
width: 0,
|
|
30
|
+
height: 0,
|
|
31
|
+
loading: true,
|
|
32
|
+
error: null
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Serialize the source so the effect re-runs only on a real change, without
|
|
36
|
+
// holding the (possibly huge) base64 string in a memoized ref.
|
|
37
|
+
const sourceKey = 'base64' in source ? `b64:${source.base64.length}:${source.base64.slice(-64)}` : `uri:${source.uri}`;
|
|
38
|
+
const currentImage = useRef(null);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
let cancelled = false;
|
|
41
|
+
const commit = image => {
|
|
42
|
+
if (cancelled) {
|
|
43
|
+
// A newer load superseded us — drop this result.
|
|
44
|
+
safeDispose(image);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Dispose the previous image before swapping in the new one.
|
|
48
|
+
if (currentImage.current && currentImage.current !== image) {
|
|
49
|
+
safeDispose(currentImage.current);
|
|
50
|
+
}
|
|
51
|
+
currentImage.current = image;
|
|
52
|
+
setState({
|
|
53
|
+
image,
|
|
54
|
+
width: image.width(),
|
|
55
|
+
height: image.height(),
|
|
56
|
+
loading: false,
|
|
57
|
+
error: null
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const fail = error => {
|
|
61
|
+
if (cancelled) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
setState(prev => ({
|
|
65
|
+
...prev,
|
|
66
|
+
loading: false,
|
|
67
|
+
error
|
|
68
|
+
}));
|
|
69
|
+
};
|
|
70
|
+
setState(prev => ({
|
|
71
|
+
...prev,
|
|
72
|
+
loading: true,
|
|
73
|
+
error: null
|
|
74
|
+
}));
|
|
75
|
+
try {
|
|
76
|
+
if ('base64' in source) {
|
|
77
|
+
const data = Skia.Data.fromBase64(stripDataUri(source.base64));
|
|
78
|
+
const image = Skia.Image.MakeImageFromEncoded(data);
|
|
79
|
+
safeDispose(data); // decoded pixels are owned by `image` now
|
|
80
|
+
if (!image) {
|
|
81
|
+
throw new Error('Failed to decode image from base64.');
|
|
82
|
+
}
|
|
83
|
+
commit(image);
|
|
84
|
+
} else {
|
|
85
|
+
// fromURI is async (may fetch a remote/local file).
|
|
86
|
+
Skia.Data.fromURI(source.uri).then(data => {
|
|
87
|
+
if (cancelled) {
|
|
88
|
+
safeDispose(data);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const image = Skia.Image.MakeImageFromEncoded(data);
|
|
92
|
+
safeDispose(data);
|
|
93
|
+
if (!image) {
|
|
94
|
+
throw new Error(`Failed to decode image from URI: ${source.uri}`);
|
|
95
|
+
}
|
|
96
|
+
commit(image);
|
|
97
|
+
}).catch(e => fail(e instanceof Error ? e : new Error(String(e))));
|
|
98
|
+
}
|
|
99
|
+
} catch (e) {
|
|
100
|
+
fail(e instanceof Error ? e : new Error(String(e)));
|
|
101
|
+
}
|
|
102
|
+
return () => {
|
|
103
|
+
cancelled = true;
|
|
104
|
+
};
|
|
105
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
106
|
+
}, [sourceKey]);
|
|
107
|
+
|
|
108
|
+
// Final safety net: dispose the last image when the hook unmounts.
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
return () => {
|
|
111
|
+
safeDispose(currentImage.current);
|
|
112
|
+
currentImage.current = null;
|
|
113
|
+
};
|
|
114
|
+
}, []);
|
|
115
|
+
return state;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=useLoadedImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useEffect","useRef","useState","Skia","safeDispose","stripDataUri","base64","comma","indexOf","startsWith","slice","useLoadedImage","source","state","setState","image","width","height","loading","error","sourceKey","length","uri","currentImage","cancelled","commit","current","fail","prev","data","Data","fromBase64","Image","MakeImageFromEncoded","Error","fromURI","then","catch","e","String"],"sourceRoot":"..\\..\\..\\src","sources":["image/useLoadedImage.ts"],"mappings":";;AAAA,SAASA,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AACnD,SAASC,IAAI,QAAQ,4BAA4B;AAIjD,SAASC,WAAW,QAAQ,mBAAmB;AAU/C,SAASC,YAAYA,CAACC,MAAc,EAAU;EAC5C,MAAMC,KAAK,GAAGD,MAAM,CAACE,OAAO,CAAC,GAAG,CAAC;EACjC,IAAIF,MAAM,CAACG,UAAU,CAAC,OAAO,CAAC,IAAIF,KAAK,KAAK,CAAC,CAAC,EAAE;IAC9C,OAAOD,MAAM,CAACI,KAAK,CAACH,KAAK,GAAG,CAAC,CAAC;EAChC;EACA,OAAOD,MAAM;AACf;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,cAAcA,CAACC,MAAmB,EAAe;EAC/D,MAAM,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGZ,QAAQ,CAAc;IAC9Ca,KAAK,EAAE,IAAI;IACXC,KAAK,EAAE,CAAC;IACRC,MAAM,EAAE,CAAC;IACTC,OAAO,EAAE,IAAI;IACbC,KAAK,EAAE;EACT,CAAC,CAAC;;EAEF;EACA;EACA,MAAMC,SAAS,GACb,QAAQ,IAAIR,MAAM,GAAG,OAAOA,MAAM,CAACN,MAAM,CAACe,MAAM,IAAIT,MAAM,CAACN,MAAM,CAACI,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,OAAOE,MAAM,CAACU,GAAG,EAAE;EAEtG,MAAMC,YAAY,GAAGtB,MAAM,CAAiB,IAAI,CAAC;EAEjDD,SAAS,CAAC,MAAM;IACd,IAAIwB,SAAS,GAAG,KAAK;IAErB,MAAMC,MAAM,GAAIV,KAAc,IAAK;MACjC,IAAIS,SAAS,EAAE;QACb;QACApB,WAAW,CAACW,KAAK,CAAC;QAClB;MACF;MACA;MACA,IAAIQ,YAAY,CAACG,OAAO,IAAIH,YAAY,CAACG,OAAO,KAAKX,KAAK,EAAE;QAC1DX,WAAW,CAACmB,YAAY,CAACG,OAAO,CAAC;MACnC;MACAH,YAAY,CAACG,OAAO,GAAGX,KAAK;MAC5BD,QAAQ,CAAC;QACPC,KAAK;QACLC,KAAK,EAAED,KAAK,CAACC,KAAK,CAAC,CAAC;QACpBC,MAAM,EAAEF,KAAK,CAACE,MAAM,CAAC,CAAC;QACtBC,OAAO,EAAE,KAAK;QACdC,KAAK,EAAE;MACT,CAAC,CAAC;IACJ,CAAC;IAED,MAAMQ,IAAI,GAAIR,KAAY,IAAK;MAC7B,IAAIK,SAAS,EAAE;QACb;MACF;MACAV,QAAQ,CAAEc,IAAI,KAAM;QAAE,GAAGA,IAAI;QAAEV,OAAO,EAAE,KAAK;QAAEC;MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC;IAEDL,QAAQ,CAAEc,IAAI,KAAM;MAAE,GAAGA,IAAI;MAAEV,OAAO,EAAE,IAAI;MAAEC,KAAK,EAAE;IAAK,CAAC,CAAC,CAAC;IAE7D,IAAI;MACF,IAAI,QAAQ,IAAIP,MAAM,EAAE;QACtB,MAAMiB,IAAI,GAAG1B,IAAI,CAAC2B,IAAI,CAACC,UAAU,CAAC1B,YAAY,CAACO,MAAM,CAACN,MAAM,CAAC,CAAC;QAC9D,MAAMS,KAAK,GAAGZ,IAAI,CAAC6B,KAAK,CAACC,oBAAoB,CAACJ,IAAI,CAAC;QACnDzB,WAAW,CAACyB,IAAI,CAAC,CAAC,CAAC;QACnB,IAAI,CAACd,KAAK,EAAE;UACV,MAAM,IAAImB,KAAK,CAAC,qCAAqC,CAAC;QACxD;QACAT,MAAM,CAACV,KAAK,CAAC;MACf,CAAC,MAAM;QACL;QACAZ,IAAI,CAAC2B,IAAI,CAACK,OAAO,CAACvB,MAAM,CAACU,GAAG,CAAC,CAC1Bc,IAAI,CAAEP,IAAI,IAAK;UACd,IAAIL,SAAS,EAAE;YACbpB,WAAW,CAACyB,IAAI,CAAC;YACjB;UACF;UACA,MAAMd,KAAK,GAAGZ,IAAI,CAAC6B,KAAK,CAACC,oBAAoB,CAACJ,IAAI,CAAC;UACnDzB,WAAW,CAACyB,IAAI,CAAC;UACjB,IAAI,CAACd,KAAK,EAAE;YACV,MAAM,IAAImB,KAAK,CAAC,oCAAoCtB,MAAM,CAACU,GAAG,EAAE,CAAC;UACnE;UACAG,MAAM,CAACV,KAAK,CAAC;QACf,CAAC,CAAC,CACDsB,KAAK,CAAEC,CAAU,IAChBX,IAAI,CAACW,CAAC,YAAYJ,KAAK,GAAGI,CAAC,GAAG,IAAIJ,KAAK,CAACK,MAAM,CAACD,CAAC,CAAC,CAAC,CACpD,CAAC;MACL;IACF,CAAC,CAAC,OAAOA,CAAC,EAAE;MACVX,IAAI,CAACW,CAAC,YAAYJ,KAAK,GAAGI,CAAC,GAAG,IAAIJ,KAAK,CAACK,MAAM,CAACD,CAAC,CAAC,CAAC,CAAC;IACrD;IAEA,OAAO,MAAM;MACXd,SAAS,GAAG,IAAI;IAClB,CAAC;IACD;EACF,CAAC,EAAE,CAACJ,SAAS,CAAC,CAAC;;EAEf;EACApB,SAAS,CAAC,MAAM;IACd,OAAO,MAAM;MACXI,WAAW,CAACmB,YAAY,CAACG,OAAO,CAAC;MACjCH,YAAY,CAACG,OAAO,GAAG,IAAI;IAC7B,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOb,KAAK;AACd","ignoreList":[]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export { ImageEditor } from './ImageEditor';
|
|
4
|
+
// Advanced: build a custom UI on top of the editor state/context.
|
|
5
|
+
export { EditorProvider, useEditor } from './context/EditorContext';
|
|
6
|
+
export { exportImage } from './export/exportImage';
|
|
7
|
+
export { DEFAULT_PALETTE, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_COLOR } from './constants';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ImageEditor","EditorProvider","useEditor","exportImage","DEFAULT_PALETTE","DEFAULT_STROKE_COLOR","DEFAULT_TEXT_COLOR"],"sourceRoot":"..\\..\\src","sources":["index.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,eAAe;AAuB3C;AACA,SAASC,cAAc,EAAEC,SAAS,QAAQ,yBAAyB;AACnE,SAASC,WAAW,QAAQ,sBAAsB;AAElD,SACEC,eAAe,EACfC,oBAAoB,EACpBC,kBAAkB,QACb,aAAa","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { MAX_HISTORY } from '../constants';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generic, pure undo/redo history over an immutable document `T`.
|
|
7
|
+
* Snapshots are cheap here because the document is plain JSON (annotations +
|
|
8
|
+
* scene transform) — it never contains image bytes.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export function initHistory(present) {
|
|
12
|
+
return {
|
|
13
|
+
past: [],
|
|
14
|
+
present,
|
|
15
|
+
future: []
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Replace the present, pushing the old present onto the undo stack. */
|
|
20
|
+
export function commit(history, next) {
|
|
21
|
+
if (next === history.present) {
|
|
22
|
+
return history;
|
|
23
|
+
}
|
|
24
|
+
const past = [...history.past, history.present];
|
|
25
|
+
// Cap the depth to bound memory.
|
|
26
|
+
if (past.length > MAX_HISTORY) {
|
|
27
|
+
past.shift();
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
past,
|
|
31
|
+
present: next,
|
|
32
|
+
future: []
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Replace the present WITHOUT creating a history entry — used for live edits
|
|
38
|
+
* (e.g. typing in a text box) that should collapse into the eventual commit.
|
|
39
|
+
*/
|
|
40
|
+
export function replacePresent(history, next) {
|
|
41
|
+
return {
|
|
42
|
+
...history,
|
|
43
|
+
present: next
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function undo(history) {
|
|
47
|
+
if (history.past.length === 0) {
|
|
48
|
+
return history;
|
|
49
|
+
}
|
|
50
|
+
const previous = history.past[history.past.length - 1];
|
|
51
|
+
const past = history.past.slice(0, -1);
|
|
52
|
+
return {
|
|
53
|
+
past,
|
|
54
|
+
present: previous,
|
|
55
|
+
future: [history.present, ...history.future]
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function redo(history) {
|
|
59
|
+
if (history.future.length === 0) {
|
|
60
|
+
return history;
|
|
61
|
+
}
|
|
62
|
+
const next = history.future[0];
|
|
63
|
+
const future = history.future.slice(1);
|
|
64
|
+
return {
|
|
65
|
+
past: [...history.past, history.present],
|
|
66
|
+
present: next,
|
|
67
|
+
future
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function canUndo(history) {
|
|
71
|
+
return history.past.length > 0;
|
|
72
|
+
}
|
|
73
|
+
export function canRedo(history) {
|
|
74
|
+
return history.future.length > 0;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["MAX_HISTORY","initHistory","present","past","future","commit","history","next","length","shift","replacePresent","undo","previous","slice","redo","canUndo","canRedo"],"sourceRoot":"..\\..\\..\\src","sources":["state/history.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,cAAc;;AAE1C;AACA;AACA;AACA;AACA;;AAOA,OAAO,SAASC,WAAWA,CAAIC,OAAU,EAAc;EACrD,OAAO;IAAEC,IAAI,EAAE,EAAE;IAAED,OAAO;IAAEE,MAAM,EAAE;EAAG,CAAC;AAC1C;;AAEA;AACA,OAAO,SAASC,MAAMA,CAAIC,OAAmB,EAAEC,IAAO,EAAc;EAClE,IAAIA,IAAI,KAAKD,OAAO,CAACJ,OAAO,EAAE;IAC5B,OAAOI,OAAO;EAChB;EACA,MAAMH,IAAI,GAAG,CAAC,GAAGG,OAAO,CAACH,IAAI,EAAEG,OAAO,CAACJ,OAAO,CAAC;EAC/C;EACA,IAAIC,IAAI,CAACK,MAAM,GAAGR,WAAW,EAAE;IAC7BG,IAAI,CAACM,KAAK,CAAC,CAAC;EACd;EACA,OAAO;IAAEN,IAAI;IAAED,OAAO,EAAEK,IAAI;IAAEH,MAAM,EAAE;EAAG,CAAC;AAC5C;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASM,cAAcA,CAAIJ,OAAmB,EAAEC,IAAO,EAAc;EAC1E,OAAO;IAAE,GAAGD,OAAO;IAAEJ,OAAO,EAAEK;EAAK,CAAC;AACtC;AAEA,OAAO,SAASI,IAAIA,CAAIL,OAAmB,EAAc;EACvD,IAAIA,OAAO,CAACH,IAAI,CAACK,MAAM,KAAK,CAAC,EAAE;IAC7B,OAAOF,OAAO;EAChB;EACA,MAAMM,QAAQ,GAAGN,OAAO,CAACH,IAAI,CAACG,OAAO,CAACH,IAAI,CAACK,MAAM,GAAG,CAAC,CAAE;EACvD,MAAML,IAAI,GAAGG,OAAO,CAACH,IAAI,CAACU,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;EACtC,OAAO;IACLV,IAAI;IACJD,OAAO,EAAEU,QAAQ;IACjBR,MAAM,EAAE,CAACE,OAAO,CAACJ,OAAO,EAAE,GAAGI,OAAO,CAACF,MAAM;EAC7C,CAAC;AACH;AAEA,OAAO,SAASU,IAAIA,CAAIR,OAAmB,EAAc;EACvD,IAAIA,OAAO,CAACF,MAAM,CAACI,MAAM,KAAK,CAAC,EAAE;IAC/B,OAAOF,OAAO;EAChB;EACA,MAAMC,IAAI,GAAGD,OAAO,CAACF,MAAM,CAAC,CAAC,CAAE;EAC/B,MAAMA,MAAM,GAAGE,OAAO,CAACF,MAAM,CAACS,KAAK,CAAC,CAAC,CAAC;EACtC,OAAO;IACLV,IAAI,EAAE,CAAC,GAAGG,OAAO,CAACH,IAAI,EAAEG,OAAO,CAACJ,OAAO,CAAC;IACxCA,OAAO,EAAEK,IAAI;IACbH;EACF,CAAC;AACH;AAEA,OAAO,SAASW,OAAOA,CAAIT,OAAmB,EAAW;EACvD,OAAOA,OAAO,CAACH,IAAI,CAACK,MAAM,GAAG,CAAC;AAChC;AAEA,OAAO,SAASQ,OAAOA,CAAIV,OAAmB,EAAW;EACvD,OAAOA,OAAO,CAACF,MAAM,CAACI,MAAM,GAAG,CAAC;AAClC","ignoreList":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export function getAnnotationById(annotations, id) {
|
|
4
|
+
if (!id) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
return annotations.find(a => a.id === id);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Annotations in paint order (ascending z). */
|
|
11
|
+
export function sortedByZ(annotations) {
|
|
12
|
+
return [...annotations].sort((a, b) => a.z - b.z);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=selectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["getAnnotationById","annotations","id","undefined","find","a","sortedByZ","sort","b","z"],"sourceRoot":"..\\..\\..\\src","sources":["state/selectors.ts"],"mappings":";;AAEA,OAAO,SAASA,iBAAiBA,CAC/BC,WAAyB,EACzBC,EAAiB,EACO;EACxB,IAAI,CAACA,EAAE,EAAE;IACP,OAAOC,SAAS;EAClB;EACA,OAAOF,WAAW,CAACG,IAAI,CAAEC,CAAC,IAAKA,CAAC,CAACH,EAAE,KAAKA,EAAE,CAAC;AAC7C;;AAEA;AACA,OAAO,SAASI,SAASA,CAACL,WAAyB,EAAgB;EACjE,OAAO,CAAC,GAAGA,WAAW,CAAC,CAACM,IAAI,CAAC,CAACF,CAAC,EAAEG,CAAC,KAAKH,CAAC,CAACI,CAAC,GAAGD,CAAC,CAACC,CAAC,CAAC;AACnD","ignoreList":[]}
|