@chem-po/react-native 0.0.24 → 0.0.26

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 (48) hide show
  1. package/lib/commonjs/components/form/UploadProgress/index.js +8 -17
  2. package/lib/commonjs/components/form/UploadProgress/index.js.map +1 -1
  3. package/lib/commonjs/components/form/input/file/index.js +26 -8
  4. package/lib/commonjs/components/form/input/file/index.js.map +1 -1
  5. package/lib/commonjs/components/image/ImageViewModal.backup.js +285 -0
  6. package/lib/commonjs/components/image/ImageViewModal.backup.js.map +1 -0
  7. package/lib/commonjs/components/image/ImageViewModal.js +79 -99
  8. package/lib/commonjs/components/image/ImageViewModal.js.map +1 -1
  9. package/lib/commonjs/components/image/ImageViewModal.old.js +285 -0
  10. package/lib/commonjs/components/image/ImageViewModal.old.js.map +1 -0
  11. package/lib/commonjs/components/loading/ProgressBar.js +78 -0
  12. package/lib/commonjs/components/loading/ProgressBar.js.map +1 -0
  13. package/lib/commonjs/components/loading/index.js +11 -0
  14. package/lib/commonjs/components/loading/index.js.map +1 -1
  15. package/lib/module/components/form/UploadProgress/index.js +6 -15
  16. package/lib/module/components/form/UploadProgress/index.js.map +1 -1
  17. package/lib/module/components/form/input/file/index.js +27 -9
  18. package/lib/module/components/form/input/file/index.js.map +1 -1
  19. package/lib/module/components/image/ImageViewModal.backup.js +277 -0
  20. package/lib/module/components/image/ImageViewModal.backup.js.map +1 -0
  21. package/lib/module/components/image/ImageViewModal.js +80 -100
  22. package/lib/module/components/image/ImageViewModal.js.map +1 -1
  23. package/lib/module/components/image/ImageViewModal.old.js +277 -0
  24. package/lib/module/components/image/ImageViewModal.old.js.map +1 -0
  25. package/lib/module/components/loading/ProgressBar.js +70 -0
  26. package/lib/module/components/loading/ProgressBar.js.map +1 -0
  27. package/lib/module/components/loading/index.js +1 -0
  28. package/lib/module/components/loading/index.js.map +1 -1
  29. package/lib/typescript/components/form/UploadProgress/index.d.ts.map +1 -1
  30. package/lib/typescript/components/form/input/file/index.d.ts +5 -3
  31. package/lib/typescript/components/form/input/file/index.d.ts.map +1 -1
  32. package/lib/typescript/components/image/ImageViewModal.backup.d.ts +9 -0
  33. package/lib/typescript/components/image/ImageViewModal.backup.d.ts.map +1 -0
  34. package/lib/typescript/components/image/ImageViewModal.d.ts.map +1 -1
  35. package/lib/typescript/components/image/ImageViewModal.old.d.ts +9 -0
  36. package/lib/typescript/components/image/ImageViewModal.old.d.ts.map +1 -0
  37. package/lib/typescript/components/loading/ProgressBar.d.ts +7 -0
  38. package/lib/typescript/components/loading/ProgressBar.d.ts.map +1 -0
  39. package/lib/typescript/components/loading/index.d.ts +1 -0
  40. package/lib/typescript/components/loading/index.d.ts.map +1 -1
  41. package/package.json +11 -10
  42. package/src/components/form/UploadProgress/index.tsx +3 -17
  43. package/src/components/form/input/file/index.tsx +28 -8
  44. package/src/components/image/ImageViewModal.backup.tsx +261 -0
  45. package/src/components/image/ImageViewModal.old.tsx +261 -0
  46. package/src/components/image/ImageViewModal.tsx +72 -79
  47. package/src/components/loading/ProgressBar.tsx +75 -0
  48. package/src/components/loading/index.ts +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useColorModeValue","useThemeValue","React","useEffect","useRef","Animated","StyleSheet","Text","View","ProgressBar","progress","label","height","accentColor","animatedWidth","Value","current","backgroundColor","timing","toValue","duration","useNativeDriver","start","createElement","style","styles","progressContainer","progressBar","progressFill","width","interpolate","inputRange","outputRange","extrapolate","create","justifyContent","alignItems","borderRadius","padding","overflow","position","color","fontSize","fontWeight","textTransform","textShadowColor","textShadowOffset","textShadowRadius"],"sourceRoot":"..\\..\\..\\..\\src","sources":["components/loading/ProgressBar.tsx"],"mappings":"AAAA,SAASA,iBAAiB,EAAEC,aAAa,QAAQ,gBAAgB;AACjE,OAAOC,KAAK,IAAIC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAChD,SAASC,QAAQ,EAAEC,UAAU,EAAEC,IAAI,EAAEC,IAAI,QAAQ,cAAc;AAE/D,OAAO,MAAMC,WAAW,GAAGA,CAAC;EAC1BC,QAAQ;EACRC,KAAK;EACLC,MAAM,GAAG;AAKX,CAAC,KAAK;EACJ,MAAMC,WAAW,GAAGZ,aAAa,CAAC,mBAAmB,CAAC;EACtD,MAAMa,aAAa,GAAGV,MAAM,CAAC,IAAIC,QAAQ,CAACU,KAAK,CAAC,CAAC,CAAC,CAAC,CAACC,OAAO;EAC3D,MAAMC,eAAe,GAAGjB,iBAAiB,CAAC,oBAAoB,EAAE,0BAA0B,CAAC;EAE3FG,SAAS,CAAC,MAAM;IACdE,QAAQ,CAACa,MAAM,CAACJ,aAAa,EAAE;MAC7BK,OAAO,EAAET,QAAQ;MACjBU,QAAQ,EAAE,GAAG;MACbC,eAAe,EAAE,KAAK,CAAE;IAC1B,CAAC,CAAC,CAACC,KAAK,CAAC,CAAC;EACZ,CAAC,EAAE,CAACZ,QAAQ,EAAEI,aAAa,CAAC,CAAC;EAE7B,oBACEZ,KAAA,CAAAqB,aAAA,CAACf,IAAI;IAACgB,KAAK,EAAE,CAACC,MAAM,CAACC,iBAAiB,EAAE;MAAEd,MAAM;MAAEK;IAAgB,CAAC;EAAE,gBACnEf,KAAA,CAAAqB,aAAA,CAACf,IAAI;IAACgB,KAAK,EAAEC,MAAM,CAACE;EAAY,gBAC9BzB,KAAA,CAAAqB,aAAA,CAAClB,QAAQ,CAACG,IAAI;IACZgB,KAAK,EAAE,CACLC,MAAM,CAACG,YAAY,EACnB;MACEC,KAAK,EAAEf,aAAa,CAACgB,WAAW,CAAC;QAC/BC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAClBC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC;QAC3BC,WAAW,EAAE;MACf,CAAC,CAAC;MACFhB,eAAe,EAAEJ;IACnB,CAAC;EACD,CACH,CACG,CAAC,eACPX,KAAA,CAAAqB,aAAA,CAAChB,IAAI;IAACiB,KAAK,EAAEC,MAAM,CAACd;EAAM,GAAEA,KAAY,CACpC,CAAC;AAEX,CAAC;AAED,MAAMc,MAAM,GAAGnB,UAAU,CAAC4B,MAAM,CAAC;EAC/BR,iBAAiB,EAAE;IACjBG,KAAK,EAAE,MAAM;IACbM,cAAc,EAAE,QAAQ;IACxBC,UAAU,EAAE,QAAQ;IACpBC,YAAY,EAAE,EAAE;IAChBC,OAAO,EAAE;EACX,CAAC;EACDX,WAAW,EAAE;IACXf,MAAM,EAAE,MAAM;IACdiB,KAAK,EAAE,MAAM;IACbQ,YAAY,EAAE,EAAE;IAChBE,QAAQ,EAAE;EACZ,CAAC;EACDX,YAAY,EAAE;IACZhB,MAAM,EAAE;EACV,CAAC;EACDD,KAAK,EAAE;IACL6B,QAAQ,EAAE,UAAU;IACpBC,KAAK,EAAE,OAAO;IACdC,QAAQ,EAAE,EAAE;IACZC,UAAU,EAAE,KAAK;IACjBC,aAAa,EAAE,WAAW;IAC1BC,eAAe,EAAE,qBAAqB;IACtCC,gBAAgB,EAAE;MAAEjB,KAAK,EAAE,CAAC;MAAEjB,MAAM,EAAE;IAAE,CAAC;IACzCmC,gBAAgB,EAAE;EACpB;AACF,CAAC,CAAC","ignoreList":[]}
