@a-type/ui 3.0.36 → 3.0.37
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/dist/cjs/components/provider/Provider.d.ts +2 -1
- package/dist/cjs/components/provider/Provider.js +3 -2
- package/dist/cjs/components/provider/Provider.js.map +1 -1
- package/dist/cjs/components/pwaInstall/PwaInstall.d.ts +5 -0
- package/dist/cjs/components/pwaInstall/PwaInstall.js +79 -0
- package/dist/cjs/components/pwaInstall/PwaInstall.js.map +1 -0
- package/dist/cjs/components/pwaInstall/PwaInstallTrigger.d.ts +3 -4
- package/dist/cjs/components/pwaInstall/PwaInstallTrigger.js +5 -48
- package/dist/cjs/components/pwaInstall/PwaInstallTrigger.js.map +1 -1
- package/dist/cjs/components/pwaInstall/index.d.ts +1 -0
- package/dist/cjs/components/pwaInstall/index.js +1 -0
- package/dist/cjs/components/pwaInstall/index.js.map +1 -1
- package/dist/cjs/components/pwaInstall/state.d.ts +4 -0
- package/dist/cjs/components/pwaInstall/state.js +13 -0
- package/dist/cjs/components/pwaInstall/state.js.map +1 -0
- package/dist/esm/components/provider/Provider.d.ts +2 -1
- package/dist/esm/components/provider/Provider.js +3 -2
- package/dist/esm/components/provider/Provider.js.map +1 -1
- package/dist/esm/components/pwaInstall/PwaInstall.d.ts +5 -0
- package/dist/esm/components/pwaInstall/PwaInstall.js +76 -0
- package/dist/esm/components/pwaInstall/PwaInstall.js.map +1 -0
- package/dist/esm/components/pwaInstall/PwaInstallTrigger.d.ts +3 -4
- package/dist/esm/components/pwaInstall/PwaInstallTrigger.js +7 -50
- package/dist/esm/components/pwaInstall/PwaInstallTrigger.js.map +1 -1
- package/dist/esm/components/pwaInstall/index.d.ts +1 -0
- package/dist/esm/components/pwaInstall/index.js +1 -0
- package/dist/esm/components/pwaInstall/index.js.map +1 -1
- package/dist/esm/components/pwaInstall/state.d.ts +4 -0
- package/dist/esm/components/pwaInstall/state.js +9 -0
- package/dist/esm/components/pwaInstall/state.js.map +1 -0
- package/package.json +1 -1
- package/src/components/provider/Provider.tsx +4 -0
- package/src/components/pwaInstall/PwaInstall.tsx +228 -0
- package/src/components/pwaInstall/PwaInstallTrigger.tsx +15 -209
- package/src/components/pwaInstall/index.ts +1 -0
- package/src/components/pwaInstall/state.ts +9 -0
|
@@ -5,11 +5,12 @@ export interface ProviderProps {
|
|
|
5
5
|
disableViewportOffset?: boolean;
|
|
6
6
|
virtualKeyboardBehavior?: 'overlay' | 'displace';
|
|
7
7
|
disableTitleBarColor?: boolean;
|
|
8
|
+
manifestPath?: string;
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* Provides all the stuff for all global junk.
|
|
11
12
|
*/
|
|
12
|
-
export declare function Provider({ children, disableParticles, disableViewportOffset, virtualKeyboardBehavior, disableTitleBarColor, }: ProviderProps): import("react/jsx-runtime.js").JSX.Element;
|
|
13
|
+
export declare function Provider({ children, disableParticles, disableViewportOffset, virtualKeyboardBehavior, disableTitleBarColor, manifestPath, }: ProviderProps): import("react/jsx-runtime.js").JSX.Element;
|
|
13
14
|
export declare const ConfigContext: import("react").Context<{
|
|
14
15
|
virtualKeyboardBehavior: "overlay" | "displace";
|
|
15
16
|
}>;
|
|
@@ -10,19 +10,20 @@ const hooks_js_1 = require("../../hooks.js");
|
|
|
10
10
|
const useVirtualKeyboardBehavior_js_1 = require("../../hooks/useVirtualKeyboardBehavior.js");
|
|
11
11
|
const index_js_1 = require("../icon/index.js");
|
|
12
12
|
const index_js_2 = require("../particles/index.js");
|
|
13
|
+
const PwaInstall_js_1 = require("../pwaInstall/PwaInstall.js");
|
|
13
14
|
const toasts_js_1 = require("../toasts/toasts.js");
|
|
14
15
|
const index_js_3 = require("../tooltip/index.js");
|
|
15
16
|
/**
|
|
16
17
|
* Provides all the stuff for all global junk.
|
|
17
18
|
*/
|
|
18
|
-
function Provider({ children, disableParticles, disableViewportOffset, virtualKeyboardBehavior = 'displace', disableTitleBarColor, }) {
|
|
19
|
+
function Provider({ children, disableParticles, disableViewportOffset, virtualKeyboardBehavior = 'displace', disableTitleBarColor, manifestPath, }) {
|
|
19
20
|
(0, hooks_js_1.useVisualViewportOffset)(disableViewportOffset);
|
|
20
21
|
const supportedVirtualKeyboardBehavior = typeof navigator !== 'undefined' && 'virtualKeyboard' in navigator
|
|
21
22
|
? virtualKeyboardBehavior
|
|
22
23
|
: 'displace';
|
|
23
24
|
(0, useVirtualKeyboardBehavior_js_1.useVirtualKeyboardBehavior)(supportedVirtualKeyboardBehavior);
|
|
24
25
|
(0, hooks_js_1.useThemedTitleBar)('gray', 'wash', undefined, disableTitleBarColor);
|
|
25
|
-
const otherStuff = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(index_js_1.IconSpritesheet, {}), (0, jsx_runtime_1.jsx)(toasts_js_1.Toaster, {})] }));
|
|
26
|
+
const otherStuff = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(index_js_1.IconSpritesheet, {}), (0, jsx_runtime_1.jsx)(toasts_js_1.Toaster, {}), (0, jsx_runtime_1.jsx)(PwaInstall_js_1.PwaInstall, { manifestPath: manifestPath })] }));
|
|
26
27
|
if (disableParticles)
|
|
27
28
|
return ((0, jsx_runtime_1.jsx)(exports.ConfigContext.Provider, { value: { virtualKeyboardBehavior: supportedVirtualKeyboardBehavior }, children: (0, jsx_runtime_1.jsxs)(index_js_3.TooltipProvider, { children: [children, otherStuff] }) }));
|
|
28
29
|
return ((0, jsx_runtime_1.jsx)(exports.ConfigContext.Provider, { value: { virtualKeyboardBehavior: supportedVirtualKeyboardBehavior }, children: (0, jsx_runtime_1.jsx)(index_js_3.TooltipProvider, { children: (0, jsx_runtime_1.jsxs)(index_js_2.ParticleLayer, { children: [children, otherStuff] }) }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../../../src/components/provider/Provider.tsx"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../../../src/components/provider/Provider.tsx"],"names":[],"mappings":";;;AAqBA,4BA+CC;AAQD,8BAEC;;AA9ED,iCAA6D;AAC7D,6CAA4E;AAC5E,6FAAuF;AACvF,+CAAmD;AACnD,oDAAsD;AACtD,+DAAyD;AACzD,mDAA8C;AAC9C,kDAAsD;AAWtD;;GAEG;AACH,SAAgB,QAAQ,CAAC,EACxB,QAAQ,EACR,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,GAAG,UAAU,EACpC,oBAAoB,EACpB,YAAY,GACG;IACf,IAAA,kCAAuB,EAAC,qBAAqB,CAAC,CAAC;IAC/C,MAAM,gCAAgC,GACrC,OAAO,SAAS,KAAK,WAAW,IAAI,iBAAiB,IAAI,SAAS;QACjE,CAAC,CAAC,uBAAuB;QACzB,CAAC,CAAC,UAAU,CAAC;IACf,IAAA,0DAA0B,EAAC,gCAAgC,CAAC,CAAC;IAC7D,IAAA,4BAAiB,EAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,CAClB,6DACC,uBAAC,0BAAe,KAAG,EACnB,uBAAC,mBAAO,KAAG,EACX,uBAAC,0BAAU,IAAC,YAAY,EAAE,YAAY,GAAI,IACxC,CACH,CAAC;IAEF,IAAI,gBAAgB;QACnB,OAAO,CACN,uBAAC,qBAAa,CAAC,QAAQ,IACtB,KAAK,EAAE,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,YAEpE,wBAAC,0BAAe,eACd,QAAQ,EACR,UAAU,IACM,GACM,CACzB,CAAC;IAEH,OAAO,CACN,uBAAC,qBAAa,CAAC,QAAQ,IACtB,KAAK,EAAE,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,YAEpE,uBAAC,0BAAe,cACf,wBAAC,wBAAa,eACZ,QAAQ,EACR,UAAU,IACI,GACC,GACM,CACzB,CAAC;AACH,CAAC;AAEY,QAAA,aAAa,GAAG,IAAA,qBAAa,EAEvC;IACF,uBAAuB,EAAE,UAAU;CACnC,CAAC,CAAC;AAEH,SAAgB,SAAS;IACxB,OAAO,IAAA,kBAAU,EAAC,qBAAa,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DialogTriggerProps } from '@radix-ui/react-dialog';
|
|
2
|
+
export interface PwaInstall extends DialogTriggerProps {
|
|
3
|
+
manifestPath?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function PwaInstall({ children, manifestPath, asChild: _, ...rest }: PwaInstall): import("react/jsx-runtime.js").JSX.Element | null;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
"use strict";
|
|
3
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
4
|
+
var t = {};
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
8
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
9
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
10
|
+
t[p[i]] = s[p[i]];
|
|
11
|
+
}
|
|
12
|
+
return t;
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PwaInstall = PwaInstall;
|
|
16
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
17
|
+
const react_1 = require("react");
|
|
18
|
+
const valtio_1 = require("valtio");
|
|
19
|
+
const platform_js_1 = require("../../platform.js");
|
|
20
|
+
const Box_js_1 = require("../box/Box.js");
|
|
21
|
+
const Button_js_1 = require("../button/Button.js");
|
|
22
|
+
const Dialog_js_1 = require("../dialog/Dialog.js");
|
|
23
|
+
const Icon_js_1 = require("../icon/Icon.js");
|
|
24
|
+
const Lightbox_js_1 = require("../lightbox/Lightbox.js");
|
|
25
|
+
const lists_js_1 = require("../lists/lists.js");
|
|
26
|
+
const typography_js_1 = require("../typography/typography.js");
|
|
27
|
+
const PlatformIcons_js_1 = require("./PlatformIcons.js");
|
|
28
|
+
const state_js_1 = require("./state.js");
|
|
29
|
+
const useIsInstallReady_js_1 = require("./useIsInstallReady.js");
|
|
30
|
+
const useWebManifest_js_1 = require("./useWebManifest.js");
|
|
31
|
+
function PwaInstall(_a) {
|
|
32
|
+
var _b, _c, _d, _e, _f, _g;
|
|
33
|
+
var { children, manifestPath, asChild: _ } = _a, rest = __rest(_a, ["children", "manifestPath", "asChild"]);
|
|
34
|
+
const installed = (0, useIsInstallReady_js_1.useIsInstalled)();
|
|
35
|
+
const manifest = (0, useWebManifest_js_1.useWebManifest)(manifestPath);
|
|
36
|
+
const { open } = (0, valtio_1.useSnapshot)(state_js_1.pwaInstallerState);
|
|
37
|
+
const [showInstructions, setShowInstructions] = (0, react_1.useState)(false);
|
|
38
|
+
if (installed) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const primaryIcon = (_b = manifest === null || manifest === void 0 ? void 0 : manifest.icons) === null || _b === void 0 ? void 0 : _b[0];
|
|
42
|
+
return ((0, jsx_runtime_1.jsx)(Dialog_js_1.Dialog, { open: open, onOpenChange: (isOpen) => {
|
|
43
|
+
state_js_1.pwaInstallerState.open = isOpen;
|
|
44
|
+
}, children: (0, jsx_runtime_1.jsxs)(Dialog_js_1.Dialog.Content, { className: "flex flex-col gap-xs", id: "pwa-install-dialog", children: [(0, jsx_runtime_1.jsxs)(Dialog_js_1.Dialog.Title, { className: "flex flex-row gap-md items-center", children: [primaryIcon && ((0, jsx_runtime_1.jsx)("img", { src: primaryIcon.src, alt: (_e = (_d = (_c = primaryIcon.label) !== null && _c !== void 0 ? _c : manifest === null || manifest === void 0 ? void 0 : manifest.short_name) !== null && _d !== void 0 ? _d : manifest === null || manifest === void 0 ? void 0 : manifest.name) !== null && _e !== void 0 ? _e : 'App Icon', className: "inline-block w-1em h-1em rounded" })), "Install ", (_g = (_f = manifest === null || manifest === void 0 ? void 0 : manifest.short_name) !== null && _f !== void 0 ? _f : manifest === null || manifest === void 0 ? void 0 : manifest.name) !== null && _g !== void 0 ? _g : 'App'] }), showInstructions ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Dialog_js_1.Dialog.Description, { children: "Follow the instructions below to install this app on your device." }), (0, jsx_runtime_1.jsx)(InstallInstructions, {}), (0, jsx_runtime_1.jsxs)(Dialog_js_1.Dialog.Actions, { children: [(0, jsx_runtime_1.jsx)(Dialog_js_1.Dialog.Close, { asChild: true, children: (0, jsx_runtime_1.jsx)(Button_js_1.Button, { emphasis: "ghost", children: "Close" }) }), (0, jsx_runtime_1.jsxs)(Button_js_1.Button, { onClick: () => setShowInstructions(false), children: [(0, jsx_runtime_1.jsx)(Icon_js_1.Icon, { name: "arrowLeft" }), " Back"] })] })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Dialog_js_1.Dialog.Description, { children: "This site is also an app. You can install it right now for easier access and more features." }), (manifest === null || manifest === void 0 ? void 0 : manifest.description) && ((0, jsx_runtime_1.jsx)(typography_js_1.P, { className: "mb-sm", children: manifest.description })), (0, jsx_runtime_1.jsx)(ManifestImageGallery, { manifestPath: manifestPath }), (0, jsx_runtime_1.jsxs)(Dialog_js_1.Dialog.Actions, { children: [(0, jsx_runtime_1.jsx)(Dialog_js_1.Dialog.Close, { asChild: true, children: (0, jsx_runtime_1.jsx)(Button_js_1.Button, { emphasis: "ghost", children: "Close" }) }), (0, jsx_runtime_1.jsx)(InstallDeviceActions, { showInstructions: () => setShowInstructions(true) })] })] }))] }) }));
|
|
45
|
+
}
|
|
46
|
+
const supportsDirectInstall = (0, platform_js_1.getSupportsPWAInstallPrompt)();
|
|
47
|
+
function InstallInstructions() {
|
|
48
|
+
const os = (0, platform_js_1.getOS)();
|
|
49
|
+
if (os === 'iOS' || os === 'Mac OS') {
|
|
50
|
+
if ((0, platform_js_1.getIsSafari)()) {
|
|
51
|
+
if (os === 'iOS') {
|
|
52
|
+
return ((0, jsx_runtime_1.jsxs)(lists_js_1.Ol, { children: [(0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariShareIcon, {}), " Tap the Share button in the toolbar."] }), (0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariPlusSquareIcon, {}), " Scroll down and tap \"Add to Home Screen\"."] })] }));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
return ((0, jsx_runtime_1.jsxs)(lists_js_1.Ol, { children: [(0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariShareIcon, {}), " Tap the Share button in the toolbar."] }), (0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariAddToDockIcon, {}), " Tap \"Add to Dock\"."] })] }));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lists_js_1.Ol, { children: (0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariIcon, {}), " Open this site in Safari to continue."] }) }), (0, jsx_runtime_1.jsx)(Box_js_1.Box, { surface: true, p: true, children: "Apple does not allow non-Safari browsers to install web apps." })] }));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return ((0, jsx_runtime_1.jsxs)(lists_js_1.Ol, { children: [(0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(Icon_js_1.Icon, { name: "dots", className: "rotate-90" }), " Tap the menu button in the toolbar."] }), (0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.AndroidAddToHomeIcon, {}), " Tap \"Add to Home Screen.\""] })] }));
|
|
63
|
+
}
|
|
64
|
+
function ManifestImageGallery({ manifestPath }) {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
const manifest = (0, useWebManifest_js_1.useWebManifest)(manifestPath);
|
|
67
|
+
if (!((_a = manifest === null || manifest === void 0 ? void 0 : manifest.screenshots) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return ((0, jsx_runtime_1.jsx)(Box_js_1.Box, { overflow: "auto-x", p: "sm", gap: true, className: "h-240px", children: (_b = manifest.screenshots) === null || _b === void 0 ? void 0 : _b.map((screenshot, index) => ((0, jsx_runtime_1.jsxs)(Lightbox_js_1.Lightbox.Root, { children: [(0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Trigger, { asChild: true, children: (0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Image, { tabIndex: 0, src: screenshot.src, alt: screenshot.label || `Screenshot ${index + 1}`, className: "border border-default rounded-xs" }, index) }), (0, jsx_runtime_1.jsxs)(Lightbox_js_1.Lightbox.Portal, { children: [(0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Overlay, { className: "z-10000" }), (0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Content, { className: "z-10001", children: (0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Image, { src: screenshot.src, alt: screenshot.label || `Screenshot ${index + 1}` }) })] })] }, screenshot.src))) }));
|
|
71
|
+
}
|
|
72
|
+
function InstallDeviceActions({ showInstructions, }) {
|
|
73
|
+
const ready = (0, useIsInstallReady_js_1.useIsInstallReady)();
|
|
74
|
+
if (supportsDirectInstall && ready) {
|
|
75
|
+
return ((0, jsx_runtime_1.jsxs)(Button_js_1.Button, { onClick: () => (0, useIsInstallReady_js_1.triggerDeferredInstall)(), emphasis: "primary", children: [(0, jsx_runtime_1.jsx)(Icon_js_1.Icon, { name: "download" }), " Install now"] }));
|
|
76
|
+
}
|
|
77
|
+
return ((0, jsx_runtime_1.jsxs)(Button_js_1.Button, { onClick: () => showInstructions(), emphasis: "primary", children: [(0, jsx_runtime_1.jsx)(Icon_js_1.Icon, { name: "arrowRight" }), " Add to Home"] }));
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=PwaInstall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PwaInstall.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/PwaInstall.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export interface PwaInstallTriggerProps extends
|
|
3
|
-
manifestPath?: string;
|
|
1
|
+
import { ButtonProps } from '../button/Button.js';
|
|
2
|
+
export interface PwaInstallTriggerProps extends ButtonProps {
|
|
4
3
|
}
|
|
5
|
-
export declare function PwaInstallTrigger({ children,
|
|
4
|
+
export declare function PwaInstallTrigger({ children, ...rest }: PwaInstallTriggerProps): import("react/jsx-runtime.js").JSX.Element | null;
|
|
@@ -14,61 +14,18 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.PwaInstallTrigger = PwaInstallTrigger;
|
|
16
16
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
17
|
-
const react_1 = require("react");
|
|
18
|
-
const platform_js_1 = require("../../platform.js");
|
|
19
|
-
const Box_js_1 = require("../box/Box.js");
|
|
20
17
|
const Button_js_1 = require("../button/Button.js");
|
|
21
|
-
const Dialog_js_1 = require("../dialog/Dialog.js");
|
|
22
18
|
const Icon_js_1 = require("../icon/Icon.js");
|
|
23
|
-
const
|
|
24
|
-
const lists_js_1 = require("../lists/lists.js");
|
|
25
|
-
const typography_js_1 = require("../typography/typography.js");
|
|
26
|
-
const PlatformIcons_js_1 = require("./PlatformIcons.js");
|
|
19
|
+
const state_js_1 = require("./state.js");
|
|
27
20
|
const useIsInstallReady_js_1 = require("./useIsInstallReady.js");
|
|
28
|
-
const useWebManifest_js_1 = require("./useWebManifest.js");
|
|
29
21
|
function PwaInstallTrigger(_a) {
|
|
30
|
-
var
|
|
31
|
-
var { children, manifestPath, asChild: _ } = _a, rest = __rest(_a, ["children", "manifestPath", "asChild"]);
|
|
22
|
+
var { children } = _a, rest = __rest(_a, ["children"]);
|
|
32
23
|
const installed = (0, useIsInstallReady_js_1.useIsInstalled)();
|
|
33
|
-
const manifest = (0, useWebManifest_js_1.useWebManifest)(manifestPath);
|
|
34
|
-
const [showInstructions, setShowInstructions] = (0, react_1.useState)(false);
|
|
35
24
|
if (installed) {
|
|
36
25
|
return null;
|
|
37
26
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
const supportsDirectInstall = (0, platform_js_1.getSupportsPWAInstallPrompt)();
|
|
42
|
-
function InstallInstructions() {
|
|
43
|
-
const os = (0, platform_js_1.getOS)();
|
|
44
|
-
if (os === 'iOS' || os === 'Mac OS') {
|
|
45
|
-
if ((0, platform_js_1.getIsSafari)()) {
|
|
46
|
-
if (os === 'iOS') {
|
|
47
|
-
return ((0, jsx_runtime_1.jsxs)(lists_js_1.Ol, { children: [(0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariShareIcon, {}), " Tap the Share button in the toolbar."] }), (0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariPlusSquareIcon, {}), " Scroll down and tap \"Add to Home Screen\"."] })] }));
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
return ((0, jsx_runtime_1.jsxs)(lists_js_1.Ol, { children: [(0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariShareIcon, {}), " Tap the Share button in the toolbar."] }), (0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariAddToDockIcon, {}), " Tap \"Add to Dock\"."] })] }));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(lists_js_1.Ol, { children: (0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.SafariIcon, {}), " Open this site in Safari to continue."] }) }), (0, jsx_runtime_1.jsx)(Box_js_1.Box, { surface: true, p: true, children: "Apple does not allow non-Safari browsers to install web apps." })] }));
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return ((0, jsx_runtime_1.jsxs)(lists_js_1.Ol, { children: [(0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(Icon_js_1.Icon, { name: "dots", className: "rotate-90" }), " Tap the menu button in the toolbar."] }), (0, jsx_runtime_1.jsxs)(lists_js_1.Ol.Item, { children: [(0, jsx_runtime_1.jsx)(PlatformIcons_js_1.AndroidAddToHomeIcon, {}), " Tap \"Add to Home Screen.\""] })] }));
|
|
58
|
-
}
|
|
59
|
-
function ManifestImageGallery({ manifestPath }) {
|
|
60
|
-
var _a, _b;
|
|
61
|
-
const manifest = (0, useWebManifest_js_1.useWebManifest)(manifestPath);
|
|
62
|
-
if (!((_a = manifest === null || manifest === void 0 ? void 0 : manifest.screenshots) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
return ((0, jsx_runtime_1.jsx)(Box_js_1.Box, { overflow: "auto-x", p: "sm", gap: true, className: "h-240px", children: (_b = manifest.screenshots) === null || _b === void 0 ? void 0 : _b.map((screenshot, index) => ((0, jsx_runtime_1.jsxs)(Lightbox_js_1.Lightbox.Root, { children: [(0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Trigger, { asChild: true, children: (0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Image, { tabIndex: 0, src: screenshot.src, alt: screenshot.label || `Screenshot ${index + 1}`, className: "border border-default rounded-xs" }, index) }), (0, jsx_runtime_1.jsxs)(Lightbox_js_1.Lightbox.Portal, { children: [(0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Overlay, { className: "z-10000" }), (0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Content, { className: "z-10001", children: (0, jsx_runtime_1.jsx)(Lightbox_js_1.Lightbox.Image, { src: screenshot.src, alt: screenshot.label || `Screenshot ${index + 1}` }) })] })] }, screenshot.src))) }));
|
|
66
|
-
}
|
|
67
|
-
function InstallDeviceActions({ showInstructions, }) {
|
|
68
|
-
const ready = (0, useIsInstallReady_js_1.useIsInstallReady)();
|
|
69
|
-
if (supportsDirectInstall && ready) {
|
|
70
|
-
return ((0, jsx_runtime_1.jsxs)(Button_js_1.Button, { onClick: () => (0, useIsInstallReady_js_1.triggerDeferredInstall)(), emphasis: "primary", children: [(0, jsx_runtime_1.jsx)(Icon_js_1.Icon, { name: "download" }), " Install now"] }));
|
|
71
|
-
}
|
|
72
|
-
return ((0, jsx_runtime_1.jsxs)(Button_js_1.Button, { onClick: () => showInstructions(), emphasis: "primary", children: [(0, jsx_runtime_1.jsx)(Icon_js_1.Icon, { name: "arrowRight" }), " Add to Home"] }));
|
|
27
|
+
return ((0, jsx_runtime_1.jsx)(Button_js_1.Button, Object.assign({ color: "primary", emphasis: "light" }, rest, { onClick: () => {
|
|
28
|
+
state_js_1.pwaInstallerState.open = true;
|
|
29
|
+
}, children: children !== null && children !== void 0 ? children : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Icon_js_1.Icon, { name: "star" }), " Install"] })) })));
|
|
73
30
|
}
|
|
74
31
|
//# sourceMappingURL=PwaInstallTrigger.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PwaInstallTrigger.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/PwaInstallTrigger.tsx"],"names":[],"mappings":";;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"PwaInstallTrigger.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/PwaInstallTrigger.tsx"],"names":[],"mappings":";;;;;;;;;;;;;AAOA,8CAyBC;;AAhCD,mDAA0D;AAC1D,6CAAuC;AACvC,yCAA+C;AAC/C,iEAAwD;AAIxD,SAAgB,iBAAiB,CAAC,EAGT;QAHS,EACjC,QAAQ,OAEgB,EADrB,IAAI,cAF0B,YAGjC,CADO;IAEP,MAAM,SAAS,GAAG,IAAA,qCAAc,GAAE,CAAC;IACnC,IAAI,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,CACN,uBAAC,kBAAM,kBACN,KAAK,EAAC,SAAS,EACf,QAAQ,EAAC,OAAO,IACZ,IAAI,IACR,OAAO,EAAE,GAAG,EAAE;YACb,4BAAiB,CAAC,IAAI,GAAG,IAAI,CAAC;QAC/B,CAAC,YAEA,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,CACZ,6DACC,uBAAC,cAAI,IAAC,IAAI,EAAC,MAAM,GAAG,gBAClB,CACH,IACO,CACT,CAAC;AACH,CAAC"}
|
|
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
};
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
__exportStar(require("./PwaInstallTrigger.js"), exports);
|
|
19
|
+
__exportStar(require("./state.js"), exports);
|
|
19
20
|
__exportStar(require("./useIsInstallReady.js"), exports);
|
|
20
21
|
__exportStar(require("./useWebManifest.js"), exports);
|
|
21
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,yDAAuC;AACvC,sDAAoC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,6CAA2B;AAC3B,yDAAuC;AACvC,sDAAoC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.pwaInstallerState = void 0;
|
|
5
|
+
exports.showPwaInstall = showPwaInstall;
|
|
6
|
+
const valtio_1 = require("valtio");
|
|
7
|
+
exports.pwaInstallerState = (0, valtio_1.proxy)({
|
|
8
|
+
open: false,
|
|
9
|
+
});
|
|
10
|
+
function showPwaInstall() {
|
|
11
|
+
exports.pwaInstallerState.open = true;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/state.ts"],"names":[],"mappings":";;;AAMA,wCAEC;AARD,mCAA+B;AAElB,QAAA,iBAAiB,GAAG,IAAA,cAAK,EAAC;IACtC,IAAI,EAAE,KAAK;CACX,CAAC,CAAC;AAEH,SAAgB,cAAc;IAC7B,yBAAiB,CAAC,IAAI,GAAG,IAAI,CAAC;AAC/B,CAAC"}
|
|
@@ -5,11 +5,12 @@ export interface ProviderProps {
|
|
|
5
5
|
disableViewportOffset?: boolean;
|
|
6
6
|
virtualKeyboardBehavior?: 'overlay' | 'displace';
|
|
7
7
|
disableTitleBarColor?: boolean;
|
|
8
|
+
manifestPath?: string;
|
|
8
9
|
}
|
|
9
10
|
/**
|
|
10
11
|
* Provides all the stuff for all global junk.
|
|
11
12
|
*/
|
|
12
|
-
export declare function Provider({ children, disableParticles, disableViewportOffset, virtualKeyboardBehavior, disableTitleBarColor, }: ProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare function Provider({ children, disableParticles, disableViewportOffset, virtualKeyboardBehavior, disableTitleBarColor, manifestPath, }: ProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
13
14
|
export declare const ConfigContext: import("react").Context<{
|
|
14
15
|
virtualKeyboardBehavior: "overlay" | "displace";
|
|
15
16
|
}>;
|
|
@@ -5,19 +5,20 @@ import { useThemedTitleBar, useVisualViewportOffset } from '../../hooks.js';
|
|
|
5
5
|
import { useVirtualKeyboardBehavior } from '../../hooks/useVirtualKeyboardBehavior.js';
|
|
6
6
|
import { IconSpritesheet } from '../icon/index.js';
|
|
7
7
|
import { ParticleLayer } from '../particles/index.js';
|
|
8
|
+
import { PwaInstall } from '../pwaInstall/PwaInstall.js';
|
|
8
9
|
import { Toaster } from '../toasts/toasts.js';
|
|
9
10
|
import { TooltipProvider } from '../tooltip/index.js';
|
|
10
11
|
/**
|
|
11
12
|
* Provides all the stuff for all global junk.
|
|
12
13
|
*/
|
|
13
|
-
export function Provider({ children, disableParticles, disableViewportOffset, virtualKeyboardBehavior = 'displace', disableTitleBarColor, }) {
|
|
14
|
+
export function Provider({ children, disableParticles, disableViewportOffset, virtualKeyboardBehavior = 'displace', disableTitleBarColor, manifestPath, }) {
|
|
14
15
|
useVisualViewportOffset(disableViewportOffset);
|
|
15
16
|
const supportedVirtualKeyboardBehavior = typeof navigator !== 'undefined' && 'virtualKeyboard' in navigator
|
|
16
17
|
? virtualKeyboardBehavior
|
|
17
18
|
: 'displace';
|
|
18
19
|
useVirtualKeyboardBehavior(supportedVirtualKeyboardBehavior);
|
|
19
20
|
useThemedTitleBar('gray', 'wash', undefined, disableTitleBarColor);
|
|
20
|
-
const otherStuff = (_jsxs(_Fragment, { children: [_jsx(IconSpritesheet, {}), _jsx(Toaster, {})] }));
|
|
21
|
+
const otherStuff = (_jsxs(_Fragment, { children: [_jsx(IconSpritesheet, {}), _jsx(Toaster, {}), _jsx(PwaInstall, { manifestPath: manifestPath })] }));
|
|
21
22
|
if (disableParticles)
|
|
22
23
|
return (_jsx(ConfigContext.Provider, { value: { virtualKeyboardBehavior: supportedVirtualKeyboardBehavior }, children: _jsxs(TooltipProvider, { children: [children, otherStuff] }) }));
|
|
23
24
|
return (_jsx(ConfigContext.Provider, { value: { virtualKeyboardBehavior: supportedVirtualKeyboardBehavior }, children: _jsx(TooltipProvider, { children: _jsxs(ParticleLayer, { children: [children, otherStuff] }) }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../../../src/components/provider/Provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAa,UAAU,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../../../src/components/provider/Provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAa,UAAU,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAWtD;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,EACxB,QAAQ,EACR,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,GAAG,UAAU,EACpC,oBAAoB,EACpB,YAAY,GACG;IACf,uBAAuB,CAAC,qBAAqB,CAAC,CAAC;IAC/C,MAAM,gCAAgC,GACrC,OAAO,SAAS,KAAK,WAAW,IAAI,iBAAiB,IAAI,SAAS;QACjE,CAAC,CAAC,uBAAuB;QACzB,CAAC,CAAC,UAAU,CAAC;IACf,0BAA0B,CAAC,gCAAgC,CAAC,CAAC;IAC7D,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,oBAAoB,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,CAClB,8BACC,KAAC,eAAe,KAAG,EACnB,KAAC,OAAO,KAAG,EACX,KAAC,UAAU,IAAC,YAAY,EAAE,YAAY,GAAI,IACxC,CACH,CAAC;IAEF,IAAI,gBAAgB;QACnB,OAAO,CACN,KAAC,aAAa,CAAC,QAAQ,IACtB,KAAK,EAAE,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,YAEpE,MAAC,eAAe,eACd,QAAQ,EACR,UAAU,IACM,GACM,CACzB,CAAC;IAEH,OAAO,CACN,KAAC,aAAa,CAAC,QAAQ,IACtB,KAAK,EAAE,EAAE,uBAAuB,EAAE,gCAAgC,EAAE,YAEpE,KAAC,eAAe,cACf,MAAC,aAAa,eACZ,QAAQ,EACR,UAAU,IACI,GACC,GACM,CACzB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAEvC;IACF,uBAAuB,EAAE,UAAU;CACnC,CAAC,CAAC;AAEH,MAAM,UAAU,SAAS;IACxB,OAAO,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DialogTriggerProps } from '@radix-ui/react-dialog';
|
|
2
|
+
export interface PwaInstall extends DialogTriggerProps {
|
|
3
|
+
manifestPath?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function PwaInstall({ children, manifestPath, asChild: _, ...rest }: PwaInstall): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// @unocss-include
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
14
|
+
import { useState } from 'react';
|
|
15
|
+
import { useSnapshot } from 'valtio';
|
|
16
|
+
import { getIsSafari, getOS, getSupportsPWAInstallPrompt, } from '../../platform.js';
|
|
17
|
+
import { Box } from '../box/Box.js';
|
|
18
|
+
import { Button } from '../button/Button.js';
|
|
19
|
+
import { Dialog } from '../dialog/Dialog.js';
|
|
20
|
+
import { Icon } from '../icon/Icon.js';
|
|
21
|
+
import { Lightbox } from '../lightbox/Lightbox.js';
|
|
22
|
+
import { Ol } from '../lists/lists.js';
|
|
23
|
+
import { P } from '../typography/typography.js';
|
|
24
|
+
import { AndroidAddToHomeIcon, SafariAddToDockIcon, SafariIcon, SafariPlusSquareIcon, SafariShareIcon, } from './PlatformIcons.js';
|
|
25
|
+
import { pwaInstallerState } from './state.js';
|
|
26
|
+
import { triggerDeferredInstall, useIsInstalled, useIsInstallReady, } from './useIsInstallReady.js';
|
|
27
|
+
import { useWebManifest } from './useWebManifest.js';
|
|
28
|
+
export function PwaInstall(_a) {
|
|
29
|
+
var _b, _c, _d, _e, _f, _g;
|
|
30
|
+
var { children, manifestPath, asChild: _ } = _a, rest = __rest(_a, ["children", "manifestPath", "asChild"]);
|
|
31
|
+
const installed = useIsInstalled();
|
|
32
|
+
const manifest = useWebManifest(manifestPath);
|
|
33
|
+
const { open } = useSnapshot(pwaInstallerState);
|
|
34
|
+
const [showInstructions, setShowInstructions] = useState(false);
|
|
35
|
+
if (installed) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const primaryIcon = (_b = manifest === null || manifest === void 0 ? void 0 : manifest.icons) === null || _b === void 0 ? void 0 : _b[0];
|
|
39
|
+
return (_jsx(Dialog, { open: open, onOpenChange: (isOpen) => {
|
|
40
|
+
pwaInstallerState.open = isOpen;
|
|
41
|
+
}, children: _jsxs(Dialog.Content, { className: "flex flex-col gap-xs", id: "pwa-install-dialog", children: [_jsxs(Dialog.Title, { className: "flex flex-row gap-md items-center", children: [primaryIcon && (_jsx("img", { src: primaryIcon.src, alt: (_e = (_d = (_c = primaryIcon.label) !== null && _c !== void 0 ? _c : manifest === null || manifest === void 0 ? void 0 : manifest.short_name) !== null && _d !== void 0 ? _d : manifest === null || manifest === void 0 ? void 0 : manifest.name) !== null && _e !== void 0 ? _e : 'App Icon', className: "inline-block w-1em h-1em rounded" })), "Install ", (_g = (_f = manifest === null || manifest === void 0 ? void 0 : manifest.short_name) !== null && _f !== void 0 ? _f : manifest === null || manifest === void 0 ? void 0 : manifest.name) !== null && _g !== void 0 ? _g : 'App'] }), showInstructions ? (_jsxs(_Fragment, { children: [_jsx(Dialog.Description, { children: "Follow the instructions below to install this app on your device." }), _jsx(InstallInstructions, {}), _jsxs(Dialog.Actions, { children: [_jsx(Dialog.Close, { asChild: true, children: _jsx(Button, { emphasis: "ghost", children: "Close" }) }), _jsxs(Button, { onClick: () => setShowInstructions(false), children: [_jsx(Icon, { name: "arrowLeft" }), " Back"] })] })] })) : (_jsxs(_Fragment, { children: [_jsx(Dialog.Description, { children: "This site is also an app. You can install it right now for easier access and more features." }), (manifest === null || manifest === void 0 ? void 0 : manifest.description) && (_jsx(P, { className: "mb-sm", children: manifest.description })), _jsx(ManifestImageGallery, { manifestPath: manifestPath }), _jsxs(Dialog.Actions, { children: [_jsx(Dialog.Close, { asChild: true, children: _jsx(Button, { emphasis: "ghost", children: "Close" }) }), _jsx(InstallDeviceActions, { showInstructions: () => setShowInstructions(true) })] })] }))] }) }));
|
|
42
|
+
}
|
|
43
|
+
const supportsDirectInstall = getSupportsPWAInstallPrompt();
|
|
44
|
+
function InstallInstructions() {
|
|
45
|
+
const os = getOS();
|
|
46
|
+
if (os === 'iOS' || os === 'Mac OS') {
|
|
47
|
+
if (getIsSafari()) {
|
|
48
|
+
if (os === 'iOS') {
|
|
49
|
+
return (_jsxs(Ol, { children: [_jsxs(Ol.Item, { children: [_jsx(SafariShareIcon, {}), " Tap the Share button in the toolbar."] }), _jsxs(Ol.Item, { children: [_jsx(SafariPlusSquareIcon, {}), " Scroll down and tap \"Add to Home Screen\"."] })] }));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
return (_jsxs(Ol, { children: [_jsxs(Ol.Item, { children: [_jsx(SafariShareIcon, {}), " Tap the Share button in the toolbar."] }), _jsxs(Ol.Item, { children: [_jsx(SafariAddToDockIcon, {}), " Tap \"Add to Dock\"."] })] }));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return (_jsxs(_Fragment, { children: [_jsx(Ol, { children: _jsxs(Ol.Item, { children: [_jsx(SafariIcon, {}), " Open this site in Safari to continue."] }) }), _jsx(Box, { surface: true, p: true, children: "Apple does not allow non-Safari browsers to install web apps." })] }));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return (_jsxs(Ol, { children: [_jsxs(Ol.Item, { children: [_jsx(Icon, { name: "dots", className: "rotate-90" }), " Tap the menu button in the toolbar."] }), _jsxs(Ol.Item, { children: [_jsx(AndroidAddToHomeIcon, {}), " Tap \"Add to Home Screen.\""] })] }));
|
|
60
|
+
}
|
|
61
|
+
function ManifestImageGallery({ manifestPath }) {
|
|
62
|
+
var _a, _b;
|
|
63
|
+
const manifest = useWebManifest(manifestPath);
|
|
64
|
+
if (!((_a = manifest === null || manifest === void 0 ? void 0 : manifest.screenshots) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return (_jsx(Box, { overflow: "auto-x", p: "sm", gap: true, className: "h-240px", children: (_b = manifest.screenshots) === null || _b === void 0 ? void 0 : _b.map((screenshot, index) => (_jsxs(Lightbox.Root, { children: [_jsx(Lightbox.Trigger, { asChild: true, children: _jsx(Lightbox.Image, { tabIndex: 0, src: screenshot.src, alt: screenshot.label || `Screenshot ${index + 1}`, className: "border border-default rounded-xs" }, index) }), _jsxs(Lightbox.Portal, { children: [_jsx(Lightbox.Overlay, { className: "z-10000" }), _jsx(Lightbox.Content, { className: "z-10001", children: _jsx(Lightbox.Image, { src: screenshot.src, alt: screenshot.label || `Screenshot ${index + 1}` }) })] })] }, screenshot.src))) }));
|
|
68
|
+
}
|
|
69
|
+
function InstallDeviceActions({ showInstructions, }) {
|
|
70
|
+
const ready = useIsInstallReady();
|
|
71
|
+
if (supportsDirectInstall && ready) {
|
|
72
|
+
return (_jsxs(Button, { onClick: () => triggerDeferredInstall(), emphasis: "primary", children: [_jsx(Icon, { name: "download" }), " Install now"] }));
|
|
73
|
+
}
|
|
74
|
+
return (_jsxs(Button, { onClick: () => showInstructions(), emphasis: "primary", children: [_jsx(Icon, { name: "arrowRight" }), " Add to Home"] }));
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=PwaInstall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PwaInstall.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/PwaInstall.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export interface PwaInstallTriggerProps extends
|
|
3
|
-
manifestPath?: string;
|
|
1
|
+
import { ButtonProps } from '../button/Button.js';
|
|
2
|
+
export interface PwaInstallTriggerProps extends ButtonProps {
|
|
4
3
|
}
|
|
5
|
-
export declare function PwaInstallTrigger({ children,
|
|
4
|
+
export declare function PwaInstallTrigger({ children, ...rest }: PwaInstallTriggerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -10,62 +10,19 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
10
10
|
}
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
|
-
import { jsx as _jsx,
|
|
14
|
-
import { useState } from 'react';
|
|
15
|
-
import { getIsSafari, getOS, getSupportsPWAInstallPrompt, } from '../../platform.js';
|
|
16
|
-
import { Box } from '../box/Box.js';
|
|
13
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
17
14
|
import { Button } from '../button/Button.js';
|
|
18
|
-
import { Dialog } from '../dialog/Dialog.js';
|
|
19
15
|
import { Icon } from '../icon/Icon.js';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import { P } from '../typography/typography.js';
|
|
23
|
-
import { AndroidAddToHomeIcon, SafariAddToDockIcon, SafariIcon, SafariPlusSquareIcon, SafariShareIcon, } from './PlatformIcons.js';
|
|
24
|
-
import { triggerDeferredInstall, useIsInstalled, useIsInstallReady, } from './useIsInstallReady.js';
|
|
25
|
-
import { useWebManifest } from './useWebManifest.js';
|
|
16
|
+
import { pwaInstallerState } from './state.js';
|
|
17
|
+
import { useIsInstalled } from './useIsInstallReady.js';
|
|
26
18
|
export function PwaInstallTrigger(_a) {
|
|
27
|
-
var
|
|
28
|
-
var { children, manifestPath, asChild: _ } = _a, rest = __rest(_a, ["children", "manifestPath", "asChild"]);
|
|
19
|
+
var { children } = _a, rest = __rest(_a, ["children"]);
|
|
29
20
|
const installed = useIsInstalled();
|
|
30
|
-
const manifest = useWebManifest(manifestPath);
|
|
31
|
-
const [showInstructions, setShowInstructions] = useState(false);
|
|
32
21
|
if (installed) {
|
|
33
22
|
return null;
|
|
34
23
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
const supportsDirectInstall = getSupportsPWAInstallPrompt();
|
|
39
|
-
function InstallInstructions() {
|
|
40
|
-
const os = getOS();
|
|
41
|
-
if (os === 'iOS' || os === 'Mac OS') {
|
|
42
|
-
if (getIsSafari()) {
|
|
43
|
-
if (os === 'iOS') {
|
|
44
|
-
return (_jsxs(Ol, { children: [_jsxs(Ol.Item, { children: [_jsx(SafariShareIcon, {}), " Tap the Share button in the toolbar."] }), _jsxs(Ol.Item, { children: [_jsx(SafariPlusSquareIcon, {}), " Scroll down and tap \"Add to Home Screen\"."] })] }));
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
return (_jsxs(Ol, { children: [_jsxs(Ol.Item, { children: [_jsx(SafariShareIcon, {}), " Tap the Share button in the toolbar."] }), _jsxs(Ol.Item, { children: [_jsx(SafariAddToDockIcon, {}), " Tap \"Add to Dock\"."] })] }));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
return (_jsxs(_Fragment, { children: [_jsx(Ol, { children: _jsxs(Ol.Item, { children: [_jsx(SafariIcon, {}), " Open this site in Safari to continue."] }) }), _jsx(Box, { surface: true, p: true, children: "Apple does not allow non-Safari browsers to install web apps." })] }));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return (_jsxs(Ol, { children: [_jsxs(Ol.Item, { children: [_jsx(Icon, { name: "dots", className: "rotate-90" }), " Tap the menu button in the toolbar."] }), _jsxs(Ol.Item, { children: [_jsx(AndroidAddToHomeIcon, {}), " Tap \"Add to Home Screen.\""] })] }));
|
|
55
|
-
}
|
|
56
|
-
function ManifestImageGallery({ manifestPath }) {
|
|
57
|
-
var _a, _b;
|
|
58
|
-
const manifest = useWebManifest(manifestPath);
|
|
59
|
-
if (!((_a = manifest === null || manifest === void 0 ? void 0 : manifest.screenshots) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
return (_jsx(Box, { overflow: "auto-x", p: "sm", gap: true, className: "h-240px", children: (_b = manifest.screenshots) === null || _b === void 0 ? void 0 : _b.map((screenshot, index) => (_jsxs(Lightbox.Root, { children: [_jsx(Lightbox.Trigger, { asChild: true, children: _jsx(Lightbox.Image, { tabIndex: 0, src: screenshot.src, alt: screenshot.label || `Screenshot ${index + 1}`, className: "border border-default rounded-xs" }, index) }), _jsxs(Lightbox.Portal, { children: [_jsx(Lightbox.Overlay, { className: "z-10000" }), _jsx(Lightbox.Content, { className: "z-10001", children: _jsx(Lightbox.Image, { src: screenshot.src, alt: screenshot.label || `Screenshot ${index + 1}` }) })] })] }, screenshot.src))) }));
|
|
63
|
-
}
|
|
64
|
-
function InstallDeviceActions({ showInstructions, }) {
|
|
65
|
-
const ready = useIsInstallReady();
|
|
66
|
-
if (supportsDirectInstall && ready) {
|
|
67
|
-
return (_jsxs(Button, { onClick: () => triggerDeferredInstall(), emphasis: "primary", children: [_jsx(Icon, { name: "download" }), " Install now"] }));
|
|
68
|
-
}
|
|
69
|
-
return (_jsxs(Button, { onClick: () => showInstructions(), emphasis: "primary", children: [_jsx(Icon, { name: "arrowRight" }), " Add to Home"] }));
|
|
24
|
+
return (_jsx(Button, Object.assign({ color: "primary", emphasis: "light" }, rest, { onClick: () => {
|
|
25
|
+
pwaInstallerState.open = true;
|
|
26
|
+
}, children: children !== null && children !== void 0 ? children : (_jsxs(_Fragment, { children: [_jsx(Icon, { name: "star" }), " Install"] })) })));
|
|
70
27
|
}
|
|
71
28
|
//# sourceMappingURL=PwaInstallTrigger.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PwaInstallTrigger.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/PwaInstallTrigger.tsx"],"names":[],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"PwaInstallTrigger.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/PwaInstallTrigger.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAIxD,MAAM,UAAU,iBAAiB,CAAC,EAGT;QAHS,EACjC,QAAQ,OAEgB,EADrB,IAAI,cAF0B,YAGjC,CADO;IAEP,MAAM,SAAS,GAAG,cAAc,EAAE,CAAC;IACnC,IAAI,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,CACN,KAAC,MAAM,kBACN,KAAK,EAAC,SAAS,EACf,QAAQ,EAAC,OAAO,IACZ,IAAI,IACR,OAAO,EAAE,GAAG,EAAE;YACb,iBAAiB,CAAC,IAAI,GAAG,IAAI,CAAC;QAC/B,CAAC,YAEA,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,CACZ,8BACC,KAAC,IAAI,IAAC,IAAI,EAAC,MAAM,GAAG,gBAClB,CACH,IACO,CACT,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/components/pwaInstall/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;IACtC,IAAI,EAAE,KAAK;CACX,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc;IAC7B,iBAAiB,CAAC,IAAI,GAAG,IAAI,CAAC;AAC/B,CAAC"}
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ import { useThemedTitleBar, useVisualViewportOffset } from '../../hooks.js';
|
|
|
3
3
|
import { useVirtualKeyboardBehavior } from '../../hooks/useVirtualKeyboardBehavior.js';
|
|
4
4
|
import { IconSpritesheet } from '../icon/index.js';
|
|
5
5
|
import { ParticleLayer } from '../particles/index.js';
|
|
6
|
+
import { PwaInstall } from '../pwaInstall/PwaInstall.js';
|
|
6
7
|
import { Toaster } from '../toasts/toasts.js';
|
|
7
8
|
import { TooltipProvider } from '../tooltip/index.js';
|
|
8
9
|
|
|
@@ -12,6 +13,7 @@ export interface ProviderProps {
|
|
|
12
13
|
disableViewportOffset?: boolean;
|
|
13
14
|
virtualKeyboardBehavior?: 'overlay' | 'displace';
|
|
14
15
|
disableTitleBarColor?: boolean;
|
|
16
|
+
manifestPath?: string;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -23,6 +25,7 @@ export function Provider({
|
|
|
23
25
|
disableViewportOffset,
|
|
24
26
|
virtualKeyboardBehavior = 'displace',
|
|
25
27
|
disableTitleBarColor,
|
|
28
|
+
manifestPath,
|
|
26
29
|
}: ProviderProps) {
|
|
27
30
|
useVisualViewportOffset(disableViewportOffset);
|
|
28
31
|
const supportedVirtualKeyboardBehavior =
|
|
@@ -35,6 +38,7 @@ export function Provider({
|
|
|
35
38
|
<>
|
|
36
39
|
<IconSpritesheet />
|
|
37
40
|
<Toaster />
|
|
41
|
+
<PwaInstall manifestPath={manifestPath} />
|
|
38
42
|
</>
|
|
39
43
|
);
|
|
40
44
|
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { DialogTriggerProps } from '@radix-ui/react-dialog';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { useSnapshot } from 'valtio';
|
|
4
|
+
import {
|
|
5
|
+
getIsSafari,
|
|
6
|
+
getOS,
|
|
7
|
+
getSupportsPWAInstallPrompt,
|
|
8
|
+
} from '../../platform.js';
|
|
9
|
+
import { Box } from '../box/Box.js';
|
|
10
|
+
import { Button } from '../button/Button.js';
|
|
11
|
+
import { Dialog } from '../dialog/Dialog.js';
|
|
12
|
+
import { Icon } from '../icon/Icon.js';
|
|
13
|
+
import { Lightbox } from '../lightbox/Lightbox.js';
|
|
14
|
+
import { Ol } from '../lists/lists.js';
|
|
15
|
+
import { P } from '../typography/typography.js';
|
|
16
|
+
import {
|
|
17
|
+
AndroidAddToHomeIcon,
|
|
18
|
+
SafariAddToDockIcon,
|
|
19
|
+
SafariIcon,
|
|
20
|
+
SafariPlusSquareIcon,
|
|
21
|
+
SafariShareIcon,
|
|
22
|
+
} from './PlatformIcons.js';
|
|
23
|
+
import { pwaInstallerState } from './state.js';
|
|
24
|
+
import {
|
|
25
|
+
triggerDeferredInstall,
|
|
26
|
+
useIsInstalled,
|
|
27
|
+
useIsInstallReady,
|
|
28
|
+
} from './useIsInstallReady.js';
|
|
29
|
+
import { useWebManifest } from './useWebManifest.js';
|
|
30
|
+
|
|
31
|
+
export interface PwaInstall extends DialogTriggerProps {
|
|
32
|
+
manifestPath?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function PwaInstall({
|
|
36
|
+
children,
|
|
37
|
+
manifestPath,
|
|
38
|
+
asChild: _,
|
|
39
|
+
...rest
|
|
40
|
+
}: PwaInstall) {
|
|
41
|
+
const installed = useIsInstalled();
|
|
42
|
+
const manifest = useWebManifest(manifestPath);
|
|
43
|
+
const { open } = useSnapshot(pwaInstallerState);
|
|
44
|
+
|
|
45
|
+
const [showInstructions, setShowInstructions] = useState(false);
|
|
46
|
+
|
|
47
|
+
if (installed) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const primaryIcon = manifest?.icons?.[0];
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Dialog
|
|
55
|
+
open={open}
|
|
56
|
+
onOpenChange={(isOpen) => {
|
|
57
|
+
pwaInstallerState.open = isOpen;
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<Dialog.Content className="flex flex-col gap-xs" id="pwa-install-dialog">
|
|
61
|
+
<Dialog.Title className="flex flex-row gap-md items-center">
|
|
62
|
+
{primaryIcon && (
|
|
63
|
+
<img
|
|
64
|
+
src={primaryIcon.src}
|
|
65
|
+
alt={
|
|
66
|
+
primaryIcon.label ??
|
|
67
|
+
manifest?.short_name ??
|
|
68
|
+
manifest?.name ??
|
|
69
|
+
'App Icon'
|
|
70
|
+
}
|
|
71
|
+
className="inline-block w-1em h-1em rounded"
|
|
72
|
+
/>
|
|
73
|
+
)}
|
|
74
|
+
Install {manifest?.short_name ?? manifest?.name ?? 'App'}
|
|
75
|
+
</Dialog.Title>
|
|
76
|
+
{showInstructions ? (
|
|
77
|
+
<>
|
|
78
|
+
<Dialog.Description>
|
|
79
|
+
Follow the instructions below to install this app on your device.
|
|
80
|
+
</Dialog.Description>
|
|
81
|
+
<InstallInstructions />
|
|
82
|
+
<Dialog.Actions>
|
|
83
|
+
<Dialog.Close asChild>
|
|
84
|
+
<Button emphasis="ghost">Close</Button>
|
|
85
|
+
</Dialog.Close>
|
|
86
|
+
<Button onClick={() => setShowInstructions(false)}>
|
|
87
|
+
<Icon name="arrowLeft" /> Back
|
|
88
|
+
</Button>
|
|
89
|
+
</Dialog.Actions>
|
|
90
|
+
</>
|
|
91
|
+
) : (
|
|
92
|
+
<>
|
|
93
|
+
<Dialog.Description>
|
|
94
|
+
This site is also an app. You can install it right now for easier
|
|
95
|
+
access and more features.
|
|
96
|
+
</Dialog.Description>
|
|
97
|
+
{manifest?.description && (
|
|
98
|
+
<P className="mb-sm">{manifest.description}</P>
|
|
99
|
+
)}
|
|
100
|
+
<ManifestImageGallery manifestPath={manifestPath} />
|
|
101
|
+
<Dialog.Actions>
|
|
102
|
+
<Dialog.Close asChild>
|
|
103
|
+
<Button emphasis="ghost">Close</Button>
|
|
104
|
+
</Dialog.Close>
|
|
105
|
+
<InstallDeviceActions
|
|
106
|
+
showInstructions={() => setShowInstructions(true)}
|
|
107
|
+
/>
|
|
108
|
+
</Dialog.Actions>
|
|
109
|
+
</>
|
|
110
|
+
)}
|
|
111
|
+
</Dialog.Content>
|
|
112
|
+
</Dialog>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const supportsDirectInstall = getSupportsPWAInstallPrompt();
|
|
117
|
+
|
|
118
|
+
function InstallInstructions() {
|
|
119
|
+
const os = getOS();
|
|
120
|
+
if (os === 'iOS' || os === 'Mac OS') {
|
|
121
|
+
if (getIsSafari()) {
|
|
122
|
+
if (os === 'iOS') {
|
|
123
|
+
return (
|
|
124
|
+
<Ol>
|
|
125
|
+
<Ol.Item>
|
|
126
|
+
<SafariShareIcon /> Tap the Share button in the toolbar.
|
|
127
|
+
</Ol.Item>
|
|
128
|
+
<Ol.Item>
|
|
129
|
+
<SafariPlusSquareIcon /> Scroll down and tap "Add to Home Screen".
|
|
130
|
+
</Ol.Item>
|
|
131
|
+
</Ol>
|
|
132
|
+
);
|
|
133
|
+
} else {
|
|
134
|
+
return (
|
|
135
|
+
<Ol>
|
|
136
|
+
<Ol.Item>
|
|
137
|
+
<SafariShareIcon /> Tap the Share button in the toolbar.
|
|
138
|
+
</Ol.Item>
|
|
139
|
+
<Ol.Item>
|
|
140
|
+
<SafariAddToDockIcon /> Tap "Add to Dock".
|
|
141
|
+
</Ol.Item>
|
|
142
|
+
</Ol>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
return (
|
|
147
|
+
<>
|
|
148
|
+
<Ol>
|
|
149
|
+
<Ol.Item>
|
|
150
|
+
<SafariIcon /> Open this site in Safari to continue.
|
|
151
|
+
</Ol.Item>
|
|
152
|
+
</Ol>
|
|
153
|
+
<Box surface p>
|
|
154
|
+
Apple does not allow non-Safari browsers to install web apps.
|
|
155
|
+
</Box>
|
|
156
|
+
</>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<Ol>
|
|
163
|
+
<Ol.Item>
|
|
164
|
+
<Icon name="dots" className="rotate-90" /> Tap the menu button in the
|
|
165
|
+
toolbar.
|
|
166
|
+
</Ol.Item>
|
|
167
|
+
<Ol.Item>
|
|
168
|
+
<AndroidAddToHomeIcon /> Tap "Add to Home Screen."
|
|
169
|
+
</Ol.Item>
|
|
170
|
+
</Ol>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function ManifestImageGallery({ manifestPath }: { manifestPath?: string }) {
|
|
175
|
+
const manifest = useWebManifest(manifestPath);
|
|
176
|
+
|
|
177
|
+
if (!manifest?.screenshots?.length) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<Box overflow="auto-x" p="sm" gap className="h-240px">
|
|
183
|
+
{manifest.screenshots?.map((screenshot, index) => (
|
|
184
|
+
<Lightbox.Root key={screenshot.src}>
|
|
185
|
+
<Lightbox.Trigger asChild>
|
|
186
|
+
<Lightbox.Image
|
|
187
|
+
tabIndex={0}
|
|
188
|
+
key={index}
|
|
189
|
+
src={screenshot.src}
|
|
190
|
+
alt={screenshot.label || `Screenshot ${index + 1}`}
|
|
191
|
+
className="border border-default rounded-xs"
|
|
192
|
+
/>
|
|
193
|
+
</Lightbox.Trigger>
|
|
194
|
+
<Lightbox.Portal>
|
|
195
|
+
<Lightbox.Overlay className="z-10000" />
|
|
196
|
+
<Lightbox.Content className="z-10001">
|
|
197
|
+
<Lightbox.Image
|
|
198
|
+
src={screenshot.src}
|
|
199
|
+
alt={screenshot.label || `Screenshot ${index + 1}`}
|
|
200
|
+
/>
|
|
201
|
+
</Lightbox.Content>
|
|
202
|
+
</Lightbox.Portal>
|
|
203
|
+
</Lightbox.Root>
|
|
204
|
+
))}
|
|
205
|
+
</Box>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function InstallDeviceActions({
|
|
210
|
+
showInstructions,
|
|
211
|
+
}: {
|
|
212
|
+
showInstructions: () => void;
|
|
213
|
+
}) {
|
|
214
|
+
const ready = useIsInstallReady();
|
|
215
|
+
if (supportsDirectInstall && ready) {
|
|
216
|
+
return (
|
|
217
|
+
<Button onClick={() => triggerDeferredInstall()} emphasis="primary">
|
|
218
|
+
<Icon name="download" /> Install now
|
|
219
|
+
</Button>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<Button onClick={() => showInstructions()} emphasis="primary">
|
|
225
|
+
<Icon name="arrowRight" /> Add to Home
|
|
226
|
+
</Button>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
@@ -1,227 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
getIsSafari,
|
|
5
|
-
getOS,
|
|
6
|
-
getSupportsPWAInstallPrompt,
|
|
7
|
-
} from '../../platform.js';
|
|
8
|
-
import { Box } from '../box/Box.js';
|
|
9
|
-
import { Button } from '../button/Button.js';
|
|
10
|
-
import { Dialog } from '../dialog/Dialog.js';
|
|
1
|
+
import { Button, ButtonProps } from '../button/Button.js';
|
|
11
2
|
import { Icon } from '../icon/Icon.js';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { P } from '../typography/typography.js';
|
|
15
|
-
import {
|
|
16
|
-
AndroidAddToHomeIcon,
|
|
17
|
-
SafariAddToDockIcon,
|
|
18
|
-
SafariIcon,
|
|
19
|
-
SafariPlusSquareIcon,
|
|
20
|
-
SafariShareIcon,
|
|
21
|
-
} from './PlatformIcons.js';
|
|
22
|
-
import {
|
|
23
|
-
triggerDeferredInstall,
|
|
24
|
-
useIsInstalled,
|
|
25
|
-
useIsInstallReady,
|
|
26
|
-
} from './useIsInstallReady.js';
|
|
27
|
-
import { useWebManifest } from './useWebManifest.js';
|
|
3
|
+
import { pwaInstallerState } from './state.js';
|
|
4
|
+
import { useIsInstalled } from './useIsInstallReady.js';
|
|
28
5
|
|
|
29
|
-
export interface PwaInstallTriggerProps extends
|
|
30
|
-
manifestPath?: string;
|
|
31
|
-
}
|
|
6
|
+
export interface PwaInstallTriggerProps extends ButtonProps {}
|
|
32
7
|
|
|
33
8
|
export function PwaInstallTrigger({
|
|
34
9
|
children,
|
|
35
|
-
manifestPath,
|
|
36
|
-
asChild: _,
|
|
37
10
|
...rest
|
|
38
11
|
}: PwaInstallTriggerProps) {
|
|
39
12
|
const installed = useIsInstalled();
|
|
40
|
-
const manifest = useWebManifest(manifestPath);
|
|
41
|
-
|
|
42
|
-
const [showInstructions, setShowInstructions] = useState(false);
|
|
43
|
-
|
|
44
13
|
if (installed) {
|
|
45
14
|
return null;
|
|
46
15
|
}
|
|
47
16
|
|
|
48
|
-
const primaryIcon = manifest?.icons?.[0];
|
|
49
|
-
|
|
50
17
|
return (
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
<Dialog.Title className="flex flex-row gap-md items-center">
|
|
61
|
-
{primaryIcon && (
|
|
62
|
-
<img
|
|
63
|
-
src={primaryIcon.src}
|
|
64
|
-
alt={
|
|
65
|
-
primaryIcon.label ??
|
|
66
|
-
manifest?.short_name ??
|
|
67
|
-
manifest?.name ??
|
|
68
|
-
'App Icon'
|
|
69
|
-
}
|
|
70
|
-
className="inline-block w-1em h-1em rounded"
|
|
71
|
-
/>
|
|
72
|
-
)}
|
|
73
|
-
Install {manifest?.short_name ?? manifest?.name ?? 'App'}
|
|
74
|
-
</Dialog.Title>
|
|
75
|
-
{showInstructions ? (
|
|
76
|
-
<>
|
|
77
|
-
<Dialog.Description>
|
|
78
|
-
Follow the instructions below to install this app on your device.
|
|
79
|
-
</Dialog.Description>
|
|
80
|
-
<InstallInstructions />
|
|
81
|
-
<Dialog.Actions>
|
|
82
|
-
<Dialog.Close asChild>
|
|
83
|
-
<Button emphasis="ghost">Close</Button>
|
|
84
|
-
</Dialog.Close>
|
|
85
|
-
<Button onClick={() => setShowInstructions(false)}>
|
|
86
|
-
<Icon name="arrowLeft" /> Back
|
|
87
|
-
</Button>
|
|
88
|
-
</Dialog.Actions>
|
|
89
|
-
</>
|
|
90
|
-
) : (
|
|
91
|
-
<>
|
|
92
|
-
<Dialog.Description>
|
|
93
|
-
This site is also an app. You can install it right now for easier
|
|
94
|
-
access and more features.
|
|
95
|
-
</Dialog.Description>
|
|
96
|
-
{manifest?.description && (
|
|
97
|
-
<P className="mb-sm">{manifest.description}</P>
|
|
98
|
-
)}
|
|
99
|
-
<ManifestImageGallery manifestPath={manifestPath} />
|
|
100
|
-
<Dialog.Actions>
|
|
101
|
-
<Dialog.Close asChild>
|
|
102
|
-
<Button emphasis="ghost">Close</Button>
|
|
103
|
-
</Dialog.Close>
|
|
104
|
-
<InstallDeviceActions
|
|
105
|
-
showInstructions={() => setShowInstructions(true)}
|
|
106
|
-
/>
|
|
107
|
-
</Dialog.Actions>
|
|
108
|
-
</>
|
|
109
|
-
)}
|
|
110
|
-
</Dialog.Content>
|
|
111
|
-
</Dialog>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const supportsDirectInstall = getSupportsPWAInstallPrompt();
|
|
116
|
-
|
|
117
|
-
function InstallInstructions() {
|
|
118
|
-
const os = getOS();
|
|
119
|
-
if (os === 'iOS' || os === 'Mac OS') {
|
|
120
|
-
if (getIsSafari()) {
|
|
121
|
-
if (os === 'iOS') {
|
|
122
|
-
return (
|
|
123
|
-
<Ol>
|
|
124
|
-
<Ol.Item>
|
|
125
|
-
<SafariShareIcon /> Tap the Share button in the toolbar.
|
|
126
|
-
</Ol.Item>
|
|
127
|
-
<Ol.Item>
|
|
128
|
-
<SafariPlusSquareIcon /> Scroll down and tap "Add to Home Screen".
|
|
129
|
-
</Ol.Item>
|
|
130
|
-
</Ol>
|
|
131
|
-
);
|
|
132
|
-
} else {
|
|
133
|
-
return (
|
|
134
|
-
<Ol>
|
|
135
|
-
<Ol.Item>
|
|
136
|
-
<SafariShareIcon /> Tap the Share button in the toolbar.
|
|
137
|
-
</Ol.Item>
|
|
138
|
-
<Ol.Item>
|
|
139
|
-
<SafariAddToDockIcon /> Tap "Add to Dock".
|
|
140
|
-
</Ol.Item>
|
|
141
|
-
</Ol>
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
} else {
|
|
145
|
-
return (
|
|
18
|
+
<Button
|
|
19
|
+
color="primary"
|
|
20
|
+
emphasis="light"
|
|
21
|
+
{...rest}
|
|
22
|
+
onClick={() => {
|
|
23
|
+
pwaInstallerState.open = true;
|
|
24
|
+
}}
|
|
25
|
+
>
|
|
26
|
+
{children ?? (
|
|
146
27
|
<>
|
|
147
|
-
<
|
|
148
|
-
<Ol.Item>
|
|
149
|
-
<SafariIcon /> Open this site in Safari to continue.
|
|
150
|
-
</Ol.Item>
|
|
151
|
-
</Ol>
|
|
152
|
-
<Box surface p>
|
|
153
|
-
Apple does not allow non-Safari browsers to install web apps.
|
|
154
|
-
</Box>
|
|
28
|
+
<Icon name="star" /> Install
|
|
155
29
|
</>
|
|
156
|
-
)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<Ol>
|
|
162
|
-
<Ol.Item>
|
|
163
|
-
<Icon name="dots" className="rotate-90" /> Tap the menu button in the
|
|
164
|
-
toolbar.
|
|
165
|
-
</Ol.Item>
|
|
166
|
-
<Ol.Item>
|
|
167
|
-
<AndroidAddToHomeIcon /> Tap "Add to Home Screen."
|
|
168
|
-
</Ol.Item>
|
|
169
|
-
</Ol>
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function ManifestImageGallery({ manifestPath }: { manifestPath?: string }) {
|
|
174
|
-
const manifest = useWebManifest(manifestPath);
|
|
175
|
-
|
|
176
|
-
if (!manifest?.screenshots?.length) {
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return (
|
|
181
|
-
<Box overflow="auto-x" p="sm" gap className="h-240px">
|
|
182
|
-
{manifest.screenshots?.map((screenshot, index) => (
|
|
183
|
-
<Lightbox.Root key={screenshot.src}>
|
|
184
|
-
<Lightbox.Trigger asChild>
|
|
185
|
-
<Lightbox.Image
|
|
186
|
-
tabIndex={0}
|
|
187
|
-
key={index}
|
|
188
|
-
src={screenshot.src}
|
|
189
|
-
alt={screenshot.label || `Screenshot ${index + 1}`}
|
|
190
|
-
className="border border-default rounded-xs"
|
|
191
|
-
/>
|
|
192
|
-
</Lightbox.Trigger>
|
|
193
|
-
<Lightbox.Portal>
|
|
194
|
-
<Lightbox.Overlay className="z-10000" />
|
|
195
|
-
<Lightbox.Content className="z-10001">
|
|
196
|
-
<Lightbox.Image
|
|
197
|
-
src={screenshot.src}
|
|
198
|
-
alt={screenshot.label || `Screenshot ${index + 1}`}
|
|
199
|
-
/>
|
|
200
|
-
</Lightbox.Content>
|
|
201
|
-
</Lightbox.Portal>
|
|
202
|
-
</Lightbox.Root>
|
|
203
|
-
))}
|
|
204
|
-
</Box>
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function InstallDeviceActions({
|
|
209
|
-
showInstructions,
|
|
210
|
-
}: {
|
|
211
|
-
showInstructions: () => void;
|
|
212
|
-
}) {
|
|
213
|
-
const ready = useIsInstallReady();
|
|
214
|
-
if (supportsDirectInstall && ready) {
|
|
215
|
-
return (
|
|
216
|
-
<Button onClick={() => triggerDeferredInstall()} emphasis="primary">
|
|
217
|
-
<Icon name="download" /> Install now
|
|
218
|
-
</Button>
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return (
|
|
223
|
-
<Button onClick={() => showInstructions()} emphasis="primary">
|
|
224
|
-
<Icon name="arrowRight" /> Add to Home
|
|
30
|
+
)}
|
|
225
31
|
</Button>
|
|
226
32
|
);
|
|
227
33
|
}
|