@js-toolkit/web-utils 1.66.0 → 1.68.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/EventEmitterListener.d.ts +3 -3
- package/EventEmitterListener.js +222 -1
- package/EventEmitterListener.utils.d.ts +24 -13
- package/EventEmitterListener.utils.js +41 -1
- package/EventListeners.js +58 -1
- package/FullscreenController.js +193 -1
- package/README.md +159 -20
- package/WakeLockController.js +76 -1
- package/base64ToDataUrl.js +3 -1
- package/blobToDataUrl.js +10 -1
- package/checkPermission.js +8 -1
- package/copyToClipboard.js +37 -1
- package/createLoop.js +30 -1
- package/createRafLoop.js +56 -1
- package/dataUrlToBlob.js +13 -1
- package/fromBase64.js +10 -1
- package/fullscreen.js +167 -1
- package/fullscreenUtils.js +37 -1
- package/getAspectRatio.js +8 -1
- package/getBrowserLanguage.js +10 -1
- package/getCurrentScriptUrl.js +4 -1
- package/getEventAwaiter.js +41 -1
- package/getGeoCoordinates.js +6 -1
- package/getGeoLocality.js +19 -1
- package/getInnerRect.js +8 -1
- package/getInnerXDimensions.js +9 -1
- package/getInnerYDimensions.js +9 -1
- package/getPinchZoomHandlers.js +134 -1
- package/getRandomID.js +4 -1
- package/getScreenSize.js +23 -1
- package/getSecondsCounter.js +47 -1
- package/iframe/getAutoConnector.js +251 -1
- package/iframe/getOriginFromMessage.js +3 -1
- package/iframe/isIframeLoaded.js +9 -1
- package/iframe/messages.d.ts +2 -2
- package/iframe/messages.js +50 -1
- package/iframe/utils.js +33 -1
- package/imageToBlob.js +20 -1
- package/isImageTypeSupported.js +8 -1
- package/isWebPSupported.js +15 -1
- package/loadImage.js +29 -1
- package/loadScript.d.ts +1 -1
- package/loadScript.js +67 -1
- package/media/Capabilities.js +44 -1
- package/media/MediaNotAttachedError.d.ts +1 -1
- package/media/MediaNotAttachedError.js +6 -1
- package/media/MediaStreamController.js +84 -1
- package/media/PipController.d.ts +2 -2
- package/media/PipController.js +140 -1
- package/media/TextTracksController/TextTracksController.d.ts +0 -3
- package/media/TextTracksController/TextTracksController.js +251 -1
- package/media/TextTracksController/index.js +1 -1
- package/media/TextTracksController/utils.js +147 -1
- package/media/getDurationTime.js +3 -1
- package/media/getMediaSource.js +11 -1
- package/media/getSourceBuffer.js +5 -1
- package/media/isMediaSeekable.js +4 -1
- package/media/parseCueText.js +224 -1
- package/media/resetMedia.js +17 -1
- package/media/timeRanges.js +9 -1
- package/media/toggleNativeSubtitles.js +21 -1
- package/metrics/ga/DataLayerProxy.js +11 -1
- package/metrics/ga/getHandler.js +99 -1
- package/metrics/ga/types.js +1 -1
- package/metrics/types.js +1 -1
- package/metrics/yandex/DataLayerProxy.js +11 -1
- package/metrics/yandex/getHandler.js +63 -1
- package/metrics/yandex/types.js +2 -1
- package/onDOMReady.js +12 -1
- package/onPageReady.js +27 -1
- package/package.json +19 -16
- package/patchConsoleLogging.js +27 -1
- package/performance/getNavigationTiming.js +14 -1
- package/platform/Semver.js +23 -1
- package/platform/getChromeVersion.d.ts +2 -0
- package/platform/getChromeVersion.js +16 -0
- package/platform/getIOSVersion.js +18 -1
- package/platform/getPlatformInfo.js +49 -1
- package/platform/isAirPlayAvailable.js +3 -1
- package/platform/isAndroid.js +7 -1
- package/platform/isChrome.js +7 -1
- package/platform/isEMESupported.js +9 -1
- package/platform/isIOS.js +9 -1
- package/platform/isMSESupported.js +16 -1
- package/platform/isMacOS.js +12 -1
- package/platform/isMediaCapabilitiesSupported.js +6 -1
- package/platform/isMobile.js +16 -1
- package/platform/isMobileSimulation.js +7 -1
- package/platform/isSafari.js +14 -1
- package/platform/isScreenHDR.js +4 -1
- package/platform/isStandaloneApp.js +4 -1
- package/platform/isTelegramWebView.js +3 -1
- package/platform/isTouchSupported.js +4 -1
- package/preventDefault.d.ts +2 -2
- package/preventDefault.js +5 -1
- package/rafCallback.js +9 -1
- package/responsive/MediaQuery.d.ts +18 -0
- package/responsive/MediaQuery.js +40 -0
- package/responsive/MediaQueryListener.d.ts +19 -0
- package/responsive/MediaQueryListener.js +55 -0
- package/responsive/ViewSize.d.ts +45 -0
- package/responsive/ViewSize.js +82 -0
- package/responsive/getViewSizeQueryMap.d.ts +2 -0
- package/responsive/getViewSizeQueryMap.js +7 -0
- package/saveFileAs.js +22 -1
- package/serviceWorker/ServiceWorkerInstaller.d.ts +0 -1
- package/serviceWorker/ServiceWorkerInstaller.js +112 -1
- package/serviceWorker/utils.d.ts +1 -1
- package/serviceWorker/utils.js +86 -1
- package/stopPropagation.d.ts +2 -2
- package/stopPropagation.js +3 -1
- package/takeScreenshot.js +51 -1
- package/toBase64.js +9 -1
- package/toLocalPoint.js +9 -1
- package/types/index.js +2 -1
- package/types/refs.js +1 -1
- package/viewableTracker.js +69 -1
- package/webrtc/PeerConnection.js +212 -1
- package/webrtc/sdputils.js +417 -1
- package/ws/WSController.js +148 -1
package/platform/Semver.js
CHANGED
|
@@ -1 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
|
2
|
+
export class Semver {
|
|
3
|
+
major;
|
|
4
|
+
minor;
|
|
5
|
+
patch;
|
|
6
|
+
static parse(version) {
|
|
7
|
+
const parts = /(\d+)\.(\d+)(?:\.(\d+))?/.exec(version);
|
|
8
|
+
if (!parts)
|
|
9
|
+
return undefined;
|
|
10
|
+
const major = parseInt(parts[1], 10) || 0;
|
|
11
|
+
const minor = parseInt(parts[2], 10) || 0;
|
|
12
|
+
const patch = parseInt(parts[3], 10) || 0;
|
|
13
|
+
return new Semver(major, minor, patch);
|
|
14
|
+
}
|
|
15
|
+
constructor(major, minor, patch) {
|
|
16
|
+
this.major = major;
|
|
17
|
+
this.minor = minor;
|
|
18
|
+
this.patch = patch;
|
|
19
|
+
}
|
|
20
|
+
toString() {
|
|
21
|
+
return `${this.major}_${this.minor}_${this.patch}`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getCachedPlatformInfo, getPlatformInfoSync } from './getPlatformInfo';
|
|
2
|
+
import { isChrome } from './isChrome';
|
|
3
|
+
import { Semver } from './Semver';
|
|
4
|
+
let memo;
|
|
5
|
+
export function getChromeVersion() {
|
|
6
|
+
if (memo === undefined) {
|
|
7
|
+
const platformInfo = getCachedPlatformInfo() ?? getPlatformInfoSync();
|
|
8
|
+
if (isChrome() && platformInfo.browser.version) {
|
|
9
|
+
memo = Semver.parse(platformInfo.browser.version);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
memo = null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return memo ?? undefined;
|
|
16
|
+
}
|
|
@@ -1 +1,18 @@
|
|
|
1
|
-
import{getCachedPlatformInfo,getPlatformInfoSync}from
|
|
1
|
+
import { getCachedPlatformInfo, getPlatformInfoSync } from './getPlatformInfo';
|
|
2
|
+
import { isIOS } from './isIOS';
|
|
3
|
+
import { Semver } from './Semver';
|
|
4
|
+
let memo;
|
|
5
|
+
export function getIOSVersion() {
|
|
6
|
+
if (memo === undefined) {
|
|
7
|
+
const platformInfo = getCachedPlatformInfo() ?? getPlatformInfoSync();
|
|
8
|
+
// if (!platformInfo) return undefined;
|
|
9
|
+
const { os } = platformInfo;
|
|
10
|
+
if (isIOS() && os.version) {
|
|
11
|
+
memo = Semver.parse(os.version);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
memo = null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return memo ?? undefined;
|
|
18
|
+
}
|
|
@@ -1 +1,49 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="ua-parser-js" preserve="true" />
|
|
2
|
+
import { UAParser } from 'ua-parser-js';
|
|
3
|
+
let syncResult;
|
|
4
|
+
let asyncResult;
|
|
5
|
+
let promise;
|
|
6
|
+
function toPlatformInfo(result) {
|
|
7
|
+
return {
|
|
8
|
+
// Is that order calls overrides values (withFeatureCheck().withClientHints()) ?
|
|
9
|
+
...result,
|
|
10
|
+
toStringObject() {
|
|
11
|
+
return Object.getOwnPropertyNames(this).reduce((acc, key) => {
|
|
12
|
+
const prop = key;
|
|
13
|
+
if (this[prop] != null && typeof this[prop] !== 'function') {
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
15
|
+
acc[prop] = this[prop].toString();
|
|
16
|
+
}
|
|
17
|
+
return acc;
|
|
18
|
+
}, {});
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function getPlatformInfoSync() {
|
|
23
|
+
if (asyncResult == null && syncResult == null) {
|
|
24
|
+
// Is that order calls overrides values (withFeatureCheck().withClientHints()) ?
|
|
25
|
+
syncResult = toPlatformInfo(new UAParser(navigator.userAgent).getResult().withFeatureCheck());
|
|
26
|
+
}
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
28
|
+
return asyncResult ?? syncResult;
|
|
29
|
+
}
|
|
30
|
+
export async function getPlatformInfo() {
|
|
31
|
+
if (asyncResult == null) {
|
|
32
|
+
promise =
|
|
33
|
+
promise ??
|
|
34
|
+
Promise.resolve(
|
|
35
|
+
// Is that order calls overrides values (withFeatureCheck().withClientHints()) ?
|
|
36
|
+
new UAParser(navigator.userAgent).getResult().withFeatureCheck().withClientHints());
|
|
37
|
+
asyncResult = toPlatformInfo(await promise);
|
|
38
|
+
syncResult = asyncResult;
|
|
39
|
+
promise = undefined;
|
|
40
|
+
}
|
|
41
|
+
return asyncResult;
|
|
42
|
+
}
|
|
43
|
+
export function getCachedPlatformInfo() {
|
|
44
|
+
if (asyncResult == null) {
|
|
45
|
+
console.warn('PlatformInfo is not ready yet.');
|
|
46
|
+
void getPlatformInfo();
|
|
47
|
+
}
|
|
48
|
+
return asyncResult;
|
|
49
|
+
}
|
package/platform/isAndroid.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
import{getCachedPlatformInfo,getPlatformInfoSync}from
|
|
1
|
+
import { getCachedPlatformInfo, getPlatformInfoSync } from './getPlatformInfo';
|
|
2
|
+
export function isAndroid() {
|
|
3
|
+
const platformInfo = getCachedPlatformInfo() ?? getPlatformInfoSync();
|
|
4
|
+
// if (!platformInfo) return false;
|
|
5
|
+
const os = platformInfo.os.name;
|
|
6
|
+
return os === 'Android' || os === 'Android-x86';
|
|
7
|
+
}
|
package/platform/isChrome.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
import{getCachedPlatformInfo,getPlatformInfoSync}from
|
|
1
|
+
import { getCachedPlatformInfo, getPlatformInfoSync } from './getPlatformInfo';
|
|
2
|
+
export function isChrome() {
|
|
3
|
+
const platformInfo = getCachedPlatformInfo() ?? getPlatformInfoSync();
|
|
4
|
+
// if (!platformInfo) return false;
|
|
5
|
+
const browser = platformInfo.browser.name;
|
|
6
|
+
return browser === 'Chrome' || browser === 'Mobile Chrome';
|
|
7
|
+
}
|
|
@@ -1 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
|
2
|
+
/** Encrypted Media Extensions */
|
|
3
|
+
export function isEMESupported() {
|
|
4
|
+
return (!!window.MediaKeys &&
|
|
5
|
+
!!window.navigator &&
|
|
6
|
+
!!window.navigator.requestMediaKeySystemAccess &&
|
|
7
|
+
!!window.MediaKeySystemAccess &&
|
|
8
|
+
!!window.MediaKeySystemAccess.prototype.getConfiguration);
|
|
9
|
+
}
|
package/platform/isIOS.js
CHANGED
|
@@ -1 +1,9 @@
|
|
|
1
|
-
import{getCachedPlatformInfo,getPlatformInfoSync}from
|
|
1
|
+
import { getCachedPlatformInfo, getPlatformInfoSync } from './getPlatformInfo';
|
|
2
|
+
import { isMobile } from './isMobile';
|
|
3
|
+
export function isIOS() {
|
|
4
|
+
const platformInfo = getCachedPlatformInfo() ?? getPlatformInfoSync();
|
|
5
|
+
// if (!platformInfo) return false;
|
|
6
|
+
return (platformInfo.os.name === 'iOS' ||
|
|
7
|
+
// WebView on iPad
|
|
8
|
+
(isMobile() && platformInfo.device.vendor === 'Apple'));
|
|
9
|
+
}
|
|
@@ -1 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
|
2
|
+
import { getMediaSource } from '../media/getMediaSource';
|
|
3
|
+
import { getSourceBuffer } from '../media/getSourceBuffer';
|
|
4
|
+
/** Media Source Extensions */
|
|
5
|
+
export function isMSESupported(managedMediaSource) {
|
|
6
|
+
// Some very old MediaSource implementations didn't have isTypeSupported.
|
|
7
|
+
if (!getMediaSource(managedMediaSource)?.isTypeSupported)
|
|
8
|
+
return false;
|
|
9
|
+
// if SourceBuffer is exposed ensure its API is valid.
|
|
10
|
+
// Older browsers do not expose SourceBuffer globally so checking SourceBuffer.prototype is impossible.
|
|
11
|
+
const sourceBuffer = getSourceBuffer(managedMediaSource);
|
|
12
|
+
return (!sourceBuffer ||
|
|
13
|
+
(sourceBuffer.prototype &&
|
|
14
|
+
typeof sourceBuffer.prototype.appendBuffer === 'function' &&
|
|
15
|
+
typeof sourceBuffer.prototype.remove === 'function'));
|
|
16
|
+
}
|
package/platform/isMacOS.js
CHANGED
|
@@ -1 +1,12 @@
|
|
|
1
|
-
import{getCachedPlatformInfo,getPlatformInfoSync}from
|
|
1
|
+
import { getCachedPlatformInfo, getPlatformInfoSync } from './getPlatformInfo';
|
|
2
|
+
import { isMobile } from './isMobile';
|
|
3
|
+
export function isMacOS() {
|
|
4
|
+
const platformInfo = getCachedPlatformInfo() ?? getPlatformInfoSync();
|
|
5
|
+
// if (!platformInfo) return false;
|
|
6
|
+
const osName = platformInfo.os.name;
|
|
7
|
+
return ((osName === 'Mac OS' ||
|
|
8
|
+
// 2.0+
|
|
9
|
+
osName === 'macOS') &&
|
|
10
|
+
// WebView on iPad
|
|
11
|
+
!isMobile());
|
|
12
|
+
}
|
|
@@ -1 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
|
2
|
+
export function isMediaCapabilitiesSupported() {
|
|
3
|
+
return (!!window.MediaCapabilities &&
|
|
4
|
+
!!window.navigator &&
|
|
5
|
+
!!window.navigator.mediaCapabilities?.decodingInfo);
|
|
6
|
+
}
|
package/platform/isMobile.js
CHANGED
|
@@ -1 +1,16 @@
|
|
|
1
|
-
import{getCachedPlatformInfo,getPlatformInfoSync}from
|
|
1
|
+
import { getCachedPlatformInfo, getPlatformInfoSync } from './getPlatformInfo';
|
|
2
|
+
export function isMobile() {
|
|
3
|
+
const platformInfo = getCachedPlatformInfo() ?? getPlatformInfoSync();
|
|
4
|
+
// if (!platformInfo) return false;
|
|
5
|
+
const deviceType = platformInfo.device.type;
|
|
6
|
+
if (deviceType === 'mobile' ||
|
|
7
|
+
deviceType === 'tablet' ||
|
|
8
|
+
// WKWebView in desktop mode on iPad
|
|
9
|
+
(!deviceType &&
|
|
10
|
+
platformInfo.device.vendor === 'Apple' &&
|
|
11
|
+
navigator.maxTouchPoints != null &&
|
|
12
|
+
navigator.maxTouchPoints > 2)) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
import{isTouchSupported}from
|
|
1
|
+
import { isTouchSupported } from './isTouchSupported';
|
|
2
|
+
/** Detect mobile simulation in Chrome DevTools. */
|
|
3
|
+
export function isMobileSimulation() {
|
|
4
|
+
return (isTouchSupported() &&
|
|
5
|
+
// maxTouchPoints is always = 1 in simulation mode
|
|
6
|
+
navigator.maxTouchPoints === 1);
|
|
7
|
+
}
|
package/platform/isSafari.js
CHANGED
|
@@ -1 +1,14 @@
|
|
|
1
|
-
import{getCachedPlatformInfo,getPlatformInfoSync}from
|
|
1
|
+
import { getCachedPlatformInfo, getPlatformInfoSync } from './getPlatformInfo';
|
|
2
|
+
import { isIOS } from './isIOS';
|
|
3
|
+
import { isMacOS } from './isMacOS';
|
|
4
|
+
export function isSafari() {
|
|
5
|
+
const platformInfo = getCachedPlatformInfo() ?? getPlatformInfoSync();
|
|
6
|
+
// if (!platformInfo) return false;
|
|
7
|
+
const browser = platformInfo.browser.name;
|
|
8
|
+
return (browser === 'Safari' ||
|
|
9
|
+
browser === 'Mobile Safari' /* ||
|
|
10
|
+
!!window.WebKitPlaybackTargetAvailabilityEvent */
|
|
11
|
+
||
|
|
12
|
+
// WebView
|
|
13
|
+
(browser === 'WebKit' && (isIOS() || isMacOS())));
|
|
14
|
+
}
|
package/platform/isScreenHDR.js
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// https://stackoverflow.com/questions/21125337/how-to-detect-if-web-app-running-standalone-on-chrome-mobile
|
|
2
|
+
export function isStandaloneApp() {
|
|
3
|
+
return window.matchMedia('(display-mode: standalone)').matches;
|
|
4
|
+
}
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
export function isTouchSupported(){
|
|
1
|
+
export function isTouchSupported() {
|
|
2
|
+
// https://habr.com/ru/companies/ruvds/articles/556156/
|
|
3
|
+
return window.matchMedia('(any-pointer: coarse) and (any-hover: none)').matches;
|
|
4
|
+
}
|
package/preventDefault.d.ts
CHANGED
package/preventDefault.js
CHANGED
package/rafCallback.js
CHANGED
|
@@ -1 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
export function rafCallback(callback) {
|
|
3
|
+
let handle = 0;
|
|
4
|
+
const fn = ((...args) => {
|
|
5
|
+
handle = requestAnimationFrame(() => callback(...args));
|
|
6
|
+
});
|
|
7
|
+
fn.cancel = () => cancelAnimationFrame(handle);
|
|
8
|
+
return fn;
|
|
9
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MediaQueryListener, type MediaQueryEventHandler } from './MediaQueryListener';
|
|
2
|
+
import type { ViewSize } from './ViewSize';
|
|
3
|
+
export type { MediaQueryEvent, MediaQueryEventHandler } from './MediaQueryListener';
|
|
4
|
+
export declare abstract class MediaQuery {
|
|
5
|
+
private static _listener;
|
|
6
|
+
static get listener(): MediaQueryListener;
|
|
7
|
+
static get isInitialized(): boolean;
|
|
8
|
+
static get currentViewSize(): ViewSize;
|
|
9
|
+
static get currentViewSizeValues(): ViewSize.Values;
|
|
10
|
+
static addListener(listener: MediaQueryEventHandler): void;
|
|
11
|
+
static removeListener(listener: MediaQueryEventHandler): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Init all media queries for handle changes.
|
|
14
|
+
* Safe for multiple calls.
|
|
15
|
+
*/
|
|
16
|
+
static init(): ViewSize;
|
|
17
|
+
static destroy(): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-extraneous-class */
|
|
2
|
+
/* eslint-disable no-underscore-dangle */
|
|
3
|
+
import { MediaQueryListener } from './MediaQueryListener';
|
|
4
|
+
export class MediaQuery {
|
|
5
|
+
static _listener;
|
|
6
|
+
static get listener() {
|
|
7
|
+
if (!this._listener) {
|
|
8
|
+
throw new Error('Media queries is not initialized. You should initialize it before by call `init` method.');
|
|
9
|
+
}
|
|
10
|
+
return this._listener;
|
|
11
|
+
}
|
|
12
|
+
static get isInitialized() {
|
|
13
|
+
return this._listener != null;
|
|
14
|
+
}
|
|
15
|
+
static get currentViewSize() {
|
|
16
|
+
return this.listener.currentViewSize;
|
|
17
|
+
}
|
|
18
|
+
static get currentViewSizeValues() {
|
|
19
|
+
return this.listener.currentViewSizeQuery;
|
|
20
|
+
}
|
|
21
|
+
static addListener(listener) {
|
|
22
|
+
this.listener.addListener(listener);
|
|
23
|
+
}
|
|
24
|
+
static removeListener(listener) {
|
|
25
|
+
return this.listener.removeListener(listener);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Init all media queries for handle changes.
|
|
29
|
+
* Safe for multiple calls.
|
|
30
|
+
*/
|
|
31
|
+
static init() {
|
|
32
|
+
this._listener ??= new MediaQueryListener();
|
|
33
|
+
return this.currentViewSize;
|
|
34
|
+
}
|
|
35
|
+
static destroy() {
|
|
36
|
+
if (!this._listener)
|
|
37
|
+
return;
|
|
38
|
+
this._listener.destroy();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ViewSize } from './ViewSize';
|
|
2
|
+
export interface MediaQueryEvent extends Pick<MediaQueryListEvent, 'matches'> {
|
|
3
|
+
readonly viewSize: ViewSize;
|
|
4
|
+
}
|
|
5
|
+
export type MediaQueryEventHandler = (event: MediaQueryEvent) => void;
|
|
6
|
+
export declare class MediaQueryListener implements Disposable {
|
|
7
|
+
private _currentViewSize;
|
|
8
|
+
private readonly mediaQueries;
|
|
9
|
+
private readonly listeners;
|
|
10
|
+
readonly queries: Readonly<Record<ViewSize, string>>;
|
|
11
|
+
get currentViewSize(): ViewSize;
|
|
12
|
+
get currentViewSizeQuery(): ViewSize.Values;
|
|
13
|
+
/** Init all media queries for handle changes. */
|
|
14
|
+
constructor();
|
|
15
|
+
addListener(listener: MediaQueryEventHandler): void;
|
|
16
|
+
removeListener(listener: MediaQueryEventHandler): boolean;
|
|
17
|
+
destroy(): void;
|
|
18
|
+
[Symbol.dispose](): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
/* https://mediag.com/news/popular-screen-resolutions-designing-for-all/ */
|
|
3
|
+
/* http://viewportsizes.com */
|
|
4
|
+
import { ViewSize } from './ViewSize';
|
|
5
|
+
import { getViewSizeQueryMap } from './getViewSizeQueryMap';
|
|
6
|
+
export class MediaQueryListener {
|
|
7
|
+
_currentViewSize;
|
|
8
|
+
mediaQueries = [];
|
|
9
|
+
listeners = new Set();
|
|
10
|
+
queries;
|
|
11
|
+
get currentViewSize() {
|
|
12
|
+
if (this._currentViewSize == null) {
|
|
13
|
+
throw new Error(`Media queries is not initialized properly. Current view size is ${String(this._currentViewSize)}.`);
|
|
14
|
+
}
|
|
15
|
+
return this._currentViewSize;
|
|
16
|
+
}
|
|
17
|
+
get currentViewSizeQuery() {
|
|
18
|
+
return ViewSize.values[this.currentViewSize];
|
|
19
|
+
}
|
|
20
|
+
/** Init all media queries for handle changes. */
|
|
21
|
+
constructor() {
|
|
22
|
+
this.queries = getViewSizeQueryMap();
|
|
23
|
+
Object.entries(this.queries).forEach(([key, query]) => {
|
|
24
|
+
const viewSize = ViewSize.of(key);
|
|
25
|
+
const mq = window.matchMedia(query);
|
|
26
|
+
this.mediaQueries.push(mq);
|
|
27
|
+
mq.onchange = ({ matches }) => {
|
|
28
|
+
if (matches) {
|
|
29
|
+
this._currentViewSize = viewSize;
|
|
30
|
+
// console.log(viewSize);
|
|
31
|
+
}
|
|
32
|
+
this.listeners.forEach((handle) => handle({ viewSize, matches }));
|
|
33
|
+
};
|
|
34
|
+
// For initialize currentViewport with right value
|
|
35
|
+
if (mq.matches) {
|
|
36
|
+
this._currentViewSize = viewSize;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
addListener(listener) {
|
|
41
|
+
this.listeners.add(listener);
|
|
42
|
+
}
|
|
43
|
+
removeListener(listener) {
|
|
44
|
+
return this.listeners.delete(listener);
|
|
45
|
+
}
|
|
46
|
+
destroy() {
|
|
47
|
+
this.mediaQueries.splice(0, this.mediaQueries.length).forEach((mq) => {
|
|
48
|
+
mq.onchange = null;
|
|
49
|
+
});
|
|
50
|
+
this.listeners.clear();
|
|
51
|
+
}
|
|
52
|
+
[Symbol.dispose]() {
|
|
53
|
+
return this.destroy();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare enum ViewSize {
|
|
2
|
+
/** minWidth=0, maxWidth=319 */
|
|
3
|
+
xxxxs = 1,
|
|
4
|
+
/** minWidth=320, maxWidth=479 */
|
|
5
|
+
xxxs = 2,
|
|
6
|
+
/** minWidth=480, maxWidth=639 */
|
|
7
|
+
xxs = 3,
|
|
8
|
+
/** minWidth=640, maxWidth=827 */
|
|
9
|
+
xs = 4,
|
|
10
|
+
/** minWidth=828, maxWidth=1023 */
|
|
11
|
+
s = 5,
|
|
12
|
+
/** minWidth=1024, maxWidth=1365 */
|
|
13
|
+
m = 6,
|
|
14
|
+
/** minWidth=1366, maxWidth=1599 */
|
|
15
|
+
l = 7,
|
|
16
|
+
/** minWidth=1600, maxWidth=1919 */
|
|
17
|
+
xl = 8,
|
|
18
|
+
/** minWidth=1920, maxWidth=2559 */
|
|
19
|
+
xxl = 9,
|
|
20
|
+
/** minWidth=2560, maxWidth=3839 */
|
|
21
|
+
xxxl = 10,
|
|
22
|
+
/** minWidth=3840, maxWidth=7679 */
|
|
23
|
+
xxxxl = 11,
|
|
24
|
+
/** minWidth=7680, maxWidth=Number.MAX_SAFE_INTEGER */
|
|
25
|
+
xxxxxl = 12
|
|
26
|
+
}
|
|
27
|
+
export declare namespace ViewSize {
|
|
28
|
+
type Type = ExtractKeysOfType<typeof ViewSize, number>;
|
|
29
|
+
type Keys = keyof Type;
|
|
30
|
+
interface Values {
|
|
31
|
+
readonly minWidth: number;
|
|
32
|
+
readonly maxWidth: number;
|
|
33
|
+
}
|
|
34
|
+
/** All values are unique. */
|
|
35
|
+
const values: Readonly<Record<ViewSize, Values>>;
|
|
36
|
+
function of(viewSizeNumber: string): ViewSize;
|
|
37
|
+
function keyOf(viewSize: ViewSize): Keys;
|
|
38
|
+
/** Sorted values. */
|
|
39
|
+
const valueList: readonly (readonly [ViewSize, Values])[];
|
|
40
|
+
function get(width: number): ViewSize;
|
|
41
|
+
function lt(size: ViewSize, than: ViewSize): boolean;
|
|
42
|
+
function lte(size: ViewSize, than: ViewSize): boolean;
|
|
43
|
+
function gt(size: ViewSize, than: ViewSize): boolean;
|
|
44
|
+
function gte(size: ViewSize, than: ViewSize): boolean;
|
|
45
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export var ViewSize;
|
|
2
|
+
(function (ViewSize) {
|
|
3
|
+
/** minWidth=0, maxWidth=319 */
|
|
4
|
+
ViewSize[ViewSize["xxxxs"] = 1] = "xxxxs";
|
|
5
|
+
/** minWidth=320, maxWidth=479 */
|
|
6
|
+
ViewSize[ViewSize["xxxs"] = 2] = "xxxs";
|
|
7
|
+
/** minWidth=480, maxWidth=639 */
|
|
8
|
+
ViewSize[ViewSize["xxs"] = 3] = "xxs";
|
|
9
|
+
/** minWidth=640, maxWidth=827 */
|
|
10
|
+
ViewSize[ViewSize["xs"] = 4] = "xs";
|
|
11
|
+
/** minWidth=828, maxWidth=1023 */
|
|
12
|
+
ViewSize[ViewSize["s"] = 5] = "s";
|
|
13
|
+
/** minWidth=1024, maxWidth=1365 */
|
|
14
|
+
ViewSize[ViewSize["m"] = 6] = "m";
|
|
15
|
+
/** minWidth=1366, maxWidth=1599 */
|
|
16
|
+
ViewSize[ViewSize["l"] = 7] = "l";
|
|
17
|
+
/** minWidth=1600, maxWidth=1919 */
|
|
18
|
+
ViewSize[ViewSize["xl"] = 8] = "xl";
|
|
19
|
+
/** minWidth=1920, maxWidth=2559 */
|
|
20
|
+
ViewSize[ViewSize["xxl"] = 9] = "xxl";
|
|
21
|
+
/** minWidth=2560, maxWidth=3839 */
|
|
22
|
+
ViewSize[ViewSize["xxxl"] = 10] = "xxxl";
|
|
23
|
+
/** minWidth=3840, maxWidth=7679 */
|
|
24
|
+
ViewSize[ViewSize["xxxxl"] = 11] = "xxxxl";
|
|
25
|
+
/** minWidth=7680, maxWidth=Number.MAX_SAFE_INTEGER */
|
|
26
|
+
ViewSize[ViewSize["xxxxxl"] = 12] = "xxxxxl";
|
|
27
|
+
})(ViewSize || (ViewSize = {}));
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
29
|
+
(function (ViewSize) {
|
|
30
|
+
/** All values are unique. */
|
|
31
|
+
ViewSize.values = {
|
|
32
|
+
[ViewSize.xxxxs]: { minWidth: 0, maxWidth: 319 },
|
|
33
|
+
[ViewSize.xxxs]: { minWidth: 320, maxWidth: 479 },
|
|
34
|
+
[ViewSize.xxs]: { minWidth: 480, maxWidth: 639 },
|
|
35
|
+
[ViewSize.xs]: { minWidth: 640, maxWidth: 827 },
|
|
36
|
+
[ViewSize.s]: { minWidth: 828, maxWidth: 1023 },
|
|
37
|
+
[ViewSize.m]: { minWidth: 1024, maxWidth: 1365 },
|
|
38
|
+
[ViewSize.l]: { minWidth: 1366, maxWidth: 1599 },
|
|
39
|
+
[ViewSize.xl]: { minWidth: 1600, maxWidth: 1919 },
|
|
40
|
+
[ViewSize.xxl]: { minWidth: 1920, maxWidth: 2559 },
|
|
41
|
+
[ViewSize.xxxl]: { minWidth: 2560, maxWidth: 3839 },
|
|
42
|
+
[ViewSize.xxxxl]: { minWidth: 3840, maxWidth: 7679 },
|
|
43
|
+
[ViewSize.xxxxxl]: { minWidth: 7680, maxWidth: Number.MAX_SAFE_INTEGER },
|
|
44
|
+
};
|
|
45
|
+
function of(viewSizeNumber) {
|
|
46
|
+
const num = +viewSizeNumber;
|
|
47
|
+
const key = (Number.isFinite(num) ? ViewSize[num] : viewSizeNumber);
|
|
48
|
+
return ViewSize[key];
|
|
49
|
+
}
|
|
50
|
+
ViewSize.of = of;
|
|
51
|
+
function keyOf(viewSize) {
|
|
52
|
+
return ViewSize[viewSize];
|
|
53
|
+
}
|
|
54
|
+
ViewSize.keyOf = keyOf;
|
|
55
|
+
/** Sorted values. */
|
|
56
|
+
ViewSize.valueList = Object.entries(ViewSize.values)
|
|
57
|
+
.map(([key, value]) => [of(key), value])
|
|
58
|
+
.sort(([, a], [, b]) => a.minWidth - b.minWidth);
|
|
59
|
+
function get(width) {
|
|
60
|
+
const viewSize = ViewSize.valueList.find(([, value]) => width >= value.minWidth && width <= value.maxWidth)?.[0] ??
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
62
|
+
ViewSize.valueList.at(-1)[0];
|
|
63
|
+
return viewSize;
|
|
64
|
+
}
|
|
65
|
+
ViewSize.get = get;
|
|
66
|
+
function lt(size, than) {
|
|
67
|
+
return size < than;
|
|
68
|
+
}
|
|
69
|
+
ViewSize.lt = lt;
|
|
70
|
+
function lte(size, than) {
|
|
71
|
+
return size <= than;
|
|
72
|
+
}
|
|
73
|
+
ViewSize.lte = lte;
|
|
74
|
+
function gt(size, than) {
|
|
75
|
+
return size > than;
|
|
76
|
+
}
|
|
77
|
+
ViewSize.gt = gt;
|
|
78
|
+
function gte(size, than) {
|
|
79
|
+
return size >= than;
|
|
80
|
+
}
|
|
81
|
+
ViewSize.gte = gte;
|
|
82
|
+
})(ViewSize || (ViewSize = {}));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ViewSize } from './ViewSize';
|
|
2
|
+
export function getViewSizeQueryMap() {
|
|
3
|
+
return ViewSize.valueList.reduce((acc, [viewSize, { minWidth, maxWidth }]) => {
|
|
4
|
+
acc[viewSize] = `only screen and (min-width: ${minWidth}px) and (max-width: ${maxWidth}px)`;
|
|
5
|
+
return acc;
|
|
6
|
+
}, {});
|
|
7
|
+
}
|
package/saveFileAs.js
CHANGED
|
@@ -1 +1,22 @@
|
|
|
1
|
-
export function saveFileAs(
|
|
1
|
+
export function saveFileAs(filename, url, attrs) {
|
|
2
|
+
const link = document.createElement('a');
|
|
3
|
+
link.setAttribute('href', url);
|
|
4
|
+
link.setAttribute('download', filename);
|
|
5
|
+
link.setAttribute('type', 'attachment');
|
|
6
|
+
if (attrs) {
|
|
7
|
+
Object.entries(attrs).forEach(([name, value]) => {
|
|
8
|
+
link.setAttribute(name, value);
|
|
9
|
+
if (name === 'target' && value === '_blank' && attrs.rel == null) {
|
|
10
|
+
link.setAttribute('rel', 'noopener noreferrer');
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
link.click();
|
|
15
|
+
}
|
|
16
|
+
// if (document.createEvent) {
|
|
17
|
+
// const event = document.createEvent('MouseEvents');
|
|
18
|
+
// event.initEvent('click', true, true);
|
|
19
|
+
// link.dispatchEvent(event);
|
|
20
|
+
// } else {
|
|
21
|
+
// link.click();
|
|
22
|
+
// }
|
|
@@ -23,7 +23,6 @@ export declare class ServiceWorkerInstaller extends EventEmitter<{
|
|
|
23
23
|
static isAvailable(): boolean;
|
|
24
24
|
private registration;
|
|
25
25
|
private cancelDefferedRegister;
|
|
26
|
-
constructor();
|
|
27
26
|
register(swUrl: string | URL, options?: ServiceWorkerInstaller.RegistrationOptions): void;
|
|
28
27
|
unregister(): void;
|
|
29
28
|
destroy(): void;
|