@symbiote-native/document-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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 A. Prokopenko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # @symbiote-native/document-picker
2
+
3
+ Let users attach a PDF, a spreadsheet or any other file from wherever it lives: local storage,
4
+ iCloud, Google Drive. One API for every [SymbioteNative](../../README.md) adapter (React, Vue,
5
+ Svelte, Solid and Angular).
6
+
7
+ It wraps [`expo-document-picker`](https://github.com/expo/expo/tree/main/packages/expo-document-picker),
8
+ which opens the system's own document UI, the same way [`@symbiote-native/print`](../print) wraps
9
+ its upstream: `expo-modules-core` is a direct dependency, never the `expo` meta-package, and the
10
+ upstream JS is hand-ported into `core/`. The mechanics live in the `symbiote-expo-native-module`
11
+ project skill.
12
+
13
+ ## Install
14
+
15
+ **New app:**
16
+
17
+ ```bash
18
+ npx @symbiote-native/cli new my-app --document-picker
19
+ ```
20
+
21
+ **Existing SymbioteNative app:**
22
+
23
+ ```bash
24
+ npx @symbiote-native/cli add --document-picker
25
+ ```
26
+
27
+ Either way: installs `@symbiote-native/document-picker` and wires the native autolinking
28
+ automatically - see [`@symbiote-native/cli`](../cli).
29
+
30
+ <details>
31
+ <summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
32
+
33
+ ```bash
34
+ npm install @symbiote-native/document-picker
35
+ ```
36
+
37
+ `expo-document-picker` and `expo-modules-core` come along as regular, pinned dependencies - never
38
+ install either yourself, and never add the `expo` meta-package to this project (it bundles its
39
+ own Metro/Babel pipeline that conflicts with this project's own).
40
+
41
+ ### Required one-time step: native autolinking wiring
42
+
43
+ Unlike a plain RN native module, `expo-document-picker`'s native code is discovered by
44
+ `expo-modules-autolinking` - this needs wiring into the native host app **once**, covering this
45
+ package and every other `expo-modules-core` package with zero further changes:
46
+
47
+ | Platform | Touches |
48
+ | -------- | ------------------------------------------------------------------------------------- |
49
+ | iOS | `ios/Podfile` - add `use_expo_modules!` |
50
+ | iOS | `AppDelegate.swift` - Expo's runtime-bootstrap hook |
51
+ | Android | `settings.gradle` / `app/build.gradle` - resolve and include the Expo Gradle projects |
52
+ | Android | `MainApplication.kt` - Expo's bootstrap hook, plus a native-module name map |
53
+
54
+ Full mechanics live in the `symbiote-expo-native-module` skill. The per-package half of that
55
+ table - the Gradle dependency and the module map entry - is generated by
56
+ [`@symbiote-native/expo-modules-link`](../expo-modules-link) from this package's
57
+ `native-link.json` on every install.
58
+
59
+ ### No runtime permission, no manifest edit
60
+
61
+ - **No runtime permission on either platform.** The system document picker is the OS's own UI;
62
+ it runs outside the app's own permission surface.
63
+ - **No manifest edit.** `expo-document-picker`'s own `AndroidManifest.xml` declares only a
64
+ `<queries>` block for Android 11+ package-visibility rules; it merges in automatically once the
65
+ Gradle project is included.
66
+ - **iCloud entitlements are opt-in and not generated.** Upstream's config plugin sets
67
+ `com.apple.developer.icloud-container-environment` and related iCloud/ubiquity entitlement
68
+ keys, but only when the app's Expo config sets `ios.usesIcloudStorage` - off by default, and
69
+ this project has no Expo config to read it from in the first place (same reasoning as
70
+ `expo-notifications`' `aps-environment` entitlement - see that package's own README). If your
71
+ app needs iCloud-backed document picking, add those entitlement keys to your own
72
+ `Info.plist`/`.entitlements` file by hand; there is nothing here to enable.
73
+
74
+ </details>
75
+
76
+ ## Shape
77
+
78
+ ```
79
+ src/core/ the whole API: getDocumentAsync. native-module.ts resolves
80
+ ExpoDocumentPicker through expo-modules-core's requireNativeModule.
81
+ src/angular/ @symbiote-native/document-picker/angular
82
+ ```
83
+
84
+ `./react`, `./vue`, `./svelte`, and `./solid` are `exports`-map aliases straight onto `src/core/` -
85
+ no physical per-framework file, same reason [`@symbiote-native/print`](../print) does the same:
86
+ the whole surface is one stateless free function, nothing to wrap in a hook, composable, or
87
+ service. `./angular` stays a physical file/subpath since Angular ships through a separate
88
+ `ngc`/AOT build (`build-ngc/`).
89
+
90
+ ## Use it
91
+
92
+ ```ts
93
+ import { getDocumentAsync } from '@symbiote-native/document-picker';
94
+
95
+ const result = await getDocumentAsync({ type: 'application/pdf', multiple: true });
96
+ if (!result.canceled) {
97
+ for (const asset of result.assets) {
98
+ console.log(asset.name, asset.uri, asset.size);
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## API
104
+
105
+ | Export | Signature | Notes |
106
+ | ------------------ | ------------------------------------------------------------------ | ------------------------------------------ |
107
+ | `getDocumentAsync` | `(options?: IDocumentPickerOptions) => Promise<IDocumentPickerResult>` | Default `type` is any MIME type. |
108
+
109
+ `IDocumentPickerOptions`: `type` (string or string array, wildcards allowed), `copyToCacheDirectory`
110
+ (default `true`), `multiple` (default `false`).
111
+ `IDocumentPickerResult`: `{ canceled: true; assets: null }` or
112
+ `{ canceled: false; assets: IDocumentPickerAsset[] }`.
113
+ `IDocumentPickerAsset`: `name`, `uri`, `lastModified`, plus optional `size` and `mimeType`.
114
+
115
+ ## Notes
116
+
117
+ - **Check `canceled` before reading `assets`.** The result is a union: `assets` is `null` when the
118
+ user backs out.
119
+ - **`size` and `mimeType` can be missing.** Not every provider reports them.
120
+ - **Web-only fields dropped.** Upstream's `base64`/`file`/`output` fields only exist on the web
121
+ platform; this package targets iOS/Android only, so they're not part of the port (matching
122
+ `expo-module.config.json`'s own `platforms: ["apple", "android"]`).
123
+
124
+ ## Common questions
125
+
126
+ - **`uri` is `content://` on Android and unreadable.** It happens with
127
+ `copyToCacheDirectory: false`; keep the default `true` so `uri` is a readable cache path.
128
+ - **`size` is missing.** Some Android providers do not report it; read the copied file instead.
129
+ - **Limit to PDFs or images.** Pass `type` (`'application/pdf'`, `'image/*'`, or an array).
130
+ - **Permission?** None needed. **Several files?** `multiple: true`.
131
+
132
+ Sources: [Expo docs: DocumentPicker](https://docs.expo.dev/versions/latest/sdk/document-picker/),
133
+ [expo/expo#11075](https://github.com/expo/expo/issues/11075).
134
+
135
+ ## Test it
136
+
137
+ ```bash
138
+ pnpm vitest run packages/document-picker
139
+ ```
140
+
141
+ The core tests fake the native module in place of `requireNativeModule`'s runtime resolution -
142
+ `ExpoDocumentPicker` only exists on a device, so a headless run would otherwise throw at import.
143
+ Upstream's only test suite (`plugin/src/__tests__/withDocumentPickerIOS-test.ts`) exercises the
144
+ config-plugin's `setICloudEntitlements` function - build-time code this project doesn't carry
145
+ over (native config here is static `native-link.json`, not a plugin we run), so it isn't ported.
146
+ The tests here cover the runtime API instead: option defaults, the string→array `type` coercion,
147
+ and result delegation.
@@ -0,0 +1 @@
1
+ export * from '../core';
@@ -0,0 +1,2 @@
1
+ // No per-instance state or event stream to wrap in an injectable service — plain re-export.
2
+ export * from '../core/index.js';
@@ -0,0 +1,3 @@
1
+ import type { IDocumentPickerOptions, IDocumentPickerResult } from './types';
2
+ /** Opens the system UI for picking one or more documents. */
3
+ export declare function getDocumentAsync(options?: IDocumentPickerOptions): Promise<IDocumentPickerResult>;
@@ -0,0 +1,10 @@
1
+ import { expoDocumentPicker } from './native-module.js';
2
+ /** Opens the system UI for picking one or more documents. */
3
+ export async function getDocumentAsync(options = {}) {
4
+ const { type = '*/*', copyToCacheDirectory = true, multiple = false, } = options;
5
+ return await expoDocumentPicker.getDocumentAsync({
6
+ type: typeof type === 'string' ? [type] : type,
7
+ copyToCacheDirectory,
8
+ multiple,
9
+ });
10
+ }
@@ -0,0 +1,2 @@
1
+ export { getDocumentAsync } from './document-picker';
2
+ export type { IDocumentPickerAsset, IDocumentPickerCanceledResult, IDocumentPickerOptions, IDocumentPickerResult, IDocumentPickerSuccessResult, } from './types';
@@ -0,0 +1 @@
1
+ export { getDocumentAsync } from './document-picker.js';
@@ -0,0 +1,5 @@
1
+ import type { IDocumentPickerOptions, IDocumentPickerResult } from './types';
2
+ export type INativeDocumentPickerModule = {
3
+ getDocumentAsync(options: IDocumentPickerOptions): Promise<IDocumentPickerResult>;
4
+ };
5
+ export declare const expoDocumentPicker: INativeDocumentPickerModule;
@@ -0,0 +1,3 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ const EXPO_DOCUMENT_PICKER_MODULE_NAME = 'ExpoDocumentPicker';
3
+ export const expoDocumentPicker = requireNativeModule(EXPO_DOCUMENT_PICKER_MODULE_NAME);
@@ -0,0 +1,24 @@
1
+ export type IDocumentPickerOptions = {
2
+ /** MIME type(s) to allow, wildcards included (`'image/*'`). Default: any type. */
3
+ type?: string | string[];
4
+ /** Copy the picked file into the app's cache dir. iOS + Android. Default `true`. */
5
+ copyToCacheDirectory?: boolean;
6
+ /** Allow multiple files. Default `false`. */
7
+ multiple?: boolean;
8
+ };
9
+ export type IDocumentPickerAsset = {
10
+ name: string;
11
+ size?: number;
12
+ uri: string;
13
+ mimeType?: string;
14
+ lastModified: number;
15
+ };
16
+ export type IDocumentPickerSuccessResult = {
17
+ canceled: false;
18
+ assets: IDocumentPickerAsset[];
19
+ };
20
+ export type IDocumentPickerCanceledResult = {
21
+ canceled: true;
22
+ assets: null;
23
+ };
24
+ export type IDocumentPickerResult = IDocumentPickerSuccessResult | IDocumentPickerCanceledResult;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from '../core';
@@ -0,0 +1,3 @@
1
+ // No per-instance state or event stream to wrap in an injectable service — plain re-export.
2
+ export * from '../core';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,cAAc,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { IDocumentPickerOptions, IDocumentPickerResult } from './types';
2
+ /** Opens the system UI for picking one or more documents. */
3
+ export declare function getDocumentAsync(options?: IDocumentPickerOptions): Promise<IDocumentPickerResult>;
@@ -0,0 +1,11 @@
1
+ import { expoDocumentPicker } from './native-module';
2
+ /** Opens the system UI for picking one or more documents. */
3
+ export async function getDocumentAsync(options = {}) {
4
+ const { type = '*/*', copyToCacheDirectory = true, multiple = false, } = options;
5
+ return await expoDocumentPicker.getDocumentAsync({
6
+ type: typeof type === 'string' ? [type] : type,
7
+ copyToCacheDirectory,
8
+ multiple,
9
+ });
10
+ }
11
+ //# sourceMappingURL=document-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-picker.js","sourceRoot":"","sources":["../../src/core/document-picker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGrD,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAAkC,EAAE;IAEpC,MAAM,EACJ,IAAI,GAAG,KAAK,EACZ,oBAAoB,GAAG,IAAI,EAC3B,QAAQ,GAAG,KAAK,GACjB,GAAG,OAAO,CAAC;IACZ,OAAO,MAAM,kBAAkB,CAAC,gBAAgB,CAAC;QAC/C,IAAI,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;QAC9C,oBAAoB;QACpB,QAAQ;KACT,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { getDocumentAsync } from './document-picker';
2
+ export type { IDocumentPickerAsset, IDocumentPickerCanceledResult, IDocumentPickerOptions, IDocumentPickerResult, IDocumentPickerSuccessResult, } from './types';
@@ -0,0 +1,2 @@
1
+ export { getDocumentAsync } from './document-picker';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { IDocumentPickerOptions, IDocumentPickerResult } from './types';
2
+ export type INativeDocumentPickerModule = {
3
+ getDocumentAsync(options: IDocumentPickerOptions): Promise<IDocumentPickerResult>;
4
+ };
5
+ export declare const expoDocumentPicker: INativeDocumentPickerModule;
@@ -0,0 +1,4 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ const EXPO_DOCUMENT_PICKER_MODULE_NAME = 'ExpoDocumentPicker';
3
+ export const expoDocumentPicker = requireNativeModule(EXPO_DOCUMENT_PICKER_MODULE_NAME);
4
+ //# sourceMappingURL=native-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-module.js","sourceRoot":"","sources":["../../src/core/native-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGxD,MAAM,gCAAgC,GAAG,oBAAoB,CAAC;AAQ9D,MAAM,CAAC,MAAM,kBAAkB,GAC7B,mBAAmB,CACjB,gCAAgC,CACjC,CAAC"}
@@ -0,0 +1,24 @@
1
+ export type IDocumentPickerOptions = {
2
+ /** MIME type(s) to allow, wildcards included (`'image/*'`). Default: any type. */
3
+ type?: string | string[];
4
+ /** Copy the picked file into the app's cache dir. iOS + Android. Default `true`. */
5
+ copyToCacheDirectory?: boolean;
6
+ /** Allow multiple files. Default `false`. */
7
+ multiple?: boolean;
8
+ };
9
+ export type IDocumentPickerAsset = {
10
+ name: string;
11
+ size?: number;
12
+ uri: string;
13
+ mimeType?: string;
14
+ lastModified: number;
15
+ };
16
+ export type IDocumentPickerSuccessResult = {
17
+ canceled: false;
18
+ assets: IDocumentPickerAsset[];
19
+ };
20
+ export type IDocumentPickerCanceledResult = {
21
+ canceled: true;
22
+ assets: null;
23
+ };
24
+ export type IDocumentPickerResult = IDocumentPickerSuccessResult | IDocumentPickerCanceledResult;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ {
2
+ "android": {
3
+ "gradleProjectName": "expo-document-picker",
4
+ "modules": [
5
+ {
6
+ "importPath": "expo.modules.documentpicker.DocumentPickerModule",
7
+ "className": "DocumentPickerModule",
8
+ "nativeName": "ExpoDocumentPicker"
9
+ }
10
+ ]
11
+ }
12
+ }
package/package.json ADDED
@@ -0,0 +1,150 @@
1
+ {
2
+ "name": "@symbiote-native/document-picker",
3
+ "version": "0.1.0",
4
+ "description": "expo-document-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 a document from any provider installed on the device.",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "react-native",
8
+ "symbiote-native",
9
+ "expo-document-picker",
10
+ "react",
11
+ "vue",
12
+ "svelte",
13
+ "solid",
14
+ "angular",
15
+ "document-picker",
16
+ "file-picker"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/OneEyed1366/symbiote-native.git",
21
+ "directory": "packages/document-picker"
22
+ },
23
+ "homepage": "https://github.com/OneEyed1366/symbiote-native/tree/master/packages/document-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/core/index.d.ts",
39
+ "default": "./build/core/index.js"
40
+ },
41
+ "./react": {
42
+ "types": "./build/core/index.d.ts",
43
+ "default": "./build/core/index.js"
44
+ },
45
+ "./svelte": {
46
+ "types": "./build/core/index.d.ts",
47
+ "default": "./build/core/index.js"
48
+ },
49
+ "./solid": {
50
+ "types": "./build/core/index.d.ts",
51
+ "default": "./build/core/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-document-picker": "57.0.2",
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/engine": "^1.4.0",
84
+ "@symbiote-native/angular": "^3.1.3",
85
+ "@symbiote-native/react": "^3.1.0",
86
+ "@symbiote-native/svelte": "^3.0.5",
87
+ "@symbiote-native/solid": "^3.0.5",
88
+ "@symbiote-native/vue": "^3.1.0"
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/solid": "3.0.5",
137
+ "@symbiote-native/engine": "1.4.0",
138
+ "@symbiote-native/test-utils": "0.4.5",
139
+ "@symbiote-native/angular": "3.1.3",
140
+ "@symbiote-native/react": "3.1.0",
141
+ "@symbiote-native/vue": "3.1.0",
142
+ "@symbiote-native/svelte": "3.0.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,2 @@
1
+ // No per-instance state or event stream to wrap in an injectable service — plain re-export.
2
+ export * from '../core';
@@ -0,0 +1,18 @@
1
+ import { expoDocumentPicker } from './native-module';
2
+ import type { IDocumentPickerOptions, IDocumentPickerResult } from './types';
3
+
4
+ /** Opens the system UI for picking one or more documents. */
5
+ export async function getDocumentAsync(
6
+ options: IDocumentPickerOptions = {},
7
+ ): Promise<IDocumentPickerResult> {
8
+ const {
9
+ type = '*/*',
10
+ copyToCacheDirectory = true,
11
+ multiple = false,
12
+ } = options;
13
+ return await expoDocumentPicker.getDocumentAsync({
14
+ type: typeof type === 'string' ? [type] : type,
15
+ copyToCacheDirectory,
16
+ multiple,
17
+ });
18
+ }
@@ -0,0 +1,8 @@
1
+ export { getDocumentAsync } from './document-picker';
2
+ export type {
3
+ IDocumentPickerAsset,
4
+ IDocumentPickerCanceledResult,
5
+ IDocumentPickerOptions,
6
+ IDocumentPickerResult,
7
+ IDocumentPickerSuccessResult,
8
+ } from './types';
@@ -0,0 +1,15 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ import type { IDocumentPickerOptions, IDocumentPickerResult } from './types';
3
+
4
+ const EXPO_DOCUMENT_PICKER_MODULE_NAME = 'ExpoDocumentPicker';
5
+
6
+ export type INativeDocumentPickerModule = {
7
+ getDocumentAsync(
8
+ options: IDocumentPickerOptions,
9
+ ): Promise<IDocumentPickerResult>;
10
+ };
11
+
12
+ export const expoDocumentPicker =
13
+ requireNativeModule<INativeDocumentPickerModule>(
14
+ EXPO_DOCUMENT_PICKER_MODULE_NAME,
15
+ );
@@ -0,0 +1,29 @@
1
+ export type IDocumentPickerOptions = {
2
+ /** MIME type(s) to allow, wildcards included (`'image/*'`). Default: any type. */
3
+ type?: string | string[];
4
+ /** Copy the picked file into the app's cache dir. iOS + Android. Default `true`. */
5
+ copyToCacheDirectory?: boolean;
6
+ /** Allow multiple files. Default `false`. */
7
+ multiple?: boolean;
8
+ };
9
+
10
+ export type IDocumentPickerAsset = {
11
+ name: string;
12
+ size?: number;
13
+ uri: string;
14
+ mimeType?: string;
15
+ lastModified: number;
16
+ };
17
+
18
+ export type IDocumentPickerSuccessResult = {
19
+ canceled: false;
20
+ assets: IDocumentPickerAsset[];
21
+ };
22
+
23
+ export type IDocumentPickerCanceledResult = {
24
+ canceled: true;
25
+ assets: null;
26
+ };
27
+
28
+ export type IDocumentPickerResult =
29
+ IDocumentPickerSuccessResult | IDocumentPickerCanceledResult;