@hook-sdk/template 0.11.0 → 0.12.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/dist/index.cjs +50 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +50 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -118,6 +118,16 @@ interface PushPromptTexts {
|
|
|
118
118
|
iosInstallCta?: string;
|
|
119
119
|
deniedTitle: string;
|
|
120
120
|
deniedBody: string;
|
|
121
|
+
/**
|
|
122
|
+
* Audit Wave 3 — Fix #33: per-platform recovery copy shown when permission
|
|
123
|
+
* is denied. All four are optional; if the matching platform's copy is
|
|
124
|
+
* missing the recovery paragraph is omitted (back-compat for callers that
|
|
125
|
+
* haven't supplied them yet).
|
|
126
|
+
*/
|
|
127
|
+
deniedRecoveryIos?: string;
|
|
128
|
+
deniedRecoveryAndroid?: string;
|
|
129
|
+
deniedRecoveryDesktop?: string;
|
|
130
|
+
deniedRecoveryInApp?: string;
|
|
121
131
|
unsupportedBody: string;
|
|
122
132
|
}
|
|
123
133
|
interface PushPromptProps {
|
|
@@ -534,6 +544,8 @@ type PushUiState = {
|
|
|
534
544
|
kind: 'subscribed';
|
|
535
545
|
} | {
|
|
536
546
|
kind: 'denied';
|
|
547
|
+
} | {
|
|
548
|
+
kind: 'dismissed';
|
|
537
549
|
} | {
|
|
538
550
|
kind: 'error';
|
|
539
551
|
code: string;
|
|
@@ -543,6 +555,7 @@ declare function usePush(): {
|
|
|
543
555
|
state: PushUiState;
|
|
544
556
|
subscribe: () => Promise<void>;
|
|
545
557
|
unsubscribe: () => Promise<void>;
|
|
558
|
+
dismiss: () => void;
|
|
546
559
|
};
|
|
547
560
|
|
|
548
561
|
declare function useReminders(): {
|
|
@@ -560,7 +573,7 @@ declare function useReminders(): {
|
|
|
560
573
|
sendAt: string | Date;
|
|
561
574
|
title: string;
|
|
562
575
|
body: string;
|
|
563
|
-
url
|
|
576
|
+
url: string;
|
|
564
577
|
}>) => Promise<{
|
|
565
578
|
accepted: number;
|
|
566
579
|
rejected: number;
|
|
@@ -572,7 +585,7 @@ declare function useReminders(): {
|
|
|
572
585
|
slot: string;
|
|
573
586
|
title: string;
|
|
574
587
|
body: string;
|
|
575
|
-
url
|
|
588
|
+
url: string;
|
|
576
589
|
}>) => Promise<void>>[0]) => Promise<void>;
|
|
577
590
|
};
|
|
578
591
|
|
package/dist/index.d.ts
CHANGED
|
@@ -118,6 +118,16 @@ interface PushPromptTexts {
|
|
|
118
118
|
iosInstallCta?: string;
|
|
119
119
|
deniedTitle: string;
|
|
120
120
|
deniedBody: string;
|
|
121
|
+
/**
|
|
122
|
+
* Audit Wave 3 — Fix #33: per-platform recovery copy shown when permission
|
|
123
|
+
* is denied. All four are optional; if the matching platform's copy is
|
|
124
|
+
* missing the recovery paragraph is omitted (back-compat for callers that
|
|
125
|
+
* haven't supplied them yet).
|
|
126
|
+
*/
|
|
127
|
+
deniedRecoveryIos?: string;
|
|
128
|
+
deniedRecoveryAndroid?: string;
|
|
129
|
+
deniedRecoveryDesktop?: string;
|
|
130
|
+
deniedRecoveryInApp?: string;
|
|
121
131
|
unsupportedBody: string;
|
|
122
132
|
}
|
|
123
133
|
interface PushPromptProps {
|
|
@@ -534,6 +544,8 @@ type PushUiState = {
|
|
|
534
544
|
kind: 'subscribed';
|
|
535
545
|
} | {
|
|
536
546
|
kind: 'denied';
|
|
547
|
+
} | {
|
|
548
|
+
kind: 'dismissed';
|
|
537
549
|
} | {
|
|
538
550
|
kind: 'error';
|
|
539
551
|
code: string;
|
|
@@ -543,6 +555,7 @@ declare function usePush(): {
|
|
|
543
555
|
state: PushUiState;
|
|
544
556
|
subscribe: () => Promise<void>;
|
|
545
557
|
unsubscribe: () => Promise<void>;
|
|
558
|
+
dismiss: () => void;
|
|
546
559
|
};
|
|
547
560
|
|
|
548
561
|
declare function useReminders(): {
|
|
@@ -560,7 +573,7 @@ declare function useReminders(): {
|
|
|
560
573
|
sendAt: string | Date;
|
|
561
574
|
title: string;
|
|
562
575
|
body: string;
|
|
563
|
-
url
|
|
576
|
+
url: string;
|
|
564
577
|
}>) => Promise<{
|
|
565
578
|
accepted: number;
|
|
566
579
|
rejected: number;
|
|
@@ -572,7 +585,7 @@ declare function useReminders(): {
|
|
|
572
585
|
slot: string;
|
|
573
586
|
title: string;
|
|
574
587
|
body: string;
|
|
575
|
-
url
|
|
588
|
+
url: string;
|
|
576
589
|
}>) => Promise<void>>[0]) => Promise<void>;
|
|
577
590
|
};
|
|
578
591
|
|
package/dist/index.js
CHANGED
|
@@ -2000,6 +2000,8 @@ function FallbackPaywall() {
|
|
|
2000
2000
|
// src/hooks/usePush.ts
|
|
2001
2001
|
import { useCallback as useCallback4, useEffect as useEffect6, useState as useState5 } from "react";
|
|
2002
2002
|
import { useHook as useHook5 } from "@hook-sdk/sdk";
|
|
2003
|
+
var DISMISS_STORAGE_KEY = "push:dismissed-until";
|
|
2004
|
+
var DISMISS_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
2003
2005
|
function detectIosNeedsInstall() {
|
|
2004
2006
|
if (typeof navigator === "undefined" || typeof window === "undefined") return false;
|
|
2005
2007
|
const ua = navigator.userAgent || "";
|
|
@@ -2010,6 +2012,21 @@ function detectIosNeedsInstall() {
|
|
|
2010
2012
|
const legacyStandalone = typeof navigator.standalone === "boolean" ? navigator.standalone : false;
|
|
2011
2013
|
return !(standalone || legacyStandalone);
|
|
2012
2014
|
}
|
|
2015
|
+
function readDismissedUntil() {
|
|
2016
|
+
if (typeof localStorage === "undefined") return null;
|
|
2017
|
+
try {
|
|
2018
|
+
const raw = localStorage.getItem(DISMISS_STORAGE_KEY);
|
|
2019
|
+
if (raw === null) return null;
|
|
2020
|
+
const n = Number.parseInt(raw, 10);
|
|
2021
|
+
return Number.isFinite(n) ? n : null;
|
|
2022
|
+
} catch {
|
|
2023
|
+
return null;
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
function isDismissedNow() {
|
|
2027
|
+
const until = readDismissedUntil();
|
|
2028
|
+
return until !== null && until > Date.now();
|
|
2029
|
+
}
|
|
2013
2030
|
function deriveState(push) {
|
|
2014
2031
|
if (!push.isAvailable()) {
|
|
2015
2032
|
if (detectIosNeedsInstall()) return { kind: "ios_needs_install" };
|
|
@@ -2022,6 +2039,7 @@ function deriveState(push) {
|
|
|
2022
2039
|
if (detectIosNeedsInstall()) return { kind: "ios_needs_install" };
|
|
2023
2040
|
return { kind: "unsupported" };
|
|
2024
2041
|
}
|
|
2042
|
+
if (isDismissedNow()) return { kind: "dismissed" };
|
|
2025
2043
|
return { kind: "prompt" };
|
|
2026
2044
|
}
|
|
2027
2045
|
function usePush() {
|
|
@@ -2051,14 +2069,41 @@ function usePush() {
|
|
|
2051
2069
|
throw e;
|
|
2052
2070
|
}
|
|
2053
2071
|
}, [push]);
|
|
2054
|
-
|
|
2072
|
+
const dismiss = useCallback4(() => {
|
|
2073
|
+
if (typeof localStorage !== "undefined") {
|
|
2074
|
+
try {
|
|
2075
|
+
localStorage.setItem(DISMISS_STORAGE_KEY, String(Date.now() + DISMISS_TTL_MS));
|
|
2076
|
+
} catch {
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
setState({ kind: "dismissed" });
|
|
2080
|
+
}, []);
|
|
2081
|
+
return { state, subscribe, unsubscribe, dismiss };
|
|
2055
2082
|
}
|
|
2056
2083
|
|
|
2057
2084
|
// src/components/PushPrompt.tsx
|
|
2058
2085
|
import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2086
|
+
function platformRecoveryCopy(texts) {
|
|
2087
|
+
if (typeof navigator === "undefined") return null;
|
|
2088
|
+
const ua = navigator.userAgent || "";
|
|
2089
|
+
const platform = detectPlatform(ua);
|
|
2090
|
+
switch (platform) {
|
|
2091
|
+
case "ios-safari":
|
|
2092
|
+
case "ios-other":
|
|
2093
|
+
return texts.deniedRecoveryIos ?? null;
|
|
2094
|
+
case "android":
|
|
2095
|
+
return texts.deniedRecoveryAndroid ?? null;
|
|
2096
|
+
case "desktop":
|
|
2097
|
+
return texts.deniedRecoveryDesktop ?? null;
|
|
2098
|
+
case "in-app":
|
|
2099
|
+
return texts.deniedRecoveryInApp ?? null;
|
|
2100
|
+
default:
|
|
2101
|
+
return null;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2059
2104
|
function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
|
|
2060
2105
|
const { state, subscribe } = usePush();
|
|
2061
|
-
if (state.kind === "subscribed") return null;
|
|
2106
|
+
if (state.kind === "subscribed" || state.kind === "dismissed") return null;
|
|
2062
2107
|
if (state.kind === "ios_needs_install") {
|
|
2063
2108
|
return /* @__PURE__ */ jsxs14("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
2064
2109
|
/* @__PURE__ */ jsx19("h3", { children: texts.iosInstallTitle }),
|
|
@@ -2067,9 +2112,11 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
|
|
|
2067
2112
|
] });
|
|
2068
2113
|
}
|
|
2069
2114
|
if (state.kind === "denied") {
|
|
2115
|
+
const recovery = platformRecoveryCopy(texts);
|
|
2070
2116
|
return /* @__PURE__ */ jsxs14("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
|
|
2071
2117
|
/* @__PURE__ */ jsx19("h3", { children: texts.deniedTitle }),
|
|
2072
|
-
/* @__PURE__ */ jsx19("p", { children: texts.deniedBody })
|
|
2118
|
+
/* @__PURE__ */ jsx19("p", { children: texts.deniedBody }),
|
|
2119
|
+
recovery && /* @__PURE__ */ jsx19("p", { "data-testid": "denied-recovery", children: recovery })
|
|
2073
2120
|
] });
|
|
2074
2121
|
}
|
|
2075
2122
|
if (state.kind === "unsupported") {
|