@symbiote-native/clipboard 0.0.1 → 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/README.md +180 -26
- package/build/angular/index.d.ts +2 -0
- package/build/angular/index.js +7 -0
- package/build/angular/services/clipboard.service/index.d.ts +6 -0
- package/build/angular/services/clipboard.service/index.js +77 -0
- package/build/core/clipboard.d.ts +86 -0
- package/build/core/clipboard.js +137 -0
- package/build/core/index.d.ts +3 -0
- package/build/core/index.js +2 -0
- package/build/core/native-module.d.ts +17 -0
- package/build/core/native-module.js +7 -0
- package/build/core/types.d.ts +67 -0
- package/build/core/types.js +28 -0
- package/build/react/hooks/use-clipboard/index.d.ts +2 -0
- package/build/react/hooks/use-clipboard/index.js +14 -0
- package/build/react/index.d.ts +2 -0
- package/build/react/index.js +8 -0
- package/build/vue/composables/use-clipboard/index.d.ts +3 -0
- package/build/vue/composables/use-clipboard/index.js +20 -0
- package/build/vue/index.d.ts +2 -0
- package/build/vue/index.js +8 -0
- package/build-ngc/angular/index.d.ts +2 -0
- package/build-ngc/angular/index.js +8 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/angular/services/clipboard.service/index.d.ts +9 -0
- package/build-ngc/angular/services/clipboard.service/index.js +36 -0
- package/build-ngc/angular/services/clipboard.service/index.js.map +1 -0
- package/build-ngc/core/clipboard.d.ts +86 -0
- package/build-ngc/core/clipboard.js +138 -0
- package/build-ngc/core/clipboard.js.map +1 -0
- package/build-ngc/core/index.d.ts +3 -0
- package/build-ngc/core/index.js +3 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/native-module.d.ts +17 -0
- package/build-ngc/core/native-module.js +8 -0
- package/build-ngc/core/native-module.js.map +1 -0
- package/build-ngc/core/types.d.ts +67 -0
- package/build-ngc/core/types.js +29 -0
- package/build-ngc/core/types.js.map +1 -0
- package/native-link.json +12 -0
- package/package.json +92 -1
- package/src/angular/index.ts +8 -0
- package/src/angular/services/clipboard.service/index.ts +35 -0
- package/src/core/clipboard.ts +163 -0
- package/src/core/index.ts +23 -0
- package/src/core/native-module.ts +42 -0
- package/src/core/types.ts +81 -0
- package/src/react/hooks/use-clipboard/index.ts +17 -0
- package/src/react/index.ts +9 -0
- package/src/vue/composables/use-clipboard/index.ts +25 -0
- package/src/vue/index.ts +9 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Ported from expo-clipboard's own Clipboard.types.ts. ContentType and StringFormat are enums —
|
|
2
|
+
// kept unprefixed, matching this repo's convention for enums (see AuthenticationType /
|
|
3
|
+
// SecurityLevel in @symbiote-native/local-auth); the plain option/result shapes get this repo's
|
|
4
|
+
// `I`-prefix convention for exported types. `ClipboardPasteButton`'s own types
|
|
5
|
+
// (PasteEventPayload, TextPasteEvent, ImagePasteEvent, AcceptedContentType, CornerStyleType,
|
|
6
|
+
// DisplayModeType) are intentionally not ported — that native paste-button view is out of scope
|
|
7
|
+
// for this pass (see the package README).
|
|
8
|
+
/**
|
|
9
|
+
* Type used to define what type of data is stored in the clipboard.
|
|
10
|
+
*/
|
|
11
|
+
export var ContentType;
|
|
12
|
+
(function (ContentType) {
|
|
13
|
+
ContentType["PLAIN_TEXT"] = "plain-text";
|
|
14
|
+
ContentType["HTML"] = "html";
|
|
15
|
+
ContentType["IMAGE"] = "image";
|
|
16
|
+
/**
|
|
17
|
+
* @platform iOS
|
|
18
|
+
*/
|
|
19
|
+
ContentType["URL"] = "url";
|
|
20
|
+
})(ContentType || (ContentType = {}));
|
|
21
|
+
/**
|
|
22
|
+
* Type used to determine string format stored in the clipboard.
|
|
23
|
+
*/
|
|
24
|
+
export var StringFormat;
|
|
25
|
+
(function (StringFormat) {
|
|
26
|
+
StringFormat["PLAIN_TEXT"] = "plainText";
|
|
27
|
+
StringFormat["HTML"] = "html";
|
|
28
|
+
})(StringFormat || (StringFormat = {}));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// React lifecycle wiring over the framework-agnostic addClipboardListener subscription (core/) —
|
|
2
|
+
// mirrors the lifecycle-bucket naming convention of adapters/react/src/hooks and the shape of
|
|
3
|
+
// @symbiote-native/sensors' useAccelerometer, adjusted for clipboard's single always-on
|
|
4
|
+
// subscription (there is no per-call config like updateIntervalMs to resubscribe on).
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
6
|
+
import { addClipboardListener } from '../../../core/index.js';
|
|
7
|
+
export function useClipboard() {
|
|
8
|
+
const [event, setEvent] = useState(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const subscription = addClipboardListener(setEvent);
|
|
11
|
+
return () => subscription.remove();
|
|
12
|
+
}, []);
|
|
13
|
+
return event;
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// @symbiote-native/clipboard/react: the React entry over the framework-agnostic core. Unlike
|
|
2
|
+
// @symbiote-native/local-auth (all stateless functions, plain re-export), clipboard has one
|
|
3
|
+
// listener-based piece — useClipboard wraps addClipboardListener with React's own lifecycle
|
|
4
|
+
// (hooks/use-clipboard), mirroring the lifecycle-bucket naming convention of
|
|
5
|
+
// adapters/react/src/hooks (never `composables`, that's Vue's term) and the shape of
|
|
6
|
+
// @symbiote-native/sensors' useAccelerometer.
|
|
7
|
+
export { useClipboard } from './hooks/use-clipboard/index.js';
|
|
8
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Vue lifecycle wiring over the framework-agnostic addClipboardListener subscription (core/) —
|
|
2
|
+
// mirrors the lifecycle-bucket naming convention of adapters/vue/src/composables and the
|
|
3
|
+
// onMounted/onUnmounted shape of @symbiote-native/sensors' useAccelerometer composable, adjusted
|
|
4
|
+
// for clipboard's single always-on subscription (no per-call config to resubscribe on).
|
|
5
|
+
import { onMounted, onUnmounted, ref } from '@vue/runtime-core';
|
|
6
|
+
import { addClipboardListener } from '../../../core/index.js';
|
|
7
|
+
export function useClipboard() {
|
|
8
|
+
// A plain ref: the value is a POJO clipboard event, not an engine node, so no shallowRef needed.
|
|
9
|
+
const event = ref(null);
|
|
10
|
+
let subscription;
|
|
11
|
+
onMounted(() => {
|
|
12
|
+
subscription = addClipboardListener(next => {
|
|
13
|
+
event.value = next;
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
onUnmounted(() => {
|
|
17
|
+
subscription?.remove();
|
|
18
|
+
});
|
|
19
|
+
return event;
|
|
20
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// @symbiote-native/clipboard/vue: the Vue entry over the framework-agnostic core. Unlike
|
|
2
|
+
// @symbiote-native/local-auth (all stateless functions, plain re-export), clipboard has one
|
|
3
|
+
// listener-based piece — useClipboard wires addClipboardListener's lifecycle onto Vue's own
|
|
4
|
+
// onMounted/onUnmounted (composables/use-clipboard), mirroring the lifecycle-bucket naming
|
|
5
|
+
// convention of adapters/vue/src/composables (never `hooks/`, that's React's term) and the
|
|
6
|
+
// shape of @symbiote-native/sensors' useAccelerometer composable.
|
|
7
|
+
export { useClipboard } from './composables/use-clipboard/index.js';
|
|
8
|
+
export * from '../core/index.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// @symbiote-native/clipboard/angular: the Angular entry over the framework-agnostic core.
|
|
2
|
+
// Unlike @symbiote-native/local-auth (all stateless functions, plain re-export), clipboard has
|
|
3
|
+
// one listener-based piece — ClipboardService.connect() is the Angular-only lifecycle half; the
|
|
4
|
+
// addClipboardListener subscription plumbing all lives in core, shared with React/Vue. Mirrors
|
|
5
|
+
// @symbiote-native/sensors' AccelerometerService.
|
|
6
|
+
export { ClipboardService } from './services/clipboard.service';
|
|
7
|
+
export * from '../core';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/angular/index.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,+FAA+F;AAC/F,gGAAgG;AAChG,+FAA+F;AAC/F,kDAAkD;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Signal } from '@angular/core';
|
|
2
|
+
import { type IClipboardEvent } from '../../../core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export declare class ClipboardService {
|
|
5
|
+
private readonly injector;
|
|
6
|
+
connect(): Signal<IClipboardEvent | null>;
|
|
7
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ClipboardService, never>;
|
|
8
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<ClipboardService>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { effect, inject, Injectable, Injector, signal } from '@angular/core';
|
|
2
|
+
import { addClipboardListener } from '../../../core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
// Angular twin of React's `useClipboard` hook and Vue's `useClipboard` composable. Angular has
|
|
5
|
+
// no per-instance hook — state and lifecycle live in DI instead, so `connect()` stands in for
|
|
6
|
+
// the hook's role: call it ONCE (typically from a component's field initializer, inside an
|
|
7
|
+
// injection context).
|
|
8
|
+
//
|
|
9
|
+
// readonly clipboardEvent = inject(ClipboardService).connect();
|
|
10
|
+
// // template: {{ clipboardEvent()?.contentTypes }}
|
|
11
|
+
//
|
|
12
|
+
// Mirrors AccelerometerService.connect() from @symbiote-native/sensors: the subscription doesn't
|
|
13
|
+
// depend on anything the caller's own signals could change between renders, so a single
|
|
14
|
+
// effect() that subscribes once and cleans up once is enough.
|
|
15
|
+
export class ClipboardService {
|
|
16
|
+
// Captured in the constructor (itself always run inside an injection context by Angular's own
|
|
17
|
+
// DI) so `connect()` can create an `effect()` even when called from plain field-initializer
|
|
18
|
+
// code that is not, on its own, an active injection context — mirrors AccelerometerService.
|
|
19
|
+
injector = inject(Injector);
|
|
20
|
+
connect() {
|
|
21
|
+
const event = signal(null, /* @ts-ignore */
|
|
22
|
+
...(ngDevMode ? [{ debugName: "event" }] : /* istanbul ignore next */ []));
|
|
23
|
+
effect(onCleanup => {
|
|
24
|
+
const subscription = addClipboardListener(next => event.set(next));
|
|
25
|
+
onCleanup(() => subscription.remove());
|
|
26
|
+
}, { injector: this.injector });
|
|
27
|
+
return event.asReadonly();
|
|
28
|
+
}
|
|
29
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ClipboardService, providedIn: 'root' });
|
|
31
|
+
}
|
|
32
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ClipboardService, decorators: [{
|
|
33
|
+
type: Injectable,
|
|
34
|
+
args: [{ providedIn: 'root' }]
|
|
35
|
+
}] });
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/angular/services/clipboard.service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAe,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,oBAAoB,EAAwB,MAAM,eAAe,CAAC;;AAE3E,+FAA+F;AAC/F,8FAA8F;AAC9F,2FAA2F;AAC3F,sBAAsB;AACtB,EAAE;AACF,kEAAkE;AAClE,sDAAsD;AACtD,EAAE;AACF,iGAAiG;AACjG,wFAAwF;AACxF,8DAA8D;AAE9D,MAAM,OAAO,gBAAgB;IAC3B,8FAA8F;IAC9F,4FAA4F;IAC5F,4FAA4F;IAC3E,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,OAAO;QACL,MAAM,KAAK,GAAG,MAAM,CAAyB,IAAI;kFAAC,CAAC;QAEnD,MAAM,CACJ,SAAS,CAAC,EAAE;YACV,MAAM,YAAY,GAAG,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YACnE,SAAS,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC,EACD,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC5B,CAAC;QAEF,OAAO,KAAK,CAAC,UAAU,EAAE,CAAC;IAC5B,CAAC;uGAlBU,gBAAgB;2GAAhB,gBAAgB,cADH,MAAM;;2FACnB,gBAAgB;kBAD5B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { EventSubscription } from 'expo-modules-core';
|
|
2
|
+
import type { IClipboardEvent, IClipboardImage, IGetImageOptions, IGetStringOptions, ISetStringOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Gets the content of the user's clipboard.
|
|
5
|
+
*
|
|
6
|
+
* Note: On iOS 16+, if the user denies paste permission, this method returns an empty string.
|
|
7
|
+
* Due to iOS platform limitations, there is no way to distinguish between an empty clipboard
|
|
8
|
+
* and denied permission.
|
|
9
|
+
*
|
|
10
|
+
* @param options Options for the clipboard content to be retrieved.
|
|
11
|
+
* @returns A promise that resolves to the content of the clipboard, or an empty string if the
|
|
12
|
+
* clipboard is empty or permission was denied.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getStringAsync(options?: IGetStringOptions): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Sets the content of the user's clipboard.
|
|
17
|
+
*
|
|
18
|
+
* @param text The string to save to the clipboard.
|
|
19
|
+
* @param options Options for the clipboard content to be set.
|
|
20
|
+
* @returns A promise that resolves to `true` once the string has been saved to the clipboard.
|
|
21
|
+
*/
|
|
22
|
+
export declare function setStringAsync(text: string, options?: ISetStringOptions): Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns whether the clipboard has text content. Returns `true` for both plain text and rich
|
|
25
|
+
* text (e.g. HTML).
|
|
26
|
+
*/
|
|
27
|
+
export declare function hasStringAsync(): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the URL from the user's clipboard.
|
|
30
|
+
*
|
|
31
|
+
* Note: On iOS 16+, if the user denies paste permission, this method returns `null`. Due to iOS
|
|
32
|
+
* platform limitations, there is no way to distinguish between no URL in clipboard and denied
|
|
33
|
+
* permission.
|
|
34
|
+
* @platform ios
|
|
35
|
+
*/
|
|
36
|
+
export declare function getUrlAsync(): Promise<string | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Sets a URL in the user's clipboard. Behaves the same as `setStringAsync`, except that it sets
|
|
39
|
+
* the clipboard content type to be a URL, letting your app or other apps know that the clipboard
|
|
40
|
+
* contains a URL and behave accordingly.
|
|
41
|
+
* @platform ios
|
|
42
|
+
*/
|
|
43
|
+
export declare function setUrlAsync(url: string): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Returns whether the clipboard has URL content.
|
|
46
|
+
* @platform ios
|
|
47
|
+
*/
|
|
48
|
+
export declare function hasUrlAsync(): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Gets the image from the user's clipboard and returns it in the specified format.
|
|
51
|
+
*
|
|
52
|
+
* Note: On iOS 16+, if the user denies paste permission, this method returns `null`. Due to iOS
|
|
53
|
+
* platform limitations, there is no way to distinguish between no image in clipboard and denied
|
|
54
|
+
* permission.
|
|
55
|
+
*
|
|
56
|
+
* @param options Specifies the desired format of the image.
|
|
57
|
+
* @returns If there was an image in the clipboard, resolves to an `IClipboardImage` object
|
|
58
|
+
* containing the base64 string and metadata of the image. Otherwise resolves to `null` (this
|
|
59
|
+
* includes cases where permission was denied).
|
|
60
|
+
*/
|
|
61
|
+
export declare function getImageAsync(options: IGetImageOptions): Promise<IClipboardImage | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Sets an image in the user's clipboard.
|
|
64
|
+
*
|
|
65
|
+
* @param base64Image Image encoded as a base64 string, without MIME type.
|
|
66
|
+
*/
|
|
67
|
+
export declare function setImageAsync(base64Image: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Returns whether the clipboard has image content.
|
|
70
|
+
*/
|
|
71
|
+
export declare function hasImageAsync(): Promise<boolean>;
|
|
72
|
+
/**
|
|
73
|
+
* Adds a listener that fires whenever the content of the user's clipboard changes. Kept here at
|
|
74
|
+
* the core level, framework-agnostic, exactly like `Accelerometer.addListener` lives in
|
|
75
|
+
* `@symbiote-native/sensors`' core — each adapter's `useClipboard` hook/composable/service wraps
|
|
76
|
+
* this in its own mount/unmount lifecycle rather than reimplementing the subscription.
|
|
77
|
+
*
|
|
78
|
+
* @param listener Callback invoked with an `IClipboardEvent` describing the new clipboard
|
|
79
|
+
* content types whenever the clipboard changes.
|
|
80
|
+
*/
|
|
81
|
+
export declare function addClipboardListener(listener: (event: IClipboardEvent) => void): EventSubscription;
|
|
82
|
+
/**
|
|
83
|
+
* Removes the listener added by `addClipboardListener`.
|
|
84
|
+
* @deprecated use `subscription.remove()` instead.
|
|
85
|
+
*/
|
|
86
|
+
export declare function removeClipboardListener(subscription: EventSubscription): void;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { UnavailabilityError } from 'expo-modules-core';
|
|
2
|
+
import { CLIPBOARD_CHANGED_EVENT_NAME, expoClipboard } from './native-module';
|
|
3
|
+
// Matches the module name upstream's own Clipboard.ts passes to every UnavailabilityError.
|
|
4
|
+
const NATIVE_MODULE_NAME = 'Clipboard';
|
|
5
|
+
/**
|
|
6
|
+
* Gets the content of the user's clipboard.
|
|
7
|
+
*
|
|
8
|
+
* Note: On iOS 16+, if the user denies paste permission, this method returns an empty string.
|
|
9
|
+
* Due to iOS platform limitations, there is no way to distinguish between an empty clipboard
|
|
10
|
+
* and denied permission.
|
|
11
|
+
*
|
|
12
|
+
* @param options Options for the clipboard content to be retrieved.
|
|
13
|
+
* @returns A promise that resolves to the content of the clipboard, or an empty string if the
|
|
14
|
+
* clipboard is empty or permission was denied.
|
|
15
|
+
*/
|
|
16
|
+
export async function getStringAsync(options = {}) {
|
|
17
|
+
if (!expoClipboard.getStringAsync) {
|
|
18
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getStringAsync');
|
|
19
|
+
}
|
|
20
|
+
return expoClipboard.getStringAsync(options);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Sets the content of the user's clipboard.
|
|
24
|
+
*
|
|
25
|
+
* @param text The string to save to the clipboard.
|
|
26
|
+
* @param options Options for the clipboard content to be set.
|
|
27
|
+
* @returns A promise that resolves to `true` once the string has been saved to the clipboard.
|
|
28
|
+
*/
|
|
29
|
+
export async function setStringAsync(text, options = {}) {
|
|
30
|
+
if (!expoClipboard.setStringAsync) {
|
|
31
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'setStringAsync');
|
|
32
|
+
}
|
|
33
|
+
return expoClipboard.setStringAsync(text, options);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns whether the clipboard has text content. Returns `true` for both plain text and rich
|
|
37
|
+
* text (e.g. HTML).
|
|
38
|
+
*/
|
|
39
|
+
export function hasStringAsync() {
|
|
40
|
+
if (!expoClipboard.hasStringAsync) {
|
|
41
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'hasStringAsync');
|
|
42
|
+
}
|
|
43
|
+
return expoClipboard.hasStringAsync();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Gets the URL from the user's clipboard.
|
|
47
|
+
*
|
|
48
|
+
* Note: On iOS 16+, if the user denies paste permission, this method returns `null`. Due to iOS
|
|
49
|
+
* platform limitations, there is no way to distinguish between no URL in clipboard and denied
|
|
50
|
+
* permission.
|
|
51
|
+
* @platform ios
|
|
52
|
+
*/
|
|
53
|
+
export async function getUrlAsync() {
|
|
54
|
+
if (!expoClipboard.getUrlAsync) {
|
|
55
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getUrlAsync');
|
|
56
|
+
}
|
|
57
|
+
return expoClipboard.getUrlAsync();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Sets a URL in the user's clipboard. Behaves the same as `setStringAsync`, except that it sets
|
|
61
|
+
* the clipboard content type to be a URL, letting your app or other apps know that the clipboard
|
|
62
|
+
* contains a URL and behave accordingly.
|
|
63
|
+
* @platform ios
|
|
64
|
+
*/
|
|
65
|
+
export async function setUrlAsync(url) {
|
|
66
|
+
if (!expoClipboard.setUrlAsync) {
|
|
67
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'setUrlAsync');
|
|
68
|
+
}
|
|
69
|
+
return expoClipboard.setUrlAsync(url);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Returns whether the clipboard has URL content.
|
|
73
|
+
* @platform ios
|
|
74
|
+
*/
|
|
75
|
+
export async function hasUrlAsync() {
|
|
76
|
+
if (!expoClipboard.hasUrlAsync) {
|
|
77
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'hasUrlAsync');
|
|
78
|
+
}
|
|
79
|
+
return expoClipboard.hasUrlAsync();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Gets the image from the user's clipboard and returns it in the specified format.
|
|
83
|
+
*
|
|
84
|
+
* Note: On iOS 16+, if the user denies paste permission, this method returns `null`. Due to iOS
|
|
85
|
+
* platform limitations, there is no way to distinguish between no image in clipboard and denied
|
|
86
|
+
* permission.
|
|
87
|
+
*
|
|
88
|
+
* @param options Specifies the desired format of the image.
|
|
89
|
+
* @returns If there was an image in the clipboard, resolves to an `IClipboardImage` object
|
|
90
|
+
* containing the base64 string and metadata of the image. Otherwise resolves to `null` (this
|
|
91
|
+
* includes cases where permission was denied).
|
|
92
|
+
*/
|
|
93
|
+
export async function getImageAsync(options) {
|
|
94
|
+
if (!expoClipboard.getImageAsync) {
|
|
95
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'getImageAsync');
|
|
96
|
+
}
|
|
97
|
+
return expoClipboard.getImageAsync(options);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Sets an image in the user's clipboard.
|
|
101
|
+
*
|
|
102
|
+
* @param base64Image Image encoded as a base64 string, without MIME type.
|
|
103
|
+
*/
|
|
104
|
+
export async function setImageAsync(base64Image) {
|
|
105
|
+
if (!expoClipboard.setImageAsync) {
|
|
106
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'setImageAsync');
|
|
107
|
+
}
|
|
108
|
+
return expoClipboard.setImageAsync(base64Image);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Returns whether the clipboard has image content.
|
|
112
|
+
*/
|
|
113
|
+
export async function hasImageAsync() {
|
|
114
|
+
if (!expoClipboard.hasImageAsync) {
|
|
115
|
+
throw new UnavailabilityError(NATIVE_MODULE_NAME, 'hasImageAsync');
|
|
116
|
+
}
|
|
117
|
+
return expoClipboard.hasImageAsync();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Adds a listener that fires whenever the content of the user's clipboard changes. Kept here at
|
|
121
|
+
* the core level, framework-agnostic, exactly like `Accelerometer.addListener` lives in
|
|
122
|
+
* `@symbiote-native/sensors`' core — each adapter's `useClipboard` hook/composable/service wraps
|
|
123
|
+
* this in its own mount/unmount lifecycle rather than reimplementing the subscription.
|
|
124
|
+
*
|
|
125
|
+
* @param listener Callback invoked with an `IClipboardEvent` describing the new clipboard
|
|
126
|
+
* content types whenever the clipboard changes.
|
|
127
|
+
*/
|
|
128
|
+
export function addClipboardListener(listener) {
|
|
129
|
+
return expoClipboard.addListener(CLIPBOARD_CHANGED_EVENT_NAME, listener);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Removes the listener added by `addClipboardListener`.
|
|
133
|
+
* @deprecated use `subscription.remove()` instead.
|
|
134
|
+
*/
|
|
135
|
+
export function removeClipboardListener(subscription) {
|
|
136
|
+
subscription.remove();
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=clipboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/core/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGxD,OAAO,EAAE,4BAA4B,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAS9E,2FAA2F;AAC3F,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAEvC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAA6B,EAAE;IAClE,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;QAClC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,aAAa,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,UAA6B,EAAE;IAE/B,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;QAClC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,aAAa,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;QAClC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,aAAa,CAAC,cAAc,EAAE,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC;AACrC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAyB;IAC3D,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;QACjC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;QACjC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,aAAa,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;QACjC,MAAM,IAAI,mBAAmB,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,aAAa,CAAC,aAAa,EAAE,CAAC;AACvC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAA0C;IAE1C,OAAO,aAAa,CAAC,WAAW,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAC;AAC3E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,YAA+B;IACrE,YAAY,CAAC,MAAM,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { getStringAsync, setStringAsync, hasStringAsync, getUrlAsync, setUrlAsync, hasUrlAsync, getImageAsync, setImageAsync, hasImageAsync, addClipboardListener, removeClipboardListener, } from './clipboard';
|
|
2
|
+
export { ContentType, StringFormat, type IGetStringOptions, type ISetStringOptions, type IGetImageOptions, type IClipboardImage, type IClipboardEvent, } from './types';
|
|
3
|
+
export type { EventSubscription } from 'expo-modules-core';
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { getStringAsync, setStringAsync, hasStringAsync, getUrlAsync, setUrlAsync, hasUrlAsync, getImageAsync, setImageAsync, hasImageAsync, addClipboardListener, removeClipboardListener, } from './clipboard';
|
|
2
|
+
export { ContentType, StringFormat, } from './types';
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,WAAW,EACX,WAAW,EACX,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,YAAY,GAMb,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { EventSubscription } from 'expo-modules-core';
|
|
2
|
+
import type { IClipboardEvent, IClipboardImage, IGetImageOptions, IGetStringOptions, ISetStringOptions } from './types';
|
|
3
|
+
export declare const CLIPBOARD_CHANGED_EVENT_NAME = "onClipboardChanged";
|
|
4
|
+
export type INativeClipboardModule = {
|
|
5
|
+
addListener(eventName: typeof CLIPBOARD_CHANGED_EVENT_NAME, listener: (event: IClipboardEvent) => void): EventSubscription;
|
|
6
|
+
removeAllListeners(eventName: typeof CLIPBOARD_CHANGED_EVENT_NAME): void;
|
|
7
|
+
getStringAsync?(options?: IGetStringOptions): Promise<string>;
|
|
8
|
+
setStringAsync?(text: string, options?: ISetStringOptions): Promise<boolean>;
|
|
9
|
+
hasStringAsync?(): Promise<boolean>;
|
|
10
|
+
getUrlAsync?(): Promise<string | null>;
|
|
11
|
+
setUrlAsync?(url: string): Promise<void>;
|
|
12
|
+
hasUrlAsync?(): Promise<boolean>;
|
|
13
|
+
getImageAsync?(options: IGetImageOptions): Promise<IClipboardImage | null>;
|
|
14
|
+
setImageAsync?(base64Image: string): Promise<void>;
|
|
15
|
+
hasImageAsync?(): Promise<boolean>;
|
|
16
|
+
};
|
|
17
|
+
export declare const expoClipboard: INativeClipboardModule;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
const EXPO_CLIPBOARD_MODULE_NAME = 'ExpoClipboard';
|
|
3
|
+
// The event name upstream's own ExpoClipboard.ts pairs with the native module's event map —
|
|
4
|
+
// kept here, next to the module resolution, since core/clipboard.ts's addClipboardListener is
|
|
5
|
+
// the only caller.
|
|
6
|
+
export const CLIPBOARD_CHANGED_EVENT_NAME = 'onClipboardChanged';
|
|
7
|
+
export const expoClipboard = requireNativeModule(EXPO_CLIPBOARD_MODULE_NAME);
|
|
8
|
+
//# 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;AAUxD,MAAM,0BAA0B,GAAG,eAAe,CAAC;AAEnD,4FAA4F;AAC5F,8FAA8F;AAC9F,mBAAmB;AACnB,MAAM,CAAC,MAAM,4BAA4B,GAAG,oBAAoB,CAAC;AAwBjE,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,CAC9C,0BAA0B,CAC3B,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type used to define what type of data is stored in the clipboard.
|
|
3
|
+
*/
|
|
4
|
+
export declare enum ContentType {
|
|
5
|
+
PLAIN_TEXT = "plain-text",
|
|
6
|
+
HTML = "html",
|
|
7
|
+
IMAGE = "image",
|
|
8
|
+
/**
|
|
9
|
+
* @platform iOS
|
|
10
|
+
*/
|
|
11
|
+
URL = "url"
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Type used to determine string format stored in the clipboard.
|
|
15
|
+
*/
|
|
16
|
+
export declare enum StringFormat {
|
|
17
|
+
PLAIN_TEXT = "plainText",
|
|
18
|
+
HTML = "html"
|
|
19
|
+
}
|
|
20
|
+
export type IGetStringOptions = {
|
|
21
|
+
/**
|
|
22
|
+
* The target format of the clipboard string to be converted to, if possible.
|
|
23
|
+
* @default StringFormat.PLAIN_TEXT
|
|
24
|
+
*/
|
|
25
|
+
preferredFormat?: StringFormat;
|
|
26
|
+
};
|
|
27
|
+
export type ISetStringOptions = {
|
|
28
|
+
/**
|
|
29
|
+
* The input format of the provided string. Adjusting this option can help other applications
|
|
30
|
+
* interpret copied string properly.
|
|
31
|
+
* @default StringFormat.PLAIN_TEXT
|
|
32
|
+
*/
|
|
33
|
+
inputFormat?: StringFormat;
|
|
34
|
+
};
|
|
35
|
+
export type IGetImageOptions = {
|
|
36
|
+
/**
|
|
37
|
+
* The format of the clipboard image to be converted to.
|
|
38
|
+
*/
|
|
39
|
+
format: 'png' | 'jpeg';
|
|
40
|
+
/**
|
|
41
|
+
* Specify the quality of the returned image, between `0` and `1`. Defaults to `1` (highest
|
|
42
|
+
* quality). Applicable only when `format` is set to `jpeg`, ignored otherwise.
|
|
43
|
+
* @default 1
|
|
44
|
+
*/
|
|
45
|
+
jpegQuality?: number;
|
|
46
|
+
};
|
|
47
|
+
export type IClipboardImage = {
|
|
48
|
+
/**
|
|
49
|
+
* A Base64-encoded string of the image data, already prepended with a
|
|
50
|
+
* `data:image/png;base64,` or `data:image/jpeg;base64,` prefix. Its format depends on the
|
|
51
|
+
* `format` option passed to `getImageAsync`.
|
|
52
|
+
*/
|
|
53
|
+
data: string;
|
|
54
|
+
/**
|
|
55
|
+
* Dimensions (`width` and `height`) of the image pasted from clipboard.
|
|
56
|
+
*/
|
|
57
|
+
size: {
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
export type IClipboardEvent = {
|
|
63
|
+
/**
|
|
64
|
+
* An array of content types that are available on the clipboard.
|
|
65
|
+
*/
|
|
66
|
+
contentTypes: ContentType[];
|
|
67
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Ported from expo-clipboard's own Clipboard.types.ts. ContentType and StringFormat are enums —
|
|
2
|
+
// kept unprefixed, matching this repo's convention for enums (see AuthenticationType /
|
|
3
|
+
// SecurityLevel in @symbiote-native/local-auth); the plain option/result shapes get this repo's
|
|
4
|
+
// `I`-prefix convention for exported types. `ClipboardPasteButton`'s own types
|
|
5
|
+
// (PasteEventPayload, TextPasteEvent, ImagePasteEvent, AcceptedContentType, CornerStyleType,
|
|
6
|
+
// DisplayModeType) are intentionally not ported — that native paste-button view is out of scope
|
|
7
|
+
// for this pass (see the package README).
|
|
8
|
+
/**
|
|
9
|
+
* Type used to define what type of data is stored in the clipboard.
|
|
10
|
+
*/
|
|
11
|
+
export var ContentType;
|
|
12
|
+
(function (ContentType) {
|
|
13
|
+
ContentType["PLAIN_TEXT"] = "plain-text";
|
|
14
|
+
ContentType["HTML"] = "html";
|
|
15
|
+
ContentType["IMAGE"] = "image";
|
|
16
|
+
/**
|
|
17
|
+
* @platform iOS
|
|
18
|
+
*/
|
|
19
|
+
ContentType["URL"] = "url";
|
|
20
|
+
})(ContentType || (ContentType = {}));
|
|
21
|
+
/**
|
|
22
|
+
* Type used to determine string format stored in the clipboard.
|
|
23
|
+
*/
|
|
24
|
+
export var StringFormat;
|
|
25
|
+
(function (StringFormat) {
|
|
26
|
+
StringFormat["PLAIN_TEXT"] = "plainText";
|
|
27
|
+
StringFormat["HTML"] = "html";
|
|
28
|
+
})(StringFormat || (StringFormat = {}));
|
|
29
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,uFAAuF;AACvF,gGAAgG;AAChG,+EAA+E;AAC/E,6FAA6F;AAC7F,gGAAgG;AAChG,0CAA0C;AAE1C;;GAEG;AACH,MAAM,CAAN,IAAY,WAQX;AARD,WAAY,WAAW;IACrB,wCAAyB,CAAA;IACzB,4BAAa,CAAA;IACb,8BAAe,CAAA;IACf;;OAEG;IACH,0BAAW,CAAA;AACb,CAAC,EARW,WAAW,KAAX,WAAW,QAQtB;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,wCAAwB,CAAA;IACxB,6BAAa,CAAA;AACf,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB"}
|