@hook-sdk/template 0.1.2 → 0.1.3

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 CHANGED
@@ -43,8 +43,8 @@ __export(index_exports, {
43
43
  module.exports = __toCommonJS(index_exports);
44
44
 
45
45
  // src/AppRoot.tsx
46
- var import_react10 = require("react");
47
- var import_sdk8 = require("@hook-sdk/sdk");
46
+ var import_react11 = require("react");
47
+ var import_sdk9 = require("@hook-sdk/sdk");
48
48
 
49
49
  // src/internal/TemplateConfigContext.tsx
50
50
  var import_react = require("react");
@@ -188,15 +188,30 @@ function SubscriptionGate({ Paywall, children }) {
188
188
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
189
189
  }
190
190
 
191
+ // src/internal/PersistedKeysPrefetch.tsx
192
+ var import_react4 = require("react");
193
+ var import_sdk3 = require("@hook-sdk/sdk");
194
+ var import_jsx_runtime6 = require("react/jsx-runtime");
195
+ function PersistedKeysPrefetch({ children }) {
196
+ const { appData } = (0, import_sdk3.useHook)();
197
+ const config = useTemplateConfig();
198
+ (0, import_react4.useEffect)(() => {
199
+ const keys = config.persistedKeys;
200
+ if (!keys || keys.length === 0) return;
201
+ appData.cache.startPrefetch(keys, (ks) => appData.bulkRead(ks));
202
+ }, [appData, config.persistedKeys]);
203
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children });
204
+ }
205
+
191
206
  // src/internal/PushPrompt.tsx
192
207
  function PushPrompt() {
193
208
  return null;
194
209
  }
195
210
 
196
211
  // src/defaults/ErrorBoundary.tsx
197
- var import_react4 = require("react");
198
- var import_jsx_runtime6 = require("react/jsx-runtime");
199
- var ErrorBoundary = class extends import_react4.Component {
212
+ var import_react5 = require("react");
213
+ var import_jsx_runtime7 = require("react/jsx-runtime");
214
+ var ErrorBoundary = class extends import_react5.Component {
200
215
  state = { error: null };
201
216
  static getDerivedStateFromError(error) {
202
217
  return { error };
@@ -206,30 +221,30 @@ var ErrorBoundary = class extends import_react4.Component {
206
221
  }
207
222
  render() {
208
223
  if (this.state.error) {
209
- return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
210
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { children: "Algo deu errado" }),
211
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
224
+ return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
225
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { children: "Algo deu errado" }),
226
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
212
227
  ] });
213
228
  }
214
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: this.props.children });
229
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: this.props.children });
215
230
  }
216
231
  };
217
232
 
218
233
  // src/hooks/useLoginForm.ts
219
- var import_react5 = require("react");
220
- var import_sdk4 = require("@hook-sdk/sdk");
234
+ var import_react6 = require("react");
235
+ var import_sdk5 = require("@hook-sdk/sdk");
221
236
 
222
237
  // src/errors.ts
