@hook-sdk/template 0.1.1 → 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
@@ -42,6 +42,10 @@ __export(index_exports, {
42
42
  });
43
43
  module.exports = __toCommonJS(index_exports);
44
44
 
45
+ // src/AppRoot.tsx
46
+ var import_react11 = require("react");
47
+ var import_sdk9 = require("@hook-sdk/sdk");
48
+
45
49
  // src/internal/TemplateConfigContext.tsx
46
50
  var import_react = require("react");
47
51
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -50,7 +54,11 @@ function TemplateConfigProvider({
50
54
  config,
51
55
  children
52
56
  }) {
53
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TemplateConfigContext.Provider, { value: config, children });
57
+ const value = (0, import_react.useMemo)(() => ({
58
+ ...config,
59
+ mode: config.subscription?.mode ?? "trial"
60
+ }), [config]);
61
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TemplateConfigContext.Provider, { value, children });
54
62
  }
55
63
  function useTemplateConfig() {
56
64
  const ctx = (0, import_react.useContext)(TemplateConfigContext);
@@ -166,23 +174,44 @@ function usePaywallState() {
166
174
 
167
175
  // src/internal/SubscriptionGate.tsx
168
176
  var import_jsx_runtime5 = require("react/jsx-runtime");
177
+ var BLOCKING = /* @__PURE__ */ new Set([
178
+ "pending",
179
+ "expired",
180
+ "canceled",
181
+ "none"
182
+ ]);
169
183
  function SubscriptionGate({ Paywall, children }) {
184
+ const { mode } = useTemplateConfig();
170
185
  const { status } = usePaywallState();
171
- if (status === "expired" || status === "canceled" || status === "past_due") {
172
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Paywall, {});
173
- }
186
+ if (mode === "free") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
187
+ if (BLOCKING.has(status)) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Paywall, {});
174
188
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
175
189
  }
176
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
+
177
206
  // src/internal/PushPrompt.tsx
178
207
  function PushPrompt() {
179
208
  return null;
180
209
  }
181
210
 
182
211
  // src/defaults/ErrorBoundary.tsx
