@umituz/react-native-image 1.3.1 → 1.3.3

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.
@@ -1,118 +0,0 @@
1
- /**
2
- * Presentation - Filter Slider Component
3
- *
4
- * Slider for adjusting filter parameters
5
- */
6
-
7
- import React from 'react';
8
- import { View, StyleSheet, Text } from 'react-native';
9
- import Slider from '@react-native-community/slider';
10
-
11
- interface FilterSliderProps {
12
- label: string;
13
- value: number;
14
- onValueChange: (value: number) => void;
15
- minimumValue?: number;
16
- maximumValue?: number;
17
- step?: number;
18
- valueFormat?: (value: number) => string;
19
- color?: string;
20
- }
21
-
22
- export function FilterSlider({
23
- label,
24
- value,
25
- onValueChange,
26
- minimumValue = 0,
27
- maximumValue = 100,
28
- step = 1,
29
- valueFormat,
30
- color = '#007bff',
31
- }: FilterSliderProps) {
32
- const formatValue = (val: number): string => {
33
- if (valueFormat) return valueFormat(val);
34
- return `${Math.round(val)}`;
35
- };
36
-
37
- return (
38
- <View style={styles.container}>
39
- <View style={styles.labelContainer}>
40
- <Text style={styles.label}>{label}</Text>
41
- <Text style={[styles.value, { color }]}>
42
- {formatValue(value)}
43
- </Text>
44
- </View>
45
-
46
- <View style={[styles.sliderTrack, { backgroundColor: `${color}20` }]}>
47
- <View
48
- style={[
49
- styles.sliderFill,
50
- {
51
- width: `${((value - minimumValue) / (maximumValue - minimumValue)) * 100}%`,
52
- backgroundColor: color
53
- }
54
- ]}
55
- />
56
- <Slider
57
- style={styles.slider}
58
- minimumValue={minimumValue}
59
- maximumValue={maximumValue}
60
- value={value}
61
- onValueChange={onValueChange}
62
- step={step}
63
- minimumTrackTintColor="transparent"
64
- maximumTrackTintColor="transparent"
65
- thumbTintColor={color}
66
- />
67
- </View>
68
- </View>
69
- );
70
- }
71
-
72
- const styles = StyleSheet.create({
73
- container: {
74
- paddingVertical: 8,
75
- gap: 8,
76
- },
77
- labelContainer: {
78
- flexDirection: 'row',
79
- justifyContent: 'space-between',
80
- alignItems: 'center',
81
- },
82
- label: {
83
- fontSize: 14,
84
- fontWeight: '500',
85
- color: '#333333',
86
- },
87
- value: {
88
- fontSize: 14,
89
- fontWeight: '600',
90
- },
91
- sliderTrack: {
92
- height: 6,
93
- borderRadius: 3,
94
- position: 'relative',
95
- },
96
- sliderFill: {
97
- height: '100%',
98
- borderRadius: 3,
99
- position: 'absolute',
100
- left: 0,
101
- top: 0,
102
- },
103
- slider: {
104
- position: 'absolute',
105
- left: 0,
106
- top: 0,
107
- width: '100%',
108
- height: '100%',
109
- opacity: 0,
110
- },
111
- thumb: {
112
- width: 20,
113
- height: 20,
114
- borderRadius: 10,
115
- borderWidth: 2,
116
- borderColor: '#ffffff',
117
- },
118
- });
@@ -1,188 +0,0 @@
1
- /**
2
- * Presentation - Editor Tool Hook
3
- *
4
- * Manages individual editor tools and their states
5
- */
6
-
7
- import { useState, useCallback } from 'react';
8
- import { DrawingEngine, type DrawingPath, type DrawingConfig } from '../../infrastructure/utils/DrawingEngine';
9
- import { CropTool, type CropConfig } from '../../infrastructure/utils/CropTool';
10
- import { TextEditor, type TextFormatting } from '../../infrastructure/utils/TextEditor';
11
- import { ShapeRenderer, type ShapeStyle } from '../../infrastructure/utils/ShapeRenderer';
12
-
13
- interface ToolState {
14
- isDrawing: boolean;
15
- currentPath: DrawingPath;
16
- startPoint?: { x: number; y: number };
17
- currentTool: string;
18
- }
19
-
20
- interface UseEditorToolsOptions {
21
- onStateChange?: (state: any) => void;
22
- canvas?: HTMLCanvasElement | null;
23
- }
24
-
25
- export function useEditorTools({ onStateChange, canvas }: UseEditorToolsOptions = {}) {
26
- const [toolState, setToolState] = useState<ToolState>({
27
- isDrawing: false,
28
- currentPath: [],
29
- currentTool: 'move',
30
- });
31
-
32
- const [drawingConfig, setDrawingConfig] = useState<DrawingConfig>({
33
- color: '#000000',
34
- size: 5,
35
- opacity: 1,
36
- style: 'normal',
37
- smoothing: true,
38
- });
39
-
40
- const [cropConfig, setCropConfig] = useState<CropConfig>({
41
- aspectRatio: undefined,
42
- lockAspectRatio: false,
43
- showGrid: true,
44
- });
45
-
46
- const [textFormatting, setTextFormatting] = useState<TextFormatting>({
47
- fontSize: 16,
48
- fontFamily: 'Arial',
49
- fontWeight: 'normal',
50
- fontStyle: 'normal',
51
- color: '#000000',
52
- textAlign: 'left',
53
- opacity: 1,
54
- });
55
-
56
- const setTool = useCallback((tool: string) => {
57
- const newState = { ...toolState, currentTool: tool };
58
- setToolState(newState);
59
- onStateChange?.(newState);
60
- }, [toolState, onStateChange]);
61
-
62
- const startDrawing = useCallback((point: { x: number; y: number }) => {
63
- if (!canvas) return;
64
-
65
- const ctx = canvas.getContext('2d');
66
- if (!ctx) return;
67
-
68
- const newState = {
69
- ...toolState,
70
- isDrawing: true,
71
- startPoint: point,
72
- currentPath: [point],
73
- };
74
- setToolState(newState);
75
- }, [toolState, canvas]);
76
-
77
- const draw = useCallback((point: { x: number; y: number }) => {
78
- if (!toolState.isDrawing || !canvas) return;
79
-
80
- const ctx = canvas.getContext('2d');
81
- if (!ctx) return;
82
-
83
- const newPath = [...toolState.currentPath, point];
84
-
85
- setToolState(prev => ({
86
- ...prev,
87
- currentPath: newPath,
88
- }));
89
-
90
- // Real-time drawing feedback
91
- const tempPath = [...toolState.currentPath, point];
92
- DrawingEngine.drawStroke(ctx, tempPath, drawingConfig);
93
- }, [toolState.isDrawing, toolState.currentPath, drawingConfig, canvas]);
94
-
95
- const stopDrawing = useCallback(() => {
96
- if (!toolState.isDrawing || !canvas) return;
97
-
98
- const ctx = canvas.getContext('2d');
99
- if (!ctx) return;
100
-
101
- // Finalize the stroke
102
- DrawingEngine.drawStroke(ctx, toolState.currentPath, drawingConfig);
103
-
104
- const newState = {
105
- ...toolState,
106
- isDrawing: false,
107
- currentPath: [],
108
- startPoint: undefined,
109
- };
110
- setToolState(newState);
111
- onStateChange?.(newState);
112
- }, [toolState, drawingConfig, canvas, onStateChange]);
113
-
114
- const drawShape = useCallback((
115
- type: 'rectangle' | 'circle' | 'line' | 'arrow',
116
- startPoint: { x: number; y: number },
117
- endPoint: { x: number; y: number },
118
- style: ShapeStyle
119
- ) => {
120
- if (!canvas) return;
121
-
122
- const ctx = canvas.getContext('2d');
123
- if (!ctx) return;
124
-
125
- DrawingEngine.drawShape(ctx, type, startPoint, endPoint, style as any);
126
- onStateChange?.({ toolState, shape: { type, startPoint, endPoint, style } });
127
- }, [canvas, onStateChange, toolState]);
128
-
129
- const addText = useCallback((
130
- text: string,
131
- position: { x: number; y: number },
132
- formatting?: Partial<TextFormatting>
133
- ) => {
134
- if (!canvas) return;
135
-
136
- const ctx = canvas.getContext('2d');
137
- if (!ctx) return;
138
-
139
- const finalFormatting = { ...textFormatting, ...formatting };
140
- TextEditor.renderText(ctx, text, position, finalFormatting);
141
-
142
- setTextFormatting(finalFormatting);
143
- onStateChange?.({ toolState, text: { text, position, formatting: finalFormatting } });
144
- }, [textFormatting, canvas, onStateChange, toolState]);
145
-
146
- const setCropArea = useCallback((cropArea: any) => {
147
- if (!canvas) return;
148
-
149
- const ctx = canvas.getContext('2d');
150
- if (!ctx) return;
151
-
152
- CropTool.drawCropOverlay(ctx, cropArea, cropConfig);
153
- onStateChange?.({ toolState, cropArea });
154
- }, [cropConfig, canvas, onStateChange, toolState]);
155
-
156
- const clearCanvas = useCallback(() => {
157
- if (!canvas) return;
158
-
159
- const ctx = canvas.getContext('2d');
160
- if (!ctx) return;
161
-
162
- ctx.clearRect(0, 0, canvas.width, canvas.height);
163
- onStateChange?.({ toolState, cleared: true });
164
- }, [canvas, onStateChange, toolState]);
165
-
166
- return {
167
- // State
168
- toolState,
169
- drawingConfig,
170
- cropConfig,
171
- textFormatting,
172
-
173
- // Actions
174
- setTool,
175
- startDrawing,
176
- draw,
177
- stopDrawing,
178
- drawShape,
179
- addText,
180
- setCropArea,
181
- clearCanvas,
182
-
183
- // Config setters
184
- setDrawingConfig,
185
- setCropConfig,
186
- setTextFormatting,
187
- };
188
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Presentation - Image Annotation Hook
3
- */
4
-
5
- import { useCallback } from 'react';
6
- import { useImageOperation } from './useImageOperation';
7
- import { ImageAnnotationService, type ImageAnnotation, type TextOverlay, type DrawingElement, type WatermarkOptions } from '../../infrastructure/services/ImageAnnotationService';
8
-
9
- export const useImageAnnotation = () => {
10
- const { isProcessing, error, execute } = useImageOperation();
11
-
12
- const addTextOverlay = useCallback((uri: string, overlay: TextOverlay) =>
13
- execute(() => ImageAnnotationService.addTextOverlay(uri, overlay), 'Failed to add text'), [execute]);
14
-
15
- const addDrawingElements = useCallback((uri: string, elements: DrawingElement[]) =>
16
- execute(() => ImageAnnotationService.addDrawingElements(uri, elements), 'Failed to add drawing'), [execute]);
17
-
18
- const addWatermark = useCallback((uri: string, options: WatermarkOptions) =>
19
- execute(() => ImageAnnotationService.addWatermark(uri, options), 'Failed to add watermark'), [execute]);
20
-
21
- const applyAnnotation = useCallback((uri: string, annotation: ImageAnnotation) =>
22
- execute(() => ImageAnnotationService.applyAnnotation(uri, annotation), 'Failed to apply annotation'), [execute]);
23
-
24
- return {
25
- addTextOverlay,
26
- addDrawingElements,
27
- addWatermark,
28
- applyAnnotation,
29
- isAnnotating: isProcessing,
30
- annotationError: error,
31
- };
32
- };
@@ -1,182 +0,0 @@
1
- /**
2
- * Presentation - Advanced Image Editor Hook
3
- */
4
-
5
- import { useState, useCallback, useRef } from 'react';
6
- import type {
7
- EditorState,
8
- EditorTool,
9
- EditorOptions,
10
- EditorExportOptions,
11
- } from '../../domain/entities/EditorTypes';
12
- import { ImageEditorService } from '../../infrastructure/services/ImageEditorService';
13
- import type { ImageManipulationResult } from '../../domain/entities/ImageTypes';
14
-
15
- interface UseEditorConfig {
16
- onSave?: (result: ImageManipulationResult) => void | Promise<void>;
17
- onCancel?: () => void;
18
- options?: EditorOptions;
19
- }
20
-
21
- export function useImageEditor({ onSave, onCancel, options }: UseEditorConfig = {}) {
22
- const [editorState, setEditorState] = useState<EditorState | null>(null);
23
- const [isProcessing, setIsProcessing] = useState(false);
24
- const [error, setError] = useState<string | null>(null);
25
-
26
- const canvasRef = useRef<HTMLCanvasElement | null>(null);
27
-
28
- const initializeEditor = useCallback(async (uri: string) => {
29
- try {
30
- setError(null);
31
- setIsProcessing(true);
32
-
33
- // Get image dimensions
34
- const dimensions = await getImageDimensions(uri);
35
- const state = ImageEditorService.createInitialState(uri, dimensions, options);
36
-
37
- setEditorState(state);
38
- setIsProcessing(false);
39
- } catch (err) {
40
- setError(err instanceof Error ? err.message : 'Failed to initialize editor');
41
- setIsProcessing(false);
42
- }
43
- }, [options]);
44
-
45
- const setTool = useCallback((tool: EditorTool) => {
46
- if (!editorState) return;
47
-
48
- const newState = ImageEditorService.setTool(editorState, tool);
49
- setEditorState(newState);
50
- }, [editorState]);
51
-
52
- const addLayer = useCallback((name?: string) => {
53
- if (!editorState) return;
54
-
55
- const newState = ImageEditorService.addLayer(editorState, name);
56
- setEditorState(newState);
57
- }, [editorState]);
58
-
59
- const removeLayer = useCallback((layerId: string) => {
60
- if (!editorState) return;
61
-
62
- try {
63
- const newState = ImageEditorService.removeLayer(editorState, layerId);
64
- setEditorState(newState);
65
- } catch (err) {
66
- setError(err instanceof Error ? err.message : 'Failed to remove layer');
67
- }
68
- }, [editorState]);
69
-
70
- const undo = useCallback(() => {
71
- if (!editorState) return;
72
-
73
- const newState = ImageEditorService.undo(editorState);
74
- setEditorState(newState);
75
- }, [editorState]);
76
-
77
- const redo = useCallback(() => {
78
- if (!editorState) return;
79
-
80
- const newState = ImageEditorService.redo(editorState);
81
- setEditorState(newState);
82
- }, [editorState]);
83
-
84
- const exportImage = useCallback(async (exportOptions?: EditorExportOptions) => {
85
- if (!editorState || !canvasRef.current) return null;
86
-
87
- try {
88
- setIsProcessing(true);
89
- setError(null);
90
-
91
- // Compose all layers
92
- const canvas = canvasRef.current;
93
- const result = await composeAndExport(canvas, editorState, exportOptions);
94
-
95
- if (onSave) {
96
- await onSave(result);
97
- }
98
-
99
- setIsProcessing(false);
100
- return result;
101
- } catch (err) {
102
- setError(err instanceof Error ? err.message : 'Failed to export image');
103
- setIsProcessing(false);
104
- return null;
105
- }
106
- }, [editorState, onSave]);
107
-
108
- const cancel = useCallback(() => {
109
- setEditorState(null);
110
- setError(null);
111
- onCancel?.();
112
- }, [onCancel]);
113
-
114
- return {
115
- // State
116
- editorState,
117
- isProcessing,
118
- error,
119
- canUndo: editorState ? ImageEditorService.canUndo(editorState) : false,
120
- canRedo: editorState ? ImageEditorService.canRedo(editorState) : false,
121
-
122
- // Actions
123
- initializeEditor,
124
- setTool,
125
- addLayer,
126
- removeLayer,
127
- undo,
128
- redo,
129
- exportImage,
130
- cancel,
131
-
132
- // Refs
133
- canvasRef,
134
- };
135
- }
136
-
137
- async function getImageDimensions(uri: string): Promise<{ width: number; height: number }> {
138
- return new Promise((resolve) => {
139
- const img = new Image();
140
- img.onload = () => {
141
- resolve({ width: img.width, height: img.height });
142
- };
143
- img.src = uri;
144
- });
145
- }
146
-
147
- async function composeAndExport(
148
- canvas: HTMLCanvasElement,
149
- state: EditorState,
150
- options?: EditorExportOptions
151
- ): Promise<ImageManipulationResult> {
152
- const ctx = canvas.getContext('2d');
153
- if (!ctx) throw new Error('Failed to get canvas context');
154
-
155
- // Clear canvas
156
- ctx.clearRect(0, 0, canvas.width, canvas.height);
157
-
158
- // Apply all layers
159
- const visibleLayers = ImageEditorService.getVisibleLayers(state);
160
-
161
- // Background layer (original image)
162
- if (visibleLayers.length > 0) {
163
- const backgroundLayer = visibleLayers[0];
164
- // Would render original image here
165
- }
166
-
167
- // Export canvas to blob
168
- return new Promise((resolve) => {
169
- canvas.toBlob(async (blob) => {
170
- if (!blob) throw new Error('Failed to create blob');
171
-
172
- const url = URL.createObjectURL(blob);
173
- resolve({
174
- uri: url,
175
- width: canvas.width,
176
- height: canvas.height,
177
- });
178
-
179
- URL.revokeObjectURL(url);
180
- }, options?.format || 'jpeg', options?.quality || 0.9);
181
- });
182
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * Presentation - Image Filter Hook
3
- */
4
-
5
- import { useCallback } from 'react';
6
- import { useImageOperation } from './useImageOperation';
7
- import { ImageFilterService } from '../../infrastructure/services/ImageFilterService';
8
- import type {
9
- ImageFilter,
10
- ImageColorAdjustment,
11
- ImageQualityMetrics,
12
- ImageColorPalette,
13
- } from '../../domain/entities/ImageFilterTypes';
14
-
15
- export const useImageFilter = () => {
16
- const { isProcessing, error, execute } = useImageOperation();
17
-
18
- const applyFilter = useCallback((uri: string, filter: ImageFilter) =>
19
- execute(() => ImageFilterService.applyFilter(uri, filter), 'Failed to apply filter'), [execute]);
20
-
21
- const applyColorAdjustment = useCallback((uri: string, adjustment: ImageColorAdjustment) =>
22
- execute(() => ImageFilterService.applyColorAdjustment(uri, adjustment), 'Failed to adjust colors'), [execute]);
23
-
24
- const analyzeQuality = useCallback((uri: string) =>
25
- execute(() => ImageFilterService.analyzeQuality(uri), 'Failed to analyze quality'), [execute]);
26
-
27
- const extractColorPalette = useCallback((uri: string, colorCount?: number) =>
28
- execute(() => ImageFilterService.extractColorPalette(uri, colorCount), 'Failed to extract colors'), [execute]);
29
-
30
- return {
31
- applyFilter,
32
- applyColorAdjustment,
33
- analyzeQuality,
34
- extractColorPalette,
35
- isFiltering: isProcessing,
36
- filterError: error,
37
- };
38
- };