223
- var import_sdk3 = require("@hook-sdk/sdk");
238
+ var import_sdk4 = require("@hook-sdk/sdk");
224
239
  function mapSdkError(err) {
225
- if (err instanceof import_sdk3.SdkRateLimitError) {
240
+ if (err instanceof import_sdk4.SdkRateLimitError) {
226
241
  return {
227
242
  code: "rate_limited",
228
243
  message: `Aguarde ${err.retryAfter}s e tente novamente.`,
229
244
  retryAfter: err.retryAfter
230
245
  };
231
246
  }
232
- if (err instanceof import_sdk3.SdkAuthError) {
247
+ if (err instanceof import_sdk4.SdkAuthError) {
233
248
  const detail = err.detail;
234
249
  if (detail === "email_unverified") {
235
250
  return { code: "email_unverified", message: "Confirme seu e-mail antes de entrar." };
@@ -239,7 +254,7 @@ function mapSdkError(err) {
239
254
  }
240
255
  return { code: "invalid_credentials", message: "E-mail ou senha inv\xE1lidos." };
241
256
  }
242
- if (err instanceof import_sdk3.SdkError && err.httpStatus === 0) {
257
+ if (err instanceof import_sdk4.SdkError && err.httpStatus === 0) {
243
258
  return { code: "network", message: "Sem conex\xE3o com o servidor. Verifique sua internet." };
244
259
  }
245
260
  if (err instanceof TypeError) {
@@ -252,23 +267,23 @@ function mapSdkError(err) {
252
267
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
253
268
  var MIN_PASSWORD = 8;
254
269
  function useLoginForm() {
255
- const { auth } = (0, import_sdk4.useHook)();
256
- const [email, setEmail] = (0, import_react5.useState)("");
257
- const [password, setPassword] = (0, import_react5.useState)("");
258
- const [submitting, setSubmitting] = (0, import_react5.useState)(false);
259
- const [error, setError] = (0, import_react5.useState)(null);
260
- const emailError = (0, import_react5.useMemo)(() => {
270
+ const { auth } = (0, import_sdk5.useHook)();
271
+ const [email, setEmail] = (0, import_react6.useState)("");
272
+ const [password, setPassword] = (0, import_react6.useState)("");
273
+ const [submitting, setSubmitting] = (0, import_react6.useState)(false);
274
+ const [error, setError] = (0, import_react6.useState)(null);
275
+ const emailError = (0, import_react6.useMemo)(() => {
261
276
  if (email.length === 0) return null;
262
277
  if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
263
278
  return null;
264
279
  }, [email]);
265
- const passwordError = (0, import_react5.useMemo)(() => {
280
+ const passwordError = (0, import_react6.useMemo)(() => {
266
281
  if (password.length === 0) return null;
267
282
  if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
268
283
  return null;
269
284
  }, [password]);
270
285
  const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && emailError === null && passwordError === null && !submitting;
271
- const submit = (0, import_react5.useCallback)(async () => {
286
+ const submit = (0, import_react6.useCallback)(async () => {
272
287
  if (!canSubmit) return false;
273
288
  setSubmitting(true);
274
289
  setError(null);
@@ -297,20 +312,20 @@ function useLoginForm() {
297
312
  }
298
313
 
299
314
  // src/defaults/DefaultLoginScreen.tsx
300
- var import_jsx_runtime7 = require("react/jsx-runtime");
315
+ var import_jsx_runtime8 = require("react/jsx-runtime");
301
316
  function DefaultLoginScreen({ onNavigate }) {
302
317
  const { name } = useTemplateConfig();
303
318
  const f = useLoginForm();
304
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
305
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
306
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Entre na sua conta" }),
307
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("form", { onSubmit: (e) => {
319
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
320
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
321
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Entre na sua conta" }),
322
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: (e) => {
308
323
  e.preventDefault();
309
324
  void f.submit();
310
325
  }, children: [
311
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
326
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
312
327
  "E-mail",
313
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
328
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
314
329
  "input",
315
330
  {
316
331
  "data-testid": "login-email",
@@ -320,11 +335,11 @@ function DefaultLoginScreen({ onNavigate }) {
320
335
  style: { display: "block", width: "100%" }
321
336
  }
322
337
  ),
323
- f.emailError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
338
+ f.emailError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
324
339
  ] }),
325
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
340
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
326
341
  "Senha",
327
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
342
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
328
343
  "input",
329
344
  {
330
345
  "data-testid": "login-password",
@@ -334,10 +349,10 @@ function DefaultLoginScreen({ onNavigate }) {
334
349
  style: { display: "block", width: "100%" }
335
350
  }
336
351
  ),
337
- f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
352
+ f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
338
353
  ] }),
339
- f.error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
340
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
354
+ f.error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
355
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
341
356
  "button",
342
357
  {
343
358
  "data-testid": "login-submit",
@@ -356,42 +371,42 @@ function DefaultLoginScreen({ onNavigate }) {
356
371
  }
357
372
  )
358
373
  ] }),
359
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { marginTop: 16, display: "flex", justifyContent: "space-between" }, children: [
360
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { "data-testid": "login-goto-signup", type: "button", onClick: () => onNavigate("signup"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Criar conta" }),
361
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { "data-testid": "login-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Esqueci senha" })
374
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { marginTop: 16, display: "flex", justifyContent: "space-between" }, children: [
375
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { "data-testid": "login-goto-signup", type: "button", onClick: () => onNavigate("signup"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Criar conta" }),
376
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { "data-testid": "login-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Esqueci senha" })
362
377
  ] })
363
378
  ] });
364
379
  }
365
380
 
366
381
  // src/hooks/useSignupForm.ts
367
- var import_react6 = require("react");
368
- var import_sdk5 = require("@hook-sdk/sdk");
382
+ var import_react7 = require("react");
383
+ var import_sdk6 = require("@hook-sdk/sdk");
369
384
  var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
370
385
  var MIN_PASSWORD2 = 8;
371
386
  function useSignupForm() {
372
- const { auth } = (0, import_sdk5.useHook)();
373
- const [name, setName] = (0, import_react6.useState)("");
374
- const [email, setEmail] = (0, import_react6.useState)("");
375
- const [password, setPassword] = (0, import_react6.useState)("");
376
- const [submitting, setSubmitting] = (0, import_react6.useState)(false);
377
- const [error, setError] = (0, import_react6.useState)(null);
378
- const nameError = (0, import_react6.useMemo)(() => {
387
+ const { auth } = (0, import_sdk6.useHook)();
388
+ const [name, setName] = (0, import_react7.useState)("");
389
+ const [email, setEmail] = (0, import_react7.useState)("");
390
+ const [password, setPassword] = (0, import_react7.useState)("");
391
+ const [submitting, setSubmitting] = (0, import_react7.useState)(false);
392
+ const [error, setError] = (0, import_react7.useState)(null);
393
+ const nameError = (0, import_react7.useMemo)(() => {
379
394
  if (name.length === 0) return null;
380
395
  if (name.trim().length < 2) return "Nome muito curto.";
381
396
  return null;
382
397
  }, [name]);
383
- const emailError = (0, import_react6.useMemo)(() => {
398
+ const emailError = (0, import_react7.useMemo)(() => {
384
399
  if (email.length === 0) return null;
385
400
  if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
386
401
  return null;
387
402
  }, [email]);
388
- const passwordError = (0, import_react6.useMemo)(() => {
403
+ const passwordError = (0, import_react7.useMemo)(() => {
389
404
  if (password.length === 0) return null;
390
405
  if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
391
406
  return null;
392
407
  }, [password]);
393
408
  const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && nameError === null && emailError === null && passwordError === null && !submitting;
394
- const submit = (0, import_react6.useCallback)(async () => {
409
+ const submit = (0, import_react7.useCallback)(async () => {
395
410
  if (!canSubmit) return false;
396
411
  setSubmitting(true);
397
412
  setError(null);
@@ -423,56 +438,56 @@ function useSignupForm() {
423
438
  }
424
439
 
425
440
  // src/defaults/DefaultSignupScreen.tsx
426
- var import_jsx_runtime8 = require("react/jsx-runtime");
441
+ var import_jsx_runtime9 = require("react/jsx-runtime");
427
442
  function DefaultSignupScreen({ onNavigate }) {
428
443
  const { name } = useTemplateConfig();
429
444
  const f = useSignupForm();
430
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
431
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
432
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Criar sua conta" }),
433
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("form", { onSubmit: (e) => {
445
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
446
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
447
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Criar sua conta" }),
448
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { onSubmit: (e) => {
434
449
  e.preventDefault();
435
450
  void f.submit();
436
451
  }, children: [
437
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
452
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
438
453
  "Nome",
439
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { "data-testid": "signup-name", value: f.name, onChange: (e) => f.setName(e.target.value), style: { display: "block", width: "100%" } }),
440
- f.nameError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("small", { style: { color: "#c00" }, children: f.nameError })
454
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { "data-testid": "signup-name", value: f.name, onChange: (e) => f.setName(e.target.value), style: { display: "block", width: "100%" } }),
455
+ f.nameError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("small", { style: { color: "#c00" }, children: f.nameError })
441
456
  ] }),
442
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
457
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
443
458
  "E-mail",
444
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { "data-testid": "signup-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
445
- f.emailError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
459
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { "data-testid": "signup-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
460
+ f.emailError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
446
461
  ] }),
447
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
462
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
448
463
  "Senha",
449
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { "data-testid": "signup-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" } }),
450
- f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
464
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { "data-testid": "signup-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" } }),
465
+ f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
451
466
  ] }),
452
- f.error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
453
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { "data-testid": "signup-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Criando..." : "Criar conta" })
467
+ f.error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
468
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { "data-testid": "signup-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Criando..." : "Criar conta" })
454
469
  ] }),
455
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { "data-testid": "signup-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "J\xE1 tem conta? Entre" }) })
470
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { "data-testid": "signup-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "J\xE1 tem conta? Entre" }) })
456
471
  ] });
457
472
  }
458
473
 
459
474
  // src/hooks/useForgotForm.ts
460
- var import_react7 = require("react");
461
- var import_sdk6 = require("@hook-sdk/sdk");
475
+ var import_react8 = require("react");
476
+ var import_sdk7 = require("@hook-sdk/sdk");
462
477
  var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
463
478
  function useForgotForm() {
464
- const { auth } = (0, import_sdk6.useHook)();
465
- const [email, setEmail] = (0, import_react7.useState)("");
466
- const [submitting, setSubmitting] = (0, import_react7.useState)(false);
467
- const [sent, setSent] = (0, import_react7.useState)(false);
468
- const [error, setError] = (0, import_react7.useState)(null);
469
- const emailError = (0, import_react7.useMemo)(() => {
479
+ const { auth } = (0, import_sdk7.useHook)();
480
+ const [email, setEmail] = (0, import_react8.useState)("");
481
+ const [submitting, setSubmitting] = (0, import_react8.useState)(false);
482
+ const [sent, setSent] = (0, import_react8.useState)(false);
483
+ const [error, setError] = (0, import_react8.useState)(null);
484
+ const emailError = (0, import_react8.useMemo)(() => {
470
485
  if (email.length === 0) return null;
471
486
  if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
472
487
  return null;
473
488
  }, [email]);
474
489
  const canSubmit = email.length > 0 && emailError === null && !submitting;
475
- const submit = (0, import_react7.useCallback)(async () => {
490
+ const submit = (0, import_react8.useCallback)(async () => {
476
491
  if (!canSubmit) return false;
477
492
  setSubmitting(true);
478
493
  setError(null);
@@ -500,66 +515,66 @@ function useForgotForm() {
500
515
  }
501
516
 
502
517
  // src/defaults/DefaultForgotScreen.tsx
503
- var import_jsx_runtime9 = require("react/jsx-runtime");
518
+ var import_jsx_runtime10 = require("react/jsx-runtime");
504
519
  function DefaultForgotScreen({ onNavigate }) {
505
520
  const { name } = useTemplateConfig();
506
521
  const f = useForgotForm();
507
522
  if (f.sent) {
508
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
509
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { children: "Verifique seu e-mail" }),
510
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { opacity: 0.7 }, children: "Enviamos um link pra redefinir sua senha." }),
511
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { "data-testid": "forgot-back-login", type: "button", onClick: () => onNavigate("login"), children: "Voltar pro login" })
523
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
524
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { children: "Verifique seu e-mail" }),
525
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7 }, children: "Enviamos um link pra redefinir sua senha." }),
526
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-testid": "forgot-back-login", type: "button", onClick: () => onNavigate("login"), children: "Voltar pro login" })
512
527
  ] });
513
528
  }
514
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
515
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
516
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Redefinir senha" }),
517
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("form", { onSubmit: (e) => {
529
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
530
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
531
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Redefinir senha" }),
532
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: (e) => {
518
533
  e.preventDefault();
519
534
  void f.submit();
520
535
  }, children: [
521
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
536
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
522
537
  "E-mail",
523
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { "data-testid": "forgot-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
524
- f.emailError && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
538
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { "data-testid": "forgot-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
539
+ f.emailError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
525
540
  ] }),
526
- f.error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
527
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { "data-testid": "forgot-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Enviando..." : "Enviar link" })
541
+ f.error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
542
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-testid": "forgot-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Enviando..." : "Enviar link" })
528
543
  ] }),
529
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { "data-testid": "forgot-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Voltar pro login" }) })
544
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-testid": "forgot-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Voltar pro login" }) })
530
545
  ] });
