@hook-sdk/template 0.18.1 → 0.20.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 +348 -233
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -11
- package/dist/index.d.ts +78 -11
- package/dist/index.js +224 -121
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -26,8 +36,10 @@ __export(index_exports, {
|
|
|
26
36
|
DeepLinkHandler: () => DeepLinkHandler,
|
|
27
37
|
EmptyState: () => EmptyState,
|
|
28
38
|
ErrorBoundary: () => ErrorBoundary,
|
|
39
|
+
I18nProvider: () => I18nProvider,
|
|
29
40
|
InstallGate: () => InstallGate,
|
|
30
41
|
InstallSplash: () => InstallSplash,
|
|
42
|
+
LanguageSwitcher: () => LanguageSwitcher,
|
|
31
43
|
LoadingState: () => LoadingState,
|
|
32
44
|
OnboardingFlow: () => OnboardingFlow,
|
|
33
45
|
PaymentReturnHandler: () => PaymentReturnHandler,
|
|
@@ -65,14 +77,14 @@ __export(index_exports, {
|
|
|
65
77
|
useSignupForm: () => useSignupForm,
|
|
66
78
|
useSubscription: () => useSubscription,
|
|
67
79
|
useToast: () => useToast,
|
|
68
|
-
useTrackOnboardingStep: () =>
|
|
80
|
+
useTrackOnboardingStep: () => import_sdk21.useTrackOnboardingStep
|
|
69
81
|
});
|
|
70
82
|
module.exports = __toCommonJS(index_exports);
|
|
71
83
|
|
|
72
84
|
// src/AppRoot.tsx
|
|
73
|
-
var
|
|
85
|
+
var import_react14 = require("react");
|
|
74
86
|
var import_react_router_dom2 = require("react-router-dom");
|
|
75
|
-
var
|
|
87
|
+
var import_sdk7 = require("@hook-sdk/sdk");
|
|
76
88
|
|
|
77
89
|
// src/config/AppConfigContext.tsx
|
|
78
90
|
var import_react = require("react");
|
|
@@ -145,6 +157,17 @@ var DeepLinksSchema = import_zod.z.object({
|
|
|
145
157
|
passwordReset: import_zod.z.string().startsWith("/").optional(),
|
|
146
158
|
emailVerify: import_zod.z.string().startsWith("/").optional()
|
|
147
159
|
}).strict();
|
|
160
|
+
var I18nConfigSchema = import_zod.z.object({
|
|
161
|
+
defaultLocale: import_zod.z.string().min(2),
|
|
162
|
+
supportedLocales: import_zod.z.array(import_zod.z.string().min(2)).min(1),
|
|
163
|
+
resources: import_zod.z.record(import_zod.z.string(), import_zod.z.record(import_zod.z.string(), import_zod.z.string()))
|
|
164
|
+
}).strict().refine((v) => v.supportedLocales.includes(v.defaultLocale), {
|
|
165
|
+
message: "i18n.defaultLocale must be a member of i18n.supportedLocales",
|
|
166
|
+
path: ["defaultLocale"]
|
|
167
|
+
});
|
|
168
|
+
var InstallPromptSchema = import_zod.z.object({
|
|
169
|
+
position: import_zod.z.enum(["pre-auth", "post-paywall"]).optional()
|
|
170
|
+
}).strict();
|
|
148
171
|
var AppConfigSchema = import_zod.z.object({
|
|
149
172
|
slug: import_zod.z.string().regex(/^[a-z0-9-]+$/),
|
|
150
173
|
name: import_zod.z.string().min(1),
|
|
@@ -158,12 +181,18 @@ var AppConfigSchema = import_zod.z.object({
|
|
|
158
181
|
persistedKeys: import_zod.z.array(PersistedKeySchema),
|
|
159
182
|
onboarding: OnboardingSchema.optional(),
|
|
160
183
|
deepLinks: DeepLinksSchema.optional(),
|
|
184
|
+
i18n: I18nConfigSchema.optional(),
|
|
161
185
|
features_enabled: import_zod.z.array(import_zod.z.string()).optional(),
|
|
186
|
+
install_prompt: InstallPromptSchema.optional(),
|
|
162
187
|
// Build-time injected theme metadata (e.g. icon_url for InstallSplash).
|
|
163
188
|
// Apps don't author this directly; deploy workflows fill it from
|
|
164
189
|
// env-resolved bundle host. Permissive shape so apps/workflows can
|
|
165
190
|
// extend without re-bumping the template schema.
|
|
166
|
-
theme: import_zod.z.object({}).passthrough().optional()
|
|
191
|
+
theme: import_zod.z.object({}).passthrough().optional(),
|
|
192
|
+
// G133 — per-tenant public app-data keys allowlist. Optional; default
|
|
193
|
+
// backfill em migration 0044 = canonical 6. Apps com keys próprias
|
|
194
|
+
// declaram aqui pra evitar 402 spam pós-signup no SubscriptionGate.
|
|
195
|
+
publicKeys: import_zod.z.array(import_zod.z.string().regex(SnakeKeyRE)).optional()
|
|
167
196
|
}).strict();
|
|
168
197
|
function parseAppConfig(input) {
|
|
169
198
|
const r = AppConfigSchema.safeParse(input);
|
|
@@ -323,7 +352,7 @@ var FALLBACK_PAYWALL = {
|
|
|
323
352
|
};
|
|
324
353
|
var isMethodAvailable = (availability, method) => availability[method] !== false;
|
|
325
354
|
function usePaywallState() {
|
|
326
|
-
const { subscription, plan } = (0, import_sdk3.useHook)();
|
|
355
|
+
const { subscription, plan, authStatus, track: track2 } = (0, import_sdk3.useHook)();
|
|
327
356
|
const configFromCtx = (0, import_react6.useContext)(AppConfigContext);
|
|
328
357
|
const paywall = configFromCtx?.paywall ?? FALLBACK_PAYWALL;
|
|
329
358
|
const isFree = paywall.mode === "free";
|
|
@@ -412,6 +441,21 @@ function usePaywallState() {
|
|
|
412
441
|
[useDefaultMessages]
|
|
413
442
|
);
|
|
414
443
|
const submit = (0, import_react6.useCallback)(async () => {
|
|
444
|
+
if (authStatus === "loading") return void 0;
|
|
445
|
+
if (authStatus !== "authenticated") {
|
|
446
|
+
track2("unauthenticated_submit_attempted", {
|
|
447
|
+
method: selectedMethod,
|
|
448
|
+
cycle,
|
|
449
|
+
cpf_valid: cpfValid
|
|
450
|
+
});
|
|
451
|
+
return void 0;
|
|
452
|
+
}
|
|
453
|
+
track2("payment_attempted", {
|
|
454
|
+
method: selectedMethod,
|
|
455
|
+
cycle,
|
|
456
|
+
cpf_valid: cpfValid,
|
|
457
|
+
selected_amount_cents: cycle === "YEARLY" ? plan.data?.yearlyPriceCents ?? (isFree ? 0 : paywall.prices.yearlyCents) : plan.data?.priceCents ?? (isFree ? 0 : paywall.prices.monthlyCents)
|
|
458
|
+
});
|
|
415
459
|
setSubmitting(true);
|
|
416
460
|
setError(null);
|
|
417
461
|
const methodToUse = selectedMethod;
|
|
@@ -472,7 +516,7 @@ function usePaywallState() {
|
|
|
472
516
|
setSubmitting(false);
|
|
473
517
|
return void 0;
|
|
474
518
|
}
|
|
475
|
-
}, [selectedMethod, availability, subscription, cycle, cpf, card, buildError]);
|
|
519
|
+
}, [authStatus, track2, selectedMethod, availability, subscription, cycle, cpf, cpfValid, card, buildError, plan, paywall]);
|
|
476
520
|
const checkout = (0, import_react6.useCallback)(
|
|
477
521
|
async (args) => {
|
|
478
522
|
setSubmitting(true);
|
|
@@ -1882,9 +1926,9 @@ var bannerStyle = {
|
|
|
1882
1926
|
|
|
1883
1927
|
// src/components/InstallGate/InstallGate.tsx
|
|
1884
1928
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1885
|
-
function InstallGate({ children }) {
|
|
1929
|
+
function InstallGate({ children, position }) {
|
|
1886
1930
|
const { slug, features_enabled } = useTemplateConfig();
|
|
1887
|
-
const enabled = features_enabled.includes("
|
|
1931
|
+
const enabled = features_enabled.includes("pwa-install");
|
|
1888
1932
|
const installState = useInstallPrompt(slug);
|
|
1889
1933
|
const shouldBlock = enabled && shouldBlockInstall(installState);
|
|
1890
1934
|
const trackedRef = (0, import_react9.useRef)(null);
|
|
@@ -1899,9 +1943,10 @@ function InstallGate({ children }) {
|
|
|
1899
1943
|
platform: installState.platform,
|
|
1900
1944
|
browser: installState.iosBrowser ?? installState.androidBrowser ?? null,
|
|
1901
1945
|
in_app_app: installState.inAppApp,
|
|
1902
|
-
variant: installState.variant
|
|
1946
|
+
variant: installState.variant,
|
|
1947
|
+
...position !== void 0 ? { position } : {}
|
|
1903
1948
|
});
|
|
1904
|
-
}, [shouldBlock, slug, installState.variant, installState.platform, installState.iosBrowser, installState.androidBrowser, installState.inAppApp]);
|
|
1949
|
+
}, [shouldBlock, slug, installState.variant, installState.platform, installState.iosBrowser, installState.androidBrowser, installState.inAppApp, position]);
|
|
1905
1950
|
if (!enabled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1906
1951
|
if (installState.isInstalled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1907
1952
|
if (installState.variant === "desktop") {
|
|
@@ -2024,23 +2069,66 @@ var ErrorBoundary = class extends import_react11.Component {
|
|
|
2024
2069
|
}
|
|
2025
2070
|
};
|
|
2026
2071
|
|
|
2027
|
-
// src/
|
|
2072
|
+
// src/i18n/I18nProvider.tsx
|
|
2028
2073
|
var import_react12 = require("react");
|
|
2074
|
+
var import_i18next = __toESM(require("i18next"), 1);
|
|
2075
|
+
var import_react_i18next = require("react-i18next");
|
|
2029
2076
|
var import_sdk5 = require("@hook-sdk/sdk");
|
|
2030
2077
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2078
|
+
function ensureInitialized(defaultLocale, supportedLocales, resources, initialLocale) {
|
|
2079
|
+
if (import_i18next.default.isInitialized) return;
|
|
2080
|
+
import_i18next.default.use(import_react_i18next.initReactI18next).init({
|
|
2081
|
+
resources: Object.fromEntries(
|
|
2082
|
+
supportedLocales.map((l) => [l, { translation: resources[l] ?? {} }])
|
|
2083
|
+
),
|
|
2084
|
+
lng: initialLocale,
|
|
2085
|
+
fallbackLng: defaultLocale,
|
|
2086
|
+
interpolation: { escapeValue: false },
|
|
2087
|
+
// useTranslation suspends by default until i18next is "ready". Inline
|
|
2088
|
+
// resources are sync, so suspending creates a guaranteed empty render
|
|
2089
|
+
// tick — confusing in apps and breaks tests that don't use Suspense.
|
|
2090
|
+
react: { useSuspense: false }
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
function I18nProvider({
|
|
2094
|
+
defaultLocale,
|
|
2095
|
+
supportedLocales,
|
|
2096
|
+
resources,
|
|
2097
|
+
children
|
|
2098
|
+
}) {
|
|
2099
|
+
const [userLocale] = (0, import_sdk5.usePersistedState)("user-locale", defaultLocale);
|
|
2100
|
+
ensureInitialized(defaultLocale, supportedLocales, resources, userLocale);
|
|
2101
|
+
(0, import_react12.useEffect)(() => {
|
|
2102
|
+
if (import_i18next.default.isInitialized && import_i18next.default.language !== userLocale) {
|
|
2103
|
+
import_i18next.default.changeLanguage(userLocale);
|
|
2104
|
+
}
|
|
2105
|
+
}, [userLocale]);
|
|
2106
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_i18next.I18nextProvider, { i18n: import_i18next.default, children });
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
// src/internal/PaymentReturnHandler.tsx
|
|
2110
|
+
var import_react13 = require("react");
|
|
2111
|
+
var import_sdk6 = require("@hook-sdk/sdk");
|
|
2112
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2031
2113
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
2032
2114
|
var MAX_CYCLES = 3;
|
|
2033
2115
|
var SUPPORT_MAILTO = "mailto:suporte@usehook.net?subject=Pagamento%20pendente";
|
|
2034
2116
|
function PaymentReturnHandler({ children }) {
|
|
2035
|
-
const { subscription } = (0,
|
|
2036
|
-
const subRef = (0,
|
|
2117
|
+
const { subscription, track: track2 } = (0, import_sdk6.useHook)();
|
|
2118
|
+
const subRef = (0, import_react13.useRef)(subscription);
|
|
2037
2119
|
subRef.current = subscription;
|
|
2038
|
-
const runIdRef = (0,
|
|
2039
|
-
const cyclesRef = (0,
|
|
2040
|
-
const
|
|
2041
|
-
const
|
|
2120
|
+
const runIdRef = (0, import_react13.useRef)(0);
|
|
2121
|
+
const cyclesRef = (0, import_react13.useRef)(0);
|
|
2122
|
+
const startMsRef = (0, import_react13.useRef)(0);
|
|
2123
|
+
const [state, setState] = (0, import_react13.useState)("idle");
|
|
2124
|
+
const runPoll = (0, import_react13.useCallback)(() => {
|
|
2042
2125
|
const runId = ++runIdRef.current;
|
|
2126
|
+
const isFirstRun = cyclesRef.current === 0;
|
|
2043
2127
|
cyclesRef.current += 1;
|
|
2128
|
+
if (isFirstRun) {
|
|
2129
|
+
startMsRef.current = Date.now();
|
|
2130
|
+
track2("payment_confirmation_started", {});
|
|
2131
|
+
}
|
|
2044
2132
|
setState("confirming");
|
|
2045
2133
|
let attempts = 0;
|
|
2046
2134
|
const tick = async () => {
|
|
@@ -2053,6 +2141,11 @@ function PaymentReturnHandler({ children }) {
|
|
|
2053
2141
|
if (runIdRef.current !== runId) return;
|
|
2054
2142
|
const status = subRef.current.status();
|
|
2055
2143
|
if (status === "active" || status === "trialing") {
|
|
2144
|
+
track2("payment_confirmation_succeeded", {
|
|
2145
|
+
cycle_count: cyclesRef.current,
|
|
2146
|
+
attempt_count: attempts,
|
|
2147
|
+
duration_ms: Date.now() - startMsRef.current
|
|
2148
|
+
});
|
|
2056
2149
|
const cleanUrl = new URL(window.location.href);
|
|
2057
2150
|
cleanUrl.searchParams.delete("paymentReturn");
|
|
2058
2151
|
window.history.replaceState({}, "", cleanUrl.toString());
|
|
@@ -2063,6 +2156,9 @@ function PaymentReturnHandler({ children }) {
|
|
|
2063
2156
|
const delay = BACKOFF_MS[attempts - 1];
|
|
2064
2157
|
if (delay === void 0) {
|
|
2065
2158
|
if (cyclesRef.current >= MAX_CYCLES) {
|
|
2159
|
+
track2("payment_confirmation_timed_out", {
|
|
2160
|
+
total_duration_ms: Date.now() - startMsRef.current
|
|
2161
|
+
});
|
|
2066
2162
|
setState("timeout");
|
|
2067
2163
|
} else {
|
|
2068
2164
|
setState("waiting");
|
|
@@ -2072,8 +2168,8 @@ function PaymentReturnHandler({ children }) {
|
|
|
2072
2168
|
setTimeout(tick, delay);
|
|
2073
2169
|
};
|
|
2074
2170
|
void tick();
|
|
2075
|
-
}, []);
|
|
2076
|
-
(0,
|
|
2171
|
+
}, [track2]);
|
|
2172
|
+
(0, import_react13.useEffect)(() => {
|
|
2077
2173
|
if (typeof window === "undefined") return;
|
|
2078
2174
|
const url = new URL(window.location.href);
|
|
2079
2175
|
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
@@ -2083,26 +2179,26 @@ function PaymentReturnHandler({ children }) {
|
|
|
2083
2179
|
runIdRef.current++;
|
|
2084
2180
|
};
|
|
2085
2181
|
}, [runPoll]);
|
|
2086
|
-
const goHome = (0,
|
|
2182
|
+
const goHome = (0, import_react13.useCallback)(() => {
|
|
2087
2183
|
const cleanUrl = new URL(window.location.href);
|
|
2088
2184
|
cleanUrl.searchParams.delete("paymentReturn");
|
|
2089
2185
|
cleanUrl.pathname = "/app/home";
|
|
2090
2186
|
window.location.href = cleanUrl.toString();
|
|
2091
2187
|
}, []);
|
|
2092
2188
|
if (state === "confirming") {
|
|
2093
|
-
return /* @__PURE__ */ (0,
|
|
2189
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: "Confirmando pagamento\u2026" });
|
|
2094
2190
|
}
|
|
2095
2191
|
if (state === "waiting") {
|
|
2096
|
-
return /* @__PURE__ */ (0,
|
|
2097
|
-
/* @__PURE__ */ (0,
|
|
2098
|
-
/* @__PURE__ */ (0,
|
|
2192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2193
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
|
|
2194
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", onClick: runPoll, style: buttonStyle, children: "Atualizar" })
|
|
2099
2195
|
] }) });
|
|
2100
2196
|
}
|
|
2101
2197
|
if (state === "timeout") {
|
|
2102
|
-
return /* @__PURE__ */ (0,
|
|
2103
|
-
/* @__PURE__ */ (0,
|
|
2104
|
-
/* @__PURE__ */ (0,
|
|
2105
|
-
/* @__PURE__ */ (0,
|
|
2198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "alert", "aria-live": "assertive", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { maxWidth: 360, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { marginBottom: 16 }, children: "Ainda n\xE3o conseguimos confirmar seu pagamento com o banco. Voc\xEA pode tentar de novo, voltar pro app, ou falar com a gente." }),
|
|
2200
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2106
2202
|
"button",
|
|
2107
2203
|
{
|
|
2108
2204
|
type: "button",
|
|
@@ -2115,7 +2211,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2115
2211
|
children: "Tentar de novo"
|
|
2116
2212
|
}
|
|
2117
2213
|
),
|
|
2118
|
-
/* @__PURE__ */ (0,
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2119
2215
|
"button",
|
|
2120
2216
|
{
|
|
2121
2217
|
type: "button",
|
|
@@ -2125,7 +2221,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2125
2221
|
children: "Voltar pro app"
|
|
2126
2222
|
}
|
|
2127
2223
|
),
|
|
2128
|
-
/* @__PURE__ */ (0,
|
|
2224
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2129
2225
|
"a",
|
|
2130
2226
|
{
|
|
2131
2227
|
href: SUPPORT_MAILTO,
|
|
@@ -2137,7 +2233,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
2137
2233
|
] })
|
|
2138
2234
|
] }) });
|
|
2139
2235
|
}
|
|
2140
|
-
return /* @__PURE__ */ (0,
|
|
2236
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_jsx_runtime20.Fragment, { children });
|
|
2141
2237
|
}
|
|
2142
2238
|
var overlayStyle2 = {
|
|
2143
2239
|
position: "fixed",
|
|
@@ -2176,7 +2272,7 @@ var linkStyle = {
|
|
|
2176
2272
|
};
|
|
2177
2273
|
|
|
2178
2274
|
// src/AppRoot.tsx
|
|
2179
|
-
var
|
|
2275
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2180
2276
|
function buildLegacyConfigShim(config) {
|
|
2181
2277
|
const paywall = config.paywall;
|
|
2182
2278
|
const isFree = paywall.mode === "free";
|
|
@@ -2249,32 +2345,47 @@ function AppRoot(props) {
|
|
|
2249
2345
|
"[hook-template] <AppRoot>: PreAuthFlow slot prop is required when config.onboarding.trigger === 'pre_signup_custom'."
|
|
2250
2346
|
);
|
|
2251
2347
|
}
|
|
2252
|
-
const legacyShim = (0,
|
|
2348
|
+
const legacyShim = (0, import_react14.useMemo)(() => buildLegacyConfigShim(config), [config]);
|
|
2253
2349
|
const Router = testRouter === "memory" ? import_react_router_dom2.MemoryRouter : import_react_router_dom2.BrowserRouter;
|
|
2254
2350
|
const basename = `/app/${config.slug}`;
|
|
2255
2351
|
const routerProps = testRouter === "memory" ? { basename, initialEntries: testInitialEntries } : { basename };
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
/* @__PURE__ */ (0,
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2352
|
+
const position = config.install_prompt?.position ?? "post-paywall";
|
|
2353
|
+
const subscriptionGated = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SubscriptionGate, { Paywall: Paywall ?? FallbackPaywall, children: position === "post-paywall" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(InstallGate, { position: "post-paywall", children: [
|
|
2354
|
+
children,
|
|
2355
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PushPrompt, {})
|
|
2356
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
2357
|
+
children,
|
|
2358
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PushPrompt, {})
|
|
2359
|
+
] }) });
|
|
2360
|
+
const authGated = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2361
|
+
AuthGated,
|
|
2362
|
+
{
|
|
2363
|
+
config,
|
|
2364
|
+
Login,
|
|
2365
|
+
Signup,
|
|
2366
|
+
Forgot,
|
|
2367
|
+
Reset,
|
|
2368
|
+
EmailVerify,
|
|
2369
|
+
Paywall,
|
|
2370
|
+
Onboarding,
|
|
2371
|
+
PreAuthFlow,
|
|
2372
|
+
children: subscriptionGated
|
|
2373
|
+
}
|
|
2374
|
+
);
|
|
2375
|
+
const routedTree = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Router, { ...routerProps, children: [
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DeepLinkHandler, { deepLinks: config.deepLinks }),
|
|
2377
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SessionExpiredBanner, {}),
|
|
2378
|
+
position === "pre-auth" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InstallGate, { position: "pre-auth", children: authGated }) : authGated
|
|
2379
|
+
] });
|
|
2380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AppConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TemplateConfigProvider, { config: legacyShim, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PersistenceRegistry, { config: config.persistedKeys, children: config.i18n ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2381
|
+
I18nProvider,
|
|
2382
|
+
{
|
|
2383
|
+
defaultLocale: config.i18n.defaultLocale,
|
|
2384
|
+
supportedLocales: config.i18n.supportedLocales,
|
|
2385
|
+
resources: config.i18n.resources,
|
|
2386
|
+
children: routedTree
|
|
2387
|
+
}
|
|
2388
|
+
) : routedTree }) }) }) }) });
|
|
2278
2389
|
}
|
|
2279
2390
|
function AuthGated({
|
|
2280
2391
|
children,
|
|
@@ -2286,37 +2397,37 @@ function AuthGated({
|
|
|
2286
2397
|
EmailVerify,
|
|
2287
2398
|
PreAuthFlow
|
|
2288
2399
|
}) {
|
|
2289
|
-
const { authStatus } = (0,
|
|
2400
|
+
const { authStatus } = (0, import_sdk7.useHook)();
|
|
2290
2401
|
if (authStatus === "loading") return null;
|
|
2291
2402
|
if (authStatus !== "authenticated") {
|
|
2292
2403
|
if (config.onboarding?.trigger === "pre_signup_custom" && PreAuthFlow) {
|
|
2293
|
-
return /* @__PURE__ */ (0,
|
|
2294
|
-
/* @__PURE__ */ (0,
|
|
2295
|
-
/* @__PURE__ */ (0,
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2297
|
-
/* @__PURE__ */ (0,
|
|
2298
|
-
EmailVerify ? /* @__PURE__ */ (0,
|
|
2299
|
-
/* @__PURE__ */ (0,
|
|
2404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_router_dom2.Routes, { children: [
|
|
2405
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/signin", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Login, {}) }),
|
|
2406
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Signup, {}) }),
|
|
2407
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Forgot, {}) }),
|
|
2408
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Reset, {}) }),
|
|
2409
|
+
EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EmailVerify, {}) }) : null,
|
|
2410
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/*", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PreAuthFlow, {}) })
|
|
2300
2411
|
] });
|
|
2301
2412
|
}
|
|
2302
|
-
return /* @__PURE__ */ (0,
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2304
|
-
/* @__PURE__ */ (0,
|
|
2305
|
-
/* @__PURE__ */ (0,
|
|
2306
|
-
/* @__PURE__ */ (0,
|
|
2307
|
-
EmailVerify ? /* @__PURE__ */ (0,
|
|
2308
|
-
/* @__PURE__ */ (0,
|
|
2413
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react_router_dom2.Routes, { children: [
|
|
2414
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Login, {}) }),
|
|
2415
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/signup", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Signup, {}) }),
|
|
2416
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/forgot", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Forgot, {}) }),
|
|
2417
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/reset", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Reset, {}) }),
|
|
2418
|
+
EmailVerify ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "/verify", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EmailVerify, {}) }) : null,
|
|
2419
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react_router_dom2.Navigate, { to: "/", replace: true }) })
|
|
2309
2420
|
] });
|
|
2310
2421
|
}
|
|
2311
|
-
return /* @__PURE__ */ (0,
|
|
2422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_jsx_runtime21.Fragment, { children });
|
|
2312
2423
|
}
|
|
2313
2424
|
function FallbackPaywall() {
|
|
2314
2425
|
return null;
|
|
2315
2426
|
}
|
|
2316
2427
|
|
|
2317
2428
|
// src/hooks/usePush.ts
|
|
2318
|
-
var
|
|
2319
|
-
var
|
|
2429
|
+
var import_react15 = require("react");
|
|
2430
|
+
var import_sdk8 = require("@hook-sdk/sdk");
|
|
2320
2431
|
var DISMISS_STORAGE_KEY = "push:dismissed-until";
|
|
2321
2432
|
var DISMISS_TTL_MS2 = 7 * 24 * 60 * 60 * 1e3;
|
|
2322
2433
|
function detectIosNeedsInstall() {
|
|
@@ -2360,12 +2471,12 @@ function deriveState(push) {
|
|
|
2360
2471
|
return { kind: "prompt" };
|
|
2361
2472
|
}
|
|
2362
2473
|
function usePush() {
|
|
2363
|
-
const { push } = (0,
|
|
2364
|
-
const [state, setState] = (0,
|
|
2365
|
-
(0,
|
|
2474
|
+
const { push } = (0, import_sdk8.useHook)();
|
|
2475
|
+
const [state, setState] = (0, import_react15.useState)(() => deriveState(push));
|
|
2476
|
+
(0, import_react15.useEffect)(() => {
|
|
2366
2477
|
setState(deriveState(push));
|
|
2367
2478
|
}, [push]);
|
|
2368
|
-
const subscribe = (0,
|
|
2479
|
+
const subscribe = (0, import_react15.useCallback)(async () => {
|
|
2369
2480
|
try {
|
|
2370
2481
|
await push.subscribe();
|
|
2371
2482
|
setState({ kind: "subscribed" });
|
|
@@ -2377,7 +2488,7 @@ function usePush() {
|
|
|
2377
2488
|
throw e;
|
|
2378
2489
|
}
|
|
2379
2490
|
}, [push]);
|
|
2380
|
-
const unsubscribe = (0,
|
|
2491
|
+
const unsubscribe = (0, import_react15.useCallback)(async () => {
|
|
2381
2492
|
try {
|
|
2382
2493
|
await push.unsubscribe();
|
|
2383
2494
|
setState({ kind: "prompt" });
|
|
@@ -2386,7 +2497,7 @@ function usePush() {
|
|
|
2386
2497
|
throw e;
|
|
2387
2498
|
}
|
|
2388
2499
|
}, [push]);
|
|
2389
|
-
const dismiss = (0,
|
|
2500
|
+
const dismiss = (0, import_react15.useCallback)(() => {
|
|
2390
2501
|
if (typeof localStorage !== "undefined") {
|
|
2391
2502
|
try {
|
|
2392
2503
|
localStorage.setItem(DISMISS_STORAGE_KEY, String(Date.now() + DISMISS_TTL_MS2));
|
|
@@ -2399,51 +2510,27 @@ function usePush() {
|
|
|
2399
2510
|
}
|
|
2400
2511
|
|
|
2401
2512
|
// src/components/PushPrompt.tsx
|
|
2402
|
-
var
|
|
2403
|
-
function platformRecoveryCopy(texts) {
|
|
2404
|
-
if (typeof navigator === "undefined") return null;
|
|
2405
|
-
const ua = navigator.userAgent || "";
|
|
2406
|
-
const platform = detectPlatform(ua);
|
|
2407
|
-
switch (platform) {
|
|
2408
|
-
case "ios-safari":
|
|
2409
|
-
case "ios-other":
|
|
2410
|
-
return texts.deniedRecoveryIos ?? null;
|
|
2411
|
-
case "android":
|
|
2412
|
-
return texts.deniedRecoveryAndroid ?? null;
|
|
2413
|
-
case "desktop":
|
|
2414
|
-
return texts.deniedRecoveryDesktop ?? null;
|
|
2415
|
-
case "in-app":
|
|
2416
|
-
return texts.deniedRecoveryInApp ?? null;
|
|
2417
|
-
default:
|
|
2418
|
-
return null;
|
|
2419
|
-
}
|
|
2420
|
-
}
|
|
2513
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2421
2514
|
function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
|
|
2422
2515
|
const { state, subscribe } = usePush();
|
|
2423
|
-
if (state.kind === "
|
|
2424
|
-
|
|
2425
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
2426
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { children: texts.iosInstallTitle }),
|
|
2427
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { children: texts.iosInstallBody }),
|
|
2428
|
-
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
2429
|
-
] });
|
|
2516
|
+
if (state.kind === "denied" || state.kind === "dismissed" || state.kind === "subscribed") {
|
|
2517
|
+
return null;
|
|
2430
2518
|
}
|
|
2431
|
-
if (state.kind === "
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
/* @__PURE__ */ (0,
|
|
2435
|
-
/* @__PURE__ */ (0,
|
|
2436
|
-
recovery && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { "data-testid": "denied-recovery", children: recovery })
|
|
2519
|
+
if (state.kind === "ios_needs_install") {
|
|
2520
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
2521
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { children: texts.iosInstallTitle }),
|
|
2522
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { children: texts.iosInstallBody }),
|
|
2523
|
+
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
2437
2524
|
] });
|
|
2438
2525
|
}
|
|
2439
2526
|
if (state.kind === "unsupported") {
|
|
2440
|
-
return /* @__PURE__ */ (0,
|
|
2527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { children: texts.unsupportedBody }) });
|
|
2441
2528
|
}
|
|
2442
2529
|
if (state.kind === "error") {
|
|
2443
|
-
return /* @__PURE__ */ (0,
|
|
2530
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { children: state.message }) });
|
|
2444
2531
|
}
|
|
2445
|
-
return /* @__PURE__ */ (0,
|
|
2446
|
-
/* @__PURE__ */ (0,
|
|
2532
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className, role: "region", children: [
|
|
2533
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2447
2534
|
"button",
|
|
2448
2535
|
{
|
|
2449
2536
|
type: "button",
|
|
@@ -2457,41 +2544,67 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
|
|
|
2457
2544
|
children: texts.cta
|
|
2458
2545
|
}
|
|
2459
2546
|
),
|
|
2460
|
-
onDeclined && /* @__PURE__ */ (0,
|
|
2547
|
+
onDeclined && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
|
|
2548
|
+
] });
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
// src/components/LanguageSwitcher.tsx
|
|
2552
|
+
var import_sdk9 = require("@hook-sdk/sdk");
|
|
2553
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2554
|
+
function LanguageSwitcher({ id, className, label = "Language" }) {
|
|
2555
|
+
const config = useAppConfig();
|
|
2556
|
+
const i18nConfig = config.i18n;
|
|
2557
|
+
const [userLocale, setUserLocale] = (0, import_sdk9.usePersistedState)(
|
|
2558
|
+
"user-locale",
|
|
2559
|
+
i18nConfig?.defaultLocale ?? "en-US"
|
|
2560
|
+
);
|
|
2561
|
+
if (!i18nConfig) return null;
|
|
2562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className, children: [
|
|
2563
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: label }) : null,
|
|
2564
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2565
|
+
"select",
|
|
2566
|
+
{
|
|
2567
|
+
id,
|
|
2568
|
+
value: userLocale,
|
|
2569
|
+
onChange: (e) => setUserLocale(e.target.value),
|
|
2570
|
+
"data-testid": "language-switcher",
|
|
2571
|
+
children: i18nConfig.supportedLocales.map((loc) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: loc, children: loc }, loc))
|
|
2572
|
+
}
|
|
2573
|
+
)
|
|
2461
2574
|
] });
|
|
2462
2575
|
}
|
|
2463
2576
|
|
|
2464
2577
|
// src/defaults/LoadingState.tsx
|
|
2465
|
-
var
|
|
2578
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2466
2579
|
function LoadingState({ message }) {
|
|
2467
|
-
return /* @__PURE__ */ (0,
|
|
2580
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "status", "aria-live": "polite", style: { padding: 24, textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: message ?? "Carregando..." }) });
|
|
2468
2581
|
}
|
|
2469
2582
|
|
|
2470
2583
|
// src/defaults/EmptyState.tsx
|
|
2471
|
-
var
|
|
2584
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2472
2585
|
function EmptyState({ title, description, action }) {
|
|
2473
|
-
return /* @__PURE__ */ (0,
|
|
2474
|
-
/* @__PURE__ */ (0,
|
|
2475
|
-
description && /* @__PURE__ */ (0,
|
|
2476
|
-
action && /* @__PURE__ */ (0,
|
|
2586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
|
|
2588
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { style: { opacity: 0.7 }, children: description }),
|
|
2589
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { marginTop: 16 }, children: action })
|
|
2477
2590
|
] });
|
|
2478
2591
|
}
|
|
2479
2592
|
|
|
2480
2593
|
// src/hooks/useLoginForm.ts
|
|
2481
|
-
var
|
|
2482
|
-
var
|
|
2594
|
+
var import_react16 = require("react");
|
|
2595
|
+
var import_sdk11 = require("@hook-sdk/sdk");
|
|
2483
2596
|
|
|
2484
2597
|
// src/errors.ts
|
|
2485
|
-
var
|
|
2598
|
+
var import_sdk10 = require("@hook-sdk/sdk");
|
|
2486
2599
|
function mapSdkError(err) {
|
|
2487
|
-
if (err instanceof
|
|
2600
|
+
if (err instanceof import_sdk10.SdkRateLimitError) {
|
|
2488
2601
|
return {
|
|
2489
2602
|
code: "rate_limited",
|
|
2490
2603
|
message: `Aguarde ${err.retryAfter}s e tente novamente.`,
|
|
2491
2604
|
retryAfter: err.retryAfter
|
|
2492
2605
|
};
|
|
2493
2606
|
}
|
|
2494
|
-
if (err instanceof
|
|
2607
|
+
if (err instanceof import_sdk10.SdkAuthError) {
|
|
2495
2608
|
const detail = err.detail;
|
|
2496
2609
|
if (detail === "email_unverified") {
|
|
2497
2610
|
return { code: "email_unverified", message: "Confirme seu e-mail antes de entrar." };
|
|
@@ -2501,7 +2614,7 @@ function mapSdkError(err) {
|
|
|
2501
2614
|
}
|
|
2502
2615
|
return { code: "invalid_credentials", message: "E-mail ou senha inv\xE1lidos." };
|
|
2503
2616
|
}
|
|
2504
|
-
if (err instanceof
|
|
2617
|
+
if (err instanceof import_sdk10.SdkError && err.httpStatus === 0) {
|
|
2505
2618
|
return { code: "network", message: "Sem conex\xE3o com o servidor. Verifique sua internet." };
|
|
2506
2619
|
}
|
|
2507
2620
|
if (err instanceof TypeError) {
|
|
@@ -2514,20 +2627,20 @@ function mapSdkError(err) {
|
|
|
2514
2627
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2515
2628
|
var MIN_PASSWORD = 8;
|
|
2516
2629
|
function useLoginForm() {
|
|
2517
|
-
const { auth } = (0,
|
|
2518
|
-
const [email, setEmail] = (0,
|
|
2519
|
-
const [password, setPassword] = (0,
|
|
2520
|
-
const [submitting, setSubmitting] = (0,
|
|
2521
|
-
const [error, setError] = (0,
|
|
2522
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2523
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2524
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2525
|
-
const validateEmail = (0,
|
|
2630
|
+
const { auth } = (0, import_sdk11.useHook)();
|
|
2631
|
+
const [email, setEmail] = (0, import_react16.useState)("");
|
|
2632
|
+
const [password, setPassword] = (0, import_react16.useState)("");
|
|
2633
|
+
const [submitting, setSubmitting] = (0, import_react16.useState)(false);
|
|
2634
|
+
const [error, setError] = (0, import_react16.useState)(null);
|
|
2635
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react16.useState)(false);
|
|
2636
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react16.useState)(false);
|
|
2637
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react16.useState)(false);
|
|
2638
|
+
const validateEmail = (0, import_react16.useMemo)(() => {
|
|
2526
2639
|
if (email.length === 0) return null;
|
|
2527
2640
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2528
2641
|
return null;
|
|
2529
2642
|
}, [email]);
|
|
2530
|
-
const validatePassword = (0,
|
|
2643
|
+
const validatePassword = (0, import_react16.useMemo)(() => {
|
|
2531
2644
|
if (password.length === 0) return null;
|
|
2532
2645
|
if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
|
|
2533
2646
|
return null;
|
|
@@ -2535,7 +2648,7 @@ function useLoginForm() {
|
|
|
2535
2648
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2536
2649
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2537
2650
|
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && validateEmail === null && validatePassword === null && !submitting;
|
|
2538
|
-
const submit = (0,
|
|
2651
|
+
const submit = (0, import_react16.useCallback)(async () => {
|
|
2539
2652
|
setFormSubmitAttempted(true);
|
|
2540
2653
|
if (!canSubmit) return false;
|
|
2541
2654
|
setSubmitting(true);
|
|
@@ -2569,32 +2682,32 @@ function useLoginForm() {
|
|
|
2569
2682
|
}
|
|
2570
2683
|
|
|
2571
2684
|
// src/hooks/useSignupForm.ts
|
|
2572
|
-
var
|
|
2573
|
-
var
|
|
2685
|
+
var import_react17 = require("react");
|
|
2686
|
+
var import_sdk12 = require("@hook-sdk/sdk");
|
|
2574
2687
|
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2575
2688
|
var MIN_PASSWORD2 = 8;
|
|
2576
2689
|
function useSignupForm() {
|
|
2577
|
-
const { auth } = (0,
|
|
2578
|
-
const [name, setName] = (0,
|
|
2579
|
-
const [email, setEmail] = (0,
|
|
2580
|
-
const [password, setPassword] = (0,
|
|
2581
|
-
const [submitting, setSubmitting] = (0,
|
|
2582
|
-
const [error, setError] = (0,
|
|
2583
|
-
const [touchedName, setTouchedName] = (0,
|
|
2584
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2585
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2586
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2587
|
-
const validateName = (0,
|
|
2690
|
+
const { auth } = (0, import_sdk12.useHook)();
|
|
2691
|
+
const [name, setName] = (0, import_react17.useState)("");
|
|
2692
|
+
const [email, setEmail] = (0, import_react17.useState)("");
|
|
2693
|
+
const [password, setPassword] = (0, import_react17.useState)("");
|
|
2694
|
+
const [submitting, setSubmitting] = (0, import_react17.useState)(false);
|
|
2695
|
+
const [error, setError] = (0, import_react17.useState)(null);
|
|
2696
|
+
const [touchedName, setTouchedName] = (0, import_react17.useState)(false);
|
|
2697
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react17.useState)(false);
|
|
2698
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react17.useState)(false);
|
|
2699
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react17.useState)(false);
|
|
2700
|
+
const validateName = (0, import_react17.useMemo)(() => {
|
|
2588
2701
|
if (name.length === 0) return null;
|
|
2589
2702
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
2590
2703
|
return null;
|
|
2591
2704
|
}, [name]);
|
|
2592
|
-
const validateEmail = (0,
|
|
2705
|
+
const validateEmail = (0, import_react17.useMemo)(() => {
|
|
2593
2706
|
if (email.length === 0) return null;
|
|
2594
2707
|
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2595
2708
|
return null;
|
|
2596
2709
|
}, [email]);
|
|
2597
|
-
const validatePassword = (0,
|
|
2710
|
+
const validatePassword = (0, import_react17.useMemo)(() => {
|
|
2598
2711
|
if (password.length === 0) return null;
|
|
2599
2712
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
2600
2713
|
return null;
|
|
@@ -2603,7 +2716,7 @@ function useSignupForm() {
|
|
|
2603
2716
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2604
2717
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2605
2718
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && validateName === null && validateEmail === null && validatePassword === null && !submitting;
|
|
2606
|
-
const submit = (0,
|
|
2719
|
+
const submit = (0, import_react17.useCallback)(async () => {
|
|
2607
2720
|
setFormSubmitAttempted(true);
|
|
2608
2721
|
if (!canSubmit) return false;
|
|
2609
2722
|
setSubmitting(true);
|
|
@@ -2641,25 +2754,25 @@ function useSignupForm() {
|
|
|
2641
2754
|
}
|
|
2642
2755
|
|
|
2643
2756
|
// src/hooks/useForgotForm.ts
|
|
2644
|
-
var
|
|
2645
|
-
var
|
|
2757
|
+
var import_react18 = require("react");
|
|
2758
|
+
var import_sdk13 = require("@hook-sdk/sdk");
|
|
2646
2759
|
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2647
2760
|
function useForgotForm() {
|
|
2648
|
-
const { auth } = (0,
|
|
2649
|
-
const [email, setEmail] = (0,
|
|
2650
|
-
const [submitting, setSubmitting] = (0,
|
|
2651
|
-
const [sent, setSent] = (0,
|
|
2652
|
-
const [error, setError] = (0,
|
|
2653
|
-
const [touchedEmail, setTouchedEmail] = (0,
|
|
2654
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2655
|
-
const validateEmail = (0,
|
|
2761
|
+
const { auth } = (0, import_sdk13.useHook)();
|
|
2762
|
+
const [email, setEmail] = (0, import_react18.useState)("");
|
|
2763
|
+
const [submitting, setSubmitting] = (0, import_react18.useState)(false);
|
|
2764
|
+
const [sent, setSent] = (0, import_react18.useState)(false);
|
|
2765
|
+
const [error, setError] = (0, import_react18.useState)(null);
|
|
2766
|
+
const [touchedEmail, setTouchedEmail] = (0, import_react18.useState)(false);
|
|
2767
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react18.useState)(false);
|
|
2768
|
+
const validateEmail = (0, import_react18.useMemo)(() => {
|
|
2656
2769
|
if (email.length === 0) return null;
|
|
2657
2770
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
2658
2771
|
return null;
|
|
2659
2772
|
}, [email]);
|
|
2660
2773
|
const emailError = touchedEmail || formSubmitAttempted ? validateEmail : null;
|
|
2661
2774
|
const canSubmit = email.length > 0 && validateEmail === null && !submitting;
|
|
2662
|
-
const submit = (0,
|
|
2775
|
+
const submit = (0, import_react18.useCallback)(async () => {
|
|
2663
2776
|
setFormSubmitAttempted(true);
|
|
2664
2777
|
if (!canSubmit) return false;
|
|
2665
2778
|
setSubmitting(true);
|
|
@@ -2690,32 +2803,32 @@ function useForgotForm() {
|
|
|
2690
2803
|
}
|
|
2691
2804
|
|
|
2692
2805
|
// src/hooks/useResetForm.ts
|
|
2693
|
-
var
|
|
2694
|
-
var
|
|
2806
|
+
var import_react19 = require("react");
|
|
2807
|
+
var import_sdk14 = require("@hook-sdk/sdk");
|
|
2695
2808
|
var MIN_PASSWORD3 = 12;
|
|
2696
2809
|
function useResetForm() {
|
|
2697
|
-
const { auth } = (0,
|
|
2698
|
-
const [token, setToken] = (0,
|
|
2699
|
-
const [password, setPassword] = (0,
|
|
2700
|
-
const [confirm, setConfirm] = (0,
|
|
2701
|
-
const [submitting, setSubmitting] = (0,
|
|
2702
|
-
const [done, setDone] = (0,
|
|
2703
|
-
const [error, setError] = (0,
|
|
2704
|
-
const [touchedPassword, setTouchedPassword] = (0,
|
|
2705
|
-
const [touchedConfirm, setTouchedConfirm] = (0,
|
|
2706
|
-
const [formSubmitAttempted, setFormSubmitAttempted] = (0,
|
|
2707
|
-
(0,
|
|
2810
|
+
const { auth } = (0, import_sdk14.useHook)();
|
|
2811
|
+
const [token, setToken] = (0, import_react19.useState)(null);
|
|
2812
|
+
const [password, setPassword] = (0, import_react19.useState)("");
|
|
2813
|
+
const [confirm, setConfirm] = (0, import_react19.useState)("");
|
|
2814
|
+
const [submitting, setSubmitting] = (0, import_react19.useState)(false);
|
|
2815
|
+
const [done, setDone] = (0, import_react19.useState)(false);
|
|
2816
|
+
const [error, setError] = (0, import_react19.useState)(null);
|
|
2817
|
+
const [touchedPassword, setTouchedPassword] = (0, import_react19.useState)(false);
|
|
2818
|
+
const [touchedConfirm, setTouchedConfirm] = (0, import_react19.useState)(false);
|
|
2819
|
+
const [formSubmitAttempted, setFormSubmitAttempted] = (0, import_react19.useState)(false);
|
|
2820
|
+
(0, import_react19.useEffect)(() => {
|
|
2708
2821
|
if (typeof window === "undefined") return;
|
|
2709
2822
|
const params = new URLSearchParams(window.location.search);
|
|
2710
2823
|
const t = params.get("token");
|
|
2711
2824
|
setToken(t && t.length > 0 ? t : null);
|
|
2712
2825
|
}, []);
|
|
2713
|
-
const validatePassword = (0,
|
|
2826
|
+
const validatePassword = (0, import_react19.useMemo)(() => {
|
|
2714
2827
|
if (password.length === 0) return null;
|
|
2715
2828
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
2716
2829
|
return null;
|
|
2717
2830
|
}, [password]);
|
|
2718
|
-
const validateConfirm = (0,
|
|
2831
|
+
const validateConfirm = (0, import_react19.useMemo)(() => {
|
|
2719
2832
|
if (confirm.length === 0) return null;
|
|
2720
2833
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
2721
2834
|
return null;
|
|
@@ -2723,7 +2836,7 @@ function useResetForm() {
|
|
|
2723
2836
|
const passwordError = touchedPassword || formSubmitAttempted ? validatePassword : null;
|
|
2724
2837
|
const confirmError = touchedConfirm || formSubmitAttempted ? validateConfirm : null;
|
|
2725
2838
|
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && validatePassword === null && validateConfirm === null && !submitting && !done;
|
|
2726
|
-
const submit = (0,
|
|
2839
|
+
const submit = (0, import_react19.useCallback)(async () => {
|
|
2727
2840
|
setFormSubmitAttempted(true);
|
|
2728
2841
|
if (!canSubmit || token === null) return;
|
|
2729
2842
|
setSubmitting(true);
|
|
@@ -2763,9 +2876,9 @@ function useResetForm() {
|
|
|
2763
2876
|
}
|
|
2764
2877
|
|
|
2765
2878
|
// src/hooks/usePlan.ts
|
|
2766
|
-
var
|
|
2879
|
+
var import_sdk15 = require("@hook-sdk/sdk");
|
|
2767
2880
|
function usePlan() {
|
|
2768
|
-
const { plan } = (0,
|
|
2881
|
+
const { plan } = (0, import_sdk15.useHook)();
|
|
2769
2882
|
return plan;
|
|
2770
2883
|
}
|
|
2771
2884
|
|
|
@@ -2798,12 +2911,12 @@ function discountPercent(anchorCents, realCents) {
|
|
|
2798
2911
|
}
|
|
2799
2912
|
|
|
2800
2913
|
// src/hooks/useAuthPrimitives.ts
|
|
2801
|
-
var
|
|
2802
|
-
var
|
|
2914
|
+
var import_react20 = require("react");
|
|
2915
|
+
var import_sdk16 = require("@hook-sdk/sdk");
|
|
2803
2916
|
var warned = false;
|
|
2804
2917
|
function useAuthPrimitives() {
|
|
2805
|
-
const { auth } = (0,
|
|
2806
|
-
(0,
|
|
2918
|
+
const { auth } = (0, import_sdk16.useHook)();
|
|
2919
|
+
(0, import_react20.useEffect)(() => {
|
|
2807
2920
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
2808
2921
|
warned = true;
|
|
2809
2922
|
console.warn(
|
|
@@ -2825,9 +2938,9 @@ function useAuthPrimitives() {
|
|
|
2825
2938
|
}
|
|
2826
2939
|
|
|
2827
2940
|
// src/hooks/useAuth.ts
|
|
2828
|
-
var
|
|
2941
|
+
var import_sdk17 = require("@hook-sdk/sdk");
|
|
2829
2942
|
function useAuth() {
|
|
2830
|
-
const { user, authStatus, auth } = (0,
|
|
2943
|
+
const { user, authStatus, auth } = (0, import_sdk17.useHook)();
|
|
2831
2944
|
return {
|
|
2832
2945
|
user,
|
|
2833
2946
|
authStatus,
|
|
@@ -2836,26 +2949,26 @@ function useAuth() {
|
|
|
2836
2949
|
}
|
|
2837
2950
|
|
|
2838
2951
|
// src/index.ts
|
|
2839
|
-
var
|
|
2952
|
+
var import_sdk21 = require("@hook-sdk/sdk");
|
|
2840
2953
|
|
|
2841
2954
|
// src/hooks/useSubscription.ts
|
|
2842
|
-
var
|
|
2955
|
+
var import_sdk18 = require("@hook-sdk/sdk");
|
|
2843
2956
|
function useSubscription() {
|
|
2844
|
-
const { subscription } = (0,
|
|
2957
|
+
const { subscription } = (0, import_sdk18.useHook)();
|
|
2845
2958
|
return {
|
|
2846
2959
|
status: subscription.status()
|
|
2847
2960
|
};
|
|
2848
2961
|
}
|
|
2849
2962
|
|
|
2850
2963
|
// src/hooks/useReminders.ts
|
|
2851
|
-
var
|
|
2852
|
-
var
|
|
2964
|
+
var import_react21 = require("react");
|
|
2965
|
+
var import_sdk19 = require("@hook-sdk/sdk");
|
|
2853
2966
|
function useReminders() {
|
|
2854
|
-
const { push } = (0,
|
|
2967
|
+
const { push } = (0, import_sdk19.useHook)();
|
|
2855
2968
|
const r = push.reminders;
|
|
2856
|
-
const [reminders, setReminders] = (0,
|
|
2857
|
-
const [loading, setLoading] = (0,
|
|
2858
|
-
const reload = (0,
|
|
2969
|
+
const [reminders, setReminders] = (0, import_react21.useState)([]);
|
|
2970
|
+
const [loading, setLoading] = (0, import_react21.useState)(true);
|
|
2971
|
+
const reload = (0, import_react21.useCallback)(async () => {
|
|
2859
2972
|
setLoading(true);
|
|
2860
2973
|
try {
|
|
2861
2974
|
const next = await r.list();
|
|
@@ -2864,38 +2977,38 @@ function useReminders() {
|
|
|
2864
2977
|
setLoading(false);
|
|
2865
2978
|
}
|
|
2866
2979
|
}, [r]);
|
|
2867
|
-
(0,
|
|
2980
|
+
(0, import_react21.useEffect)(() => {
|
|
2868
2981
|
void reload();
|
|
2869
2982
|
}, [reload]);
|
|
2870
|
-
const setReminder = (0,
|
|
2983
|
+
const setReminder = (0, import_react21.useCallback)(async (input) => {
|
|
2871
2984
|
await r.set(input);
|
|
2872
2985
|
await reload();
|
|
2873
2986
|
}, [r, reload]);
|
|
2874
|
-
const deleteReminder = (0,
|
|
2987
|
+
const deleteReminder = (0, import_react21.useCallback)(async (slot) => {
|
|
2875
2988
|
await r.delete(slot);
|
|
2876
2989
|
await reload();
|
|
2877
2990
|
}, [r, reload]);
|
|
2878
|
-
const schedule = (0,
|
|
2991
|
+
const schedule = (0, import_react21.useCallback)(async (items) => {
|
|
2879
2992
|
return r.schedule(items);
|
|
2880
2993
|
}, [r]);
|
|
2881
|
-
const setFallbacks = (0,
|
|
2994
|
+
const setFallbacks = (0, import_react21.useCallback)(async (items) => {
|
|
2882
2995
|
return r.setFallbacks(items);
|
|
2883
2996
|
}, [r]);
|
|
2884
2997
|
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
2885
2998
|
}
|
|
2886
2999
|
|
|
2887
3000
|
// src/hooks/useToast.ts
|
|
2888
|
-
var
|
|
3001
|
+
var import_react22 = require("react");
|
|
2889
3002
|
function useToast() {
|
|
2890
|
-
const [items, setItems] = (0,
|
|
2891
|
-
const show = (0,
|
|
3003
|
+
const [items, setItems] = (0, import_react22.useState)([]);
|
|
3004
|
+
const show = (0, import_react22.useCallback)((message, kind = "info") => {
|
|
2892
3005
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
2893
3006
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
2894
3007
|
setTimeout(() => {
|
|
2895
3008
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
2896
3009
|
}, 4e3);
|
|
2897
3010
|
}, []);
|
|
2898
|
-
const dismiss = (0,
|
|
3011
|
+
const dismiss = (0, import_react22.useCallback)((id) => {
|
|
2899
3012
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
2900
3013
|
}, []);
|
|
2901
3014
|
return { items, show, dismiss };
|
|
@@ -2903,20 +3016,20 @@ function useToast() {
|
|
|
2903
3016
|
|
|
2904
3017
|
// src/RouteBoundary.tsx
|
|
2905
3018
|
var import_react_router_dom3 = require("react-router-dom");
|
|
2906
|
-
var
|
|
3019
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2907
3020
|
function RouteBoundary({ children }) {
|
|
2908
|
-
return /* @__PURE__ */ (0,
|
|
3021
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_react_router_dom3.Routes, { children: [
|
|
2909
3022
|
children,
|
|
2910
|
-
/* @__PURE__ */ (0,
|
|
3023
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react_router_dom3.Route, { path: "*", element: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DefaultNotFound, {}) })
|
|
2911
3024
|
] });
|
|
2912
3025
|
}
|
|
2913
3026
|
function DefaultNotFound() {
|
|
2914
|
-
return /* @__PURE__ */ (0,
|
|
3027
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { role: "alert", children: "P\xE1gina n\xE3o encontrada" });
|
|
2915
3028
|
}
|
|
2916
3029
|
|
|
2917
3030
|
// src/PreAuthShell.tsx
|
|
2918
3031
|
var import_react_router_dom4 = require("react-router-dom");
|
|
2919
|
-
var
|
|
3032
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2920
3033
|
function PreAuthShell({
|
|
2921
3034
|
basename,
|
|
2922
3035
|
testRouter,
|
|
@@ -2924,20 +3037,20 @@ function PreAuthShell({
|
|
|
2924
3037
|
children
|
|
2925
3038
|
}) {
|
|
2926
3039
|
if (testRouter === "memory") {
|
|
2927
|
-
return /* @__PURE__ */ (0,
|
|
3040
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom4.MemoryRouter, { basename, initialEntries: testInitialEntries, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom4.Routes, { children }) });
|
|
2928
3041
|
}
|
|
2929
|
-
return /* @__PURE__ */ (0,
|
|
3042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom4.BrowserRouter, { basename, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react_router_dom4.Routes, { children }) });
|
|
2930
3043
|
}
|
|
2931
3044
|
|
|
2932
3045
|
// src/OnboardingFlow.tsx
|
|
2933
|
-
var
|
|
2934
|
-
var
|
|
3046
|
+
var import_react24 = require("react");
|
|
3047
|
+
var import_sdk20 = require("@hook-sdk/sdk");
|
|
2935
3048
|
|
|
2936
3049
|
// src/hooks/useOnboardingStep.ts
|
|
2937
|
-
var
|
|
2938
|
-
var OnboardingStepContext = (0,
|
|
3050
|
+
var import_react23 = require("react");
|
|
3051
|
+
var OnboardingStepContext = (0, import_react23.createContext)(null);
|
|
2939
3052
|
function useOnboardingStep() {
|
|
2940
|
-
const ctx = (0,
|
|
3053
|
+
const ctx = (0, import_react23.useContext)(OnboardingStepContext);
|
|
2941
3054
|
if (!ctx) {
|
|
2942
3055
|
throw new Error(
|
|
2943
3056
|
"[hook-template] useOnboardingStep must be used inside <OnboardingFlow>. (G75)"
|
|
@@ -2947,7 +3060,7 @@ function useOnboardingStep() {
|
|
|
2947
3060
|
}
|
|
2948
3061
|
|
|
2949
3062
|
// src/OnboardingFlow.tsx
|
|
2950
|
-
var
|
|
3063
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
2951
3064
|
var isFilled = (v) => v != null && v !== "";
|
|
2952
3065
|
var CURRENT_STEP_FIELD = "currentStep";
|
|
2953
3066
|
function readPersistedStepIdx(draft) {
|
|
@@ -2960,12 +3073,12 @@ function OnboardingFlow({
|
|
|
2960
3073
|
onComplete,
|
|
2961
3074
|
persistKey
|
|
2962
3075
|
}) {
|
|
2963
|
-
const [draft, setDraft, status] = (0,
|
|
2964
|
-
const draftRef = (0,
|
|
3076
|
+
const [draft, setDraft, status] = (0, import_sdk20.usePersistedState)(persistKey, {});
|
|
3077
|
+
const draftRef = (0, import_react24.useRef)(draft);
|
|
2965
3078
|
draftRef.current = draft;
|
|
2966
3079
|
const idx = readPersistedStepIdx(draft);
|
|
2967
3080
|
const clampedIdx = Math.min(Math.max(idx, 0), Math.max(steps.length - 1, 0));
|
|
2968
|
-
const setIdx = (0,
|
|
3081
|
+
const setIdx = (0, import_react24.useCallback)(
|
|
2969
3082
|
(n) => {
|
|
2970
3083
|
setDraft((prev) => {
|
|
2971
3084
|
const prevIdx = readPersistedStepIdx(prev);
|
|
@@ -2975,7 +3088,7 @@ function OnboardingFlow({
|
|
|
2975
3088
|
},
|
|
2976
3089
|
[setDraft]
|
|
2977
3090
|
);
|
|
2978
|
-
const setValue = (0,
|
|
3091
|
+
const setValue = (0, import_react24.useCallback)(
|
|
2979
3092
|
(patch) => {
|
|
2980
3093
|
draftRef.current = { ...draftRef.current, ...patch };
|
|
2981
3094
|
setDraft((prev) => ({ ...prev, ...patch }));
|
|
@@ -2983,9 +3096,9 @@ function OnboardingFlow({
|
|
|
2983
3096
|
[setDraft]
|
|
2984
3097
|
);
|
|
2985
3098
|
const step = steps[clampedIdx];
|
|
2986
|
-
const hookCtx = (0,
|
|
3099
|
+
const hookCtx = (0, import_sdk20.useHook)();
|
|
2987
3100
|
const track2 = typeof hookCtx.track === "function" ? hookCtx.track : void 0;
|
|
2988
|
-
(0,
|
|
3101
|
+
(0, import_react24.useEffect)(() => {
|
|
2989
3102
|
if (status.loading) return;
|
|
2990
3103
|
if (!step) return;
|
|
2991
3104
|
if (!track2) return;
|
|
@@ -2995,11 +3108,11 @@ function OnboardingFlow({
|
|
|
2995
3108
|
total_steps: steps.length
|
|
2996
3109
|
});
|
|
2997
3110
|
}, [step?.id, clampedIdx, steps.length, status.loading, track2]);
|
|
2998
|
-
const valid = (0,
|
|
3111
|
+
const valid = (0, import_react24.useMemo)(
|
|
2999
3112
|
() => step ? (step.validates ?? []).every((field) => isFilled(draft[field])) : false,
|
|
3000
3113
|
[draft, step]
|
|
3001
3114
|
);
|
|
3002
|
-
const next = (0,
|
|
3115
|
+
const next = (0, import_react24.useCallback)(() => {
|
|
3003
3116
|
if (!step) return;
|
|
3004
3117
|
const current = draftRef.current;
|
|
3005
3118
|
const validNow = (step.validates ?? []).every((field) => isFilled(current[field]));
|
|
@@ -3010,8 +3123,8 @@ function OnboardingFlow({
|
|
|
3010
3123
|
setIdx(clampedIdx + 1);
|
|
3011
3124
|
}
|
|
3012
3125
|
}, [clampedIdx, onComplete, step, steps.length, setIdx]);
|
|
3013
|
-
const prevStep = (0,
|
|
3014
|
-
const ctx = (0,
|
|
3126
|
+
const prevStep = (0, import_react24.useCallback)(() => setIdx((i) => Math.max(0, i - 1)), [setIdx]);
|
|
3127
|
+
const ctx = (0, import_react24.useMemo)(
|
|
3015
3128
|
() => ({
|
|
3016
3129
|
stepIndex: clampedIdx,
|
|
3017
3130
|
totalSteps: steps.length,
|
|
@@ -3037,7 +3150,7 @@ function OnboardingFlow({
|
|
|
3037
3150
|
`[hook-template] OnboardingFlow: missing screen component for step '${step.id}' (expected key '${step.screen}' in screens prop)`
|
|
3038
3151
|
);
|
|
3039
3152
|
}
|
|
3040
|
-
return /* @__PURE__ */ (0,
|
|
3153
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(OnboardingStepContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Screen, {}) });
|
|
3041
3154
|
}
|
|
3042
3155
|
|
|
3043
3156
|
// src/hooks/useFeature.ts
|
|
@@ -3053,8 +3166,10 @@ function useFeature(name) {
|
|
|
3053
3166
|
DeepLinkHandler,
|
|
3054
3167
|
EmptyState,
|
|
3055
3168
|
ErrorBoundary,
|
|
3169
|
+
I18nProvider,
|
|
3056
3170
|
InstallGate,
|
|
3057
3171
|
InstallSplash,
|
|
3172
|
+
LanguageSwitcher,
|
|
3058
3173
|
LoadingState,
|
|
3059
3174
|
OnboardingFlow,
|
|
3060
3175
|
PaymentReturnHandler,
|