@@ -3,4 +3,5 @@ export * from './Loading';
3
3
  export * from './LoadingImage';
4
4
  export * from './LoadingOverlay';
5
5
  export * from './LoadingSwitch';
6
+ export * from './ProgressBar';
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"..\\..\\..\\..\\src","sources":["components/loading/index.ts"],"mappings":"AAAA,cAAc,oBAAoB;AAClC,cAAc,WAAW;AACzB,cAAc,gBAAgB;AAC9B,cAAc,kBAAkB;AAChC,cAAc,iBAAiB","ignoreList":[]}
1
+ {"version":3,"names":[],"sourceRoot":"..\\..\\..\\..\\src","sources":["components/loading/index.ts"],"mappings":"AAAA,cAAc,oBAAoB;AAClC,cAAc,WAAW;AACzB,cAAc,gBAAgB;AAC9B,cAAc,kBAAkB;AAChC,cAAc,iBAAiB;AAC/B,cAAc,eAAe","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/UploadProgress/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,OAAO,KAAkB,MAAM,OAAO,CAAA;AAqCtC,eAAO,MAAM,cAAc,GAAI,aAAa;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,sBAwBpE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/UploadProgress/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAkB,MAAM,OAAO,CAAA;AAsCtC,eAAO,MAAM,cAAc,GAAI,aAAa;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,sBAUpE,CAAA"}
@@ -1,12 +1,14 @@
1
- import { FileValue, InputRef } from '@chem-po/core';
1
+ import { FileValue, ImageViewOptions, InputRef } from '@chem-po/core';
2
2
  import { FileField } from '@chem-po/react';
