native-fn 1.1.8 → 1.1.9
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 +2362 -20
- package/dist/native.cjs +1 -1
- package/dist/native.min.cjs +1 -1
- package/dist/native.min.mjs +1 -1
- package/dist/native.mjs +1 -1
- package/dist/native.umd.js +1 -1
- package/dist/native.umd.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,36 +1,2378 @@
|
|
|
1
1
|
# native-fn API Reference
|
|
2
|
-
|
|
3
2
|
<br>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
<a href="https://www.npmjs.com/package/native-fn"></a>
|
|
4
|
+
<a href="https://www.npmjs.com/package/native-fn"></a>
|
|
5
|
+
<a href="https://github.com/pjy0509/native-fn.git"></a>
|
|
6
|
+
<br/>
|
|
7
|
+
<a href="https://www.jsdelivr.com/package/npm/native-fn" target="_blank"><img alt="jsDelivr" src="http://www.google.com/s2/favicons?domain=www.jsdelivr.com/"></a>
|
|
8
|
+
<a href="https://www.npmjs.com/package/native-fn" target="_blank"><img alt="npm" src="http://www.google.com/s2/favicons?domain=www.npmjs.com/"></a>
|
|
9
|
+
<a href="https://github.com/pjy0509/native-fn.git" target="_blank"><img alt="repository" src="http://www.google.com/s2/favicons?domain=https://github.com/pjy0509/native-fn.git/"></a>
|
|
10
|
+
## Installation
|
|
7
11
|
|
|
8
|
-
|
|
12
|
+
**npm**
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
## Install
|
|
12
|
-
npm
|
|
13
|
-
```bash
|
|
14
|
+
```shell
|
|
14
15
|
npm i native-fn
|
|
15
16
|
```
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
**yarn**
|
|
19
|
+
|
|
20
|
+
```shell
|
|
18
21
|
yarn add native-fn
|
|
19
22
|
```
|
|
20
|
-
|
|
23
|
+
|
|
24
|
+
**cdnjs**
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<script src="https://unpkg.com/native-fn"></script>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**jsdelivr**
|
|
31
|
+
|
|
21
32
|
```html
|
|
22
|
-
<script src=
|
|
33
|
+
<script src="https://cdn.jsdelivr.net/npm/native-fn"></script>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Table of Contents
|
|
37
|
+
|
|
38
|
+
- **[appearance](#appearance)**
|
|
39
|
+
- [value](#appearance-value)
|
|
40
|
+
- [onChange](#appearance-onchange)
|
|
41
|
+
- **[badge](#badge)**
|
|
42
|
+
- [set](#badge-set)
|
|
43
|
+
- [clear](#badge-clear)
|
|
44
|
+
- **[battery](#battery)**
|
|
45
|
+
- [value](#battery-value)
|
|
46
|
+
- [onChange](#battery-onchange)
|
|
47
|
+
- **[clipboard](#clipboard)**
|
|
48
|
+
- [copy](#clipboard-copy)
|
|
49
|
+
- [paste](#clipboard-paste)
|
|
50
|
+
- **[dimension](#dimension)**
|
|
51
|
+
- [value](#dimension-value)
|
|
52
|
+
- [environment](#dimension-environment)
|
|
53
|
+
- [onChange](#dimension-onchange)
|
|
54
|
+
- **[fullscreen](#fullscreen)**
|
|
55
|
+
- [request](#fullscreen-request)
|
|
56
|
+
- [exit](#fullscreen-exit)
|
|
57
|
+
- [toggle](#fullscreen-toggle)
|
|
58
|
+
- [onChange](#fullscreen-onchange)
|
|
59
|
+
- [onError](#fullscreen-onerror)
|
|
60
|
+
- **[geolocation](#geolocation)**
|
|
61
|
+
- [value](#geolocation-value)
|
|
62
|
+
- [onChange](#geolocation-onchange)
|
|
63
|
+
- **[notification](#notification)**
|
|
64
|
+
- [send](#notification-send)
|
|
65
|
+
- **[open](#open)**
|
|
66
|
+
- [app](#open-app)
|
|
67
|
+
- [telephone](#open-telephone)
|
|
68
|
+
- [message](#open-message)
|
|
69
|
+
- [mail](#open-mail)
|
|
70
|
+
- [file](#open-file)
|
|
71
|
+
- [directory](#open-directory)
|
|
72
|
+
- [setting](#open-setting)
|
|
73
|
+
- [camera](#open-camera)
|
|
74
|
+
- [contact](#open-contact)
|
|
75
|
+
- [share](#open-share)
|
|
76
|
+
- [calendar](#open-calendar)
|
|
77
|
+
- **[permission](#permission)**
|
|
78
|
+
- [request](#permission-request)
|
|
79
|
+
- [check](#permission-check)
|
|
80
|
+
- **[pip](#pip)**
|
|
81
|
+
- [request](#pip-request)
|
|
82
|
+
- [exit](#pip-exit)
|
|
83
|
+
- [toggle](#pip-toggle)
|
|
84
|
+
- [onChange](#pip-onchange)
|
|
85
|
+
- [onError](#pip-onerror)
|
|
86
|
+
- **[platform](#platform)**
|
|
87
|
+
- [os](#platform-os)
|
|
88
|
+
- [browser](#platform-browser)
|
|
89
|
+
- [engine](#platform-engine)
|
|
90
|
+
- [device](#platform-device)
|
|
91
|
+
- [locale](#platform-locale)
|
|
92
|
+
- [gpu](#platform-gpu)
|
|
93
|
+
- [userAgent](#platform-useragent)
|
|
94
|
+
- [ready](#platform-ready)
|
|
95
|
+
- [isWebview](#platform-iswebview)
|
|
96
|
+
- [isNode](#platform-isnode)
|
|
97
|
+
- [isStandalone](#platform-isstandalone)
|
|
98
|
+
- **[theme](#theme)**
|
|
99
|
+
- [value](#theme-value)
|
|
100
|
+
- **[vibration](#vibration)**
|
|
101
|
+
- [run](#vibration-run)
|
|
102
|
+
- [stop](#vibration-stop)
|
|
103
|
+
|
|
104
|
+
## appearance
|
|
105
|
+
|
|
106
|
+
[`value`](#appearance-value) · [`onChange`](#appearance-onchange)
|
|
107
|
+
|
|
108
|
+
<h3 id="appearance-value"><code>appearance.value</code></h3>
|
|
109
|
+
|
|
110
|
+
**Signature**
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
get value(): Appearances
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Returns the current color scheme of the device.
|
|
117
|
+
|
|
118
|
+
**Example**
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
console.log(Native.appearance.value); // 'dark' | 'light' | 'unknown'
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Returns**
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
Appearances
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
enum Appearances {
|
|
133
|
+
Unknown = 'unknown',
|
|
134
|
+
Light = 'light',
|
|
135
|
+
Dark = 'dark',
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
<h3 id="appearance-onchange"><code>appearance.onChange</code></h3>
|
|
142
|
+
|
|
143
|
+
**Signature**
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
onChange(listener: (appearance: Appearances) => void, options?: AddEventListenerOptions): () => void
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Subscribes to device color scheme changes.
|
|
150
|
+
|
|
151
|
+
**Example**
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
const unsubscribe = Native.appearance.onChange((appearance) => {
|
|
155
|
+
console.log(appearance); // 'dark' | 'light'
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
unsubscribe();
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Returns**
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
() => void
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
// call to remove the listener
|
|
170
|
+
unsubscribe();
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## badge
|
|
176
|
+
|
|
177
|
+
[`set`](#badge-set) · [`clear`](#badge-clear)
|
|
178
|
+
|
|
179
|
+
<h3 id="badge-set"><code>badge.set</code></h3>
|
|
180
|
+
|
|
181
|
+
**Signature**
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
set(contents: number): Promise<void>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Sets the app badge count.
|
|
188
|
+
|
|
189
|
+
**Example**
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
await Native.badge.set(5);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Returns**
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
Promise<void>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
**Throws**
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
throw new NotSupportedError // navigator.setAppBadge unavailable
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
<h3 id="badge-clear"><code>badge.clear</code></h3>
|
|
211
|
+
|
|
212
|
+
**Signature**
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
clear(): Promise<void>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Clears the app badge.
|
|
219
|
+
|
|
220
|
+
**Example**
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
await Native.badge.clear();
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Returns**
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
Promise<void>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
**Throws**
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
throw new NotSupportedError // navigator.setAppBadge unavailable
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## battery
|
|
242
|
+
|
|
243
|
+
[`value`](#battery-value) · [`onChange`](#battery-onchange)
|
|
244
|
+
|
|
245
|
+
<h3 id="battery-value"><code>battery.value</code></h3>
|
|
246
|
+
|
|
247
|
+
**Signature**
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
get value(): Promise<BatteryManager>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Returns the current battery status.
|
|
254
|
+
|
|
255
|
+
**Example**
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
const battery = await Native.battery.value;
|
|
259
|
+
|
|
260
|
+
console.log(battery.level); // 0.0 – 1.0
|
|
261
|
+
console.log(battery.charging); // true | false
|
|
262
|
+
console.log(battery.chargingTime); // seconds until full
|
|
263
|
+
console.log(battery.dischargingTime); // seconds until empty
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Returns**
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
Promise<BatteryManager>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
interface BatteryManager {
|
|
275
|
+
readonly charging: boolean;
|
|
276
|
+
readonly chargingTime: number;
|
|
277
|
+
readonly dischargingTime: number;
|
|
278
|
+
readonly level: number;
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Throws**
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
throw new NotSupportedError // navigator.getBattery unavailable
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
<h3 id="battery-onchange"><code>battery.onChange</code></h3>
|
|
291
|
+
|
|
292
|
+
**Signature**
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
onChange(listener: (battery: BatteryManager) => void, options?: AddEventListenerOptions): () => void
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Subscribes to battery status changes.
|
|
299
|
+
|
|
300
|
+
**Example**
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
const unsubscribe = Native.battery.onChange((battery) => {
|
|
304
|
+
console.log(battery.level); // 0.0 – 1.0
|
|
305
|
+
console.log(battery.charging); // true | false
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
unsubscribe();
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**Returns**
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
() => void
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
// call to remove the listener
|
|
320
|
+
unsubscribe();
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## clipboard
|
|
326
|
+
|
|
327
|
+
[`copy`](#clipboard-copy) · [`paste`](#clipboard-paste)
|
|
328
|
+
|
|
329
|
+
<h3 id="clipboard-copy"><code>clipboard.copy</code></h3>
|
|
330
|
+
|
|
331
|
+
**Signature**
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
copy(item: any): Promise<boolean>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Copies a value to the clipboard. Accepts string, Element, Selection, object, or array.
|
|
338
|
+
|
|
339
|
+
**Flowchart**
|
|
340
|
+
|
|
341
|
+
```mermaid
|
|
342
|
+
flowchart TD
|
|
343
|
+
A([clipboard.copy called]) --> B[Convert item to text and html]
|
|
344
|
+
B --> C{Clipboard API available?}
|
|
345
|
+
C -->|yes| D[copyViaClipboardAPI]
|
|
346
|
+
C -->|no| E[copyViaLegacy]
|
|
347
|
+
D --> F{Success?}
|
|
348
|
+
F -->|yes| G([return true])
|
|
349
|
+
F -->|no| E
|
|
350
|
+
E --> H{ClipboardItem + write available?}
|
|
351
|
+
H -->|yes| I[navigator.clipboard.write with text/html + text/plain]
|
|
352
|
+
H -->|no| J{writeText available?}
|
|
353
|
+
J -->|yes| K[navigator.clipboard.writeText]
|
|
354
|
+
J -->|no| L[copyViaSelection via execCommand]
|
|
355
|
+
L --> M{execCommand success?}
|
|
356
|
+
M -->|yes| G
|
|
357
|
+
M -->|no| N[copyViaClipboardData IE fallback]
|
|
358
|
+
N --> O([return boolean])
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Example**
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
// String
|
|
365
|
+
await Native.clipboard.copy('Hello world');
|
|
366
|
+
|
|
367
|
+
// DOM element (copies outerHTML + textContent)
|
|
368
|
+
await Native.clipboard.copy(document.querySelector('.content'));
|
|
369
|
+
|
|
370
|
+
// Object → serialized as JSON
|
|
371
|
+
await Native.clipboard.copy({ key: 'value' });
|
|
372
|
+
|
|
373
|
+
// Current selection
|
|
374
|
+
await Native.clipboard.copy(window.getSelection());
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**Returns**
|
|
378
|
+
|
|
379
|
+
```ts
|
|
380
|
+
Promise<boolean>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
<h3 id="clipboard-paste"><code>clipboard.paste</code></h3>
|
|
387
|
+
|
|
388
|
+
**Signature**
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
paste(): Promise<string>
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Reads the current clipboard content as a string.
|
|
395
|
+
|
|
396
|
+
**Flowchart**
|
|
397
|
+
|
|
398
|
+
```mermaid
|
|
399
|
+
flowchart TD
|
|
400
|
+
A([clipboard.paste called]) --> B{Clipboard API available?}
|
|
401
|
+
B -->|yes| C[pasteViaClipboardAPI]
|
|
402
|
+
B -->|no| D[pasteViaLegacy]
|
|
403
|
+
C --> E{ClipboardItem + read available?}
|
|
404
|
+
E -->|yes| F[navigator.clipboard.read]
|
|
405
|
+
E -->|no| G[navigator.clipboard.readText]
|
|
406
|
+
F --> H{text/html type found?}
|
|
407
|
+
H -->|yes| I([return html string])
|
|
408
|
+
H -->|no| J{text/plain found?}
|
|
409
|
+
J -->|yes| K([return plain string])
|
|
410
|
+
J -->|no| D
|
|
411
|
+
G --> L{Success?}
|
|
412
|
+
L -->|yes| M([return string])
|
|
413
|
+
L -->|no| D
|
|
414
|
+
D --> N[pasteViaSelection via execCommand]
|
|
415
|
+
N --> O{Success?}
|
|
416
|
+
O -->|yes| P([return string])
|
|
417
|
+
O -->|no| Q[pasteViaClipboardData IE fallback]
|
|
418
|
+
Q --> R([return string])
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**Example**
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
const text = await Native.clipboard.paste();
|
|
425
|
+
|
|
426
|
+
console.log(text); // HTML string if available, plain text otherwise
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Returns**
|
|
430
|
+
|
|
431
|
+
```ts
|
|
432
|
+
Promise<string>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## dimension
|
|
439
|
+
|
|
440
|
+
[`value`](#dimension-value) · [`environment`](#dimension-environment) · [`onChange`](#dimension-onchange)
|
|
441
|
+
|
|
442
|
+
<h3 id="dimension-value"><code>dimension.value</code></h3>
|
|
443
|
+
|
|
444
|
+
**Signature**
|
|
445
|
+
|
|
446
|
+
```ts
|
|
447
|
+
get value(): Dimensions
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Returns current viewport dimensions, device pixel ratio, and orientation.
|
|
451
|
+
|
|
452
|
+
**Example**
|
|
453
|
+
|
|
454
|
+
```ts
|
|
455
|
+
const { innerWidth, innerHeight, outerWidth, outerHeight, scale, orientation } = Native.dimension.value;
|
|
456
|
+
|
|
457
|
+
console.log(innerWidth, innerHeight); // visible viewport size
|
|
458
|
+
console.log(scale); // device pixel ratio e.g. 2, 3
|
|
459
|
+
|
|
460
|
+
if (orientation === Orientation.Portrait) {
|
|
461
|
+
console.log('Portrait mode');
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**Returns**
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
Dimensions
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
```ts
|
|
473
|
+
interface Dimensions {
|
|
474
|
+
outerWidth: number;
|
|
475
|
+
outerHeight: number;
|
|
476
|
+
innerWidth: number;
|
|
477
|
+
innerHeight: number;
|
|
478
|
+
scale: number;
|
|
479
|
+
orientation: Orientation;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
enum Orientation {
|
|
483
|
+
Portrait = 'portrait',
|
|
484
|
+
Landscape = 'landscape',
|
|
485
|
+
Unknown = 'unknown',
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
<h3 id="dimension-environment"><code>dimension.environment</code></h3>
|
|
492
|
+
|
|
493
|
+
**Signature**
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
environment: Environment
|
|
23
497
|
```
|
|
24
498
|
|
|
25
|
-
|
|
499
|
+
Provides access to CSS environment variable values: safe-area-inset, keyboard-inset, titlebar-area, and viewport-segment.
|
|
26
500
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
501
|
+
**Example**
|
|
502
|
+
|
|
503
|
+
```ts
|
|
504
|
+
// Safe area insets (e.g. iPhone notch / Dynamic Island)
|
|
505
|
+
const inset = Native.dimension.environment.safeAreaInset.value;
|
|
506
|
+
console.log(inset.top, inset.bottom, inset.left, inset.right);
|
|
507
|
+
|
|
508
|
+
// Virtual keyboard height
|
|
509
|
+
const kb = Native.dimension.environment.keyboardInset.value;
|
|
510
|
+
console.log(kb.height); // 0 when keyboard is hidden
|
|
511
|
+
|
|
512
|
+
// Subscribe to safe area changes
|
|
513
|
+
const unsubscribe = Native.dimension.environment.safeAreaInset.onChange((inset) => {
|
|
514
|
+
document.body.style.paddingBottom = inset.bottom + 'px';
|
|
515
|
+
});
|
|
516
|
+
unsubscribe();
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
**Returns**
|
|
520
|
+
|
|
521
|
+
```ts
|
|
522
|
+
Environment
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
```ts
|
|
527
|
+
interface Environment {
|
|
528
|
+
safeAreaInset: EnvironmentPreset<'safe-area-inset'>;
|
|
529
|
+
safeAreaMaxInset: EnvironmentPreset<'safe-area-max-inset'>;
|
|
530
|
+
keyboardInset: EnvironmentPreset<'keyboard-inset'>;
|
|
531
|
+
titlebarArea: EnvironmentPreset<'titlebar-area'>;
|
|
532
|
+
viewportSegment: EnvironmentPreset<'viewport-segment'>;
|
|
30
533
|
}
|
|
31
534
|
|
|
32
|
-
interface
|
|
33
|
-
|
|
34
|
-
|
|
535
|
+
interface EnvironmentPreset<K> {
|
|
536
|
+
get value(): EnvironmentPresetValues<K>;
|
|
537
|
+
onChange(listener: (value: EnvironmentPresetValues<K>) => void, options?: AddEventListenerOptions): () => void;
|
|
35
538
|
}
|
|
36
539
|
```
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
<h3 id="dimension-onchange"><code>dimension.onChange</code></h3>
|
|
544
|
+
|
|
545
|
+
**Signature**
|
|
546
|
+
|
|
547
|
+
```ts
|
|
548
|
+
onChange(listener: (dimension: Dimensions) => void, options?: AddEventListenerOptions): () => void
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
Subscribes to viewport dimension and orientation changes.
|
|
552
|
+
|
|
553
|
+
**Example**
|
|
554
|
+
|
|
555
|
+
```ts
|
|
556
|
+
const unsubscribe = Native.dimension.onChange((dimension) => {
|
|
557
|
+
console.log(dimension.innerWidth, dimension.innerHeight);
|
|
558
|
+
console.log(dimension.orientation); // 'portrait' | 'landscape'
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
unsubscribe();
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
**Returns**
|
|
565
|
+
|
|
566
|
+
```ts
|
|
567
|
+
() => void
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
```ts
|
|
572
|
+
// call to remove the listener
|
|
573
|
+
unsubscribe();
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## fullscreen
|
|
579
|
+
|
|
580
|
+
[`request`](#fullscreen-request) · [`exit`](#fullscreen-exit) · [`toggle`](#fullscreen-toggle) · [`onChange`](#fullscreen-onchange) · [`onError`](#fullscreen-onerror)
|
|
581
|
+
|
|
582
|
+
<h3 id="fullscreen-request"><code>fullscreen.request</code></h3>
|
|
583
|
+
|
|
584
|
+
**Signature**
|
|
585
|
+
|
|
586
|
+
```ts
|
|
587
|
+
request(target?: Element, options?: FullscreenOptions): Promise<void>
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Requests fullscreen for an element. Concurrent calls are queued (FIFO).
|
|
591
|
+
|
|
592
|
+
**Flowchart**
|
|
593
|
+
|
|
594
|
+
```mermaid
|
|
595
|
+
flowchart TD
|
|
596
|
+
A([Fullscreen.request called]) --> B[Set lastIntendedOperation to request]
|
|
597
|
+
B --> C{activeOperation in progress?}
|
|
598
|
+
C -->|no| D[requestImmediately]
|
|
599
|
+
C -->|yes| E[Push to pendingQueue]
|
|
600
|
+
D --> F{api available?}
|
|
601
|
+
F -->|yes| G[Call element api.request]
|
|
602
|
+
F -->|no| H[fallbackToIOSVideo]
|
|
603
|
+
G --> I{Promise returned?}
|
|
604
|
+
I -->|yes| J{Resolved?}
|
|
605
|
+
J -->|yes| K([resolve])
|
|
606
|
+
J -->|no| H
|
|
607
|
+
I -->|no| K
|
|
608
|
+
H --> L{iOS + VIDEO + webkitSupportsFullscreen?}
|
|
609
|
+
L -->|yes| M[video.webkitEnterFullscreen]
|
|
610
|
+
M --> K
|
|
611
|
+
L -->|no| N([Throw NotSupportedError])
|
|
612
|
+
D --> O[drainPendingOperation on settle]
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
**Example**
|
|
616
|
+
|
|
617
|
+
```ts
|
|
618
|
+
// Default: documentElement on desktop, first video on iOS
|
|
619
|
+
await Native.fullscreen.request();
|
|
620
|
+
|
|
621
|
+
// Specific element
|
|
622
|
+
await Native.fullscreen.request(document.getElementById('player'));
|
|
623
|
+
|
|
624
|
+
// With options
|
|
625
|
+
await Native.fullscreen.request(element, { navigationUI: 'hide' });
|
|
626
|
+
|
|
627
|
+
// Concurrent calls — safely queued, not dropped
|
|
628
|
+
Native.fullscreen.request(document.querySelector('video#a'));
|
|
629
|
+
Native.fullscreen.request(document.querySelector('video#b'));
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
**Returns**
|
|
633
|
+
|
|
634
|
+
```ts
|
|
635
|
+
Promise<void>
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
**Throws**
|
|
640
|
+
|
|
641
|
+
```ts
|
|
642
|
+
throw new NotSupportedError // element does not support fullscreen
|
|
643
|
+
```
|
|
644
|
+
```ts
|
|
645
|
+
throw new NotSupportedError // iOS video lacks webkitEnterFullscreen
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
<h3 id="fullscreen-exit"><code>fullscreen.exit</code></h3>
|
|
651
|
+
|
|
652
|
+
**Signature**
|
|
653
|
+
|
|
654
|
+
```ts
|
|
655
|
+
exit(): Promise<void>
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
Exits fullscreen. Concurrent calls are queued (FIFO).
|
|
659
|
+
|
|
660
|
+
**Flowchart**
|
|
661
|
+
|
|
662
|
+
```mermaid
|
|
663
|
+
flowchart TD
|
|
664
|
+
A([Fullscreen.exit called]) --> B[Set lastIntendedOperation to exit]
|
|
665
|
+
B --> C{activeOperation in progress?}
|
|
666
|
+
C -->|no| D[exitImmediately]
|
|
667
|
+
C -->|yes| E[Push to pendingQueue]
|
|
668
|
+
D --> F{getElement null and lastIOSVideo null?}
|
|
669
|
+
F -->|yes| K([resolve immediately])
|
|
670
|
+
F -->|no| G{api available?}
|
|
671
|
+
G -->|yes| H[Call document api.exit]
|
|
672
|
+
G -->|no| I[fallbackToIOSVideo]
|
|
673
|
+
H --> J{Resolved?}
|
|
674
|
+
J -->|yes| K
|
|
675
|
+
J -->|no| I
|
|
676
|
+
I --> L{Displaying fullscreen video found?}
|
|
677
|
+
L -->|yes| M[webkitExitFullscreen]
|
|
678
|
+
M --> K
|
|
679
|
+
L -->|no| N([Throw NotSupportedError])
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
**Example**
|
|
683
|
+
|
|
684
|
+
```ts
|
|
685
|
+
await Native.fullscreen.exit();
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
**Returns**
|
|
689
|
+
|
|
690
|
+
```ts
|
|
691
|
+
Promise<void>
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
**Throws**
|
|
696
|
+
|
|
697
|
+
```ts
|
|
698
|
+
throw new NotSupportedError // failed to exit fullscreen
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
---
|
|
702
|
+
|
|
703
|
+
<h3 id="fullscreen-toggle"><code>fullscreen.toggle</code></h3>
|
|
704
|
+
|
|
705
|
+
**Signature**
|
|
706
|
+
|
|
707
|
+
```ts
|
|
708
|
+
toggle(target?: Element, options?: FullscreenOptions): Promise<void>
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
Toggles fullscreen on or off.
|
|
712
|
+
|
|
713
|
+
**Example**
|
|
714
|
+
|
|
715
|
+
```ts
|
|
716
|
+
// Toggle on button click
|
|
717
|
+
btn.addEventListener('click', () => Native.fullscreen.toggle());
|
|
718
|
+
|
|
719
|
+
// Toggle a specific element
|
|
720
|
+
btn.addEventListener('click', () => {
|
|
721
|
+
Native.fullscreen.toggle(document.getElementById('player'));
|
|
722
|
+
});
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
**Returns**
|
|
726
|
+
|
|
727
|
+
```ts
|
|
728
|
+
Promise<void>
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
**Throws**
|
|
733
|
+
|
|
734
|
+
```ts
|
|
735
|
+
throw new NotSupportedError // propagated from request() or exit()
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
<h3 id="fullscreen-onchange"><code>fullscreen.onChange</code></h3>
|
|
741
|
+
|
|
742
|
+
**Signature**
|
|
743
|
+
|
|
744
|
+
```ts
|
|
745
|
+
onChange(listener: (event: Event) => void, options?: AddEventListenerOptions): () => void
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
Subscribes to fullscreen state changes.
|
|
749
|
+
|
|
750
|
+
**Example**
|
|
751
|
+
|
|
752
|
+
```ts
|
|
753
|
+
const unsubscribe = Native.fullscreen.onChange(() => {
|
|
754
|
+
console.log('isFullscreen:', Native.fullscreen.isFullscreen);
|
|
755
|
+
console.log('element:', Native.fullscreen.element);
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
unsubscribe();
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
**Returns**
|
|
762
|
+
|
|
763
|
+
```ts
|
|
764
|
+
() => void
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
```ts
|
|
769
|
+
// call to remove the listener
|
|
770
|
+
unsubscribe();
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
---
|
|
774
|
+
|
|
775
|
+
<h3 id="fullscreen-onerror"><code>fullscreen.onError</code></h3>
|
|
776
|
+
|
|
777
|
+
**Signature**
|
|
778
|
+
|
|
779
|
+
```ts
|
|
780
|
+
onError(listener: (event: Event) => void, options?: AddEventListenerOptions): () => void
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
Subscribes to fullscreen errors.
|
|
784
|
+
|
|
785
|
+
**Example**
|
|
786
|
+
|
|
787
|
+
```ts
|
|
788
|
+
const unsubscribe = Native.fullscreen.onError((event) => {
|
|
789
|
+
console.error('Fullscreen error:', event);
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
unsubscribe();
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
**Returns**
|
|
796
|
+
|
|
797
|
+
```ts
|
|
798
|
+
() => void
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
```ts
|
|
803
|
+
// call to remove the listener
|
|
804
|
+
unsubscribe();
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
---
|
|
808
|
+
|
|
809
|
+
## geolocation
|
|
810
|
+
|
|
811
|
+
[`value`](#geolocation-value) · [`onChange`](#geolocation-onchange)
|
|
812
|
+
|
|
813
|
+
<h3 id="geolocation-value"><code>geolocation.value</code></h3>
|
|
814
|
+
|
|
815
|
+
**Signature**
|
|
816
|
+
|
|
817
|
+
```ts
|
|
818
|
+
get value(): Promise<GeolocationCoordinates>
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
Returns the current geographic coordinates. Falls back to IP-based location if the Geolocation API is unavailable or permission is denied.
|
|
822
|
+
|
|
823
|
+
**Flowchart**
|
|
824
|
+
|
|
825
|
+
```mermaid
|
|
826
|
+
flowchart TD
|
|
827
|
+
A([geolocation.value called]) --> B{navigator.geolocation supported?}
|
|
828
|
+
B -->|no| F[Fallback to ip-api.com]
|
|
829
|
+
B -->|yes| C[Permission.request geolocation]
|
|
830
|
+
C --> D{Permission granted?}
|
|
831
|
+
D -->|no| F
|
|
832
|
+
D -->|yes| E[getCurrentPosition]
|
|
833
|
+
E --> G{Success?}
|
|
834
|
+
G -->|yes| H([Resolve GeolocationCoordinates])
|
|
835
|
+
G -->|no| F
|
|
836
|
+
F --> I{ip-api.com responded?}
|
|
837
|
+
I -->|yes| J([Resolve approximate coordinates])
|
|
838
|
+
I -->|no| K([Throw original error])
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
**Example**
|
|
842
|
+
|
|
843
|
+
```ts
|
|
844
|
+
const coords = await Native.geolocation.value;
|
|
845
|
+
|
|
846
|
+
console.log(coords.latitude, coords.longitude);
|
|
847
|
+
console.log(coords.accuracy); // -1 when resolved via IP fallback
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
**Returns**
|
|
851
|
+
|
|
852
|
+
```ts
|
|
853
|
+
Promise<GeolocationCoordinates>
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
```ts
|
|
858
|
+
interface GeolocationCoordinates {
|
|
859
|
+
readonly latitude: number;
|
|
860
|
+
readonly longitude: number;
|
|
861
|
+
readonly accuracy: number; // -1 when resolved via IP fallback
|
|
862
|
+
readonly altitude: number | null;
|
|
863
|
+
readonly altitudeAccuracy: number | null;
|
|
864
|
+
readonly heading: number | null;
|
|
865
|
+
readonly speed: number | null;
|
|
866
|
+
}
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
**Throws**
|
|
870
|
+
|
|
871
|
+
```ts
|
|
872
|
+
throw new NotSupportedError // geolocation unavailable and IP fallback failed
|
|
873
|
+
```
|
|
874
|
+
```ts
|
|
875
|
+
throw new PermissionNotGrantedError // permission denied and IP fallback failed
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
---
|
|
879
|
+
|
|
880
|
+
<h3 id="geolocation-onchange"><code>geolocation.onChange</code></h3>
|
|
881
|
+
|
|
882
|
+
**Signature**
|
|
883
|
+
|
|
884
|
+
```ts
|
|
885
|
+
onChange(listener: (coordinates: GeolocationCoordinates) => void, options?: AddEventListenerOptions): () => void
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
Subscribes to geographic position changes.
|
|
889
|
+
|
|
890
|
+
**Example**
|
|
891
|
+
|
|
892
|
+
```ts
|
|
893
|
+
const unsubscribe = Native.geolocation.onChange((coords) => {
|
|
894
|
+
console.log(coords.latitude, coords.longitude);
|
|
895
|
+
console.log(coords.accuracy); // meters
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
unsubscribe();
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
**Returns**
|
|
902
|
+
|
|
903
|
+
```ts
|
|
904
|
+
() => void
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
```ts
|
|
909
|
+
// call to remove the listener
|
|
910
|
+
unsubscribe();
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
---
|
|
914
|
+
|
|
915
|
+
## notification
|
|
916
|
+
|
|
917
|
+
[`send`](#notification-send)
|
|
918
|
+
|
|
919
|
+
<h3 id="notification-send"><code>notification.send</code></h3>
|
|
920
|
+
|
|
921
|
+
**Signature**
|
|
922
|
+
|
|
923
|
+
```ts
|
|
924
|
+
send(options: NotificationOptions): Promise<Notification>
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
Sends a native notification after requesting permission.
|
|
928
|
+
|
|
929
|
+
**Example**
|
|
930
|
+
|
|
931
|
+
```ts
|
|
932
|
+
// Basic notification
|
|
933
|
+
const notification = await Native.notification.send({
|
|
934
|
+
title: 'Hello',
|
|
935
|
+
body: 'You have a new message.',
|
|
936
|
+
icon: '/icon.png',
|
|
937
|
+
});
|
|
938
|
+
|
|
939
|
+
// With event handlers
|
|
940
|
+
const notification = await Native.notification.send({
|
|
941
|
+
title: 'Download complete',
|
|
942
|
+
body: 'your-file.zip is ready.',
|
|
943
|
+
onClick: () => window.focus(),
|
|
944
|
+
onClose: () => console.log('dismissed'),
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
// Close the notification programmatically.
|
|
948
|
+
notification.close();
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
**Returns**
|
|
952
|
+
|
|
953
|
+
```ts
|
|
954
|
+
Promise<Notification>
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
```ts
|
|
959
|
+
interface NotificationOptions {
|
|
960
|
+
title: string;
|
|
961
|
+
badge?: string;
|
|
962
|
+
body?: string;
|
|
963
|
+
data?: any;
|
|
964
|
+
dir?: NotificationDirection;
|
|
965
|
+
icon?: string;
|
|
966
|
+
lang?: string;
|
|
967
|
+
requireInteraction?: boolean;
|
|
968
|
+
silent?: boolean | null;
|
|
969
|
+
tag?: string;
|
|
970
|
+
onClick?: (event: Event) => any;
|
|
971
|
+
onClose?: (event: Event) => any;
|
|
972
|
+
onError?: (event: Event) => any;
|
|
973
|
+
onShow?: (event: Event) => any;
|
|
974
|
+
}
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
**Throws**
|
|
978
|
+
|
|
979
|
+
```ts
|
|
980
|
+
throw new NotSupportedError // window.Notification unavailable
|
|
981
|
+
```
|
|
982
|
+
```ts
|
|
983
|
+
throw new PermissionNotGrantedError // notification permission denied
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
---
|
|
987
|
+
|
|
988
|
+
## open
|
|
989
|
+
|
|
990
|
+
[`app`](#open-app) · [`telephone`](#open-telephone) · [`message`](#open-message) · [`mail`](#open-mail) · [`file`](#open-file) · [`directory`](#open-directory) · [`setting`](#open-setting) · [`camera`](#open-camera) · [`contact`](#open-contact) · [`share`](#open-share) · [`calendar`](#open-calendar)
|
|
991
|
+
|
|
992
|
+
<h3 id="open-app"><code>open.app</code></h3>
|
|
993
|
+
|
|
994
|
+
**Signature**
|
|
995
|
+
|
|
996
|
+
```ts
|
|
997
|
+
app(options: AppOpenOptions): Promise<AppOpenState>
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
Opens a native app. Falls back through multiple URL strategies until one succeeds.
|
|
1001
|
+
|
|
1002
|
+
**Flowchart**
|
|
1003
|
+
|
|
1004
|
+
```mermaid
|
|
1005
|
+
flowchart TD
|
|
1006
|
+
A([Native.open.app called]) --> B[Detect current OS]
|
|
1007
|
+
B --> C[Extract app info by OS]
|
|
1008
|
+
C --> D[Build URL priority list]
|
|
1009
|
+
D --> E[tryOpenURL sequentially]
|
|
1010
|
+
E --> F{Success?}
|
|
1011
|
+
F -->|yes| G([Resolve AppOpenState])
|
|
1012
|
+
F -->|no| H{URLs remaining?}
|
|
1013
|
+
H -->|yes| E
|
|
1014
|
+
H -->|no| I([Throw URLOpenError])
|
|
1015
|
+
|
|
1016
|
+
subgraph tryOpenURL
|
|
1017
|
+
T1([Register blur and focus events]) --> T2[Open URL via href / iframe / cordova]
|
|
1018
|
+
T2 --> T3{blur fired?}
|
|
1019
|
+
T3 -->|yes| T4([resolve])
|
|
1020
|
+
T3 -->|no| T5([reject via timeout])
|
|
1021
|
+
end
|
|
1022
|
+
|
|
1023
|
+
E -.->|delegates to| T1
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
**Example**
|
|
1027
|
+
|
|
1028
|
+
```ts
|
|
1029
|
+
try {
|
|
1030
|
+
const result = await Native.open.app({
|
|
1031
|
+
android: {
|
|
1032
|
+
scheme: 'ms-excel://',
|
|
1033
|
+
packageName: 'com.microsoft.office.excel',
|
|
1034
|
+
allowAppStore: true,
|
|
1035
|
+
// allowWebStore: false,
|
|
1036
|
+
// intent: 'intent://#Intent;scheme=ms-excel;...',
|
|
1037
|
+
// fallback: 'https://www.microsoft.com/ko-kr/microsoft-365/excel',
|
|
1038
|
+
// timeout: 1000,
|
|
1039
|
+
},
|
|
1040
|
+
ios: {
|
|
1041
|
+
scheme: 'ms-excel://',
|
|
1042
|
+
trackId: '586683407',
|
|
1043
|
+
allowAppStore: true,
|
|
1044
|
+
// allowWebStore: false,
|
|
1045
|
+
// universal: '',
|
|
1046
|
+
// bundleId: 'com.microsoft.Office.Excel',
|
|
1047
|
+
// fallback: 'https://www.microsoft.com/ko-kr/microsoft-365/excel',
|
|
1048
|
+
// timeout: 2000,
|
|
1049
|
+
},
|
|
1050
|
+
windows: {
|
|
1051
|
+
scheme: 'ms-excel://',
|
|
1052
|
+
productId: 'cfq7ttc0pr28',
|
|
1053
|
+
allowAppStore: true,
|
|
1054
|
+
// allowWebStore: false,
|
|
1055
|
+
// fallback: 'https://www.microsoft.com/ko-kr/microsoft-365/excel',
|
|
1056
|
+
// timeout: 750,
|
|
1057
|
+
},
|
|
1058
|
+
macos: {
|
|
1059
|
+
scheme: 'ms-excel://',
|
|
1060
|
+
trackId: '462058435',
|
|
1061
|
+
allowAppStore: true,
|
|
1062
|
+
// allowWebStore: false,
|
|
1063
|
+
// bundleId: 'com.microsoft.Excel',
|
|
1064
|
+
// fallback: 'https://www.microsoft.com/ko-kr/microsoft-365/excel',
|
|
1065
|
+
// timeout: 750,
|
|
1066
|
+
},
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
switch (result) {
|
|
1070
|
+
AppOpenState.Intent:
|
|
1071
|
+
console.log('Opened via Android intent.'); break;
|
|
1072
|
+
AppOpenState.Universal:
|
|
1073
|
+
console.log('Opened via Universal Link.'); break;
|
|
1074
|
+
AppOpenState.Scheme:
|
|
1075
|
+
console.log('Opened via custom scheme.'); break;
|
|
1076
|
+
AppOpenState.Fallback:
|
|
1077
|
+
console.log('Opened via fallback URL.'); break;
|
|
1078
|
+
AppOpenState.Store:
|
|
1079
|
+
console.log('Redirected to App Store.'); break;
|
|
1080
|
+
}
|
|
1081
|
+
} catch (e) {
|
|
1082
|
+
if (e instanceof Native.open.Errors.URLOpenError) {
|
|
1083
|
+
console.error('All URLs exhausted:', e.message);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
```
|
|
1087
|
+
|
|
1088
|
+
**Returns**
|
|
1089
|
+
|
|
1090
|
+
```ts
|
|
1091
|
+
Promise<AppOpenState>
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
```ts
|
|
1096
|
+
enum AppOpenState {
|
|
1097
|
+
Intent = 'Intent',
|
|
1098
|
+
Universal = 'Universal',
|
|
1099
|
+
Scheme = 'Scheme',
|
|
1100
|
+
Fallback = 'Fallback',
|
|
1101
|
+
Store = 'Store',
|
|
1102
|
+
}
|
|
1103
|
+
```
|
|
1104
|
+
|
|
1105
|
+
**Throws**
|
|
1106
|
+
|
|
1107
|
+
```ts
|
|
1108
|
+
throw new URLOpenError // all candidate URLs were tried and none succeeded
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
---
|
|
1112
|
+
|
|
1113
|
+
<h3 id="open-telephone"><code>open.telephone</code></h3>
|
|
1114
|
+
|
|
1115
|
+
**Signature**
|
|
1116
|
+
|
|
1117
|
+
```ts
|
|
1118
|
+
telephone(options: TelephoneOptions): Promise<void>
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
Opens the native phone dialer.
|
|
1122
|
+
|
|
1123
|
+
**Example**
|
|
1124
|
+
|
|
1125
|
+
```ts
|
|
1126
|
+
await Native.open.telephone({ to: '+821012345678' });
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
**Returns**
|
|
1130
|
+
|
|
1131
|
+
```ts
|
|
1132
|
+
Promise<void>
|
|
1133
|
+
```
|
|
1134
|
+
|
|
1135
|
+
|
|
1136
|
+
**Throws**
|
|
1137
|
+
|
|
1138
|
+
```ts
|
|
1139
|
+
throw new URLOpenError // failed to open the phone dialer
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
---
|
|
1143
|
+
|
|
1144
|
+
<h3 id="open-message"><code>open.message</code></h3>
|
|
1145
|
+
|
|
1146
|
+
**Signature**
|
|
1147
|
+
|
|
1148
|
+
```ts
|
|
1149
|
+
message(options: MessageOptions): Promise<void>
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
Opens the native SMS app.
|
|
1153
|
+
|
|
1154
|
+
**Example**
|
|
1155
|
+
|
|
1156
|
+
```ts
|
|
1157
|
+
// With pre-filled body
|
|
1158
|
+
await Native.open.message({
|
|
1159
|
+
to: '+821012345678',
|
|
1160
|
+
body: 'Hello from Native.open!',
|
|
1161
|
+
});
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
**Returns**
|
|
1165
|
+
|
|
1166
|
+
```ts
|
|
1167
|
+
Promise<void>
|
|
1168
|
+
```
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
**Throws**
|
|
1172
|
+
|
|
1173
|
+
```ts
|
|
1174
|
+
throw new URLOpenError // failed to open the SMS app
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
---
|
|
1178
|
+
|
|
1179
|
+
<h3 id="open-mail"><code>open.mail</code></h3>
|
|
1180
|
+
|
|
1181
|
+
**Signature**
|
|
1182
|
+
|
|
1183
|
+
```ts
|
|
1184
|
+
mail(options: MailOptions): Promise<void>
|
|
1185
|
+
```
|
|
1186
|
+
|
|
1187
|
+
Opens the native mail client.
|
|
1188
|
+
|
|
1189
|
+
**Example**
|
|
1190
|
+
|
|
1191
|
+
```ts
|
|
1192
|
+
// Single recipient
|
|
1193
|
+
await Native.open.mail({
|
|
1194
|
+
to: 'hello@example.com',
|
|
1195
|
+
subject: 'Greetings',
|
|
1196
|
+
body: 'Hi there!',
|
|
1197
|
+
});
|
|
1198
|
+
|
|
1199
|
+
// Multiple recipients with cc / bcc
|
|
1200
|
+
await Native.open.mail({
|
|
1201
|
+
to: ['hello@example.com', 'world@example.com'],
|
|
1202
|
+
cc: 'cc@example.com',
|
|
1203
|
+
bcc: 'bcc@example.com',
|
|
1204
|
+
subject: 'Greetings',
|
|
1205
|
+
body: 'Hi there!',
|
|
1206
|
+
});
|
|
1207
|
+
```
|
|
1208
|
+
|
|
1209
|
+
**Returns**
|
|
1210
|
+
|
|
1211
|
+
```ts
|
|
1212
|
+
Promise<void>
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
**Throws**
|
|
1217
|
+
|
|
1218
|
+
```ts
|
|
1219
|
+
throw new URLOpenError // failed to open the mail client
|
|
1220
|
+
```
|
|
1221
|
+
|
|
1222
|
+
---
|
|
1223
|
+
|
|
1224
|
+
<h3 id="open-file"><code>open.file</code></h3>
|
|
1225
|
+
|
|
1226
|
+
**Signature**
|
|
1227
|
+
|
|
1228
|
+
```ts
|
|
1229
|
+
file(options?: FileOptions): Promise<File[]>
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
Opens a file picker dialog.
|
|
1233
|
+
|
|
1234
|
+
**Example**
|
|
1235
|
+
|
|
1236
|
+
```ts
|
|
1237
|
+
// Single file
|
|
1238
|
+
const [file] = await Native.open.file({
|
|
1239
|
+
accept: ['.pdf'],
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
// Multiple files with type filter
|
|
1243
|
+
const files = await Native.open.file({
|
|
1244
|
+
multiple: true,
|
|
1245
|
+
accept: ['.png', '.jpg', 'image/webp'],
|
|
1246
|
+
startIn: ExplorerStartIn.Pictures,
|
|
1247
|
+
});
|
|
1248
|
+
```
|
|
1249
|
+
|
|
1250
|
+
**Returns**
|
|
1251
|
+
|
|
1252
|
+
```ts
|
|
1253
|
+
Promise<File[]>
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
|
|
1257
|
+
**Throws**
|
|
1258
|
+
|
|
1259
|
+
```ts
|
|
1260
|
+
throw new UserCancelledError // user dismissed the picker
|
|
1261
|
+
```
|
|
1262
|
+
```ts
|
|
1263
|
+
throw new NotSupportedError // showOpenFilePicker and input fallback both unavailable
|
|
1264
|
+
```
|
|
1265
|
+
|
|
1266
|
+
---
|
|
1267
|
+
|
|
1268
|
+
<h3 id="open-directory"><code>open.directory</code></h3>
|
|
1269
|
+
|
|
1270
|
+
**Signature**
|
|
1271
|
+
|
|
1272
|
+
```ts
|
|
1273
|
+
directory(options?: DirectoryOptions): Promise<FileWithPath[]>
|
|
1274
|
+
```
|
|
1275
|
+
|
|
1276
|
+
Opens a directory picker and returns all files with their relative paths.
|
|
1277
|
+
|
|
1278
|
+
**Example**
|
|
1279
|
+
|
|
1280
|
+
```ts
|
|
1281
|
+
// Read-only
|
|
1282
|
+
const entries = await Native.open.directory();
|
|
1283
|
+
|
|
1284
|
+
// Read-write
|
|
1285
|
+
const entries = await Native.open.directory({
|
|
1286
|
+
mode: DirectoryExploreMode.ReadWrite,
|
|
1287
|
+
});
|
|
1288
|
+
|
|
1289
|
+
entries.forEach(({ file, relativePath }) => {
|
|
1290
|
+
console.log(relativePath, file.size); // 'src/index.ts', 1024
|
|
1291
|
+
});
|
|
1292
|
+
```
|
|
1293
|
+
|
|
1294
|
+
**Returns**
|
|
1295
|
+
|
|
1296
|
+
```ts
|
|
1297
|
+
Promise<FileWithPath[]>
|
|
1298
|
+
```
|
|
1299
|
+
|
|
1300
|
+
|
|
1301
|
+
```ts
|
|
1302
|
+
interface FileWithPath {
|
|
1303
|
+
file: File;
|
|
1304
|
+
relativePath: string;
|
|
1305
|
+
}
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
**Throws**
|
|
1309
|
+
|
|
1310
|
+
```ts
|
|
1311
|
+
throw new NotSupportedError // showDirectoryPicker and webkitdirectory both unavailable
|
|
1312
|
+
```
|
|
1313
|
+
```ts
|
|
1314
|
+
throw new UserCancelledError // user dismissed the picker
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
---
|
|
1318
|
+
|
|
1319
|
+
<h3 id="open-setting"><code>open.setting</code></h3>
|
|
1320
|
+
|
|
1321
|
+
**Signature**
|
|
1322
|
+
|
|
1323
|
+
```ts
|
|
1324
|
+
setting(type: SettingType): Promise<void>
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1327
|
+
Opens a system settings screen. iOS is unsupported.
|
|
1328
|
+
|
|
1329
|
+
**Example**
|
|
1330
|
+
|
|
1331
|
+
```ts
|
|
1332
|
+
// General settings
|
|
1333
|
+
await Native.open.setting(SettingType.General);
|
|
1334
|
+
|
|
1335
|
+
// Accessibility settings
|
|
1336
|
+
await Native.open.setting(SettingType.Accessibility);
|
|
1337
|
+
|
|
1338
|
+
// Battery settings (Android 5.1+)
|
|
1339
|
+
await Native.open.setting(SettingType.Battery);
|
|
1340
|
+
```
|
|
1341
|
+
|
|
1342
|
+
**Returns**
|
|
1343
|
+
|
|
1344
|
+
```ts
|
|
1345
|
+
Promise<void>
|
|
1346
|
+
```
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
**Throws**
|
|
1350
|
+
|
|
1351
|
+
```ts
|
|
1352
|
+
throw new URLOpenError // canOpenSetting() returned false
|
|
1353
|
+
```
|
|
1354
|
+
```ts
|
|
1355
|
+
throw new URLOpenError // all setting URLs failed
|
|
1356
|
+
```
|
|
1357
|
+
|
|
1358
|
+
---
|
|
1359
|
+
|
|
1360
|
+
<h3 id="open-camera"><code>open.camera</code></h3>
|
|
1361
|
+
|
|
1362
|
+
**Signature**
|
|
1363
|
+
|
|
1364
|
+
```ts
|
|
1365
|
+
camera(options?: CameraOptions): Promise<File[]>
|
|
1366
|
+
```
|
|
1367
|
+
|
|
1368
|
+
Opens the device camera.
|
|
1369
|
+
|
|
1370
|
+
**Example**
|
|
1371
|
+
|
|
1372
|
+
```ts
|
|
1373
|
+
// Rear-facing photo (default)
|
|
1374
|
+
const [photo] = await Native.open.camera();
|
|
1375
|
+
|
|
1376
|
+
// Front-facing video
|
|
1377
|
+
const [video] = await Native.open.camera({
|
|
1378
|
+
type: CameraType.Video,
|
|
1379
|
+
capture: CaptureType.User,
|
|
1380
|
+
});
|
|
1381
|
+
```
|
|
1382
|
+
|
|
1383
|
+
**Returns**
|
|
1384
|
+
|
|
1385
|
+
```ts
|
|
1386
|
+
Promise<File[]>
|
|
1387
|
+
```
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
**Throws**
|
|
1391
|
+
|
|
1392
|
+
```ts
|
|
1393
|
+
throw new UserCancelledError // user dismissed the camera UI
|
|
1394
|
+
```
|
|
1395
|
+
|
|
1396
|
+
---
|
|
1397
|
+
|
|
1398
|
+
<h3 id="open-contact"><code>open.contact</code></h3>
|
|
1399
|
+
|
|
1400
|
+
**Signature**
|
|
1401
|
+
|
|
1402
|
+
```ts
|
|
1403
|
+
contact(options?: ContactOptions): Promise<Contact[]>
|
|
1404
|
+
```
|
|
1405
|
+
|
|
1406
|
+
Opens the native contact picker.
|
|
1407
|
+
|
|
1408
|
+
**Example**
|
|
1409
|
+
|
|
1410
|
+
```ts
|
|
1411
|
+
// Single contact
|
|
1412
|
+
const [contact] = await Native.open.contact();
|
|
1413
|
+
console.log(contact.name, contact.tel);
|
|
1414
|
+
|
|
1415
|
+
// Multiple contacts
|
|
1416
|
+
const contacts = await Native.open.contact({ multiple: true });
|
|
1417
|
+
contacts.forEach((c) => console.log(c.name, c.email));
|
|
1418
|
+
```
|
|
1419
|
+
|
|
1420
|
+
**Returns**
|
|
1421
|
+
|
|
1422
|
+
```ts
|
|
1423
|
+
Promise<Contact[]>
|
|
1424
|
+
```
|
|
1425
|
+
|
|
1426
|
+
|
|
1427
|
+
```ts
|
|
1428
|
+
interface Contact {
|
|
1429
|
+
name?: string;
|
|
1430
|
+
email?: string;
|
|
1431
|
+
tel?: string;
|
|
1432
|
+
address?: string;
|
|
1433
|
+
icon?: Blob[];
|
|
1434
|
+
}
|
|
1435
|
+
```
|
|
1436
|
+
|
|
1437
|
+
**Throws**
|
|
1438
|
+
|
|
1439
|
+
```ts
|
|
1440
|
+
throw new NotSupportedError // navigator.contacts unavailable
|
|
1441
|
+
```
|
|
1442
|
+
|
|
1443
|
+
---
|
|
1444
|
+
|
|
1445
|
+
<h3 id="open-share"><code>open.share</code></h3>
|
|
1446
|
+
|
|
1447
|
+
**Signature**
|
|
1448
|
+
|
|
1449
|
+
```ts
|
|
1450
|
+
share(options: ShareData): Promise<void>
|
|
1451
|
+
```
|
|
1452
|
+
|
|
1453
|
+
Opens the native OS share sheet.
|
|
1454
|
+
|
|
1455
|
+
**Example**
|
|
1456
|
+
|
|
1457
|
+
```ts
|
|
1458
|
+
// Share a URL
|
|
1459
|
+
await Native.open.share({
|
|
1460
|
+
title: 'Check this out',
|
|
1461
|
+
url: 'https://example.com',
|
|
1462
|
+
});
|
|
1463
|
+
|
|
1464
|
+
// Share text and URL
|
|
1465
|
+
await Native.open.share({
|
|
1466
|
+
title: 'Check this out',
|
|
1467
|
+
text: 'Shared via Native.open',
|
|
1468
|
+
url: 'https://example.com',
|
|
1469
|
+
});
|
|
1470
|
+
```
|
|
1471
|
+
|
|
1472
|
+
**Returns**
|
|
1473
|
+
|
|
1474
|
+
```ts
|
|
1475
|
+
Promise<void>
|
|
1476
|
+
```
|
|
1477
|
+
|
|
1478
|
+
|
|
1479
|
+
**Throws**
|
|
1480
|
+
|
|
1481
|
+
```ts
|
|
1482
|
+
throw new NotSupportedError // navigator.share unavailable or canShare() false
|
|
1483
|
+
```
|
|
1484
|
+
```ts
|
|
1485
|
+
throw new UserCancelledError // user dismissed the share sheet
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
---
|
|
1489
|
+
|
|
1490
|
+
<h3 id="open-calendar"><code>open.calendar</code></h3>
|
|
1491
|
+
|
|
1492
|
+
**Signature**
|
|
1493
|
+
|
|
1494
|
+
```ts
|
|
1495
|
+
calendar(options: CalendarOptions): void
|
|
1496
|
+
```
|
|
1497
|
+
|
|
1498
|
+
Generates an RFC 5545 .ics file and triggers a download to open in the default calendar app.
|
|
1499
|
+
|
|
1500
|
+
**Example**
|
|
1501
|
+
|
|
1502
|
+
```ts
|
|
1503
|
+
// Basic event
|
|
1504
|
+
Native.open.calendar({
|
|
1505
|
+
title: 'Team Sync',
|
|
1506
|
+
description: 'Weekly alignment meeting',
|
|
1507
|
+
location: 'Seoul, Korea',
|
|
1508
|
+
startDate: new Date('2026-04-01T10:00:00Z'),
|
|
1509
|
+
endDate: new Date('2026-04-01T11:00:00Z'),
|
|
1510
|
+
});
|
|
1511
|
+
|
|
1512
|
+
// Recurring event with alarm
|
|
1513
|
+
Native.open.calendar({
|
|
1514
|
+
title: 'Weekly Standup',
|
|
1515
|
+
startDate: new Date('2026-04-01T09:00:00Z'),
|
|
1516
|
+
endDate: new Date('2026-04-01T09:15:00Z'),
|
|
1517
|
+
alarm: [{ minutes: 10, before: true }],
|
|
1518
|
+
recur: { frequency: 'WEEKLY', byDay: ['MO'], count: 12 },
|
|
1519
|
+
});
|
|
1520
|
+
|
|
1521
|
+
// All-day event
|
|
1522
|
+
Native.open.calendar({
|
|
1523
|
+
title: 'Company Holiday',
|
|
1524
|
+
allDay: true,
|
|
1525
|
+
startDate: new Date('2026-05-05T00:00:00Z'),
|
|
1526
|
+
endDate: new Date('2026-05-05T00:00:00Z'),
|
|
1527
|
+
});
|
|
1528
|
+
```
|
|
1529
|
+
|
|
1530
|
+
**Returns**
|
|
1531
|
+
|
|
1532
|
+
```ts
|
|
1533
|
+
void
|
|
1534
|
+
```
|
|
1535
|
+
|
|
1536
|
+
|
|
1537
|
+
---
|
|
1538
|
+
|
|
1539
|
+
## permission
|
|
1540
|
+
|
|
1541
|
+
[`request`](#permission-request) · [`check`](#permission-check)
|
|
1542
|
+
|
|
1543
|
+
<h3 id="permission-request"><code>permission.request</code></h3>
|
|
1544
|
+
|
|
1545
|
+
**Signature**
|
|
1546
|
+
|
|
1547
|
+
```ts
|
|
1548
|
+
request(type: PermissionType): Promise<PermissionState>
|
|
1549
|
+
```
|
|
1550
|
+
|
|
1551
|
+
Requests a permission. Resolves immediately if already granted.
|
|
1552
|
+
|
|
1553
|
+
**Flowchart**
|
|
1554
|
+
|
|
1555
|
+
```mermaid
|
|
1556
|
+
flowchart TD
|
|
1557
|
+
A([permission.request called]) --> B[check current state]
|
|
1558
|
+
B --> C{Already granted?}
|
|
1559
|
+
C -->|yes| D([Resolve Grant])
|
|
1560
|
+
C -->|no| E{PermissionType?}
|
|
1561
|
+
E -->|Notification| F[Notification.requestPermission]
|
|
1562
|
+
E -->|Geolocation| G[getCurrentPosition to trigger prompt]
|
|
1563
|
+
E -->|Camera| H[getUserMedia video=true]
|
|
1564
|
+
E -->|ClipboardRead| I[clipboard.read]
|
|
1565
|
+
E -->|Microphone| J[getUserMedia audio=true]
|
|
1566
|
+
E -->|MIDI| k[requestMIDIAccess]
|
|
1567
|
+
E -->|unknown| L([Resolve Unsupported])
|
|
1568
|
+
F & G & H & I & J --> M[check state again]
|
|
1569
|
+
M --> N([Resolve PermissionState])
|
|
1570
|
+
```
|
|
1571
|
+
|
|
1572
|
+
**Example**
|
|
1573
|
+
|
|
1574
|
+
```ts
|
|
1575
|
+
const state = await Native.permission.request(PermissionType.Notification);
|
|
1576
|
+
|
|
1577
|
+
switch (state) {
|
|
1578
|
+
case PermissionState.Grant:
|
|
1579
|
+
console.log('Permission granted.'); break;
|
|
1580
|
+
case PermissionState.Denied:
|
|
1581
|
+
console.log('Permission denied.'); break;
|
|
1582
|
+
case PermissionState.Prompt:
|
|
1583
|
+
console.log('Not yet decided.'); break;
|
|
1584
|
+
case PermissionState.Unsupported:
|
|
1585
|
+
console.log('Not supported.'); break;
|
|
1586
|
+
}
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1589
|
+
**Returns**
|
|
1590
|
+
|
|
1591
|
+
```ts
|
|
1592
|
+
Promise<PermissionState>
|
|
1593
|
+
```
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
```ts
|
|
1597
|
+
enum PermissionType {
|
|
1598
|
+
Notification = 'notifications',
|
|
1599
|
+
Geolocation = 'geolocation',
|
|
1600
|
+
Camera = 'camera',
|
|
1601
|
+
ClipboardRead = 'clipboard-read',
|
|
1602
|
+
Microphone = 'microphone',
|
|
1603
|
+
MIDI = 'midi',
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
enum PermissionState {
|
|
1607
|
+
Grant = 'grant',
|
|
1608
|
+
Denied = 'denied',
|
|
1609
|
+
Prompt = 'prompt',
|
|
1610
|
+
Unsupported = 'unsupported',
|
|
1611
|
+
}
|
|
1612
|
+
```
|
|
1613
|
+
|
|
1614
|
+
---
|
|
1615
|
+
|
|
1616
|
+
<h3 id="permission-check"><code>permission.check</code></h3>
|
|
1617
|
+
|
|
1618
|
+
**Signature**
|
|
1619
|
+
|
|
1620
|
+
```ts
|
|
1621
|
+
check(type: PermissionType): Promise<PermissionState>
|
|
1622
|
+
```
|
|
1623
|
+
|
|
1624
|
+
Returns the current permission state without triggering a prompt.
|
|
1625
|
+
|
|
1626
|
+
**Example**
|
|
1627
|
+
|
|
1628
|
+
```ts
|
|
1629
|
+
// Check before accessing a feature
|
|
1630
|
+
const state = await Native.permission.check(PermissionType.Geolocation);
|
|
1631
|
+
|
|
1632
|
+
if (state === PermissionState.Grant) {
|
|
1633
|
+
const coords = await Native.geolocation.value;
|
|
1634
|
+
}
|
|
1635
|
+
```
|
|
1636
|
+
|
|
1637
|
+
**Returns**
|
|
1638
|
+
|
|
1639
|
+
```ts
|
|
1640
|
+
Promise<PermissionState>
|
|
1641
|
+
```
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
```ts
|
|
1645
|
+
enum PermissionState {
|
|
1646
|
+
Grant = 'grant',
|
|
1647
|
+
Denied = 'denied',
|
|
1648
|
+
Prompt = 'prompt',
|
|
1649
|
+
Unsupported = 'unsupported',
|
|
1650
|
+
}
|
|
1651
|
+
```
|
|
1652
|
+
|
|
1653
|
+
---
|
|
1654
|
+
|
|
1655
|
+
## pip
|
|
1656
|
+
|
|
1657
|
+
[`request`](#pip-request) · [`exit`](#pip-exit) · [`toggle`](#pip-toggle) · [`onChange`](#pip-onchange) · [`onError`](#pip-onerror)
|
|
1658
|
+
|
|
1659
|
+
<h3 id="pip-request"><code>pip.request</code></h3>
|
|
1660
|
+
|
|
1661
|
+
**Signature**
|
|
1662
|
+
|
|
1663
|
+
```ts
|
|
1664
|
+
request(target?: HTMLVideoElement): Promise<void>
|
|
1665
|
+
```
|
|
1666
|
+
|
|
1667
|
+
Requests Picture-in-Picture for a video element. Concurrent calls are queued (FIFO).
|
|
1668
|
+
|
|
1669
|
+
**Flowchart**
|
|
1670
|
+
|
|
1671
|
+
```mermaid
|
|
1672
|
+
flowchart TD
|
|
1673
|
+
A([Pip.request called]) --> B[Set lastIntendedOperation to request]
|
|
1674
|
+
B --> C{activeOperation in progress?}
|
|
1675
|
+
C -->|no| D[requestImmediately]
|
|
1676
|
+
C -->|yes| E[Push to pendingQueue]
|
|
1677
|
+
D --> F{target is video element?}
|
|
1678
|
+
F -->|no| Z([Throw NotSupportedError])
|
|
1679
|
+
F -->|yes| G{requestPictureInPicture available?}
|
|
1680
|
+
G -->|yes| H[Call video.requestPictureInPicture]
|
|
1681
|
+
G -->|no| I[fallbackToWebkitVideo]
|
|
1682
|
+
H --> J{Resolved?}
|
|
1683
|
+
J -->|yes| K([resolve])
|
|
1684
|
+
J -->|no| I
|
|
1685
|
+
I --> L{webkitSupportsPresentationMode PIP?}
|
|
1686
|
+
L -->|yes| M[webkitSetPresentationMode picture-in-picture]
|
|
1687
|
+
M --> K
|
|
1688
|
+
L -->|no| N([Throw NotSupportedError])
|
|
1689
|
+
D --> O[drainPendingOperation on settle]
|
|
1690
|
+
```
|
|
1691
|
+
|
|
1692
|
+
**Example**
|
|
1693
|
+
|
|
1694
|
+
```ts
|
|
1695
|
+
// Default: first video element
|
|
1696
|
+
await Native.pip.request();
|
|
1697
|
+
|
|
1698
|
+
// Specific video element
|
|
1699
|
+
await Native.pip.request(document.querySelector('video#player'));
|
|
1700
|
+
|
|
1701
|
+
// Concurrent calls — safely queued, not dropped
|
|
1702
|
+
Native.pip.request(document.querySelector('video#a'));
|
|
1703
|
+
Native.pip.request(document.querySelector('video#b'));
|
|
1704
|
+
```
|
|
1705
|
+
|
|
1706
|
+
**Returns**
|
|
1707
|
+
|
|
1708
|
+
```ts
|
|
1709
|
+
Promise<void>
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
**Throws**
|
|
1714
|
+
|
|
1715
|
+
```ts
|
|
1716
|
+
throw new NotSupportedError // target is not a video element
|
|
1717
|
+
```
|
|
1718
|
+
```ts
|
|
1719
|
+
throw new NotSupportedError // PiP disabled on this element (disablePictureInPicture)
|
|
1720
|
+
```
|
|
1721
|
+
```ts
|
|
1722
|
+
throw new NotSupportedError // requestPictureInPicture and webkitSetPresentationMode both unavailable
|
|
1723
|
+
```
|
|
1724
|
+
|
|
1725
|
+
---
|
|
1726
|
+
|
|
1727
|
+
<h3 id="pip-exit"><code>pip.exit</code></h3>
|
|
1728
|
+
|
|
1729
|
+
**Signature**
|
|
1730
|
+
|
|
1731
|
+
```ts
|
|
1732
|
+
exit(): Promise<void>
|
|
1733
|
+
```
|
|
1734
|
+
|
|
1735
|
+
Exits Picture-in-Picture. Concurrent calls are queued (FIFO).
|
|
1736
|
+
|
|
1737
|
+
**Example**
|
|
1738
|
+
|
|
1739
|
+
```ts
|
|
1740
|
+
await Native.pip.exit();
|
|
1741
|
+
```
|
|
1742
|
+
|
|
1743
|
+
**Returns**
|
|
1744
|
+
|
|
1745
|
+
```ts
|
|
1746
|
+
Promise<void>
|
|
1747
|
+
```
|
|
1748
|
+
|
|
1749
|
+
|
|
1750
|
+
**Throws**
|
|
1751
|
+
|
|
1752
|
+
```ts
|
|
1753
|
+
throw new NotSupportedError // failed to exit PiP
|
|
1754
|
+
```
|
|
1755
|
+
|
|
1756
|
+
---
|
|
1757
|
+
|
|
1758
|
+
<h3 id="pip-toggle"><code>pip.toggle</code></h3>
|
|
1759
|
+
|
|
1760
|
+
**Signature**
|
|
1761
|
+
|
|
1762
|
+
```ts
|
|
1763
|
+
toggle(target?: HTMLVideoElement): Promise<void>
|
|
1764
|
+
```
|
|
1765
|
+
|
|
1766
|
+
Toggles Picture-in-Picture on or off.
|
|
1767
|
+
|
|
1768
|
+
**Example**
|
|
1769
|
+
|
|
1770
|
+
```ts
|
|
1771
|
+
// Toggle on button click
|
|
1772
|
+
btn.addEventListener('click', () => Native.pip.toggle());
|
|
1773
|
+
|
|
1774
|
+
// Toggle a specific video element
|
|
1775
|
+
btn.addEventListener('click', () => {
|
|
1776
|
+
Native.pip.toggle(document.querySelector('video#player'));
|
|
1777
|
+
});
|
|
1778
|
+
```
|
|
1779
|
+
|
|
1780
|
+
**Returns**
|
|
1781
|
+
|
|
1782
|
+
```ts
|
|
1783
|
+
Promise<void>
|
|
1784
|
+
```
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
**Throws**
|
|
1788
|
+
|
|
1789
|
+
```ts
|
|
1790
|
+
throw new NotSupportedError // propagated from request() or exit()
|
|
1791
|
+
```
|
|
1792
|
+
|
|
1793
|
+
---
|
|
1794
|
+
|
|
1795
|
+
<h3 id="pip-onchange"><code>pip.onChange</code></h3>
|
|
1796
|
+
|
|
1797
|
+
**Signature**
|
|
1798
|
+
|
|
1799
|
+
```ts
|
|
1800
|
+
onChange(listener: (event: Event) => void, options?: AddEventListenerOptions): () => void
|
|
1801
|
+
```
|
|
1802
|
+
|
|
1803
|
+
Subscribes to Picture-in-Picture state changes.
|
|
1804
|
+
|
|
1805
|
+
**Example**
|
|
1806
|
+
|
|
1807
|
+
```ts
|
|
1808
|
+
const unsubscribe = Native.pip.onChange(() => {
|
|
1809
|
+
console.log('isPip:', Native.pip.isPip);
|
|
1810
|
+
console.log('element:', Native.pip.element);
|
|
1811
|
+
});
|
|
1812
|
+
|
|
1813
|
+
unsubscribe();
|
|
1814
|
+
```
|
|
1815
|
+
|
|
1816
|
+
**Returns**
|
|
1817
|
+
|
|
1818
|
+
```ts
|
|
1819
|
+
() => void
|
|
1820
|
+
```
|
|
1821
|
+
|
|
1822
|
+
|
|
1823
|
+
```ts
|
|
1824
|
+
// call to remove the listener
|
|
1825
|
+
unsubscribe();
|
|
1826
|
+
```
|
|
1827
|
+
|
|
1828
|
+
---
|
|
1829
|
+
|
|
1830
|
+
<h3 id="pip-onerror"><code>pip.onError</code></h3>
|
|
1831
|
+
|
|
1832
|
+
**Signature**
|
|
1833
|
+
|
|
1834
|
+
```ts
|
|
1835
|
+
onError(listener: (event: Event) => void, options?: AddEventListenerOptions): () => void
|
|
1836
|
+
```
|
|
1837
|
+
|
|
1838
|
+
Subscribes to Picture-in-Picture errors.
|
|
1839
|
+
|
|
1840
|
+
**Example**
|
|
1841
|
+
|
|
1842
|
+
```ts
|
|
1843
|
+
const unsubscribe = Native.pip.onError((event) => {
|
|
1844
|
+
console.error('PiP error:', event);
|
|
1845
|
+
});
|
|
1846
|
+
|
|
1847
|
+
unsubscribe();
|
|
1848
|
+
```
|
|
1849
|
+
|
|
1850
|
+
**Returns**
|
|
1851
|
+
|
|
1852
|
+
```ts
|
|
1853
|
+
() => void
|
|
1854
|
+
```
|
|
1855
|
+
|
|
1856
|
+
|
|
1857
|
+
```ts
|
|
1858
|
+
// call to remove the listener
|
|
1859
|
+
unsubscribe();
|
|
1860
|
+
```
|
|
1861
|
+
|
|
1862
|
+
---
|
|
1863
|
+
|
|
1864
|
+
## platform
|
|
1865
|
+
|
|
1866
|
+
[`os`](#platform-os) · [`browser`](#platform-browser) · [`engine`](#platform-engine) · [`device`](#platform-device) · [`locale`](#platform-locale) · [`gpu`](#platform-gpu) · [`userAgent`](#platform-useragent) · [`ready`](#platform-ready) · [`isWebview`](#platform-iswebview) · [`isNode`](#platform-isnode) · [`isStandalone`](#platform-isstandalone)
|
|
1867
|
+
|
|
1868
|
+
<h3 id="platform-os"><code>platform.os</code></h3>
|
|
1869
|
+
|
|
1870
|
+
**Signature**
|
|
1871
|
+
|
|
1872
|
+
```ts
|
|
1873
|
+
get os(): NameVersionPair<OS>
|
|
1874
|
+
```
|
|
1875
|
+
|
|
1876
|
+
Returns the detected OS name and version.
|
|
1877
|
+
|
|
1878
|
+
**Example**
|
|
1879
|
+
|
|
1880
|
+
```ts
|
|
1881
|
+
const { name, version } = Native.platform.os;
|
|
1882
|
+
|
|
1883
|
+
switch (name) {
|
|
1884
|
+
case OS.iOS:
|
|
1885
|
+
console.log('iOS', version); break;
|
|
1886
|
+
case OS.Android:
|
|
1887
|
+
console.log('Android', version); break;
|
|
1888
|
+
case OS.Windows:
|
|
1889
|
+
console.log('Windows', version); break;
|
|
1890
|
+
case OS.MacOS:
|
|
1891
|
+
console.log('macOS', version); break;
|
|
1892
|
+
}
|
|
1893
|
+
```
|
|
1894
|
+
|
|
1895
|
+
**Returns**
|
|
1896
|
+
|
|
1897
|
+
```ts
|
|
1898
|
+
NameVersionPair<OS>
|
|
1899
|
+
```
|
|
1900
|
+
|
|
1901
|
+
|
|
1902
|
+
```ts
|
|
1903
|
+
interface NameVersionPair<T> {
|
|
1904
|
+
name: T;
|
|
1905
|
+
version: string;
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
enum OS {
|
|
1909
|
+
Unknown = 'Unknown',
|
|
1910
|
+
Android = 'Android',
|
|
1911
|
+
iOS = 'iOS',
|
|
1912
|
+
Windows = 'Windows',
|
|
1913
|
+
MacOS = 'MacOS',
|
|
1914
|
+
}
|
|
1915
|
+
```
|
|
1916
|
+
|
|
1917
|
+
---
|
|
1918
|
+
|
|
1919
|
+
<h3 id="platform-browser"><code>platform.browser</code></h3>
|
|
1920
|
+
|
|
1921
|
+
**Signature**
|
|
1922
|
+
|
|
1923
|
+
```ts
|
|
1924
|
+
get browser(): NameVersionPair<Browsers>
|
|
1925
|
+
```
|
|
1926
|
+
|
|
1927
|
+
Returns the detected browser name and version.
|
|
1928
|
+
|
|
1929
|
+
**Example**
|
|
1930
|
+
|
|
1931
|
+
```ts
|
|
1932
|
+
const { name, version } = Native.platform.browser;
|
|
1933
|
+
|
|
1934
|
+
if (name === Browsers.Safari) {
|
|
1935
|
+
console.log('Safari', version); // e.g. '17.0'
|
|
1936
|
+
}
|
|
1937
|
+
```
|
|
1938
|
+
|
|
1939
|
+
**Returns**
|
|
1940
|
+
|
|
1941
|
+
```ts
|
|
1942
|
+
NameVersionPair<Browsers>
|
|
1943
|
+
```
|
|
1944
|
+
|
|
1945
|
+
|
|
1946
|
+
```ts
|
|
1947
|
+
enum Browsers {
|
|
1948
|
+
Unknown = 'Unknown',
|
|
1949
|
+
Chrome = 'Chrome',
|
|
1950
|
+
Safari = 'Safari',
|
|
1951
|
+
Edge = 'Edge',
|
|
1952
|
+
Firefox = 'Firefox',
|
|
1953
|
+
Opera = 'Opera',
|
|
1954
|
+
IE = 'IE',
|
|
1955
|
+
SamsungInternet = 'SamsungInternet',
|
|
1956
|
+
}
|
|
1957
|
+
```
|
|
1958
|
+
|
|
1959
|
+
---
|
|
1960
|
+
|
|
1961
|
+
<h3 id="platform-engine"><code>platform.engine</code></h3>
|
|
1962
|
+
|
|
1963
|
+
**Signature**
|
|
1964
|
+
|
|
1965
|
+
```ts
|
|
1966
|
+
get engine(): NameVersionPair<Engines>
|
|
1967
|
+
```
|
|
1968
|
+
|
|
1969
|
+
Returns the detected rendering engine name and version.
|
|
1970
|
+
|
|
1971
|
+
**Example**
|
|
1972
|
+
|
|
1973
|
+
```ts
|
|
1974
|
+
const { name, version } = Native.platform.engine;
|
|
1975
|
+
|
|
1976
|
+
if (name === Engines.Blink) {
|
|
1977
|
+
console.log('Blink', version); // e.g. '120.0.6099.62'
|
|
1978
|
+
}
|
|
1979
|
+
```
|
|
1980
|
+
|
|
1981
|
+
**Returns**
|
|
1982
|
+
|
|
1983
|
+
```ts
|
|
1984
|
+
NameVersionPair<Engines>
|
|
1985
|
+
```
|
|
1986
|
+
|
|
1987
|
+
|
|
1988
|
+
```ts
|
|
1989
|
+
enum Engines {
|
|
1990
|
+
Unknown = 'Unknown',
|
|
1991
|
+
EdgeHTML = 'EdgeHTML',
|
|
1992
|
+
ArkWeb = 'ArkWeb',
|
|
1993
|
+
Blink = 'Blink',
|
|
1994
|
+
Presto = 'Presto',
|
|
1995
|
+
WebKit = 'WebKit',
|
|
1996
|
+
Trident = 'Trident',
|
|
1997
|
+
Gecko = 'Gecko',
|
|
1998
|
+
}
|
|
1999
|
+
```
|
|
2000
|
+
|
|
2001
|
+
---
|
|
2002
|
+
|
|
2003
|
+
<h3 id="platform-device"><code>platform.device</code></h3>
|
|
2004
|
+
|
|
2005
|
+
**Signature**
|
|
2006
|
+
|
|
2007
|
+
```ts
|
|
2008
|
+
get device(): Devices
|
|
2009
|
+
```
|
|
2010
|
+
|
|
2011
|
+
Returns the device category: Mobile, Desktop, or Unknown.
|
|
2012
|
+
|
|
2013
|
+
**Example**
|
|
2014
|
+
|
|
2015
|
+
```ts
|
|
2016
|
+
if (Native.platform.device === Devices.Mobile) {
|
|
2017
|
+
console.log('Running on a mobile device');
|
|
2018
|
+
}
|
|
2019
|
+
```
|
|
2020
|
+
|
|
2021
|
+
**Returns**
|
|
2022
|
+
|
|
2023
|
+
```ts
|
|
2024
|
+
Devices
|
|
2025
|
+
```
|
|
2026
|
+
|
|
2027
|
+
|
|
2028
|
+
```ts
|
|
2029
|
+
enum Devices {
|
|
2030
|
+
Unknown = 'Unknown',
|
|
2031
|
+
Mobile = 'Mobile',
|
|
2032
|
+
Desktop = 'Desktop',
|
|
2033
|
+
}
|
|
2034
|
+
```
|
|
2035
|
+
|
|
2036
|
+
---
|
|
2037
|
+
|
|
2038
|
+
<h3 id="platform-locale"><code>platform.locale</code></h3>
|
|
2039
|
+
|
|
2040
|
+
**Signature**
|
|
2041
|
+
|
|
2042
|
+
```ts
|
|
2043
|
+
get locale(): Locale
|
|
2044
|
+
```
|
|
2045
|
+
|
|
2046
|
+
Returns the current locale, timezone, UTC offset, and text direction.
|
|
2047
|
+
|
|
2048
|
+
**Example**
|
|
2049
|
+
|
|
2050
|
+
```ts
|
|
2051
|
+
const { language, languages, timezone, offset, isRTL } = Native.platform.locale;
|
|
2052
|
+
|
|
2053
|
+
console.log(language); // 'ko-KR'
|
|
2054
|
+
console.log(languages); // ['ko-KR', 'en-US']
|
|
2055
|
+
console.log(timezone); // 'Asia/Seoul'
|
|
2056
|
+
console.log(offset); // 540 (UTC+9 in minutes)
|
|
2057
|
+
console.log(isRTL); // false
|
|
2058
|
+
```
|
|
2059
|
+
|
|
2060
|
+
**Returns**
|
|
2061
|
+
|
|
2062
|
+
```ts
|
|
2063
|
+
Locale
|
|
2064
|
+
```
|
|
2065
|
+
|
|
2066
|
+
|
|
2067
|
+
```ts
|
|
2068
|
+
interface Locale {
|
|
2069
|
+
language: string | null;
|
|
2070
|
+
languages: string[];
|
|
2071
|
+
timezone: string | null;
|
|
2072
|
+
offset: number;
|
|
2073
|
+
isRTL: boolean;
|
|
2074
|
+
}
|
|
2075
|
+
```
|
|
2076
|
+
|
|
2077
|
+
---
|
|
2078
|
+
|
|
2079
|
+
<h3 id="platform-gpu"><code>platform.gpu</code></h3>
|
|
2080
|
+
|
|
2081
|
+
**Signature**
|
|
2082
|
+
|
|
2083
|
+
```ts
|
|
2084
|
+
get gpu(): GPU
|
|
2085
|
+
```
|
|
2086
|
+
|
|
2087
|
+
Returns GPU information. Await Native.platform.ready for guaranteed complete data.
|
|
2088
|
+
|
|
2089
|
+
**Example**
|
|
2090
|
+
|
|
2091
|
+
```ts
|
|
2092
|
+
// Guaranteed complete data
|
|
2093
|
+
await Native.platform.ready;
|
|
2094
|
+
const { vendor, architecture, device, description } = Native.platform.gpu;
|
|
2095
|
+
|
|
2096
|
+
console.log(vendor); // 'apple'
|
|
2097
|
+
console.log(architecture); // 'common-3'
|
|
2098
|
+
console.log(device); // 'Apple M2'
|
|
2099
|
+
```
|
|
2100
|
+
|
|
2101
|
+
**Returns**
|
|
2102
|
+
|
|
2103
|
+
```ts
|
|
2104
|
+
GPU
|
|
2105
|
+
```
|
|
2106
|
+
|
|
2107
|
+
|
|
2108
|
+
```ts
|
|
2109
|
+
interface GPU {
|
|
2110
|
+
vendor?: string;
|
|
2111
|
+
architecture?: string;
|
|
2112
|
+
device?: string;
|
|
2113
|
+
description?: string;
|
|
2114
|
+
}
|
|
2115
|
+
```
|
|
2116
|
+
|
|
2117
|
+
---
|
|
2118
|
+
|
|
2119
|
+
<h3 id="platform-useragent"><code>platform.userAgent</code></h3>
|
|
2120
|
+
|
|
2121
|
+
**Signature**
|
|
2122
|
+
|
|
2123
|
+
```ts
|
|
2124
|
+
get userAgent(): string
|
|
2125
|
+
set userAgent(value: string)
|
|
2126
|
+
```
|
|
2127
|
+
|
|
2128
|
+
Gets or sets the User-Agent string used for all platform detection. The setter invalidates all parsed caches.
|
|
2129
|
+
|
|
2130
|
+
**Example**
|
|
2131
|
+
|
|
2132
|
+
```ts
|
|
2133
|
+
// Read current UA
|
|
2134
|
+
console.log(Native.platform.userAgent);
|
|
2135
|
+
|
|
2136
|
+
// Override for testing
|
|
2137
|
+
Native.platform.userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)...';
|
|
2138
|
+
console.log(Native.platform.os.name); // 'iOS'
|
|
2139
|
+
|
|
2140
|
+
// Restore original UA
|
|
2141
|
+
Native.platform.userAgent = originalUA;
|
|
2142
|
+
await Native.platform.ready;
|
|
2143
|
+
```
|
|
2144
|
+
|
|
2145
|
+
**Returns**
|
|
2146
|
+
|
|
2147
|
+
```ts
|
|
2148
|
+
string
|
|
2149
|
+
```
|
|
2150
|
+
|
|
2151
|
+
|
|
2152
|
+
---
|
|
2153
|
+
|
|
2154
|
+
<h3 id="platform-ready"><code>platform.ready</code></h3>
|
|
2155
|
+
|
|
2156
|
+
**Signature**
|
|
2157
|
+
|
|
2158
|
+
```ts
|
|
2159
|
+
get ready(): Promise<void>
|
|
2160
|
+
```
|
|
2161
|
+
|
|
2162
|
+
Resolves when all async platform detection has settled.
|
|
2163
|
+
|
|
2164
|
+
**Example**
|
|
2165
|
+
|
|
2166
|
+
```ts
|
|
2167
|
+
await Native.platform.ready;
|
|
2168
|
+
|
|
2169
|
+
// All values now reflect high-entropy and WebGPU data
|
|
2170
|
+
console.log(Native.platform.os.name);
|
|
2171
|
+
console.log(Native.platform.browser.name);
|
|
2172
|
+
console.log(Native.platform.gpu.vendor);
|
|
2173
|
+
```
|
|
2174
|
+
|
|
2175
|
+
**Returns**
|
|
2176
|
+
|
|
2177
|
+
```ts
|
|
2178
|
+
Promise<void>
|
|
2179
|
+
```
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
---
|
|
2183
|
+
|
|
2184
|
+
<h3 id="platform-iswebview"><code>platform.isWebview</code></h3>
|
|
2185
|
+
|
|
2186
|
+
**Signature**
|
|
2187
|
+
|
|
2188
|
+
```ts
|
|
2189
|
+
get isWebview(): boolean
|
|
2190
|
+
```
|
|
2191
|
+
|
|
2192
|
+
Returns true when running inside a native WebView.
|
|
2193
|
+
|
|
2194
|
+
**Example**
|
|
2195
|
+
|
|
2196
|
+
```ts
|
|
2197
|
+
if (Native.platform.isWebview) {
|
|
2198
|
+
console.log('Running inside a native WebView');
|
|
2199
|
+
}
|
|
2200
|
+
```
|
|
2201
|
+
|
|
2202
|
+
**Returns**
|
|
2203
|
+
|
|
2204
|
+
```ts
|
|
2205
|
+
boolean
|
|
2206
|
+
```
|
|
2207
|
+
|
|
2208
|
+
|
|
2209
|
+
---
|
|
2210
|
+
|
|
2211
|
+
<h3 id="platform-isnode"><code>platform.isNode</code></h3>
|
|
2212
|
+
|
|
2213
|
+
**Signature**
|
|
2214
|
+
|
|
2215
|
+
```ts
|
|
2216
|
+
get isNode(): boolean
|
|
2217
|
+
```
|
|
2218
|
+
|
|
2219
|
+
Returns true when running in a Node.js environment.
|
|
2220
|
+
|
|
2221
|
+
**Example**
|
|
2222
|
+
|
|
2223
|
+
```ts
|
|
2224
|
+
if (Native.platform.isNode) {
|
|
2225
|
+
console.log('Running in Node.js');
|
|
2226
|
+
}
|
|
2227
|
+
```
|
|
2228
|
+
|
|
2229
|
+
**Returns**
|
|
2230
|
+
|
|
2231
|
+
```ts
|
|
2232
|
+
boolean
|
|
2233
|
+
```
|
|
2234
|
+
|
|
2235
|
+
|
|
2236
|
+
---
|
|
2237
|
+
|
|
2238
|
+
<h3 id="platform-isstandalone"><code>platform.isStandalone</code></h3>
|
|
2239
|
+
|
|
2240
|
+
**Signature**
|
|
2241
|
+
|
|
2242
|
+
```ts
|
|
2243
|
+
get isStandalone(): boolean
|
|
2244
|
+
```
|
|
2245
|
+
|
|
2246
|
+
Returns true when running as an installed PWA.
|
|
2247
|
+
|
|
2248
|
+
**Example**
|
|
2249
|
+
|
|
2250
|
+
```ts
|
|
2251
|
+
if (Native.platform.isStandalone) {
|
|
2252
|
+
console.log('Running as installed PWA');
|
|
2253
|
+
}
|
|
2254
|
+
```
|
|
2255
|
+
|
|
2256
|
+
**Returns**
|
|
2257
|
+
|
|
2258
|
+
```ts
|
|
2259
|
+
boolean
|
|
2260
|
+
```
|
|
2261
|
+
|
|
2262
|
+
|
|
2263
|
+
---
|
|
2264
|
+
|
|
2265
|
+
## theme
|
|
2266
|
+
|
|
2267
|
+
[`value`](#theme-value)
|
|
2268
|
+
|
|
2269
|
+
<h3 id="theme-value"><code>theme.value</code></h3>
|
|
2270
|
+
|
|
2271
|
+
**Signature**
|
|
2272
|
+
|
|
2273
|
+
```ts
|
|
2274
|
+
get value(): string | undefined
|
|
2275
|
+
set value(color: string | undefined)
|
|
2276
|
+
```
|
|
2277
|
+
|
|
2278
|
+
Gets or sets the browser theme color via the meta theme-color tag.
|
|
2279
|
+
|
|
2280
|
+
**Example**
|
|
2281
|
+
|
|
2282
|
+
```ts
|
|
2283
|
+
// Read
|
|
2284
|
+
console.log(Native.theme.value); // '#ffffff' | undefined
|
|
2285
|
+
|
|
2286
|
+
// Set
|
|
2287
|
+
Native.theme.value = '#1a1a2e';
|
|
2288
|
+
|
|
2289
|
+
// Remove
|
|
2290
|
+
Native.theme.value = undefined;
|
|
2291
|
+
```
|
|
2292
|
+
|
|
2293
|
+
**Returns**
|
|
2294
|
+
|
|
2295
|
+
```ts
|
|
2296
|
+
string | undefined
|
|
2297
|
+
```
|
|
2298
|
+
|
|
2299
|
+
|
|
2300
|
+
---
|
|
2301
|
+
|
|
2302
|
+
## vibration
|
|
2303
|
+
|
|
2304
|
+
[`run`](#vibration-run) · [`stop`](#vibration-stop)
|
|
2305
|
+
|
|
2306
|
+
<h3 id="vibration-run"><code>vibration.run</code></h3>
|
|
2307
|
+
|
|
2308
|
+
**Signature**
|
|
2309
|
+
|
|
2310
|
+
```ts
|
|
2311
|
+
run(pattern: number | number[]): boolean
|
|
2312
|
+
```
|
|
2313
|
+
|
|
2314
|
+
Triggers device vibration. Pass a number for a single pulse or an array to define a pattern.
|
|
2315
|
+
|
|
2316
|
+
**Example**
|
|
2317
|
+
|
|
2318
|
+
```ts
|
|
2319
|
+
// Single pulse — 200ms
|
|
2320
|
+
Native.vibration.run(200);
|
|
2321
|
+
|
|
2322
|
+
// Pattern — vibrate 100ms, pause 50ms, vibrate 200ms
|
|
2323
|
+
Native.vibration.run([100, 50, 200]);
|
|
2324
|
+
|
|
2325
|
+
// Stop any ongoing vibration
|
|
2326
|
+
Native.vibration.run(0);
|
|
2327
|
+
```
|
|
2328
|
+
|
|
2329
|
+
**Returns**
|
|
2330
|
+
|
|
2331
|
+
```ts
|
|
2332
|
+
boolean
|
|
2333
|
+
```
|
|
2334
|
+
|
|
2335
|
+
|
|
2336
|
+
**Throws**
|
|
2337
|
+
|
|
2338
|
+
```ts
|
|
2339
|
+
throw new NotSupportedError // navigator.vibrate unavailable
|
|
2340
|
+
```
|
|
2341
|
+
|
|
2342
|
+
---
|
|
2343
|
+
|
|
2344
|
+
<h3 id="vibration-stop"><code>vibration.stop</code></h3>
|
|
2345
|
+
|
|
2346
|
+
**Signature**
|
|
2347
|
+
|
|
2348
|
+
```ts
|
|
2349
|
+
stop(): boolean
|
|
2350
|
+
```
|
|
2351
|
+
|
|
2352
|
+
Stops any ongoing vibration.
|
|
2353
|
+
|
|
2354
|
+
**Example**
|
|
2355
|
+
|
|
2356
|
+
```ts
|
|
2357
|
+
Native.vibration.stop();
|
|
2358
|
+
```
|
|
2359
|
+
|
|
2360
|
+
**Returns**
|
|
2361
|
+
|
|
2362
|
+
```ts
|
|
2363
|
+
boolean
|
|
2364
|
+
```
|
|
2365
|
+
|
|
2366
|
+
|
|
2367
|
+
```ts
|
|
2368
|
+
// true — stop request accepted by the browser
|
|
2369
|
+
// false — document is hidden or vibration is unsupported
|
|
2370
|
+
```
|
|
2371
|
+
|
|
2372
|
+
**Throws**
|
|
2373
|
+
|
|
2374
|
+
```ts
|
|
2375
|
+
throw new NotSupportedError // navigator.vibrate unavailable
|
|
2376
|
+
```
|
|
2377
|
+
|
|
2378
|
+
---
|