@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/README.md +51 -0
- package/dist/index.cjs +297 -168
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -4
- package/dist/index.d.ts +27 -4
- package/dist/index.js +243 -114
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
// src/AppRoot.tsx
|
|
2
|
+
import { useCallback as useCallback6, useEffect as useEffect4, useRef, useState as useState8 } from "react";
|
|
3
|
+
import { useHook as useHook8 } from "@hook-sdk/sdk";
|
|
4
|
+
|
|
1
5
|
// src/internal/TemplateConfigContext.tsx
|
|
2
|
-
import { createContext, useContext } from "react";
|
|
6
|
+
import { createContext, useContext, useMemo } from "react";
|
|
3
7
|
import { jsx } from "react/jsx-runtime";
|
|
4
8
|
var TemplateConfigContext = createContext(null);
|
|
5
9
|
function TemplateConfigProvider({
|
|
6
10
|
config,
|
|
7
11
|
children
|
|
8
12
|
}) {
|
|
9
|
-
|
|
13
|
+
const value = useMemo(() => ({
|
|
14
|
+
...config,
|
|
15
|
+
mode: config.subscription?.mode ?? "trial"
|
|
16
|
+
}), [config]);
|
|
17
|
+
return /* @__PURE__ */ jsx(TemplateConfigContext.Provider, { value, children });
|
|
10
18
|
}
|
|
11
19
|
function useTemplateConfig() {
|
|
12
20
|
const ctx = useContext(TemplateConfigContext);
|
|
@@ -122,14 +130,35 @@ function usePaywallState() {
|
|
|
122
130
|
|
|
123
131
|
// src/internal/SubscriptionGate.tsx
|
|
124
132
|
import { Fragment as Fragment2, jsx as jsx5 } from "react/jsx-runtime";
|
|
133
|
+
var BLOCKING = /* @__PURE__ */ new Set([
|
|
134
|
+
"pending",
|
|
135
|
+
"expired",
|
|
136
|
+
"canceled",
|
|
137
|
+
"none"
|
|
138
|
+
]);
|
|
125
139
|
function SubscriptionGate({ Paywall, children }) {
|
|
140
|
+
const { mode } = useTemplateConfig();
|
|
126
141
|
const { status } = usePaywallState();
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
}
|
|
142
|
+
if (mode === "free") return /* @__PURE__ */ jsx5(Fragment2, { children });
|
|
143
|
+
if (BLOCKING.has(status)) return /* @__PURE__ */ jsx5(Paywall, {});
|
|
130
144
|
return /* @__PURE__ */ jsx5(Fragment2, { children });
|
|
131
145
|
}
|
|
132
146
|
|
|
147
|
+
// src/internal/PersistedKeysPrefetch.tsx
|
|
148
|
+
import { useEffect as useEffect2 } from "react";
|
|
149
|
+
import { useHook as useHook3 } from "@hook-sdk/sdk";
|
|
150
|
+
import { Fragment as Fragment3, jsx as jsx6 } from "react/jsx-runtime";
|
|
151
|
+
function PersistedKeysPrefetch({ children }) {
|
|
152
|
+
const { appData } = useHook3();
|
|
153
|
+
const config = useTemplateConfig();
|
|
154
|
+
useEffect2(() => {
|
|
155
|
+
const keys = config.persistedKeys;
|
|
156
|
+
if (!keys || keys.length === 0) return;
|
|
157
|
+
appData.cache.startPrefetch(keys, (ks) => appData.bulkRead(ks));
|
|
158
|
+
}, [appData, config.persistedKeys]);
|
|
159
|
+
return /* @__PURE__ */ jsx6(Fragment3, { children });
|
|
160
|
+
}
|
|
161
|
+
|
|
133
162
|
// src/internal/PushPrompt.tsx
|
|
134
163
|
function PushPrompt() {
|
|
135
164
|
return null;
|
|
@@ -137,7 +166,7 @@ function PushPrompt() {
|
|
|
137
166
|
|
|
138
167
|
// src/defaults/ErrorBoundary.tsx
|
|
139
168
|
import { Component } from "react";
|
|
140
|
-
import { Fragment as
|
|
169
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs } from "react/jsx-runtime";
|
|
141
170
|
var ErrorBoundary = class extends Component {
|
|
142
171
|
state = { error: null };
|
|
143
172
|
static getDerivedStateFromError(error) {
|
|
@@ -149,17 +178,17 @@ var ErrorBoundary = class extends Component {
|
|
|
149
178
|
render() {
|
|
150
179
|
if (this.state.error) {
|
|
151
180
|
return this.props.fallback ?? /* @__PURE__ */ jsxs("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
|
|
152
|
-
/* @__PURE__ */
|
|
153
|
-
/* @__PURE__ */
|
|
181
|
+
/* @__PURE__ */ jsx7("h2", { children: "Algo deu errado" }),
|
|
182
|
+
/* @__PURE__ */ jsx7("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
|
|
154
183
|
] });
|
|
155
184
|
}
|
|
156
|
-
return /* @__PURE__ */
|
|
185
|
+
return /* @__PURE__ */ jsx7(Fragment4, { children: this.props.children });
|
|
157
186
|
}
|
|
158
187
|
};
|
|
159
188
|
|
|
160
189
|
// src/hooks/useLoginForm.ts
|
|
161
|
-
import { useCallback as useCallback2, useMemo, useState as useState3 } from "react";
|
|
162
|
-
import { useHook as
|
|
190
|
+
import { useCallback as useCallback2, useMemo as useMemo2, useState as useState3 } from "react";
|
|
191
|
+
import { useHook as useHook4 } from "@hook-sdk/sdk";
|
|
163
192
|
|
|
164
193
|
// src/errors.ts
|
|
165
194
|
import { SdkError, SdkAuthError, SdkRateLimitError } from "@hook-sdk/sdk";
|
|
@@ -194,30 +223,32 @@ function mapSdkError(err) {
|
|
|
194
223
|
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
195
224
|
var MIN_PASSWORD = 8;
|
|
196
225
|
function useLoginForm() {
|
|
197
|
-
const { auth } =
|
|
226
|
+
const { auth } = useHook4();
|
|
198
227
|
const [email, setEmail] = useState3("");
|
|
199
228
|
const [password, setPassword] = useState3("");
|
|
200
229
|
const [submitting, setSubmitting] = useState3(false);
|
|
201
230
|
const [error, setError] = useState3(null);
|
|
202
|
-
const emailError =
|
|
231
|
+
const emailError = useMemo2(() => {
|
|
203
232
|
if (email.length === 0) return null;
|
|
204
233
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
205
234
|
return null;
|
|
206
235
|
}, [email]);
|
|
207
|
-
const passwordError =
|
|
236
|
+
const passwordError = useMemo2(() => {
|
|
208
237
|
if (password.length === 0) return null;
|
|
209
238
|
if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
|
|
210
239
|
return null;
|
|
211
240
|
}, [password]);
|
|
212
241
|
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && emailError === null && passwordError === null && !submitting;
|
|
213
242
|
const submit = useCallback2(async () => {
|
|
214
|
-
if (!canSubmit) return;
|
|
243
|
+
if (!canSubmit) return false;
|
|
215
244
|
setSubmitting(true);
|
|
216
245
|
setError(null);
|
|
217
246
|
try {
|
|
218
247
|
await auth.login({ email, password });
|
|
248
|
+
return true;
|
|
219
249
|
} catch (err) {
|
|
220
250
|
setError(mapSdkError(err));
|
|
251
|
+
return false;
|
|
221
252
|
} finally {
|
|
222
253
|
setSubmitting(false);
|
|
223
254
|
}
|
|
@@ -237,20 +268,20 @@ function useLoginForm() {
|
|
|
237
268
|
}
|
|
238
269
|
|
|
239
270
|
// src/defaults/DefaultLoginScreen.tsx
|
|
240
|
-
import { jsx as
|
|
271
|
+
import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
241
272
|
function DefaultLoginScreen({ onNavigate }) {
|
|
242
273
|
const { name } = useTemplateConfig();
|
|
243
274
|
const f = useLoginForm();
|
|
244
275
|
return /* @__PURE__ */ jsxs2("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
245
|
-
/* @__PURE__ */
|
|
246
|
-
/* @__PURE__ */
|
|
276
|
+
/* @__PURE__ */ jsx8("h1", { style: { marginBottom: 8 }, children: name }),
|
|
277
|
+
/* @__PURE__ */ jsx8("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Entre na sua conta" }),
|
|
247
278
|
/* @__PURE__ */ jsxs2("form", { onSubmit: (e) => {
|
|
248
279
|
e.preventDefault();
|
|
249
280
|
void f.submit();
|
|
250
281
|
}, children: [
|
|
251
282
|
/* @__PURE__ */ jsxs2("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
252
283
|
"E-mail",
|
|
253
|
-
/* @__PURE__ */
|
|
284
|
+
/* @__PURE__ */ jsx8(
|
|
254
285
|
"input",
|
|
255
286
|
{
|
|
256
287
|
"data-testid": "login-email",
|
|
@@ -260,11 +291,11 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
260
291
|
style: { display: "block", width: "100%" }
|
|
261
292
|
}
|
|
262
293
|
),
|
|
263
|
-
f.emailError && /* @__PURE__ */
|
|
294
|
+
f.emailError && /* @__PURE__ */ jsx8("small", { style: { color: "#c00" }, children: f.emailError })
|
|
264
295
|
] }),
|
|
265
296
|
/* @__PURE__ */ jsxs2("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
266
297
|
"Senha",
|
|
267
|
-
/* @__PURE__ */
|
|
298
|
+
/* @__PURE__ */ jsx8(
|
|
268
299
|
"input",
|
|
269
300
|
{
|
|
270
301
|
"data-testid": "login-password",
|
|
@@ -274,10 +305,10 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
274
305
|
style: { display: "block", width: "100%" }
|
|
275
306
|
}
|
|
276
307
|
),
|
|
277
|
-
f.passwordError && /* @__PURE__ */
|
|
308
|
+
f.passwordError && /* @__PURE__ */ jsx8("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
278
309
|
] }),
|
|
279
|
-
f.error && /* @__PURE__ */
|
|
280
|
-
/* @__PURE__ */
|
|
310
|
+
f.error && /* @__PURE__ */ jsx8("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
311
|
+
/* @__PURE__ */ jsx8(
|
|
281
312
|
"button",
|
|
282
313
|
{
|
|
283
314
|
"data-testid": "login-submit",
|
|
@@ -297,48 +328,50 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
297
328
|
)
|
|
298
329
|
] }),
|
|
299
330
|
/* @__PURE__ */ jsxs2("div", { style: { marginTop: 16, display: "flex", justifyContent: "space-between" }, children: [
|
|
300
|
-
/* @__PURE__ */
|
|
301
|
-
/* @__PURE__ */
|
|
331
|
+
/* @__PURE__ */ jsx8("button", { "data-testid": "login-goto-signup", type: "button", onClick: () => onNavigate("signup"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Criar conta" }),
|
|
332
|
+
/* @__PURE__ */ jsx8("button", { "data-testid": "login-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Esqueci senha" })
|
|
302
333
|
] })
|
|
303
334
|
] });
|
|
304
335
|
}
|
|
305
336
|
|
|
306
337
|
// src/hooks/useSignupForm.ts
|
|
307
|
-
import { useCallback as useCallback3, useMemo as
|
|
308
|
-
import { useHook as
|
|
338
|
+
import { useCallback as useCallback3, useMemo as useMemo3, useState as useState4 } from "react";
|
|
339
|
+
import { useHook as useHook5 } from "@hook-sdk/sdk";
|
|
309
340
|
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
310
341
|
var MIN_PASSWORD2 = 8;
|
|
311
342
|
function useSignupForm() {
|
|
312
|
-
const { auth } =
|
|
343
|
+
const { auth } = useHook5();
|
|
313
344
|
const [name, setName] = useState4("");
|
|
314
345
|
const [email, setEmail] = useState4("");
|
|
315
346
|
const [password, setPassword] = useState4("");
|
|
316
347
|
const [submitting, setSubmitting] = useState4(false);
|
|
317
348
|
const [error, setError] = useState4(null);
|
|
318
|
-
const nameError =
|
|
349
|
+
const nameError = useMemo3(() => {
|
|
319
350
|
if (name.length === 0) return null;
|
|
320
351
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
321
352
|
return null;
|
|
322
353
|
}, [name]);
|
|
323
|
-
const emailError =
|
|
354
|
+
const emailError = useMemo3(() => {
|
|
324
355
|
if (email.length === 0) return null;
|
|
325
356
|
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
326
357
|
return null;
|
|
327
358
|
}, [email]);
|
|
328
|
-
const passwordError =
|
|
359
|
+
const passwordError = useMemo3(() => {
|
|
329
360
|
if (password.length === 0) return null;
|
|
330
361
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
331
362
|
return null;
|
|
332
363
|
}, [password]);
|
|
333
364
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && nameError === null && emailError === null && passwordError === null && !submitting;
|
|
334
365
|
const submit = useCallback3(async () => {
|
|
335
|
-
if (!canSubmit) return;
|
|
366
|
+
if (!canSubmit) return false;
|
|
336
367
|
setSubmitting(true);
|
|
337
368
|
setError(null);
|
|
338
369
|
try {
|
|
339
370
|
await auth.signup({ name, email, password });
|
|
371
|
+
return true;
|
|
340
372
|
} catch (err) {
|
|
341
373
|
setError(mapSdkError(err));
|
|
374
|
+
return false;
|
|
342
375
|
} finally {
|
|
343
376
|
setSubmitting(false);
|
|
344
377
|
}
|
|
@@ -361,64 +394,66 @@ function useSignupForm() {
|
|
|
361
394
|
}
|
|
362
395
|
|
|
363
396
|
// src/defaults/DefaultSignupScreen.tsx
|
|
364
|
-
import { jsx as
|
|
397
|
+
import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
365
398
|
function DefaultSignupScreen({ onNavigate }) {
|
|
366
399
|
const { name } = useTemplateConfig();
|
|
367
400
|
const f = useSignupForm();
|
|
368
401
|
return /* @__PURE__ */ jsxs3("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
369
|
-
/* @__PURE__ */
|
|
370
|
-
/* @__PURE__ */
|
|
402
|
+
/* @__PURE__ */ jsx9("h1", { style: { marginBottom: 8 }, children: name }),
|
|
403
|
+
/* @__PURE__ */ jsx9("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Criar sua conta" }),
|
|
371
404
|
/* @__PURE__ */ jsxs3("form", { onSubmit: (e) => {
|
|
372
405
|
e.preventDefault();
|
|
373
406
|
void f.submit();
|
|
374
407
|
}, children: [
|
|
375
408
|
/* @__PURE__ */ jsxs3("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
376
409
|
"Nome",
|
|
377
|
-
/* @__PURE__ */
|
|
378
|
-
f.nameError && /* @__PURE__ */
|
|
410
|
+
/* @__PURE__ */ jsx9("input", { "data-testid": "signup-name", value: f.name, onChange: (e) => f.setName(e.target.value), style: { display: "block", width: "100%" } }),
|
|
411
|
+
f.nameError && /* @__PURE__ */ jsx9("small", { style: { color: "#c00" }, children: f.nameError })
|
|
379
412
|
] }),
|
|
380
413
|
/* @__PURE__ */ jsxs3("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
381
414
|
"E-mail",
|
|
382
|
-
/* @__PURE__ */
|
|
383
|
-
f.emailError && /* @__PURE__ */
|
|
415
|
+
/* @__PURE__ */ jsx9("input", { "data-testid": "signup-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
|
|
416
|
+
f.emailError && /* @__PURE__ */ jsx9("small", { style: { color: "#c00" }, children: f.emailError })
|
|
384
417
|
] }),
|
|
385
418
|
/* @__PURE__ */ jsxs3("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
386
419
|
"Senha",
|
|
387
|
-
/* @__PURE__ */
|
|
388
|
-
f.passwordError && /* @__PURE__ */
|
|
420
|
+
/* @__PURE__ */ jsx9("input", { "data-testid": "signup-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" } }),
|
|
421
|
+
f.passwordError && /* @__PURE__ */ jsx9("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
389
422
|
] }),
|
|
390
|
-
f.error && /* @__PURE__ */
|
|
391
|
-
/* @__PURE__ */
|
|
423
|
+
f.error && /* @__PURE__ */ jsx9("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
424
|
+
/* @__PURE__ */ jsx9("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" })
|
|
392
425
|
] }),
|
|
393
|
-
/* @__PURE__ */
|
|
426
|
+
/* @__PURE__ */ jsx9("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ jsx9("button", { "data-testid": "signup-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "J\xE1 tem conta? Entre" }) })
|
|
394
427
|
] });
|
|
395
428
|
}
|
|
396
429
|
|
|
397
430
|
// src/hooks/useForgotForm.ts
|
|
398
|
-
import { useCallback as useCallback4, useMemo as
|
|
399
|
-
import { useHook as
|
|
431
|
+
import { useCallback as useCallback4, useMemo as useMemo4, useState as useState5 } from "react";
|
|
432
|
+
import { useHook as useHook6 } from "@hook-sdk/sdk";
|
|
400
433
|
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
401
434
|
function useForgotForm() {
|
|
402
|
-
const { auth } =
|
|
435
|
+
const { auth } = useHook6();
|
|
403
436
|
const [email, setEmail] = useState5("");
|
|
404
437
|
const [submitting, setSubmitting] = useState5(false);
|
|
405
438
|
const [sent, setSent] = useState5(false);
|
|
406
439
|
const [error, setError] = useState5(null);
|
|
407
|
-
const emailError =
|
|
440
|
+
const emailError = useMemo4(() => {
|
|
408
441
|
if (email.length === 0) return null;
|
|
409
442
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
410
443
|
return null;
|
|
411
444
|
}, [email]);
|
|
412
445
|
const canSubmit = email.length > 0 && emailError === null && !submitting;
|
|
413
446
|
const submit = useCallback4(async () => {
|
|
414
|
-
if (!canSubmit) return;
|
|
447
|
+
if (!canSubmit) return false;
|
|
415
448
|
setSubmitting(true);
|
|
416
449
|
setError(null);
|
|
417
450
|
try {
|
|
418
451
|
await auth.forgot({ email });
|
|
419
452
|
setSent(true);
|
|
453
|
+
return true;
|
|
420
454
|
} catch (err) {
|
|
421
455
|
setError(mapSdkError(err));
|
|
456
|
+
return false;
|
|
422
457
|
} finally {
|
|
423
458
|
setSubmitting(false);
|
|
424
459
|
}
|
|
@@ -436,60 +471,60 @@ function useForgotForm() {
|
|
|
436
471
|
}
|
|
437
472
|
|
|
438
473
|
// src/defaults/DefaultForgotScreen.tsx
|
|
439
|
-
import { jsx as
|
|
474
|
+
import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
440
475
|
function DefaultForgotScreen({ onNavigate }) {
|
|
441
476
|
const { name } = useTemplateConfig();
|
|
442
477
|
const f = useForgotForm();
|
|
443
478
|
if (f.sent) {
|
|
444
479
|
return /* @__PURE__ */ jsxs4("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
445
|
-
/* @__PURE__ */
|
|
446
|
-
/* @__PURE__ */
|
|
447
|
-
/* @__PURE__ */
|
|
480
|
+
/* @__PURE__ */ jsx10("h1", { children: "Verifique seu e-mail" }),
|
|
481
|
+
/* @__PURE__ */ jsx10("p", { style: { opacity: 0.7 }, children: "Enviamos um link pra redefinir sua senha." }),
|
|
482
|
+
/* @__PURE__ */ jsx10("button", { "data-testid": "forgot-back-login", type: "button", onClick: () => onNavigate("login"), children: "Voltar pro login" })
|
|
448
483
|
] });
|
|
449
484
|
}
|
|
450
485
|
return /* @__PURE__ */ jsxs4("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
451
|
-
/* @__PURE__ */
|
|
452
|
-
/* @__PURE__ */
|
|
486
|
+
/* @__PURE__ */ jsx10("h1", { style: { marginBottom: 8 }, children: name }),
|
|
487
|
+
/* @__PURE__ */ jsx10("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Redefinir senha" }),
|
|
453
488
|
/* @__PURE__ */ jsxs4("form", { onSubmit: (e) => {
|
|
454
489
|
e.preventDefault();
|
|
455
490
|
void f.submit();
|
|
456
491
|
}, children: [
|
|
457
492
|
/* @__PURE__ */ jsxs4("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
458
493
|
"E-mail",
|
|
459
|
-
/* @__PURE__ */
|
|
460
|
-
f.emailError && /* @__PURE__ */
|
|
494
|
+
/* @__PURE__ */ jsx10("input", { "data-testid": "forgot-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
|
|
495
|
+
f.emailError && /* @__PURE__ */ jsx10("small", { style: { color: "#c00" }, children: f.emailError })
|
|
461
496
|
] }),
|
|
462
|
-
f.error && /* @__PURE__ */
|
|
463
|
-
/* @__PURE__ */
|
|
497
|
+
f.error && /* @__PURE__ */ jsx10("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
498
|
+
/* @__PURE__ */ jsx10("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" })
|
|
464
499
|
] }),
|
|
465
|
-
/* @__PURE__ */
|
|
500
|
+
/* @__PURE__ */ jsx10("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ jsx10("button", { "data-testid": "forgot-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Voltar pro login" }) })
|
|
466
501
|
] });
|
|
467
502
|
}
|
|
468
503
|
|
|
469
504
|
// src/hooks/useResetForm.ts
|
|
470
|
-
import { useCallback as useCallback5, useEffect as
|
|
471
|
-
import { useHook as
|
|
505
|
+
import { useCallback as useCallback5, useEffect as useEffect3, useMemo as useMemo5, useState as useState6 } from "react";
|
|
506
|
+
import { useHook as useHook7 } from "@hook-sdk/sdk";
|
|
472
507
|
var MIN_PASSWORD3 = 12;
|
|
473
508
|
function useResetForm() {
|
|
474
|
-
const { auth } =
|
|
509
|
+
const { auth } = useHook7();
|
|
475
510
|
const [token, setToken] = useState6(null);
|
|
476
511
|
const [password, setPassword] = useState6("");
|
|
477
512
|
const [confirm, setConfirm] = useState6("");
|
|
478
513
|
const [submitting, setSubmitting] = useState6(false);
|
|
479
514
|
const [done, setDone] = useState6(false);
|
|
480
515
|
const [error, setError] = useState6(null);
|
|
481
|
-
|
|
516
|
+
useEffect3(() => {
|
|
482
517
|
if (typeof window === "undefined") return;
|
|
483
518
|
const params = new URLSearchParams(window.location.search);
|
|
484
519
|
const t = params.get("token");
|
|
485
520
|
setToken(t && t.length > 0 ? t : null);
|
|
486
521
|
}, []);
|
|
487
|
-
const passwordError =
|
|
522
|
+
const passwordError = useMemo5(() => {
|
|
488
523
|
if (password.length === 0) return null;
|
|
489
524
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
490
525
|
return null;
|
|
491
526
|
}, [password]);
|
|
492
|
-
const confirmError =
|
|
527
|
+
const confirmError = useMemo5(() => {
|
|
493
528
|
if (confirm.length === 0) return null;
|
|
494
529
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
495
530
|
return null;
|
|
@@ -531,50 +566,50 @@ function useResetForm() {
|
|
|
531
566
|
}
|
|
532
567
|
|
|
533
568
|
// src/defaults/DefaultResetScreen.tsx
|
|
534
|
-
import { jsx as
|
|
569
|
+
import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
535
570
|
function DefaultResetScreen({ onNavigate }) {
|
|
536
571
|
const { name } = useTemplateConfig();
|
|
537
572
|
const f = useResetForm();
|
|
538
573
|
if (f.done) {
|
|
539
574
|
return /* @__PURE__ */ jsxs5("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
540
|
-
/* @__PURE__ */
|
|
541
|
-
/* @__PURE__ */
|
|
542
|
-
/* @__PURE__ */
|
|
575
|
+
/* @__PURE__ */ jsx11("h1", { children: "Senha alterada" }),
|
|
576
|
+
/* @__PURE__ */ jsx11("p", { style: { opacity: 0.7 }, children: "Agora \xE9 s\xF3 fazer login com a nova senha." }),
|
|
577
|
+
/* @__PURE__ */ jsx11("button", { "data-testid": "reset-back-login", type: "button", onClick: () => onNavigate("login"), children: "Ir pro login" })
|
|
543
578
|
] });
|
|
544
579
|
}
|
|
545
580
|
if (f.token === null) {
|
|
546
581
|
return /* @__PURE__ */ jsxs5("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
547
|
-
/* @__PURE__ */
|
|
548
|
-
/* @__PURE__ */
|
|
549
|
-
/* @__PURE__ */
|
|
582
|
+
/* @__PURE__ */ jsx11("h1", { children: "Link inv\xE1lido" }),
|
|
583
|
+
/* @__PURE__ */ jsx11("p", { style: { opacity: 0.7 }, children: "Pe\xE7a um novo link de reset." }),
|
|
584
|
+
/* @__PURE__ */ jsx11("button", { "data-testid": "reset-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), children: "Pedir novo link" })
|
|
550
585
|
] });
|
|
551
586
|
}
|
|
552
587
|
return /* @__PURE__ */ jsxs5("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
553
|
-
/* @__PURE__ */
|
|
554
|
-
/* @__PURE__ */
|
|
588
|
+
/* @__PURE__ */ jsx11("h1", { style: { marginBottom: 8 }, children: name }),
|
|
589
|
+
/* @__PURE__ */ jsx11("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Escolha uma nova senha" }),
|
|
555
590
|
/* @__PURE__ */ jsxs5("form", { onSubmit: (e) => {
|
|
556
591
|
e.preventDefault();
|
|
557
592
|
void f.submit();
|
|
558
593
|
}, children: [
|
|
559
594
|
/* @__PURE__ */ jsxs5("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
560
595
|
"Nova senha",
|
|
561
|
-
/* @__PURE__ */
|
|
562
|
-
f.passwordError && /* @__PURE__ */
|
|
596
|
+
/* @__PURE__ */ jsx11("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" }),
|
|
597
|
+
f.passwordError && /* @__PURE__ */ jsx11("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
563
598
|
] }),
|
|
564
599
|
/* @__PURE__ */ jsxs5("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
565
600
|
"Confirmar senha",
|
|
566
|
-
/* @__PURE__ */
|
|
567
|
-
f.confirmError && /* @__PURE__ */
|
|
601
|
+
/* @__PURE__ */ jsx11("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" }),
|
|
602
|
+
f.confirmError && /* @__PURE__ */ jsx11("small", { style: { color: "#c00" }, children: f.confirmError })
|
|
568
603
|
] }),
|
|
569
|
-
f.error && /* @__PURE__ */
|
|
570
|
-
/* @__PURE__ */
|
|
604
|
+
f.error && /* @__PURE__ */ jsx11("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
605
|
+
/* @__PURE__ */ jsx11("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" })
|
|
571
606
|
] })
|
|
572
607
|
] });
|
|
573
608
|
}
|
|
574
609
|
|
|
575
610
|
// src/defaults/DefaultPaywall.tsx
|
|
576
611
|
import { useState as useState7 } from "react";
|
|
577
|
-
import { jsx as
|
|
612
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
578
613
|
function DefaultPaywall() {
|
|
579
614
|
const config = useTemplateConfig();
|
|
580
615
|
const { checkout, opening, error } = usePaywallState();
|
|
@@ -583,15 +618,15 @@ function DefaultPaywall() {
|
|
|
583
618
|
const cpfDigits = cpf.replace(/\D/g, "");
|
|
584
619
|
const canCheckout = cpfDigits.length === 11 && !opening;
|
|
585
620
|
return /* @__PURE__ */ jsxs6("main", { style: { padding: 24, maxWidth: 440, margin: "0 auto", textAlign: "center" }, children: [
|
|
586
|
-
/* @__PURE__ */
|
|
587
|
-
p.subtitle && /* @__PURE__ */
|
|
588
|
-
/* @__PURE__ */
|
|
589
|
-
/* @__PURE__ */
|
|
590
|
-
/* @__PURE__ */
|
|
621
|
+
/* @__PURE__ */ jsx12("h1", { style: { marginBottom: 8 }, children: p.title }),
|
|
622
|
+
p.subtitle && /* @__PURE__ */ jsx12("p", { style: { opacity: 0.7, marginBottom: 24 }, children: p.subtitle }),
|
|
623
|
+
/* @__PURE__ */ jsx12("ul", { style: { listStyle: "none", padding: 0, textAlign: "left", marginBottom: 24 }, children: p.benefits.map((b) => /* @__PURE__ */ jsxs6("li", { style: { padding: "8px 0", display: "flex", alignItems: "center" }, children: [
|
|
624
|
+
/* @__PURE__ */ jsx12("span", { "aria-hidden": true, style: { marginRight: 8 }, children: "\u2713" }),
|
|
625
|
+
/* @__PURE__ */ jsx12("span", { children: b })
|
|
591
626
|
] }, b)) }),
|
|
592
627
|
/* @__PURE__ */ jsxs6("div", { style: { textAlign: "left", marginBottom: 16 }, children: [
|
|
593
|
-
/* @__PURE__ */
|
|
594
|
-
/* @__PURE__ */
|
|
628
|
+
/* @__PURE__ */ jsx12("label", { style: { display: "block", fontSize: 14, opacity: 0.7, marginBottom: 4 }, children: "Seu CPF (pra emiss\xE3o de recibo)" }),
|
|
629
|
+
/* @__PURE__ */ jsx12(
|
|
595
630
|
"input",
|
|
596
631
|
{
|
|
597
632
|
"data-testid": "paywall-cpf",
|
|
@@ -604,8 +639,8 @@ function DefaultPaywall() {
|
|
|
604
639
|
}
|
|
605
640
|
)
|
|
606
641
|
] }),
|
|
607
|
-
error && /* @__PURE__ */
|
|
608
|
-
/* @__PURE__ */
|
|
642
|
+
error && /* @__PURE__ */ jsx12("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: error.message }),
|
|
643
|
+
/* @__PURE__ */ jsx12(
|
|
609
644
|
"button",
|
|
610
645
|
{
|
|
611
646
|
"data-testid": "paywall-cta",
|
|
@@ -626,13 +661,107 @@ function DefaultPaywall() {
|
|
|
626
661
|
children: opening ? "Abrindo..." : p.cta
|
|
627
662
|
}
|
|
628
663
|
),
|
|
629
|
-
p.priceHint && /* @__PURE__ */
|
|
630
|
-
p.footerNote && /* @__PURE__ */
|
|
664
|
+
p.priceHint && /* @__PURE__ */ jsx12("p", { style: { opacity: 0.6, marginTop: 12 }, children: p.priceHint }),
|
|
665
|
+
p.footerNote && /* @__PURE__ */ jsx12("p", { style: { opacity: 0.5, marginTop: 16, fontSize: 12 }, children: p.footerNote })
|
|
631
666
|
] });
|
|
632
667
|
}
|
|
633
668
|
|
|
634
669
|
// src/AppRoot.tsx
|
|
635
|
-
import { jsx as
|
|
670
|
+
import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
671
|
+
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
672
|
+
function PaymentReturnHandler({ children }) {
|
|
673
|
+
const { subscription } = useHook8();
|
|
674
|
+
const subRef = useRef(subscription);
|
|
675
|
+
subRef.current = subscription;
|
|
676
|
+
const runIdRef = useRef(0);
|
|
677
|
+
const [state, setState] = useState8("idle");
|
|
678
|
+
const runPoll = useCallback6(() => {
|
|
679
|
+
const runId = ++runIdRef.current;
|
|
680
|
+
setState("confirming");
|
|
681
|
+
let attempts = 0;
|
|
682
|
+
const tick = async () => {
|
|
683
|
+
if (runIdRef.current !== runId) return;
|
|
684
|
+
attempts++;
|
|
685
|
+
try {
|
|
686
|
+
await subRef.current.refresh();
|
|
687
|
+
} catch {
|
|
688
|
+
}
|
|
689
|
+
if (runIdRef.current !== runId) return;
|
|
690
|
+
const status = subRef.current.status();
|
|
691
|
+
if (status === "active" || status === "trialing") {
|
|
692
|
+
const cleanUrl = new URL(window.location.href);
|
|
693
|
+
cleanUrl.searchParams.delete("paymentReturn");
|
|
694
|
+
window.history.replaceState({}, "", cleanUrl.toString());
|
|
695
|
+
setState("idle");
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
const delay = BACKOFF_MS[attempts - 1];
|
|
699
|
+
if (delay === void 0) {
|
|
700
|
+
setState("waiting");
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
setTimeout(tick, delay);
|
|
704
|
+
};
|
|
705
|
+
void tick();
|
|
706
|
+
}, []);
|
|
707
|
+
useEffect4(() => {
|
|
708
|
+
if (typeof window === "undefined") return;
|
|
709
|
+
const url = new URL(window.location.href);
|
|
710
|
+
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
711
|
+
runPoll();
|
|
712
|
+
return () => {
|
|
713
|
+
runIdRef.current++;
|
|
714
|
+
};
|
|
715
|
+
}, [runPoll]);
|
|
716
|
+
if (state === "confirming") {
|
|
717
|
+
return /* @__PURE__ */ jsx13(
|
|
718
|
+
"div",
|
|
719
|
+
{
|
|
720
|
+
role: "status",
|
|
721
|
+
"aria-live": "polite",
|
|
722
|
+
style: overlayStyle,
|
|
723
|
+
children: "Confirmando pagamento\u2026"
|
|
724
|
+
}
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
if (state === "waiting") {
|
|
728
|
+
return /* @__PURE__ */ jsx13("div", { role: "status", "aria-live": "polite", style: overlayStyle, children: /* @__PURE__ */ jsxs7("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
729
|
+
/* @__PURE__ */ jsx13("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
|
|
730
|
+
/* @__PURE__ */ jsx13(
|
|
731
|
+
"button",
|
|
732
|
+
{
|
|
733
|
+
type: "button",
|
|
734
|
+
onClick: runPoll,
|
|
735
|
+
style: buttonStyle,
|
|
736
|
+
children: "Atualizar"
|
|
737
|
+
}
|
|
738
|
+
)
|
|
739
|
+
] }) });
|
|
740
|
+
}
|
|
741
|
+
return /* @__PURE__ */ jsx13(Fragment5, { children });
|
|
742
|
+
}
|
|
743
|
+
var overlayStyle = {
|
|
744
|
+
position: "fixed",
|
|
745
|
+
inset: 0,
|
|
746
|
+
display: "flex",
|
|
747
|
+
alignItems: "center",
|
|
748
|
+
justifyContent: "center",
|
|
749
|
+
background: "rgba(0,0,0,0.4)",
|
|
750
|
+
zIndex: 9999,
|
|
751
|
+
color: "white",
|
|
752
|
+
fontSize: "1rem",
|
|
753
|
+
padding: 24
|
|
754
|
+
};
|
|
755
|
+
var buttonStyle = {
|
|
756
|
+
background: "white",
|
|
757
|
+
color: "black",
|
|
758
|
+
border: "none",
|
|
759
|
+
borderRadius: 8,
|
|
760
|
+
padding: "10px 24px",
|
|
761
|
+
fontSize: "1rem",
|
|
762
|
+
fontWeight: 600,
|
|
763
|
+
cursor: "pointer"
|
|
764
|
+
};
|
|
636
765
|
function AppRoot({
|
|
637
766
|
config,
|
|
638
767
|
children,
|
|
@@ -642,29 +771,29 @@ function AppRoot({
|
|
|
642
771
|
Reset = DefaultResetScreen,
|
|
643
772
|
Paywall = DefaultPaywall
|
|
644
773
|
}) {
|
|
645
|
-
return /* @__PURE__ */
|
|
774
|
+
return /* @__PURE__ */ jsx13(PaymentReturnHandler, { children: /* @__PURE__ */ jsx13(TemplateConfigProvider, { config, children: /* @__PURE__ */ jsx13(ErrorBoundary, { children: /* @__PURE__ */ jsx13(ThemeProvider, { children: /* @__PURE__ */ jsx13(AuthGate, { Login, Signup, Forgot, Reset, children: /* @__PURE__ */ jsx13(PersistedKeysPrefetch, { children: /* @__PURE__ */ jsxs7(SubscriptionGate, { Paywall, children: [
|
|
646
775
|
children,
|
|
647
|
-
/* @__PURE__ */
|
|
648
|
-
] }) }) }) }) });
|
|
776
|
+
/* @__PURE__ */ jsx13(PushPrompt, {})
|
|
777
|
+
] }) }) }) }) }) }) });
|
|
649
778
|
}
|
|
650
779
|
|
|
651
780
|
// src/defaults/EmptyState.tsx
|
|
652
|
-
import { jsx as
|
|
781
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
653
782
|
function EmptyState({ title, description, action }) {
|
|
654
783
|
return /* @__PURE__ */ jsxs8("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
655
|
-
/* @__PURE__ */
|
|
656
|
-
description && /* @__PURE__ */
|
|
657
|
-
action && /* @__PURE__ */
|
|
784
|
+
/* @__PURE__ */ jsx14("h2", { style: { marginBottom: 8 }, children: title }),
|
|
785
|
+
description && /* @__PURE__ */ jsx14("p", { style: { opacity: 0.7 }, children: description }),
|
|
786
|
+
action && /* @__PURE__ */ jsx14("div", { style: { marginTop: 16 }, children: action })
|
|
658
787
|
] });
|
|
659
788
|
}
|
|
660
789
|
|
|
661
790
|
// src/hooks/useAuthPrimitives.ts
|
|
662
|
-
import { useEffect as
|
|
663
|
-
import { useHook as
|
|
791
|
+
import { useEffect as useEffect5 } from "react";
|
|
792
|
+
import { useHook as useHook9 } from "@hook-sdk/sdk";
|
|
664
793
|
var warned = false;
|
|
665
794
|
function useAuthPrimitives() {
|
|
666
|
-
const { auth } =
|
|
667
|
-
|
|
795
|
+
const { auth } = useHook9();
|
|
796
|
+
useEffect5(() => {
|
|
668
797
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
669
798
|
warned = true;
|
|
670
799
|
console.warn(
|
|
@@ -686,18 +815,18 @@ function useAuthPrimitives() {
|
|
|
686
815
|
}
|
|
687
816
|
|
|
688
817
|
// src/hooks/useSubscription.ts
|
|
689
|
-
import { useHook as
|
|
818
|
+
import { useHook as useHook10 } from "@hook-sdk/sdk";
|
|
690
819
|
function useSubscription() {
|
|
691
|
-
const { subscription } =
|
|
820
|
+
const { subscription } = useHook10();
|
|
692
821
|
return {
|
|
693
822
|
status: subscription.status()
|
|
694
823
|
};
|
|
695
824
|
}
|
|
696
825
|
|
|
697
826
|
// src/hooks/usePush.ts
|
|
698
|
-
import { useHook as
|
|
827
|
+
import { useHook as useHook11 } from "@hook-sdk/sdk";
|
|
699
828
|
function usePush() {
|
|
700
|
-
const { push } =
|
|
829
|
+
const { push } = useHook11();
|
|
701
830
|
return {
|
|
702
831
|
status: push.status(),
|
|
703
832
|
subscribe: push.subscribe,
|
|
@@ -706,17 +835,17 @@ function usePush() {
|
|
|
706
835
|
}
|
|
707
836
|
|
|
708
837
|
// src/hooks/useToast.ts
|
|
709
|
-
import { useCallback as
|
|
838
|
+
import { useCallback as useCallback7, useState as useState9 } from "react";
|
|
710
839
|
function useToast() {
|
|
711
|
-
const [items, setItems] =
|
|
712
|
-
const show =
|
|
840
|
+
const [items, setItems] = useState9([]);
|
|
841
|
+
const show = useCallback7((message, kind = "info") => {
|
|
713
842
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
714
843
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
715
844
|
setTimeout(() => {
|
|
716
845
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
717
846
|
}, 4e3);
|
|
718
847
|
}, []);
|
|
719
|
-
const dismiss =
|
|
848
|
+
const dismiss = useCallback7((id) => {
|
|
720
849
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
721
850
|
}, []);
|
|
722
851
|
return { items, show, dismiss };
|