3
3
  import React from 'react';
4
+ import { StyleProp, ViewStyle } from 'react-native';
4
5
  import { FieldProps } from '../../types';
5
- export declare const FileView: ({ value, hasUpload, imageOptions, withFullView, }: {
6
+ export declare const FileView: ({ value, hasUpload, imageOptions, withFullView, nonImageContainerStyle, }: {
6
7
  value?: FileValue | null;
7
8
  hasUpload?: boolean;
8
- imageOptions?: any;
9
+ imageOptions?: ImageViewOptions;
9
10
  withFullView?: boolean;
11
+ nonImageContainerStyle?: StyleProp<ViewStyle>;
10
12
  }) => React.JSX.Element;
11
13
  export declare const FileComponent: React.ForwardRefExoticComponent<FieldProps<FileField> & React.RefAttributes<InputRef>>;
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/form/input/file/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAkB,MAAM,eAAe,CAAA;AACnE,OAAO,EACL,SAAS,EAMV,MAAM,gBAAgB,CAAA;AAIvB,OAAO,KAA0E,MAAM,OAAO,CAAA;AAG9F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AA+BxC,eAAO,MAAM,QAAQ,GAAI,mDAKtB;IACD,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,YAAY,CAAC,EAAE,GAAG,CAAA;IAClB,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,sBAgCA,CAAA;AAED,eAAO,MAAM,aAAa,wFA2FzB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/form/input/file/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,QAAQ,EAAkB,MAAM,eAAe,CAAA;AACrF,OAAO,EACL,SAAS,EAOV,MAAM,gBAAgB,CAAA;AAIvB,OAAO,KAA0E,MAAM,OAAO,CAAA;AAC9F,OAAO,EAAE,SAAS,EAA4C,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AA+BxC,eAAO,MAAM,QAAQ,GAAI,2EAMtB;IACD,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,YAAY,CAAC,EAAE,gBAAgB,CAAA;IAC/B,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,sBAAsB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAC9C,sBAuCA,CAAA;AAED,eAAO,MAAM,aAAa,wFA2FzB,CAAA"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface ImageViewModalProps {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ src: string | null;
6
+ }
7
+ export declare const ImageViewModal: React.FC<ImageViewModalProps>;
8
+ export {};
9
+ //# sourceMappingURL=ImageViewModal.backup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageViewModal.backup.d.ts","sourceRoot":"","sources":["../../../../src/components/image/ImageViewModal.backup.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAiD,MAAM,OAAO,CAAA;AAKrE,UAAU,mBAAmB;IAC3B,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA4MxD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImageViewModal.d.ts","sourceRoot":"","sources":["../../../../src/components/image/ImageViewModal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAiD,MAAM,OAAO,CAAA;AAKrE,UAAU,mBAAmB;IAC3B,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA4MxD,CAAA"}
1
+ {"version":3,"file":"ImageViewModal.d.ts","sourceRoot":"","sources":["../../../../src/components/image/ImageViewModal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAoD,MAAM,OAAO,CAAA;AAMxE,UAAU,mBAAmB;IAC3B,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAoMxD,CAAA"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface ImageViewModalProps {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ src: string | null;
6
+ }
7
+ export declare const ImageViewModal: React.FC<ImageViewModalProps>;
8
+ export {};
9
+ //# sourceMappingURL=ImageViewModal.old.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageViewModal.old.d.ts","sourceRoot":"","sources":["../../../../src/components/image/ImageViewModal.old.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAiD,MAAM,OAAO,CAAA;AAKrE,UAAU,mBAAmB;IAC3B,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA4MxD,CAAA"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export declare const ProgressBar: ({ progress, label, height, }: {
3
+ progress: number;
4
+ label?: string;
5
+ height?: number;
6
+ }) => React.JSX.Element;
7
+ //# sourceMappingURL=ProgressBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProgressBar.d.ts","sourceRoot":"","sources":["../../../../src/components/loading/ProgressBar.tsx"],"names":[],"mappings":"AACA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAGhD,eAAO,MAAM,WAAW,GAAI,8BAIzB;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,sBAiCA,CAAA"}
@@ -3,4 +3,5 @@ export * from './Loading';
3
3
  export * from './LoadingImage';
4
4
  export * from './LoadingOverlay';
5
5
  export * from './LoadingSwitch';
6
+ export * from './ProgressBar';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/loading/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/loading/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@chem-po/react-native",
3
3
  "author": "Elan Canfield",
4
4
  "license": "MIT",
5
- "version": "0.0.24",
5
+ "version": "0.0.26",
6
6
  "main": "lib/commonjs/index.js",
7
7
  "types": "lib/typescript/index.d.ts",
8
8
  "source": "src/index.ts",
@@ -34,23 +34,24 @@
34
34
  "@lottiefiles/dotlottie-react": "^0.13.5",
35
35
  "@react-native-async-storage/async-storage": "2.1.2",
36
36
  "@react-native-community/slider": "4.5.6",
37
- "expo-constants": "~17.1.6",
38
- "expo-document-picker": "~13.1.5",
37
+ "expo-constants": "~17.1.7",
38
+ "expo-document-picker": "~13.1.6",
39
39
  "expo-image-picker": "~16.1.4",
40
40
  "lottie-react-native": "7.2.2",
41
41
  "nested-property": "^4.0.0",
42
- "react": "^19.0.0",
42
+ "react": "19.0.0",
43
43
  "react-hook-form": "^7.55.0",
44
- "react-native": "0.79.3",
44
+ "react-native": "0.79.5",
45
45
  "react-native-element-dropdown": "^2.12.4",
46
46
  "react-native-gesture-handler": "~2.24.0",
47
+ "react-native-reanimated": "~3.17.4",
47
48
  "react-native-notifier": "^2.0.0",
48
49
  "react-native-paper": "^5.14.3",
49
50
  "react-native-paper-dates": "^0.22.42",
50
51
  "react-native-svg": "15.11.2",
51
52
  "zustand": "^4.3.3",
52
- "@chem-po/core": "0.0.24",
53
- "@chem-po/react": "0.0.24"
53
+ "@chem-po/react": "0.0.26",
54
+ "@chem-po/core": "0.0.26"
54
55
  },
