vue-screenfull 1.0.1 → 1.0.4
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/LICENSE +1 -1
- package/MANUAL_TESTING.md +32 -0
- package/README.md +355 -19
- package/lib/global.d.ts +31 -0
- package/lib/index.cjs.js +7 -30
- package/lib/index.cjs.js.map +1 -0
- package/lib/index.d.ts +229 -5
- package/lib/index.esm.js +7 -26
- package/lib/index.esm.js.map +1 -0
- package/lib/index.mjs +7 -0
- package/lib/index.mjs.map +1 -0
- package/lib/typing.d.ts +123 -0
- package/lib/vue-screenfull.min.js +7 -0
- package/lib/vue-screenfull.min.js.map +1 -0
- package/package.json +88 -61
- package/index.js +0 -0
- package/lib/example.d.ts +0 -2
- package/lib/example.d.ts.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/src/example.html +0 -15
- package/src/example.ts +0 -7
- package/src/index.ts +0 -34
- package/tsconfig.json +0 -79
- package/typing.d.ts +0 -5
package/LICENSE
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Browser testing strategy and manual matrix
|
|
2
|
+
|
|
3
|
+
Automated unit tests cover property mapping, state, errors, cleanup, targets, Vue integration, and
|
|
4
|
+
fallback. Real-browser smoke tests should load `/playground/`, verify capability diagnostics, and
|
|
5
|
+
exercise a request from a genuine click. Native fullscreen is not made a hard headless-CI assertion:
|
|
6
|
+
Chromium, Firefox, and WebKit automation can reject it when user activation or the host display is
|
|
7
|
+
unavailable.
|
|
8
|
+
|
|
9
|
+
Record the date, browser/OS version, native availability, page/element/video targets, change event,
|
|
10
|
+
Escape/visible-button exit, browser UI, iframe result, fallback result, and limitation for each row.
|
|
11
|
+
An unchecked row is a documented target, not a tested claim.
|
|
12
|
+
|
|
13
|
+
| Environment | Native | Element | Events/exit | Fallback | Last verified / notes |
|
|
14
|
+
| ----------------- | ------ | ------- | ----------- | -------- | ------------------------------------------------------------- |
|
|
15
|
+
| Windows + Chrome | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
16
|
+
| Windows + Edge | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
17
|
+
| Windows + Firefox | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
18
|
+
| macOS + Safari | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
19
|
+
| macOS + Chrome | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
20
|
+
| macOS + Firefox | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
21
|
+
| Android + Chrome | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
22
|
+
| Android + Firefox | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
23
|
+
| Samsung Internet | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
24
|
+
| iPadOS + Safari | ☐ | ☐ | ☐ | ☐ | Not manually verified |
|
|
25
|
+
| iPhone + Safari | ☐ | ☐ | ☐ | ☐ | Expect arbitrary-element restrictions; verify current release |
|
|
26
|
+
| Android WebView | ☐ | ☐ | ☐ | ☐ | Host settings affect support |
|
|
27
|
+
| iOS WKWebView | ☐ | ☐ | ☐ | ☐ | Host settings and iOS release affect support |
|
|
28
|
+
|
|
29
|
+
For iframe checks, test both an allowed iframe (`allow="fullscreen" allowfullscreen`) and one without
|
|
30
|
+
permission. Confirm errors are visible, focus returns after library-driven exit, fallback restores
|
|
31
|
+
inline styles/body scroll, navigation and app switching do not leave stale state, and an accessible
|
|
32
|
+
exit remains keyboard/touch reachable.
|
package/README.md
CHANGED
|
@@ -1,40 +1,376 @@
|
|
|
1
|
-
#
|
|
1
|
+
# vue-screenfull
|
|
2
2
|
|
|
3
|
-
[![
|
|
4
|
-
[![
|
|
3
|
+
[![npm version][npm-version-image]][npm-url]
|
|
4
|
+
[![license][license-image]][license-url]
|
|
5
5
|
|
|
6
|
-
[npm-image]: https://img.shields.io/npm/v/vue-screenfull
|
|
7
|
-
[npm-url]: https://npmjs.
|
|
8
|
-
[
|
|
9
|
-
[
|
|
6
|
+
[npm-version-image]: https://img.shields.io/npm/v/vue-screenfull.svg
|
|
7
|
+
[npm-url]: https://www.npmjs.com/package/vue-screenfull
|
|
8
|
+
[license-image]: https://img.shields.io/npm/l/vue-screenfull.svg
|
|
9
|
+
[license-url]: https://github.com/chengchuu/vue-screenfull/blob/main/LICENSE
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Reactive, strongly typed, SSR-safe fullscreen utilities designed for Vue 3.
|
|
12
|
+
The library uses the browser Fullscreen API when available and can optionally provide an explicitly labelled CSS pseudo-fullscreen fallback.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
- [Project website](https://chengchuu.github.io/vue-screenfull/)
|
|
15
|
+
- [Live playground](https://chengchuu.github.io/vue-screenfull/playground/)
|
|
16
|
+
- [API documentation](https://chengchuu.github.io/vue-screenfull/api/)
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
## Features
|
|
16
19
|
|
|
20
|
+
- Reactive Composition API state with automatic scope cleanup.
|
|
21
|
+
- Standard, WebKit, Mozilla, and Microsoft-prefixed API detection.
|
|
22
|
+
- Vue template refs, component refs, elements, and safe CSS selectors.
|
|
23
|
+
- Structured results and actionable errors instead of swallowed rejections.
|
|
24
|
+
- Renderless component, directive, optional plugin, and framework-light controller.
|
|
25
|
+
- No fullscreen wrapper or other runtime dependency; Vue remains a peer dependency.
|
|
26
|
+
- CJS, ESM, browser IIFE, source maps, and declarations.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install vue-screenfull
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The browser bundle is `lib/vue-screenfull.min.js`, exposes `VUE_SCREENFULL`, and expects Vue to be available as the global `Vue`.
|
|
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.
|
|
45
|
+
|
|
46
|
+
## Basic Usage
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<script setup lang="ts">
|
|
50
|
+
import { useTemplateRef } from "vue";
|
|
51
|
+
import { useScreenfull } from "vue-screenfull";
|
|
52
|
+
|
|
53
|
+
const target = useTemplateRef<HTMLElement>("target");
|
|
54
|
+
const { isEnabled, isFullscreen, error, toggle } = useScreenfull();
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<template>
|
|
58
|
+
<section ref="target">
|
|
59
|
+
<p>Fullscreen content</p>
|
|
60
|
+
<button type="button" :disabled="!isEnabled" @click="toggle(target)">
|
|
61
|
+
{{ isFullscreen ? "Exit fullscreen" : "Enter fullscreen" }}
|
|
62
|
+
</button>
|
|
63
|
+
<p v-if="error" role="alert">{{ error.message }}</p>
|
|
64
|
+
</section>
|
|
65
|
+
</template>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Call `request` or `toggle` directly inside a click, keyboard, or touch handler.
|
|
69
|
+
Browsers normally require transient user activation and can reject even when `isEnabled.value` is true.
|
|
70
|
+
|
|
71
|
+
## Fullscreen a Specific Element
|
|
72
|
+
|
|
73
|
+
```vue
|
|
74
|
+
<script setup lang="ts">
|
|
75
|
+
import { useTemplateRef } from "vue";
|
|
76
|
+
import { useScreenfullTarget } from "vue-screenfull";
|
|
77
|
+
const panel = useTemplateRef<HTMLElement>("panel");
|
|
78
|
+
const { request, isFullscreen } = useScreenfullTarget(panel);
|
|
79
|
+
</script>
|
|
80
|
+
<template>
|
|
81
|
+
<section ref="panel">
|
|
82
|
+
<button type="button" @click="request()">Open panel</button>
|
|
83
|
+
<span>Active: {{ isFullscreen }}</span>
|
|
84
|
+
</section>
|
|
85
|
+
</template>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`useScreenfull().request()` with no target opens `document.documentElement`.
|
|
89
|
+
A selector such as `request("#player")` is resolved with `document.querySelector`; invalid or unmatched selectors return `INVALID_TARGET`.
|
|
90
|
+
|
|
91
|
+
## Toggle Fullscreen
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
const result = await toggle(target, { navigationUI: "hide" });
|
|
95
|
+
if (!result.ok) console.warn(result.error.code, result.error.suggestion);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
For image content, pass the image template ref. For a video, pass an `HTMLVideoElement` ref.
|
|
99
|
+
Some mobile browsers offer video-only fullscreen independently of arbitrary-element fullscreen.
|
|
100
|
+
|
|
101
|
+
## Exit Fullscreen
|
|
102
|
+
|
|
103
|
+
```vue
|
|
104
|
+
<button type="button" @click="exit">Exit fullscreen</button>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Always include a visible exit button, particularly when fallback is enabled. Escape often exits,
|
|
108
|
+
but browser Escape behavior cannot be overridden reliably. Exits initiated by browser UI are reflected through native change events.
|
|
109
|
+
|
|
110
|
+
## Check Support
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
const { isEnabled, status } = useScreenfull();
|
|
114
|
+
// isEnabled.value: native API currently enabled
|
|
115
|
+
// status.value: idle | requesting | fullscreen | exiting | fallback | unsupported | error
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Feature detection is more reliable than user-agent checks across Safari, iOS/iPadOS, and WebViews.
|
|
119
|
+
|
|
120
|
+
## Handle Errors
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
const result = await request(target);
|
|
124
|
+
if (!result.ok) {
|
|
125
|
+
console.error(
|
|
126
|
+
result.error.code,
|
|
127
|
+
result.error.message,
|
|
128
|
+
result.error.suggestion,
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Errors distinguish unsupported/SSR environments, invalid or detached targets, user activation,
|
|
134
|
+
permissions and iframe policy, pending transitions, native request/exit failures, and fallback
|
|
135
|
+
failures. `error` keeps the last error until `clearError()` is called.
|
|
136
|
+
|
|
137
|
+
## CSS Fallback
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
const { request, exit, isFallback } = useScreenfull({
|
|
141
|
+
fallback: "css",
|
|
142
|
+
fallbackClass: "my-pseudo-fullscreen",
|
|
143
|
+
lockScroll: true,
|
|
144
|
+
restoreFocus: true,
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
CSS fallback fixes an `HTMLElement` to the visual viewport, preserves every inline style it changes,
|
|
149
|
+
locks and restores body scrolling, preserves the scroll position, adds the configured class,
|
|
150
|
+
exits on Escape when possible, and restores focus. Cleanup also runs when its Vue scope is disposed.
|
|
151
|
+
It is pseudo-fullscreen: it cannot hide address bars, browser controls, notifications,
|
|
152
|
+
or operating-system UI. Keep an accessible exit button inside the target:
|
|
153
|
+
|
|
154
|
+
```vue
|
|
155
|
+
<button type="button" @click="exit">Close full-page view</button>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
A custom fallback implements `enter(context)` and `exit(context)` and is responsible for complete cleanup.
|
|
159
|
+
|
|
160
|
+
## Component Usage
|
|
161
|
+
|
|
162
|
+
```vue
|
|
163
|
+
<Screenfull
|
|
164
|
+
target="#article"
|
|
165
|
+
fallback="css"
|
|
166
|
+
v-slot="screenfull"
|
|
167
|
+
@error="report"
|
|
168
|
+
>
|
|
169
|
+
<button type="button" @click="screenfull.toggle()">
|
|
170
|
+
{{ screenfull.isFullscreen ? "Exit" : "Open article" }}
|
|
171
|
+
</button>
|
|
172
|
+
<button v-if="screenfull.isFullscreen" type="button" @click="screenfull.exit">Exit</button>
|
|
173
|
+
</Screenfull>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The renderless component emits `change`, `enter`, `exit`, `error`, and `fallback`.
|
|
177
|
+
Its default slot receives all composable refs and actions; it imposes no visual system.
|
|
178
|
+
|
|
179
|
+
## Directive Usage
|
|
180
|
+
|
|
181
|
+
```vue
|
|
182
|
+
<button v-screenfull>Fullscreen page</button>
|
|
183
|
+
<button v-screenfull="target">Toggle target</button>
|
|
184
|
+
<button v-screenfull:request="target">Enter target</button>
|
|
185
|
+
<button v-screenfull:exit>Exit</button>
|
|
186
|
+
<button
|
|
187
|
+
v-screenfull="{ target, action: 'toggle', options: { navigationUI: 'hide' } }"
|
|
188
|
+
>Toggle</button>
|
|
17
189
|
```
|
|
18
|
-
|
|
190
|
+
|
|
191
|
+
Only `request`, `exit`, and `toggle` arguments are supported. The default is `toggle`.
|
|
192
|
+
Directives need local registration unless the plugin is installed:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
const vScreenfull = importedDirective;
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Plugin Installation
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import { createApp } from "vue";
|
|
202
|
+
import VueScreenfull from "vue-screenfull";
|
|
203
|
+
import App from "./App.vue";
|
|
204
|
+
|
|
205
|
+
createApp(App).use(VueScreenfull).mount("#app");
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
This registers `Screenfull` and `v-screenfull`. Names can be changed with `componentName` and `directiveName`.
|
|
209
|
+
Named composable imports never require plugin installation and remain tree-shakable.
|
|
210
|
+
|
|
211
|
+
## Advanced Usage
|
|
212
|
+
|
|
213
|
+
The framework-light controller is useful for migration and non-component integrations:
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
import { createScreenfullController } from "vue-screenfull";
|
|
217
|
+
|
|
218
|
+
const controller = createScreenfullController({ restoreFocus: true });
|
|
219
|
+
const onChange = (state) => console.log(state.isFullscreen, state.element);
|
|
220
|
+
controller.on("change", onChange);
|
|
221
|
+
await controller.request(document.querySelector("#map"));
|
|
222
|
+
controller.off("change", onChange);
|
|
223
|
+
await controller.destroy();
|
|
19
224
|
```
|
|
20
225
|
|
|
21
|
-
|
|
226
|
+
`raw` is a read-only diagnostic mapping of detected browser property/event names, or `null`.
|
|
227
|
+
It is not the recommended API. Each composable creates one controller and disposes it with its Vue scope;
|
|
228
|
+
multiple controllers synchronize through the same document's native events.
|
|
229
|
+
Importing the package does not register listeners or touch the DOM.
|
|
230
|
+
|
|
231
|
+
Reactive callbacks can observe changes without duplicate component wiring:
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
useScreenfull({ onEnter: announce, onExit: announce, onError: report });
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`restoreFocus: true` (the default) focuses the initiating element after exit where practical.
|
|
238
|
+
`exitOnRouteChange` listens for browser `popstate`; router-specific navigation can instead call `exit()` in the application's own route hook.
|
|
239
|
+
|
|
240
|
+
## iframe Usage
|
|
241
|
+
|
|
242
|
+
The embedding page controls permission. A typical iframe is:
|
|
243
|
+
|
|
244
|
+
```html
|
|
245
|
+
<iframe
|
|
246
|
+
src="https://example.com/player"
|
|
247
|
+
allow="fullscreen"
|
|
248
|
+
allowfullscreen
|
|
249
|
+
></iframe>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Permissions Policy or a missing iframe permission can still reject.
|
|
253
|
+
The library returns `IFRAME_PERMISSION_REQUIRED` when a denial can be associated with an embedded document;
|
|
254
|
+
it cannot override the parent page's policy.
|
|
255
|
+
|
|
256
|
+
## Mobile Considerations
|
|
257
|
+
|
|
258
|
+
- Use direct user gestures and keep a visible touch-sized exit control.
|
|
259
|
+
- Feature-detect rather than assuming support by device name.
|
|
260
|
+
- iPhone Safari and WKWebView behavior may be limited or video-specific.
|
|
261
|
+
- Dynamic browser chrome changes viewport height; CSS fallback uses `100dvh` where supported.
|
|
262
|
+
- Native navigation, tab switching, app switching, and OS gestures may exit fullscreen.
|
|
263
|
+
- Neither native capability nor this library guarantees browser/OS controls disappear.
|
|
22
264
|
|
|
23
|
-
|
|
265
|
+
## SSR and Nuxt
|
|
24
266
|
|
|
267
|
+
Imports are safe in Vite SSR, Nuxt 3, Node tests, and static generation. Outside a browser,
|
|
268
|
+
`isEnabled` is false, status is `unsupported`, and actions return `NOT_IN_BROWSER`.
|
|
269
|
+
|
|
270
|
+
```vue
|
|
271
|
+
<script setup lang="ts">
|
|
272
|
+
import { useScreenfull } from "vue-screenfull";
|
|
273
|
+
const screenfull = useScreenfull(); // safe during Nuxt setup/SSR
|
|
274
|
+
</script>
|
|
275
|
+
<template>
|
|
276
|
+
<ClientOnly>
|
|
277
|
+
<button
|
|
278
|
+
type="button"
|
|
279
|
+
:disabled="!screenfull.isEnabled.value"
|
|
280
|
+
@click="screenfull.toggle()"
|
|
281
|
+
>
|
|
282
|
+
Toggle page fullscreen
|
|
283
|
+
</button>
|
|
284
|
+
</ClientOnly>
|
|
285
|
+
</template>
|
|
25
286
|
```
|
|
26
|
-
|
|
287
|
+
|
|
288
|
+
When destructuring refs in `<script setup>`, templates unwrap them automatically;
|
|
289
|
+
when accessing through an object as above, use `.value` in script expressions.
|
|
290
|
+
|
|
291
|
+
## Migrating from screenfull
|
|
292
|
+
|
|
293
|
+
`vue-screenfull` is an independent Vue 3 library inspired by screenfull's public API and compatibility goals.
|
|
294
|
+
It is not drop-in compatible and is not endorsed by screenfull's maintainers.
|
|
295
|
+
|
|
296
|
+
| screenfull concept | vue-screenfull equivalent |
|
|
297
|
+
| -------------------------------------- | ------------------------------------------------------- |
|
|
298
|
+
| `screenfull.request(element, options)` | `request(element, options)` |
|
|
299
|
+
| `screenfull.exit()` | `exit()` |
|
|
300
|
+
| `screenfull.toggle(element, options)` | `toggle(element, options)` |
|
|
301
|
+
| `screenfull.isEnabled` | reactive `isEnabled.value` |
|
|
302
|
+
| `screenfull.isFullscreen` | reactive `isFullscreen.value` |
|
|
303
|
+
| `screenfull.element` | reactive `fullscreenElement.value` |
|
|
304
|
+
| `screenfull.on("change", fn)` | refs, callbacks, component events, or controller events |
|
|
305
|
+
| `screenfull.on("error", fn)` | reactive `error`, callbacks, or controller events |
|
|
306
|
+
|
|
307
|
+
Before:
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
import screenfull from "screenfull";
|
|
311
|
+
if (screenfull.isEnabled) await screenfull.toggle(element);
|
|
27
312
|
```
|
|
28
313
|
|
|
29
|
-
|
|
314
|
+
After:
|
|
30
315
|
|
|
316
|
+
```ts
|
|
317
|
+
import { useScreenfull } from "vue-screenfull";
|
|
318
|
+
const { isEnabled, toggle } = useScreenfull();
|
|
319
|
+
if (isEnabled.value) {
|
|
320
|
+
const result = await toggle(element);
|
|
321
|
+
if (!result.ok) console.error(result.error.message);
|
|
322
|
+
}
|
|
31
323
|
```
|
|
32
|
-
|
|
324
|
+
|
|
325
|
+
Key differences are reactive refs, automatic lifecycle cleanup, SSR-safe imports, structured results/errors, optional pseudo-fullscreen, and Vue component/directive APIs.
|
|
326
|
+
Controller listeners receive typed state/errors rather than raw DOM events.
|
|
327
|
+
Legacy `onchange`/`onerror` aliases are not provided. The plugin is optional.
|
|
328
|
+
|
|
329
|
+
## API Reference
|
|
330
|
+
|
|
331
|
+
Root exports:
|
|
332
|
+
|
|
333
|
+
- `useScreenfull(options?)`, `useScreenfullTarget(target, options?)`
|
|
334
|
+
- `Screenfull`, `vScreenfull`, and the default plugin
|
|
335
|
+
- `createScreenfullController(options?)`
|
|
336
|
+
- `detectFullscreenApi(document)` and `resolveScreenfullTarget(target, document)`
|
|
337
|
+
- all public target, option, state, result, error, event, component, directive, plugin, and raw-map types
|
|
338
|
+
|
|
339
|
+
Actions resolve to `{ ok, mode, element, error }`; `mode` is `native`, `fallback`, or `none`.
|
|
340
|
+
Generated TypeDoc is published at [chengchuu.github.io/vue-screenfull/api/](https://chengchuu.github.io/vue-screenfull/api/).
|
|
341
|
+
|
|
342
|
+
## Live Playground
|
|
343
|
+
|
|
344
|
+
The deployed playground is at [chengchuu.github.io/vue-screenfull/playground/](https://chengchuu.github.io/vue-screenfull/playground/).
|
|
345
|
+
It includes page, element, image-style, and video targets; explicit exit; diagnostics;
|
|
346
|
+
invalid-target feedback; event history; accessibility, iframe, mobile, and migration notes. Run it locally with:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
33
349
|
npm run dev
|
|
350
|
+
```
|
|
34
351
|
|
|
35
|
-
|
|
36
|
-
|
|
352
|
+
Native fullscreen automation is intentionally not treated as universally reliable because browsers enforce user activation.
|
|
353
|
+
|
|
354
|
+
## Development
|
|
37
355
|
|
|
38
|
-
|
|
356
|
+
Node.js 22 is used in CI.
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
npm install
|
|
360
|
+
npm run typecheck
|
|
361
|
+
npm run lint
|
|
362
|
+
npm run format:check
|
|
363
|
+
npm run test
|
|
364
|
+
npm run build
|
|
39
365
|
npm run docs
|
|
366
|
+
npm run seo:validate
|
|
367
|
+
npm run preview
|
|
368
|
+
npm pack --dry-run
|
|
40
369
|
```
|
|
370
|
+
|
|
371
|
+
See `MANUAL_TESTING.md` for the browser matrix and real-browser strategy.
|
|
372
|
+
Production output remains `lib/index.cjs.js`, `lib/index.esm.js`, `lib/vue-screenfull.min.js`, `lib/index.d.ts`, `lib/typing.d.ts`, and `lib/global.d.ts`. Native Node ESM resolves through the additional conditional entry `lib/index.mjs`.
|
|
373
|
+
|
|
374
|
+
## License and Attribution
|
|
375
|
+
|
|
376
|
+
Released under the MIT License. This independent project acknowledges [screenfull](https://github.com/sindresorhus/screenfull) (MIT) for its public API and cross-browser compatibility inspiration, and `vue-fullscreen` (MIT) as a Vue ecosystem reference. No endorsement is implied.
|
package/lib/global.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Legacy Fullscreen API names used only after runtime feature detection. */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface Document {
|
|
6
|
+
webkitExitFullscreen?: () => Promise<void> | void;
|
|
7
|
+
webkitFullscreenElement?: Element | null;
|
|
8
|
+
webkitFullscreenEnabled?: boolean;
|
|
9
|
+
webkitCancelFullScreen?: () => Promise<void> | void;
|
|
10
|
+
webkitCurrentFullScreenElement?: Element | null;
|
|
11
|
+
mozCancelFullScreen?: () => Promise<void> | void;
|
|
12
|
+
mozFullScreenElement?: Element | null;
|
|
13
|
+
mozFullScreenEnabled?: boolean;
|
|
14
|
+
msExitFullscreen?: () => Promise<void> | void;
|
|
15
|
+
msFullscreenElement?: Element | null;
|
|
16
|
+
msFullscreenEnabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface Element {
|
|
19
|
+
webkitRequestFullscreen?: (
|
|
20
|
+
options?: FullscreenOptions,
|
|
21
|
+
) => Promise<void> | void;
|
|
22
|
+
webkitRequestFullScreen?: (
|
|
23
|
+
options?: FullscreenOptions,
|
|
24
|
+
) => Promise<void> | void;
|
|
25
|
+
mozRequestFullScreen?: (
|
|
26
|
+
options?: FullscreenOptions,
|
|
27
|
+
) => Promise<void> | void;
|
|
28
|
+
msRequestFullscreen?: (options?: FullscreenOptions) => Promise<void> | void;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export {};
|
package/lib/index.cjs.js
CHANGED
|
@@ -1,30 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// https://vuejs.org/guide/typescript/overview.html#definecomponent
|
|
9
|
-
var com = vue.defineComponent({
|
|
10
|
-
// type inference enabled
|
|
11
|
-
template: "\n <div>\n <span>{{ FirstName }}</span>\n </div>\n ",
|
|
12
|
-
// props: {
|
|
13
|
-
// name: String,
|
|
14
|
-
// msg: { type: String, required: true }
|
|
15
|
-
// },
|
|
16
|
-
data: function data() {
|
|
17
|
-
return {
|
|
18
|
-
count: 1,
|
|
19
|
-
FirstName: 'm'
|
|
20
|
-
};
|
|
21
|
-
},
|
|
22
|
-
mounted: function mounted() {
|
|
23
|
-
// this.name; // type: string | undefined
|
|
24
|
-
// this.msg; // type: string
|
|
25
|
-
// this.count; // type: number
|
|
26
|
-
this.FirstName = 'Cheng';
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
exports.com = com;
|
|
1
|
+
/*!
|
|
2
|
+
* vue-screenfull v1.0.4
|
|
3
|
+
* (c) 2018-2026 Cheng https://www.npmjs.com/package/vue-screenfull
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("vue");function n(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 r(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,u(t.key),t)}}(e.prototype,n),Object.defineProperty(e,"prototype",{writable:!1}),e}function t(){var e,n,r="function"==typeof Symbol?Symbol:{},o=r.iterator||"@@iterator",u=r.toStringTag||"@@toStringTag";function i(r,t,o,u){var i=t&&t.prototype instanceof c?t:c,s=Object.create(i.prototype);return l(s,"_invoke",function(r,t,l){var o,u,i,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,u=0,i=e,d.n=r,a}};function v(r,t){for(u=r,i=t,n=0;!f&&c&&!l&&n<s.length;n++){var l,o=s[n],v=d.p,b=o[2];r>3?(l=b===t)&&(i=o[(u=o[4])?5:(u=3,3)],o[4]=o[5]=e):o[0]<=v&&((l=r<2&&v<o[1])?(u=0,d.v=t,d.n=o[1]):v<b&&(l=r<3||o[0]>t||t>b)&&(o[4]=r,o[5]=t,d.n=b,u=0))}if(l||r>1)return a;throw f=!0,t}return function(l,s,b){if(c>1)throw TypeError("Generator is already running");for(f&&1===s&&v(s,b),u=s,i=b;(n=u<2?e:i)||!f;){o||(u?u<3?(u>1&&(d.n=-1),v(u,i)):d.n=i:d.v=i);try{if(c=2,o){if(u||(l="next"),n=o[l]){if(!(n=n.call(o,i)))throw TypeError("iterator result is not an object");if(!n.done)return n;i=n.value,u<2&&(u=0)}else 1===u&&(n=o.return)&&n.call(o),u<2&&(i=TypeError("The iterator does not provide a '"+l+"' method"),u=1);o=e}else if((n=(f=d.n<0)?i:r.call(t,d))!==a)break}catch(n){o=e,u=1,i=n}finally{c=1}}return{value:n,done:f}}}(r,o,u),!0),s}var a={};function c(){}function s(){}function f(){}n=Object.getPrototypeOf;var d=[][o]?n(n([][o]())):(l(n={},o,function(){return this}),n),v=f.prototype=c.prototype=Object.create(d);function b(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,f):(e.__proto__=f,l(e,u,"GeneratorFunction")),e.prototype=Object.create(v),e}return s.prototype=f,l(v,"constructor",f),l(f,"constructor",s),s.displayName="GeneratorFunction",l(f,u,"GeneratorFunction"),l(v),l(v,u,"Generator"),l(v,o,function(){return this}),l(v,"toString",function(){return"[object Generator]"}),(t=function(){return{w:i,m:b}})()}function l(e,n,r,t){var o=Object.defineProperty;try{o({},"",{})}catch(e){o=0}l=function(e,n,r,t){function u(n,r){l(e,n,function(e){return this._invoke(n,r,e)})}n?o?o(e,n,{value:r,enumerable:!t,configurable:!t,writable:!t}):e[n]=r:(u("next",0),u("throw",1),u("return",2))},l(e,n,r,t)}function o(e,r){return function(e){if(Array.isArray(e))return e}(e)||function(e,n){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var t,l,o,u,i=[],a=!0,c=!1;try{if(o=(r=r.call(e)).next,0===n);else for(;!(a=(t=o.call(r)).done)&&(i.push(t.value),i.length!==n);a=!0);}catch(e){c=!0,l=e}finally{try{if(!a&&null!=r.return&&(u=r.return(),Object(u)!==u))return}finally{if(c)throw l}}return i}}(e,r)||function(e,r){if(e){if("string"==typeof e)return n(e,r);var t={}.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?n(e,r):void 0}}(e,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 u(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 u(e){try{a(t.next(e))}catch(e){o(e)}}function i(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(u,i)}a((t=t.apply(e,n||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;var a=[{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 c(e){var n=e.documentElement,r=e,t=a.find(function(e){return"function"==typeof n[e.requestFullscreen]&&"function"==typeof r[e.exitFullscreen]});return t?Object.freeze(Object.assign({},t)):null}var s=["position","inset","top","right","bottom","left","width","height","max-width","max-height","margin","z-index","overflow","background"],f=new WeakMap,d=/*#__PURE__*/function(){return r(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},[{key:"enter",value:function(e){var n,r,t,l,u,i,a,c,d,v,b=e.element,h=e.document,m=e.options,p=null===(n=h.defaultView)||void 0===n?void 0:n.HTMLElement;if(!(p&&b instanceof p))throw new TypeError("CSS fallback requires an HTMLElement.");var y=f.get(h);if(y&&y!==this)throw new Error("Another CSS fullscreen fallback is already active.");f.set(h,this);try{this.element=b,this.className=null!==(r=m.fallbackClass)&&void 0!==r?r:"vue-screenfull-fallback",this.styles={};for(var g=0,E=s;g<E.length;g++){var k=E[g];this.styles[k]={value:this.element.style.getPropertyValue(k),priority:this.element.style.getPropertyPriority(k)}}this.bodyOverflow={value:null!==(l=null===(t=h.body)||void 0===t?void 0:t.style.getPropertyValue("overflow"))&&void 0!==l?l:"",priority:null!==(i=null===(u=h.body)||void 0===u?void 0:u.style.getPropertyPriority("overflow"))&&void 0!==i?i:""},this.scrollX=null!==(c=null===(a=h.defaultView)||void 0===a?void 0:a.scrollX)&&void 0!==c?c:0,this.scrollY=null!==(v=null===(d=h.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=o(F[S],2),T=O[0],x=O[1];this.element.style.setProperty(T,x,"important")}this.addedClass=!this.element.classList.contains(this.className),this.addedClass&&this.element.classList.add(this.className),this.lockedScroll=!1!==m.lockScroll,this.lockedScroll&&h.body&&h.body.style.setProperty("overflow","hidden","important")}catch(e){try{this.exit({element:b,document:h,options:m})}finally{f.get(h)===this&&f.delete(h)}throw e}}},{key:"exit",value:function(e){var n,r,t=e.document;if(this.element&&this.styles)try{for(var l=0,o=s;l<o.length;l++){var u=o[l],i=this.styles[u];i.value?this.element.style.setProperty(u,i.value,i.priority):this.element.style.removeProperty(u)}this.addedClass&&this.element.classList.remove(this.className),this.lockedScroll&&t.body&&(this.bodyOverflow.value?t.body.style.setProperty("overflow",this.bodyOverflow.value,this.bodyOverflow.priority):t.body.style.removeProperty("overflow"),null===(r=null===(n=t.defaultView)||void 0===n?void 0:n.scrollTo)||void 0===r||r.call(n,this.scrollX,this.scrollY))}finally{f.get(t)===this&&f.delete(t),this.element=null,this.styles=null,this.addedClass=!1,this.lockedScroll=!1}}}])}();function v(e){return e.fallback&&"none"!==e.fallback?"css"===e.fallback?new d:e.fallback:null}var b={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:b[e]}}function m(e,n,r){var t,l=e instanceof Error?"".concat(e.name,": ").concat(e.message):String(e),o=l.toLowerCase(),u="exit"===n?"EXIT_FAILED":"fallback"===n?"FALLBACK_FAILED":"REQUEST_FAILED";if(o.includes("activation")||o.includes("gesture"))u="USER_ACTIVATION_REQUIRED";else if(o.includes("permission")||o.includes("denied")||o.includes("security")){var i;try{i=Boolean(null===(t=null==r?void 0:r.defaultView)||void 0===t?void 0:t.frameElement)}catch(e){i=!0}u=i?"IFRAME_PERMISSION_REQUIRED":"PERMISSION_DENIED"}return h(u,"Fullscreen ".concat(n," failed: ").concat(l),e)}var p=function(e,n){return{ok:!0,mode:e,element:n,error:null}};function y(){var e,n,r=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?c(o):null,a=new Set,s=new Set,f=v(l),d=null,b=l,y=null,g=!1,E=!1,k=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()||d),isFallback:Boolean(d),element:S()||d,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,x=F().isFullscreen,R=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),a.forEach(function(n){return O(n,e)}))},_=function(e){return k=e,arguments.length>1&&void 0!==arguments[1]&&arguments[1]||(w="NOT_SUPPORTED"===e.code||"NOT_IN_BROWSER"===e.code?"unsupported":"error"),E||(O(l.onError,e),s.forEach(function(n){return O(n,e)}),R()),l.debug&&"undefined"!=typeof console&&console.warn("[vue-screenfull]",e),{ok:!1,mode:"none",element:F().element,error:e}},C=function(){w=S()?"fullscreen":"idle";var e=F();e.isFullscreen!==x&&(e.isFullscreen?O(l.onEnter,e):O(l.onExit,e),x=e.isFullscreen),R()},I=function(e){g||_(m(e,"request",o))},N=function(e){"Escape"===e.key&&d&&D.exit()},P=function(){F().isFullscreen&&D.exit()},j=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}},q=function(e){return i(r,void 0,void 0,/*#__PURE__*/t().m(function n(){var r,l,o;return t().w(function(n){for(;;)switch(n.p=n.n){case 0:if(r=j(),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,r.promise;case 4:if((o=n.v).ok){n.n=5;break}throw o.cause;case 5:return n.p=5,r.cleanup(),n.f(5);case 6:return n.a(2)}},n,null,[[1,,5,6]])}))},A=function(){return i(r,void 0,void 0,/*#__PURE__*/t().m(function e(){var n;return t().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,q(function(){return n.call(o)});case 2:return e.a(2)}},e)}))};function L(e,n){return i(this,void 0,void 0,/*#__PURE__*/t().m(function r(){var u,i,a,c,s,y;return t().w(function(r){for(;;)switch(r.p=r.n){case 0:if(i=null!==(u=null==n?void 0:n.fallback)&&void 0!==u?u:l.fallback,a=Object.assign(Object.assign({},l),{fallback:i}),f=v(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,b=a,r.n=2,f.enter({element:e,document:o,options:a});case 2:if(!E){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 d=e,w="fallback",s=F(),x=!0,O(l.onFallback,s),O(l.onEnter,s),R(),r.a(2,p("fallback",e));case 5:return r.p=5,y=r.v,r.a(2,_(m(y,"fallback",o)))}},r,null,[[1,5]])}))}o&&u&&(o.addEventListener(u.fullscreenchange,C),o.addEventListener(u.fullscreenerror,I)),o&&(o.addEventListener("keydown",N),l.exitOnRouteChange&&(null===(n=o.defaultView)||void 0===n||n.addEventListener("popstate",P)));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 k},get raw(){return u},request:function(e,n){return i(this,void 0,void 0,/*#__PURE__*/t().m(function r(){var i,a,c,s,f,v,b,k;return t().w(function(r){for(;;)switch(r.p=r.n){case 0:if(!E&&o){r.n=1;break}return r.a(2,_(h("NOT_IN_BROWSER","Fullscreen is unavailable outside a browser document.")));case 1:if(!g){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,p(d?"fallback":"native",i));case 5:if(!d){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(y=!1===l.restoreFocus?null:o.activeElement,g=!0,w="requesting",R(),r.p=8,u&&D.isEnabled){r.n=10;break}return r.n=9,L(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,q(function(){return c.call(i,s)});case 11:return E||(w=S()?"fullscreen":"idle",R()),r.a(2,p("native",S()||i));case 12:if(r.p=12,b=r.v,!E){r.n=13;break}return f=m(b,"request",o),r.a(2,{ok:!1,mode:"none",element:null,error:f});case 13:if(v=m(b,"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,A();case 15:r.n=17;break;case 16:return r.p=16,k=r.v,r.a(2,_(m(k,"exit",o)));case 17:return r.n=18,L(i,n);case 19:return r.a(2,_(v));case 20:return r.p=20,g=!1,r.f(20);case 21:return r.a(2)}},r,null,[[14,16],[8,12,20,21]])}))},exit:function(){return i(this,void 0,void 0,/*#__PURE__*/t().m(function e(){var n,r,i,a;return t().w(function(e){for(;;)switch(e.p=e.n){case 0:if(!E&&o){e.n=1;break}return e.a(2,_(h("NOT_IN_BROWSER","Fullscreen is unavailable outside a browser document.")));case 1:if(!g){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,p("native",null));case 3:if(g=!0,w="exiting",R(),e.p=4,!d||!f){e.n=6;break}return r=d,e.n=5,f.exit({element:r,document:o,options:b});case 5:d=null,w="idle",i=F(),x=!1,O(l.onExit,i),R(),e.n=8;break;case 6:if(!u||!S()){e.n=8;break}return e.n=7,A();case 7:w=S()?"fullscreen":"idle",R();case 8:return null===(n=null==y?void 0:y.focus)||void 0===n||n.call(y),y=null,e.a(2,p(d?"fallback":"native",F().element));case 9:return e.p=9,a=e.v,e.a(2,_(m(a,"exit",o)));case 10:return e.p=10,g=!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__*/t().m(function r(){return t().w(function(r){for(;;)if(0===r.n)return r.a(2,F().isFullscreen?D.exit():D.request(e,n))},r)}))},on:function(e,n){"change"===e?a.add(n):s.add(n)},off:function(e,n){"change"===e?a.delete(n):s.delete(n)},clearError:function(){k=null,"error"===w&&(w=F().isFullscreen?d?"fallback":"fullscreen":"idle"),R()},destroy:function(){return i(this,void 0,void 0,/*#__PURE__*/t().m(function e(){var n,r,i;return t().w(function(e){for(;;)switch(e.p=e.n){case 0:if(!E){e.n=1;break}return e.a(2);case 1:if(E=!0,!(d&&f&&o)){e.n=6;break}return r=d,e.p=2,e.n=3,f.exit({element:r,document:o,options:b});case 3:e.n=5;break;case 4:e.p=4,i=e.v,k=m(i,"fallback",o);case 5:d=null;case 6:o&&u&&(o.removeEventListener(u.fullscreenchange,C),o.removeEventListener(u.fullscreenerror,I)),null==o||o.removeEventListener("keydown",N),l.exitOnRouteChange&&(null===(n=null==o?void 0:o.defaultView)||void 0===n||n.removeEventListener("popstate",P)),a.clear(),s.clear();case 7:return e.a(2)}},e,null,[[2,4]])}))}};return D}function g(n,r){if(!r)return null;if(void 0===n)return r.documentElement;var t=e.isRef(n)?n.value:n;if(null==t)return null;if("string"==typeof t)try{return r.querySelector(t)}catch(e){return null}return"object"==typeof t&&"$el"in t&&(t=t.$el),t&&"object"==typeof t&&1===t.nodeType?t:null}function E(){var n,r=this,l=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},o=y(l),u=e.ref(o.isEnabled),a=e.ref(o.isFullscreen),c=e.ref(o.isFallback),s=e.shallowRef(o.element),f=e.shallowRef(null),d=e.ref(o.status),v=e.shallowRef(o.error),b=null!==(n=l.document)&&void 0!==n?n:"undefined"==typeof document?void 0:document,m=function(e){u.value=e.isEnabled,a.value=e.isFullscreen,c.value=e.isFallback,s.value=e.element,d.value=e.status,v.value=o.error},p=function(e){v.value=e,d.value=o.status};o.on("change",m),o.on("error",p);var E=function(){var e,n=h(b?"INVALID_TARGET":"NOT_IN_BROWSER",b?"The target is not a valid element or selector in this document.":"Fullscreen is unavailable outside a browser document.");v.value=n,d.value=b?"error":"unsupported";try{null===(e=l.onError)||void 0===e||e.call(l,n)}catch(e){"undefined"!=typeof console&&console.error("[vue-screenfull] Listener failed.",e)}return{ok:!1,mode:"none",element:null,error:n}},k=function(e){var n=g(e,b);return f.value=n,n};return e.getCurrentScope()&&e.onScopeDispose(function(){o.off("change",m),o.off("error",p),o.destroy()}),{isEnabled:e.readonly(u),isFullscreen:e.readonly(a),isFallback:e.readonly(c),fullscreenElement:e.shallowReadonly(s),targetElement:e.shallowReadonly(f),status:e.readonly(d),error:e.readonly(v),request:function(e,n){return i(r,void 0,void 0,/*#__PURE__*/t().m(function r(){var l;return t().w(function(r){for(;;)if(0===r.n)return l=k(e),r.a(2,l?o.request(l,n):E())},r)}))},exit:function(){return o.exit()},toggle:function(e,n){return i(r,void 0,void 0,/*#__PURE__*/t().m(function r(){var l;return t().w(function(r){for(;;)switch(r.n){case 0:if(!o.isFullscreen){r.n=1;break}return r.a(2,o.exit());case 1:return l=k(e),r.a(2,l?o.request(l,n):E())}},r)}))},clearError:function(){o.clearError(),v.value=null}}}var k=/*#__PURE__*/e.defineComponent({name:"Screenfull",props:{target:{type:[String,Object],default:void 0},fallback:{type:[String,Object],default:"none"},fallbackClass:{type:String,default:"vue-screenfull-fallback"},lockScroll:{type:Boolean,default:!0},restoreFocus:{type:Boolean,default:!0},exitOnRouteChange:{type:Boolean,default:!1},debug:{type:Boolean,default:!1}},emits:{change:function(e){return"object"==typeof e},enter:function(e){return"object"==typeof e},exit:function(e){return"object"==typeof e},error:function(e){return"object"==typeof e},fallback:function(e){return"object"==typeof e}},slots:Object,setup:function(e,n){var r=n.slots,t=n.emit,l=E({fallback:e.fallback,fallbackClass:e.fallbackClass,lockScroll:e.lockScroll,restoreFocus:e.restoreFocus,exitOnRouteChange:e.exitOnRouteChange,debug:e.debug,onChange:function(e){return t("change",e)},onEnter:function(e){return t("enter",e)},onExit:function(e){return t("exit",e)},onError:function(e){return t("error",e)},onFallback:function(e){return t("fallback",e)}}),o=Object.assign(Object.assign({},l),{request:function(n,r){return l.request(void 0===n?e.target:n,r)},toggle:function(n,r){return l.toggle(void 0===n?e.target:n,r)}});return function(){var e;return null===(e=r.default)||void 0===e?void 0:e.call(r,o)}}}),w=/*#__PURE__*/new WeakMap;var S={mounted:function(e,n){var r=y(),t={controller:r,binding:n,click:function(){}};t.click=function(){var n=t.binding.value,l=function(e){return Boolean(e&&"object"==typeof e&&!("nodeType"in e)&&!("value"in e)&&("target"in e||"action"in e||"options"in e))}(n)?n:{target:n},o=t.binding.arg||l.action||"toggle",u=g(l.target,e.ownerDocument);"exit"===o?r.exit():"request"===o?r.request(u,l.options):r.toggle(u,l.options)},w.set(e,t),e.addEventListener("click",t.click)},updated:function(e,n){var r=w.get(e);r&&(r.binding=n)},unmounted:function(e){var n=w.get(e);n&&(e.removeEventListener("click",n.click),n.controller.destroy(),w.delete(e))}},F={install:function(e){var n,r,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};e.component(null!==(n=t.componentName)&&void 0!==n?n:"Screenfull",k),e.directive(null!==(r=t.directiveName)&&void 0!==r?r:"screenfull",S)}};exports.Screenfull=k,exports.createScreenfullController=y,exports.default=F,exports.detectFullscreenApi=c,exports.resolveScreenfullTarget=g,exports.useScreenfull=E,exports.useScreenfullTarget=function(e){var n=E(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{});return Object.assign(Object.assign({},n),{request:function(r,t){return n.request(e,t)},toggle:function(r,t){return n.toggle(e,t)}})},exports.vScreenfull=S;
|
|
7
|
+
//# sourceMappingURL=index.cjs.js.map
|