531
546
  }
532
547
 
533
548
  // src/hooks/useResetForm.ts
534
- var import_react8 = require("react");
535
- var import_sdk7 = require("@hook-sdk/sdk");
549
+ var import_react9 = require("react");
550
+ var import_sdk8 = require("@hook-sdk/sdk");
536
551
  var MIN_PASSWORD3 = 12;
537
552
  function useResetForm() {
538
- const { auth } = (0, import_sdk7.useHook)();
539
- const [token, setToken] = (0, import_react8.useState)(null);
540
- const [password, setPassword] = (0, import_react8.useState)("");
541
- const [confirm, setConfirm] = (0, import_react8.useState)("");
542
- const [submitting, setSubmitting] = (0, import_react8.useState)(false);
543
- const [done, setDone] = (0, import_react8.useState)(false);
544
- const [error, setError] = (0, import_react8.useState)(null);
545
- (0, import_react8.useEffect)(() => {
553
+ const { auth } = (0, import_sdk8.useHook)();
554
+ const [token, setToken] = (0, import_react9.useState)(null);
555
+ const [password, setPassword] = (0, import_react9.useState)("");
556
+ const [confirm, setConfirm] = (0, import_react9.useState)("");
557
+ const [submitting, setSubmitting] = (0, import_react9.useState)(false);
558
+ const [done, setDone] = (0, import_react9.useState)(false);
559
+ const [error, setError] = (0, import_react9.useState)(null);
560
+ (0, import_react9.useEffect)(() => {
546
561
  if (typeof window === "undefined") return;
547
562
  const params = new URLSearchParams(window.location.search);
548
563
  const t = params.get("token");
549
564
  setToken(t && t.length > 0 ? t : null);
550
565
  }, []);
551
- const passwordError = (0, import_react8.useMemo)(() => {
566
+ const passwordError = (0, import_react9.useMemo)(() => {
552
567
  if (password.length === 0) return null;
553
568
  if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
554
569
  return null;
555
570
  }, [password]);
556
- const confirmError = (0, import_react8.useMemo)(() => {
571
+ const confirmError = (0, import_react9.useMemo)(() => {
557
572
  if (confirm.length === 0) return null;
558
573
  if (confirm !== password) return "Senhas n\xE3o coincidem.";
559
574
  return null;
560
575
  }, [confirm, password]);
561
576
  const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && passwordError === null && confirmError === null && !submitting && !done;
562
- const submit = (0, import_react8.useCallback)(async () => {
577
+ const submit = (0, import_react9.useCallback)(async () => {
563
578
  if (!canSubmit || token === null) return;
564
579
  setSubmitting(true);
565
580
  setError(null);
@@ -595,67 +610,67 @@ function useResetForm() {
595
610
  }
596
611
 
597
612
  // src/defaults/DefaultResetScreen.tsx
598
- var import_jsx_runtime10 = require("react/jsx-runtime");
613
+ var import_jsx_runtime11 = require("react/jsx-runtime");
599
614
  function DefaultResetScreen({ onNavigate }) {
600
615
  const { name } = useTemplateConfig();
601
616
  const f = useResetForm();
602
617
  if (f.done) {
603
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
604
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { children: "Senha alterada" }),
605
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7 }, children: "Agora \xE9 s\xF3 fazer login com a nova senha." }),
606
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-testid": "reset-back-login", type: "button", onClick: () => onNavigate("login"), children: "Ir pro login" })
618
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
619
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { children: "Senha alterada" }),
620
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.7 }, children: "Agora \xE9 s\xF3 fazer login com a nova senha." }),
621
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { "data-testid": "reset-back-login", type: "button", onClick: () => onNavigate("login"), children: "Ir pro login" })
607
622
  ] });
608
623
  }