55
56
  "devDependencies": {
56
57
  "@babel/core": "^7.26.0",
@@ -67,9 +68,9 @@
67
68
  },
68
69
  "peerDependencies": {
69
70
  "expo": "~53.0.11",
70
- "react": "^19.0.0",
71
- "react-dom": "^19.0.0",
72
- "react-native": "0.79.3"
71
+ "react": "19.0.0",
72
+ "react-dom": "19.0.0",
73
+ "react-native": "0.79.4"
73
74
  },
74
75
  "react-native-builder-bob": {
75
76
  "source": "src",
@@ -1,7 +1,7 @@
1
1
  import { UploadsState } from '@chem-po/core'
2
- import { useThemeValue } from '@chem-po/react'
3
2
  import React, { useMemo } from 'react'
4
- import { Animated, StyleSheet, Text, View } from 'react-native'
3
+ import { StyleSheet, View } from 'react-native'
4
+ import { ProgressBar } from '../../loading/ProgressBar'
5
5
 
6
6
  const styles = StyleSheet.create({
7
7
  container: {
@@ -40,24 +40,10 @@ const styles = StyleSheet.create({
40
40
  export const UploadProgress = ({ uploads }: { uploads: UploadsState }) => {
41
41
  const asArr = useMemo(() => Object.values(uploads), [uploads])
42
42
 
43
- const accentColor = useThemeValue('colors.accent.300')
44
43
  return (
45
44
  <View style={styles.container}>
46
45
  {asArr.map(upload => (
47
- <Animated.View key={upload.label} style={styles.progressContainer}>
48
- <View style={styles.progressBar}>
49
- <Animated.View
50
- style={[
51
- styles.progressFill,
52
- {
53
- width: `${upload.percent * 100}%`,
54
- backgroundColor: accentColor,
55
- },
56
- ]}
57
- />
58
- </View>
59
- <Text style={styles.label}>{upload.label}</Text>
60
- </Animated.View>
46
+ <ProgressBar key={upload.label} progress={upload.percent} label={upload.label} />
61
47
  ))}
62
48
  </View>
63
49
  )
@@ -1,6 +1,7 @@
1
- import { FileValue, InputRef, LocalFileValue } from '@chem-po/core'
1
+ import { FileValue, ImageViewOptions, InputRef, LocalFileValue } from '@chem-po/core'
2
2
  import {
3
3
  FileField,
4
+ useBackgroundColor,
4
5
  useBorderColor,
5
6
  useIconColor,
6
7
  useObjectUrl,
@@ -11,7 +12,7 @@ import { Ionicons } from '@expo/vector-icons'
11
12
  import * as DocumentPicker from 'expo-document-picker'
12
13
  import * as ImagePicker from 'expo-image-picker'
13
14
  import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useState } from 'react'
14
- import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
15
+ import { StyleProp, StyleSheet, Text, TouchableOpacity, View, ViewStyle } from 'react-native'
15
16
  import { LoadingImage } from '../../../loading/LoadingImage'
16
17
  import { FieldProps } from '../../types'
17
18
 
@@ -49,11 +50,13 @@ export const FileView = ({
49
50
  hasUpload,
50
51
  imageOptions,
51
52
  withFullView,
53
+ nonImageContainerStyle,
52
54
  }: {
53
55
  value?: FileValue | null
54
56
  hasUpload?: boolean
55
- imageOptions?: any
57
+ imageOptions?: ImageViewOptions
56
58
  withFullView?: boolean
59
+ nonImageContainerStyle?: StyleProp<ViewStyle>
57
60
  }) => {
58
61
  const { storagePath, dataUrl } = value ?? {}
59
62
  const missingFile = !dataUrl && !storagePath
@@ -63,6 +66,7 @@ export const FileView = ({
63
66
  const iconColor = useIconColor()
64
67
  const fileNameColor = useTextColor()
65
68
  const borderColor = useBorderColor()
69
+ const backgroundColor = useBackgroundColor(100)
66
70
  if (!value || missingFile) {
67
71
  return <NoFileView hasUpload={hasUpload} />
68
72
  }
@@ -81,9 +85,15 @@ export const FileView = ({
81
85
  }
82
86
 
83
87
  return (
84
- <View style={[styles.fileContainer, { borderColor }]}>
85
- <Ionicons name="document" size={24} color={iconColor} />
86
- <Text style={[styles.filename, { color: fileNameColor }]}>{value.filename}</Text>
88
+ <View style={[styles.fileContainer, { borderColor, backgroundColor }, nonImageContainerStyle]}>
89
+ <View style={styles.iconContainer}>
90
+ <Ionicons name="document" size={24} color={iconColor} />
91
+ </View>
92
+ <View style={styles.filenameContainer}>
93
+ <Text numberOfLines={1} style={[styles.filename, { color: fileNameColor }]}>
94
+ {value.filename}
95
+ </Text>
96
+ </View>
87
97
  </View>
88
98
  )
89
99
  }
@@ -220,13 +230,23 @@ const styles = StyleSheet.create({
220
230
  fileContainer: {
221
231
  flexDirection: 'row',
222
232
  alignItems: 'center',
223
- padding: 8,
224
233
  borderWidth: 1,
225
234
  borderRadius: 4,
235
+ maxWidth: '100%',
236
+ overflow: 'hidden',
237
+ },
238
+ filenameContainer: {
239
+ flex: 1,
240
+ paddingRight: 4,
241
+ alignItems: 'center',
226
242
  },
227
243
  filename: {
228
244
  fontSize: 14,
229
- marginLeft: 8,
245
+ lineHeight: 30,
246
+ flex: 1,
247
+ },
248
+ iconContainer: {
249
+ padding: 4,
230
250
  },
231
251
  image: {
232
252
  borderRadius: 4,
@@ -0,0 +1,261 @@
1
+ import { useScreen } from '@chem-po/react'
2
+ import { Ionicons } from '@expo/vector-icons'
3
+ import React, { useCallback, useMemo, useRef, useState } from 'react'
4
+ import { Animated, Image, Modal, StyleSheet, TouchableOpacity, View } from 'react-native'
5
+ import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler'
6
+ import { LoadingLogo } from '../loading/Loading'
7
+
8
+ interface ImageViewModalProps {
9
+ isOpen: boolean
10
+ onClose: () => void
11
+ src: string | null
12
+ }
13
+
14
+ export const ImageViewModal: React.FC<ImageViewModalProps> = ({ isOpen, onClose, src }) => {
15
+ const [loading, setLoading] = useState(true)
16
+ const screenWidth = useScreen(s => s.width)
17
+ const screenHeight = useScreen(s => s.height)
18
+ const [imageSize, setImageSize] = useState({ width: screenWidth / 2, height: screenHeight / 2 })
19
+
20
+ // Animated values for zoom and pan
21
+ const scale = useRef(new Animated.Value(1)).current
22
+ const translateX = useRef(new Animated.Value(0)).current
23
+ const translateY = useRef(new Animated.Value(0)).current
24
+
25
+ // Gesture state
26
+ const savedScale = useRef(1)
27
+ const savedTranslateX = useRef(0)
28
+ const savedTranslateY = useRef(0)
29
+ const currentScale = useRef(1)
30
+ const currentTranslateX = useRef(0)
31
+ const currentTranslateY = useRef(0)
32
+
33
+ const { height, width } = useMemo(() => {
34
+ if (loading) return imageSize
35
+ const ratio = imageSize.width / imageSize.height
36
+ let h = Math.min(imageSize.height, screenHeight * 0.9)
37
+ let w = h * ratio
38
+ if (w > screenWidth * 0.9) {
39
+ w = Math.min(imageSize.width, screenWidth * 0.9)
40
+ h = w / ratio
41
+ }
42
+ return { height: h, width: w }
43
+ }, [screenHeight, screenWidth, imageSize, loading])
44
+
45
+ const onLoadStart = useCallback(() => setLoading(true), [])
46
+ const onLoad = useCallback((e: any) => {
47
+ const { width: naturalWidth, height: naturalHeight } = e.nativeEvent.source
48
+ setImageSize({ width: naturalWidth, height: naturalHeight })
49
+ setLoading(false)
50
+ }, [])
51
+
52
+ // Reset zoom and pan when modal opens/closes
53
+ const resetTransform = useCallback(() => {
54
+ scale.setValue(1)
55
+ translateX.setValue(0)
56
+ translateY.setValue(0)
57
+ savedScale.current = 1
58
+ savedTranslateX.current = 0
59
+ savedTranslateY.current = 0
60
+ currentScale.current = 1
61
+ currentTranslateX.current = 0
62
+ currentTranslateY.current = 0
63
+ }, [scale, translateX, translateY])
64
+
65
+ // Reset when modal closes or src changes
66
+ React.useEffect(() => {
67
+ if (!isOpen || !src) {
68
+ resetTransform()
69
+ }
70
+ }, [isOpen, src, resetTransform])
71
+
72
+ // Pan gesture
73
+ const panGesture = Gesture.Pan()
74
+ .onUpdate(event => {
75
+ // Only allow panning if zoomed in
76
+ if (savedScale.current > 1) {
77
+ const newTranslateX = savedTranslateX.current + event.translationX
78
+ const newTranslateY = savedTranslateY.current + event.translationY
79
+
80
+ // Calculate bounds to prevent panning too far
81
+ const maxTranslateX = (width * savedScale.current - width) / 2
82
+ const maxTranslateY = (height * savedScale.current - height) / 2
83
+
84
+ const boundedTranslateX = Math.max(-maxTranslateX, Math.min(maxTranslateX, newTranslateX))
85
+ const boundedTranslateY = Math.max(-maxTranslateY, Math.min(maxTranslateY, newTranslateY))
86
+
87
+ translateX.setValue(boundedTranslateX)
88
+ translateY.setValue(boundedTranslateY)
89
+ currentTranslateX.current = boundedTranslateX
90
+ currentTranslateY.current = boundedTranslateY
91
+ }
92
+ })
93
+ .onEnd(() => {
94
+ savedTranslateX.current = currentTranslateX.current
95
+ savedTranslateY.current = currentTranslateY.current
96
+ })
97
+
98
+ // Pinch gesture
99
+ const pinchGesture = Gesture.Pinch()
100
+ .onUpdate(event => {
101
+ const newScale = savedScale.current * event.scale
102
+ // Limit zoom between 1x and 5x
103
+ const boundedScale = Math.max(1, Math.min(5, newScale))
104
+ scale.setValue(boundedScale)
105
+ currentScale.current = boundedScale
106
+
107
+ // If zooming out to 1x, reset position
108
+ if (boundedScale <= 1) {
109
+ translateX.setValue(0)
110
+ translateY.setValue(0)
111
+ currentTranslateX.current = 0
112
+ currentTranslateY.current = 0
113
+ }
114
+ })
115
+ .onEnd(() => {
116
+ savedScale.current = currentScale.current
117
+ // If scale is close to 1, snap back to 1
118
+ if (savedScale.current < 1.1) {
119
+ Animated.parallel([
120
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true }),
121
+ Animated.spring(translateX, { toValue: 0, useNativeDriver: true }),
122
+ Animated.spring(translateY, { toValue: 0, useNativeDriver: true }),
123
+ ]).start()
124
+ savedScale.current = 1
125
+ savedTranslateX.current = 0
126
+ savedTranslateY.current = 0
127
+ currentScale.current = 1
128
+ currentTranslateX.current = 0
129
+ currentTranslateY.current = 0
130
+ } else {
131
+ savedTranslateX.current = currentTranslateX.current
132
+ savedTranslateY.current = currentTranslateY.current
133
+ }
134
+ })
135
+
136
+ // Double tap to zoom
137
+ const doubleTapGesture = Gesture.Tap()
138
+ .numberOfTaps(2)
139
+ .onEnd(() => {
140
+ if (savedScale.current > 1) {
141
+ // Zoom out
142
+ Animated.parallel([
143
+ Animated.spring(scale, { toValue: 1, useNativeDriver: true }),
144
+ Animated.spring(translateX, { toValue: 0, useNativeDriver: true }),
145
+ Animated.spring(translateY, { toValue: 0, useNativeDriver: true }),
146
+ ]).start()
147
+ savedScale.current = 1
148
+ savedTranslateX.current = 0
149
+ savedTranslateY.current = 0
150
+ currentScale.current = 1
151
+ currentTranslateX.current = 0
152
+ currentTranslateY.current = 0
153
+ } else {
154
+ // Zoom in to 2x
155
+ Animated.spring(scale, { toValue: 2, useNativeDriver: true }).start()
156
+ savedScale.current = 2
157
+ currentScale.current = 2
158
+ }
159
+ })
160
+
161
+ // Test simple single tap gesture
162
+
163
+ // Combine gestures - simplified approach
164
+ const combinedGestures = Gesture.Race(
165
+ doubleTapGesture,
166
+ Gesture.Simultaneous(panGesture, pinchGesture),
167
+ )
168
+
169
+ if (!isOpen) {
170
+ return null
171
+ }
172
+
173
+ return (
174
+ <Modal visible={isOpen} transparent animationType="fade" onRequestClose={onClose}>
175
+ <GestureHandlerRootView style={styles.gestureRoot}>
176
+ <View style={styles.modalOverlay}>
177
+ <TouchableOpacity
178
+ style={styles.backgroundTouchable}
179
+ activeOpacity={1}
180
+ onPress={onClose}
181
+ />
182
+ <View style={styles.contentContainer}>
183
+ <GestureDetector gesture={combinedGestures}>
184
+ <Animated.View
185
+ style={[
186
+ styles.imageContainer,
187
+ {
188
+ width,
189
+ height,
190
+ opacity: loading ? 0 : 1,
191
+ transform: [{ scale }, { translateX }, { translateY }],
192
+ },
193
+ ]}>
194
+ <Image
195
+ source={src ? { uri: src } : undefined}
196
+ style={styles.image}
197
+ onLoadStart={onLoadStart}
198
+ onLoad={onLoad}
199
+ resizeMode="contain"
200
+ />
201
+ </Animated.View>
202
+ </GestureDetector>
203
+
204
+ <TouchableOpacity style={styles.closeButton} onPress={onClose}>
205
+ <Ionicons name="close" size={24} color="white" />
206
+ </TouchableOpacity>
207
+
208
+ {loading || !src ? (
209
+ <View style={styles.loadingContainer}>
210
+ <LoadingLogo isLoading={loading} size={70} />
211
+ </View>
212
+ ) : null}
213
+ </View>
214
+ </View>
215
+ </GestureHandlerRootView>
216
+ </Modal>
217
+ )
218
+ }
219
+
220
+ const styles = StyleSheet.create({
221
+ gestureRoot: {
222
+ flex: 1,
223
+ },
224
+ modalOverlay: {
225
+ flex: 1,
226
+ backgroundColor: 'rgba(0, 0, 0, 0.7)',
227
+ },
228
+ backgroundTouchable: {
229
+ ...StyleSheet.absoluteFillObject,
230
+ },
231
+ contentContainer: {
232
+ flex: 1,
233
+ justifyContent: 'center',
234
+ alignItems: 'center',
235
+ padding: 16,
236
+ },
237
+ imageContainer: {
238
+ overflow: 'hidden',
239
+ borderRadius: 4,
240
+ },
241
+ image: {
242
+ width: '100%',
243
+ height: '100%',
244
+ },
245
+ closeButton: {
246
+ position: 'absolute',
247
+ top: 16,
248
+ right: 16,
249
+ width: 40,
250
+ height: 40,
251
+ borderRadius: 20,
252
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
253
+ justifyContent: 'center',
254
+ alignItems: 'center',
255
+ },
256
+ loadingContainer: {
257
+ ...StyleSheet.absoluteFillObject,
258
+ justifyContent: 'center',
259
+ alignItems: 'center',
260
+ },
261
+ })