@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.
- package/lib/commonjs/components/form/UploadProgress/index.js +8 -17
- package/lib/commonjs/components/form/UploadProgress/index.js.map +1 -1
- package/lib/commonjs/components/form/input/file/index.js +26 -8
- package/lib/commonjs/components/form/input/file/index.js.map +1 -1
- package/lib/commonjs/components/image/ImageViewModal.backup.js +285 -0
- package/lib/commonjs/components/image/ImageViewModal.backup.js.map +1 -0
- package/lib/commonjs/components/image/ImageViewModal.js +79 -99
- package/lib/commonjs/components/image/ImageViewModal.js.map +1 -1
- package/lib/commonjs/components/image/ImageViewModal.old.js +285 -0
- package/lib/commonjs/components/image/ImageViewModal.old.js.map +1 -0
- package/lib/commonjs/components/loading/ProgressBar.js +78 -0
- package/lib/commonjs/components/loading/ProgressBar.js.map +1 -0
- package/lib/commonjs/components/loading/index.js +11 -0
- package/lib/commonjs/components/loading/index.js.map +1 -1
- package/lib/module/components/form/UploadProgress/index.js +6 -15
- package/lib/module/components/form/UploadProgress/index.js.map +1 -1
- package/lib/module/components/form/input/file/index.js +27 -9
- package/lib/module/components/form/input/file/index.js.map +1 -1
- package/lib/module/components/image/ImageViewModal.backup.js +277 -0
- package/lib/module/components/image/ImageViewModal.backup.js.map +1 -0
- package/lib/module/components/image/ImageViewModal.js +80 -100
- package/lib/module/components/image/ImageViewModal.js.map +1 -1
- package/lib/module/components/image/ImageViewModal.old.js +277 -0
- package/lib/module/components/image/ImageViewModal.old.js.map +1 -0
- package/lib/module/components/loading/ProgressBar.js +70 -0
- package/lib/module/components/loading/ProgressBar.js.map +1 -0
- package/lib/module/components/loading/index.js +1 -0
- package/lib/module/components/loading/index.js.map +1 -1
- package/lib/typescript/components/form/UploadProgress/index.d.ts.map +1 -1
- package/lib/typescript/components/form/input/file/index.d.ts +5 -3
- package/lib/typescript/components/form/input/file/index.d.ts.map +1 -1
- package/lib/typescript/components/image/ImageViewModal.backup.d.ts +9 -0
- package/lib/typescript/components/image/ImageViewModal.backup.d.ts.map +1 -0
- package/lib/typescript/components/image/ImageViewModal.d.ts.map +1 -1
- package/lib/typescript/components/image/ImageViewModal.old.d.ts +9 -0
- package/lib/typescript/components/image/ImageViewModal.old.d.ts.map +1 -0
- package/lib/typescript/components/loading/ProgressBar.d.ts +7 -0
- package/lib/typescript/components/loading/ProgressBar.d.ts.map +1 -0
- package/lib/typescript/components/loading/index.d.ts +1 -0
- package/lib/typescript/components/loading/index.d.ts.map +1 -1
- package/package.json +11 -10
- package/src/components/form/UploadProgress/index.tsx +3 -17
- package/src/components/form/input/file/index.tsx +28 -8
- package/src/components/image/ImageViewModal.backup.tsx +261 -0
- package/src/components/image/ImageViewModal.old.tsx +261 -0
- package/src/components/image/ImageViewModal.tsx +72 -79
- package/src/components/loading/ProgressBar.tsx +75 -0
- 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":[]}
|
|
@@ -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;
|
|
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?:
|
|
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;
|
|
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,
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|
|
@@ -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.
|
|
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.
|
|
38
|
-
"expo-document-picker": "~13.1.
|
|
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": "
|
|
42
|
+
"react": "19.0.0",
|
|
43
43
|
"react-hook-form": "^7.55.0",
|
|
44
|
-
"react-native": "0.79.
|
|
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/
|
|
53
|
-
"@chem-po/
|
|
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": "
|
|
71
|
-
"react-dom": "
|
|
72
|
-
"react-native": "0.79.
|
|
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 {
|
|
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
|
-
<
|
|
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?:
|
|
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
|
-
<
|
|
86
|
-
|
|
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
|
-
|
|
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
|
+
})
|