609
624
  if (f.token === null) {
610
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
611
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { children: "Link inv\xE1lido" }),
612
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7 }, children: "Pe\xE7a um novo link de reset." }),
613
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-testid": "reset-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), children: "Pedir novo link" })
625
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
626
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { children: "Link inv\xE1lido" }),
627
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.7 }, children: "Pe\xE7a um novo link de reset." }),
628
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { "data-testid": "reset-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), children: "Pedir novo link" })
614
629
  ] });
615
630
  }
616
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
617
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
618
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Escolha uma nova senha" }),
619
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: (e) => {
631
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
632
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
633
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Escolha uma nova senha" }),
634
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("form", { onSubmit: (e) => {
620
635
  e.preventDefault();
621
636
  void f.submit();
622
637
  }, children: [
623
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
638
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
624
639
  "Nova senha",
625
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { "data-testid": "reset-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" }, autoComplete: "new-password" }),
626
- f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
640
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { "data-testid": "reset-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" }, autoComplete: "new-password" }),
641
+ f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
627
642
  ] }),
628
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
643
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
629
644
  "Confirmar senha",
630
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { "data-testid": "reset-confirm", type: "password", value: f.confirm, onChange: (e) => f.setConfirm(e.target.value), style: { display: "block", width: "100%" }, autoComplete: "new-password" }),
631
- f.confirmError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("small", { style: { color: "#c00" }, children: f.confirmError })
645
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { "data-testid": "reset-confirm", type: "password", value: f.confirm, onChange: (e) => f.setConfirm(e.target.value), style: { display: "block", width: "100%" }, autoComplete: "new-password" }),
646
+ f.confirmError && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("small", { style: { color: "#c00" }, children: f.confirmError })
632
647
  ] }),
