@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.
Files changed (52) hide show
  1. package/lib/commonjs/assets/frames/film_vintage.png +0 -0
  2. package/lib/commonjs/assets/frames/floral_gold.png +0 -0
  3. package/lib/commonjs/assets/frames/minimal_double.png +0 -0
  4. package/lib/commonjs/assets/frames/polaroid_white.png +0 -0
  5. package/lib/commonjs/assets/frames/watercolor_floral.png +0 -0
  6. package/lib/commonjs/components/VideoEditor.js +167 -0
  7. package/lib/commonjs/components/VideoEditor.js.map +1 -0
  8. package/lib/commonjs/index.js +14 -0
  9. package/lib/commonjs/index.js.map +1 -0
  10. package/lib/commonjs/native/CameraView.js +109 -0
  11. package/lib/commonjs/native/CameraView.js.map +1 -0
  12. package/lib/commonjs/native/FrameGrabber.js +17 -0
  13. package/lib/commonjs/native/FrameGrabber.js.map +1 -0
  14. package/lib/commonjs/native/MediaEditor.js +24 -0
  15. package/lib/commonjs/native/MediaEditor.js.map +1 -0
  16. package/lib/commonjs/native/MediaLibrary.js +45 -0
  17. package/lib/commonjs/native/MediaLibrary.js.map +1 -0
  18. package/lib/commonjs/native/MediaPicker.js +17 -0
  19. package/lib/commonjs/native/MediaPicker.js.map +1 -0
  20. package/lib/commonjs/native/MediaPlayer.js +17 -0
  21. package/lib/commonjs/native/MediaPlayer.js.map +1 -0
  22. package/lib/commonjs/native/VideoPreview.js +17 -0
  23. package/lib/commonjs/native/VideoPreview.js.map +1 -0
  24. package/lib/commonjs/package.json +1 -0
  25. package/lib/commonjs/screens/CropScreen.js +1231 -0
  26. package/lib/commonjs/screens/CropScreen.js.map +1 -0
  27. package/lib/commonjs/screens/EditorScreen.js +5858 -0
  28. package/lib/commonjs/screens/EditorScreen.js.map +1 -0
  29. package/lib/commonjs/screens/ExportScreen.js +294 -0
  30. package/lib/commonjs/screens/ExportScreen.js.map +1 -0
  31. package/lib/commonjs/screens/GalleryScreen.js +510 -0
  32. package/lib/commonjs/screens/GalleryScreen.js.map +1 -0
  33. package/lib/commonjs/screens/PickScreen.js +1261 -0
  34. package/lib/commonjs/screens/PickScreen.js.map +1 -0
  35. package/lib/commonjs/types.js +2 -0
  36. package/lib/commonjs/types.js.map +1 -0
  37. package/lib/module/components/VideoEditor.js +7 -1
  38. package/lib/module/components/VideoEditor.js.map +1 -1
  39. package/lib/module/screens/CropScreen.js +22 -7
  40. package/lib/module/screens/CropScreen.js.map +1 -1
  41. package/lib/module/screens/EditorScreen.js +142 -42
  42. package/lib/module/screens/EditorScreen.js.map +1 -1
  43. package/lib/module/screens/PickScreen.js +76 -16
  44. package/lib/module/screens/PickScreen.js.map +1 -1
  45. package/lib/typescript/src/components/VideoEditor.d.ts +9 -1
  46. package/lib/typescript/src/screens/CropScreen.d.ts +2 -1
  47. package/lib/typescript/src/screens/PickScreen.d.ts +3 -1
  48. package/package.json +14 -8
  49. package/src/components/VideoEditor.tsx +14 -0
  50. package/src/screens/CropScreen.tsx +47 -31
  51. package/src/screens/EditorScreen.tsx +139 -45
  52. 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: startX + gesture.dx,
914
- y: startY + gesture.dy
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(Pressable, {
2227
- onLongPress: () => removeTextOverlay(overlay.id),
2228
- onPress: () => {
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(Pressable, {
2470
- onLongPress: () => removeTextOverlay(overlay.id),
2471
- onPress: () => {
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(Pressable, {
3061
- onLongPress: () => removeTextOverlay(overlay.id),
3062
- onPress: () => {
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,