@omg-dev/pwa 0.4.24
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/auto.mjs +26 -0
- package/dist/core-YJoFChtB.mjs +151 -0
- package/dist/index.mjs +3 -0
- package/dist/react-Q0c2GHRr.mjs +726 -0
- package/dist/remix-cta.mjs +122 -0
- package/package.json +42 -0
- package/src/auto.tsx +55 -0
- package/src/core.ts +197 -0
- package/src/icons.tsx +134 -0
- package/src/index.ts +21 -0
- package/src/react.tsx +364 -0
- package/src/remix-cta.tsx +160 -0
- package/src/styles.ts +213 -0
package/dist/auto.mjs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { a as isDismissed, f as wasAutoShown, l as setAutoShown, n as detectPlatform, o as isInIframe, s as isStandalone, t as countVisit } from "./core-YJoFChtB.mjs";
|
|
2
|
+
import { n as VibesInstallPrompt } from "./react-Q0c2GHRr.mjs";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { createRoot } from "react-dom/client";
|
|
5
|
+
//#region src/auto.tsx
|
|
6
|
+
function shouldAutoShow() {
|
|
7
|
+
if (typeof window === "undefined" || typeof document === "undefined") return false;
|
|
8
|
+
if (isInIframe()) return false;
|
|
9
|
+
if (isStandalone()) return false;
|
|
10
|
+
if (isDismissed() || wasAutoShown()) return false;
|
|
11
|
+
const platform = detectPlatform();
|
|
12
|
+
if (platform !== "ios-safari" && platform !== "ios-chrome" && platform !== "ios-other" && platform !== "android") return false;
|
|
13
|
+
return countVisit() >= 2;
|
|
14
|
+
}
|
|
15
|
+
function mount() {
|
|
16
|
+
if (!shouldAutoShow()) return;
|
|
17
|
+
setAutoShown();
|
|
18
|
+
const host = document.createElement("div");
|
|
19
|
+
host.id = "vibes-pwa-auto";
|
|
20
|
+
document.body.appendChild(host);
|
|
21
|
+
createRoot(host).render(/* @__PURE__ */ jsx(VibesInstallPrompt, { variant: "floating" }));
|
|
22
|
+
}
|
|
23
|
+
if (typeof window !== "undefined") if (document.readyState === "complete") setTimeout(mount, 2500);
|
|
24
|
+
else window.addEventListener("load", () => setTimeout(mount, 2500), { once: true });
|
|
25
|
+
//#endregion
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
//#region src/core.ts
|
|
2
|
+
function detectPlatform() {
|
|
3
|
+
if (typeof navigator === "undefined") return "unsupported";
|
|
4
|
+
const ua = navigator.userAgent;
|
|
5
|
+
if (/iPad|iPhone|iPod/.test(ua) || /Mac/.test(ua) && navigator.maxTouchPoints > 1) {
|
|
6
|
+
if (/CriOS/.test(ua)) return "ios-chrome";
|
|
7
|
+
if (/FxiOS|EdgiOS|OPiOS|OPT\//.test(ua)) return "ios-other";
|
|
8
|
+
if (/Safari/.test(ua)) return "ios-safari";
|
|
9
|
+
return "unsupported";
|
|
10
|
+
}
|
|
11
|
+
if (/Android/.test(ua)) {
|
|
12
|
+
if (/; wv\)/.test(ua)) return "unsupported";
|
|
13
|
+
return "android";
|
|
14
|
+
}
|
|
15
|
+
if (/Edg\//.test(ua)) return "desktop-chrome";
|
|
16
|
+
if (/Chrome|Chromium/.test(ua)) return "desktop-chrome";
|
|
17
|
+
if (/Safari/.test(ua)) return "desktop-safari";
|
|
18
|
+
return "unsupported";
|
|
19
|
+
}
|
|
20
|
+
function isStandalone() {
|
|
21
|
+
if (typeof window === "undefined") return false;
|
|
22
|
+
if (window.matchMedia?.("(display-mode: standalone)").matches) return true;
|
|
23
|
+
return navigator.standalone === true;
|
|
24
|
+
}
|
|
25
|
+
/** True inside any iframe — e.g. the omg dashboard's preview pane. The
|
|
26
|
+
* install UI must never render there: the iframe URL is not the app URL. */
|
|
27
|
+
function isInIframe() {
|
|
28
|
+
try {
|
|
29
|
+
return window.self !== window.top;
|
|
30
|
+
} catch {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const SERVER_SNAPSHOT = {
|
|
35
|
+
canPrompt: false,
|
|
36
|
+
installed: false
|
|
37
|
+
};
|
|
38
|
+
function getStore() {
|
|
39
|
+
if (typeof window === "undefined") return null;
|
|
40
|
+
const w = window;
|
|
41
|
+
if (!w.__vibesPwaStore) {
|
|
42
|
+
const store = {
|
|
43
|
+
bip: null,
|
|
44
|
+
snapshot: {
|
|
45
|
+
canPrompt: false,
|
|
46
|
+
installed: isStandalone()
|
|
47
|
+
},
|
|
48
|
+
subs: /* @__PURE__ */ new Set()
|
|
49
|
+
};
|
|
50
|
+
w.__vibesPwaStore = store;
|
|
51
|
+
window.addEventListener("beforeinstallprompt", (e) => {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
store.bip = e;
|
|
54
|
+
publish(store);
|
|
55
|
+
});
|
|
56
|
+
window.addEventListener("appinstalled", () => {
|
|
57
|
+
store.bip = null;
|
|
58
|
+
store.snapshot = {
|
|
59
|
+
canPrompt: false,
|
|
60
|
+
installed: true
|
|
61
|
+
};
|
|
62
|
+
for (const cb of store.subs) cb();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return w.__vibesPwaStore;
|
|
66
|
+
}
|
|
67
|
+
function publish(store) {
|
|
68
|
+
store.snapshot = {
|
|
69
|
+
canPrompt: !!store.bip,
|
|
70
|
+
installed: store.snapshot.installed
|
|
71
|
+
};
|
|
72
|
+
for (const cb of store.subs) cb();
|
|
73
|
+
}
|
|
74
|
+
getStore();
|
|
75
|
+
function subscribeInstallState(cb) {
|
|
76
|
+
const store = getStore();
|
|
77
|
+
if (!store) return () => {};
|
|
78
|
+
store.subs.add(cb);
|
|
79
|
+
return () => store.subs.delete(cb);
|
|
80
|
+
}
|
|
81
|
+
function getInstallState() {
|
|
82
|
+
return getStore()?.snapshot ?? SERVER_SNAPSHOT;
|
|
83
|
+
}
|
|
84
|
+
function getServerInstallState() {
|
|
85
|
+
return SERVER_SNAPSHOT;
|
|
86
|
+
}
|
|
87
|
+
/** Fire the captured native install prompt (Chromium only). Resolves
|
|
88
|
+
* "unavailable" when no prompt was captured OR prompt() itself fails
|
|
89
|
+
* (emulated/headless contexts) — callers fall back to the guide. */
|
|
90
|
+
async function promptNativeInstall() {
|
|
91
|
+
const store = getStore();
|
|
92
|
+
if (!store?.bip) return "unavailable";
|
|
93
|
+
const ev = store.bip;
|
|
94
|
+
store.bip = null;
|
|
95
|
+
try {
|
|
96
|
+
await ev.prompt();
|
|
97
|
+
const { outcome } = await ev.userChoice;
|
|
98
|
+
if (outcome === "accepted") store.snapshot = {
|
|
99
|
+
canPrompt: false,
|
|
100
|
+
installed: true
|
|
101
|
+
};
|
|
102
|
+
publish(store);
|
|
103
|
+
return outcome;
|
|
104
|
+
} catch {
|
|
105
|
+
publish(store);
|
|
106
|
+
return "unavailable";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const KEY_DISMISSED = "vibes-pwa:dismissed";
|
|
110
|
+
const KEY_VISITS = "vibes-pwa:visits";
|
|
111
|
+
const KEY_AUTO_SHOWN = "vibes-pwa:auto-shown";
|
|
112
|
+
const SESSION_COUNTED = "vibes-pwa:counted";
|
|
113
|
+
function lsGet(key) {
|
|
114
|
+
try {
|
|
115
|
+
return localStorage.getItem(key);
|
|
116
|
+
} catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function lsSet(key, value) {
|
|
121
|
+
try {
|
|
122
|
+
localStorage.setItem(key, value);
|
|
123
|
+
} catch {}
|
|
124
|
+
}
|
|
125
|
+
function isDismissed() {
|
|
126
|
+
return lsGet(KEY_DISMISSED) === "1";
|
|
127
|
+
}
|
|
128
|
+
function setDismissed() {
|
|
129
|
+
lsSet(KEY_DISMISSED, "1");
|
|
130
|
+
}
|
|
131
|
+
function wasAutoShown() {
|
|
132
|
+
return lsGet(KEY_AUTO_SHOWN) === "1";
|
|
133
|
+
}
|
|
134
|
+
function setAutoShown() {
|
|
135
|
+
lsSet(KEY_AUTO_SHOWN, "1");
|
|
136
|
+
}
|
|
137
|
+
/** Count one visit per browser session; returns the running total. */
|
|
138
|
+
function countVisit() {
|
|
139
|
+
const prev = Number(lsGet(KEY_VISITS) ?? "0") || 0;
|
|
140
|
+
try {
|
|
141
|
+
if (sessionStorage.getItem(SESSION_COUNTED) === "1") return prev;
|
|
142
|
+
sessionStorage.setItem(SESSION_COUNTED, "1");
|
|
143
|
+
} catch {
|
|
144
|
+
return prev + 1;
|
|
145
|
+
}
|
|
146
|
+
const next = prev + 1;
|
|
147
|
+
lsSet(KEY_VISITS, String(next));
|
|
148
|
+
return next;
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
export { isDismissed as a, promptNativeInstall as c, subscribeInstallState as d, wasAutoShown as f, getServerInstallState as i, setAutoShown as l, detectPlatform as n, isInIframe as o, getInstallState as r, isStandalone as s, countVisit as t, setDismissed as u };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as isDismissed, c as promptNativeInstall, n as detectPlatform, o as isInIframe, s as isStandalone, t as countVisit, u as setDismissed } from "./core-YJoFChtB.mjs";
|
|
2
|
+
import { i as useInstallPrompt, n as VibesInstallPrompt, r as defaultAppName, t as InstallGuide } from "./react-Q0c2GHRr.mjs";
|
|
3
|
+
export { InstallGuide, VibesInstallPrompt, countVisit, defaultAppName, detectPlatform, isDismissed, isInIframe, isStandalone, promptNativeInstall, setDismissed, useInstallPrompt };
|