633
- f.error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
634
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { "data-testid": "reset-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Alterando..." : "Alterar senha" })
648
+ f.error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
649
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { "data-testid": "reset-submit", type: "submit", disabled: !f.canSubmit, style: { width: "100%", padding: 12, background: "var(--hook-color-primary)", color: "#fff", border: "none", borderRadius: 8, opacity: f.canSubmit ? 1 : 0.5 }, children: f.submitting ? "Alterando..." : "Alterar senha" })
635
650
  ] })
636
651
  ] });
637
652
  }
638
653
 
639
654
  // src/defaults/DefaultPaywall.tsx
640
- var import_react9 = require("react");
641
- var import_jsx_runtime11 = require("react/jsx-runtime");
655
+ var import_react10 = require("react");
656
+ var import_jsx_runtime12 = require("react/jsx-runtime");
642
657
  function DefaultPaywall() {
643
658
  const config = useTemplateConfig();
644
659
  const { checkout, opening, error } = usePaywallState();
645
660
  const p = config.subscription.paywall_config;
646
- const [cpf, setCpf] = (0, import_react9.useState)("");
661
+ const [cpf, setCpf] = (0, import_react10.useState)("");
647
662
  const cpfDigits = cpf.replace(/\D/g, "");
648
663
  const canCheckout = cpfDigits.length === 11 && !opening;
649
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("main", { style: { padding: 24, maxWidth: 440, margin: "0 auto", textAlign: "center" }, children: [
650
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: { marginBottom: 8 }, children: p.title }),
651
- p.subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: p.subtitle }),
652
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("ul", { style: { listStyle: "none", padding: 0, textAlign: "left", marginBottom: 24 }, children: p.benefits.map((b) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("li", { style: { padding: "8px 0", display: "flex", alignItems: "center" }, children: [
653
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { "aria-hidden": true, style: { marginRight: 8 }, children: "\u2713" }),
654
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: b })
664
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("main", { style: { padding: 24, maxWidth: 440, margin: "0 auto", textAlign: "center" }, children: [
665
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h1", { style: { marginBottom: 8 }, children: p.title }),
666
+ p.subtitle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: p.subtitle }),
667
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ul", { style: { listStyle: "none", padding: 0, textAlign: "left", marginBottom: 24 }, children: p.benefits.map((b) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("li", { style: { padding: "8px 0", display: "flex", alignItems: "center" }, children: [
668
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { "aria-hidden": true, style: { marginRight: 8 }, children: "\u2713" }),
669
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: b })
655
670
  ] }, b)) }),
