@hook-sdk/template 0.1.4 → 0.2.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 +154 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -11
- package/dist/index.d.ts +83 -11
- package/dist/index.js +152 -24
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -29,12 +29,14 @@ __export(index_exports, {
|
|
|
29
29
|
EmptyState: () => EmptyState,
|
|
30
30
|
ErrorBoundary: () => ErrorBoundary,
|
|
31
31
|
LoadingState: () => LoadingState,
|
|
32
|
+
PushPrompt: () => PushPrompt2,
|
|
32
33
|
useAuth: () => useAuth,
|
|
33
34
|
useAuthPrimitives: () => useAuthPrimitives,
|
|
34
35
|
useForgotForm: () => useForgotForm,
|
|
35
36
|
useLoginForm: () => useLoginForm,
|
|
36
37
|
usePaywallState: () => usePaywallState,
|
|
37
38
|
usePush: () => usePush,
|
|
39
|
+
useReminders: () => useReminders,
|
|
38
40
|
useResetForm: () => useResetForm,
|
|
39
41
|
useSignupForm: () => useSignupForm,
|
|
40
42
|
useSubscription: () => useSubscription,
|
|
@@ -821,23 +823,123 @@ function AppRoot({
|
|
|
821
823
|
] }) }) }) }) }) }) });
|
|
822
824
|
}
|
|
823
825
|
|
|
824
|
-
// src/
|
|
826
|
+
// src/hooks/usePush.ts
|
|
827
|
+
var import_react12 = require("react");
|
|
828
|
+
var import_sdk10 = require("@hook-sdk/sdk");
|
|
829
|
+
function detectIosNeedsInstall() {
|
|
830
|
+
if (typeof navigator === "undefined" || typeof window === "undefined") return false;
|
|
831
|
+
const ua = navigator.userAgent || "";
|
|
832
|
+
const isIos = /iPhone|iPad|iPod/.test(ua);
|
|
833
|
+
if (!isIos) return false;
|
|
834
|
+
const mm = window.matchMedia?.("(display-mode: standalone)");
|
|
835
|
+
const standalone = mm?.matches === true;
|
|
836
|
+
const legacyStandalone = typeof navigator.standalone === "boolean" ? navigator.standalone : false;
|
|
837
|
+
return !(standalone || legacyStandalone);
|
|
838
|
+
}
|
|
839
|
+
function deriveState(push) {
|
|
840
|
+
if (!push.isAvailable()) {
|
|
841
|
+
if (detectIosNeedsInstall()) return { kind: "ios_needs_install" };
|
|
842
|
+
return { kind: "unsupported" };
|
|
843
|
+
}
|
|
844
|
+
const status = push.status();
|
|
845
|
+
if (status === "granted") return { kind: "subscribed" };
|
|
846
|
+
if (status === "denied") return { kind: "denied" };
|
|
847
|
+
if (status === "unsupported") {
|
|
848
|
+
if (detectIosNeedsInstall()) return { kind: "ios_needs_install" };
|
|
849
|
+
return { kind: "unsupported" };
|
|
850
|
+
}
|
|
851
|
+
return { kind: "prompt" };
|
|
852
|
+
}
|
|
853
|
+
function usePush() {
|
|
854
|
+
const { push } = (0, import_sdk10.useHook)();
|
|
855
|
+
const [state, setState] = (0, import_react12.useState)(() => deriveState(push));
|
|
856
|
+
(0, import_react12.useEffect)(() => {
|
|
857
|
+
setState(deriveState(push));
|
|
858
|
+
}, [push]);
|
|
859
|
+
const subscribe = (0, import_react12.useCallback)(async () => {
|
|
860
|
+
try {
|
|
861
|
+
await push.subscribe();
|
|
862
|
+
setState({ kind: "subscribed" });
|
|
863
|
+
} catch (e) {
|
|
864
|
+
const code = e?.code ?? "push.unknown";
|
|
865
|
+
const message = e?.message ?? "Push subscription failed";
|
|
866
|
+
if (code === "push.permission_denied") setState({ kind: "denied" });
|
|
867
|
+
else setState({ kind: "error", code, message });
|
|
868
|
+
throw e;
|
|
869
|
+
}
|
|
870
|
+
}, [push]);
|
|
871
|
+
const unsubscribe = (0, import_react12.useCallback)(async () => {
|
|
872
|
+
try {
|
|
873
|
+
await push.unsubscribe();
|
|
874
|
+
setState({ kind: "prompt" });
|
|
875
|
+
} catch (e) {
|
|
876
|
+
setState({ kind: "error", code: e?.code ?? "push.unknown", message: e?.message ?? "failed" });
|
|
877
|
+
throw e;
|
|
878
|
+
}
|
|
879
|
+
}, [push]);
|
|
880
|
+
return { state, subscribe, unsubscribe };
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// src/components/PushPrompt.tsx
|
|
825
884
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
885
|
+
function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
|
|
886
|
+
const { state, subscribe } = usePush();
|
|
887
|
+
if (state.kind === "subscribed") return null;
|
|
888
|
+
if (state.kind === "ios_needs_install") {
|
|
889
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { children: texts.iosInstallTitle }),
|
|
891
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: texts.iosInstallBody }),
|
|
892
|
+
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
893
|
+
] });
|
|
894
|
+
}
|
|
895
|
+
if (state.kind === "denied") {
|
|
896
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
|
|
897
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { children: texts.deniedTitle }),
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: texts.deniedBody })
|
|
899
|
+
] });
|
|
900
|
+
}
|
|
901
|
+
if (state.kind === "unsupported") {
|
|
902
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: texts.unsupportedBody }) });
|
|
903
|
+
}
|
|
904
|
+
if (state.kind === "error") {
|
|
905
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: state.message }) });
|
|
906
|
+
}
|
|
907
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className, role: "region", children: [
|
|
908
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
909
|
+
"button",
|
|
910
|
+
{
|
|
911
|
+
type: "button",
|
|
912
|
+
onClick: async () => {
|
|
913
|
+
try {
|
|
914
|
+
await subscribe();
|
|
915
|
+
onSubscribed?.();
|
|
916
|
+
} catch {
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
children: texts.cta
|
|
920
|
+
}
|
|
921
|
+
),
|
|
922
|
+
onDeclined && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
|
|
923
|
+
] });
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// src/defaults/EmptyState.tsx
|
|
927
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
826
928
|
function EmptyState({ title, description, action }) {
|
|
827
|
-
return /* @__PURE__ */ (0,
|
|
828
|
-
/* @__PURE__ */ (0,
|
|
829
|
-
description && /* @__PURE__ */ (0,
|
|
830
|
-
action && /* @__PURE__ */ (0,
|
|
929
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
|
|
931
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: { opacity: 0.7 }, children: description }),
|
|
932
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { marginTop: 16 }, children: action })
|
|
831
933
|
] });
|
|
832
934
|
}
|
|
833
935
|
|
|
834
936
|
// src/hooks/useAuthPrimitives.ts
|
|
835
|
-
var
|
|
836
|
-
var
|
|
937
|
+
var import_react13 = require("react");
|
|
938
|
+
var import_sdk11 = require("@hook-sdk/sdk");
|
|
837
939
|
var warned = false;
|
|
838
940
|
function useAuthPrimitives() {
|
|
839
|
-
const { auth } = (0,
|
|
840
|
-
(0,
|
|
941
|
+
const { auth } = (0, import_sdk11.useHook)();
|
|
942
|
+
(0, import_react13.useEffect)(() => {
|
|
841
943
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
842
944
|
warned = true;
|
|
843
945
|
console.warn(
|
|
@@ -859,37 +961,63 @@ function useAuthPrimitives() {
|
|
|
859
961
|
}
|
|
860
962
|
|
|
861
963
|
// src/hooks/useSubscription.ts
|
|
862
|
-
var
|
|
964
|
+
var import_sdk12 = require("@hook-sdk/sdk");
|
|
863
965
|
function useSubscription() {
|
|
864
|
-
const { subscription } = (0,
|
|
966
|
+
const { subscription } = (0, import_sdk12.useHook)();
|
|
865
967
|
return {
|
|
866
968
|
status: subscription.status()
|
|
867
969
|
};
|
|
868
970
|
}
|
|
869
971
|
|
|
870
|
-
// src/hooks/
|
|
871
|
-
var
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
972
|
+
// src/hooks/useReminders.ts
|
|
973
|
+
var import_react14 = require("react");
|
|
974
|
+
var import_sdk13 = require("@hook-sdk/sdk");
|
|
975
|
+
function useReminders() {
|
|
976
|
+
const { push } = (0, import_sdk13.useHook)();
|
|
977
|
+
const r = push.reminders;
|
|
978
|
+
const [reminders, setReminders] = (0, import_react14.useState)([]);
|
|
979
|
+
const [loading, setLoading] = (0, import_react14.useState)(true);
|
|
980
|
+
const reload = (0, import_react14.useCallback)(async () => {
|
|
981
|
+
setLoading(true);
|
|
982
|
+
try {
|
|
983
|
+
const next = await r.list();
|
|
984
|
+
setReminders(next);
|
|
985
|
+
} finally {
|
|
986
|
+
setLoading(false);
|
|
987
|
+
}
|
|
988
|
+
}, [r]);
|
|
989
|
+
(0, import_react14.useEffect)(() => {
|
|
990
|
+
void reload();
|
|
991
|
+
}, [reload]);
|
|
992
|
+
const setReminder = (0, import_react14.useCallback)(async (input) => {
|
|
993
|
+
await r.set(input);
|
|
994
|
+
await reload();
|
|
995
|
+
}, [r, reload]);
|
|
996
|
+
const deleteReminder = (0, import_react14.useCallback)(async (slot) => {
|
|
997
|
+
await r.delete(slot);
|
|
998
|
+
await reload();
|
|
999
|
+
}, [r, reload]);
|
|
1000
|
+
const schedule = (0, import_react14.useCallback)(async (items) => {
|
|
1001
|
+
return r.schedule(items);
|
|
1002
|
+
}, [r]);
|
|
1003
|
+
const setFallbacks = (0, import_react14.useCallback)(async (items) => {
|
|
1004
|
+
return r.setFallbacks(items);
|
|
1005
|
+
}, [r]);
|
|
1006
|
+
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
879
1007
|
}
|
|
880
1008
|
|
|
881
1009
|
// src/hooks/useToast.ts
|
|
882
|
-
var
|
|
1010
|
+
var import_react15 = require("react");
|
|
883
1011
|
function useToast() {
|
|
884
|
-
const [items, setItems] = (0,
|
|
885
|
-
const show = (0,
|
|
1012
|
+
const [items, setItems] = (0, import_react15.useState)([]);
|
|
1013
|
+
const show = (0, import_react15.useCallback)((message, kind = "info") => {
|
|
886
1014
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
887
1015
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
888
1016
|
setTimeout(() => {
|
|
889
1017
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
890
1018
|
}, 4e3);
|
|
891
1019
|
}, []);
|
|
892
|
-
const dismiss = (0,
|
|
1020
|
+
const dismiss = (0, import_react15.useCallback)((id) => {
|
|
893
1021
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
894
1022
|
}, []);
|
|
895
1023
|
return { items, show, dismiss };
|
|
@@ -905,12 +1033,14 @@ function useToast() {
|
|
|
905
1033
|
EmptyState,
|
|
906
1034
|
ErrorBoundary,
|
|
907
1035
|
LoadingState,
|
|
1036
|
+
PushPrompt,
|
|
908
1037
|
useAuth,
|
|
909
1038
|
useAuthPrimitives,
|
|
910
1039
|
useForgotForm,
|
|
911
1040
|
useLoginForm,
|
|
912
1041
|
usePaywallState,
|
|
913
1042
|
usePush,
|
|
1043
|
+
useReminders,
|
|
914
1044
|
useResetForm,
|
|
915
1045
|
useSignupForm,
|
|
916
1046
|
useSubscription,
|