native-fn 1.1.8 → 1.2.0

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