656
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { textAlign: "left", marginBottom: 16 }, children: [
657
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { style: { display: "block", fontSize: 14, opacity: 0.7, marginBottom: 4 }, children: "Seu CPF (pra emiss\xE3o de recibo)" }),
658
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
671
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { textAlign: "left", marginBottom: 16 }, children: [
672
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", { style: { display: "block", fontSize: 14, opacity: 0.7, marginBottom: 4 }, children: "Seu CPF (pra emiss\xE3o de recibo)" }),
673
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
659
674
  "input",
660
675
  {
661
676
  "data-testid": "paywall-cpf",
@@ -668,8 +683,8 @@ function DefaultPaywall() {
668
683
  }
669
684
  )
670
685
  ] }),
671
- error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: error.message }),
672
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
686
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: error.message }),
687
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
673
688
  "button",
674
689
  {
675
690
  "data-testid": "paywall-cta",
@@ -690,72 +705,107 @@ function DefaultPaywall() {
690
705
  children: opening ? "Abrindo..." : p.cta
691
706
  }
692
707
  ),
693
- p.priceHint && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.6, marginTop: 12 }, children: p.priceHint }),
694
- p.footerNote && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.5, marginTop: 16, fontSize: 12 }, children: p.footerNote })
708
+ p.priceHint && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: { opacity: 0.6, marginTop: 12 }, children: p.priceHint }),
709
+ p.footerNote && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: { opacity: 0.5, marginTop: 16, fontSize: 12 }, children: p.footerNote })
695
710
  ] });
696
711
  }
