@umituz/react-native-design-system 4.25.8 → 4.25.10
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/package.json +1 -1
- package/src/atoms/AtomicAvatar.tsx +0 -5
- package/src/atoms/AtomicInput.tsx +0 -2
- package/src/atoms/AtomicProgress.tsx +0 -5
- package/src/atoms/AtomicTextArea.tsx +0 -4
- package/src/atoms/card/AtomicCard.tsx +111 -54
- package/src/atoms/input/types.ts +0 -2
- package/src/atoms/skeleton/AtomicSkeleton.tsx +2 -2
- package/src/image/presentation/components/ImageGallery.tsx +16 -15
- package/src/image/presentation/components/editor/StickerPickerSheet.tsx +4 -7
- package/src/index.ts +5 -0
- package/src/layouts/ScreenHeader/ScreenHeader.tsx +0 -2
- package/src/loading/presentation/providers/LoadingProvider.tsx +13 -4
- package/src/molecules/SearchBar/SearchBar.tsx +0 -2
- package/src/molecules/SearchBar/SearchSuggestions.tsx +1 -1
- package/src/molecules/SearchBar/types.ts +0 -1
- package/src/molecules/StepHeader/StepHeader.tsx +1 -1
- package/src/molecules/avatar/Avatar.tsx +76 -71
- package/src/molecules/avatar/AvatarGroup.tsx +1 -1
- package/src/molecules/calendar/presentation/components/CalendarDayCell.tsx +2 -3
- package/src/molecules/calendar/presentation/components/CalendarWeekdayHeader.tsx +1 -1
- package/src/molecules/countdown/components/Countdown.tsx +14 -11
- package/src/molecules/info-grid/InfoGrid.tsx +2 -2
- package/src/onboarding/presentation/components/BackgroundImageCollage.tsx +2 -2
- package/src/onboarding/presentation/components/OnboardingBackground.tsx +63 -49
- package/src/onboarding/presentation/components/OnboardingSlide.tsx +2 -2
- package/src/theme/infrastructure/providers/DesignSystemProvider.tsx +3 -1
- package/src/gallery/gallery-download.service.ts +0 -69
- package/src/gallery/gallery-save.service.ts +0 -80
- package/src/gallery/index.ts +0 -3
- package/src/gallery/types.ts +0 -11
- package/src/image/domain/entities/EditorTypes.ts +0 -23
- package/src/image/domain/entities/editor/EditorConfigTypes.ts +0 -35
- package/src/image/domain/entities/editor/EditorElementTypes.ts +0 -60
- package/src/image/domain/entities/editor/EditorFilterTypes.ts +0 -9
- package/src/image/domain/entities/editor/EditorLayerTypes.ts +0 -34
- package/src/image/domain/entities/editor/EditorStateTypes.ts +0 -35
- package/src/image/domain/entities/editor/EditorToolTypes.ts +0 -33
- package/src/image/infrastructure/services/ImageEditorService.ts +0 -134
- package/src/image/infrastructure/utils/ImageAnalysisUtils.ts +0 -120
- package/src/image/infrastructure/utils/ImageEditorHistoryUtils.ts +0 -63
- package/src/image/infrastructure/utils/LayerManager.ts +0 -65
- package/src/media/infrastructure/hooks/useGenericMediaGeneration.ts +0 -170
- package/src/molecules/ConfirmationModal.tsx +0 -42
- package/src/molecules/calendar/infrastructure/storage/CalendarStore.types.ts +0 -64
- package/src/molecules/calendar/infrastructure/storage/CalendarStore.utils.ts +0 -56
- package/src/molecules/calendar/infrastructure/storage/EventActions.ts +0 -140
- package/src/molecules/calendar/infrastructure/storage/NavigationActions.ts +0 -118
- package/src/molecules/calendar/presentation/hooks/useCalendar.ts +0 -185
- package/src/molecules/confirmation-modal/index.ts +0 -7
- package/src/molecules/listitem/index.ts +0 -6
- package/src/molecules/navigation/components/index.ts +0 -4
- package/src/molecules/navigation/utils/NavigationTheme.ts +0 -21
- package/src/presentation/utils/variants/compound.ts +0 -34
- package/src/services/api/ApiClient.ts +0 -180
- package/src/services/api/index.ts +0 -9
- package/src/services/api/types/ApiTypes.ts +0 -50
- package/src/services/api/utils/requestBuilder.ts +0 -92
- package/src/services/api/utils/responseHandler.ts +0 -130
- package/src/storage/cache/index.ts +0 -28
- package/src/theme/core/tokens/BorderRadius.ts +0 -16
- package/src/utilities/clipboard/ClipboardUtils.ts +0 -67
- package/src/utilities/clipboard/index.ts +0 -5
- package/src/utilities/index.ts +0 -6
- package/src/utilities/sharing/domain/entities/Share.ts +0 -104
- package/src/utilities/sharing/domain/entities/SharingUtils.ts +0 -111
- package/src/utilities/sharing/index.ts +0 -33
- package/src/utilities/sharing/infrastructure/services/SharingService.ts +0 -165
- package/src/utilities/sharing/presentation/hooks/useSharing.ts +0 -116
- package/src/utils/colorMapper.ts +0 -193
- package/src/utils/errors/adapters/CacheErrorAdapter.ts +0 -68
- package/src/utils/errors/adapters/ImageErrorAdapter.ts +0 -91
- package/src/utils/errors/adapters/StorageErrorAdapter.ts +0 -107
- package/src/utils/formatHelper.ts +0 -16
- package/src/utils/formatters/dateFormatter.ts +0 -64
- package/src/utils/formatters/numberFormatter.ts +0 -130
- package/src/utils/index.ts +0 -16
- package/src/utils/styleComposer.ts +0 -94
- package/src/utils/validationHelper.ts +0 -16
- package/src/utils/validators/dataValidators.ts +0 -111
- package/src/utils/validators/numericValidators.ts +0 -106
- package/src/utils/validators/stringValidators.ts +0 -85
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain - Editor Types (Main Export)
|
|
3
|
-
*
|
|
4
|
-
* Central export point for all editor-related types
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// Tools
|
|
8
|
-
export * from './editor/EditorToolTypes';
|
|
9
|
-
|
|
10
|
-
// Elements
|
|
11
|
-
export * from './editor/EditorElementTypes';
|
|
12
|
-
|
|
13
|
-
// Layers & History
|
|
14
|
-
export * from './editor/EditorLayerTypes';
|
|
15
|
-
|
|
16
|
-
// State
|
|
17
|
-
export * from './editor/EditorStateTypes';
|
|
18
|
-
|
|
19
|
-
// Configuration
|
|
20
|
-
export * from './editor/EditorConfigTypes';
|
|
21
|
-
|
|
22
|
-
// Filters
|
|
23
|
-
export * from './editor/EditorFilterTypes';
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain - Editor Configuration Types
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export interface EditorOptions {
|
|
6
|
-
maxLayers?: number;
|
|
7
|
-
maxHistory?: number;
|
|
8
|
-
enableUndo?: boolean;
|
|
9
|
-
enableRedo?: boolean;
|
|
10
|
-
enableFilters?: boolean;
|
|
11
|
-
enableShapes?: boolean;
|
|
12
|
-
enableText?: boolean;
|
|
13
|
-
enableStickers?: boolean;
|
|
14
|
-
enableCrop?: boolean;
|
|
15
|
-
brushSizeRange?: [number, number];
|
|
16
|
-
strokeWidthRange?: [number, number];
|
|
17
|
-
fontSizeRange?: [number, number];
|
|
18
|
-
defaultColors?: string[];
|
|
19
|
-
stickerPacks?: string[];
|
|
20
|
-
customFonts?: string[];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface EditorExportOptions {
|
|
24
|
-
format: 'jpeg' | 'png' | 'webp';
|
|
25
|
-
quality: number;
|
|
26
|
-
backgroundColor?: string;
|
|
27
|
-
includeHiddenLayers?: boolean;
|
|
28
|
-
flattenLayers?: boolean;
|
|
29
|
-
maxSize?: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface EditorEvent {
|
|
33
|
-
type: 'toolChange' | 'layerAdd' | 'layerRemove' | 'layerUpdate' | 'selectionChange' | 'historyChange';
|
|
34
|
-
data: unknown;
|
|
35
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain - Editor Element Types
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { ShapeType } from './EditorToolTypes';
|
|
6
|
-
|
|
7
|
-
export interface EditorPoint {
|
|
8
|
-
x: number;
|
|
9
|
-
y: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface EditorDimensions {
|
|
13
|
-
width: number;
|
|
14
|
-
height: number;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface EditorStroke {
|
|
18
|
-
points: EditorPoint[];
|
|
19
|
-
color: string;
|
|
20
|
-
size: number;
|
|
21
|
-
style: string;
|
|
22
|
-
opacity: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface EditorShape {
|
|
26
|
-
type: ShapeType;
|
|
27
|
-
startPoint: EditorPoint;
|
|
28
|
-
endPoint: EditorPoint;
|
|
29
|
-
color: string;
|
|
30
|
-
strokeWidth: number;
|
|
31
|
-
fillColor?: string;
|
|
32
|
-
opacity: number;
|
|
33
|
-
rotation?: number;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface EditorText {
|
|
37
|
-
id: string;
|
|
38
|
-
text: string;
|
|
39
|
-
position: EditorPoint;
|
|
40
|
-
fontSize: number;
|
|
41
|
-
fontFamily: string;
|
|
42
|
-
color: string;
|
|
43
|
-
backgroundColor?: string;
|
|
44
|
-
rotation: number;
|
|
45
|
-
opacity: number;
|
|
46
|
-
maxWidth?: number;
|
|
47
|
-
textAlign: 'left' | 'center' | 'right';
|
|
48
|
-
fontWeight: 'normal' | 'bold';
|
|
49
|
-
fontStyle: 'normal' | 'italic';
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface EditorSticker {
|
|
53
|
-
id: string;
|
|
54
|
-
uri: string;
|
|
55
|
-
position: EditorPoint;
|
|
56
|
-
size: EditorDimensions;
|
|
57
|
-
rotation: number;
|
|
58
|
-
opacity: number;
|
|
59
|
-
scale: number;
|
|
60
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain - Editor Layer Types
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { EditorStroke, EditorShape, EditorText, EditorSticker } from './EditorElementTypes';
|
|
6
|
-
|
|
7
|
-
export interface EditorLayer {
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
visible: boolean;
|
|
11
|
-
opacity: number;
|
|
12
|
-
locked: boolean;
|
|
13
|
-
elements: Array<{
|
|
14
|
-
type: 'stroke' | 'shape' | 'text' | 'sticker';
|
|
15
|
-
data: EditorStroke | EditorShape | EditorText | EditorSticker;
|
|
16
|
-
}>;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface EditorHistory {
|
|
20
|
-
id: string;
|
|
21
|
-
timestamp: Date;
|
|
22
|
-
layers: EditorLayer[];
|
|
23
|
-
thumbnail?: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface EditorSelection {
|
|
27
|
-
bounds: {
|
|
28
|
-
x: number;
|
|
29
|
-
y: number;
|
|
30
|
-
width: number;
|
|
31
|
-
height: number;
|
|
32
|
-
};
|
|
33
|
-
elements: string[];
|
|
34
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain - Editor State Types
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { EditorTool } from './EditorToolTypes';
|
|
6
|
-
import type { EditorLayer } from './EditorLayerTypes';
|
|
7
|
-
import type { EditorSelection } from './EditorLayerTypes';
|
|
8
|
-
import type { EditorHistory } from './EditorLayerTypes';
|
|
9
|
-
import type { EditorPoint, EditorDimensions } from './EditorElementTypes';
|
|
10
|
-
import type { EditorFilter } from './EditorFilterTypes';
|
|
11
|
-
|
|
12
|
-
export interface EditorCropArea {
|
|
13
|
-
x: number;
|
|
14
|
-
y: number;
|
|
15
|
-
width: number;
|
|
16
|
-
height: number;
|
|
17
|
-
aspectRatio?: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface EditorState {
|
|
21
|
-
originalUri: string;
|
|
22
|
-
currentUri?: string;
|
|
23
|
-
tool: EditorTool;
|
|
24
|
-
selectedLayer?: string;
|
|
25
|
-
layers: EditorLayer[];
|
|
26
|
-
history: EditorHistory[];
|
|
27
|
-
historyIndex: number;
|
|
28
|
-
selection?: EditorSelection;
|
|
29
|
-
cropArea?: EditorCropArea;
|
|
30
|
-
activeFilter?: EditorFilter;
|
|
31
|
-
isDirty: boolean;
|
|
32
|
-
dimensions: EditorDimensions;
|
|
33
|
-
zoom: number;
|
|
34
|
-
pan: EditorPoint;
|
|
35
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Domain - Editor Tool Types
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export enum EditorTool {
|
|
6
|
-
MOVE = 'move',
|
|
7
|
-
BRUSH = 'brush',
|
|
8
|
-
ERASER = 'eraser',
|
|
9
|
-
TEXT = 'text',
|
|
10
|
-
SHAPE = 'shape',
|
|
11
|
-
CROP = 'crop',
|
|
12
|
-
FILTER = 'filter',
|
|
13
|
-
STICKER = 'sticker',
|
|
14
|
-
SELECT = 'select',
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export enum ShapeType {
|
|
18
|
-
RECTANGLE = 'rectangle',
|
|
19
|
-
CIRCLE = 'circle',
|
|
20
|
-
LINE = 'line',
|
|
21
|
-
ARROW = 'arrow',
|
|
22
|
-
TRIANGLE = 'triangle',
|
|
23
|
-
STAR = 'star',
|
|
24
|
-
HEART = 'heart',
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export enum BrushStyle {
|
|
28
|
-
NORMAL = 'normal',
|
|
29
|
-
MARKER = 'marker',
|
|
30
|
-
SPRAY = 'spray',
|
|
31
|
-
PENCIL = 'pencil',
|
|
32
|
-
CALIGRAPHY = 'caligraphy',
|
|
33
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure - Editor Service
|
|
3
|
-
*
|
|
4
|
-
* Core editing functionality with layer and tool management
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
EditorTool,
|
|
9
|
-
type EditorState,
|
|
10
|
-
type EditorLayer,
|
|
11
|
-
type EditorHistory
|
|
12
|
-
} from '../../domain/entities/EditorTypes';
|
|
13
|
-
import { ImageErrorHandler, IMAGE_ERROR_CODES } from '../utils/ImageErrorHandler';
|
|
14
|
-
import { ImageEditorHistoryUtils } from '../utils/ImageEditorHistoryUtils';
|
|
15
|
-
|
|
16
|
-
export class ImageEditorService {
|
|
17
|
-
static generateId(): string {
|
|
18
|
-
return Math.random().toString(36).substring(2, 11);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static createInitialState(
|
|
22
|
-
uri: string,
|
|
23
|
-
dimensions: { width: number; height: number }
|
|
24
|
-
): EditorState {
|
|
25
|
-
const defaultLayer: EditorLayer = {
|
|
26
|
-
id: 'background',
|
|
27
|
-
name: 'Background',
|
|
28
|
-
visible: true,
|
|
29
|
-
opacity: 1,
|
|
30
|
-
locked: true,
|
|
31
|
-
elements: [],
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
originalUri: uri,
|
|
36
|
-
tool: EditorTool.MOVE,
|
|
37
|
-
layers: [defaultLayer],
|
|
38
|
-
history: [{
|
|
39
|
-
id: ImageEditorService.generateId(),
|
|
40
|
-
timestamp: new Date(),
|
|
41
|
-
layers: [defaultLayer],
|
|
42
|
-
}],
|
|
43
|
-
historyIndex: 0,
|
|
44
|
-
isDirty: false,
|
|
45
|
-
dimensions,
|
|
46
|
-
zoom: 1,
|
|
47
|
-
pan: { x: 0, y: 0 },
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
static addLayer(state: EditorState, name?: string): EditorState {
|
|
52
|
-
const newLayer: EditorLayer = {
|
|
53
|
-
id: ImageEditorService.generateId(),
|
|
54
|
-
name: name || `Layer ${state.layers.length}`,
|
|
55
|
-
visible: true,
|
|
56
|
-
opacity: 1,
|
|
57
|
-
locked: false,
|
|
58
|
-
elements: [],
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
return ImageEditorService.commitHistory(state, [...state.layers, newLayer], {
|
|
62
|
-
selectedLayer: newLayer.id,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
static removeLayer(state: EditorState, layerId: string): EditorState {
|
|
67
|
-
if (state.layers.length <= 1) {
|
|
68
|
-
throw ImageErrorHandler.createError('Cannot remove background', IMAGE_ERROR_CODES.VALIDATION_ERROR, 'removeLayer');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const newLayers = state.layers.filter(layer => layer.id !== layerId);
|
|
72
|
-
return ImageEditorService.commitHistory(state, newLayers, {
|
|
73
|
-
selectedLayer: newLayers[0]!.id,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
static updateLayer(state: EditorState, layerId: string, updates: Partial<EditorLayer>): EditorState {
|
|
78
|
-
const newLayers = state.layers.map(layer => layer.id === layerId ? { ...layer, ...updates } : layer);
|
|
79
|
-
return ImageEditorService.commitHistory(state, newLayers);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
static addElementToLayer(state: EditorState, layerId: string, element: EditorLayer['elements'][number]): EditorState {
|
|
83
|
-
const layer = state.layers.find(l => l.id === layerId);
|
|
84
|
-
if (!layer || layer.locked) {
|
|
85
|
-
throw ImageErrorHandler.createError('Invalid layer operation', IMAGE_ERROR_CODES.VALIDATION_ERROR, 'addElementToLayer');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const newLayers = state.layers.map(l =>
|
|
89
|
-
l.id === layerId ? { ...l, elements: [...l.elements, element] } : l
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
return ImageEditorService.commitHistory(state, newLayers);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
private static commitHistory(
|
|
96
|
-
state: EditorState,
|
|
97
|
-
newLayers: EditorLayer[],
|
|
98
|
-
additionalState: Partial<EditorState> = {}
|
|
99
|
-
): EditorState {
|
|
100
|
-
const history: EditorHistory = {
|
|
101
|
-
id: ImageEditorService.generateId(),
|
|
102
|
-
timestamp: new Date(),
|
|
103
|
-
layers: newLayers,
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
...ImageEditorHistoryUtils.addToHistory(state, history),
|
|
108
|
-
...additionalState,
|
|
109
|
-
layers: newLayers,
|
|
110
|
-
isDirty: true,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
static undo = ImageEditorHistoryUtils.undo;
|
|
115
|
-
static redo = ImageEditorHistoryUtils.redo;
|
|
116
|
-
static canUndo = ImageEditorHistoryUtils.canUndo;
|
|
117
|
-
static canRedo = ImageEditorHistoryUtils.canRedo;
|
|
118
|
-
|
|
119
|
-
static setTool(state: EditorState, tool: EditorTool): EditorState {
|
|
120
|
-
return { ...state, tool };
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
static setZoom(state: EditorState, zoom: number): EditorState {
|
|
124
|
-
return { ...state, zoom: Math.max(0.1, Math.min(5, zoom)) };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
static setPan(state: EditorState, pan: { x: number; y: number }): EditorState {
|
|
128
|
-
return { ...state, pan };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
static getVisibleLayers(state: EditorState): EditorLayer[] {
|
|
132
|
-
return state.layers.filter(layer => layer.visible);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Image Infrastructure - Image Analysis
|
|
3
|
-
*
|
|
4
|
-
* Image analysis utilities
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export class ImageAnalysisUtils {
|
|
8
|
-
static calculateColorBalance(imageData: Uint8ClampedArray): {
|
|
9
|
-
redBalance: number;
|
|
10
|
-
greenBalance: number;
|
|
11
|
-
blueBalance: number;
|
|
12
|
-
} {
|
|
13
|
-
let redSum = 0, greenSum = 0, blueSum = 0;
|
|
14
|
-
const pixelCount = imageData.length / 4;
|
|
15
|
-
|
|
16
|
-
for (let i = 0; i < imageData.length; i += 4) {
|
|
17
|
-
redSum += imageData[i]!;
|
|
18
|
-
greenSum += imageData[i + 1]!;
|
|
19
|
-
blueSum += imageData[i + 2]!;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const redMean = redSum / pixelCount;
|
|
23
|
-
const greenMean = greenSum / pixelCount;
|
|
24
|
-
const blueMean = blueSum / pixelCount;
|
|
25
|
-
const grayMean = (redMean + greenMean + blueMean) / 3;
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
redBalance: (grayMean - redMean) / 255,
|
|
29
|
-
greenBalance: (grayMean - greenMean) / 255,
|
|
30
|
-
blueBalance: (grayMean - blueMean) / 255,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
static detectNoise(imageData: Uint8ClampedArray): number {
|
|
35
|
-
let noiseLevel = 0;
|
|
36
|
-
let sampleCount = 0;
|
|
37
|
-
|
|
38
|
-
for (let i = 0; i < imageData.length - 40; i += 40) {
|
|
39
|
-
const r1 = imageData[i]!;
|
|
40
|
-
const g1 = imageData[i + 1]!;
|
|
41
|
-
const b1 = imageData[i + 2]!;
|
|
42
|
-
|
|
43
|
-
const r2 = imageData[i + 4]!;
|
|
44
|
-
const g2 = imageData[i + 5]!;
|
|
45
|
-
const b2 = imageData[i + 6]!;
|
|
46
|
-
|
|
47
|
-
const diff = Math.abs(r1 - r2) + Math.abs(g1 - g2) + Math.abs(b1 - b2);
|
|
48
|
-
noiseLevel += diff;
|
|
49
|
-
sampleCount++;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return noiseLevel / (sampleCount * 3 * 255);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
static applySharpening(imageData: Uint8ClampedArray, width: number, height: number): Uint8ClampedArray {
|
|
56
|
-
const result = new Uint8ClampedArray(imageData.length);
|
|
57
|
-
const kernel = [
|
|
58
|
-
0, -1, 0,
|
|
59
|
-
-1, 5, -1,
|
|
60
|
-
0, -1, 0
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
for (let i = 0; i < imageData.length; i += 4) {
|
|
64
|
-
const pixelIndex = i / 4;
|
|
65
|
-
const x = pixelIndex % width;
|
|
66
|
-
const y = Math.floor(pixelIndex / width);
|
|
67
|
-
|
|
68
|
-
for (let c = 0; c < 3; c++) {
|
|
69
|
-
let sum = 0;
|
|
70
|
-
for (let ky = -1; ky <= 1; ky++) {
|
|
71
|
-
for (let kx = -1; kx <= 1; kx++) {
|
|
72
|
-
const nx = x + kx;
|
|
73
|
-
const ny = y + ky;
|
|
74
|
-
|
|
75
|
-
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
|
76
|
-
const neighborIndex = (ny * width + nx) * 4 + c;
|
|
77
|
-
sum += (imageData[neighborIndex] ?? 0) * (kernel[(ky + 1) * 3 + (kx + 1)] ?? 0);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
result[i + c] = Math.min(255, Math.max(0, sum));
|
|
82
|
-
}
|
|
83
|
-
result[i + 3] = imageData[i + 3] ?? 255;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return result;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
static applyNoiseReduction(imageData: Uint8ClampedArray, width: number, height: number): Uint8ClampedArray {
|
|
90
|
-
const result = new Uint8ClampedArray(imageData.length);
|
|
91
|
-
|
|
92
|
-
for (let i = 0; i < imageData.length; i += 4) {
|
|
93
|
-
const pixelIndex = i / 4;
|
|
94
|
-
const x = pixelIndex % width;
|
|
95
|
-
const y = Math.floor(pixelIndex / width);
|
|
96
|
-
|
|
97
|
-
for (let c = 0; c < 3; c++) {
|
|
98
|
-
const values: number[] = [];
|
|
99
|
-
|
|
100
|
-
for (let dy = -1; dy <= 1; dy++) {
|
|
101
|
-
for (let dx = -1; dx <= 1; dx++) {
|
|
102
|
-
const nx = x + dx;
|
|
103
|
-
const ny = y + dy;
|
|
104
|
-
|
|
105
|
-
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
|
|
106
|
-
const neighborIndex = (ny * width + nx) * 4 + c;
|
|
107
|
-
values.push(imageData[neighborIndex] ?? 0);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
values.sort((a, b) => a - b);
|
|
113
|
-
result[i + c] = values[Math.floor(values.length / 2)] ?? 0;
|
|
114
|
-
}
|
|
115
|
-
result[i + 3] = imageData[i + 3] ?? 255;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return result;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure - Editor History Utils
|
|
3
|
-
*
|
|
4
|
-
* Logic for managing editor state history and undo/redo
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { type EditorState, type EditorHistory } from '../../domain/entities/EditorTypes';
|
|
8
|
-
|
|
9
|
-
export class ImageEditorHistoryUtils {
|
|
10
|
-
static addToHistory(
|
|
11
|
-
state: EditorState,
|
|
12
|
-
newHistory: EditorHistory,
|
|
13
|
-
maxHistory: number = 50
|
|
14
|
-
): EditorState {
|
|
15
|
-
const newHistoryArray = [...state.history.slice(0, state.historyIndex + 1), newHistory];
|
|
16
|
-
|
|
17
|
-
if (newHistoryArray.length > maxHistory) {
|
|
18
|
-
newHistoryArray.shift();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
...state,
|
|
23
|
-
history: newHistoryArray,
|
|
24
|
-
historyIndex: newHistoryArray.length - 1,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static undo(state: EditorState): EditorState {
|
|
29
|
-
if (state.historyIndex <= 0) return state;
|
|
30
|
-
|
|
31
|
-
const newIndex = state.historyIndex - 1;
|
|
32
|
-
const historyState = state.history[newIndex]!;
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
...state,
|
|
36
|
-
layers: historyState.layers,
|
|
37
|
-
historyIndex: newIndex,
|
|
38
|
-
isDirty: true,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
static redo(state: EditorState): EditorState {
|
|
43
|
-
if (state.historyIndex >= state.history.length - 1) return state;
|
|
44
|
-
|
|
45
|
-
const newIndex = state.historyIndex + 1;
|
|
46
|
-
const historyState = state.history[newIndex]!;
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
...state,
|
|
50
|
-
layers: historyState.layers,
|
|
51
|
-
historyIndex: newIndex,
|
|
52
|
-
isDirty: true,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
static canUndo(state: EditorState): boolean {
|
|
57
|
-
return state.historyIndex > 0;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
static canRedo(state: EditorState): boolean {
|
|
61
|
-
return state.historyIndex < state.history.length - 1;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure - Layer Manager
|
|
3
|
-
*
|
|
4
|
-
* Manages editor layers with composition and rendering
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { EditorLayer } from '../../domain/entities/EditorTypes';
|
|
8
|
-
import { ImageEditorService } from '../services/ImageEditorService';
|
|
9
|
-
|
|
10
|
-
export type LayerOperation = 'add' | 'remove' | 'move' | 'merge' | 'duplicate';
|
|
11
|
-
|
|
12
|
-
export interface LayerComposition {
|
|
13
|
-
width: number;
|
|
14
|
-
height: number;
|
|
15
|
-
backgroundColor?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class LayerManager {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
static mergeLayers(
|
|
22
|
-
layers: EditorLayer[],
|
|
23
|
-
targetIds: string[]
|
|
24
|
-
): EditorLayer[] {
|
|
25
|
-
const targetLayers = layers.filter(layer => targetIds.includes(layer.id));
|
|
26
|
-
const otherLayers = layers.filter(layer => !targetIds.includes(layer.id));
|
|
27
|
-
|
|
28
|
-
if (targetLayers.length === 0) return layers;
|
|
29
|
-
|
|
30
|
-
const mergedElements = targetLayers.flatMap(layer => layer.elements);
|
|
31
|
-
const mergedLayer: EditorLayer = {
|
|
32
|
-
id: ImageEditorService.generateId(),
|
|
33
|
-
name: targetLayers.map(l => l.name).join(' + '),
|
|
34
|
-
visible: true,
|
|
35
|
-
opacity: 1,
|
|
36
|
-
locked: false,
|
|
37
|
-
elements: mergedElements,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
return [...otherLayers, mergedLayer];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static duplicateLayer(layer: EditorLayer): EditorLayer {
|
|
44
|
-
return {
|
|
45
|
-
...layer,
|
|
46
|
-
id: ImageEditorService.generateId(),
|
|
47
|
-
name: `${layer.name} Copy`,
|
|
48
|
-
elements: [...layer.elements],
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
static reorderLayers(
|
|
53
|
-
layers: Array<{ id: string; index?: number }>,
|
|
54
|
-
fromIndex: number,
|
|
55
|
-
toIndex: number
|
|
56
|
-
): Array<{ id: string; index?: number }> {
|
|
57
|
-
const result = [...layers];
|
|
58
|
-
const [moved] = result.splice(fromIndex, 1) as [{ id: string; index?: number }];
|
|
59
|
-
result.splice(toIndex, 0, moved);
|
|
60
|
-
|
|
61
|
-
return result.map((layer, index) => ({ ...layer, index }));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|