adjacent-react 0.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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +45 -0
- package/dist/badge/app-badge.d.ts +36 -0
- package/dist/badge/app-badge.d.ts.map +1 -0
- package/dist/badge/app-badge.js +49 -0
- package/dist/badge/app-badge.js.map +1 -0
- package/dist/badge/use-app-badge.d.ts +12 -0
- package/dist/badge/use-app-badge.d.ts.map +1 -0
- package/dist/badge/use-app-badge.js +20 -0
- package/dist/badge/use-app-badge.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/install/install-element.d.ts +19 -0
- package/dist/install/install-element.d.ts.map +1 -0
- package/dist/install/install-element.js +16 -0
- package/dist/install/install-element.js.map +1 -0
- package/dist/install/install-store.d.ts +33 -0
- package/dist/install/install-store.d.ts.map +1 -0
- package/dist/install/install-store.js +74 -0
- package/dist/install/install-store.js.map +1 -0
- package/dist/install/use-install.d.ts +7 -0
- package/dist/install/use-install.d.ts.map +1 -0
- package/dist/install/use-install.js +8 -0
- package/dist/install/use-install.js.map +1 -0
- package/dist/media/media-session.d.ts +38 -0
- package/dist/media/media-session.d.ts.map +1 -0
- package/dist/media/media-session.js +42 -0
- package/dist/media/media-session.js.map +1 -0
- package/dist/media/use-media-session.d.ts +24 -0
- package/dist/media/use-media-session.d.ts.map +1 -0
- package/dist/media/use-media-session.js +87 -0
- package/dist/media/use-media-session.js.map +1 -0
- package/dist/notifications/notifications.d.ts +48 -0
- package/dist/notifications/notifications.d.ts.map +1 -0
- package/dist/notifications/notifications.js +42 -0
- package/dist/notifications/notifications.js.map +1 -0
- package/dist/notifications/push.d.ts +26 -0
- package/dist/notifications/push.d.ts.map +1 -0
- package/dist/notifications/push.js +61 -0
- package/dist/notifications/push.js.map +1 -0
- package/dist/notifications/use-notifications.d.ts +12 -0
- package/dist/notifications/use-notifications.d.ts.map +1 -0
- package/dist/notifications/use-notifications.js +61 -0
- package/dist/notifications/use-notifications.js.map +1 -0
- package/dist/runtime/runtime-store.d.ts +58 -0
- package/dist/runtime/runtime-store.d.ts.map +1 -0
- package/dist/runtime/runtime-store.js +166 -0
- package/dist/runtime/runtime-store.js.map +1 -0
- package/dist/runtime/use-adjacent.d.ts +14 -0
- package/dist/runtime/use-adjacent.d.ts.map +1 -0
- package/dist/runtime/use-adjacent.js +18 -0
- package/dist/runtime/use-adjacent.js.map +1 -0
- package/package.json +66 -0
package/CHANGELOG.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eric Kweyunga
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# adjacent-react
|
|
2
|
+
|
|
3
|
+
Installation state and progressive web app runtime hooks for React.
|
|
4
|
+
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- [Installation prompt](https://github.com/erickweyunga/adjacent-framework/blob/main/docs/install-prompt.md)
|
|
8
|
+
- [Application lifecycle](https://github.com/erickweyunga/adjacent-framework/blob/main/docs/lifecycle.md)
|
|
9
|
+
- [All the documentation](https://github.com/erickweyunga/adjacent-framework/blob/main/docs/README.md)
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install adjacent-react
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Most projects get this through the CLI instead, which installs and wires it up:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx adjacent-cli init
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Adjacent ships no install button. `useInstall()` reports whether the browser
|
|
24
|
+
can prompt and which platform to write instructions for; `useAdjacent()` adds
|
|
25
|
+
connectivity, service worker state, update activation, and cache control.
|
|
26
|
+
`useMediaSession()` publishes what is playing to the lock screen, the OS media
|
|
27
|
+
control and the hardware keys. `useAppBadge()` puts a count on the application
|
|
28
|
+
icon, and `useNotifications()` covers permission and showing, with
|
|
29
|
+
`subscribeToPush()` for messages that arrive when the app is closed. What any
|
|
30
|
+
of it looks like is the application's decision.
|
|
31
|
+
|
|
32
|
+
## Issues
|
|
33
|
+
|
|
34
|
+
If you hit a problem using this package, please
|
|
35
|
+
[report it here](https://github.com/erickweyunga/adjacent-framework/issues/new).
|
|
36
|
+
|
|
37
|
+
## Contributing
|
|
38
|
+
|
|
39
|
+
Issues and pull requests are welcome. Please read the
|
|
40
|
+
[contributing guide](https://github.com/erickweyunga/adjacent-framework/blob/main/CONTRIBUTING.md)
|
|
41
|
+
first.
|
|
42
|
+
|
|
43
|
+
## License
|
|
44
|
+
|
|
45
|
+
MIT
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What to show on the application's icon. A number shows a count, `"dot"`
|
|
3
|
+
* shows a mark with no number, and null or undefined removes the badge.
|
|
4
|
+
*/
|
|
5
|
+
export type AppBadgeValue = number | "dot" | null | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Whether the icon can carry a badge. False on the server.
|
|
8
|
+
*
|
|
9
|
+
* Checked at runtime rather than trusted from the types: TypeScript's DOM
|
|
10
|
+
* library declares both methods unconditionally, and a browser without them is
|
|
11
|
+
* exactly the case this exists for.
|
|
12
|
+
*/
|
|
13
|
+
export declare function supportsAppBadge(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* What to call for a value, since the API spells "no badge" three ways and
|
|
16
|
+
* "count of zero" is one of them: `setAppBadge(0)` clears rather than showing a
|
|
17
|
+
* zero, so a count that has fallen to nothing needs no special case at the call
|
|
18
|
+
* site.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveBadgeCall(value: AppBadgeValue): {
|
|
21
|
+
readonly kind: "clear";
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: "set";
|
|
24
|
+
readonly count?: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Puts a badge on the application's icon, or takes it off.
|
|
28
|
+
*
|
|
29
|
+
* Resolves false where the browser has no badging rather than throwing, since
|
|
30
|
+
* a badge is an enhancement and no application should branch on it. A browser
|
|
31
|
+
* that has the API and still refuses does throw, because that is a real fault.
|
|
32
|
+
*/
|
|
33
|
+
export declare function setAppBadge(value: AppBadgeValue): Promise<boolean>;
|
|
34
|
+
/** Takes the badge off the icon. */
|
|
35
|
+
export declare function clearAppBadge(): Promise<boolean>;
|
|
36
|
+
//# sourceMappingURL=app-badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-badge.d.ts","sourceRoot":"","sources":["../../src/badge/app-badge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;AAE9D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,aAAa,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAMhF;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAWxE;AAED,oCAAoC;AACpC,wBAAgB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAEhD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the icon can carry a badge. False on the server.
|
|
3
|
+
*
|
|
4
|
+
* Checked at runtime rather than trusted from the types: TypeScript's DOM
|
|
5
|
+
* library declares both methods unconditionally, and a browser without them is
|
|
6
|
+
* exactly the case this exists for.
|
|
7
|
+
*/
|
|
8
|
+
export function supportsAppBadge() {
|
|
9
|
+
return typeof navigator !== "undefined" && typeof navigator.setAppBadge === "function";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* What to call for a value, since the API spells "no badge" three ways and
|
|
13
|
+
* "count of zero" is one of them: `setAppBadge(0)` clears rather than showing a
|
|
14
|
+
* zero, so a count that has fallen to nothing needs no special case at the call
|
|
15
|
+
* site.
|
|
16
|
+
*/
|
|
17
|
+
export function resolveBadgeCall(value) {
|
|
18
|
+
if (value === null || value === undefined)
|
|
19
|
+
return { kind: "clear" };
|
|
20
|
+
if (value === "dot")
|
|
21
|
+
return { kind: "set" };
|
|
22
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
23
|
+
return { kind: "clear" };
|
|
24
|
+
// Fractions are not a count, and the API floors them anyway.
|
|
25
|
+
return { kind: "set", count: Math.floor(value) };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Puts a badge on the application's icon, or takes it off.
|
|
29
|
+
*
|
|
30
|
+
* Resolves false where the browser has no badging rather than throwing, since
|
|
31
|
+
* a badge is an enhancement and no application should branch on it. A browser
|
|
32
|
+
* that has the API and still refuses does throw, because that is a real fault.
|
|
33
|
+
*/
|
|
34
|
+
export async function setAppBadge(value) {
|
|
35
|
+
if (!supportsAppBadge())
|
|
36
|
+
return false;
|
|
37
|
+
const call = resolveBadgeCall(value);
|
|
38
|
+
if (call.kind === "clear") {
|
|
39
|
+
await navigator.clearAppBadge();
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
await navigator.setAppBadge(call.count);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
/** Takes the badge off the icon. */
|
|
46
|
+
export function clearAppBadge() {
|
|
47
|
+
return setAppBadge(null);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=app-badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-badge.js","sourceRoot":"","sources":["../../src/badge/app-badge.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,SAAS,KAAK,WAAW,IAAI,OAAO,SAAS,CAAC,WAAW,KAAK,UAAU,CAAC;AACzF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAoB;IAEpB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACpE,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACpE,6DAA6D;IAC7D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAoB;IACpD,IAAI,CAAC,gBAAgB,EAAE;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAErC,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,MAAM,SAAS,CAAC,aAAa,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type AppBadgeValue } from "./app-badge.js";
|
|
2
|
+
/**
|
|
3
|
+
* Keeps the application icon's badge in step with a value, so the badge is
|
|
4
|
+
* described rather than pushed: render with three unread and the icon says
|
|
5
|
+
* three, render with none and it clears.
|
|
6
|
+
*
|
|
7
|
+
* The badge is not cleared when the component unmounts. It belongs to the
|
|
8
|
+
* installed application rather than to a screen, and a count that survives the
|
|
9
|
+
* app being closed is the entire point of it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useAppBadge(value: AppBadgeValue): void;
|
|
12
|
+
//# sourceMappingURL=use-app-badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-app-badge.d.ts","sourceRoot":"","sources":["../../src/badge/use-app-badge.ts"],"names":[],"mappings":"AAIA,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEjE;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAMtD"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { setAppBadge } from "./app-badge.js";
|
|
4
|
+
/**
|
|
5
|
+
* Keeps the application icon's badge in step with a value, so the badge is
|
|
6
|
+
* described rather than pushed: render with three unread and the icon says
|
|
7
|
+
* three, render with none and it clears.
|
|
8
|
+
*
|
|
9
|
+
* The badge is not cleared when the component unmounts. It belongs to the
|
|
10
|
+
* installed application rather than to a screen, and a count that survives the
|
|
11
|
+
* app being closed is the entire point of it.
|
|
12
|
+
*/
|
|
13
|
+
export function useAppBadge(value) {
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
// Rejections are swallowed: a badge is an enhancement, and a host that
|
|
16
|
+
// refuses one must not take the render down with it.
|
|
17
|
+
void setAppBadge(value).catch(() => undefined);
|
|
18
|
+
}, [value]);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=use-app-badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-app-badge.js","sourceRoot":"","sources":["../../src/badge/use-app-badge.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,WAAW,EAAsB,MAAM,gBAAgB,CAAC;AAEjE;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAoB;IAC9C,SAAS,CAAC,GAAG,EAAE;QACb,uEAAuE;QACvE,qDAAqD;QACrD,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACjD,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AACd,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { clearAppBadge, resolveBadgeCall, setAppBadge, supportsAppBadge, type AppBadgeValue, } from "./badge/app-badge.js";
|
|
2
|
+
export { useAppBadge } from "./badge/use-app-badge.js";
|
|
3
|
+
export { Install, supportsInstallElement, type InstallProps } from "./install/install-element.js";
|
|
4
|
+
export { detectManualInstallPlatform, type InstallOutcome, type InstallState, type ManualInstallPlatform, } from "./install/install-store.js";
|
|
5
|
+
export { useInstall, type UseInstallResult } from "./install/use-install.js";
|
|
6
|
+
export { supportsMediaSession, toMetadataInit, toPositionState, type MediaSessionActionName, type MediaSessionArtwork, type MediaSessionMetadata, type MediaSessionPlaybackState, type MediaSessionPosition, } from "./media/media-session.js";
|
|
7
|
+
export { canRequestNotificationPermission, readNotificationPermission, requestNotificationPermission, showNotification, supportsNotifications, type NotificationAction, type NotificationPermissionState, type ShowNotificationOptions, } from "./notifications/notifications.js";
|
|
8
|
+
export { decodeVapidKey, getPushSubscription, subscribeToPush, supportsPush, unsubscribeFromPush, } from "./notifications/push.js";
|
|
9
|
+
export { useNotifications, type UseNotificationsResult, } from "./notifications/use-notifications.js";
|
|
10
|
+
export { useMediaSession, type MediaSessionHandlers, type UseMediaSessionOptions, } from "./media/use-media-session.js";
|
|
11
|
+
export { type AdjacentRuntimeSnapshot, type ConnectivityState, type ServiceWorkerState, } from "./runtime/runtime-store.js";
|
|
12
|
+
export { useAdjacent, type UseAdjacentResult } from "./runtime/use-adjacent.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,KAAK,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAClG,OAAO,EACL,2BAA2B,EAC3B,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,qBAAqB,GAC3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,GAC1B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,gCAAgC,EAChC,0BAA0B,EAC1B,6BAA6B,EAC7B,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,uBAAuB,GAC7B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,gBAAgB,EAChB,KAAK,sBAAsB,GAC5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { clearAppBadge, resolveBadgeCall, setAppBadge, supportsAppBadge, } from "./badge/app-badge.js";
|
|
2
|
+
export { useAppBadge } from "./badge/use-app-badge.js";
|
|
3
|
+
export { Install, supportsInstallElement } from "./install/install-element.js";
|
|
4
|
+
export { detectManualInstallPlatform, } from "./install/install-store.js";
|
|
5
|
+
export { useInstall } from "./install/use-install.js";
|
|
6
|
+
export { supportsMediaSession, toMetadataInit, toPositionState, } from "./media/media-session.js";
|
|
7
|
+
export { canRequestNotificationPermission, readNotificationPermission, requestNotificationPermission, showNotification, supportsNotifications, } from "./notifications/notifications.js";
|
|
8
|
+
export { decodeVapidKey, getPushSubscription, subscribeToPush, supportsPush, unsubscribeFromPush, } from "./notifications/push.js";
|
|
9
|
+
export { useNotifications, } from "./notifications/use-notifications.js";
|
|
10
|
+
export { useMediaSession, } from "./media/use-media-session.js";
|
|
11
|
+
export { useAdjacent } from "./runtime/use-adjacent.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,gBAAgB,GAEjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAqB,MAAM,8BAA8B,CAAC;AAClG,OAAO,EACL,2BAA2B,GAI5B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,UAAU,EAAyB,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,eAAe,GAMhB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,gCAAgC,EAChC,0BAA0B,EAC1B,6BAA6B,EAC7B,gBAAgB,EAChB,qBAAqB,GAItB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,gBAAgB,GAEjB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,eAAe,GAGhB,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAAE,WAAW,EAA0B,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
+
declare module "react" {
|
|
3
|
+
namespace JSX {
|
|
4
|
+
interface IntrinsicElements {
|
|
5
|
+
install: import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement> & {
|
|
6
|
+
readonly installurl?: string;
|
|
7
|
+
readonly manifestid?: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export interface InstallProps extends HTMLAttributes<HTMLElement> {
|
|
13
|
+
readonly children: ReactNode;
|
|
14
|
+
readonly installUrl?: string;
|
|
15
|
+
readonly manifestId?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function supportsInstallElement(browserWindow: Window): boolean;
|
|
18
|
+
export declare function Install({ children, installUrl, manifestId, ...elementProps }: InstallProps): import("react").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=install-element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-element.d.ts","sourceRoot":"","sources":["../../src/install/install-element.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AAEf,OAAO,QAAQ,OAAO,CAAC;IACrB,UAAU,GAAG,CAAC;QACZ,UAAU,iBAAiB;YAMzB,OAAO,EAAE,OAAO,OAAO,EAAE,iBAAiB,CACxC,OAAO,OAAO,EAAE,cAAc,CAAC,WAAW,CAAC,EAC3C,WAAW,CACZ,GAAG;gBACF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;aAC9B,CAAC;SACH;KACF;CACF;AAED,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAC,WAAW,CAAC;IAC/D,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAErE;AAED,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,UAAU,EACV,UAAU,EACV,GAAG,YAAY,EAChB,EAAE,YAAY,+BAcd"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState, } from "react";
|
|
4
|
+
export function supportsInstallElement(browserWindow) {
|
|
5
|
+
return "HTMLInstallElement" in browserWindow;
|
|
6
|
+
}
|
|
7
|
+
export function Install({ children, installUrl, manifestId, ...elementProps }) {
|
|
8
|
+
const [isSupported, setIsSupported] = useState(false);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
setIsSupported(supportsInstallElement(window));
|
|
11
|
+
}, []);
|
|
12
|
+
if (!isSupported)
|
|
13
|
+
return _jsx(_Fragment, { children: children });
|
|
14
|
+
return (_jsx("install", { ...elementProps, installurl: installUrl, manifestid: manifestId, children: children }));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=install-element.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-element.js","sourceRoot":"","sources":["../../src/install/install-element.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAGL,SAAS,EACT,QAAQ,GACT,MAAM,OAAO,CAAC;AA2Bf,MAAM,UAAU,sBAAsB,CAAC,aAAqB;IAC1D,OAAO,oBAAoB,IAAI,aAAa,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,EACtB,QAAQ,EACR,UAAU,EACV,UAAU,EACV,GAAG,YAAY,EACF;IACb,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEtD,SAAS,CAAC,GAAG,EAAE;QACb,cAAc,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,IAAI,CAAC,WAAW;QAAE,OAAO,4BAAG,QAAQ,GAAI,CAAC;IAEzC,OAAO,CACL,qBAAa,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,YACtE,QAAQ,GACD,CACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type ManualInstallPlatform = "android" | "browser" | "ios" | "macos";
|
|
2
|
+
export type InstallState = {
|
|
3
|
+
readonly status: "checking";
|
|
4
|
+
} | {
|
|
5
|
+
readonly status: "available";
|
|
6
|
+
} | {
|
|
7
|
+
readonly status: "manual";
|
|
8
|
+
readonly platform: ManualInstallPlatform;
|
|
9
|
+
} | {
|
|
10
|
+
readonly status: "installed";
|
|
11
|
+
} | {
|
|
12
|
+
readonly status: "unavailable";
|
|
13
|
+
};
|
|
14
|
+
export type InstallOutcome = "accepted" | "dismissed" | "manual" | "unavailable";
|
|
15
|
+
type Listener = () => void;
|
|
16
|
+
export declare function detectManualInstallPlatform(userAgent: string): ManualInstallPlatform;
|
|
17
|
+
declare class InstallStore {
|
|
18
|
+
private deferredPrompt?;
|
|
19
|
+
private listening;
|
|
20
|
+
private readonly listeners;
|
|
21
|
+
private state;
|
|
22
|
+
readonly subscribe: (listener: Listener) => (() => void);
|
|
23
|
+
readonly getSnapshot: () => InstallState;
|
|
24
|
+
readonly getServerSnapshot: () => InstallState;
|
|
25
|
+
readonly prompt: () => Promise<InstallOutcome>;
|
|
26
|
+
private readonly onBeforeInstallPrompt;
|
|
27
|
+
private readonly onInstalled;
|
|
28
|
+
private start;
|
|
29
|
+
private setState;
|
|
30
|
+
}
|
|
31
|
+
export declare const installStore: InstallStore;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=install-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-store.d.ts","sourceRoot":"","sources":["../../src/install/install-store.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,OAAO,CAAC;AAE5E,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GAC/B;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC;AAEvC,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;AAMjF,KAAK,QAAQ,GAAG,MAAM,IAAI,CAAC;AAc3B,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,GAChB,qBAAqB,CAOvB;AAED,cAAM,YAAY;IAChB,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuB;IACjD,OAAO,CAAC,KAAK,CAAwC;IAErD,QAAQ,CAAC,SAAS,GAAI,UAAU,QAAQ,KAAG,CAAC,MAAM,IAAI,CAAC,CAIrD;IAEF,QAAQ,CAAC,WAAW,QAAO,YAAY,CAAe;IAEtD,QAAQ,CAAC,iBAAiB,QAAO,YAAY,CAAiB;IAE9D,QAAQ,CAAC,MAAM,QAAa,OAAO,CAAC,cAAc,CAAC,CAkBjD;IAEF,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAIpC;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAG1B;IAEF,OAAO,CAAC,KAAK;IAeb,OAAO,CAAC,QAAQ;CAIjB;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const SERVER_STATE = { status: "checking" };
|
|
2
|
+
function isStandalone() {
|
|
3
|
+
const navigatorWithStandalone = navigator;
|
|
4
|
+
return (window.matchMedia("(display-mode: standalone)").matches ||
|
|
5
|
+
navigatorWithStandalone.standalone === true);
|
|
6
|
+
}
|
|
7
|
+
export function detectManualInstallPlatform(userAgent) {
|
|
8
|
+
if (/iPad|iPhone|iPod/i.test(userAgent))
|
|
9
|
+
return "ios";
|
|
10
|
+
if (/Android/i.test(userAgent))
|
|
11
|
+
return "android";
|
|
12
|
+
if (/Macintosh/i.test(userAgent) && /Safari/i.test(userAgent) && !/Chrome|Chromium|Edg/i.test(userAgent)) {
|
|
13
|
+
return "macos";
|
|
14
|
+
}
|
|
15
|
+
return "browser";
|
|
16
|
+
}
|
|
17
|
+
class InstallStore {
|
|
18
|
+
deferredPrompt;
|
|
19
|
+
listening = false;
|
|
20
|
+
listeners = new Set();
|
|
21
|
+
state = { status: "checking" };
|
|
22
|
+
subscribe = (listener) => {
|
|
23
|
+
this.listeners.add(listener);
|
|
24
|
+
this.start();
|
|
25
|
+
return () => this.listeners.delete(listener);
|
|
26
|
+
};
|
|
27
|
+
getSnapshot = () => this.state;
|
|
28
|
+
getServerSnapshot = () => SERVER_STATE;
|
|
29
|
+
prompt = async () => {
|
|
30
|
+
if (this.state.status === "manual")
|
|
31
|
+
return "manual";
|
|
32
|
+
if (this.state.status !== "available" || !this.deferredPrompt) {
|
|
33
|
+
return "unavailable";
|
|
34
|
+
}
|
|
35
|
+
const prompt = this.deferredPrompt;
|
|
36
|
+
this.deferredPrompt = undefined;
|
|
37
|
+
const { outcome } = await prompt.prompt();
|
|
38
|
+
this.setState(outcome === "accepted"
|
|
39
|
+
? { status: "installed" }
|
|
40
|
+
: {
|
|
41
|
+
platform: detectManualInstallPlatform(navigator.userAgent),
|
|
42
|
+
status: "manual",
|
|
43
|
+
});
|
|
44
|
+
return outcome;
|
|
45
|
+
};
|
|
46
|
+
onBeforeInstallPrompt = (event) => {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
this.deferredPrompt = event;
|
|
49
|
+
this.setState({ status: "available" });
|
|
50
|
+
};
|
|
51
|
+
onInstalled = () => {
|
|
52
|
+
this.deferredPrompt = undefined;
|
|
53
|
+
this.setState({ status: "installed" });
|
|
54
|
+
};
|
|
55
|
+
start() {
|
|
56
|
+
if (this.listening || typeof window === "undefined")
|
|
57
|
+
return;
|
|
58
|
+
this.listening = true;
|
|
59
|
+
if (isStandalone()) {
|
|
60
|
+
this.setState({ status: "installed" });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const platform = detectManualInstallPlatform(navigator.userAgent);
|
|
64
|
+
this.setState({ status: "manual", platform });
|
|
65
|
+
window.addEventListener("beforeinstallprompt", this.onBeforeInstallPrompt);
|
|
66
|
+
window.addEventListener("appinstalled", this.onInstalled);
|
|
67
|
+
}
|
|
68
|
+
setState(state) {
|
|
69
|
+
this.state = state;
|
|
70
|
+
this.listeners.forEach((listener) => listener());
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export const installStore = new InstallStore();
|
|
74
|
+
//# sourceMappingURL=install-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-store.js","sourceRoot":"","sources":["../../src/install/install-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type InstallOutcome, type InstallState } from "./install-store.js";
|
|
2
|
+
export interface UseInstallResult {
|
|
3
|
+
readonly install: () => Promise<InstallOutcome>;
|
|
4
|
+
readonly state: InstallState;
|
|
5
|
+
}
|
|
6
|
+
export declare function useInstall(): UseInstallResult;
|
|
7
|
+
//# sourceMappingURL=use-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-install.d.ts","sourceRoot":"","sources":["../../src/install/use-install.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE1F,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;CAC9B;AAED,wBAAgB,UAAU,IAAI,gBAAgB,CAQ7C"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useSyncExternalStore } from "react";
|
|
3
|
+
import { installStore } from "./install-store.js";
|
|
4
|
+
export function useInstall() {
|
|
5
|
+
const state = useSyncExternalStore(installStore.subscribe, installStore.getSnapshot, installStore.getServerSnapshot);
|
|
6
|
+
return { install: installStore.prompt, state };
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=use-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-install.js","sourceRoot":"","sources":["../../src/install/use-install.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAAE,YAAY,EAA0C,MAAM,oBAAoB,CAAC;AAO1F,MAAM,UAAU,UAAU;IACxB,MAAM,KAAK,GAAG,oBAAoB,CAChC,YAAY,CAAC,SAAS,EACtB,YAAY,CAAC,WAAW,EACxB,YAAY,CAAC,iBAAiB,CAC/B,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** The actions a host can offer, in the order a media control usually shows them. */
|
|
2
|
+
export type MediaSessionActionName = "nexttrack" | "pause" | "play" | "previoustrack" | "seekbackward" | "seekforward" | "seekto" | "stop";
|
|
3
|
+
export type MediaSessionPlaybackState = "none" | "paused" | "playing";
|
|
4
|
+
export interface MediaSessionArtwork {
|
|
5
|
+
readonly sizes?: string;
|
|
6
|
+
readonly src: string;
|
|
7
|
+
readonly type?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface MediaSessionMetadata {
|
|
10
|
+
readonly album?: string;
|
|
11
|
+
readonly artist?: string;
|
|
12
|
+
/**
|
|
13
|
+
* What the lock screen and the OS media control show. Several sizes let the
|
|
14
|
+
* host pick rather than scale one.
|
|
15
|
+
*/
|
|
16
|
+
readonly artwork?: readonly MediaSessionArtwork[];
|
|
17
|
+
readonly title: string;
|
|
18
|
+
}
|
|
19
|
+
export interface MediaSessionPosition {
|
|
20
|
+
/** Seconds. An element that has not loaded its metadata reports NaN here. */
|
|
21
|
+
readonly duration: number;
|
|
22
|
+
readonly playbackRate?: number;
|
|
23
|
+
readonly position?: number;
|
|
24
|
+
}
|
|
25
|
+
/** Whether this browser has the API at all. False on the server. */
|
|
26
|
+
export declare function supportsMediaSession(): boolean;
|
|
27
|
+
export declare function toMetadataInit(metadata: MediaSessionMetadata): MediaMetadataInit;
|
|
28
|
+
/**
|
|
29
|
+
* The position a host can actually be told, or undefined when there is none.
|
|
30
|
+
*
|
|
31
|
+
* `setPositionState` throws rather than ignoring a value it dislikes, and the
|
|
32
|
+
* values it dislikes are the ones a media element produces normally: `duration`
|
|
33
|
+
* is NaN until metadata loads, and `currentTime` can overshoot the duration by
|
|
34
|
+
* a frame at the end of a track. Both would otherwise throw in a timeupdate
|
|
35
|
+
* handler, which is to say sixty times a second.
|
|
36
|
+
*/
|
|
37
|
+
export declare function toPositionState(position: MediaSessionPosition): MediaPositionState | undefined;
|
|
38
|
+
//# sourceMappingURL=media-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-session.d.ts","sourceRoot":"","sources":["../../src/media/media-session.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,MAAM,MAAM,sBAAsB,GAC9B,WAAW,GACX,OAAO,GACP,MAAM,GACN,eAAe,GACf,cAAc,GACd,aAAa,GACb,QAAQ,GACR,MAAM,CAAC;AAEX,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,oEAAoE;AACpE,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,iBAAiB,CAWhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,oBAAoB,GAC7B,kBAAkB,GAAG,SAAS,CAehC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Whether this browser has the API at all. False on the server. */
|
|
2
|
+
export function supportsMediaSession() {
|
|
3
|
+
return typeof navigator !== "undefined" && "mediaSession" in navigator;
|
|
4
|
+
}
|
|
5
|
+
export function toMetadataInit(metadata) {
|
|
6
|
+
return {
|
|
7
|
+
album: metadata.album ?? "",
|
|
8
|
+
artist: metadata.artist ?? "",
|
|
9
|
+
artwork: metadata.artwork?.map((image) => ({
|
|
10
|
+
sizes: image.sizes ?? "",
|
|
11
|
+
src: image.src,
|
|
12
|
+
type: image.type ?? "",
|
|
13
|
+
})) ?? [],
|
|
14
|
+
title: metadata.title,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The position a host can actually be told, or undefined when there is none.
|
|
19
|
+
*
|
|
20
|
+
* `setPositionState` throws rather than ignoring a value it dislikes, and the
|
|
21
|
+
* values it dislikes are the ones a media element produces normally: `duration`
|
|
22
|
+
* is NaN until metadata loads, and `currentTime` can overshoot the duration by
|
|
23
|
+
* a frame at the end of a track. Both would otherwise throw in a timeupdate
|
|
24
|
+
* handler, which is to say sixty times a second.
|
|
25
|
+
*/
|
|
26
|
+
export function toPositionState(position) {
|
|
27
|
+
const { duration } = position;
|
|
28
|
+
if (!Number.isFinite(duration) || duration < 0)
|
|
29
|
+
return undefined;
|
|
30
|
+
const rate = position.playbackRate;
|
|
31
|
+
return {
|
|
32
|
+
duration,
|
|
33
|
+
// Clamped rather than rejected: overshooting at the end of a track is
|
|
34
|
+
// ordinary, and refusing to report it would freeze the scrubber there.
|
|
35
|
+
position: Math.min(Math.max(position.position ?? 0, 0), duration),
|
|
36
|
+
// Zero is what a paused element reports on some browsers, and it throws.
|
|
37
|
+
...(rate !== undefined && Number.isFinite(rate) && rate !== 0
|
|
38
|
+
? { playbackRate: rate }
|
|
39
|
+
: null),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=media-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-session.js","sourceRoot":"","sources":["../../src/media/media-session.ts"],"names":[],"mappings":"AAqCA,oEAAoE;AACpE,MAAM,UAAU,oBAAoB;IAClC,OAAO,OAAO,SAAS,KAAK,WAAW,IAAI,cAAc,IAAI,SAAS,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAA8B;IAC3D,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE;QAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE;QAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACzC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE;YACxB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;SACvB,CAAC,CAAC,IAAI,EAAE;QACT,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,QAA8B;IAE9B,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAEjE,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC;IACnC,OAAO;QACL,QAAQ;QACR,sEAAsE;QACtE,uEAAuE;QACvE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC;QACjE,yEAAyE;QACzE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;YAC3D,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE;YACxB,CAAC,CAAC,IAAI,CAAC;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type MediaSessionActionName, type MediaSessionMetadata, type MediaSessionPlaybackState, type MediaSessionPosition } from "./media-session.js";
|
|
2
|
+
export type MediaSessionHandlers = Partial<Record<MediaSessionActionName, MediaSessionActionHandler>>;
|
|
3
|
+
export interface UseMediaSessionOptions {
|
|
4
|
+
/**
|
|
5
|
+
* What the hardware keys, the lock screen and the OS media control call.
|
|
6
|
+
* Whatever is absent is left to the host, which then hides that control.
|
|
7
|
+
*/
|
|
8
|
+
readonly actions?: MediaSessionHandlers;
|
|
9
|
+
/** Null clears what the host is showing, for a player with nothing loaded. */
|
|
10
|
+
readonly metadata?: MediaSessionMetadata | null;
|
|
11
|
+
readonly playbackState?: MediaSessionPlaybackState;
|
|
12
|
+
readonly position?: MediaSessionPosition | null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Publishes what is playing to the operating system: the lock screen, the
|
|
16
|
+
* media control in a notification shade or menu bar, and the hardware keys on
|
|
17
|
+
* a keyboard or headset.
|
|
18
|
+
*
|
|
19
|
+
* It renders nothing and owns no audio. The application keeps its own element
|
|
20
|
+
* and its own state, and describes them here, which is the same division the
|
|
21
|
+
* rest of Adjacent uses.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useMediaSession({ actions, metadata, playbackState, position, }: UseMediaSessionOptions): void;
|
|
24
|
+
//# sourceMappingURL=use-media-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-media-session.d.ts","sourceRoot":"","sources":["../../src/media/use-media-session.ts"],"names":[],"mappings":"AAIA,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,oBAAoB,GAAG,OAAO,CACxC,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,CAAC,CAC1D,CAAC;AAEF,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,oBAAoB,CAAC;IACxC,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,aAAa,CAAC,EAAE,yBAAyB,CAAC;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACjD;AAaD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,QAAQ,EACR,aAAa,EACb,QAAQ,GACT,EAAE,sBAAsB,GAAG,IAAI,CAmE/B"}
|