697
712
 
698
713
  // src/AppRoot.tsx
699
- var import_jsx_runtime12 = require("react/jsx-runtime");
714
+ var import_jsx_runtime13 = require("react/jsx-runtime");
715
+ var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
700
716
  function PaymentReturnHandler({ children }) {
701
- const { subscription } = (0, import_sdk8.useHook)();
702
- const [confirming, setConfirming] = (0, import_react10.useState)(false);
703
- (0, import_react10.useEffect)(() => {
704
- if (typeof window === "undefined") return;
705
- const url = new URL(window.location.href);
706
- if (url.searchParams.get("paymentReturn") !== "1") return;
707
- let cancelled = false;
717
+ const { subscription } = (0, import_sdk9.useHook)();
718
+ const subRef = (0, import_react11.useRef)(subscription);
719
+ subRef.current = subscription;
720
+ const runIdRef = (0, import_react11.useRef)(0);
721
+ const [state, setState] = (0, import_react11.useState)("idle");
722
+ const runPoll = (0, import_react11.useCallback)(() => {
723
+ const runId = ++runIdRef.current;
724
+ setState("confirming");
708
725
  let attempts = 0;
709
- setConfirming(true);
710
726
  const tick = async () => {
711
- if (cancelled) return;
712
- if (attempts >= 10) {
713
- setConfirming(false);
714
- return;
715
- }
727
+ if (runIdRef.current !== runId) return;
716
728
  attempts++;
717
729
  try {
718
- await subscription.refresh();
730
+ await subRef.current.refresh();
719
731
  } catch {
720
732
  }
721
- if (cancelled) return;
722
- if (subscription.status() === "active") {
733
+ if (runIdRef.current !== runId) return;
734
+ const status = subRef.current.status();
735
+ if (status === "active" || status === "trialing") {
723
736
  const cleanUrl = new URL(window.location.href);
724
737
  cleanUrl.searchParams.delete("paymentReturn");
725
738
  window.history.replaceState({}, "", cleanUrl.toString());
726
- setConfirming(false);
739
+ setState("idle");
727
740
  return;
728
741
  }
729
- setTimeout(tick, 1e3);
742
+ const delay = BACKOFF_MS[attempts - 1];
743
+ if (delay === void 0) {
744
+ setState("waiting");
745
+ return;
746
+ }
747
+ setTimeout(tick, delay);
730
748
  };
731
749
  void tick();
750
+ }, []);
751
+ (0, import_react11.useEffect)(() => {
752
+ if (typeof window === "undefined") return;
753
+ const url = new URL(window.location.href);
754
+ if (url.searchParams.get("paymentReturn") !== "1") return;
755
+ runPoll();
732
756
  return () => {
733
- cancelled = true;
757
+ runIdRef.current++;
734
758
  };
735
- }, [subscription]);
736
- if (confirming) {
737
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
759
+ }, [runPoll]);
760
+ if (state === "confirming") {
761
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
738
762
  "div",
739
763
  {
740
764
  role: "status",
741
765
  "aria-live": "polite",
742
- style: {
743
- position: "fixed",
744
- inset: 0,
745
- display: "flex",
746
- alignItems: "center",
747
- justifyContent: "center",
748
- background: "rgba(0,0,0,0.4)",
749
- zIndex: 9999,
750
- color: "white",
751
- fontSize: "1rem"
752
- },
766
+ style: overlayStyle,
753
767
  children: "Confirmando pagamento\u2026"
754
768
  }
755
769
  );
756
770
  }
757
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children });
771
+ if (state === "waiting") {
772
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
773
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
774
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
775
+ "button",
776
+ {
777
+ type: "button",
778
+ onClick: runPoll,
779
+ style: buttonStyle,
780
+ children: "Atualizar"
781
+ }
782
+ )
783
+ ] }) });
784
+ }
785
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children });
758
786
  }
