@umituz/react-native-photo-editor 1.0.3 → 1.0.5

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.
@@ -0,0 +1,31 @@
1
+ const js = require("@eslint/js");
2
+ const tseslint = require("@typescript-eslint/eslint-plugin");
3
+ const tsParser = require("@typescript-eslint/parser");
4
+
5
+ module.exports = [
6
+ js.configs.recommended,
7
+ {
8
+ files: ["**/*.ts", "**/*.tsx"],
9
+ languageOptions: {
10
+ parser: tsParser,
11
+ parserOptions: {
12
+ ecmaVersion: 2020,
13
+ sourceType: "module",
14
+ project: "./tsconfig.json",
15
+ },
16
+ },
17
+ plugins: {
18
+ "@typescript-eslint": tseslint,
19
+ },
20
+ rules: {
21
+ ...tseslint.configs.recommended.rules,
22
+ "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
23
+ "@typescript-eslint/explicit-function-return-type": "off",
24
+ "@typescript-eslint/no-explicit-any": "warn",
25
+ "no-console": "off",
26
+ },
27
+ },
28
+ {
29
+ ignores: ["node_modules/", "*.js"],
30
+ },
31
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-photo-editor",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "A powerful, generic photo editor for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -21,12 +21,27 @@
21
21
  "peerDependencies": {
22
22
  "react": "*",
23
23
  "react-native": "*",
24
- "@umituz/react-native-design-system": "*"
24
+ "@umituz/react-native-design-system": "*",
25
+ "react-native-gesture-handler": "*",
26
+ "react-native-reanimated": "*"
25
27
  },
26
28
  "dependencies": {
27
29
  "expo-image-picker": "*",
28
30
  "expo-media-library": "*",
29
31
  "expo-file-system": "*",
30
32
  "expo-image": "*"
33
+ },
34
+ "devDependencies": {
35
+ "@types/react": "*",
36
+ "@types/react-native": "*",
37
+ "@typescript-eslint/parser": "*",
38
+ "@typescript-eslint/eslint-plugin": "*",
39
+ "eslint": "*",
40
+ "typescript": "*",
41
+ "react-native-gesture-handler": "*",
42
+ "react-native-reanimated": "*",
43
+ "expo-application": "*",
44
+ "expo-device": "*",
45
+ "expo-linear-gradient": "*"
31
46
  }
32
47
  }
@@ -7,6 +7,7 @@ import {
7
7
  BottomSheetModal,
8
8
  SafeBottomSheetModalProvider,
9
9
  useSafeAreaInsets,
10
+ DesignTokens,
10
11
  } from "@umituz/react-native-design-system";
11
12
 
12
13
  import { EditorCanvas } from "./components/EditorCanvas";
@@ -18,11 +19,12 @@ import { LayerManager } from "./components/LayerManager";
18
19
  import { TextEditorSheet } from "./components/TextEditorSheet";
19
20
  import { createEditorStyles } from "./styles";
20
21
  import { usePhotoEditorUI } from "./hooks/usePhotoEditorUI";
22
+ import { Layer } from "./types";
21
23
 
22
24
  export interface EditorActions {
23
- addTextLayer: (tokens: any) => string;
24
- updateLayer: (id: string, updates: any) => void;
25
- getLayers: () => any[];
25
+ addTextLayer: (tokens: DesignTokens) => string;
26
+ updateLayer: (id: string, updates: Partial<Layer>) => void;
27
+ getLayers: () => Layer[];
26
28
  getActiveLayerId: () => string | null;
27
29
  }
28
30
 
