@symbiote-native/image-picker 0.1.0
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/LICENSE +21 -0
- package/README.md +188 -0
- package/build/angular/index.d.ts +3 -0
- package/build/angular/index.js +3 -0
- package/build/angular/services/camera-permissions.service/index.d.ts +5 -0
- package/build/angular/services/camera-permissions.service/index.js +60 -0
- package/build/angular/services/media-library-permissions.service/index.d.ts +5 -0
- package/build/angular/services/media-library-permissions.service/index.js +60 -0
- package/build/core/image-picker.d.ts +9 -0
- package/build/core/image-picker.js +52 -0
- package/build/core/index.d.ts +3 -0
- package/build/core/index.js +3 -0
- package/build/core/media-library-permission-api.d.ts +11 -0
- package/build/core/media-library-permission-api.js +9 -0
- package/build/core/native-module.d.ts +13 -0
- package/build/core/native-module.js +3 -0
- package/build/core/types.d.ts +127 -0
- package/build/core/types.js +54 -0
- package/build/core/utils.d.ts +4 -0
- package/build/core/utils.js +24 -0
- package/build/react/index.d.ts +3 -0
- package/build/react/index.js +3 -0
- package/build/react/use-camera-permissions.d.ts +8 -0
- package/build/react/use-camera-permissions.js +10 -0
- package/build/react/use-media-library-permissions.d.ts +10 -0
- package/build/react/use-media-library-permissions.js +7 -0
- package/build/solid/index.d.ts +3 -0
- package/build/solid/index.js +3 -0
- package/build/solid/use-camera-permissions.d.ts +9 -0
- package/build/solid/use-camera-permissions.js +10 -0
- package/build/solid/use-media-library-permissions.d.ts +11 -0
- package/build/solid/use-media-library-permissions.js +7 -0
- package/build/svelte/index.d.ts +3 -0
- package/build/svelte/index.js +3 -0
- package/build/svelte/use-camera-permissions.svelte.d.ts +8 -0
- package/build/svelte/use-camera-permissions.svelte.js +10 -0
- package/build/svelte/use-media-library-permissions.svelte.d.ts +10 -0
- package/build/svelte/use-media-library-permissions.svelte.js +7 -0
- package/build/vue/index.d.ts +3 -0
- package/build/vue/index.js +3 -0
- package/build/vue/use-camera-permissions.d.ts +9 -0
- package/build/vue/use-camera-permissions.js +10 -0
- package/build/vue/use-media-library-permissions.d.ts +11 -0
- package/build/vue/use-media-library-permissions.js +7 -0
- package/build-ngc/angular/index.d.ts +3 -0
- package/build-ngc/angular/index.js +4 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/angular/services/camera-permissions.service/index.d.ts +8 -0
- package/build-ngc/angular/services/camera-permissions.service/index.js +17 -0
- package/build-ngc/angular/services/camera-permissions.service/index.js.map +1 -0
- package/build-ngc/angular/services/media-library-permissions.service/index.d.ts +8 -0
- package/build-ngc/angular/services/media-library-permissions.service/index.js +17 -0
- package/build-ngc/angular/services/media-library-permissions.service/index.js.map +1 -0
- package/build-ngc/core/image-picker.d.ts +9 -0
- package/build-ngc/core/image-picker.js +53 -0
- package/build-ngc/core/image-picker.js.map +1 -0
- package/build-ngc/core/index.d.ts +3 -0
- package/build-ngc/core/index.js +4 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/media-library-permission-api.d.ts +11 -0
- package/build-ngc/core/media-library-permission-api.js +10 -0
- package/build-ngc/core/media-library-permission-api.js.map +1 -0
- package/build-ngc/core/native-module.d.ts +13 -0
- package/build-ngc/core/native-module.js +4 -0
- package/build-ngc/core/native-module.js.map +1 -0
- package/build-ngc/core/types.d.ts +127 -0
- package/build-ngc/core/types.js +55 -0
- package/build-ngc/core/types.js.map +1 -0
- package/build-ngc/core/utils.d.ts +4 -0
- package/build-ngc/core/utils.js +25 -0
- package/build-ngc/core/utils.js.map +1 -0
- package/native-link.json +20 -0
- package/package.json +150 -0
- package/src/angular/index.ts +3 -0
- package/src/angular/services/camera-permissions.service/index.ts +16 -0
- package/src/angular/services/media-library-permissions.service/index.ts +19 -0
- package/src/core/image-picker.ts +90 -0
- package/src/core/index.ts +11 -0
- package/src/core/media-library-permission-api.ts +23 -0
- package/src/core/native-module.ts +34 -0
- package/src/core/types.ts +145 -0
- package/src/core/utils.ts +36 -0
- package/src/react/index.ts +6 -0
- package/src/react/use-camera-permissions.ts +25 -0
- package/src/react/use-media-library-permissions.ts +26 -0
- package/src/solid/index.ts +6 -0
- package/src/solid/use-camera-permissions.ts +26 -0
- package/src/solid/use-media-library-permissions.ts +27 -0
- package/src/svelte/index.ts +6 -0
- package/src/svelte/svelte-ambient.d.ts +3 -0
- package/src/svelte/svelte-compile.test-helper.ts +7 -0
- package/src/svelte/use-camera-permissions.svelte.ts +25 -0
- package/src/svelte/use-media-library-permissions.svelte.ts +26 -0
- package/src/vue/index.ts +6 -0
- package/src/vue/use-camera-permissions.ts +26 -0
- package/src/vue/use-media-library-permissions.ts +27 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { PermissionResponse } from 'expo-modules-core';
|
|
2
|
+
export type ICameraPermissionResponse = PermissionResponse;
|
|
3
|
+
export type IMediaLibraryPermissionResponse = PermissionResponse & {
|
|
4
|
+
/** `'all'` | `'limited'` (Android 13+/iOS 14+) | `'none'`. */
|
|
5
|
+
accessPrivileges?: 'all' | 'limited' | 'none';
|
|
6
|
+
};
|
|
7
|
+
/** @deprecated use an array of `IMediaType` instead. */
|
|
8
|
+
export declare enum MediaTypeOptions {
|
|
9
|
+
All = "All",
|
|
10
|
+
Videos = "Videos",
|
|
11
|
+
Images = "Images"
|
|
12
|
+
}
|
|
13
|
+
export type IMediaType = 'images' | 'videos' | 'livePhotos';
|
|
14
|
+
/** Android only. */
|
|
15
|
+
export type IDefaultTab = 'photos' | 'albums';
|
|
16
|
+
export declare enum VideoExportPreset {
|
|
17
|
+
Passthrough = 0,
|
|
18
|
+
LowQuality = 1,
|
|
19
|
+
MediumQuality = 2,
|
|
20
|
+
HighestQuality = 3,
|
|
21
|
+
H264_640x480 = 4,
|
|
22
|
+
H264_960x540 = 5,
|
|
23
|
+
H264_1280x720 = 6,
|
|
24
|
+
H264_1920x1080 = 7,
|
|
25
|
+
H264_3840x2160 = 8,
|
|
26
|
+
HEVC_1920x1080 = 9,
|
|
27
|
+
HEVC_3840x2160 = 10
|
|
28
|
+
}
|
|
29
|
+
export declare enum UIImagePickerControllerQualityType {
|
|
30
|
+
High = 0,
|
|
31
|
+
Medium = 1,
|
|
32
|
+
Low = 2,
|
|
33
|
+
VGA640x480 = 3,
|
|
34
|
+
IFrame1280x720 = 4,
|
|
35
|
+
IFrame960x540 = 5
|
|
36
|
+
}
|
|
37
|
+
/** iOS only — maps to `UIModalPresentationStyle`. */
|
|
38
|
+
export declare enum UIImagePickerPresentationStyle {
|
|
39
|
+
FULL_SCREEN = "fullScreen",
|
|
40
|
+
PAGE_SHEET = "pageSheet",
|
|
41
|
+
FORM_SHEET = "formSheet",
|
|
42
|
+
CURRENT_CONTEXT = "currentContext",
|
|
43
|
+
OVER_FULL_SCREEN = "overFullScreen",
|
|
44
|
+
OVER_CURRENT_CONTEXT = "overCurrentContext",
|
|
45
|
+
POPOVER = "popover",
|
|
46
|
+
AUTOMATIC = "automatic"
|
|
47
|
+
}
|
|
48
|
+
/** iOS only — maps to `PHPickerConfigurationAssetRepresentationMode`. */
|
|
49
|
+
export declare enum UIImagePickerPreferredAssetRepresentationMode {
|
|
50
|
+
Automatic = "automatic",
|
|
51
|
+
Compatible = "compatible",
|
|
52
|
+
Current = "current"
|
|
53
|
+
}
|
|
54
|
+
export declare enum CameraType {
|
|
55
|
+
back = "back",
|
|
56
|
+
front = "front"
|
|
57
|
+
}
|
|
58
|
+
export type IImagePickerAsset = {
|
|
59
|
+
uri: string;
|
|
60
|
+
/** Usable with `@symbiote-native/media-library`. Null if unavailable or access is limited. */
|
|
61
|
+
assetId?: string | null;
|
|
62
|
+
width: number;
|
|
63
|
+
height: number;
|
|
64
|
+
type?: 'image' | 'video' | 'livePhoto' | 'pairedVideo' | null;
|
|
65
|
+
fileName?: string | null;
|
|
66
|
+
fileSize?: number;
|
|
67
|
+
exif?: Record<string, unknown> | null;
|
|
68
|
+
/** Base64 JPEG data — set only when the `base64` option is truthy. */
|
|
69
|
+
base64?: string | null;
|
|
70
|
+
duration?: number | null;
|
|
71
|
+
mimeType?: string;
|
|
72
|
+
/** Set only when `livePhotos` was requested and a live photo was picked. iOS only. */
|
|
73
|
+
pairedVideoAsset?: IImagePickerAsset | null;
|
|
74
|
+
};
|
|
75
|
+
export type IImagePickerErrorResult = {
|
|
76
|
+
code: string;
|
|
77
|
+
message: string;
|
|
78
|
+
exception?: string;
|
|
79
|
+
};
|
|
80
|
+
export type IImagePickerSuccessResult = {
|
|
81
|
+
canceled: false;
|
|
82
|
+
assets: IImagePickerAsset[];
|
|
83
|
+
};
|
|
84
|
+
export type IImagePickerCanceledResult = {
|
|
85
|
+
canceled: true;
|
|
86
|
+
assets: null;
|
|
87
|
+
};
|
|
88
|
+
export type IImagePickerResult = IImagePickerSuccessResult | IImagePickerCanceledResult;
|
|
89
|
+
export type ICropShape = 'rectangle' | 'oval';
|
|
90
|
+
export type IImagePickerOptions = {
|
|
91
|
+
/** Crop/rotate after picking. Exclusive with `allowsMultipleSelection`. Default `false`. */
|
|
92
|
+
allowsEditing?: boolean;
|
|
93
|
+
/** `[x, y]` crop aspect ratio. Android only. */
|
|
94
|
+
aspect?: [number, number];
|
|
95
|
+
/** Android only. Default `'rectangle'`. */
|
|
96
|
+
shape?: ICropShape;
|
|
97
|
+
/** `0`–`1`. Default `1.0`. */
|
|
98
|
+
quality?: number;
|
|
99
|
+
/** Default `'images'`. */
|
|
100
|
+
mediaTypes?: IMediaType | IMediaType[] | MediaTypeOptions;
|
|
101
|
+
exif?: boolean;
|
|
102
|
+
base64?: boolean;
|
|
103
|
+
/** @deprecated iOS 11+ only. */
|
|
104
|
+
videoExportPreset?: VideoExportPreset;
|
|
105
|
+
/** iOS only. Default `High`. */
|
|
106
|
+
videoQuality?: UIImagePickerControllerQualityType;
|
|
107
|
+
/** Ignored when `allowsEditing` is set. Default `false`. */
|
|
108
|
+
allowsMultipleSelection?: boolean;
|
|
109
|
+
/** `0` = system maximum. Android + iOS 14+. Default `0`. */
|
|
110
|
+
selectionLimit?: number;
|
|
111
|
+
/** iOS 15+ only. Default `false`. */
|
|
112
|
+
orderedSelection?: boolean;
|
|
113
|
+
/** Android only. Default `'photos'`. */
|
|
114
|
+
defaultTab?: IDefaultTab;
|
|
115
|
+
/** Seconds. `0` = no limit (default). No effect on web. */
|
|
116
|
+
videoMaxDuration?: number;
|
|
117
|
+
/** iOS only. Default `AUTOMATIC`. */
|
|
118
|
+
presentationStyle?: UIImagePickerPresentationStyle;
|
|
119
|
+
/** Default `back`. */
|
|
120
|
+
cameraType?: CameraType;
|
|
121
|
+
/** iOS 14+ only. Default `Automatic`. */
|
|
122
|
+
preferredAssetRepresentationMode?: UIImagePickerPreferredAssetRepresentationMode;
|
|
123
|
+
/** Android only — allows picking from outside the photo library. Default `false`. */
|
|
124
|
+
legacy?: boolean;
|
|
125
|
+
/** iOS only — download from iCloud if not stored locally. Default `false`. */
|
|
126
|
+
shouldDownloadFromNetwork?: boolean;
|
|
127
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** @deprecated use an array of `IMediaType` instead. */
|
|
2
|
+
export var MediaTypeOptions;
|
|
3
|
+
(function (MediaTypeOptions) {
|
|
4
|
+
MediaTypeOptions["All"] = "All";
|
|
5
|
+
MediaTypeOptions["Videos"] = "Videos";
|
|
6
|
+
MediaTypeOptions["Images"] = "Images";
|
|
7
|
+
})(MediaTypeOptions || (MediaTypeOptions = {}));
|
|
8
|
+
export var VideoExportPreset;
|
|
9
|
+
(function (VideoExportPreset) {
|
|
10
|
+
VideoExportPreset[VideoExportPreset["Passthrough"] = 0] = "Passthrough";
|
|
11
|
+
VideoExportPreset[VideoExportPreset["LowQuality"] = 1] = "LowQuality";
|
|
12
|
+
VideoExportPreset[VideoExportPreset["MediumQuality"] = 2] = "MediumQuality";
|
|
13
|
+
VideoExportPreset[VideoExportPreset["HighestQuality"] = 3] = "HighestQuality";
|
|
14
|
+
VideoExportPreset[VideoExportPreset["H264_640x480"] = 4] = "H264_640x480";
|
|
15
|
+
VideoExportPreset[VideoExportPreset["H264_960x540"] = 5] = "H264_960x540";
|
|
16
|
+
VideoExportPreset[VideoExportPreset["H264_1280x720"] = 6] = "H264_1280x720";
|
|
17
|
+
VideoExportPreset[VideoExportPreset["H264_1920x1080"] = 7] = "H264_1920x1080";
|
|
18
|
+
VideoExportPreset[VideoExportPreset["H264_3840x2160"] = 8] = "H264_3840x2160";
|
|
19
|
+
VideoExportPreset[VideoExportPreset["HEVC_1920x1080"] = 9] = "HEVC_1920x1080";
|
|
20
|
+
VideoExportPreset[VideoExportPreset["HEVC_3840x2160"] = 10] = "HEVC_3840x2160";
|
|
21
|
+
})(VideoExportPreset || (VideoExportPreset = {}));
|
|
22
|
+
export var UIImagePickerControllerQualityType;
|
|
23
|
+
(function (UIImagePickerControllerQualityType) {
|
|
24
|
+
UIImagePickerControllerQualityType[UIImagePickerControllerQualityType["High"] = 0] = "High";
|
|
25
|
+
UIImagePickerControllerQualityType[UIImagePickerControllerQualityType["Medium"] = 1] = "Medium";
|
|
26
|
+
UIImagePickerControllerQualityType[UIImagePickerControllerQualityType["Low"] = 2] = "Low";
|
|
27
|
+
UIImagePickerControllerQualityType[UIImagePickerControllerQualityType["VGA640x480"] = 3] = "VGA640x480";
|
|
28
|
+
UIImagePickerControllerQualityType[UIImagePickerControllerQualityType["IFrame1280x720"] = 4] = "IFrame1280x720";
|
|
29
|
+
UIImagePickerControllerQualityType[UIImagePickerControllerQualityType["IFrame960x540"] = 5] = "IFrame960x540";
|
|
30
|
+
})(UIImagePickerControllerQualityType || (UIImagePickerControllerQualityType = {}));
|
|
31
|
+
/** iOS only — maps to `UIModalPresentationStyle`. */
|
|
32
|
+
export var UIImagePickerPresentationStyle;
|
|
33
|
+
(function (UIImagePickerPresentationStyle) {
|
|
34
|
+
UIImagePickerPresentationStyle["FULL_SCREEN"] = "fullScreen";
|
|
35
|
+
UIImagePickerPresentationStyle["PAGE_SHEET"] = "pageSheet";
|
|
36
|
+
UIImagePickerPresentationStyle["FORM_SHEET"] = "formSheet";
|
|
37
|
+
UIImagePickerPresentationStyle["CURRENT_CONTEXT"] = "currentContext";
|
|
38
|
+
UIImagePickerPresentationStyle["OVER_FULL_SCREEN"] = "overFullScreen";
|
|
39
|
+
UIImagePickerPresentationStyle["OVER_CURRENT_CONTEXT"] = "overCurrentContext";
|
|
40
|
+
UIImagePickerPresentationStyle["POPOVER"] = "popover";
|
|
41
|
+
UIImagePickerPresentationStyle["AUTOMATIC"] = "automatic";
|
|
42
|
+
})(UIImagePickerPresentationStyle || (UIImagePickerPresentationStyle = {}));
|
|
43
|
+
/** iOS only — maps to `PHPickerConfigurationAssetRepresentationMode`. */
|
|
44
|
+
export var UIImagePickerPreferredAssetRepresentationMode;
|
|
45
|
+
(function (UIImagePickerPreferredAssetRepresentationMode) {
|
|
46
|
+
UIImagePickerPreferredAssetRepresentationMode["Automatic"] = "automatic";
|
|
47
|
+
UIImagePickerPreferredAssetRepresentationMode["Compatible"] = "compatible";
|
|
48
|
+
UIImagePickerPreferredAssetRepresentationMode["Current"] = "current";
|
|
49
|
+
})(UIImagePickerPreferredAssetRepresentationMode || (UIImagePickerPreferredAssetRepresentationMode = {}));
|
|
50
|
+
export var CameraType;
|
|
51
|
+
(function (CameraType) {
|
|
52
|
+
CameraType["back"] = "back";
|
|
53
|
+
CameraType["front"] = "front";
|
|
54
|
+
})(CameraType || (CameraType = {}));
|
|
55
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AASA,wDAAwD;AACxD,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,+BAAW,CAAA;IACX,qCAAiB,CAAA;IACjB,qCAAiB,CAAA;AACnB,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B;AAOD,MAAM,CAAN,IAAY,iBAYX;AAZD,WAAY,iBAAiB;IAC3B,uEAAe,CAAA;IACf,qEAAc,CAAA;IACd,2EAAiB,CAAA;IACjB,6EAAkB,CAAA;IAClB,yEAAgB,CAAA;IAChB,yEAAgB,CAAA;IAChB,2EAAiB,CAAA;IACjB,6EAAkB,CAAA;IAClB,6EAAkB,CAAA;IAClB,6EAAkB,CAAA;IAClB,8EAAmB,CAAA;AACrB,CAAC,EAZW,iBAAiB,KAAjB,iBAAiB,QAY5B;AAED,MAAM,CAAN,IAAY,kCAOX;AAPD,WAAY,kCAAkC;IAC5C,2FAAQ,CAAA;IACR,+FAAU,CAAA;IACV,yFAAO,CAAA;IACP,uGAAc,CAAA;IACd,+GAAkB,CAAA;IAClB,6GAAiB,CAAA;AACnB,CAAC,EAPW,kCAAkC,KAAlC,kCAAkC,QAO7C;AAED,qDAAqD;AACrD,MAAM,CAAN,IAAY,8BASX;AATD,WAAY,8BAA8B;IACxC,4DAA0B,CAAA;IAC1B,0DAAwB,CAAA;IACxB,0DAAwB,CAAA;IACxB,oEAAkC,CAAA;IAClC,qEAAmC,CAAA;IACnC,6EAA2C,CAAA;IAC3C,qDAAmB,CAAA;IACnB,yDAAuB,CAAA;AACzB,CAAC,EATW,8BAA8B,KAA9B,8BAA8B,QASzC;AAED,yEAAyE;AACzE,MAAM,CAAN,IAAY,6CAIX;AAJD,WAAY,6CAA6C;IACvD,wEAAuB,CAAA;IACvB,0EAAyB,CAAA;IACzB,oEAAmB,CAAA;AACrB,CAAC,EAJW,6CAA6C,KAA7C,6CAA6C,QAIxD;AAED,MAAM,CAAN,IAAY,UAGX;AAHD,WAAY,UAAU;IACpB,2BAAa,CAAA;IACb,6BAAe,CAAA;AACjB,CAAC,EAHW,UAAU,KAAV,UAAU,QAGrB"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { MediaTypeOptions } from './types';
|
|
2
|
+
import type { IImagePickerOptions, IMediaType } from './types';
|
|
3
|
+
export declare function parseMediaTypes(mediaTypes: MediaTypeOptions | IMediaType | IMediaType[]): IMediaType[];
|
|
4
|
+
export declare function mapDeprecatedOptions(options: IImagePickerOptions): IImagePickerOptions;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MediaTypeOptions } from './types';
|
|
2
|
+
const DEPRECATED_MEDIA_TYPE_MAP = {
|
|
3
|
+
[MediaTypeOptions.Images]: ['images'],
|
|
4
|
+
[MediaTypeOptions.Videos]: ['videos'],
|
|
5
|
+
[MediaTypeOptions.All]: ['images', 'videos'],
|
|
6
|
+
};
|
|
7
|
+
export function parseMediaTypes(mediaTypes) {
|
|
8
|
+
if (mediaTypes === MediaTypeOptions.Images ||
|
|
9
|
+
mediaTypes === MediaTypeOptions.Videos ||
|
|
10
|
+
mediaTypes === MediaTypeOptions.All) {
|
|
11
|
+
console.warn('[image-picker] `MediaTypeOptions` is deprecated. Use `IMediaType` or an array of it instead.');
|
|
12
|
+
return DEPRECATED_MEDIA_TYPE_MAP[mediaTypes];
|
|
13
|
+
}
|
|
14
|
+
if (typeof mediaTypes === 'string') {
|
|
15
|
+
return [mediaTypes];
|
|
16
|
+
}
|
|
17
|
+
return mediaTypes;
|
|
18
|
+
}
|
|
19
|
+
export function mapDeprecatedOptions(options) {
|
|
20
|
+
if (!options.mediaTypes) {
|
|
21
|
+
return options;
|
|
22
|
+
}
|
|
23
|
+
return { ...options, mediaTypes: parseMediaTypes(options.mediaTypes) };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/core/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG3C,MAAM,yBAAyB,GAA2C;IACxE,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC;IACrC,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC;IACrC,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7C,CAAC;AAEF,MAAM,UAAU,eAAe,CAC7B,UAAwD;IAExD,IACE,UAAU,KAAK,gBAAgB,CAAC,MAAM;QACtC,UAAU,KAAK,gBAAgB,CAAC,MAAM;QACtC,UAAU,KAAK,gBAAgB,CAAC,GAAG,EACnC,CAAC;QACD,OAAO,CAAC,IAAI,CACV,8FAA8F,CAC/F,CAAC;QACF,OAAO,yBAAyB,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,OAA4B;IAE5B,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;AACzE,CAAC"}
|
package/native-link.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"android": {
|
|
3
|
+
"gradleProjectName": "expo-image-picker",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"importPath": "expo.modules.imagepicker.ImagePickerModule",
|
|
7
|
+
"className": "ImagePickerModule",
|
|
8
|
+
"nativeName": "ExponentImagePicker"
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
"manifestPermissions": ["android.permission.RECORD_AUDIO"]
|
|
12
|
+
},
|
|
13
|
+
"ios": {
|
|
14
|
+
"infoPlistKeys": {
|
|
15
|
+
"NSPhotoLibraryUsageDescription": "This app uses the photo library to let you pick images and videos.",
|
|
16
|
+
"NSCameraUsageDescription": "This app uses the camera to let you take a photo or video.",
|
|
17
|
+
"NSMicrophoneUsageDescription": "This app uses the microphone to record audio for videos."
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@symbiote-native/image-picker",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "expo-image-picker wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Opens the system UI for picking an image/video or taking a photo with the camera.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"react-native",
|
|
8
|
+
"symbiote-native",
|
|
9
|
+
"expo-image-picker",
|
|
10
|
+
"react",
|
|
11
|
+
"vue",
|
|
12
|
+
"svelte",
|
|
13
|
+
"solid",
|
|
14
|
+
"angular",
|
|
15
|
+
"image-picker",
|
|
16
|
+
"camera"
|
|
17
|
+
],
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/OneEyed1366/symbiote-native.git",
|
|
21
|
+
"directory": "packages/image-picker"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/OneEyed1366/symbiote-native/tree/master/packages/image-picker#readme",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/OneEyed1366/symbiote-native/issues"
|
|
26
|
+
},
|
|
27
|
+
"author": "Andrey Prokopenko <psevdoproger@gmail.com>",
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "./build/core/index.js",
|
|
30
|
+
"module": "./build/core/index.js",
|
|
31
|
+
"types": "./build/core/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./build/core/index.d.ts",
|
|
35
|
+
"default": "./build/core/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./vue": {
|
|
38
|
+
"types": "./build/vue/index.d.ts",
|
|
39
|
+
"default": "./build/vue/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./react": {
|
|
42
|
+
"types": "./build/react/index.d.ts",
|
|
43
|
+
"default": "./build/react/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./svelte": {
|
|
46
|
+
"types": "./build/svelte/index.d.ts",
|
|
47
|
+
"default": "./build/svelte/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./solid": {
|
|
50
|
+
"types": "./build/solid/index.d.ts",
|
|
51
|
+
"default": "./build/solid/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./angular": {
|
|
54
|
+
"types": "./build-ngc/angular/index.d.ts",
|
|
55
|
+
"react-native": "./build-ngc/angular/index.js",
|
|
56
|
+
"default": "./src/angular/index.ts"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"files": [
|
|
60
|
+
"src",
|
|
61
|
+
"build",
|
|
62
|
+
"build-ngc",
|
|
63
|
+
"native-link.json",
|
|
64
|
+
"!src/**/*.test.*",
|
|
65
|
+
"!src/**/*.spec.*",
|
|
66
|
+
"!src/**/*.detox.*"
|
|
67
|
+
],
|
|
68
|
+
"publishConfig": {
|
|
69
|
+
"access": "public"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"expo-image-picker": "57.0.20",
|
|
73
|
+
"expo-modules-core": "57.0.20"
|
|
74
|
+
},
|
|
75
|
+
"peerDependencies": {
|
|
76
|
+
"@angular/core": ">=20",
|
|
77
|
+
"@vue/runtime-core": "^3.5.13",
|
|
78
|
+
"react": ">=19.0.0",
|
|
79
|
+
"react-native": ">=0.86",
|
|
80
|
+
"solid-js": ">=1.9.0",
|
|
81
|
+
"svelte": ">=5.56.0",
|
|
82
|
+
"vue": ">=3.5.0",
|
|
83
|
+
"@symbiote-native/angular": "^3.1.3",
|
|
84
|
+
"@symbiote-native/engine": "^1.4.0",
|
|
85
|
+
"@symbiote-native/svelte": "^3.0.5",
|
|
86
|
+
"@symbiote-native/vue": "^3.1.0",
|
|
87
|
+
"@symbiote-native/react": "^3.1.0",
|
|
88
|
+
"@symbiote-native/solid": "^3.0.5"
|
|
89
|
+
},
|
|
90
|
+
"peerDependenciesMeta": {
|
|
91
|
+
"@symbiote-native/angular": {
|
|
92
|
+
"optional": true
|
|
93
|
+
},
|
|
94
|
+
"@symbiote-native/react": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"@symbiote-native/solid": {
|
|
98
|
+
"optional": true
|
|
99
|
+
},
|
|
100
|
+
"@symbiote-native/svelte": {
|
|
101
|
+
"optional": true
|
|
102
|
+
},
|
|
103
|
+
"@symbiote-native/vue": {
|
|
104
|
+
"optional": true
|
|
105
|
+
},
|
|
106
|
+
"@angular/core": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
109
|
+
"@vue/runtime-core": {
|
|
110
|
+
"optional": true
|
|
111
|
+
},
|
|
112
|
+
"react": {
|
|
113
|
+
"optional": true
|
|
114
|
+
},
|
|
115
|
+
"solid-js": {
|
|
116
|
+
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"svelte": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"vue": {
|
|
122
|
+
"optional": true
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"devDependencies": {
|
|
126
|
+
"@angular/compiler": "~22.0.8",
|
|
127
|
+
"@angular/compiler-cli": "~22.0.8",
|
|
128
|
+
"@angular/core": "~22.0.8",
|
|
129
|
+
"@types/node": "^26.0.0",
|
|
130
|
+
"@types/react": "^19.2.0",
|
|
131
|
+
"@vue/runtime-core": "^3.5.13",
|
|
132
|
+
"react": "19.2.3",
|
|
133
|
+
"solid-js": "^1.9.14",
|
|
134
|
+
"svelte": "^5.56.0",
|
|
135
|
+
"typescript": "~6.0.0",
|
|
136
|
+
"@symbiote-native/angular": "3.1.3",
|
|
137
|
+
"@symbiote-native/vue": "3.1.0",
|
|
138
|
+
"@symbiote-native/svelte": "3.0.5",
|
|
139
|
+
"@symbiote-native/solid": "3.0.5",
|
|
140
|
+
"@symbiote-native/engine": "1.4.0",
|
|
141
|
+
"@symbiote-native/react": "3.1.0",
|
|
142
|
+
"@symbiote-native/test-utils": "0.4.5"
|
|
143
|
+
},
|
|
144
|
+
"scripts": {
|
|
145
|
+
"typecheck": "tsc --build",
|
|
146
|
+
"clean": "rm -rf build-ngc",
|
|
147
|
+
"ng:build": "pnpm run clean && ngc -p tsconfig.angular.json",
|
|
148
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Angular twin of `../../react`'s `useCameraPermissions`
|
|
2
|
+
|
|
3
|
+
import { Injectable } from '@angular/core';
|
|
4
|
+
import { PermissionsServiceBase } from '@symbiote-native/angular';
|
|
5
|
+
import {
|
|
6
|
+
getCameraPermissionsAsync,
|
|
7
|
+
requestCameraPermissionsAsync,
|
|
8
|
+
} from '../../../core';
|
|
9
|
+
import type { ICameraPermissionResponse } from '../../../core';
|
|
10
|
+
|
|
11
|
+
@Injectable({ providedIn: 'root' })
|
|
12
|
+
export class CameraPermissionsService extends PermissionsServiceBase<ICameraPermissionResponse> {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(getCameraPermissionsAsync, requestCameraPermissionsAsync);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Angular twin of `../../react`'s `useMediaLibraryPermissions`, `get`/`request` take a `writeOnly` flag
|
|
2
|
+
|
|
3
|
+
import { Injectable } from '@angular/core';
|
|
4
|
+
import { PermissionsServiceBase } from '@symbiote-native/angular';
|
|
5
|
+
import {
|
|
6
|
+
getMediaLibraryPermissionsAsync,
|
|
7
|
+
requestMediaLibraryPermissionsAsync,
|
|
8
|
+
} from '../../../core';
|
|
9
|
+
import type { IMediaLibraryPermissionResponse } from '../../../core';
|
|
10
|
+
|
|
11
|
+
@Injectable({ providedIn: 'root' })
|
|
12
|
+
export class MediaLibraryPermissionsService extends PermissionsServiceBase<
|
|
13
|
+
IMediaLibraryPermissionResponse,
|
|
14
|
+
boolean
|
|
15
|
+
> {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(getMediaLibraryPermissionsAsync, requestMediaLibraryPermissionsAsync);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { CodedError, UnavailabilityError } from 'expo-modules-core';
|
|
2
|
+
import { expoImagePicker } from './native-module';
|
|
3
|
+
import { mapDeprecatedOptions } from './utils';
|
|
4
|
+
import type {
|
|
5
|
+
ICameraPermissionResponse,
|
|
6
|
+
IImagePickerErrorResult,
|
|
7
|
+
IImagePickerOptions,
|
|
8
|
+
IImagePickerResult,
|
|
9
|
+
IMediaLibraryPermissionResponse,
|
|
10
|
+
} from './types';
|
|
11
|
+
|
|
12
|
+
function validateOptions(options: IImagePickerOptions): IImagePickerOptions {
|
|
13
|
+
const { aspect, quality, videoMaxDuration } = options;
|
|
14
|
+
if (aspect != null) {
|
|
15
|
+
const [x, y] = aspect;
|
|
16
|
+
if (x <= 0 || y <= 0) {
|
|
17
|
+
throw new CodedError(
|
|
18
|
+
'ERR_INVALID_ARGUMENT',
|
|
19
|
+
`Invalid aspect ratio values ${x}:${y}. Provide positive numbers.`,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (quality != null && (quality < 0 || quality > 1)) {
|
|
24
|
+
throw new CodedError(
|
|
25
|
+
'ERR_INVALID_ARGUMENT',
|
|
26
|
+
`Invalid 'quality' value ${quality}. Provide a value between 0 and 1.`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
if (videoMaxDuration != null && videoMaxDuration < 0) {
|
|
30
|
+
throw new CodedError(
|
|
31
|
+
'ERR_INVALID_ARGUMENT',
|
|
32
|
+
`Invalid 'videoMaxDuration' value ${videoMaxDuration}. Provide a non-negative number.`,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return options;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function getCameraPermissionsAsync(): Promise<ICameraPermissionResponse> {
|
|
39
|
+
return expoImagePicker.getCameraPermissionsAsync();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function getMediaLibraryPermissionsAsync(
|
|
43
|
+
writeOnly: boolean = false,
|
|
44
|
+
): Promise<IMediaLibraryPermissionResponse> {
|
|
45
|
+
return expoImagePicker.getMediaLibraryPermissionsAsync(writeOnly);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function requestCameraPermissionsAsync(): Promise<ICameraPermissionResponse> {
|
|
49
|
+
return expoImagePicker.requestCameraPermissionsAsync();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function requestMediaLibraryPermissionsAsync(
|
|
53
|
+
writeOnly: boolean = false,
|
|
54
|
+
): Promise<IMediaLibraryPermissionResponse> {
|
|
55
|
+
return expoImagePicker.requestMediaLibraryPermissionsAsync(writeOnly);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Android only — recovers a result lost to `MainActivity` being killed mid-pick. */
|
|
59
|
+
export async function getPendingResultAsync(): Promise<
|
|
60
|
+
IImagePickerResult | IImagePickerErrorResult | null
|
|
61
|
+
> {
|
|
62
|
+
if (expoImagePicker.getPendingResultAsync) {
|
|
63
|
+
return expoImagePicker.getPendingResultAsync();
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function launchCameraAsync(
|
|
69
|
+
options: IImagePickerOptions = {},
|
|
70
|
+
): Promise<IImagePickerResult> {
|
|
71
|
+
if (!expoImagePicker.launchCameraAsync) {
|
|
72
|
+
throw new UnavailabilityError('ImagePicker', 'launchCameraAsync');
|
|
73
|
+
}
|
|
74
|
+
const mappedOptions = mapDeprecatedOptions(options);
|
|
75
|
+
return await expoImagePicker.launchCameraAsync(
|
|
76
|
+
validateOptions(mappedOptions),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function launchImageLibraryAsync(
|
|
81
|
+
options: IImagePickerOptions = {},
|
|
82
|
+
): Promise<IImagePickerResult> {
|
|
83
|
+
const mappedOptions = mapDeprecatedOptions(options);
|
|
84
|
+
if (mappedOptions.allowsEditing && mappedOptions.allowsMultipleSelection) {
|
|
85
|
+
console.warn(
|
|
86
|
+
'[image-picker] `allowsEditing` is ignored when `allowsMultipleSelection` is enabled.',
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return await expoImagePicker.launchImageLibraryAsync(mappedOptions);
|
|
90
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { PermissionStatus } from 'expo-modules-core';
|
|
2
|
+
export {
|
|
3
|
+
getCameraPermissionsAsync,
|
|
4
|
+
getMediaLibraryPermissionsAsync,
|
|
5
|
+
getPendingResultAsync,
|
|
6
|
+
launchCameraAsync,
|
|
7
|
+
launchImageLibraryAsync,
|
|
8
|
+
requestCameraPermissionsAsync,
|
|
9
|
+
requestMediaLibraryPermissionsAsync,
|
|
10
|
+
} from './image-picker';
|
|
11
|
+
export * from './types';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// `methods` every adapter's `useMediaLibraryPermissions` binds to the shared
|
|
2
|
+
// `@symbiote-native/{react,vue,solid}` `createPermissionHook` factory
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
getMediaLibraryPermissionsAsync,
|
|
6
|
+
requestMediaLibraryPermissionsAsync,
|
|
7
|
+
} from './index';
|
|
8
|
+
import type { IMediaLibraryPermissionResponse } from './types';
|
|
9
|
+
import { splitWriteOnlyPermissionOptions } from '@symbiote-native/engine';
|
|
10
|
+
|
|
11
|
+
export type IMediaLibraryPermissionMethodOptions = { writeOnly?: boolean };
|
|
12
|
+
|
|
13
|
+
export const mediaLibraryPermissionMethods = {
|
|
14
|
+
getMethod: (options?: IMediaLibraryPermissionMethodOptions) =>
|
|
15
|
+
getMediaLibraryPermissionsAsync(options?.writeOnly),
|
|
16
|
+
requestMethod: (options?: IMediaLibraryPermissionMethodOptions) =>
|
|
17
|
+
requestMediaLibraryPermissionsAsync(options?.writeOnly),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const splitMediaLibraryPermissionOptions =
|
|
21
|
+
splitWriteOnlyPermissionOptions;
|
|
22
|
+
|
|
23
|
+
export type { IMediaLibraryPermissionResponse };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
import type {
|
|
3
|
+
ICameraPermissionResponse,
|
|
4
|
+
IImagePickerErrorResult,
|
|
5
|
+
IImagePickerOptions,
|
|
6
|
+
IImagePickerResult,
|
|
7
|
+
IMediaLibraryPermissionResponse,
|
|
8
|
+
} from './types';
|
|
9
|
+
|
|
10
|
+
const EXPO_IMAGE_PICKER_MODULE_NAME = 'ExponentImagePicker';
|
|
11
|
+
|
|
12
|
+
export type INativeImagePickerModule = {
|
|
13
|
+
getCameraPermissionsAsync(): Promise<ICameraPermissionResponse>;
|
|
14
|
+
getMediaLibraryPermissionsAsync(
|
|
15
|
+
writeOnly: boolean,
|
|
16
|
+
): Promise<IMediaLibraryPermissionResponse>;
|
|
17
|
+
requestCameraPermissionsAsync(): Promise<ICameraPermissionResponse>;
|
|
18
|
+
requestMediaLibraryPermissionsAsync(
|
|
19
|
+
writeOnly: boolean,
|
|
20
|
+
): Promise<IMediaLibraryPermissionResponse>;
|
|
21
|
+
/** Android only — absent on iOS's native module. */
|
|
22
|
+
getPendingResultAsync?(): Promise<
|
|
23
|
+
IImagePickerResult | IImagePickerErrorResult
|
|
24
|
+
>;
|
|
25
|
+
/** Absent on web's native module. */
|
|
26
|
+
launchCameraAsync?(options: IImagePickerOptions): Promise<IImagePickerResult>;
|
|
27
|
+
launchImageLibraryAsync(
|
|
28
|
+
options: IImagePickerOptions,
|
|
29
|
+
): Promise<IImagePickerResult>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const expoImagePicker = requireNativeModule<INativeImagePickerModule>(
|
|
33
|
+
EXPO_IMAGE_PICKER_MODULE_NAME,
|
|
34
|
+
);
|