787
+ var overlayStyle = {
788
+ position: "fixed",
789
+ inset: 0,
790
+ display: "flex",
791
+ alignItems: "center",
792
+ justifyContent: "center",
793
+ background: "rgba(0,0,0,0.4)",
794
+ zIndex: 9999,
795
+ color: "white",
796
+ fontSize: "1rem",
797
+ padding: 24
798
+ };
799
+ var buttonStyle = {
800
+ background: "white",
801
+ color: "black",
802
+ border: "none",
803
+ borderRadius: 8,
804
+ padding: "10px 24px",
805
+ fontSize: "1rem",
806
+ fontWeight: 600,
807
+ cursor: "pointer"
808
+ };
759
809
  function AppRoot({
760
810
  config,
761
811
  children,
@@ -765,29 +815,29 @@ function AppRoot({
765
815
  Reset = DefaultResetScreen,
766
816
  Paywall = DefaultPaywall
767
817
  }) {
768
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PaymentReturnHandler, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TemplateConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(AuthGate, { Login, Signup, Forgot, Reset, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(SubscriptionGate, { Paywall, children: [
818
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PaymentReturnHandler, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TemplateConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(AuthGate, { Login, Signup, Forgot, Reset, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PersistedKeysPrefetch, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(SubscriptionGate, { Paywall, children: [
769
819
  children,
770
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PushPrompt, {})
771
- ] }) }) }) }) }) });
820
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PushPrompt, {})
821
+ ] }) }) }) }) }) }) });
772
822
  }
773
823
 
774
824
  // src/defaults/EmptyState.tsx
775
- var import_jsx_runtime13 = require("react/jsx-runtime");
825
+ var import_jsx_runtime14 = require("react/jsx-runtime");
776
826
  function EmptyState({ title, description, action }) {
777
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
778
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
779
- description && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: { opacity: 0.7 }, children: description }),
780
- action && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { marginTop: 16 }, children: action })
827
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
828
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
829
+ description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { opacity: 0.7 }, children: description }),
830
+ action && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { marginTop: 16 }, children: action })
781
831
  ] });
782
832
  }
783
833
 
784
834
  // src/hooks/useAuthPrimitives.ts
785
- var import_react11 = require("react");
786
- var import_sdk9 = require("@hook-sdk/sdk");
835
+ var import_react12 = require("react");
836
+ var import_sdk10 = require("@hook-sdk/sdk");
787
837
  var warned = false;
788
838
  function useAuthPrimitives() {
789
- const { auth } = (0, import_sdk9.useHook)();
790
- (0, import_react11.useEffect)(() => {
839
+ const { auth } = (0, import_sdk10.useHook)();
840
+ (0, import_react12.useEffect)(() => {
791
841
  if (!warned && process.env.NODE_ENV !== "production") {
792
842
  warned = true;
793
843
  console.warn(
@@ -809,18 +859,18 @@ function useAuthPrimitives() {
809
859
  }
810
860
 
811
861
  // src/hooks/useSubscription.ts
812
- var import_sdk10 = require("@hook-sdk/sdk");
862
+ var import_sdk11 = require("@hook-sdk/sdk");
813
863
  function useSubscription() {
814
- const { subscription } = (0, import_sdk10.useHook)();
864
+ const { subscription } = (0, import_sdk11.useHook)();
815
865
  return {
816
866
  status: subscription.status()
817
867
  };
818
868
  }
819
869
 
820
870
  // src/hooks/usePush.ts
821
- var import_sdk11 = require("@hook-sdk/sdk");
871
+ var import_sdk12 = require("@hook-sdk/sdk");
822
872
  function usePush() {
823
- const { push } = (0, import_sdk11.useHook)();
873
+ const { push } = (0, import_sdk12.useHook)();
824
874
  return {
825
875
  status: push.status(),
826
876
  subscribe: push.subscribe,
@@ -829,17 +879,17 @@ function usePush() {
829
879
  }
830
880
 
831
881
  // src/hooks/useToast.ts
832
- var import_react12 = require("react");
882
+ var import_react13 = require("react");
833
883
  function useToast() {
834
- const [items, setItems] = (0, import_react12.useState)([]);
835
- const show = (0, import_react12.useCallback)((message, kind = "info") => {
884
+ const [items, setItems] = (0, import_react13.useState)([]);
885
+ const show = (0, import_react13.useCallback)((message, kind = "info") => {
836
886
  const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
837
887
  setItems((prev) => [...prev, { id, message, kind }]);
838
888
  setTimeout(() => {
839
889
  setItems((prev) => prev.filter((t) => t.id !== id));
840
890
  }, 4e3);
841
891
  }, []);
842
- const dismiss = (0, import_react12.useCallback)((id) => {
892
+ const dismiss = (0, import_react13.useCallback)((id) => {
843
893
  setItems((prev) => prev.filter((t) => t.id !== id));
844
894
  }, []);
845
895
  return { items, show, dismiss };