vue-screenfull 1.0.8 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -72
- package/README.zh-CN.md +87 -7
- package/lib/browser.cjs.js +7 -0
- package/lib/browser.cjs.js.map +1 -0
- package/lib/browser.d.ts +94 -0
- package/lib/browser.esm.js +7 -0
- package/lib/browser.esm.js.map +1 -0
- package/lib/browser.mjs +7 -0
- package/lib/browser.mjs.map +1 -0
- package/lib/index.cjs.js +2 -2
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +6 -5
- package/lib/index.esm.js +2 -2
- package/lib/index.esm.js.map +1 -1
- package/lib/index.mjs +2 -2
- package/lib/index.mjs.map +1 -1
- package/lib/typing.d.ts +2 -1
- package/lib/vue-screenfull.browser.min.js +7 -0
- package/lib/vue-screenfull.browser.min.js.map +1 -0
- package/lib/vue-screenfull.min.js +2 -2
- package/lib/vue-screenfull.min.js.map +1 -1
- package/package.json +21 -4
- /package/{MANUAL_TESTING.md → guides/MANUAL_TESTING.md} +0 -0
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
[license-image]: https://img.shields.io/npm/l/vue-screenfull.svg
|
|
9
9
|
[license-url]: https://github.com/chengchuu/vue-screenfull/blob/main/LICENSE
|
|
10
10
|
|
|
11
|
-
Reactive, strongly typed, SSR-safe fullscreen utilities
|
|
12
|
-
|
|
11
|
+
Reactive, strongly typed, and SSR-safe fullscreen utilities for Vue 3, with an optional CSS
|
|
12
|
+
pseudo-fullscreen fallback.
|
|
13
13
|
|
|
14
14
|
- [Project website](https://chengchuu.github.io/vue-screenfull/)
|
|
15
15
|
- [Live playground](https://chengchuu.github.io/vue-screenfull/playground/)
|
|
@@ -21,9 +21,7 @@ An optional CSS pseudo-fullscreen fallback is also available.
|
|
|
21
21
|
- Standard, WebKit, Mozilla, and Microsoft-prefixed API detection.
|
|
22
22
|
- Vue template refs, component refs, elements, and safe CSS selectors.
|
|
23
23
|
- Structured results and actionable errors instead of swallowed rejections.
|
|
24
|
-
- Renderless component, directive, optional plugin, and framework-
|
|
25
|
-
- No fullscreen wrapper or other runtime dependency; Vue remains a peer dependency.
|
|
26
|
-
- CJS, ESM, browser IIFE, source maps, and declarations.
|
|
24
|
+
- Renderless component, directive, optional plugin, and framework-neutral controller.
|
|
27
25
|
|
|
28
26
|
## Installation
|
|
29
27
|
|
|
@@ -31,17 +29,8 @@ An optional CSS pseudo-fullscreen fallback is also available.
|
|
|
31
29
|
npm install vue-screenfull
|
|
32
30
|
```
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## Browser Support
|
|
37
|
-
|
|
38
|
-
Support is feature-detected at runtime. Current Chrome, Edge, Firefox, and Safari desktop releases,
|
|
39
|
-
Chrome/Firefox/Samsung Internet on Android, and Safari on iPadOS commonly expose the API. iPhone
|
|
40
|
-
Safari, Android/iOS WebViews, managed devices, and embedded documents may restrict arbitrary-element
|
|
41
|
-
fullscreen. This policy describes targets, not a guarantee for every OS/browser release.
|
|
42
|
-
|
|
43
|
-
Native fullscreen can hide more browser UI, but the browser and operating system retain control.
|
|
44
|
-
The CSS fallback only fills the visual viewport and never claims to hide system or browser chrome.
|
|
32
|
+
`lib/vue-screenfull.min.js` exposes `VUE_SCREENFULL` and requires the global `Vue`. Although Vue is
|
|
33
|
+
an optional peer dependency, package-root imports still require Vue 3 at runtime.
|
|
45
34
|
|
|
46
35
|
## Basic Usage
|
|
47
36
|
|
|
@@ -65,8 +54,8 @@ const { isEnabled, isFullscreen, error, toggle } = useScreenfull();
|
|
|
65
54
|
</template>
|
|
66
55
|
```
|
|
67
56
|
|
|
68
|
-
Call `request` or `toggle` directly
|
|
69
|
-
|
|
57
|
+
Call `request` or `toggle` directly from a click, keyboard, or touch handler. Browsers normally
|
|
58
|
+
require transient user activation and can reject a request even when `isEnabled.value` is true.
|
|
70
59
|
|
|
71
60
|
## Fullscreen a Specific Element
|
|
72
61
|
|
|
@@ -86,7 +75,8 @@ const { request, isFullscreen } = useScreenfullTarget(panel);
|
|
|
86
75
|
```
|
|
87
76
|
|
|
88
77
|
`useScreenfull().request()` with no target opens `document.documentElement`.
|
|
89
|
-
A selector such as `request("#player")` is resolved with `document.querySelector
|
|
78
|
+
A selector such as `request("#player")` is resolved with `document.querySelector`. Invalid or
|
|
79
|
+
unmatched selectors return `INVALID_TARGET`.
|
|
90
80
|
|
|
91
81
|
## Toggle Fullscreen
|
|
92
82
|
|
|
@@ -104,8 +94,9 @@ Some mobile browsers offer video-only fullscreen independently of arbitrary-elem
|
|
|
104
94
|
<button type="button" @click="exit">Exit fullscreen</button>
|
|
105
95
|
```
|
|
106
96
|
|
|
107
|
-
Always include a visible exit button, particularly when fallback is enabled. Escape often exits
|
|
108
|
-
but browser
|
|
97
|
+
Always include a visible exit button, particularly when fallback is enabled. Escape often exits
|
|
98
|
+
fullscreen, but its browser behavior cannot be overridden reliably. Native change events reflect
|
|
99
|
+
exits initiated through the browser UI.
|
|
109
100
|
|
|
110
101
|
## Check Support
|
|
111
102
|
|
|
@@ -145,18 +136,20 @@ const { request, exit, isFallback } = useScreenfull({
|
|
|
145
136
|
});
|
|
146
137
|
```
|
|
147
138
|
|
|
148
|
-
CSS fallback fixes an `HTMLElement` to the visual viewport
|
|
149
|
-
locks and restores background body scrolling
|
|
150
|
-
preserves the scroll position, adds the configured class, exits on Escape when
|
|
151
|
-
focus. Cleanup also runs when its Vue scope is disposed.
|
|
152
|
-
|
|
153
|
-
|
|
139
|
+
CSS fallback fixes an `HTMLElement` to the visual viewport and preserves every inline style that it
|
|
140
|
+
changes. For element targets, it locks and restores background body scrolling. It keeps whole-page
|
|
141
|
+
targets scrollable, preserves the scroll position, adds the configured class, exits on Escape when
|
|
142
|
+
possible, and restores focus. Cleanup also runs when its Vue scope is disposed.
|
|
143
|
+
|
|
144
|
+
This mode is pseudo-fullscreen. It cannot hide address bars, browser controls, notifications, or
|
|
145
|
+
operating-system UI. Keep an accessible exit button inside the target:
|
|
154
146
|
|
|
155
147
|
```vue
|
|
156
148
|
<button type="button" @click="exit">Close full-page view</button>
|
|
157
149
|
```
|
|
158
150
|
|
|
159
|
-
A custom fallback implements `enter(context)` and `exit(context)` and is responsible for complete
|
|
151
|
+
A custom fallback implements `enter(context)` and `exit(context)` and is responsible for complete
|
|
152
|
+
cleanup.
|
|
160
153
|
|
|
161
154
|
## Component Usage
|
|
162
155
|
|
|
@@ -174,8 +167,8 @@ A custom fallback implements `enter(context)` and `exit(context)` and is respons
|
|
|
174
167
|
</Screenfull>
|
|
175
168
|
```
|
|
176
169
|
|
|
177
|
-
The renderless component emits `change`, `enter`, `exit`, `error`, and `fallback`.
|
|
178
|
-
|
|
170
|
+
The renderless component emits `change`, `enter`, `exit`, `error`, and `fallback`. Its default slot
|
|
171
|
+
receives all composable refs and actions without imposing a visual system.
|
|
179
172
|
|
|
180
173
|
## Directive Usage
|
|
181
174
|
|
|
@@ -206,15 +199,96 @@ import App from "./App.vue";
|
|
|
206
199
|
createApp(App).use(VueScreenfull).mount("#app");
|
|
207
200
|
```
|
|
208
201
|
|
|
209
|
-
This registers `Screenfull` and `v-screenfull`.
|
|
210
|
-
Named composable imports
|
|
202
|
+
This registers `Screenfull` and `v-screenfull`. Use `componentName` and `directiveName` to change
|
|
203
|
+
their names. Named composable imports do not require plugin installation and remain tree-shakable.
|
|
204
|
+
|
|
205
|
+
## Vue-free Browser Entry
|
|
206
|
+
|
|
207
|
+
Use `vue-screenfull/browser` when the caller does not own a Vue root. This subpath exports only
|
|
208
|
+
`createScreenfullController`, `detectFullscreenApi`, and their framework-neutral types. It does not
|
|
209
|
+
load Vue or Mazey at runtime.
|
|
210
|
+
|
|
211
|
+
With npm:
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
import {
|
|
215
|
+
createScreenfullController,
|
|
216
|
+
type ScreenfullChangeListener,
|
|
217
|
+
} from "vue-screenfull/browser";
|
|
218
|
+
|
|
219
|
+
const controller = createScreenfullController({ restoreFocus: true });
|
|
220
|
+
const target = document.querySelector("#player");
|
|
221
|
+
const button = document.querySelector("#toggle-fullscreen");
|
|
222
|
+
const toggle = () => controller.toggle(target);
|
|
223
|
+
const onChange: ScreenfullChangeListener = (state) => {
|
|
224
|
+
console.log(state.isFullscreen, state.element);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
button?.addEventListener("click", toggle);
|
|
228
|
+
controller.on("change", onChange);
|
|
229
|
+
|
|
230
|
+
async function dispose() {
|
|
231
|
+
button?.removeEventListener("click", toggle);
|
|
232
|
+
controller.off("change", onChange);
|
|
233
|
+
await controller.destroy();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Call dispose() when the integration is disposed.
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
As a native browser ES module:
|
|
240
|
+
|
|
241
|
+
```html
|
|
242
|
+
<script type="module">
|
|
243
|
+
import { createScreenfullController } from "https://cdn.jsdelivr.net/npm/vue-screenfull/lib/browser.mjs";
|
|
244
|
+
|
|
245
|
+
const controller = createScreenfullController();
|
|
246
|
+
const target = document.querySelector("#player");
|
|
247
|
+
const button = document.querySelector("#toggle-fullscreen");
|
|
248
|
+
const toggle = () => controller.toggle(target);
|
|
249
|
+
|
|
250
|
+
button?.addEventListener("click", toggle);
|
|
251
|
+
|
|
252
|
+
async function dispose() {
|
|
253
|
+
button?.removeEventListener("click", toggle);
|
|
254
|
+
await controller.destroy();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Call dispose() when the integration is disposed.
|
|
258
|
+
</script>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
As a classic script:
|
|
262
|
+
|
|
263
|
+
```html
|
|
264
|
+
<script src="https://cdn.jsdelivr.net/npm/vue-screenfull/lib/vue-screenfull.browser.min.js"></script>
|
|
265
|
+
<script>
|
|
266
|
+
const controller = VUE_SCREENFULL_BROWSER.createScreenfullController();
|
|
267
|
+
const target = document.querySelector("#player");
|
|
268
|
+
const button = document.querySelector("#toggle-fullscreen");
|
|
269
|
+
const toggle = () => controller.toggle(target);
|
|
270
|
+
|
|
271
|
+
button?.addEventListener("click", toggle);
|
|
272
|
+
|
|
273
|
+
function dispose() {
|
|
274
|
+
button?.removeEventListener("click", toggle);
|
|
275
|
+
return controller.destroy();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Call dispose() when the integration is disposed.
|
|
279
|
+
</script>
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Call `request` or `toggle` directly from a click, keyboard, or touch handler because browsers
|
|
283
|
+
normally require transient user activation. Retain the controller and call `destroy()` when the
|
|
284
|
+
integration is disposed so its listeners and any active CSS fallback are cleaned up.
|
|
211
285
|
|
|
212
286
|
## Advanced Usage
|
|
213
287
|
|
|
214
|
-
The framework-
|
|
288
|
+
The framework-neutral controller is useful for migration and non-component integrations:
|
|
215
289
|
|
|
216
290
|
```ts
|
|
217
|
-
import { createScreenfullController } from "vue-screenfull";
|
|
291
|
+
import { createScreenfullController } from "vue-screenfull/browser";
|
|
218
292
|
|
|
219
293
|
const controller = createScreenfullController({ restoreFocus: true });
|
|
220
294
|
const onChange = (state) => console.log(state.isFullscreen, state.element);
|
|
@@ -224,10 +298,10 @@ controller.off("change", onChange);
|
|
|
224
298
|
await controller.destroy();
|
|
225
299
|
```
|
|
226
300
|
|
|
227
|
-
`raw` is a read-only diagnostic mapping of detected browser property
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
301
|
+
`raw` is a read-only diagnostic mapping of detected browser property and event names, or `null`. It
|
|
302
|
+
is not the recommended API. Each composable creates one controller and disposes it with its Vue
|
|
303
|
+
scope. Multiple controllers synchronize through the same document's native events. Importing the
|
|
304
|
+
package does not register listeners or touch the DOM.
|
|
231
305
|
|
|
232
306
|
Reactive callbacks can observe changes without duplicate component wiring:
|
|
233
307
|
|
|
@@ -236,7 +310,8 @@ useScreenfull({ onEnter: announce, onExit: announce, onError: report });
|
|
|
236
310
|
```
|
|
237
311
|
|
|
238
312
|
`restoreFocus: true` (the default) focuses the initiating element after exit where practical.
|
|
239
|
-
`exitOnRouteChange` listens for browser `popstate
|
|
313
|
+
`exitOnRouteChange` listens for browser `popstate`. For router-specific navigation, call `exit()`
|
|
314
|
+
from the application's route hook instead.
|
|
240
315
|
|
|
241
316
|
## iframe Usage
|
|
242
317
|
|
|
@@ -250,9 +325,9 @@ The embedding page controls permission. A typical iframe is:
|
|
|
250
325
|
></iframe>
|
|
251
326
|
```
|
|
252
327
|
|
|
253
|
-
Permissions Policy or
|
|
254
|
-
|
|
255
|
-
|
|
328
|
+
A Permissions Policy restriction or missing iframe permission can still reject the request. The
|
|
329
|
+
library returns `IFRAME_PERMISSION_REQUIRED` when it can associate a denial with an embedded
|
|
330
|
+
document. It cannot override the parent page's policy.
|
|
256
331
|
|
|
257
332
|
## Mobile Considerations
|
|
258
333
|
|
|
@@ -263,10 +338,21 @@ it cannot override the parent page's policy.
|
|
|
263
338
|
- Native navigation, tab switching, app switching, and OS gestures may exit fullscreen.
|
|
264
339
|
- Neither native capability nor this library guarantees browser/OS controls disappear.
|
|
265
340
|
|
|
341
|
+
## Browser Support
|
|
342
|
+
|
|
343
|
+
Support is detected at runtime. Current desktop releases of Chrome, Edge, Firefox, and Safari
|
|
344
|
+
commonly expose the API. Chrome, Firefox, and Samsung Internet on Android and Safari on iPadOS also
|
|
345
|
+
commonly expose it. iPhone Safari, Android and iOS WebViews, managed devices, and embedded documents
|
|
346
|
+
may restrict arbitrary-element fullscreen. This policy identifies support targets; it does not
|
|
347
|
+
guarantee support in every browser or operating-system release.
|
|
348
|
+
|
|
349
|
+
Native fullscreen can hide more browser UI, but the browser and operating system retain control.
|
|
350
|
+
The CSS fallback only fills the visual viewport and never claims to hide system or browser chrome.
|
|
351
|
+
|
|
266
352
|
## SSR and Nuxt
|
|
267
353
|
|
|
268
354
|
Imports are safe in Vite SSR, Nuxt 3, Node tests, and static generation. Outside a browser,
|
|
269
|
-
`isEnabled` is false
|
|
355
|
+
`isEnabled` is `false`, the status is `unsupported`, and actions return `NOT_IN_BROWSER`.
|
|
270
356
|
|
|
271
357
|
```vue
|
|
272
358
|
<script setup lang="ts">
|
|
@@ -286,16 +372,16 @@ const screenfull = useScreenfull(); // safe during Nuxt setup/SSR
|
|
|
286
372
|
</template>
|
|
287
373
|
```
|
|
288
374
|
|
|
289
|
-
|
|
290
|
-
|
|
375
|
+
Templates automatically unwrap refs destructured in `<script setup>`. When accessing refs through
|
|
376
|
+
an object as shown in the example, use `.value` in script expressions.
|
|
291
377
|
|
|
292
378
|
## Migrating from screenfull
|
|
293
379
|
|
|
294
|
-
`vue-screenfull` is an independent Vue 3 library inspired by screenfull's public API and
|
|
295
|
-
It is not drop-in compatible and is not endorsed by screenfull's maintainers.
|
|
380
|
+
`vue-screenfull` is an independent Vue 3 library inspired by screenfull's public API and
|
|
381
|
+
compatibility goals. It is not drop-in compatible and is not endorsed by screenfull's maintainers.
|
|
296
382
|
|
|
297
383
|
| screenfull concept | vue-screenfull equivalent |
|
|
298
|
-
|
|
|
384
|
+
| :------------------------------------- | :------------------------------------------------------ |
|
|
299
385
|
| `screenfull.request(element, options)` | `request(element, options)` |
|
|
300
386
|
| `screenfull.exit()` | `exit()` |
|
|
301
387
|
| `screenfull.toggle(element, options)` | `toggle(element, options)` |
|
|
@@ -323,9 +409,10 @@ if (isEnabled.value) {
|
|
|
323
409
|
}
|
|
324
410
|
```
|
|
325
411
|
|
|
326
|
-
Key differences
|
|
327
|
-
|
|
328
|
-
|
|
412
|
+
Key differences include reactive refs, automatic lifecycle cleanup, SSR-safe imports, structured
|
|
413
|
+
results and errors, optional pseudo-fullscreen, and Vue component and directive APIs. Controller
|
|
414
|
+
listeners receive typed state and errors instead of raw DOM events. Legacy `onchange` and `onerror`
|
|
415
|
+
aliases are not provided. The plugin is optional.
|
|
329
416
|
|
|
330
417
|
## API Reference
|
|
331
418
|
|
|
@@ -337,39 +424,46 @@ Root exports:
|
|
|
337
424
|
- `detectFullscreenApi(document)` and `resolveScreenfullTarget(target, document)`
|
|
338
425
|
- all public target, option, state, result, error, event, component, directive, plugin, and raw-map types
|
|
339
426
|
|
|
340
|
-
|
|
341
|
-
|
|
427
|
+
The `vue-screenfull/browser` subpath exports `createScreenfullController`, `detectFullscreenApi`,
|
|
428
|
+
and only framework-neutral controller types.
|
|
429
|
+
|
|
430
|
+
Actions resolve to `{ ok, mode, element, error }`. The `mode` value is `native`, `fallback`, or
|
|
431
|
+
`none`. Generated TypeDoc is published at
|
|
432
|
+
[chengchuu.github.io/vue-screenfull/api/](https://chengchuu.github.io/vue-screenfull/api/).
|
|
342
433
|
|
|
343
434
|
## Live Playground
|
|
344
435
|
|
|
345
|
-
The deployed playground is at
|
|
346
|
-
|
|
347
|
-
|
|
436
|
+
The deployed playground is available at
|
|
437
|
+
[chengchuu.github.io/vue-screenfull/playground/](https://chengchuu.github.io/vue-screenfull/playground/).
|
|
438
|
+
It includes page, element, image-style, and video targets; explicit exit controls; diagnostics;
|
|
439
|
+
invalid-target feedback; event history; and accessibility, iframe, mobile, and migration notes. Run
|
|
440
|
+
it locally with:
|
|
348
441
|
|
|
349
442
|
```bash
|
|
350
443
|
npm run dev
|
|
351
444
|
```
|
|
352
445
|
|
|
353
|
-
Native fullscreen automation is intentionally not treated as universally reliable because browsers
|
|
446
|
+
Native fullscreen automation is intentionally not treated as universally reliable because browsers
|
|
447
|
+
enforce user activation.
|
|
354
448
|
|
|
355
449
|
## Installable Documentation Website
|
|
356
450
|
|
|
357
|
-
The project website is a Progressive Web App scoped to `/vue-screenfull/`. Its homepage,
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
cache-first storage.
|
|
362
|
-
from both the network and runtime cache.
|
|
451
|
+
The project website is a Progressive Web App scoped to `/vue-screenfull/`. Its homepage, playground,
|
|
452
|
+
and API documentation share a generated manifest and a Google Workbox v7 service worker. Documents,
|
|
453
|
+
scripts, and styles use bounded network-first caches. This strategy normally prioritizes current
|
|
454
|
+
documentation without pairing fresh HTML with stale bundles. Local images and fonts use bounded
|
|
455
|
+
cache-first storage. The site uses a precached offline page only when the requested document is
|
|
456
|
+
unavailable from both the network and the runtime cache.
|
|
363
457
|
|
|
364
|
-
Installation uses the browser's native `beforeinstallprompt` flow when available. The site
|
|
365
|
-
|
|
366
|
-
iOS
|
|
458
|
+
Installation uses the browser's native `beforeinstallprompt` flow when available. The site does not
|
|
459
|
+
open that prompt automatically. In browsers without a custom prompt, use the browser menu or, on
|
|
460
|
+
iOS and iPadOS Safari, **Share → Add to Home Screen**. Installing the website is separate from the
|
|
367
461
|
Fullscreen API and does not grant fullscreen capability.
|
|
368
462
|
|
|
369
463
|
Worker updates remain user-controlled. When a new version is waiting, choose **Update now** to
|
|
370
|
-
activate it and reload the current page once. On the playground, this explicit action
|
|
371
|
-
|
|
372
|
-
|
|
464
|
+
activate it and reload the current page once. On the playground, only this explicit action reloads
|
|
465
|
+
an active session during an update. The generated worker includes a final-artifact version marker,
|
|
466
|
+
so deployable website changes can be detected without precaching unversioned bundles.
|
|
373
467
|
|
|
374
468
|
## Development
|
|
375
469
|
|
|
@@ -392,9 +486,15 @@ npm pack --dry-run
|
|
|
392
486
|
Normal `npm run dev` does not register the production worker. Build `npm run docs` and serve the
|
|
393
487
|
generated `docs` directory from localhost under `/vue-screenfull/` for production-like PWA testing.
|
|
394
488
|
|
|
395
|
-
See `MANUAL_TESTING.md` for the browser matrix and real-browser
|
|
396
|
-
|
|
489
|
+
See [`guides/MANUAL_TESTING.md`](./guides/MANUAL_TESTING.md) for the browser matrix and real-browser
|
|
490
|
+
strategy. The root entry produces `lib/index.cjs.js`, `lib/index.esm.js`, `lib/index.mjs`,
|
|
491
|
+
`lib/vue-screenfull.min.js`, `lib/index.d.ts`, `lib/typing.d.ts`, and `lib/global.d.ts`. The
|
|
492
|
+
framework-neutral entry produces `lib/browser.cjs.js`, `lib/browser.esm.js`, `lib/browser.mjs`,
|
|
493
|
+
`lib/browser.d.ts`, and `lib/vue-screenfull.browser.min.js`. JavaScript bundles include source maps.
|
|
397
494
|
|
|
398
495
|
## License and Attribution
|
|
399
496
|
|
|
400
|
-
Released under the MIT License. This independent project acknowledges
|
|
497
|
+
Released under the MIT License. This independent project acknowledges
|
|
498
|
+
[screenfull](https://github.com/sindresorhus/screenfull) (MIT) for its public API and cross-browser
|
|
499
|
+
compatibility inspiration, and `vue-fullscreen` (MIT) as a Vue ecosystem reference. No endorsement
|
|
500
|
+
is implied.
|
package/README.zh-CN.md
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
- 检测带 WebKit、Mozilla、Microsoft 前缀的 API。
|
|
23
23
|
- 支持 Vue 模板引用、组件引用、元素和安全的 CSS 选择器。
|
|
24
24
|
- 返回结构化结果和可操作的错误,不会静默忽略 Promise 拒绝。
|
|
25
|
-
-
|
|
26
|
-
-
|
|
25
|
+
- 提供无渲染组件、指令、可选插件和框架无关的控制器。
|
|
26
|
+
- 提供适用于 npm、浏览器原生模块和经典脚本的无 Vue 浏览器入口。
|
|
27
27
|
- 提供 CJS、ESM、浏览器 IIFE、源映射和类型声明。
|
|
28
28
|
|
|
29
29
|
## 安装
|
|
@@ -32,7 +32,76 @@
|
|
|
32
32
|
npm install vue-screenfull
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
浏览器包为 `lib/vue-screenfull.min.js`。它会暴露 `VUE_SCREENFULL`,并要求通过全局变量 `Vue` 访问 Vue。
|
|
35
|
+
浏览器包为 `lib/vue-screenfull.min.js`。它会暴露 `VUE_SCREENFULL`,并要求通过全局变量 `Vue` 访问 Vue。Vue 只在软件包安装层面标记为可选。通过软件包根入口导入 API 时,运行时仍需要 Vue 3。
|
|
36
|
+
|
|
37
|
+
### 无 Vue 浏览器入口
|
|
38
|
+
|
|
39
|
+
如果调用方没有 Vue 根实例,请使用 `vue-screenfull/browser`。该子路径只导出 `createScreenfullController`、`detectFullscreenApi` 和框架无关的类型。运行时不会加载 Vue 或 Mazey。
|
|
40
|
+
|
|
41
|
+
通过 npm 使用:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createScreenfullController } from "vue-screenfull/browser";
|
|
45
|
+
|
|
46
|
+
const controller = createScreenfullController({ restoreFocus: true });
|
|
47
|
+
const target = document.querySelector("#player");
|
|
48
|
+
const button = document.querySelector("#toggle-fullscreen");
|
|
49
|
+
const toggle = () => controller.toggle(target);
|
|
50
|
+
|
|
51
|
+
button?.addEventListener("click", toggle);
|
|
52
|
+
|
|
53
|
+
async function dispose() {
|
|
54
|
+
button?.removeEventListener("click", toggle);
|
|
55
|
+
await controller.destroy();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 集成销毁时调用 dispose()。
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
通过浏览器原生 ES 模块使用:
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<script type="module">
|
|
65
|
+
import { createScreenfullController } from "https://cdn.jsdelivr.net/npm/vue-screenfull/lib/browser.mjs";
|
|
66
|
+
|
|
67
|
+
const controller = createScreenfullController();
|
|
68
|
+
const target = document.querySelector("#player");
|
|
69
|
+
const button = document.querySelector("#toggle-fullscreen");
|
|
70
|
+
const toggle = () => controller.toggle(target);
|
|
71
|
+
|
|
72
|
+
button?.addEventListener("click", toggle);
|
|
73
|
+
|
|
74
|
+
async function dispose() {
|
|
75
|
+
button?.removeEventListener("click", toggle);
|
|
76
|
+
await controller.destroy();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 集成销毁时调用 dispose()。
|
|
80
|
+
</script>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
通过经典脚本使用:
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<script src="https://cdn.jsdelivr.net/npm/vue-screenfull/lib/vue-screenfull.browser.min.js"></script>
|
|
87
|
+
<script>
|
|
88
|
+
const controller = VUE_SCREENFULL_BROWSER.createScreenfullController();
|
|
89
|
+
const target = document.querySelector("#player");
|
|
90
|
+
const button = document.querySelector("#toggle-fullscreen");
|
|
91
|
+
const toggle = () => controller.toggle(target);
|
|
92
|
+
|
|
93
|
+
button?.addEventListener("click", toggle);
|
|
94
|
+
|
|
95
|
+
function dispose() {
|
|
96
|
+
button?.removeEventListener("click", toggle);
|
|
97
|
+
return controller.destroy();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 集成销毁时调用 dispose()。
|
|
101
|
+
</script>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
请在点击、键盘或触摸事件处理程序中直接调用 `request` 或 `toggle`。浏览器通常要求短暂的用户激活状态。请保留控制器,并在集成销毁时调用 `destroy()`。该方法会清理监听器和正在运行的 CSS 回退方案。
|
|
36
105
|
|
|
37
106
|
## 浏览器支持
|
|
38
107
|
|
|
@@ -196,10 +265,10 @@ createApp(App).use(VueScreenfull).mount("#app");
|
|
|
196
265
|
|
|
197
266
|
## 高级用法
|
|
198
267
|
|
|
199
|
-
|
|
268
|
+
框架无关的控制器适用于迁移和非组件集成:
|
|
200
269
|
|
|
201
270
|
```ts
|
|
202
|
-
import { createScreenfullController } from "vue-screenfull";
|
|
271
|
+
import { createScreenfullController } from "vue-screenfull/browser";
|
|
203
272
|
|
|
204
273
|
const controller = createScreenfullController({ restoreFocus: true });
|
|
205
274
|
const onChange = (state) => console.log(state.isFullscreen, state.element);
|
|
@@ -313,6 +382,8 @@ if (isEnabled.value) {
|
|
|
313
382
|
|
|
314
383
|
操作会解析为 `{ ok, mode, element, error }`。`mode` 为 `native`、`fallback` 或 `none`。生成的 TypeDoc 发布于 [API 文档网站](https://chengchuu.github.io/vue-screenfull/api/)。
|
|
315
384
|
|
|
385
|
+
`vue-screenfull/browser` 子路径只导出 `createScreenfullController`、`detectFullscreenApi` 和框架无关的控制器类型。
|
|
386
|
+
|
|
316
387
|
## 在线演练场
|
|
317
388
|
|
|
318
389
|
已部署的版本位于 [vue-screenfull 在线演练场](https://chengchuu.github.io/vue-screenfull/playground/)。其中包含页面、元素、图片样式和视频目标。它还提供显式退出、诊断、无效目标反馈和事件历史记录。其他内容包括无障碍、iframe、移动端和迁移说明。使用以下命令在本地运行:
|
|
@@ -351,16 +422,25 @@ npm pack --dry-run
|
|
|
351
422
|
|
|
352
423
|
常规的 `npm run dev` 不会注册生产环境 Worker。若要在类似生产环境中测试 PWA,请运行 `npm run docs`。然后在 localhost 的 `/vue-screenfull/` 路径下提供生成的 `docs` 目录。
|
|
353
424
|
|
|
354
|
-
有关浏览器矩阵和真实浏览器测试策略,请参阅 `MANUAL_TESTING.md
|
|
425
|
+
有关浏览器矩阵和真实浏览器测试策略,请参阅 [`guides/MANUAL_TESTING.md`](./guides/MANUAL_TESTING.md)。根入口会生成以下文件:
|
|
355
426
|
|
|
356
427
|
- `lib/index.cjs.js`
|
|
357
428
|
- `lib/index.esm.js`
|
|
429
|
+
- `lib/index.mjs`
|
|
358
430
|
- `lib/vue-screenfull.min.js`
|
|
359
431
|
- `lib/index.d.ts`
|
|
360
432
|
- `lib/typing.d.ts`
|
|
361
433
|
- `lib/global.d.ts`
|
|
362
434
|
|
|
363
|
-
|
|
435
|
+
框架无关的入口会生成以下文件:
|
|
436
|
+
|
|
437
|
+
- `lib/browser.cjs.js`
|
|
438
|
+
- `lib/browser.esm.js`
|
|
439
|
+
- `lib/browser.mjs`
|
|
440
|
+
- `lib/browser.d.ts`
|
|
441
|
+
- `lib/vue-screenfull.browser.min.js`
|
|
442
|
+
|
|
443
|
+
JavaScript 软件包会包含源映射。
|
|
364
444
|
|
|
365
445
|
## 许可证与致谢
|
|
366
446
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* vue-screenfull v1.1.0
|
|
3
|
+
* (c) 2018-2026 Cheng https://www.npmjs.com/package/vue-screenfull
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
"use strict";function e(e,n){(null==n||n>e.length)&&(n=e.length);for(var r=0,t=Array(n);r<n;r++)t[r]=e[r];return t}function n(e,n,r){return n&&function(e,n){for(var r=0;r<n.length;r++){var t=n[r];t.enumerable=t.enumerable||!1,t.configurable=!0,"value"in t&&(t.writable=!0),Object.defineProperty(e,o(t.key),t)}}(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),e}function r(){var e,n,l="function"==typeof Symbol?Symbol:{},o=l.iterator||"@@iterator",i=l.toStringTag||"@@toStringTag";function u(r,l,o,i){var u=l&&l.prototype instanceof c?l:c,s=Object.create(u.prototype);return t(s,"_invoke",function(r,t,l){var o,i,u,c=0,s=l||[],f=!1,d={p:0,n:0,v:e,a:v,f:v.bind(e,4),d:function(n,r){return o=n,i=0,u=e,d.n=r,a}};function v(r,t){for(i=r,u=t,n=0;!f&&c&&!l&&n<s.length;n++){var l,o=s[n],v=d.p,h=o[2];r>3?(l=h===t)&&(u=o[(i=o[4])?5:(i=3,3)],o[4]=o[5]=e):o[0]<=v&&((l=r<2&&v<o[1])?(i=0,d.v=t,d.n=o[1]):v<h&&(l=r<3||o[0]>t||t>h)&&(o[4]=r,o[5]=t,d.n=h,i=0))}if(l||r>1)return a;throw f=!0,t}return function(l,s,h){if(c>1)throw TypeError("Generator is already running");for(f&&1===s&&v(s,h),i=s,u=h;(n=i<2?e:u)||!f;){o||(i?i<3?(i>1&&(d.n=-1),v(i,u)):d.n=u:d.v=u);try{if(c=2,o){if(i||(l="next"),n=o[l]){if(!(n=n.call(o,u)))throw TypeError("iterator result is not an object");if(!n.done)return n;u=n.value,i<2&&(i=0)}else 1===i&&(n=o.return)&&n.call(o),i<2&&(u=TypeError("The iterator does not provide a '"+l+"' method"),i=1);o=e}else if((n=(f=d.n<0)?u:r.call(t,d))!==a)break}catch(n){o=e,i=1,u=n}finally{c=1}}return{value:n,done:f}}}(r,o,i),!0),s}var a={};function c(){}function s(){}function f(){}n=Object.getPrototypeOf;var d=[][o]?n(n([][o]())):(t(n={},o,function(){return this}),n),v=f.prototype=c.prototype=Object.create(d);function h(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,f):(e.__proto__=f,t(e,i,"GeneratorFunction")),e.prototype=Object.create(v),e}return s.prototype=f,t(v,"constructor",f),t(f,"constructor",s),s.displayName="GeneratorFunction",t(f,i,"GeneratorFunction"),t(v),t(v,i,"Generator"),t(v,o,function(){return this}),t(v,"toString",function(){return"[object Generator]"}),(r=function(){return{w:u,m:h}})()}function t(e,n,r,l){var o=Object.defineProperty;try{o({},"",{})}catch(e){o=0}t=function(e,n,r,l){function i(n,r){t(e,n,function(e){return this._invoke(n,r,e)})}n?o?o(e,n,{value:r,enumerable:!l,configurable:!l,writable:!l}):e[n]=r:(i("next",0),i("throw",1),i("return",2))},t(e,n,r,l)}function l(n,r){return function(e){if(Array.isArray(e))return e}(n)||function(e,n){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var t,l,o,i,u=[],a=!0,c=!1;try{if(o=(r=r.call(e)).next,0===n);else for(;!(a=(t=o.call(r)).done)&&(u.push(t.value),u.length!==n);a=!0);}catch(e){c=!0,l=e}finally{try{if(!a&&null!=r.return&&(i=r.return(),Object(i)!==i))return}finally{if(c)throw l}}return u}}(n,r)||function(n,r){if(n){if("string"==typeof n)return e(n,r);var t={}.toString.call(n).slice(8,-1);return"Object"===t&&n.constructor&&(t=n.constructor.name),"Map"===t||"Set"===t?Array.from(n):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?e(n,r):void 0}}(n,r)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(e){var n=function(e,n){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var t=r.call(e,n);if("object"!=typeof t)return t;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e,"string");return"symbol"==typeof n?n:n+""}function i(e,n,r,t){return new(r||(r=Promise))(function(l,o){function i(e){try{a(t.next(e))}catch(e){o(e)}}function u(e){try{a(t.throw(e))}catch(e){o(e)}}function a(e){var n;e.done?l(e.value):(n=e.value,n instanceof r?n:new r(function(e){e(n)})).then(i,u)}a((t=t.apply(e,n||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;var u=[{requestFullscreen:"requestFullscreen",exitFullscreen:"exitFullscreen",fullscreenElement:"fullscreenElement",fullscreenEnabled:"fullscreenEnabled",fullscreenchange:"fullscreenchange",fullscreenerror:"fullscreenerror"},{requestFullscreen:"webkitRequestFullscreen",exitFullscreen:"webkitExitFullscreen",fullscreenElement:"webkitFullscreenElement",fullscreenEnabled:"webkitFullscreenEnabled",fullscreenchange:"webkitfullscreenchange",fullscreenerror:"webkitfullscreenerror"},{requestFullscreen:"webkitRequestFullScreen",exitFullscreen:"webkitCancelFullScreen",fullscreenElement:"webkitCurrentFullScreenElement",fullscreenEnabled:"webkitCancelFullScreen",fullscreenchange:"webkitfullscreenchange",fullscreenerror:"webkitfullscreenerror"},{requestFullscreen:"mozRequestFullScreen",exitFullscreen:"mozCancelFullScreen",fullscreenElement:"mozFullScreenElement",fullscreenEnabled:"mozFullScreenEnabled",fullscreenchange:"mozfullscreenchange",fullscreenerror:"mozfullscreenerror"},{requestFullscreen:"msRequestFullscreen",exitFullscreen:"msExitFullscreen",fullscreenElement:"msFullscreenElement",fullscreenEnabled:"msFullscreenEnabled",fullscreenchange:"MSFullscreenChange",fullscreenerror:"MSFullscreenError"}];function a(e){var n=e.documentElement,r=e,t=u.find(function(e){return"function"==typeof n[e.requestFullscreen]&&"function"==typeof r[e.exitFullscreen]});return t?Object.freeze(Object.assign({},t)):null}var c=["position","inset","top","right","bottom","left","width","height","max-width","max-height","margin","z-index","overflow","background"],s=new WeakMap,f=/*#__PURE__*/function(){return n(function e(){!function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this,e),this.element=null,this.styles=null,this.bodyOverflow={value:"",priority:""},this.scrollX=0,this.scrollY=0,this.className="",this.addedClass=!1,this.lockedScroll=!1,this.bodyScrollLocked=!1},[{key:"enter",value:function(e){var n,r,t,o,i,u,a,f,d,v,h=e.element,b=e.document,m=e.options,y=null===(n=b.defaultView)||void 0===n?void 0:n.HTMLElement;if(!(y&&h instanceof y))throw new TypeError("CSS fallback requires an HTMLElement.");var p=s.get(b);if(p&&p!==this)throw new Error("Another CSS fullscreen fallback is already active.");s.set(b,this);try{this.element=h,this.className=null!==(r=m.fallbackClass)&&void 0!==r?r:"vue-screenfull-fallback",this.styles={};for(var E=0,k=c;E<k.length;E++){var g=k[E];this.styles[g]={value:this.element.style.getPropertyValue(g),priority:this.element.style.getPropertyPriority(g)}}this.bodyOverflow={value:null!==(o=null===(t=b.body)||void 0===t?void 0:t.style.getPropertyValue("overflow"))&&void 0!==o?o:"",priority:null!==(u=null===(i=b.body)||void 0===i?void 0:i.style.getPropertyPriority("overflow"))&&void 0!==u?u:""},this.scrollX=null!==(f=null===(a=b.defaultView)||void 0===a?void 0:a.scrollX)&&void 0!==f?f:0,this.scrollY=null!==(v=null===(d=b.defaultView)||void 0===d?void 0:d.scrollY)&&void 0!==v?v:0;for(var w=[["position","fixed"],["inset","0"],["top","0"],["right","0"],["bottom","0"],["left","0"],["width","100vw"],["height","100dvh"],["max-width","none"],["max-height","none"],["margin","0"],["z-index","2147483647"],["overflow","auto"],["background",this.element.style.background||"Canvas"]],S=0,F=w;S<F.length;S++){var O=l(F[S],2),T=O[0],R=O[1];this.element.style.setProperty(T,R,"important")}this.addedClass=!this.element.classList.contains(this.className),this.addedClass&&this.element.classList.add(this.className),this.lockedScroll=!1!==m.lockScroll,this.bodyScrollLocked=Boolean(this.lockedScroll&&b.body&&this.element!==b.documentElement&&this.element!==b.body),this.bodyScrollLocked&&b.body&&b.body.style.setProperty("overflow","hidden","important")}catch(e){try{this.exit({element:h,document:b,options:m})}finally{s.get(b)===this&&s.delete(b)}throw e}}},{key:"exit",value:function(e){var n,r,t=e.document;if(this.element&&this.styles)try{for(var l=0,o=c;l<o.length;l++){var i=o[l],u=this.styles[i];u.value?this.element.style.setProperty(i,u.value,u.priority):this.element.style.removeProperty(i)}this.addedClass&&this.element.classList.remove(this.className),this.bodyScrollLocked&&t.body&&(this.bodyOverflow.value?t.body.style.setProperty("overflow",this.bodyOverflow.value,this.bodyOverflow.priority):t.body.style.removeProperty("overflow")),this.lockedScroll&&(null===(r=null===(n=t.defaultView)||void 0===n?void 0:n.scrollTo)||void 0===r||r.call(n,this.scrollX,this.scrollY))}finally{s.get(t)===this&&s.delete(t),this.element=null,this.styles=null,this.addedClass=!1,this.lockedScroll=!1,this.bodyScrollLocked=!1}}}])}();function d(e){return e.fallback&&"none"!==e.fallback?"css"===e.fallback?new f:e.fallback:null}var v={NOT_SUPPORTED:"Enable the CSS fallback or use a browser with the Fullscreen API.",NOT_IN_BROWSER:"Call fullscreen actions after the component mounts in a browser.",USER_ACTIVATION_REQUIRED:"Call request() directly from a click, key, or touch handler.",PERMISSION_DENIED:"Check browser settings and the document Permissions Policy.",IFRAME_PERMISSION_REQUIRED:'Add allow="fullscreen" and allowfullscreen to the embedding iframe.',TARGET_NOT_CONNECTED:"Attach the target element to the current document before requesting fullscreen.",REQUEST_IN_PROGRESS:"Wait for the current fullscreen transition to finish."};function h(e,n,r){return{code:e,message:n,cause:r,recoverable:!(arguments.length>3&&void 0!==arguments[3])||arguments[3],suggestion:v[e]}}function b(e,n,r){var t,l=e instanceof Error?"".concat(e.name,": ").concat(e.message):String(e),o=l.toLowerCase(),i="exit"===n?"EXIT_FAILED":"fallback"===n?"FALLBACK_FAILED":"REQUEST_FAILED";if(o.includes("activation")||o.includes("gesture"))i="USER_ACTIVATION_REQUIRED";else if(o.includes("permission")||o.includes("denied")||o.includes("security")){var u;try{u=Boolean(null===(t=null==r?void 0:r.defaultView)||void 0===t?void 0:t.frameElement)}catch(e){u=!0}i=u?"IFRAME_PERMISSION_REQUIRED":"PERMISSION_DENIED"}return h(i,"Fullscreen ".concat(n," failed: ").concat(l),e)}var m=function(e,n){return{ok:!0,mode:e,element:n,error:null}};exports.createScreenfullController=function(){var e,n,t=this,l=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},o=null!==(e=l.document)&&void 0!==e?e:"undefined"==typeof document?void 0:document,u=o?a(o):null,c=new Set,s=new Set,f=d(l),v=null,y=l,p=null,E=!1,k=!1,g=null,w=o?"idle":"unsupported",S=function(){return o&&u?o[u.fullscreenElement]:null},F=function(){return{isEnabled:Boolean(o&&u&&!1!==o[u.fullscreenEnabled]),isFullscreen:Boolean(S()||v),isFallback:Boolean(v),element:S()||v,status:w}},O=function(e,n){if(e)try{e(n)}catch(e){"undefined"!=typeof console&&console.error("[vue-screenfull] Listener failed.",e)}},T=null,R=F().isFullscreen,x=function(){var e=F();T&&T.isEnabled===e.isEnabled&&T.isFullscreen===e.isFullscreen&&T.isFallback===e.isFallback&&T.status===e.status&&T.element===e.element||(T=e,O(l.onChange,e),c.forEach(function(n){return O(n,e)}))},_=function(e){return g=e,arguments.length>1&&void 0!==arguments[1]&&arguments[1]||(w="NOT_SUPPORTED"===e.code||"NOT_IN_BROWSER"===e.code?"unsupported":"error"),k||(O(l.onError,e),s.forEach(function(n){return O(n,e)}),x()),l.debug&&"undefined"!=typeof console&&console.warn("[vue-screenfull]",e),{ok:!1,mode:"none",element:F().element,error:e}},I=function(){w=S()?"fullscreen":"idle";var e=F();e.isFullscreen!==R&&(e.isFullscreen?O(l.onEnter,e):O(l.onExit,e),R=e.isFullscreen),x()},P=function(e){E||_(b(e,"request",o))},N=function(e){"Escape"===e.key&&v&&D.exit()},C=function(){F().isFullscreen&&D.exit()},L=function(){var e,n,r=!1,t=new Promise(function(e){n=e}),l=function(){o&&u&&(o.removeEventListener(u.fullscreenchange,a),o.removeEventListener(u.fullscreenerror,c),void 0!==e&&globalThis.clearTimeout(e))},i=function(e){r||(r=!0,l(),n(e))},a=function(){return i({ok:!0})},c=function(e){return i({ok:!1,cause:e})};return o&&u&&(o.addEventListener(u.fullscreenchange,a),o.addEventListener(u.fullscreenerror,c),e=globalThis.setTimeout(function(){return i({ok:!1,cause:new Error("Timed out waiting for a fullscreen event.")})},3e3)),{promise:t,cleanup:l}},A=function(e){return i(t,void 0,void 0,/*#__PURE__*/r().m(function n(){var t,l,o;return r().w(function(n){for(;;)switch(n.p=n.n){case 0:if(t=L(),n.p=1,!(l=e())||"function"!=typeof l.then){n.n=3;break}return n.n=2,l;case 2:n.n=5;break;case 3:return n.n=4,t.promise;case 4:if((o=n.v).ok){n.n=5;break}throw o.cause;case 5:return n.p=5,t.cleanup(),n.f(5);case 6:return n.a(2)}},n,null,[[1,,5,6]])}))},q=function(){return i(t,void 0,void 0,/*#__PURE__*/r().m(function e(){var n;return r().w(function(e){for(;;)switch(e.n){case 0:if(o&&u&&S()){e.n=1;break}return e.a(2);case 1:return n=o[u.exitFullscreen],e.n=2,A(function(){return n.call(o)});case 2:return e.a(2)}},e)}))};function j(e,n){return i(this,void 0,void 0,/*#__PURE__*/r().m(function t(){var i,u,a,c,s,p;return r().w(function(r){for(;;)switch(r.p=r.n){case 0:if(u=null!==(i=null==n?void 0:n.fallback)&&void 0!==i?i:l.fallback,a=Object.assign(Object.assign({},l),{fallback:u}),f=d(a),o&&f){r.n=1;break}return r.a(2,_(h("NOT_SUPPORTED","The Fullscreen API is unavailable and no fallback is enabled.")));case 1:return r.p=1,y=a,r.n=2,f.enter({element:e,document:o,options:a});case 2:if(!k){r.n=4;break}return r.n=3,f.exit({element:e,document:o,options:a});case 3:return c=h("REQUEST_FAILED","The fullscreen controller was destroyed before the fallback request completed."),r.a(2,{ok:!1,mode:"none",element:null,error:c});case 4:return v=e,w="fallback",s=F(),R=!0,O(l.onFallback,s),O(l.onEnter,s),x(),r.a(2,m("fallback",e));case 5:return r.p=5,p=r.v,r.a(2,_(b(p,"fallback",o)))}},t,null,[[1,5]])}))}o&&u&&(o.addEventListener(u.fullscreenchange,I),o.addEventListener(u.fullscreenerror,P)),o&&(o.addEventListener("keydown",N),l.exitOnRouteChange&&(null===(n=o.defaultView)||void 0===n||n.addEventListener("popstate",C)));var D={get isEnabled(){return F().isEnabled},get isFullscreen(){return F().isFullscreen},get isFallback(){return F().isFallback},get element(){return F().element},get status(){return w},get error(){return g},get raw(){return u},request:function(e,n){return i(this,void 0,void 0,/*#__PURE__*/r().m(function t(){var i,a,c,s,f,d,y,g;return r().w(function(r){for(;;)switch(r.p=r.n){case 0:if(!k&&o){r.n=1;break}return r.a(2,_(h("NOT_IN_BROWSER","Fullscreen is unavailable outside a browser document.")));case 1:if(!E){r.n=2;break}return r.a(2,_(h("REQUEST_IN_PROGRESS","A fullscreen transition is already in progress."),!0));case 2:if((i=void 0===e?o.documentElement:e)&&1===i.nodeType){r.n=3;break}return r.a(2,_(h("INVALID_TARGET","The fullscreen target is not an Element.")));case 3:if(i.isConnected&&i.ownerDocument===o){r.n=4;break}return r.a(2,_(h("TARGET_NOT_CONNECTED","The fullscreen target must be connected to the current document.")));case 4:if(!F().isFullscreen){r.n=7;break}if(F().element!==i){r.n=5;break}return r.a(2,m(v?"fallback":"native",i));case 5:if(!v){r.n=7;break}return r.n=6,D.exit();case 6:if((a=r.v).ok){r.n=7;break}return r.a(2,a);case 7:if(p=!1===l.restoreFocus?null:o.activeElement,E=!0,w="requesting",x(),r.p=8,u&&D.isEnabled){r.n=10;break}return r.n=9,j(i,n);case 9:case 18:return r.a(2,r.v);case 10:return c=i[u.requestFullscreen],delete(s=Object.assign({},n)).fallback,r.n=11,A(function(){return c.call(i,s)});case 11:return k||(w=S()?"fullscreen":"idle",x()),r.a(2,m("native",S()||i));case 12:if(r.p=12,y=r.v,!k){r.n=13;break}return f=b(y,"request",o),r.a(2,{ok:!1,mode:"none",element:null,error:f});case 13:if(d=b(y,"request",o),!(null==n?void 0:n.fallback)&&!l.fallback){r.n=19;break}if(!S()){r.n=17;break}return r.p=14,r.n=15,q();case 15:r.n=17;break;case 16:return r.p=16,g=r.v,r.a(2,_(b(g,"exit",o)));case 17:return r.n=18,j(i,n);case 19:return r.a(2,_(d));case 20:return r.p=20,E=!1,r.f(20);case 21:return r.a(2)}},t,null,[[14,16],[8,12,20,21]])}))},exit:function(){return i(this,void 0,void 0,/*#__PURE__*/r().m(function e(){var n,t,i,a;return r().w(function(e){for(;;)switch(e.p=e.n){case 0:if(!k&&o){e.n=1;break}return e.a(2,_(h("NOT_IN_BROWSER","Fullscreen is unavailable outside a browser document.")));case 1:if(!E){e.n=2;break}return e.a(2,_(h("REQUEST_IN_PROGRESS","A fullscreen transition is already in progress."),!0));case 2:if(F().isFullscreen){e.n=3;break}return e.a(2,m("native",null));case 3:if(E=!0,w="exiting",x(),e.p=4,!v||!f){e.n=6;break}return t=v,e.n=5,f.exit({element:t,document:o,options:y});case 5:v=null,w="idle",i=F(),R=!1,O(l.onExit,i),x(),e.n=8;break;case 6:if(!u||!S()){e.n=8;break}return e.n=7,q();case 7:w=S()?"fullscreen":"idle",x();case 8:return null===(n=null==p?void 0:p.focus)||void 0===n||n.call(p),p=null,e.a(2,m(v?"fallback":"native",F().element));case 9:return e.p=9,a=e.v,e.a(2,_(b(a,"exit",o)));case 10:return e.p=10,E=!1,e.f(10);case 11:return e.a(2)}},e,null,[[4,9,10,11]])}))},toggle:function(e,n){return i(this,void 0,void 0,/*#__PURE__*/r().m(function t(){return r().w(function(r){for(;;)if(0===r.n)return r.a(2,F().isFullscreen?D.exit():D.request(e,n))},t)}))},on:function(e,n){"change"===e?c.add(n):s.add(n)},off:function(e,n){"change"===e?c.delete(n):s.delete(n)},clearError:function(){g=null,"error"===w&&(w=F().isFullscreen?v?"fallback":"fullscreen":"idle"),x()},destroy:function(){return i(this,void 0,void 0,/*#__PURE__*/r().m(function e(){var n,t,i;return r().w(function(e){for(;;)switch(e.p=e.n){case 0:if(!k){e.n=1;break}return e.a(2);case 1:if(k=!0,!(v&&f&&o)){e.n=6;break}return t=v,e.p=2,e.n=3,f.exit({element:t,document:o,options:y});case 3:e.n=5;break;case 4:e.p=4,i=e.v,g=b(i,"fallback",o);case 5:v=null;case 6:o&&u&&(o.removeEventListener(u.fullscreenchange,I),o.removeEventListener(u.fullscreenerror,P)),null==o||o.removeEventListener("keydown",N),l.exitOnRouteChange&&(null===(n=null==o?void 0:o.defaultView)||void 0===n||n.removeEventListener("popstate",C)),c.clear(),s.clear();case 7:return e.a(2)}},e,null,[[2,4]])}))}};return D},exports.detectFullscreenApi=a;
|
|
7
|
+
//# sourceMappingURL=browser.cjs.js.map
|