@@ -72,6 +74,7 @@ export const PhotoEditor: React.FC<PhotoEditorProps> = ({
72
74
  updateLayer,
73
75
  deleteLayer,
74
76
  selectLayer,
77
+ addTextLayer,
75
78
  handleAddText,
76
79
  handleTextLayerTap,
77
80
  handleSaveText,
@@ -15,7 +15,7 @@ import {
15
15
  interface AIMagicSheetProps {
16
16
  onGenerateCaption: (style: string) => void;
17
17
  isLoading?: boolean;
18
- t: (key: string) => string;
18
+ _t: (key: string) => string;
19
19
  }
20
20
 
21
21
  const AI_STYLES = [
@@ -30,7 +30,7 @@ const AI_STYLES = [
30
30
  export const AIMagicSheet: React.FC<AIMagicSheetProps> = ({
31
31
  onGenerateCaption,
32
32
  isLoading = false,
33
- t,
33
+ _t,
34
34
  }) => {
35
35
  const tokens = useAppDesignTokens();
36
36
  const [selectedStyle, setSelectedStyle] = useState<string | null>(null);
@@ -1,4 +1,4 @@
1
- import React, { useMemo } from "react";
1
+ import React from "react";
2
2
  import { StyleSheet, View } from "react-native";
3
3
  import { Gesture, GestureDetector } from "react-native-gesture-handler";
4
4
  import Animated, {
@@ -10,7 +10,7 @@ import {
10
10
  AtomicText,
11
11
  useAppDesignTokens,
12
12
  } from "@umituz/react-native-design-system";
13
- import { TextAlign } from "../../domain/Editor.types";
13
+ import { TextAlign } from "../types";
14
14
 
15
15
  interface DraggableTextProps {
16
16
  text: string;
@@ -22,8 +22,8 @@ interface DraggableTextProps {
22
22
  scale?: number;
23
23
  opacity?: number;
24
24
  backgroundColor?: string;
25
- strokeColor?: string;
26
- strokeWidth?: number;
25
+ _strokeColor?: string;
26
+ _strokeWidth?: number;
27
27
  initialX: number;
28
28
  initialY: number;
29
29
  onDragEnd: (x: number, y: number) => void;
@@ -41,8 +41,8 @@ export const DraggableText: React.FC<DraggableTextProps> = ({
41
41
  scale = 1,
42
42
  opacity = 1,
43
43
  backgroundColor = "transparent",
44
- strokeColor,
45
- strokeWidth = 2,
44
+ _strokeColor,
45
+ _strokeWidth = 2,
46
46
  initialX,
47
47
  initialY,
48
48
  onDragEnd,
@@ -47,8 +47,8 @@ export const EditorCanvas: React.FC<EditorCanvasProps> = ({
47
47
  scale={textLayer.scale}
48
48
  opacity={textLayer.opacity}
49
49
  backgroundColor={textLayer.backgroundColor}
50
- strokeColor={textLayer.strokeColor}
51
- strokeWidth={textLayer.strokeWidth}
50
+ _strokeColor={textLayer.strokeColor}
51
+ _strokeWidth={textLayer.strokeWidth}
52
52
  initialX={textLayer.x}
53
53
  initialY={textLayer.y}
54
54
  onDragEnd={(x, y) => onLayerMove(layer.id, x, y)}
@@ -6,21 +6,14 @@ import {
6
6
  useAppDesignTokens,
7
7
  } from "@umituz/react-native-design-system";
8
8
 
9
- interface FilterOption {
10
- id: string;
11
- name: string;
12
- icon: string;
13
- value: number;
14
- }
15
-
16
- const FILTERS: FilterOption[] = [
17
- { id: "none", name: "None", icon: "close-circle", value: 0 },
18
- { id: "sepia", name: "Sepia", icon: "color-palette", value: 0.5 },
19
- { id: "grayscale", name: "B&W", icon: "contrast", value: 1 },
20
- { id: "vintage", name: "Vintage", icon: "time", value: 0.7 },
21
- { id: "warm", name: "Warm", icon: "sunny", value: 0.3 },
22
- { id: "cool", name: "Cool", icon: "snow", value: 0.3 },
23
- ];
9
+ const FILTERS = [
10
+ { id: "none", name: "None", icon: "close-circle" as const, value: 0 },
11
+ { id: "sepia", name: "Sepia", icon: "color-palette" as const, value: 0.5 },
12
+ { id: "grayscale", name: "B&W", icon: "contrast" as const, value: 1 },
13
+ { id: "vintage", name: "Vintage", icon: "time" as const, value: 0.7 },
14
+ { id: "warm", name: "Warm", icon: "sunny" as const, value: 0.3 },
15
+ { id: "cool", name: "Cool", icon: "snow" as const, value: 0.3 },
16
+ ] as const;
24
17
 
25
18
  interface FilterPickerProps {
26
19
  selectedFilter: string;
@@ -82,7 +75,7 @@ export const FilterPicker: React.FC<FilterPickerProps> = ({
82
75
  onPress={() => onSelectFilter(filter.id, filter.value)}
83
76
  >
84
77
  <AtomicIcon
85
- name={filter.icon as any}
78
+ name={filter.icon}
86
79
  size="lg"
87
80
  color={selectedFilter === filter.id ? "primary" : "textSecondary"}
88
81
  />
@@ -1,6 +1,7 @@
1
1
  import { useRef, useState, useCallback, useEffect } from "react";
2
2
  import { BottomSheetModalRef, DesignTokens } from "@umituz/react-native-design-system";
3
3
  import { usePhotoEditor } from "./usePhotoEditor";
4
+ import { Layer, TextLayer } from "../types";
4
5
 
5
6
  export const usePhotoEditorUI = (
6
7
  initialCaption: string | undefined,
@@ -32,16 +33,17 @@ export const usePhotoEditorUI = (
32
33
  useEffect(() => {
33
34
  if (initialCaption) {
34
35
  const id = addTextLayer(tokens);
35
- setTimeout(() => {
36
- updateLayer(id, { text: initialCaption } as any, true);
37
- }, 0);
36
+ void Promise.resolve().then(() => {
37
+ updateLayer(id, { text: initialCaption } as Partial<Layer>, true);
38
+ });
38
39
  }
39
- // eslint-disable-next-line react-hooks/exhaustive-deps
40
- }, []);
40
+ }, [initialCaption, addTextLayer, tokens]);
41
41
 
42
42
  const handleAddText = useCallback(() => {
43
43
  addTextLayer(tokens);
44
- setTimeout(() => textEditorSheetRef.current?.present(), 100);
44
+ void Promise.resolve().then(() => {
45
+ textEditorSheetRef.current?.present();
46
+ });
45
47
  }, [addTextLayer, tokens]);
46
48
 
47
49
  const handleTextLayerTap = useCallback(
@@ -49,8 +51,9 @@ export const usePhotoEditorUI = (
49
51
  selectLayer(layerId);
50
52
  const layer = layers.find((l) => l.id === layerId);
51
53
  if (layer?.type === "text") {
52
- setEditingText((layer as any).text || "");
53
- setFontSize((layer as any).fontSize || 48);
54
+ const textLayer = layer as TextLayer;
55
+ setEditingText(textLayer.text || "");
56
+ setFontSize(textLayer.fontSize || 48);
54
57
  textEditorSheetRef.current?.present();
55
58
  }
56
59
  },
@@ -63,10 +66,10 @@ export const usePhotoEditorUI = (
63
66
  text: editingText,
64
67
  fontSize,
65
68
  fontFamily: selectedFont,
66
- } as any);
69
+ } as Partial<Layer>);
67
70
  }
68
71
  textEditorSheetRef.current?.dismiss();
69
- }, [activeLayerId, editingText, fontSize, selectedFont, updateLayer]);
72
+ }, [activeLayerId, editingText, fontSize, selectedFont, updateLayer, textEditorSheetRef]);
70
73
 
71
74
  const handleSelectFilter = useCallback(
72
75
  (filterId: string, value: number) => {
@@ -116,6 +119,7 @@ export const usePhotoEditorUI = (
116
119
  updateLayer,
117
120
  deleteLayer,
118
121
  selectLayer,
122
+ addTextLayer,
119
123
  // UI Actions
120
124
  handleAddText,
121
125
  handleTextLayerTap,
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "lib": ["ES2020"],
5
+ "allowJs": false,
6
+ "skipLibCheck": true,
7
+ "esModuleInterop": true,
8
+ "allowSyntheticDefaultImports": true,
9
+ "strict": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "moduleResolution": "node",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "jsx": "react-native",
16
+ "declaration": false,
17
+ "noUnusedLocals": false,
18
+ "noUnusedParameters": false,
19
+ "noImplicitReturns": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "baseUrl": "."
22
+ },
23
+ "include": ["src/**/*"],
24
+ "exclude": ["node_modules"]
25
+ }