@symbiote-native/sharing 0.0.1 → 0.2.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/build/angular/index.js +1 -1
- package/build/core/index.js +1 -1
- package/build/core/sharing.js +1 -1
- package/build/react/index.js +1 -1
- package/build/svelte/index.d.ts +1 -0
- package/build/svelte/index.js +7 -0
- package/build/vue/index.js +1 -1
- package/package.json +30 -13
- package/src/svelte/index.ts +7 -0
- package/src/core/sharing.test.ts +0 -105
package/build/angular/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @symbiote-native/sharing/angular: the Angular entry over the framework-agnostic core. Same
|
|
2
2
|
// reasoning as the React/Vue entries — no per-instance state or event stream to wrap in a
|
|
3
3
|
// service, so this is a plain re-export.
|
|
4
|
-
export * from '../core';
|
|
4
|
+
export * from '../core/index.js';
|
package/build/core/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { isAvailableAsync, shareAsync } from './sharing';
|
|
1
|
+
export { isAvailableAsync, shareAsync } from './sharing.js';
|
package/build/core/sharing.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UnavailabilityError } from 'expo-modules-core';
|
|
2
|
-
import { expoSharing } from './native-module';
|
|
2
|
+
import { expoSharing } from './native-module.js';
|
|
3
3
|
const NATIVE_MODULE_NAME = 'expo-sharing';
|
|
4
4
|
/**
|
|
5
5
|
* Whether the share sheet can be opened on this device. Resolves `true` on Android and iOS.
|
package/build/react/index.js
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
// hook could own or clean up — so this is a plain re-export, the same shape
|
|
4
4
|
// packages/secure-store's React entry has for the same reason. The one part of expo-sharing that
|
|
5
5
|
// WOULD need a hook (incoming share) is out of scope here; see the README.
|
|
6
|
-
export * from '../core';
|
|
6
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../core';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @symbiote-native/sharing/svelte: the Svelte entry over the framework-agnostic core.
|
|
2
|
+
// Both exports are stateless free functions — no per-instance state, no event stream, nothing a
|
|
3
|
+
// rune could own or clean up — so this is a plain re-export. The one part of expo-sharing that
|
|
4
|
+
// WOULD need lifecycle (incoming share) is out of scope here; see the README. Svelte's lifecycle
|
|
5
|
+
// bucket is `runes/` (adapters/svelte/src/runes — never React's `hooks` or Vue's
|
|
6
|
+
// `composables`), and this package has none to fill.
|
|
7
|
+
export * from '../core/index.js';
|
package/build/vue/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @symbiote-native/sharing/vue: the Vue entry over the framework-agnostic core. Same reasoning
|
|
2
2
|
// as the React entry — no per-instance state or event stream to wire onto Vue's reactivity, so
|
|
3
3
|
// this is a plain re-export.
|
|
4
|
-
export * from '../core';
|
|
4
|
+
export * from '../core/index.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/sharing",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "expo-sharing wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, and Angular adapters. Opens the platform share sheet for a local file.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"types": "./build/react/index.d.ts",
|
|
31
31
|
"default": "./build/react/index.js"
|
|
32
32
|
},
|
|
33
|
+
"./svelte": {
|
|
34
|
+
"types": "./build/svelte/index.d.ts",
|
|
35
|
+
"default": "./build/svelte/index.js"
|
|
36
|
+
},
|
|
33
37
|
"./angular": {
|
|
34
38
|
"types": "./build-ngc/angular/index.d.ts",
|
|
35
39
|
"react-native": "./build-ngc/angular/index.js",
|
|
@@ -40,7 +44,10 @@
|
|
|
40
44
|
"src",
|
|
41
45
|
"build",
|
|
42
46
|
"build-ngc",
|
|
43
|
-
"native-link.json"
|
|
47
|
+
"native-link.json",
|
|
48
|
+
"!src/**/*.test.*",
|
|
49
|
+
"!src/**/*.spec.*",
|
|
50
|
+
"!src/**/*.detox.*"
|
|
44
51
|
],
|
|
45
52
|
"publishConfig": {
|
|
46
53
|
"access": "public"
|
|
@@ -50,15 +57,17 @@
|
|
|
50
57
|
"expo-modules-core": "57.0.5"
|
|
51
58
|
},
|
|
52
59
|
"peerDependencies": {
|
|
60
|
+
"@symbiote-native/angular": ">=0.6.2",
|
|
53
61
|
"@symbiote-native/engine": ">=0.1.7",
|
|
62
|
+
"@symbiote-native/react": ">=0.2.8",
|
|
63
|
+
"@symbiote-native/svelte": ">=0.1.0",
|
|
64
|
+
"@symbiote-native/vue": ">=0.3.8",
|
|
54
65
|
"@angular/core": ">=20",
|
|
55
66
|
"@vue/runtime-core": "^3.5.13",
|
|
56
67
|
"react": ">=19.0.0",
|
|
57
68
|
"react-native": ">=0.86",
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"@symbiote-native/react": "0.2.8",
|
|
61
|
-
"@symbiote-native/vue": "0.3.8"
|
|
69
|
+
"svelte": ">=5.56.0",
|
|
70
|
+
"vue": ">=3.5.0"
|
|
62
71
|
},
|
|
63
72
|
"peerDependenciesMeta": {
|
|
64
73
|
"@symbiote-native/angular": {
|
|
@@ -67,6 +76,9 @@
|
|
|
67
76
|
"@symbiote-native/react": {
|
|
68
77
|
"optional": true
|
|
69
78
|
},
|
|
79
|
+
"@symbiote-native/svelte": {
|
|
80
|
+
"optional": true
|
|
81
|
+
},
|
|
70
82
|
"@symbiote-native/vue": {
|
|
71
83
|
"optional": true
|
|
72
84
|
},
|
|
@@ -79,24 +91,29 @@
|
|
|
79
91
|
"react": {
|
|
80
92
|
"optional": true
|
|
81
93
|
},
|
|
94
|
+
"svelte": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
82
97
|
"vue": {
|
|
83
98
|
"optional": true
|
|
84
99
|
}
|
|
85
100
|
},
|
|
86
101
|
"devDependencies": {
|
|
87
|
-
"@angular/compiler": "
|
|
88
|
-
"@angular/compiler-cli": "
|
|
89
|
-
"@angular/core": "
|
|
102
|
+
"@angular/compiler": "~22.0.8",
|
|
103
|
+
"@angular/compiler-cli": "~22.0.8",
|
|
104
|
+
"@angular/core": "~22.0.8",
|
|
90
105
|
"@types/node": "^26.0.0",
|
|
91
106
|
"@types/react": "^19.2.0",
|
|
92
107
|
"@vue/runtime-core": "^3.5.13",
|
|
93
108
|
"react": "19.2.3",
|
|
109
|
+
"svelte": "^5.56.0",
|
|
94
110
|
"typescript": "~6.0.0",
|
|
111
|
+
"@symbiote-native/angular": "0.7.0",
|
|
112
|
+
"@symbiote-native/engine": "0.2.0",
|
|
113
|
+
"@symbiote-native/react": "0.3.0",
|
|
114
|
+
"@symbiote-native/svelte": "0.2.0",
|
|
95
115
|
"@symbiote-native/test-utils": "0.1.6",
|
|
96
|
-
"@symbiote-native/
|
|
97
|
-
"@symbiote-native/engine": "0.1.7",
|
|
98
|
-
"@symbiote-native/vue": "0.3.8",
|
|
99
|
-
"@symbiote-native/angular": "0.6.1"
|
|
116
|
+
"@symbiote-native/vue": "0.4.0"
|
|
100
117
|
},
|
|
101
118
|
"scripts": {
|
|
102
119
|
"typecheck": "tsc --build",
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @symbiote-native/sharing/svelte: the Svelte entry over the framework-agnostic core.
|
|
2
|
+
// Both exports are stateless free functions — no per-instance state, no event stream, nothing a
|
|
3
|
+
// rune could own or clean up — so this is a plain re-export. The one part of expo-sharing that
|
|
4
|
+
// WOULD need lifecycle (incoming share) is out of scope here; see the README. Svelte's lifecycle
|
|
5
|
+
// bucket is `runes/` (adapters/svelte/src/runes — never React's `hooks` or Vue's
|
|
6
|
+
// `composables`), and this package has none to fill.
|
|
7
|
+
export * from '../core';
|
package/src/core/sharing.test.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
const FAKE_NATIVE_SHARING = {
|
|
4
|
-
shareAsync: vi.fn(async () => undefined),
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
// The real ExpoSharing native module only exists on device — resolving it via
|
|
8
|
-
// requireNativeModule() at import time would throw in this headless run, so the module-lookup
|
|
9
|
-
// file is faked in place of expo-modules-core's runtime resolution, the same pattern
|
|
10
|
-
// packages/secure-store/src/core/secure-store.test.ts uses.
|
|
11
|
-
vi.mock('./native-module', () => ({
|
|
12
|
-
expoSharing: FAKE_NATIVE_SHARING,
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
// expo-modules-core's real entry transitively imports 'react-native', whose Flow-typed source
|
|
16
|
-
// Vitest's Oxc transform can't parse — so only the members used as values are faked.
|
|
17
|
-
vi.mock('expo-modules-core', () => ({
|
|
18
|
-
UnavailabilityError: class UnavailabilityError extends Error {
|
|
19
|
-
constructor(moduleName: string, propertyName: string) {
|
|
20
|
-
super(`${propertyName} is not available on ${moduleName}`);
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
const { isAvailableAsync, shareAsync } = await import('./sharing');
|
|
26
|
-
|
|
27
|
-
const LOCAL_FILE_URL = 'file:///tmp/report.pdf';
|
|
28
|
-
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
vi.clearAllMocks();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
describe('isAvailableAsync', () => {
|
|
34
|
-
it('reports availability from the presence of the native share method', async () => {
|
|
35
|
-
await expect(isAvailableAsync()).resolves.toBe(true);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('reports unavailable when the native module cannot share', async () => {
|
|
39
|
-
const { shareAsync: native } = FAKE_NATIVE_SHARING;
|
|
40
|
-
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
41
|
-
FAKE_NATIVE_SHARING.shareAsync = undefined;
|
|
42
|
-
|
|
43
|
-
await expect(isAvailableAsync()).resolves.toBe(false);
|
|
44
|
-
|
|
45
|
-
FAKE_NATIVE_SHARING.shareAsync = native;
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('defers to the native check when the module implements one', async () => {
|
|
49
|
-
const nativeCheck = vi.fn(async () => false);
|
|
50
|
-
Object.assign(FAKE_NATIVE_SHARING, { isAvailableAsync: nativeCheck });
|
|
51
|
-
|
|
52
|
-
await expect(isAvailableAsync()).resolves.toBe(false);
|
|
53
|
-
expect(nativeCheck).toHaveBeenCalled();
|
|
54
|
-
|
|
55
|
-
Reflect.deleteProperty(FAKE_NATIVE_SHARING, 'isAvailableAsync');
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
describe('shareAsync', () => {
|
|
60
|
-
it('passes the url and options straight through', async () => {
|
|
61
|
-
await shareAsync(LOCAL_FILE_URL, { mimeType: 'application/pdf', dialogTitle: 'Send report' });
|
|
62
|
-
expect(FAKE_NATIVE_SHARING.shareAsync).toHaveBeenCalledWith(LOCAL_FILE_URL, {
|
|
63
|
-
mimeType: 'application/pdf',
|
|
64
|
-
dialogTitle: 'Send report',
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('defaults the options to an empty object', async () => {
|
|
69
|
-
await shareAsync(LOCAL_FILE_URL);
|
|
70
|
-
expect(FAKE_NATIVE_SHARING.shareAsync).toHaveBeenCalledWith(LOCAL_FILE_URL, {});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('forwards the iPad anchor rectangle unflattened', async () => {
|
|
74
|
-
const anchor = { x: 10, y: 20, width: 1, height: 1 };
|
|
75
|
-
await shareAsync(LOCAL_FILE_URL, { anchor });
|
|
76
|
-
expect(FAKE_NATIVE_SHARING.shareAsync).toHaveBeenCalledWith(LOCAL_FILE_URL, { anchor });
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('throws an UnavailabilityError-shaped error when the native method is absent', async () => {
|
|
80
|
-
const { shareAsync: native } = FAKE_NATIVE_SHARING;
|
|
81
|
-
// @ts-expect-error -- simulating a platform where the native module has no such method
|
|
82
|
-
FAKE_NATIVE_SHARING.shareAsync = undefined;
|
|
83
|
-
|
|
84
|
-
await expect(shareAsync(LOCAL_FILE_URL)).rejects.toThrow(
|
|
85
|
-
'shareAsync is not available on expo-sharing',
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
FAKE_NATIVE_SHARING.shareAsync = native;
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
// Validation happens before the native call so a bad url fails with a readable message here
|
|
93
|
-
// rather than as an argument-conversion failure on iOS or a generic share failure on Android.
|
|
94
|
-
describe('url validation', () => {
|
|
95
|
-
it('rejects an empty url', async () => {
|
|
96
|
-
await expect(shareAsync('')).rejects.toThrow(/Invalid url provided to Sharing/);
|
|
97
|
-
expect(FAKE_NATIVE_SHARING.shareAsync).not.toHaveBeenCalled();
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('rejects a non-string url before reaching the native module', async () => {
|
|
101
|
-
// @ts-expect-error -- the guard exists precisely for callers without type checking
|
|
102
|
-
await expect(shareAsync(undefined)).rejects.toThrow(/Invalid url provided to Sharing/);
|
|
103
|
-
expect(FAKE_NATIVE_SHARING.shareAsync).not.toHaveBeenCalled();
|
|
104
|
-
});
|
|
105
|
-
});
|