183
- var import_react4 = require("react");
184
- var import_jsx_runtime6 = require("react/jsx-runtime");
185
- 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 {
186
215
  state = { error: null };
187
216
  static getDerivedStateFromError(error) {
188
217
  return { error };
@@ -192,30 +221,30 @@ var ErrorBoundary = class extends import_react4.Component {
192
221
  }
193
222
  render() {
194
223
  if (this.state.error) {
195
- return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
196
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { children: "Algo deu errado" }),
197
- /* @__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." })
198
227
  ] });
199
228
  }
200
- 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 });
201
230
  }
202
231
  };
203
232
 
204
233
  // src/hooks/useLoginForm.ts
205
- var import_react5 = require("react");
206
- var import_sdk4 = require("@hook-sdk/sdk");
234
+ var import_react6 = require("react");
235
+ var import_sdk5 = require("@hook-sdk/sdk");
207
236
 
208
237
  // src/errors.ts
209
- var import_sdk3 = require("@hook-sdk/sdk");
238
+ var import_sdk4 = require("@hook-sdk/sdk");
210
239
  function mapSdkError(err) {
211
- if (err instanceof import_sdk3.SdkRateLimitError) {
240
+ if (err instanceof import_sdk4.SdkRateLimitError) {
212
241
  return {
213
242
  code: "rate_limited",
214
243
  message: `Aguarde ${err.retryAfter}s e tente novamente.`,
215
244
  retryAfter: err.retryAfter
216
245
  };
217
246
  }
218
- if (err instanceof import_sdk3.SdkAuthError) {
247
+ if (err instanceof import_sdk4.SdkAuthError) {
219
248
  const detail = err.detail;
220
249
  if (detail === "email_unverified") {
221
250
  return { code: "email_unverified", message: "Confirme seu e-mail antes de entrar." };
@@ -225,7 +254,7 @@ function mapSdkError(err) {
225
254
  }
226
255
  return { code: "invalid_credentials", message: "E-mail ou senha inv\xE1lidos." };
227
256
  }
228
- if (err instanceof import_sdk3.SdkError && err.httpStatus === 0) {
257
+ if (err instanceof import_sdk4.SdkError && err.httpStatus === 0) {
229
258
  return { code: "network", message: "Sem conex\xE3o com o servidor. Verifique sua internet." };
230
259
  }
231
260
  if (err instanceof TypeError) {
@@ -238,30 +267,32 @@ function mapSdkError(err) {
238
267
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
239
268
  var MIN_PASSWORD = 8;
240
269
  function useLoginForm() {
241
- const { auth } = (0, import_sdk4.useHook)();
242
- const [email, setEmail] = (0, import_react5.useState)("");
243
- const [password, setPassword] = (0, import_react5.useState)("");
244
- const [submitting, setSubmitting] = (0, import_react5.useState)(false);
245
- const [error, setError] = (0, import_react5.useState)(null);
246
- 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)(() => {
247
276
  if (email.length === 0) return null;
248
277
  if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
249
278
  return null;
250
279
  }, [email]);
251
- const passwordError = (0, import_react5.useMemo)(() => {
280
+ const passwordError = (0, import_react6.useMemo)(() => {
252
281
  if (password.length === 0) return null;
253
282
  if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
254
283
  return null;
255
284
  }, [password]);
256
285
  const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && emailError === null && passwordError === null && !submitting;
257
- const submit = (0, import_react5.useCallback)(async () => {
258
- if (!canSubmit) return;
286
+ const submit = (0, import_react6.useCallback)(async () => {
287
+ if (!canSubmit) return false;
259
288
  setSubmitting(true);
260
289
  setError(null);
261
290
  try {
262
291
  await auth.login({ email, password });
292
+ return true;
263
293
  } catch (err) {
264
294
  setError(mapSdkError(err));
295
+ return false;
265
296
  } finally {
266
297
  setSubmitting(false);
267
298
  }
@@ -281,20 +312,20 @@ function useLoginForm() {
281
312
  }
282
313
 
283
314
  // src/defaults/DefaultLoginScreen.tsx
284
- var import_jsx_runtime7 = require("react/jsx-runtime");
315
+ var import_jsx_runtime8 = require("react/jsx-runtime");
285
316
  function DefaultLoginScreen({ onNavigate }) {
286
317
  const { name } = useTemplateConfig();
287
318
  const f = useLoginForm();
288
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
289
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
290
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Entre na sua conta" }),
291
- /* @__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) => {
292
323
  e.preventDefault();
293
324
  void f.submit();
294
325
  }, children: [
295
- /* @__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: [
296
327
  "E-mail",
297
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
328
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
298
329
  "input",
299
330
  {
300
331
  "data-testid": "login-email",
@@ -304,11 +335,11 @@ function DefaultLoginScreen({ onNavigate }) {
304
335
  style: { display: "block", width: "100%" }
305
336
  }
306
337
  ),
307
- 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 })
308
339
  ] }),
309
- /* @__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: [
310
341
  "Senha",
311
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
342
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
312
343
  "input",
313
344
  {
314
345
  "data-testid": "login-password",
@@ -318,10 +349,10 @@ function DefaultLoginScreen({ onNavigate }) {
318
349
  style: { display: "block", width: "100%" }
319
350
  }
320
351
  ),
321
- 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 })
322
353
  ] }),
323
- f.error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
324
- /* @__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)(
325
356
  "button",
326
357
  {
327
358
  "data-testid": "login-submit",
@@ -340,49 +371,51 @@ function DefaultLoginScreen({ onNavigate }) {
340
371
  }
341
372
  )
342
373
  ] }),
343
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { marginTop: 16, display: "flex", justifyContent: "space-between" }, children: [
344
- /* @__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" }),
345
- /* @__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" })
346
377
  ] })
347
378
  ] });
348
379
  }
349
380
 
350
381
  // src/hooks/useSignupForm.ts
351
- var import_react6 = require("react");
352
- var import_sdk5 = require("@hook-sdk/sdk");
382
+ var import_react7 = require("react");
383
+ var import_sdk6 = require("@hook-sdk/sdk");
353
384
  var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
354
385
  var MIN_PASSWORD2 = 8;
355
386
  function useSignupForm() {
356
- const { auth } = (0, import_sdk5.useHook)();
357
- const [name, setName] = (0, import_react6.useState)("");
358
- const [email, setEmail] = (0, import_react6.useState)("");
359
- const [password, setPassword] = (0, import_react6.useState)("");
360
- const [submitting, setSubmitting] = (0, import_react6.useState)(false);
361
- const [error, setError] = (0, import_react6.useState)(null);
362
- 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)(() => {
363
394
  if (name.length === 0) return null;
364
395
  if (name.trim().length < 2) return "Nome muito curto.";
365
396
  return null;
366
397
  }, [name]);
367
- const emailError = (0, import_react6.useMemo)(() => {
398
+ const emailError = (0, import_react7.useMemo)(() => {
368
399
  if (email.length === 0) return null;
369
400
  if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
370
401
  return null;
371
402
  }, [email]);
372
- const passwordError = (0, import_react6.useMemo)(() => {
403
+ const passwordError = (0, import_react7.useMemo)(() => {
373
404
  if (password.length === 0) return null;
374
405
  if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
375
406
  return null;
376
407
  }, [password]);
377
408
  const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && nameError === null && emailError === null && passwordError === null && !submitting;
378
- const submit = (0, import_react6.useCallback)(async () => {
379
- if (!canSubmit) return;
409
+ const submit = (0, import_react7.useCallback)(async () => {
410
+ if (!canSubmit) return false;
380
411
  setSubmitting(true);
381
412
  setError(null);
382
413
  try {
383
414
  await auth.signup({ name, email, password });
415
+ return true;
384
416
  } catch (err) {
385
417
  setError(mapSdkError(err));
418
+ return false;
386
419
  } finally {
387
420
  setSubmitting(false);
388
421
  }
@@ -405,64 +438,66 @@ function useSignupForm() {
405
438
  }
406
439
 
407
440
  // src/defaults/DefaultSignupScreen.tsx
408
- var import_jsx_runtime8 = require("react/jsx-runtime");
441
+ var import_jsx_runtime9 = require("react/jsx-runtime");
409
442
  function DefaultSignupScreen({ onNavigate }) {
410
443
  const { name } = useTemplateConfig();
411
444
  const f = useSignupForm();
412
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
413
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
414
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Criar sua conta" }),
415
- /* @__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) => {
416
449
  e.preventDefault();
417
450
  void f.submit();
418
451
  }, children: [
419
- /* @__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: [
420
453
  "Nome",
421
- /* @__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%" } }),
422
- 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 })
423
456
  ] }),
424
- /* @__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: [
425
458
  "E-mail",
426
- /* @__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%" } }),
427
- 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 })
428
461
  ] }),
429
- /* @__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: [
430
463
  "Senha",
431
- /* @__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%" } }),
432
- 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 })
433
466
  ] }),
434
- f.error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
435
- /* @__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" })
436
469
  ] }),
437
- /* @__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" }) })
438
471
  ] });
439
472
  }
440
473
 
441
474
  // src/hooks/useForgotForm.ts
442
- var import_react7 = require("react");
443
- var import_sdk6 = require("@hook-sdk/sdk");
475
+ var import_react8 = require("react");
476
+ var import_sdk7 = require("@hook-sdk/sdk");
444
477
  var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
445
478
  function useForgotForm() {
446
- const { auth } = (0, import_sdk6.useHook)();
447
- const [email, setEmail] = (0, import_react7.useState)("");
448
- const [submitting, setSubmitting] = (0, import_react7.useState)(false);
449
- const [sent, setSent] = (0, import_react7.useState)(false);
450
- const [error, setError] = (0, import_react7.useState)(null);
451
- 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)(() => {
452
485
  if (email.length === 0) return null;
453
486
  if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
454
487
  return null;
455
488
  }, [email]);
456
489
  const canSubmit = email.length > 0 && emailError === null && !submitting;
457
- const submit = (0, import_react7.useCallback)(async () => {
458
- if (!canSubmit) return;
490
+ const submit = (0, import_react8.useCallback)(async () => {
491
+ if (!canSubmit) return false;
459
492
  setSubmitting(true);
460
493
  setError(null);
461
494
  try {
462
495
  await auth.forgot({ email });
463
496
  setSent(true);
497
+ return true;
464
498
  } catch (err) {
465
499
  setError(mapSdkError(err));
500
+ return false;
466
501
  } finally {
467
502
  setSubmitting(false);
468
503
  }
@@ -480,66 +515,66 @@ function useForgotForm() {
480
515
  }
481
516
 
482
517
  // src/defaults/DefaultForgotScreen.tsx
483
- var import_jsx_runtime9 = require("react/jsx-runtime");
518
+ var import_jsx_runtime10 = require("react/jsx-runtime");
484
519
  function DefaultForgotScreen({ onNavigate }) {
485
520
  const { name } = useTemplateConfig();
486
521
  const f = useForgotForm();
487
522
  if (f.sent) {
488
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
489
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { children: "Verifique seu e-mail" }),
490
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { opacity: 0.7 }, children: "Enviamos um link pra redefinir sua senha." }),
491
- /* @__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" })
492
527
  ] });
493
528
  }
494
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
495
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
496
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Redefinir senha" }),
497
- /* @__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) => {
498
533
  e.preventDefault();
499
534
  void f.submit();
500
535
  }, children: [
501
- /* @__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: [
502
537
  "E-mail",
503
- /* @__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%" } }),
504
- 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 })
505
540
  ] }),
506
- f.error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
507
- /* @__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" })
508
543
  ] }),
509
- /* @__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" }) })
510
545
  ] });
511
546
  }
512
547
 
513
548
  // src/hooks/useResetForm.ts
514
- var import_react8 = require("react");
515
- var import_sdk7 = require("@hook-sdk/sdk");
549
+ var import_react9 = require("react");
550
+ var import_sdk8 = require("@hook-sdk/sdk");
516
551
  var MIN_PASSWORD3 = 12;
517
552
  function useResetForm() {
518
- const { auth } = (0, import_sdk7.useHook)();
519
- const [token, setToken] = (0, import_react8.useState)(null);
520
- const [password, setPassword] = (0, import_react8.useState)("");
521
- const [confirm, setConfirm] = (0, import_react8.useState)("");
522
- const [submitting, setSubmitting] = (0, import_react8.useState)(false);
523
- const [done, setDone] = (0, import_react8.useState)(false);
524
- const [error, setError] = (0, import_react8.useState)(null);
525
- (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)(() => {
526
561
  if (typeof window === "undefined") return;
527
562
  const params = new URLSearchParams(window.location.search);
528
563
  const t = params.get("token");
529
564
  setToken(t && t.length > 0 ? t : null);
530
565
  }, []);
531
- const passwordError = (0, import_react8.useMemo)(() => {
566
+ const passwordError = (0, import_react9.useMemo)(() => {
532
567
  if (password.length === 0) return null;
533
568
  if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
534
569
  return null;
535
570
  }, [password]);
536
- const confirmError = (0, import_react8.useMemo)(() => {
571
+ const confirmError = (0, import_react9.useMemo)(() => {
537
572
  if (confirm.length === 0) return null;
538
573
  if (confirm !== password) return "Senhas n\xE3o coincidem.";
539
574
  return null;
540
575
  }, [confirm, password]);
541
576
  const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && passwordError === null && confirmError === null && !submitting && !done;
542
- const submit = (0, import_react8.useCallback)(async () => {
577
+ const submit = (0, import_react9.useCallback)(async () => {
543
578
  if (!canSubmit || token === null) return;
544
579
  setSubmitting(true);
545
580
  setError(null);
@@ -575,67 +610,67 @@ function useResetForm() {
575
610
  }
576
611
 
577
612
  // src/defaults/DefaultResetScreen.tsx
578
- var import_jsx_runtime10 = require("react/jsx-runtime");
613
+ var import_jsx_runtime11 = require("react/jsx-runtime");
579
614
  function DefaultResetScreen({ onNavigate }) {
580
615
  const { name } = useTemplateConfig();
581
616
  const f = useResetForm();
582
617
  if (f.done) {
583
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
584
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { children: "Senha alterada" }),
585
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7 }, children: "Agora \xE9 s\xF3 fazer login com a nova senha." }),
586
- /* @__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" })
587
622
  ] });
588
623
  }
589
624
  if (f.token === null) {
590
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
591
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { children: "Link inv\xE1lido" }),
592
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7 }, children: "Pe\xE7a um novo link de reset." }),
593
- /* @__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" })
594
629
  ] });
595
630
  }
596
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
597
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
598
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Escolha uma nova senha" }),
599
- /* @__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) => {
600
635
  e.preventDefault();
601
636
  void f.submit();
602
637
  }, children: [
603
- /* @__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: [
604
639
  "Nova senha",
605
- /* @__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" }),
606
- 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 })
607
642
  ] }),
608
- /* @__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: [
609
644
  "Confirmar senha",
610
- /* @__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" }),
611
- 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 })
612
647
  ] }),
613
- f.error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
614
- /* @__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" })
615
650
  ] })
616
651
  ] });
617
652
  }
618
653
 
619
654
  // src/defaults/DefaultPaywall.tsx
620
- var import_react9 = require("react");
621
- var import_jsx_runtime11 = require("react/jsx-runtime");
655
+ var import_react10 = require("react");
656
+ var import_jsx_runtime12 = require("react/jsx-runtime");
622
657
  function DefaultPaywall() {
623
658
  const config = useTemplateConfig();
624
659
  const { checkout, opening, error } = usePaywallState();
625
660
  const p = config.subscription.paywall_config;
626
- const [cpf, setCpf] = (0, import_react9.useState)("");
661
+ const [cpf, setCpf] = (0, import_react10.useState)("");
627
662
  const cpfDigits = cpf.replace(/\D/g, "");
628
663
  const canCheckout = cpfDigits.length === 11 && !opening;
629
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("main", { style: { padding: 24, maxWidth: 440, margin: "0 auto", textAlign: "center" }, children: [
630
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: { marginBottom: 8 }, children: p.title }),
631
- p.subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: p.subtitle }),
632
- /* @__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: [
633
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { "aria-hidden": true, style: { marginRight: 8 }, children: "\u2713" }),
634
- /* @__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 })
635
670
  ] }, b)) }),
636
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { textAlign: "left", marginBottom: 16 }, children: [
637
- /* @__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)" }),
638
- /* @__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)(
639
674
  "input",
640
675
  {
641
676
  "data-testid": "paywall-cpf",
@@ -648,8 +683,8 @@ function DefaultPaywall() {
648
683
  }
649
684
  )
650
685
  ] }),
651
- error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: error.message }),
652
- /* @__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)(
653
688
  "button",
654
689
  {
655
690
  "data-testid": "paywall-cta",
@@ -670,13 +705,107 @@ function DefaultPaywall() {
670
705
  children: opening ? "Abrindo..." : p.cta
671
706
  }
672
707
  ),
673
- p.priceHint && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { opacity: 0.6, marginTop: 12 }, children: p.priceHint }),
674
- 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 })
675
710
  ] });
676
711
  }
677
712
 
678
713
  // src/AppRoot.tsx
679
- 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];
716
+ function PaymentReturnHandler({ children }) {
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");
725
+ let attempts = 0;
726
+ const tick = async () => {
727
+ if (runIdRef.current !== runId) return;
728
+ attempts++;
729
+ try {
730
+ await subRef.current.refresh();
731
+ } catch {
732
+ }
733
+ if (runIdRef.current !== runId) return;
734
+ const status = subRef.current.status();
735
+ if (status === "active" || status === "trialing") {
736
+ const cleanUrl = new URL(window.location.href);
737
+ cleanUrl.searchParams.delete("paymentReturn");
738
+ window.history.replaceState({}, "", cleanUrl.toString());
739
+ setState("idle");
740
+ return;
741
+ }
742
+ const delay = BACKOFF_MS[attempts - 1];
743
+ if (delay === void 0) {
744
+ setState("waiting");
745
+ return;
746
+ }
747
+ setTimeout(tick, delay);
748
+ };
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();
756
+ return () => {
757
+ runIdRef.current++;
758
+ };
759
+ }, [runPoll]);
760
+ if (state === "confirming") {
761
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
762
+ "div",
763
+ {
764
+ role: "status",
765
+ "aria-live": "polite",
766
+ style: overlayStyle,
767
+ children: "Confirmando pagamento\u2026"
768
+ }
769
+ );
770
+ }
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 });
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
+ };
680
809
  function AppRoot({
681
810
  config,
682
811
  children,
@@ -686,29 +815,29 @@ function AppRoot({
686
815
  Reset = DefaultResetScreen,
687
816
  Paywall = DefaultPaywall
688
817
  }) {
689
- return /* @__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: [
690
819
  children,
691
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PushPrompt, {})
692
- ] }) }) }) }) });
820
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(PushPrompt, {})
821
+ ] }) }) }) }) }) }) });
693
822
  }
694
823
 
695
824
  // src/defaults/EmptyState.tsx
696
- var import_jsx_runtime13 = require("react/jsx-runtime");
825
+ var import_jsx_runtime14 = require("react/jsx-runtime");
697
826
  function EmptyState({ title, description, action }) {
698
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
699
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
700
- description && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: { opacity: 0.7 }, children: description }),
701
- 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 })
702
831
  ] });
703
832
  }
704
833
 
705
834
  // src/hooks/useAuthPrimitives.ts
706
- var import_react10 = require("react");
707
- var import_sdk8 = require("@hook-sdk/sdk");
835
+ var import_react12 = require("react");
836
+ var import_sdk10 = require("@hook-sdk/sdk");
708
837
  var warned = false;
709
838
  function useAuthPrimitives() {
710
- const { auth } = (0, import_sdk8.useHook)();
711
- (0, import_react10.useEffect)(() => {
839
+ const { auth } = (0, import_sdk10.useHook)();
840
+ (0, import_react12.useEffect)(() => {
712
841
  if (!warned && process.env.NODE_ENV !== "production") {
713
842
  warned = true;
714
843
  console.warn(
@@ -730,18 +859,18 @@ function useAuthPrimitives() {
730
859
  }
731
860
 
732
861
  // src/hooks/useSubscription.ts
733
- var import_sdk9 = require("@hook-sdk/sdk");
862
+ var import_sdk11 = require("@hook-sdk/sdk");
734
863
  function useSubscription() {
735
- const { subscription } = (0, import_sdk9.useHook)();
864
+ const { subscription } = (0, import_sdk11.useHook)();
736
865
  return {
737
866
  status: subscription.status()
738
867
  };
739
868
  }
740
869
 
741
870
  // src/hooks/usePush.ts
742
- var import_sdk10 = require("@hook-sdk/sdk");
871
+ var import_sdk12 = require("@hook-sdk/sdk");
743
872
  function usePush() {
744
- const { push } = (0, import_sdk10.useHook)();
873
+ const { push } = (0, import_sdk12.useHook)();
745
874
  return {
746
875
  status: push.status(),
747
876
  subscribe: push.subscribe,
@@ -750,17 +879,17 @@ function usePush() {
750
879
  }
751
880
 
752
881
  // src/hooks/useToast.ts
753
- var import_react11 = require("react");
882
+ var import_react13 = require("react");
754
883
  function useToast() {
755
- const [items, setItems] = (0, import_react11.useState)([]);
756
- const show = (0, import_react11.useCallback)((message, kind = "info") => {
884
+ const [items, setItems] = (0, import_react13.useState)([]);
885
+ const show = (0, import_react13.useCallback)((message, kind = "info") => {
757
886
  const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
758
887
  setItems((prev) => [...prev, { id, message, kind }]);
759
888
  setTimeout(() => {
760
889
  setItems((prev) => prev.filter((t) => t.id !== id));
761
890
  }, 4e3);
762
891
  }, []);
763
- const dismiss = (0, import_react11.useCallback)((id) => {
892
+ const dismiss = (0, import_react13.useCallback)((id) => {
764
893
  setItems((prev) => prev.filter((t) => t.id !== id));
765
894
  }, []);
766
895
  return { items, show, dismiss };