@technotoil/image-video-editor 0.1.0 → 0.1.1
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/lib/commonjs/assets/frames/film_vintage.png +0 -0
- package/lib/commonjs/assets/frames/floral_gold.png +0 -0
- package/lib/commonjs/assets/frames/minimal_double.png +0 -0
- package/lib/commonjs/assets/frames/polaroid_white.png +0 -0
- package/lib/commonjs/assets/frames/watercolor_floral.png +0 -0
- package/lib/commonjs/components/VideoEditor.js +167 -0
- package/lib/commonjs/components/VideoEditor.js.map +1 -0
- package/lib/commonjs/index.js +14 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/native/CameraView.js +109 -0
- package/lib/commonjs/native/CameraView.js.map +1 -0
- package/lib/commonjs/native/FrameGrabber.js +17 -0
- package/lib/commonjs/native/FrameGrabber.js.map +1 -0
- package/lib/commonjs/native/MediaEditor.js +24 -0
- package/lib/commonjs/native/MediaEditor.js.map +1 -0
- package/lib/commonjs/native/MediaLibrary.js +45 -0
- package/lib/commonjs/native/MediaLibrary.js.map +1 -0
- package/lib/commonjs/native/MediaPicker.js +17 -0
- package/lib/commonjs/native/MediaPicker.js.map +1 -0
- package/lib/commonjs/native/MediaPlayer.js +17 -0
- package/lib/commonjs/native/MediaPlayer.js.map +1 -0
- package/lib/commonjs/native/VideoPreview.js +17 -0
- package/lib/commonjs/native/VideoPreview.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/screens/CropScreen.js +1231 -0
- package/lib/commonjs/screens/CropScreen.js.map +1 -0
- package/lib/commonjs/screens/EditorScreen.js +5858 -0
- package/lib/commonjs/screens/EditorScreen.js.map +1 -0
- package/lib/commonjs/screens/ExportScreen.js +294 -0
- package/lib/commonjs/screens/ExportScreen.js.map +1 -0
- package/lib/commonjs/screens/GalleryScreen.js +510 -0
- package/lib/commonjs/screens/GalleryScreen.js.map +1 -0
- package/lib/commonjs/screens/PickScreen.js +1261 -0
- package/lib/commonjs/screens/PickScreen.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/components/VideoEditor.js +7 -1
- package/lib/module/components/VideoEditor.js.map +1 -1
- package/lib/module/screens/CropScreen.js +22 -7
- package/lib/module/screens/CropScreen.js.map +1 -1
- package/lib/module/screens/EditorScreen.js +142 -42
- package/lib/module/screens/EditorScreen.js.map +1 -1
- package/lib/module/screens/PickScreen.js +76 -16
- package/lib/module/screens/PickScreen.js.map +1 -1
- package/lib/typescript/src/components/VideoEditor.d.ts +9 -1
- package/lib/typescript/src/screens/CropScreen.d.ts +2 -1
- package/lib/typescript/src/screens/PickScreen.d.ts +3 -1
- package/package.json +14 -8
- package/src/components/VideoEditor.tsx +14 -0
- package/src/screens/CropScreen.tsx +47 -31
- package/src/screens/EditorScreen.tsx +139 -45
- package/src/screens/PickScreen.tsx +95 -18
|
@@ -10,6 +10,7 @@ import Video from 'react-native-video';
|
|
|
10
10
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
|
11
11
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
12
12
|
const SCREEN_WIDTH = Dimensions.get('window').width;
|
|
13
|
+
const SCREEN_HEIGHT = Dimensions.get('window').height;
|
|
13
14
|
const TIMELINE_WIDTH = SCREEN_WIDTH - 40;
|
|
14
15
|
const HANDLE_SIZE = 24;
|
|
15
16
|
const CARD_WIDTH = SCREEN_WIDTH * 0.76;
|
|
@@ -428,6 +429,8 @@ export function EditorScreen({
|
|
|
428
429
|
const [newText, setNewText] = useState('');
|
|
429
430
|
const isNewOverlay = React.useRef(false); // track if overlay was just created (not yet saved)
|
|
430
431
|
const originalOverlayBackup = React.useRef(null);
|
|
432
|
+
const [activeDraggingId, setActiveDraggingId] = useState(null);
|
|
433
|
+
const [isOverTrash, setIsOverTrash] = useState(false);
|
|
431
434
|
|
|
432
435
|
// ── Stickers ────────────────────────────────────────────────────────────────
|
|
433
436
|
const STICKER_LIST = ['😂', '❤️', '🔥', '✨', '💯', '👑', '🎉', '🌈', '🎶', '💫', '🙌', '😍', '🤩', '😎', '🥳', '🌸', '🦋', '⚡', '🌙', '💎', '🍕', '🎸', '🎬', '📸', '🎯', '🌺', '🦄', '🐉', '🎭', '🪩'];
|
|
@@ -894,10 +897,17 @@ export function EditorScreen({
|
|
|
894
897
|
const createTextPan = id => {
|
|
895
898
|
let startX = 0;
|
|
896
899
|
let startY = 0;
|
|
900
|
+
let pressStartTime = 0;
|
|
901
|
+
let hasMoved = false;
|
|
902
|
+
let longPressTimeout = null;
|
|
897
903
|
return PanResponder.create({
|
|
898
904
|
onStartShouldSetPanResponder: () => true,
|
|
899
905
|
onMoveShouldSetPanResponder: () => true,
|
|
900
906
|
onPanResponderGrant: () => {
|
|
907
|
+
pressStartTime = Date.now();
|
|
908
|
+
hasMoved = false;
|
|
909
|
+
setActiveDraggingId(id);
|
|
910
|
+
setIsOverTrash(false);
|
|
901
911
|
setOverlays(prev => {
|
|
902
912
|
const item = prev.find(o => o.id === id);
|
|
903
913
|
if (item) {
|
|
@@ -906,13 +916,78 @@ export function EditorScreen({
|
|
|
906
916
|
}
|
|
907
917
|
return prev;
|
|
908
918
|
});
|
|
919
|
+
|
|
920
|
+
// Setup long press timer (600ms)
|
|
921
|
+
if (longPressTimeout) clearTimeout(longPressTimeout);
|
|
922
|
+
longPressTimeout = setTimeout(() => {
|
|
923
|
+
if (!hasMoved) {
|
|
924
|
+
removeTextOverlay(id);
|
|
925
|
+
}
|
|
926
|
+
}, 600);
|
|
909
927
|
},
|
|
910
928
|
onPanResponderMove: (_, gesture) => {
|
|
929
|
+
if (Math.abs(gesture.dx) > 4 || Math.abs(gesture.dy) > 4) {
|
|
930
|
+
hasMoved = true;
|
|
931
|
+
if (longPressTimeout) {
|
|
932
|
+
clearTimeout(longPressTimeout);
|
|
933
|
+
longPressTimeout = null;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
const newX = startX + gesture.dx;
|
|
937
|
+
const newY = startY + gesture.dy;
|
|
938
|
+
|
|
939
|
+
// Trash zone: bottom 140px of screen, center horizontal
|
|
940
|
+
const isNearTrash = gesture.moveY > SCREEN_HEIGHT - 140 && Math.abs(gesture.moveX - SCREEN_WIDTH / 2) < 90;
|
|
941
|
+
setIsOverTrash(isNearTrash);
|
|
911
942
|
setOverlays(prev => prev.map(o => o.id === id ? {
|
|
912
943
|
...o,
|
|
913
|
-
x:
|
|
914
|
-
y:
|
|
944
|
+
x: newX,
|
|
945
|
+
y: newY
|
|
915
946
|
} : o));
|
|
947
|
+
},
|
|
948
|
+
onPanResponderRelease: (_, gesture) => {
|
|
949
|
+
if (longPressTimeout) {
|
|
950
|
+
clearTimeout(longPressTimeout);
|
|
951
|
+
longPressTimeout = null;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// Check if released over trash zone using final touch screen coordinates
|
|
955
|
+
const releasedOverTrash = gesture.moveY > SCREEN_HEIGHT - 140 && Math.abs(gesture.moveX - SCREEN_WIDTH / 2) < 90;
|
|
956
|
+
|
|
957
|
+
// Reset dragging states
|
|
958
|
+
setActiveDraggingId(null);
|
|
959
|
+
setIsOverTrash(false);
|
|
960
|
+
if (releasedOverTrash) {
|
|
961
|
+
setTimeout(() => {
|
|
962
|
+
removeTextOverlay(id);
|
|
963
|
+
}, 50);
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
const pressDuration = Date.now() - pressStartTime;
|
|
967
|
+
if (!hasMoved && pressDuration < 250) {
|
|
968
|
+
pushToHistory();
|
|
969
|
+
setOverlays(prev => {
|
|
970
|
+
const found = prev.find(o => o.id === id);
|
|
971
|
+
if (found) {
|
|
972
|
+
originalOverlayBackup.current = {
|
|
973
|
+
...found
|
|
974
|
+
};
|
|
975
|
+
isNewOverlay.current = false;
|
|
976
|
+
setEditingTextId(id);
|
|
977
|
+
setNewText(found.text);
|
|
978
|
+
setPanel('text');
|
|
979
|
+
}
|
|
980
|
+
return prev;
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
},
|
|
984
|
+
onPanResponderTerminate: () => {
|
|
985
|
+
if (longPressTimeout) {
|
|
986
|
+
clearTimeout(longPressTimeout);
|
|
987
|
+
longPressTimeout = null;
|
|
988
|
+
}
|
|
989
|
+
setActiveDraggingId(null);
|
|
990
|
+
setIsOverTrash(false);
|
|
916
991
|
}
|
|
917
992
|
});
|
|
918
993
|
};
|
|
@@ -2223,20 +2298,9 @@ export function EditorScreen({
|
|
|
2223
2298
|
zIndex: 20
|
|
2224
2299
|
}, isSelected && styles.selectedTextContainer],
|
|
2225
2300
|
...responder.panHandlers,
|
|
2226
|
-
children: /*#__PURE__*/_jsx(
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
pushToHistory();
|
|
2230
|
-
// Backup original state (text, color, position, size, etc.)
|
|
2231
|
-
const found = overlays.find(o => o.id === overlay.id);
|
|
2232
|
-
if (found) {
|
|
2233
|
-
originalOverlayBackup.current = {
|
|
2234
|
-
...found
|
|
2235
|
-
};
|
|
2236
|
-
}
|
|
2237
|
-
isNewOverlay.current = false;
|
|
2238
|
-
setEditingTextId(overlay.id);
|
|
2239
|
-
setNewText(overlay.text);
|
|
2301
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
2302
|
+
style: {
|
|
2303
|
+
padding: 4
|
|
2240
2304
|
},
|
|
2241
2305
|
children: /*#__PURE__*/_jsx(Text, {
|
|
2242
2306
|
style: [styles.textOverlay, {
|
|
@@ -2466,19 +2530,9 @@ export function EditorScreen({
|
|
|
2466
2530
|
zIndex: 20
|
|
2467
2531
|
}, isSelected && styles.selectedTextContainer],
|
|
2468
2532
|
...responder.panHandlers,
|
|
2469
|
-
children: /*#__PURE__*/_jsx(
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
pushToHistory();
|
|
2473
|
-
const found = overlays.find(o => o.id === overlay.id);
|
|
2474
|
-
if (found) {
|
|
2475
|
-
originalOverlayBackup.current = {
|
|
2476
|
-
...found
|
|
2477
|
-
};
|
|
2478
|
-
}
|
|
2479
|
-
isNewOverlay.current = false;
|
|
2480
|
-
setEditingTextId(overlay.id);
|
|
2481
|
-
setNewText(overlay.text);
|
|
2533
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
2534
|
+
style: {
|
|
2535
|
+
padding: 4
|
|
2482
2536
|
},
|
|
2483
2537
|
children: /*#__PURE__*/_jsx(Text, {
|
|
2484
2538
|
style: [styles.textOverlay, {
|
|
@@ -3057,19 +3111,9 @@ export function EditorScreen({
|
|
|
3057
3111
|
zIndex: 20
|
|
3058
3112
|
}, isSelected && styles.selectedTextContainer],
|
|
3059
3113
|
...responder.panHandlers,
|
|
3060
|
-
children: /*#__PURE__*/_jsx(
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
pushToHistory();
|
|
3064
|
-
const found = overlays.find(o => o.id === overlay.id);
|
|
3065
|
-
if (found) {
|
|
3066
|
-
originalOverlayBackup.current = {
|
|
3067
|
-
...found
|
|
3068
|
-
};
|
|
3069
|
-
}
|
|
3070
|
-
isNewOverlay.current = false;
|
|
3071
|
-
setEditingTextId(overlay.id);
|
|
3072
|
-
setNewText(overlay.text);
|
|
3114
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
3115
|
+
style: {
|
|
3116
|
+
padding: 4
|
|
3073
3117
|
},
|
|
3074
3118
|
children: /*#__PURE__*/_jsx(Text, {
|
|
3075
3119
|
style: [styles.textOverlay, {
|
|
@@ -4097,6 +4141,24 @@ export function EditorScreen({
|
|
|
4097
4141
|
})]
|
|
4098
4142
|
})
|
|
4099
4143
|
})
|
|
4144
|
+
}), activeDraggingId !== null && /*#__PURE__*/_jsx(View, {
|
|
4145
|
+
style: styles.globalTrashZone,
|
|
4146
|
+
pointerEvents: "none",
|
|
4147
|
+
children: /*#__PURE__*/_jsxs(View, {
|
|
4148
|
+
style: [styles.trashZoneContainer, isOverTrash && styles.trashZoneActive, isOverTrash ? {
|
|
4149
|
+
transform: [{
|
|
4150
|
+
scale: 1.15
|
|
4151
|
+
}]
|
|
4152
|
+
} : {}],
|
|
4153
|
+
children: [/*#__PURE__*/_jsx(Ionicons, {
|
|
4154
|
+
name: isOverTrash ? "trash" : "trash-outline",
|
|
4155
|
+
size: 20,
|
|
4156
|
+
color: "#fff"
|
|
4157
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
4158
|
+
style: styles.trashZoneText,
|
|
4159
|
+
children: isOverTrash ? "Release to Delete" : "Drag here to delete"
|
|
4160
|
+
})]
|
|
4161
|
+
})
|
|
4100
4162
|
})]
|
|
4101
4163
|
});
|
|
4102
4164
|
}
|
|
@@ -5375,6 +5437,44 @@ const styles = StyleSheet.create({
|
|
|
5375
5437
|
borderWidth: 1,
|
|
5376
5438
|
borderColor: 'rgba(255, 255, 255, 0.3)'
|
|
5377
5439
|
},
|
|
5440
|
+
globalTrashZone: {
|
|
5441
|
+
position: 'absolute',
|
|
5442
|
+
bottom: Platform.OS === 'ios' ? 48 : 28,
|
|
5443
|
+
left: 0,
|
|
5444
|
+
right: 0,
|
|
5445
|
+
alignItems: 'center',
|
|
5446
|
+
justifyContent: 'center',
|
|
5447
|
+
zIndex: 9999
|
|
5448
|
+
},
|
|
5449
|
+
trashZoneContainer: {
|
|
5450
|
+
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
|
5451
|
+
paddingHorizontal: 20,
|
|
5452
|
+
paddingVertical: 12,
|
|
5453
|
+
borderRadius: 24,
|
|
5454
|
+
flexDirection: 'row',
|
|
5455
|
+
alignItems: 'center',
|
|
5456
|
+
justifyContent: 'center',
|
|
5457
|
+
borderWidth: 1.5,
|
|
5458
|
+
borderColor: 'rgba(255, 255, 255, 0.25)',
|
|
5459
|
+
shadowColor: '#000',
|
|
5460
|
+
shadowOffset: {
|
|
5461
|
+
width: 0,
|
|
5462
|
+
height: 4
|
|
5463
|
+
},
|
|
5464
|
+
shadowOpacity: 0.4,
|
|
5465
|
+
shadowRadius: 6,
|
|
5466
|
+
elevation: 8
|
|
5467
|
+
},
|
|
5468
|
+
trashZoneActive: {
|
|
5469
|
+
backgroundColor: '#ef4444',
|
|
5470
|
+
borderColor: '#fca5a5'
|
|
5471
|
+
},
|
|
5472
|
+
trashZoneText: {
|
|
5473
|
+
color: '#ffffff',
|
|
5474
|
+
fontSize: 12,
|
|
5475
|
+
fontWeight: '700',
|
|
5476
|
+
marginLeft: 8
|
|
5477
|
+
},
|
|
5378
5478
|
cropIconText: {
|
|
5379
5479
|
color: '#FFFFFF',
|
|
5380
5480
|
fontSize: 18,
|