@hook-sdk/template 0.3.0 → 0.4.1
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 +1519 -206
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -1
- package/dist/index.d.ts +101 -1
- package/dist/index.js +1500 -197
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -28,11 +28,21 @@ __export(index_exports, {
|
|
|
28
28
|
DefaultSignupScreen: () => DefaultSignupScreen,
|
|
29
29
|
EmptyState: () => EmptyState,
|
|
30
30
|
ErrorBoundary: () => ErrorBoundary,
|
|
31
|
+
InstallGate: () => InstallGate,
|
|
32
|
+
InstallSplash: () => InstallSplash,
|
|
31
33
|
LoadingState: () => LoadingState,
|
|
32
34
|
PushPrompt: () => PushPrompt2,
|
|
35
|
+
detectAndroidBrowser: () => detectAndroidBrowser,
|
|
36
|
+
detectIOSBrowser: () => detectIOSBrowser,
|
|
37
|
+
detectInAppApp: () => detectInAppApp,
|
|
38
|
+
detectPlatform: () => detectPlatform,
|
|
39
|
+
detectStandalone: () => detectStandalone,
|
|
40
|
+
shouldBlockInstall: () => shouldBlockInstall,
|
|
41
|
+
shouldShowPermanentOption: () => shouldShowPermanentOption,
|
|
33
42
|
useAuth: () => useAuth,
|
|
34
43
|
useAuthPrimitives: () => useAuthPrimitives,
|
|
35
44
|
useForgotForm: () => useForgotForm,
|
|
45
|
+
useInstallPrompt: () => useInstallPrompt,
|
|
36
46
|
useLoginForm: () => useLoginForm,
|
|
37
47
|
usePaywallState: () => usePaywallState,
|
|
38
48
|
usePush: () => usePush,
|
|
@@ -45,7 +55,7 @@ __export(index_exports, {
|
|
|
45
55
|
module.exports = __toCommonJS(index_exports);
|
|
46
56
|
|
|
47
57
|
// src/AppRoot.tsx
|
|
48
|
-
var
|
|
58
|
+
var import_react16 = require("react");
|
|
49
59
|
var import_sdk9 = require("@hook-sdk/sdk");
|
|
50
60
|
|
|
51
61
|
// src/internal/TemplateConfigContext.tsx
|
|
@@ -210,10 +220,1303 @@ function PushPrompt() {
|
|
|
210
220
|
return null;
|
|
211
221
|
}
|
|
212
222
|
|
|
213
|
-
// src/
|
|
223
|
+
// src/components/InstallGate/InstallGate.tsx
|
|
224
|
+
var import_react8 = require("react");
|
|
225
|
+
|
|
226
|
+
// src/hooks/useInstallPrompt.ts
|
|
214
227
|
var import_react5 = require("react");
|
|
228
|
+
var IOS_RE = /iPad|iPhone|iPod/;
|
|
229
|
+
var IOS_NON_SAFARI_RE = /CriOS|FxiOS|EdgiOS/;
|
|
230
|
+
var ANDROID_RE = /Android/;
|
|
231
|
+
var IN_APP_RE = /Instagram|FBAN|FBAV|BytedanceWebview|TikTok|Line\/|Twitter|Snapchat|Pinterest|LinkedIn|WhatsApp|MicroMessenger|Telegram/i;
|
|
232
|
+
var PERMANENT_DISMISS_REPROMPT_DAYS = 14;
|
|
233
|
+
var SESSION_SKIPS_BEFORE_PERMANENT_OPTION = 2;
|
|
234
|
+
var storageKey = {
|
|
235
|
+
sessionSkip: (slug) => `install:${slug}:session-skip`,
|
|
236
|
+
dismissedAt: (slug) => `install:${slug}:dismissed-at`,
|
|
237
|
+
installedAt: (slug) => `install:${slug}:installed-at`,
|
|
238
|
+
skipCount: (slug) => `install:${slug}:skip-count`
|
|
239
|
+
};
|
|
240
|
+
function detectPlatform(ua) {
|
|
241
|
+
if (IN_APP_RE.test(ua)) return "in-app";
|
|
242
|
+
const isIOS = IOS_RE.test(ua);
|
|
243
|
+
if (isIOS) {
|
|
244
|
+
const isSafari = /Safari/.test(ua) && !IOS_NON_SAFARI_RE.test(ua);
|
|
245
|
+
return isSafari ? "ios-safari" : "ios-other";
|
|
246
|
+
}
|
|
247
|
+
if (ANDROID_RE.test(ua)) return "android";
|
|
248
|
+
return "desktop";
|
|
249
|
+
}
|
|
250
|
+
function detectIOSBrowser(ua) {
|
|
251
|
+
if (!IOS_RE.test(ua)) return null;
|
|
252
|
+
if (/CriOS/.test(ua)) return "chrome";
|
|
253
|
+
if (/FxiOS/.test(ua)) return "firefox";
|
|
254
|
+
if (/EdgiOS/.test(ua)) return "edge";
|
|
255
|
+
if (/Safari/.test(ua)) return "safari";
|
|
256
|
+
return "other";
|
|
257
|
+
}
|
|
258
|
+
function detectAndroidBrowser(ua) {
|
|
259
|
+
if (!ANDROID_RE.test(ua)) return null;
|
|
260
|
+
if (/EdgA/.test(ua)) return "edge";
|
|
261
|
+
if (/OPR|OPT/.test(ua)) return "opera";
|
|
262
|
+
if (/SamsungBrowser/.test(ua)) return "samsung";
|
|
263
|
+
if (/Firefox/.test(ua)) return "firefox";
|
|
264
|
+
if (/Chrome/.test(ua)) return "chrome";
|
|
265
|
+
return "other";
|
|
266
|
+
}
|
|
267
|
+
function detectInAppApp(ua) {
|
|
268
|
+
if (!IN_APP_RE.test(ua)) return null;
|
|
269
|
+
if (/Instagram/i.test(ua)) return "instagram";
|
|
270
|
+
if (/FBAN|FBAV/.test(ua)) return "facebook";
|
|
271
|
+
if (/BytedanceWebview|TikTok/i.test(ua)) return "tiktok";
|
|
272
|
+
if (/WhatsApp/i.test(ua)) return "whatsapp";
|
|
273
|
+
if (/Twitter/i.test(ua)) return "twitter";
|
|
274
|
+
if (/LinkedIn/i.test(ua)) return "linkedin";
|
|
275
|
+
if (/Telegram/i.test(ua)) return "telegram";
|
|
276
|
+
if (/Line\//i.test(ua)) return "line";
|
|
277
|
+
if (/Snapchat/i.test(ua)) return "snapchat";
|
|
278
|
+
if (/Pinterest/i.test(ua)) return "pinterest";
|
|
279
|
+
if (/MicroMessenger/i.test(ua)) return "wechat";
|
|
280
|
+
return "other";
|
|
281
|
+
}
|
|
282
|
+
function detectStandalone() {
|
|
283
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") {
|
|
284
|
+
return { installed: false, source: null };
|
|
285
|
+
}
|
|
286
|
+
const mm = window.matchMedia?.("(display-mode: standalone)");
|
|
287
|
+
if (mm?.matches) return { installed: true, source: "match_media" };
|
|
288
|
+
const fs = window.matchMedia?.("(display-mode: fullscreen)");
|
|
289
|
+
if (fs?.matches) return { installed: true, source: "match_media" };
|
|
290
|
+
if (navigator.standalone === true) return { installed: true, source: "navigator_standalone" };
|
|
291
|
+
return { installed: false, source: null };
|
|
292
|
+
}
|
|
293
|
+
function track(event, props) {
|
|
294
|
+
if (typeof window === "undefined") return;
|
|
295
|
+
window.posthog?.capture?.(event, props);
|
|
296
|
+
}
|
|
297
|
+
function pickVariant(state) {
|
|
298
|
+
if (state.isInstalled) return "none";
|
|
299
|
+
switch (state.platform) {
|
|
300
|
+
case "android":
|
|
301
|
+
return state.isInstallable ? "android-native" : "android-manual";
|
|
302
|
+
case "ios-safari":
|
|
303
|
+
return "ios-safari";
|
|
304
|
+
case "ios-other":
|
|
305
|
+
return "ios-other";
|
|
306
|
+
case "in-app":
|
|
307
|
+
return "in-app";
|
|
308
|
+
case "desktop":
|
|
309
|
+
return state.isInstallable ? "desktop" : "none";
|
|
310
|
+
default:
|
|
311
|
+
return "none";
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function safeStorage() {
|
|
315
|
+
if (typeof localStorage === "undefined") return null;
|
|
316
|
+
try {
|
|
317
|
+
localStorage.setItem("__install_probe", "1");
|
|
318
|
+
localStorage.removeItem("__install_probe");
|
|
319
|
+
return localStorage;
|
|
320
|
+
} catch {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function readPermanentDismiss(slug) {
|
|
325
|
+
const storage = safeStorage();
|
|
326
|
+
if (!storage) return { dismissed: false, dismissedAt: null };
|
|
327
|
+
const raw = storage.getItem(storageKey.dismissedAt(slug));
|
|
328
|
+
if (!raw) return { dismissed: false, dismissedAt: null };
|
|
329
|
+
const parsed = Date.parse(raw);
|
|
330
|
+
if (Number.isNaN(parsed)) return { dismissed: false, dismissedAt: null };
|
|
331
|
+
const daysAgo = (Date.now() - parsed) / (1e3 * 60 * 60 * 24);
|
|
332
|
+
return { dismissed: daysAgo < PERMANENT_DISMISS_REPROMPT_DAYS, dismissedAt: raw };
|
|
333
|
+
}
|
|
334
|
+
function readInstalledMarker(slug) {
|
|
335
|
+
const storage = safeStorage();
|
|
336
|
+
if (!storage) return false;
|
|
337
|
+
return storage.getItem(storageKey.installedAt(slug)) !== null;
|
|
338
|
+
}
|
|
339
|
+
function readSkipCount(slug) {
|
|
340
|
+
const storage = safeStorage();
|
|
341
|
+
if (!storage) return 0;
|
|
342
|
+
const raw = storage.getItem(storageKey.skipCount(slug));
|
|
343
|
+
const n = raw ? Number.parseInt(raw, 10) : 0;
|
|
344
|
+
return Number.isFinite(n) && n >= 0 ? n : 0;
|
|
345
|
+
}
|
|
346
|
+
function readSessionSkip(slug) {
|
|
347
|
+
if (typeof sessionStorage === "undefined") return false;
|
|
348
|
+
try {
|
|
349
|
+
return sessionStorage.getItem(storageKey.sessionSkip(slug)) === "true";
|
|
350
|
+
} catch {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function useInstallPrompt(slug) {
|
|
355
|
+
const ua = typeof navigator !== "undefined" && typeof navigator.userAgent === "string" ? navigator.userAgent : "";
|
|
356
|
+
const platform = detectPlatform(ua);
|
|
357
|
+
const iosBrowser = detectIOSBrowser(ua);
|
|
358
|
+
const androidBrowser = detectAndroidBrowser(ua);
|
|
359
|
+
const inAppApp = detectInAppApp(ua);
|
|
360
|
+
const [isInstallable, setIsInstallable] = (0, import_react5.useState)(() => {
|
|
361
|
+
if (typeof window === "undefined") return false;
|
|
362
|
+
return window.__pwaInstallPrompt != null;
|
|
363
|
+
});
|
|
364
|
+
const [isInstalled, setIsInstalled] = (0, import_react5.useState)(() => {
|
|
365
|
+
const { installed } = detectStandalone();
|
|
366
|
+
return installed || readInstalledMarker(slug);
|
|
367
|
+
});
|
|
368
|
+
const [isDismissedSession, setIsDismissedSession] = (0, import_react5.useState)(() => readSessionSkip(slug));
|
|
369
|
+
const [isDismissedPermanent, setIsDismissedPermanent] = (0, import_react5.useState)(() => readPermanentDismiss(slug).dismissed);
|
|
370
|
+
const [skipCount, setSkipCount] = (0, import_react5.useState)(() => readSkipCount(slug));
|
|
371
|
+
(0, import_react5.useEffect)(() => {
|
|
372
|
+
if (typeof window === "undefined") return;
|
|
373
|
+
if (window.__pwaInstallPrompt) {
|
|
374
|
+
setIsInstallable(true);
|
|
375
|
+
}
|
|
376
|
+
const onPrompt = (e) => {
|
|
377
|
+
e.preventDefault();
|
|
378
|
+
window.__pwaInstallPrompt = e;
|
|
379
|
+
setIsInstallable(true);
|
|
380
|
+
};
|
|
381
|
+
const onInstalled = () => {
|
|
382
|
+
setIsInstalled(true);
|
|
383
|
+
setIsInstallable(false);
|
|
384
|
+
window.__pwaInstallPrompt = null;
|
|
385
|
+
const storage = safeStorage();
|
|
386
|
+
if (storage) storage.setItem(storageKey.installedAt(slug), (/* @__PURE__ */ new Date()).toISOString());
|
|
387
|
+
};
|
|
388
|
+
window.addEventListener("beforeinstallprompt", onPrompt);
|
|
389
|
+
window.addEventListener("appinstalled", onInstalled);
|
|
390
|
+
return () => {
|
|
391
|
+
window.removeEventListener("beforeinstallprompt", onPrompt);
|
|
392
|
+
window.removeEventListener("appinstalled", onInstalled);
|
|
393
|
+
};
|
|
394
|
+
}, [slug]);
|
|
395
|
+
(0, import_react5.useEffect)(() => {
|
|
396
|
+
if (typeof window === "undefined") return;
|
|
397
|
+
const mq = window.matchMedia?.("(display-mode: standalone)");
|
|
398
|
+
if (!mq) return;
|
|
399
|
+
const handler = (e) => {
|
|
400
|
+
if (e.matches) {
|
|
401
|
+
setIsInstalled(true);
|
|
402
|
+
track("pwa_install_standalone_detected", { slug, source: "match_media" });
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
mq.addEventListener?.("change", handler);
|
|
406
|
+
return () => mq.removeEventListener?.("change", handler);
|
|
407
|
+
}, [slug]);
|
|
408
|
+
const variant = pickVariant({
|
|
409
|
+
platform,
|
|
410
|
+
iosBrowser,
|
|
411
|
+
androidBrowser,
|
|
412
|
+
inAppApp,
|
|
413
|
+
isInstallable,
|
|
414
|
+
isInstalled,
|
|
415
|
+
isDismissedSession,
|
|
416
|
+
isDismissedPermanent,
|
|
417
|
+
skipCount
|
|
418
|
+
});
|
|
419
|
+
const promptInstall = (0, import_react5.useCallback)(async () => {
|
|
420
|
+
if (typeof window === "undefined") return false;
|
|
421
|
+
const prompt = window.__pwaInstallPrompt;
|
|
422
|
+
if (!prompt) return false;
|
|
423
|
+
track("pwa_install_prompt_clicked", { slug });
|
|
424
|
+
try {
|
|
425
|
+
await prompt.prompt();
|
|
426
|
+
const { outcome } = await prompt.userChoice;
|
|
427
|
+
track("pwa_install_prompt_outcome", { slug, outcome });
|
|
428
|
+
if (outcome === "accepted") {
|
|
429
|
+
setIsInstalled(true);
|
|
430
|
+
setIsInstallable(false);
|
|
431
|
+
window.__pwaInstallPrompt = null;
|
|
432
|
+
const storage = safeStorage();
|
|
433
|
+
if (storage) storage.setItem(storageKey.installedAt(slug), (/* @__PURE__ */ new Date()).toISOString());
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
return false;
|
|
437
|
+
} catch {
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
}, [slug]);
|
|
441
|
+
const dismissSession = (0, import_react5.useCallback)(() => {
|
|
442
|
+
if (typeof sessionStorage !== "undefined") {
|
|
443
|
+
try {
|
|
444
|
+
sessionStorage.setItem(storageKey.sessionSkip(slug), "true");
|
|
445
|
+
} catch {
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const storage = safeStorage();
|
|
449
|
+
const newCount = skipCount + 1;
|
|
450
|
+
if (storage) storage.setItem(storageKey.skipCount(slug), String(newCount));
|
|
451
|
+
setSkipCount(newCount);
|
|
452
|
+
setIsDismissedSession(true);
|
|
453
|
+
track("pwa_install_session_skip", { slug, platform, skip_count: newCount });
|
|
454
|
+
}, [slug, skipCount, platform]);
|
|
455
|
+
const dismissPermanent = (0, import_react5.useCallback)(() => {
|
|
456
|
+
const storage = safeStorage();
|
|
457
|
+
if (storage) storage.setItem(storageKey.dismissedAt(slug), (/* @__PURE__ */ new Date()).toISOString());
|
|
458
|
+
setIsDismissedPermanent(true);
|
|
459
|
+
track("pwa_install_permanent_dismiss", { slug, platform, prior_skip_count: skipCount });
|
|
460
|
+
}, [slug, platform, skipCount]);
|
|
461
|
+
const showIOSOtherHelp = (0, import_react5.useCallback)(() => {
|
|
462
|
+
track("pwa_install_ios_other_help_shown", { slug });
|
|
463
|
+
}, [slug]);
|
|
464
|
+
const copyLink = (0, import_react5.useCallback)(async () => {
|
|
465
|
+
if (typeof navigator === "undefined" || typeof location === "undefined") return;
|
|
466
|
+
try {
|
|
467
|
+
await navigator.clipboard?.writeText?.(location.href);
|
|
468
|
+
} catch {
|
|
469
|
+
}
|
|
470
|
+
}, []);
|
|
471
|
+
const reset = (0, import_react5.useCallback)(() => {
|
|
472
|
+
const storage = safeStorage();
|
|
473
|
+
if (storage) {
|
|
474
|
+
storage.removeItem(storageKey.dismissedAt(slug));
|
|
475
|
+
storage.removeItem(storageKey.installedAt(slug));
|
|
476
|
+
storage.removeItem(storageKey.skipCount(slug));
|
|
477
|
+
}
|
|
478
|
+
if (typeof sessionStorage !== "undefined") {
|
|
479
|
+
try {
|
|
480
|
+
sessionStorage.removeItem(storageKey.sessionSkip(slug));
|
|
481
|
+
} catch {
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
setIsDismissedSession(false);
|
|
485
|
+
setIsDismissedPermanent(false);
|
|
486
|
+
setSkipCount(0);
|
|
487
|
+
}, [slug]);
|
|
488
|
+
return {
|
|
489
|
+
platform,
|
|
490
|
+
iosBrowser,
|
|
491
|
+
androidBrowser,
|
|
492
|
+
inAppApp,
|
|
493
|
+
isInstallable,
|
|
494
|
+
isInstalled,
|
|
495
|
+
isDismissedSession,
|
|
496
|
+
isDismissedPermanent,
|
|
497
|
+
skipCount,
|
|
498
|
+
variant,
|
|
499
|
+
promptInstall,
|
|
500
|
+
dismissSession,
|
|
501
|
+
dismissPermanent,
|
|
502
|
+
showIOSOtherHelp,
|
|
503
|
+
copyLink,
|
|
504
|
+
reset
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
function shouldBlockInstall(state, now = Date.now()) {
|
|
508
|
+
if (state.isInstalled) return false;
|
|
509
|
+
if (state.variant === "none") return false;
|
|
510
|
+
if (state.isDismissedSession) return false;
|
|
511
|
+
if (state.isDismissedPermanent) {
|
|
512
|
+
void now;
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
if (state.platform === "desktop" && !state.isInstallable) return false;
|
|
516
|
+
if (state.platform === "unknown") return false;
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
function shouldShowPermanentOption(state) {
|
|
520
|
+
return state.skipCount >= SESSION_SKIPS_BEFORE_PERMANENT_OPTION;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// src/components/InstallGate/copy.ts
|
|
524
|
+
var INSTALL_COPY = {
|
|
525
|
+
android: {
|
|
526
|
+
native: {
|
|
527
|
+
title: "Instale no seu celular",
|
|
528
|
+
subtitle: "Acesso r\xE1pido, sem precisar do navegador",
|
|
529
|
+
cta: "Baixar",
|
|
530
|
+
skip: "Continuar no navegador",
|
|
531
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
532
|
+
},
|
|
533
|
+
manual: {
|
|
534
|
+
title: "Instale em 2 toques",
|
|
535
|
+
subtitle: 'Toque no menu do navegador e escolha "Instalar aplicativo"',
|
|
536
|
+
step1: "Toque no menu do navegador",
|
|
537
|
+
step2: 'Escolha "Instalar aplicativo"',
|
|
538
|
+
cta: "Entendi",
|
|
539
|
+
skip: "Continuar no navegador",
|
|
540
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
iosSafari: {
|
|
544
|
+
title: "Adicione \xE0 sua Tela de In\xEDcio",
|
|
545
|
+
subtitle: "Siga os 3 passos",
|
|
546
|
+
step1: {
|
|
547
|
+
title: "Toque em Compartilhar",
|
|
548
|
+
subtitle: "Na barra inferior do Safari"
|
|
549
|
+
},
|
|
550
|
+
step2: {
|
|
551
|
+
title: 'Role e toque em "Adicionar \xE0 Tela de In\xEDcio"',
|
|
552
|
+
iconLabel: "Adicionar \xE0 Tela de In\xEDcio"
|
|
553
|
+
},
|
|
554
|
+
step3: {
|
|
555
|
+
title: 'Toque em "Adicionar" pra confirmar',
|
|
556
|
+
buttonLabel: "Adicionar"
|
|
557
|
+
},
|
|
558
|
+
skip: "Continuar no Safari",
|
|
559
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
560
|
+
},
|
|
561
|
+
iosOther: {
|
|
562
|
+
title: "Abra no Safari pra instalar",
|
|
563
|
+
subtitle: "No Chrome/Firefox/Edge do iPhone n\xE3o d\xE1 pra instalar PWA. Abra o link no Safari.",
|
|
564
|
+
ctaPrimary: "Abrir no Safari",
|
|
565
|
+
ctaSecondary: "Copiar link",
|
|
566
|
+
copiedToast: "Link copiado. Cole no Safari.",
|
|
567
|
+
skip: "Continuar mesmo assim",
|
|
568
|
+
skipPermanent: "N\xE3o me pergunte mais",
|
|
569
|
+
help: {
|
|
570
|
+
step1: {
|
|
571
|
+
title: "Toque em \u22EF ou no bot\xE3o compartilhar",
|
|
572
|
+
subtitle: "Na barra inferior ou superior do navegador"
|
|
573
|
+
},
|
|
574
|
+
step2: {
|
|
575
|
+
title: 'Escolha "Abrir no Safari"',
|
|
576
|
+
subtitle: "O app vai abrir direto no Safari"
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
inApp: {
|
|
581
|
+
instagram: {
|
|
582
|
+
title: "Pra instalar, abra fora do Instagram",
|
|
583
|
+
step1: "Toque em \u22EF (canto superior direito)",
|
|
584
|
+
step2: 'Escolha "Abrir no navegador externo"'
|
|
585
|
+
},
|
|
586
|
+
facebook: {
|
|
587
|
+
title: "Pra instalar, abra fora do Facebook",
|
|
588
|
+
step1: "Toque em \u22EE",
|
|
589
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
590
|
+
},
|
|
591
|
+
tiktok: {
|
|
592
|
+
title: "Pra instalar, abra fora do TikTok",
|
|
593
|
+
step1: "Toque em \u22EF",
|
|
594
|
+
step2: 'Escolha "Abrir no Safari" (iOS) ou "Abrir no Chrome" (Android)'
|
|
595
|
+
},
|
|
596
|
+
whatsapp: {
|
|
597
|
+
title: "Pra instalar, abra fora do WhatsApp",
|
|
598
|
+
step1: "Toque longo no link",
|
|
599
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
600
|
+
},
|
|
601
|
+
twitter: {
|
|
602
|
+
title: "Pra instalar, abra fora do Twitter",
|
|
603
|
+
step1: "Toque em \u22EF",
|
|
604
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
605
|
+
},
|
|
606
|
+
linkedin: {
|
|
607
|
+
title: "Pra instalar, abra fora do LinkedIn",
|
|
608
|
+
step1: "Toque em \u22EF",
|
|
609
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
610
|
+
},
|
|
611
|
+
telegram: {
|
|
612
|
+
title: "Pra instalar, abra fora do Telegram",
|
|
613
|
+
step1: "Toque em \u22EE",
|
|
614
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
615
|
+
},
|
|
616
|
+
line: {
|
|
617
|
+
title: "Pra instalar, abra fora do LINE",
|
|
618
|
+
step1: "Toque em \u22EF",
|
|
619
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
620
|
+
},
|
|
621
|
+
snapchat: {
|
|
622
|
+
title: "Pra instalar, abra fora do Snapchat",
|
|
623
|
+
step1: "Mantenha pressionado o link",
|
|
624
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
625
|
+
},
|
|
626
|
+
pinterest: {
|
|
627
|
+
title: "Pra instalar, abra fora do Pinterest",
|
|
628
|
+
step1: "Toque em \u22EF",
|
|
629
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
630
|
+
},
|
|
631
|
+
wechat: {
|
|
632
|
+
title: "Pra instalar, abra fora do WeChat",
|
|
633
|
+
step1: "Toque em \u22EF",
|
|
634
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
635
|
+
},
|
|
636
|
+
other: {
|
|
637
|
+
title: "Abra no navegador do celular",
|
|
638
|
+
step1: "Toque no menu do app atual",
|
|
639
|
+
step2: 'Escolha "Abrir no Chrome" ou "Abrir no Safari"'
|
|
640
|
+
},
|
|
641
|
+
copy: "Copiar link",
|
|
642
|
+
copiedToast: "Link copiado. Cole no Chrome/Safari.",
|
|
643
|
+
skip: "Continuar aqui mesmo",
|
|
644
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
645
|
+
},
|
|
646
|
+
desktop: {
|
|
647
|
+
title: "Instale no computador",
|
|
648
|
+
subtitle: "Acesso r\xE1pido",
|
|
649
|
+
cta: "Baixar",
|
|
650
|
+
close: "Fechar"
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
// src/components/InstallGate/InstallSplash.tsx
|
|
215
655
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
216
|
-
|
|
656
|
+
function InstallSplash({ children, title, subtitle }) {
|
|
657
|
+
const { name, theme } = useTemplateConfig();
|
|
658
|
+
const iconUrl = theme.icon_url || theme.logo_url || null;
|
|
659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
660
|
+
"div",
|
|
661
|
+
{
|
|
662
|
+
role: "dialog",
|
|
663
|
+
"aria-modal": "true",
|
|
664
|
+
"aria-labelledby": "install-splash-title",
|
|
665
|
+
"aria-describedby": subtitle ? "install-splash-subtitle" : void 0,
|
|
666
|
+
style: overlayStyle,
|
|
667
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: cardStyle, children: [
|
|
668
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", justifyContent: "center", marginBottom: 16 }, children: iconUrl ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
669
|
+
"img",
|
|
670
|
+
{
|
|
671
|
+
src: iconUrl,
|
|
672
|
+
alt: `\xCDcone de ${name}`,
|
|
673
|
+
style: { width: 80, height: 80, borderRadius: 20, objectFit: "cover" }
|
|
674
|
+
}
|
|
675
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
676
|
+
"div",
|
|
677
|
+
{
|
|
678
|
+
style: {
|
|
679
|
+
width: 80,
|
|
680
|
+
height: 80,
|
|
681
|
+
borderRadius: 20,
|
|
682
|
+
background: "var(--hook-color-primary)",
|
|
683
|
+
color: "#fff",
|
|
684
|
+
display: "flex",
|
|
685
|
+
alignItems: "center",
|
|
686
|
+
justifyContent: "center",
|
|
687
|
+
fontSize: 36,
|
|
688
|
+
fontWeight: 700
|
|
689
|
+
},
|
|
690
|
+
children: name.charAt(0).toUpperCase()
|
|
691
|
+
}
|
|
692
|
+
) }),
|
|
693
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { id: "install-splash-title", style: titleStyle, children: title }),
|
|
694
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { id: "install-splash-subtitle", style: subtitleStyle, children: subtitle }),
|
|
695
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { marginTop: 24 }, children }),
|
|
696
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: footerStyle, children: "por Hook" })
|
|
697
|
+
] })
|
|
698
|
+
}
|
|
699
|
+
);
|
|
700
|
+
}
|
|
701
|
+
var primaryButtonStyle = {
|
|
702
|
+
width: "100%",
|
|
703
|
+
padding: "14px 20px",
|
|
704
|
+
background: "var(--hook-color-primary)",
|
|
705
|
+
color: "#fff",
|
|
706
|
+
border: "none",
|
|
707
|
+
borderRadius: 999,
|
|
708
|
+
fontSize: 17,
|
|
709
|
+
fontWeight: 600,
|
|
710
|
+
cursor: "pointer",
|
|
711
|
+
marginBottom: 12
|
|
712
|
+
};
|
|
713
|
+
var secondaryButtonStyle = {
|
|
714
|
+
width: "100%",
|
|
715
|
+
padding: "12px 20px",
|
|
716
|
+
background: "transparent",
|
|
717
|
+
color: "var(--hook-color-primary)",
|
|
718
|
+
border: "1px solid var(--hook-color-primary)",
|
|
719
|
+
borderRadius: 999,
|
|
720
|
+
fontSize: 15,
|
|
721
|
+
fontWeight: 500,
|
|
722
|
+
cursor: "pointer",
|
|
723
|
+
marginBottom: 12
|
|
724
|
+
};
|
|
725
|
+
var skipLinkStyle = {
|
|
726
|
+
display: "block",
|
|
727
|
+
width: "100%",
|
|
728
|
+
padding: "10px",
|
|
729
|
+
marginTop: 8,
|
|
730
|
+
background: "transparent",
|
|
731
|
+
color: "#555",
|
|
732
|
+
border: "none",
|
|
733
|
+
fontSize: 14,
|
|
734
|
+
textDecoration: "underline",
|
|
735
|
+
cursor: "pointer",
|
|
736
|
+
textAlign: "center"
|
|
737
|
+
};
|
|
738
|
+
var skipPermanentLinkStyle = {
|
|
739
|
+
...skipLinkStyle,
|
|
740
|
+
color: "#999",
|
|
741
|
+
fontSize: 13,
|
|
742
|
+
marginTop: 4
|
|
743
|
+
};
|
|
744
|
+
var overlayStyle = {
|
|
745
|
+
position: "fixed",
|
|
746
|
+
inset: 0,
|
|
747
|
+
background: "var(--hook-color-background, #fafafa)",
|
|
748
|
+
zIndex: 1e4,
|
|
749
|
+
display: "flex",
|
|
750
|
+
alignItems: "center",
|
|
751
|
+
justifyContent: "center",
|
|
752
|
+
padding: 20,
|
|
753
|
+
overflow: "auto"
|
|
754
|
+
};
|
|
755
|
+
var cardStyle = {
|
|
756
|
+
width: "100%",
|
|
757
|
+
maxWidth: 420,
|
|
758
|
+
padding: 24,
|
|
759
|
+
textAlign: "center"
|
|
760
|
+
};
|
|
761
|
+
var titleStyle = {
|
|
762
|
+
fontSize: 24,
|
|
763
|
+
fontWeight: 700,
|
|
764
|
+
lineHeight: 1.2,
|
|
765
|
+
margin: "0 0 8px 0",
|
|
766
|
+
color: "#111"
|
|
767
|
+
};
|
|
768
|
+
var subtitleStyle = {
|
|
769
|
+
fontSize: 15,
|
|
770
|
+
lineHeight: 1.4,
|
|
771
|
+
color: "#555",
|
|
772
|
+
margin: 0
|
|
773
|
+
};
|
|
774
|
+
var footerStyle = {
|
|
775
|
+
fontSize: 11,
|
|
776
|
+
color: "#aaa",
|
|
777
|
+
marginTop: 32,
|
|
778
|
+
letterSpacing: 0.5
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
// src/components/InstallGate/icons.tsx
|
|
782
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
783
|
+
var defaultSvgProps = (size) => ({
|
|
784
|
+
width: size,
|
|
785
|
+
height: size,
|
|
786
|
+
viewBox: "0 0 24 24",
|
|
787
|
+
fill: "none",
|
|
788
|
+
stroke: "currentColor",
|
|
789
|
+
strokeWidth: 2,
|
|
790
|
+
strokeLinecap: "round",
|
|
791
|
+
strokeLinejoin: "round"
|
|
792
|
+
});
|
|
793
|
+
function ShareIconIOS({ size = 24, style, className }) {
|
|
794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
795
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 2L12 15" }),
|
|
796
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M8 6L12 2L16 6" }),
|
|
797
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M4 11v9a2 2 0 002 2h12a2 2 0 002-2v-9" })
|
|
798
|
+
] });
|
|
799
|
+
}
|
|
800
|
+
function MenuDotsVerticalIcon({ size = 24, style, className }) {
|
|
801
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "5", r: "1.5" }),
|
|
803
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "12", r: "1.5" }),
|
|
804
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "19", r: "1.5" })
|
|
805
|
+
] });
|
|
806
|
+
}
|
|
807
|
+
function MenuDotsHorizontalIcon({ size = 24, style, className }) {
|
|
808
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
809
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "5", cy: "12", r: "1.5" }),
|
|
810
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "12", cy: "12", r: "1.5" }),
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("circle", { cx: "19", cy: "12", r: "1.5" })
|
|
812
|
+
] });
|
|
813
|
+
}
|
|
814
|
+
function SquarePlusIcon({ size = 24, style, className }) {
|
|
815
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M12 8v8" }),
|
|
818
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M8 12h8" })
|
|
819
|
+
] });
|
|
820
|
+
}
|
|
821
|
+
function DownloadIcon({ size = 24, style, className }) {
|
|
822
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
823
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
|
|
824
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "7 10 12 15 17 10" }),
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
|
|
826
|
+
] });
|
|
827
|
+
}
|
|
828
|
+
function ExternalLinkIcon({ size = 24, style, className }) {
|
|
829
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6" }),
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("polyline", { points: "15 3 21 3 21 9" }),
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
|
|
833
|
+
] });
|
|
834
|
+
}
|
|
835
|
+
function XIcon({ size = 20, style, className }) {
|
|
836
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
837
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
838
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
839
|
+
] });
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// src/components/InstallGate/variants/AndroidNativeVariant.tsx
|
|
843
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
844
|
+
function AndroidNativeVariant({
|
|
845
|
+
state,
|
|
846
|
+
actions
|
|
847
|
+
}) {
|
|
848
|
+
const copy = INSTALL_COPY.android.native;
|
|
849
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
|
|
851
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
852
|
+
"button",
|
|
853
|
+
{
|
|
854
|
+
"data-testid": "install-prompt-cta-android-native",
|
|
855
|
+
type: "button",
|
|
856
|
+
onClick: () => void actions.promptInstall(),
|
|
857
|
+
style: { ...primaryButtonStyle, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8 },
|
|
858
|
+
children: [
|
|
859
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DownloadIcon, { size: 18 }),
|
|
860
|
+
copy.cta
|
|
861
|
+
]
|
|
862
|
+
}
|
|
863
|
+
),
|
|
864
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
865
|
+
"button",
|
|
866
|
+
{
|
|
867
|
+
"data-testid": "install-prompt-skip-session",
|
|
868
|
+
type: "button",
|
|
869
|
+
onClick: actions.dismissSession,
|
|
870
|
+
style: skipLinkStyle,
|
|
871
|
+
children: copy.skip
|
|
872
|
+
}
|
|
873
|
+
),
|
|
874
|
+
showPermanent && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
875
|
+
"button",
|
|
876
|
+
{
|
|
877
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
878
|
+
type: "button",
|
|
879
|
+
onClick: actions.dismissPermanent,
|
|
880
|
+
style: skipPermanentLinkStyle,
|
|
881
|
+
children: copy.skipPermanent
|
|
882
|
+
}
|
|
883
|
+
)
|
|
884
|
+
] });
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// src/components/InstallGate/variants/AndroidManualVariant.tsx
|
|
888
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
889
|
+
function AndroidManualVariant({
|
|
890
|
+
state,
|
|
891
|
+
actions
|
|
892
|
+
}) {
|
|
893
|
+
const copy = INSTALL_COPY.android.manual;
|
|
894
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
895
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(InstallSplash, { title: copy.title, children: [
|
|
896
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Step, { n: 1, icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MenuDotsVerticalIcon, { size: 20 }), children: copy.step1 }),
|
|
897
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Step, { n: 2, icon: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DownloadIcon, { size: 18 }), children: copy.step2 }),
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
899
|
+
"button",
|
|
900
|
+
{
|
|
901
|
+
"data-testid": "install-prompt-cta-android-manual",
|
|
902
|
+
type: "button",
|
|
903
|
+
onClick: actions.dismissSession,
|
|
904
|
+
style: primaryButtonStyle,
|
|
905
|
+
children: copy.cta
|
|
906
|
+
}
|
|
907
|
+
),
|
|
908
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
909
|
+
"button",
|
|
910
|
+
{
|
|
911
|
+
"data-testid": "install-prompt-skip-session",
|
|
912
|
+
type: "button",
|
|
913
|
+
onClick: actions.dismissSession,
|
|
914
|
+
style: skipLinkStyle,
|
|
915
|
+
children: copy.skip
|
|
916
|
+
}
|
|
917
|
+
),
|
|
918
|
+
showPermanent && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
919
|
+
"button",
|
|
920
|
+
{
|
|
921
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
922
|
+
type: "button",
|
|
923
|
+
onClick: actions.dismissPermanent,
|
|
924
|
+
style: skipPermanentLinkStyle,
|
|
925
|
+
children: copy.skipPermanent
|
|
926
|
+
}
|
|
927
|
+
)
|
|
928
|
+
] });
|
|
929
|
+
}
|
|
930
|
+
function Step({ n, icon, children }) {
|
|
931
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
932
|
+
"div",
|
|
933
|
+
{
|
|
934
|
+
style: {
|
|
935
|
+
display: "flex",
|
|
936
|
+
alignItems: "center",
|
|
937
|
+
gap: 12,
|
|
938
|
+
padding: "12px 14px",
|
|
939
|
+
background: "#f5f5f7",
|
|
940
|
+
borderRadius: 12,
|
|
941
|
+
marginBottom: 10,
|
|
942
|
+
textAlign: "left"
|
|
943
|
+
},
|
|
944
|
+
children: [
|
|
945
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
946
|
+
"div",
|
|
947
|
+
{
|
|
948
|
+
style: {
|
|
949
|
+
width: 28,
|
|
950
|
+
height: 28,
|
|
951
|
+
borderRadius: "50%",
|
|
952
|
+
background: "var(--hook-color-primary)",
|
|
953
|
+
color: "#fff",
|
|
954
|
+
display: "flex",
|
|
955
|
+
alignItems: "center",
|
|
956
|
+
justifyContent: "center",
|
|
957
|
+
fontSize: 14,
|
|
958
|
+
fontWeight: 700,
|
|
959
|
+
flexShrink: 0
|
|
960
|
+
},
|
|
961
|
+
children: n
|
|
962
|
+
}
|
|
963
|
+
),
|
|
964
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { flex: 1, fontSize: 15, color: "#333" }, children }),
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
|
|
966
|
+
]
|
|
967
|
+
}
|
|
968
|
+
);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// src/components/InstallGate/Step.tsx
|
|
972
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
973
|
+
function Step2({
|
|
974
|
+
n,
|
|
975
|
+
title,
|
|
976
|
+
subtitle,
|
|
977
|
+
visual
|
|
978
|
+
}) {
|
|
979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
980
|
+
"div",
|
|
981
|
+
{
|
|
982
|
+
style: {
|
|
983
|
+
display: "flex",
|
|
984
|
+
alignItems: "flex-start",
|
|
985
|
+
gap: 12,
|
|
986
|
+
marginBottom: 16,
|
|
987
|
+
textAlign: "left"
|
|
988
|
+
},
|
|
989
|
+
children: [
|
|
990
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
991
|
+
"div",
|
|
992
|
+
{
|
|
993
|
+
style: {
|
|
994
|
+
width: 32,
|
|
995
|
+
height: 32,
|
|
996
|
+
borderRadius: 10,
|
|
997
|
+
background: "var(--hook-color-primary)",
|
|
998
|
+
color: "#fff",
|
|
999
|
+
display: "flex",
|
|
1000
|
+
alignItems: "center",
|
|
1001
|
+
justifyContent: "center",
|
|
1002
|
+
fontSize: 15,
|
|
1003
|
+
fontWeight: 700,
|
|
1004
|
+
flexShrink: 0
|
|
1005
|
+
},
|
|
1006
|
+
children: n
|
|
1007
|
+
}
|
|
1008
|
+
),
|
|
1009
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { flex: 1 }, children: [
|
|
1010
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { margin: 0, fontSize: 15, fontWeight: 500, color: "#111", lineHeight: 1.3 }, children: title }),
|
|
1011
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { margin: "4px 0 0 0", fontSize: 13, color: "#777" }, children: subtitle }),
|
|
1012
|
+
visual
|
|
1013
|
+
] })
|
|
1014
|
+
]
|
|
1015
|
+
}
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// src/components/InstallGate/variants/IOSafariVariant.tsx
|
|
1020
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1021
|
+
function IOSafariVariant({
|
|
1022
|
+
state,
|
|
1023
|
+
actions
|
|
1024
|
+
}) {
|
|
1025
|
+
const copy = INSTALL_COPY.iosSafari;
|
|
1026
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
1027
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
|
|
1028
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1029
|
+
Step2,
|
|
1030
|
+
{
|
|
1031
|
+
n: 1,
|
|
1032
|
+
title: copy.step1.title,
|
|
1033
|
+
subtitle: copy.step1.subtitle,
|
|
1034
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1035
|
+
"div",
|
|
1036
|
+
{
|
|
1037
|
+
style: {
|
|
1038
|
+
display: "flex",
|
|
1039
|
+
justifyContent: "center",
|
|
1040
|
+
alignItems: "center",
|
|
1041
|
+
background: "#f5f5f7",
|
|
1042
|
+
borderRadius: 12,
|
|
1043
|
+
padding: "12px 0",
|
|
1044
|
+
marginTop: 8
|
|
1045
|
+
},
|
|
1046
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
|
|
1047
|
+
}
|
|
1048
|
+
)
|
|
1049
|
+
}
|
|
1050
|
+
),
|
|
1051
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1052
|
+
Step2,
|
|
1053
|
+
{
|
|
1054
|
+
n: 2,
|
|
1055
|
+
title: copy.step2.title,
|
|
1056
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1057
|
+
"div",
|
|
1058
|
+
{
|
|
1059
|
+
style: {
|
|
1060
|
+
display: "flex",
|
|
1061
|
+
alignItems: "center",
|
|
1062
|
+
gap: 10,
|
|
1063
|
+
background: "#f5f5f7",
|
|
1064
|
+
borderRadius: 12,
|
|
1065
|
+
padding: "12px 14px",
|
|
1066
|
+
marginTop: 8
|
|
1067
|
+
},
|
|
1068
|
+
children: [
|
|
1069
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
|
|
1070
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
|
|
1071
|
+
]
|
|
1072
|
+
}
|
|
1073
|
+
)
|
|
1074
|
+
}
|
|
1075
|
+
),
|
|
1076
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1077
|
+
Step2,
|
|
1078
|
+
{
|
|
1079
|
+
n: 3,
|
|
1080
|
+
title: copy.step3.title,
|
|
1081
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1082
|
+
"div",
|
|
1083
|
+
{
|
|
1084
|
+
style: {
|
|
1085
|
+
display: "flex",
|
|
1086
|
+
justifyContent: "flex-end",
|
|
1087
|
+
background: "#f5f5f7",
|
|
1088
|
+
borderRadius: 12,
|
|
1089
|
+
padding: "10px 14px",
|
|
1090
|
+
marginTop: 8
|
|
1091
|
+
},
|
|
1092
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1093
|
+
"span",
|
|
1094
|
+
{
|
|
1095
|
+
style: {
|
|
1096
|
+
color: "var(--hook-color-primary)",
|
|
1097
|
+
fontSize: 15,
|
|
1098
|
+
fontWeight: 600
|
|
1099
|
+
},
|
|
1100
|
+
children: copy.step3.buttonLabel
|
|
1101
|
+
}
|
|
1102
|
+
)
|
|
1103
|
+
}
|
|
1104
|
+
)
|
|
1105
|
+
}
|
|
1106
|
+
),
|
|
1107
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1108
|
+
"button",
|
|
1109
|
+
{
|
|
1110
|
+
"data-testid": "install-prompt-skip-session",
|
|
1111
|
+
type: "button",
|
|
1112
|
+
onClick: actions.dismissSession,
|
|
1113
|
+
style: { ...skipLinkStyle, marginTop: 16 },
|
|
1114
|
+
children: copy.skip
|
|
1115
|
+
}
|
|
1116
|
+
),
|
|
1117
|
+
showPermanent && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1118
|
+
"button",
|
|
1119
|
+
{
|
|
1120
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
1121
|
+
type: "button",
|
|
1122
|
+
onClick: actions.dismissPermanent,
|
|
1123
|
+
style: skipPermanentLinkStyle,
|
|
1124
|
+
children: copy.skipPermanent
|
|
1125
|
+
}
|
|
1126
|
+
)
|
|
1127
|
+
] });
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
// src/components/InstallGate/variants/IOSOtherVariant.tsx
|
|
1131
|
+
var import_react6 = require("react");
|
|
1132
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1133
|
+
function IOSOtherVariant({
|
|
1134
|
+
state,
|
|
1135
|
+
actions
|
|
1136
|
+
}) {
|
|
1137
|
+
const copy = INSTALL_COPY.iosOther;
|
|
1138
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
1139
|
+
const [copied, setCopied] = (0, import_react6.useState)(false);
|
|
1140
|
+
const [helpOpen, setHelpOpen] = (0, import_react6.useState)(false);
|
|
1141
|
+
const handleCopy = async () => {
|
|
1142
|
+
await actions.copyLink();
|
|
1143
|
+
setCopied(true);
|
|
1144
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
1145
|
+
};
|
|
1146
|
+
const handleShowHelp = () => {
|
|
1147
|
+
if (!helpOpen) actions.showIOSOtherHelp();
|
|
1148
|
+
setHelpOpen(true);
|
|
1149
|
+
};
|
|
1150
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
|
|
1151
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1152
|
+
"button",
|
|
1153
|
+
{
|
|
1154
|
+
"data-testid": "install-prompt-cta-ios-other-primary",
|
|
1155
|
+
type: "button",
|
|
1156
|
+
onClick: handleShowHelp,
|
|
1157
|
+
"aria-expanded": helpOpen,
|
|
1158
|
+
style: primaryButtonStyle,
|
|
1159
|
+
children: copy.ctaPrimary
|
|
1160
|
+
}
|
|
1161
|
+
),
|
|
1162
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1163
|
+
"button",
|
|
1164
|
+
{
|
|
1165
|
+
"data-testid": "install-prompt-cta-ios-other-secondary",
|
|
1166
|
+
type: "button",
|
|
1167
|
+
onClick: () => void handleCopy(),
|
|
1168
|
+
style: secondaryButtonStyle,
|
|
1169
|
+
children: copied ? copy.copiedToast : copy.ctaSecondary
|
|
1170
|
+
}
|
|
1171
|
+
),
|
|
1172
|
+
helpOpen && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1173
|
+
"div",
|
|
1174
|
+
{
|
|
1175
|
+
"data-testid": "install-prompt-ios-other-help",
|
|
1176
|
+
style: { marginTop: 20, textAlign: "left" },
|
|
1177
|
+
children: [
|
|
1178
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1179
|
+
Step2,
|
|
1180
|
+
{
|
|
1181
|
+
n: 1,
|
|
1182
|
+
title: copy.help.step1.title,
|
|
1183
|
+
subtitle: copy.help.step1.subtitle,
|
|
1184
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1185
|
+
"div",
|
|
1186
|
+
{
|
|
1187
|
+
style: {
|
|
1188
|
+
display: "flex",
|
|
1189
|
+
justifyContent: "center",
|
|
1190
|
+
alignItems: "center",
|
|
1191
|
+
background: "#f5f5f7",
|
|
1192
|
+
borderRadius: 12,
|
|
1193
|
+
padding: "12px 0",
|
|
1194
|
+
marginTop: 8
|
|
1195
|
+
},
|
|
1196
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1197
|
+
MenuDotsHorizontalIcon,
|
|
1198
|
+
{
|
|
1199
|
+
size: 28,
|
|
1200
|
+
style: { color: "var(--hook-color-primary)" }
|
|
1201
|
+
}
|
|
1202
|
+
)
|
|
1203
|
+
}
|
|
1204
|
+
)
|
|
1205
|
+
}
|
|
1206
|
+
),
|
|
1207
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1208
|
+
Step2,
|
|
1209
|
+
{
|
|
1210
|
+
n: 2,
|
|
1211
|
+
title: copy.help.step2.title,
|
|
1212
|
+
subtitle: copy.help.step2.subtitle,
|
|
1213
|
+
visual: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1214
|
+
"div",
|
|
1215
|
+
{
|
|
1216
|
+
style: {
|
|
1217
|
+
display: "flex",
|
|
1218
|
+
alignItems: "center",
|
|
1219
|
+
gap: 10,
|
|
1220
|
+
background: "#f5f5f7",
|
|
1221
|
+
borderRadius: 12,
|
|
1222
|
+
padding: "12px 14px",
|
|
1223
|
+
marginTop: 8
|
|
1224
|
+
},
|
|
1225
|
+
children: [
|
|
1226
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ExternalLinkIcon, { size: 22, style: { color: "#555" } }),
|
|
1227
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 14, color: "#333" }, children: "Abrir no Safari" })
|
|
1228
|
+
]
|
|
1229
|
+
}
|
|
1230
|
+
)
|
|
1231
|
+
}
|
|
1232
|
+
)
|
|
1233
|
+
]
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1237
|
+
"button",
|
|
1238
|
+
{
|
|
1239
|
+
"data-testid": "install-prompt-skip-session",
|
|
1240
|
+
type: "button",
|
|
1241
|
+
onClick: actions.dismissSession,
|
|
1242
|
+
style: skipLinkStyle,
|
|
1243
|
+
children: copy.skip
|
|
1244
|
+
}
|
|
1245
|
+
),
|
|
1246
|
+
showPermanent && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1247
|
+
"button",
|
|
1248
|
+
{
|
|
1249
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
1250
|
+
type: "button",
|
|
1251
|
+
onClick: actions.dismissPermanent,
|
|
1252
|
+
style: skipPermanentLinkStyle,
|
|
1253
|
+
children: copy.skipPermanent
|
|
1254
|
+
}
|
|
1255
|
+
)
|
|
1256
|
+
] });
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// src/components/InstallGate/variants/InAppBrowserVariant.tsx
|
|
1260
|
+
var import_react7 = require("react");
|
|
1261
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1262
|
+
function InAppBrowserVariant({
|
|
1263
|
+
state,
|
|
1264
|
+
actions
|
|
1265
|
+
}) {
|
|
1266
|
+
const app = state.inAppApp ?? "other";
|
|
1267
|
+
const appCopy = INSTALL_COPY.inApp[app] ?? INSTALL_COPY.inApp.other;
|
|
1268
|
+
const copy = INSTALL_COPY.inApp;
|
|
1269
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
1270
|
+
const [copied, setCopied] = (0, import_react7.useState)(false);
|
|
1271
|
+
const handleCopy = async () => {
|
|
1272
|
+
await actions.copyLink();
|
|
1273
|
+
setCopied(true);
|
|
1274
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
1275
|
+
};
|
|
1276
|
+
const DotsIcon = app === "facebook" || app === "telegram" ? MenuDotsVerticalIcon : MenuDotsHorizontalIcon;
|
|
1277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(InstallSplash, { title: appCopy.title, children: [
|
|
1278
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Step3, { n: 1, icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DotsIcon, { size: 20 }), children: appCopy.step1 }),
|
|
1279
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Step3, { n: 2, icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ExternalLinkIcon, { size: 18 }), children: appCopy.step2 }),
|
|
1280
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1281
|
+
"button",
|
|
1282
|
+
{
|
|
1283
|
+
"data-testid": "install-prompt-cta-inapp-copy",
|
|
1284
|
+
type: "button",
|
|
1285
|
+
onClick: () => void handleCopy(),
|
|
1286
|
+
style: { ...primaryButtonStyle, marginTop: 8 },
|
|
1287
|
+
children: copied ? copy.copiedToast : copy.copy
|
|
1288
|
+
}
|
|
1289
|
+
),
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1291
|
+
"button",
|
|
1292
|
+
{
|
|
1293
|
+
"data-testid": "install-prompt-skip-session",
|
|
1294
|
+
type: "button",
|
|
1295
|
+
onClick: actions.dismissSession,
|
|
1296
|
+
style: skipLinkStyle,
|
|
1297
|
+
children: copy.skip
|
|
1298
|
+
}
|
|
1299
|
+
),
|
|
1300
|
+
showPermanent && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1301
|
+
"button",
|
|
1302
|
+
{
|
|
1303
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
1304
|
+
type: "button",
|
|
1305
|
+
onClick: actions.dismissPermanent,
|
|
1306
|
+
style: skipPermanentLinkStyle,
|
|
1307
|
+
children: copy.skipPermanent
|
|
1308
|
+
}
|
|
1309
|
+
)
|
|
1310
|
+
] });
|
|
1311
|
+
}
|
|
1312
|
+
function Step3({
|
|
1313
|
+
n,
|
|
1314
|
+
icon,
|
|
1315
|
+
children
|
|
1316
|
+
}) {
|
|
1317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1318
|
+
"div",
|
|
1319
|
+
{
|
|
1320
|
+
style: {
|
|
1321
|
+
display: "flex",
|
|
1322
|
+
alignItems: "center",
|
|
1323
|
+
gap: 12,
|
|
1324
|
+
padding: "12px 14px",
|
|
1325
|
+
background: "#f5f5f7",
|
|
1326
|
+
borderRadius: 12,
|
|
1327
|
+
marginBottom: 10,
|
|
1328
|
+
textAlign: "left"
|
|
1329
|
+
},
|
|
1330
|
+
children: [
|
|
1331
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1332
|
+
"div",
|
|
1333
|
+
{
|
|
1334
|
+
style: {
|
|
1335
|
+
width: 28,
|
|
1336
|
+
height: 28,
|
|
1337
|
+
borderRadius: "50%",
|
|
1338
|
+
background: "var(--hook-color-primary)",
|
|
1339
|
+
color: "#fff",
|
|
1340
|
+
display: "flex",
|
|
1341
|
+
alignItems: "center",
|
|
1342
|
+
justifyContent: "center",
|
|
1343
|
+
fontSize: 14,
|
|
1344
|
+
fontWeight: 700,
|
|
1345
|
+
flexShrink: 0
|
|
1346
|
+
},
|
|
1347
|
+
children: n
|
|
1348
|
+
}
|
|
1349
|
+
),
|
|
1350
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { flex: 1, fontSize: 14, color: "#333" }, children }),
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
|
|
1352
|
+
]
|
|
1353
|
+
}
|
|
1354
|
+
);
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
// src/components/InstallGate/variants/DesktopVariant.tsx
|
|
1358
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1359
|
+
function DesktopVariant({
|
|
1360
|
+
state,
|
|
1361
|
+
actions
|
|
1362
|
+
}) {
|
|
1363
|
+
const { name, theme } = useTemplateConfig();
|
|
1364
|
+
const copy = INSTALL_COPY.desktop;
|
|
1365
|
+
const iconUrl = theme.icon_url || theme.logo_url || null;
|
|
1366
|
+
if (!state.isInstallable) return null;
|
|
1367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1368
|
+
"div",
|
|
1369
|
+
{
|
|
1370
|
+
role: "complementary",
|
|
1371
|
+
"aria-label": copy.title,
|
|
1372
|
+
style: bannerStyle,
|
|
1373
|
+
children: [
|
|
1374
|
+
iconUrl ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1375
|
+
"img",
|
|
1376
|
+
{
|
|
1377
|
+
src: iconUrl,
|
|
1378
|
+
alt: "",
|
|
1379
|
+
style: { width: 40, height: 40, borderRadius: 10, objectFit: "cover", flexShrink: 0 }
|
|
1380
|
+
}
|
|
1381
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1382
|
+
"div",
|
|
1383
|
+
{
|
|
1384
|
+
style: {
|
|
1385
|
+
width: 40,
|
|
1386
|
+
height: 40,
|
|
1387
|
+
borderRadius: 10,
|
|
1388
|
+
background: "var(--hook-color-primary)",
|
|
1389
|
+
color: "#fff",
|
|
1390
|
+
display: "flex",
|
|
1391
|
+
alignItems: "center",
|
|
1392
|
+
justifyContent: "center",
|
|
1393
|
+
fontSize: 18,
|
|
1394
|
+
fontWeight: 700,
|
|
1395
|
+
flexShrink: 0
|
|
1396
|
+
},
|
|
1397
|
+
children: name.charAt(0).toUpperCase()
|
|
1398
|
+
}
|
|
1399
|
+
),
|
|
1400
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1401
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 14, fontWeight: 600, color: "#111" }, children: copy.title }),
|
|
1402
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { fontSize: 12, color: "#666" }, children: copy.subtitle })
|
|
1403
|
+
] }),
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1405
|
+
"button",
|
|
1406
|
+
{
|
|
1407
|
+
"data-testid": "install-prompt-cta-desktop",
|
|
1408
|
+
type: "button",
|
|
1409
|
+
onClick: () => void actions.promptInstall(),
|
|
1410
|
+
style: {
|
|
1411
|
+
padding: "8px 14px",
|
|
1412
|
+
background: "var(--hook-color-primary)",
|
|
1413
|
+
color: "#fff",
|
|
1414
|
+
border: "none",
|
|
1415
|
+
borderRadius: 999,
|
|
1416
|
+
fontSize: 13,
|
|
1417
|
+
fontWeight: 600,
|
|
1418
|
+
cursor: "pointer",
|
|
1419
|
+
display: "inline-flex",
|
|
1420
|
+
alignItems: "center",
|
|
1421
|
+
gap: 6,
|
|
1422
|
+
flexShrink: 0
|
|
1423
|
+
},
|
|
1424
|
+
children: [
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DownloadIcon, { size: 14 }),
|
|
1426
|
+
copy.cta
|
|
1427
|
+
]
|
|
1428
|
+
}
|
|
1429
|
+
),
|
|
1430
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1431
|
+
"button",
|
|
1432
|
+
{
|
|
1433
|
+
"data-testid": "install-prompt-desktop-close",
|
|
1434
|
+
type: "button",
|
|
1435
|
+
onClick: actions.dismissPermanent,
|
|
1436
|
+
"aria-label": copy.close,
|
|
1437
|
+
style: {
|
|
1438
|
+
background: "transparent",
|
|
1439
|
+
border: "none",
|
|
1440
|
+
cursor: "pointer",
|
|
1441
|
+
color: "#888",
|
|
1442
|
+
padding: 4,
|
|
1443
|
+
flexShrink: 0
|
|
1444
|
+
},
|
|
1445
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(XIcon, { size: 16 })
|
|
1446
|
+
}
|
|
1447
|
+
)
|
|
1448
|
+
]
|
|
1449
|
+
}
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
var bannerStyle = {
|
|
1453
|
+
position: "fixed",
|
|
1454
|
+
bottom: 24,
|
|
1455
|
+
right: 24,
|
|
1456
|
+
zIndex: 1e4,
|
|
1457
|
+
display: "flex",
|
|
1458
|
+
alignItems: "center",
|
|
1459
|
+
gap: 12,
|
|
1460
|
+
padding: "12px 16px",
|
|
1461
|
+
background: "#fff",
|
|
1462
|
+
border: "1px solid rgba(0,0,0,0.08)",
|
|
1463
|
+
borderRadius: 16,
|
|
1464
|
+
boxShadow: "0 10px 30px rgba(0,0,0,0.12)",
|
|
1465
|
+
maxWidth: 400
|
|
1466
|
+
};
|
|
1467
|
+
|
|
1468
|
+
// src/components/InstallGate/InstallGate.tsx
|
|
1469
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1470
|
+
function InstallGate({ children }) {
|
|
1471
|
+
const { slug, features_enabled } = useTemplateConfig();
|
|
1472
|
+
const enabled = features_enabled.includes("install_prompt");
|
|
1473
|
+
const installState = useInstallPrompt(slug);
|
|
1474
|
+
const shouldBlock = enabled && shouldBlockInstall(installState);
|
|
1475
|
+
const trackedRef = (0, import_react8.useRef)(null);
|
|
1476
|
+
(0, import_react8.useEffect)(() => {
|
|
1477
|
+
if (!shouldBlock) return;
|
|
1478
|
+
if (typeof window === "undefined") return;
|
|
1479
|
+
const variantKey = `${slug}:${installState.variant}`;
|
|
1480
|
+
if (trackedRef.current === variantKey) return;
|
|
1481
|
+
trackedRef.current = variantKey;
|
|
1482
|
+
window.posthog?.capture?.("pwa_install_splash_shown", {
|
|
1483
|
+
slug,
|
|
1484
|
+
platform: installState.platform,
|
|
1485
|
+
browser: installState.iosBrowser ?? installState.androidBrowser ?? null,
|
|
1486
|
+
in_app_app: installState.inAppApp,
|
|
1487
|
+
variant: installState.variant
|
|
1488
|
+
});
|
|
1489
|
+
}, [shouldBlock, slug, installState.variant, installState.platform, installState.iosBrowser, installState.androidBrowser, installState.inAppApp]);
|
|
1490
|
+
if (!enabled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1491
|
+
if (installState.isInstalled) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1492
|
+
if (installState.variant === "desktop") {
|
|
1493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
1494
|
+
children,
|
|
1495
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DesktopVariant, { state: installState, actions: installState })
|
|
1496
|
+
] });
|
|
1497
|
+
}
|
|
1498
|
+
if (!shouldBlock) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1499
|
+
switch (installState.variant) {
|
|
1500
|
+
case "android-native":
|
|
1501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AndroidNativeVariant, { state: installState, actions: installState });
|
|
1502
|
+
case "android-manual":
|
|
1503
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AndroidManualVariant, { state: installState, actions: installState });
|
|
1504
|
+
case "ios-safari":
|
|
1505
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IOSafariVariant, { state: installState, actions: installState });
|
|
1506
|
+
case "ios-other":
|
|
1507
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IOSOtherVariant, { state: installState, actions: installState });
|
|
1508
|
+
case "in-app":
|
|
1509
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(InAppBrowserVariant, { state: installState, actions: installState });
|
|
1510
|
+
case "none":
|
|
1511
|
+
default:
|
|
1512
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children });
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
// src/defaults/ErrorBoundary.tsx
|
|
1517
|
+
var import_react9 = require("react");
|
|
1518
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1519
|
+
var ErrorBoundary = class extends import_react9.Component {
|
|
217
1520
|
state = { error: null };
|
|
218
1521
|
static getDerivedStateFromError(error) {
|
|
219
1522
|
return { error };
|
|
@@ -223,17 +1526,17 @@ var ErrorBoundary = class extends import_react5.Component {
|
|
|
223
1526
|
}
|
|
224
1527
|
render() {
|
|
225
1528
|
if (this.state.error) {
|
|
226
|
-
return this.props.fallback ?? /* @__PURE__ */ (0,
|
|
227
|
-
/* @__PURE__ */ (0,
|
|
228
|
-
/* @__PURE__ */ (0,
|
|
1529
|
+
return this.props.fallback ?? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
|
|
1530
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h2", { children: "Algo deu errado" }),
|
|
1531
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
|
|
229
1532
|
] });
|
|
230
1533
|
}
|
|
231
|
-
return /* @__PURE__ */ (0,
|
|
1534
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_jsx_runtime17.Fragment, { children: this.props.children });
|
|
232
1535
|
}
|
|
233
1536
|
};
|
|
234
1537
|
|
|
235
1538
|
// src/hooks/useLoginForm.ts
|
|
236
|
-
var
|
|
1539
|
+
var import_react10 = require("react");
|
|
237
1540
|
var import_sdk5 = require("@hook-sdk/sdk");
|
|
238
1541
|
|
|
239
1542
|
// src/errors.ts
|
|
@@ -270,22 +1573,22 @@ var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
|
270
1573
|
var MIN_PASSWORD = 8;
|
|
271
1574
|
function useLoginForm() {
|
|
272
1575
|
const { auth } = (0, import_sdk5.useHook)();
|
|
273
|
-
const [email, setEmail] = (0,
|
|
274
|
-
const [password, setPassword] = (0,
|
|
275
|
-
const [submitting, setSubmitting] = (0,
|
|
276
|
-
const [error, setError] = (0,
|
|
277
|
-
const emailError = (0,
|
|
1576
|
+
const [email, setEmail] = (0, import_react10.useState)("");
|
|
1577
|
+
const [password, setPassword] = (0, import_react10.useState)("");
|
|
1578
|
+
const [submitting, setSubmitting] = (0, import_react10.useState)(false);
|
|
1579
|
+
const [error, setError] = (0, import_react10.useState)(null);
|
|
1580
|
+
const emailError = (0, import_react10.useMemo)(() => {
|
|
278
1581
|
if (email.length === 0) return null;
|
|
279
1582
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
280
1583
|
return null;
|
|
281
1584
|
}, [email]);
|
|
282
|
-
const passwordError = (0,
|
|
1585
|
+
const passwordError = (0, import_react10.useMemo)(() => {
|
|
283
1586
|
if (password.length === 0) return null;
|
|
284
1587
|
if (password.length < MIN_PASSWORD) return `M\xEDnimo de ${MIN_PASSWORD} caracteres.`;
|
|
285
1588
|
return null;
|
|
286
1589
|
}, [password]);
|
|
287
1590
|
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && emailError === null && passwordError === null && !submitting;
|
|
288
|
-
const submit = (0,
|
|
1591
|
+
const submit = (0, import_react10.useCallback)(async () => {
|
|
289
1592
|
if (!canSubmit) return false;
|
|
290
1593
|
setSubmitting(true);
|
|
291
1594
|
setError(null);
|
|
@@ -315,13 +1618,13 @@ function useLoginForm() {
|
|
|
315
1618
|
}
|
|
316
1619
|
|
|
317
1620
|
// src/internal/GoogleSignInButton.tsx
|
|
318
|
-
var
|
|
1621
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
319
1622
|
function GoogleSignInButton({
|
|
320
1623
|
onClick,
|
|
321
1624
|
testId = "oauth-google",
|
|
322
1625
|
label = "Continuar com Google"
|
|
323
1626
|
}) {
|
|
324
|
-
return /* @__PURE__ */ (0,
|
|
1627
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
325
1628
|
"button",
|
|
326
1629
|
{
|
|
327
1630
|
"data-testid": testId,
|
|
@@ -344,36 +1647,36 @@ function GoogleSignInButton({
|
|
|
344
1647
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
|
|
345
1648
|
},
|
|
346
1649
|
children: [
|
|
347
|
-
/* @__PURE__ */ (0,
|
|
1650
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(GoogleGlyph, {}),
|
|
348
1651
|
label
|
|
349
1652
|
]
|
|
350
1653
|
}
|
|
351
1654
|
);
|
|
352
1655
|
}
|
|
353
1656
|
function GoogleGlyph() {
|
|
354
|
-
return /* @__PURE__ */ (0,
|
|
355
|
-
/* @__PURE__ */ (0,
|
|
1657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
|
|
1658
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
356
1659
|
"path",
|
|
357
1660
|
{
|
|
358
1661
|
d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844a4.14 4.14 0 0 1-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.874 2.684-6.615z",
|
|
359
1662
|
fill: "#4285F4"
|
|
360
1663
|
}
|
|
361
1664
|
),
|
|
362
|
-
/* @__PURE__ */ (0,
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
363
1666
|
"path",
|
|
364
1667
|
{
|
|
365
1668
|
d: "M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 0 0 9 18z",
|
|
366
1669
|
fill: "#34A853"
|
|
367
1670
|
}
|
|
368
1671
|
),
|
|
369
|
-
/* @__PURE__ */ (0,
|
|
1672
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
370
1673
|
"path",
|
|
371
1674
|
{
|
|
372
1675
|
d: "M3.964 10.71A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.957 4.042l3.007-2.332z",
|
|
373
1676
|
fill: "#FBBC05"
|
|
374
1677
|
}
|
|
375
1678
|
),
|
|
376
|
-
/* @__PURE__ */ (0,
|
|
1679
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
377
1680
|
"path",
|
|
378
1681
|
{
|
|
379
1682
|
d: "M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 0 0 .957 4.958L3.964 7.29C4.672 5.163 6.656 3.58 9 3.58z",
|
|
@@ -384,8 +1687,8 @@ function GoogleGlyph() {
|
|
|
384
1687
|
}
|
|
385
1688
|
|
|
386
1689
|
// src/internal/OAuthErrorBanner.tsx
|
|
387
|
-
var
|
|
388
|
-
var
|
|
1690
|
+
var import_react11 = require("react");
|
|
1691
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
389
1692
|
var ERROR_MESSAGES = {
|
|
390
1693
|
invalid_state: "Sess\xE3o expirou, tente de novo.",
|
|
391
1694
|
access_denied: "Voc\xEA cancelou o login com Google.",
|
|
@@ -405,13 +1708,13 @@ function stripErrorFromUrl() {
|
|
|
405
1708
|
window.history.replaceState({}, "", url.toString());
|
|
406
1709
|
}
|
|
407
1710
|
function OAuthErrorBanner() {
|
|
408
|
-
const [code, setCode] = (0,
|
|
409
|
-
(0,
|
|
1711
|
+
const [code, setCode] = (0, import_react11.useState)(() => readErrorCode());
|
|
1712
|
+
(0, import_react11.useEffect)(() => {
|
|
410
1713
|
if (code !== null) stripErrorFromUrl();
|
|
411
1714
|
}, [code]);
|
|
412
1715
|
if (!code) return null;
|
|
413
1716
|
const message = ERROR_MESSAGES[code] ?? "N\xE3o conseguimos conectar ao Google. Tente de novo.";
|
|
414
|
-
return /* @__PURE__ */ (0,
|
|
1717
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
415
1718
|
"div",
|
|
416
1719
|
{
|
|
417
1720
|
role: "alert",
|
|
@@ -426,7 +1729,7 @@ function OAuthErrorBanner() {
|
|
|
426
1729
|
},
|
|
427
1730
|
children: [
|
|
428
1731
|
message,
|
|
429
|
-
/* @__PURE__ */ (0,
|
|
1732
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
430
1733
|
"button",
|
|
431
1734
|
{
|
|
432
1735
|
type: "button",
|
|
@@ -451,16 +1754,16 @@ function OAuthErrorBanner() {
|
|
|
451
1754
|
}
|
|
452
1755
|
|
|
453
1756
|
// src/defaults/DefaultLoginScreen.tsx
|
|
454
|
-
var
|
|
1757
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
455
1758
|
function DefaultLoginScreen({ onNavigate }) {
|
|
456
1759
|
const { name } = useTemplateConfig();
|
|
457
1760
|
const f = useLoginForm();
|
|
458
|
-
return /* @__PURE__ */ (0,
|
|
459
|
-
/* @__PURE__ */ (0,
|
|
460
|
-
/* @__PURE__ */ (0,
|
|
461
|
-
/* @__PURE__ */ (0,
|
|
462
|
-
/* @__PURE__ */ (0,
|
|
463
|
-
/* @__PURE__ */ (0,
|
|
1761
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
1762
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
|
|
1763
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Entre na sua conta" }),
|
|
1764
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(OAuthErrorBanner, {}),
|
|
1765
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(GoogleSignInButton, { onClick: f.loginWithGoogle, testId: "login-oauth-google" }),
|
|
1766
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
464
1767
|
"div",
|
|
465
1768
|
{
|
|
466
1769
|
"aria-hidden": "true",
|
|
@@ -473,19 +1776,19 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
473
1776
|
fontSize: 12
|
|
474
1777
|
},
|
|
475
1778
|
children: [
|
|
476
|
-
/* @__PURE__ */ (0,
|
|
1779
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } }),
|
|
477
1780
|
"ou",
|
|
478
|
-
/* @__PURE__ */ (0,
|
|
1781
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } })
|
|
479
1782
|
]
|
|
480
1783
|
}
|
|
481
1784
|
),
|
|
482
|
-
/* @__PURE__ */ (0,
|
|
1785
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("form", { onSubmit: (e) => {
|
|
483
1786
|
e.preventDefault();
|
|
484
1787
|
void f.submit();
|
|
485
1788
|
}, children: [
|
|
486
|
-
/* @__PURE__ */ (0,
|
|
1789
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
487
1790
|
"E-mail",
|
|
488
|
-
/* @__PURE__ */ (0,
|
|
1791
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
489
1792
|
"input",
|
|
490
1793
|
{
|
|
491
1794
|
"data-testid": "login-email",
|
|
@@ -495,11 +1798,11 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
495
1798
|
style: { display: "block", width: "100%" }
|
|
496
1799
|
}
|
|
497
1800
|
),
|
|
498
|
-
f.emailError && /* @__PURE__ */ (0,
|
|
1801
|
+
f.emailError && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
|
|
499
1802
|
] }),
|
|
500
|
-
/* @__PURE__ */ (0,
|
|
1803
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
501
1804
|
"Senha",
|
|
502
|
-
/* @__PURE__ */ (0,
|
|
1805
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
503
1806
|
"input",
|
|
504
1807
|
{
|
|
505
1808
|
"data-testid": "login-password",
|
|
@@ -509,10 +1812,10 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
509
1812
|
style: { display: "block", width: "100%" }
|
|
510
1813
|
}
|
|
511
1814
|
),
|
|
512
|
-
f.passwordError && /* @__PURE__ */ (0,
|
|
1815
|
+
f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
513
1816
|
] }),
|
|
514
|
-
f.error && /* @__PURE__ */ (0,
|
|
515
|
-
/* @__PURE__ */ (0,
|
|
1817
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
1818
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
516
1819
|
"button",
|
|
517
1820
|
{
|
|
518
1821
|
"data-testid": "login-submit",
|
|
@@ -531,42 +1834,42 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
531
1834
|
}
|
|
532
1835
|
)
|
|
533
1836
|
] }),
|
|
534
|
-
/* @__PURE__ */ (0,
|
|
535
|
-
/* @__PURE__ */ (0,
|
|
536
|
-
/* @__PURE__ */ (0,
|
|
1837
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { marginTop: 16, display: "flex", justifyContent: "space-between" }, children: [
|
|
1838
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { "data-testid": "login-goto-signup", type: "button", onClick: () => onNavigate("signup"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Criar conta" }),
|
|
1839
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { "data-testid": "login-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Esqueci senha" })
|
|
537
1840
|
] })
|
|
538
1841
|
] });
|
|
539
1842
|
}
|
|
540
1843
|
|
|
541
1844
|
// src/hooks/useSignupForm.ts
|
|
542
|
-
var
|
|
1845
|
+
var import_react12 = require("react");
|
|
543
1846
|
var import_sdk6 = require("@hook-sdk/sdk");
|
|
544
1847
|
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
545
1848
|
var MIN_PASSWORD2 = 8;
|
|
546
1849
|
function useSignupForm() {
|
|
547
1850
|
const { auth } = (0, import_sdk6.useHook)();
|
|
548
|
-
const [name, setName] = (0,
|
|
549
|
-
const [email, setEmail] = (0,
|
|
550
|
-
const [password, setPassword] = (0,
|
|
551
|
-
const [submitting, setSubmitting] = (0,
|
|
552
|
-
const [error, setError] = (0,
|
|
553
|
-
const nameError = (0,
|
|
1851
|
+
const [name, setName] = (0, import_react12.useState)("");
|
|
1852
|
+
const [email, setEmail] = (0, import_react12.useState)("");
|
|
1853
|
+
const [password, setPassword] = (0, import_react12.useState)("");
|
|
1854
|
+
const [submitting, setSubmitting] = (0, import_react12.useState)(false);
|
|
1855
|
+
const [error, setError] = (0, import_react12.useState)(null);
|
|
1856
|
+
const nameError = (0, import_react12.useMemo)(() => {
|
|
554
1857
|
if (name.length === 0) return null;
|
|
555
1858
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
556
1859
|
return null;
|
|
557
1860
|
}, [name]);
|
|
558
|
-
const emailError = (0,
|
|
1861
|
+
const emailError = (0, import_react12.useMemo)(() => {
|
|
559
1862
|
if (email.length === 0) return null;
|
|
560
1863
|
if (!EMAIL_RE2.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
561
1864
|
return null;
|
|
562
1865
|
}, [email]);
|
|
563
|
-
const passwordError = (0,
|
|
1866
|
+
const passwordError = (0, import_react12.useMemo)(() => {
|
|
564
1867
|
if (password.length === 0) return null;
|
|
565
1868
|
if (password.length < MIN_PASSWORD2) return `M\xEDnimo de ${MIN_PASSWORD2} caracteres.`;
|
|
566
1869
|
return null;
|
|
567
1870
|
}, [password]);
|
|
568
1871
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && nameError === null && emailError === null && passwordError === null && !submitting;
|
|
569
|
-
const submit = (0,
|
|
1872
|
+
const submit = (0, import_react12.useCallback)(async () => {
|
|
570
1873
|
if (!canSubmit) return false;
|
|
571
1874
|
setSubmitting(true);
|
|
572
1875
|
setError(null);
|
|
@@ -599,16 +1902,16 @@ function useSignupForm() {
|
|
|
599
1902
|
}
|
|
600
1903
|
|
|
601
1904
|
// src/defaults/DefaultSignupScreen.tsx
|
|
602
|
-
var
|
|
1905
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
603
1906
|
function DefaultSignupScreen({ onNavigate }) {
|
|
604
1907
|
const { name } = useTemplateConfig();
|
|
605
1908
|
const f = useSignupForm();
|
|
606
|
-
return /* @__PURE__ */ (0,
|
|
607
|
-
/* @__PURE__ */ (0,
|
|
608
|
-
/* @__PURE__ */ (0,
|
|
609
|
-
/* @__PURE__ */ (0,
|
|
610
|
-
/* @__PURE__ */ (0,
|
|
611
|
-
/* @__PURE__ */ (0,
|
|
1909
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
1910
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
|
|
1911
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Criar sua conta" }),
|
|
1912
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OAuthErrorBanner, {}),
|
|
1913
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GoogleSignInButton, { onClick: f.loginWithGoogle, testId: "signup-oauth-google" }),
|
|
1914
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
612
1915
|
"div",
|
|
613
1916
|
{
|
|
614
1917
|
"aria-hidden": "true",
|
|
@@ -621,55 +1924,55 @@ function DefaultSignupScreen({ onNavigate }) {
|
|
|
621
1924
|
fontSize: 12
|
|
622
1925
|
},
|
|
623
1926
|
children: [
|
|
624
|
-
/* @__PURE__ */ (0,
|
|
1927
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } }),
|
|
625
1928
|
"ou",
|
|
626
|
-
/* @__PURE__ */ (0,
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } })
|
|
627
1930
|
]
|
|
628
1931
|
}
|
|
629
1932
|
),
|
|
630
|
-
/* @__PURE__ */ (0,
|
|
1933
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("form", { onSubmit: (e) => {
|
|
631
1934
|
e.preventDefault();
|
|
632
1935
|
void f.submit();
|
|
633
1936
|
}, children: [
|
|
634
|
-
/* @__PURE__ */ (0,
|
|
1937
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
635
1938
|
"Nome",
|
|
636
|
-
/* @__PURE__ */ (0,
|
|
637
|
-
f.nameError && /* @__PURE__ */ (0,
|
|
1939
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { "data-testid": "signup-name", value: f.name, onChange: (e) => f.setName(e.target.value), style: { display: "block", width: "100%" } }),
|
|
1940
|
+
f.nameError && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("small", { style: { color: "#c00" }, children: f.nameError })
|
|
638
1941
|
] }),
|
|
639
|
-
/* @__PURE__ */ (0,
|
|
1942
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
640
1943
|
"E-mail",
|
|
641
|
-
/* @__PURE__ */ (0,
|
|
642
|
-
f.emailError && /* @__PURE__ */ (0,
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { "data-testid": "signup-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
|
|
1945
|
+
f.emailError && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
|
|
643
1946
|
] }),
|
|
644
|
-
/* @__PURE__ */ (0,
|
|
1947
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
645
1948
|
"Senha",
|
|
646
|
-
/* @__PURE__ */ (0,
|
|
647
|
-
f.passwordError && /* @__PURE__ */ (0,
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { "data-testid": "signup-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" } }),
|
|
1950
|
+
f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
648
1951
|
] }),
|
|
649
|
-
f.error && /* @__PURE__ */ (0,
|
|
650
|
-
/* @__PURE__ */ (0,
|
|
1952
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
1953
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.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" })
|
|
651
1954
|
] }),
|
|
652
|
-
/* @__PURE__ */ (0,
|
|
1955
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.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" }) })
|
|
653
1956
|
] });
|
|
654
1957
|
}
|
|
655
1958
|
|
|
656
1959
|
// src/hooks/useForgotForm.ts
|
|
657
|
-
var
|
|
1960
|
+
var import_react13 = require("react");
|
|
658
1961
|
var import_sdk7 = require("@hook-sdk/sdk");
|
|
659
1962
|
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
660
1963
|
function useForgotForm() {
|
|
661
1964
|
const { auth } = (0, import_sdk7.useHook)();
|
|
662
|
-
const [email, setEmail] = (0,
|
|
663
|
-
const [submitting, setSubmitting] = (0,
|
|
664
|
-
const [sent, setSent] = (0,
|
|
665
|
-
const [error, setError] = (0,
|
|
666
|
-
const emailError = (0,
|
|
1965
|
+
const [email, setEmail] = (0, import_react13.useState)("");
|
|
1966
|
+
const [submitting, setSubmitting] = (0, import_react13.useState)(false);
|
|
1967
|
+
const [sent, setSent] = (0, import_react13.useState)(false);
|
|
1968
|
+
const [error, setError] = (0, import_react13.useState)(null);
|
|
1969
|
+
const emailError = (0, import_react13.useMemo)(() => {
|
|
667
1970
|
if (email.length === 0) return null;
|
|
668
1971
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
669
1972
|
return null;
|
|
670
1973
|
}, [email]);
|
|
671
1974
|
const canSubmit = email.length > 0 && emailError === null && !submitting;
|
|
672
|
-
const submit = (0,
|
|
1975
|
+
const submit = (0, import_react13.useCallback)(async () => {
|
|
673
1976
|
if (!canSubmit) return false;
|
|
674
1977
|
setSubmitting(true);
|
|
675
1978
|
setError(null);
|
|
@@ -697,66 +2000,66 @@ function useForgotForm() {
|
|
|
697
2000
|
}
|
|
698
2001
|
|
|
699
2002
|
// src/defaults/DefaultForgotScreen.tsx
|
|
700
|
-
var
|
|
2003
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
701
2004
|
function DefaultForgotScreen({ onNavigate }) {
|
|
702
2005
|
const { name } = useTemplateConfig();
|
|
703
2006
|
const f = useForgotForm();
|
|
704
2007
|
if (f.sent) {
|
|
705
|
-
return /* @__PURE__ */ (0,
|
|
706
|
-
/* @__PURE__ */ (0,
|
|
707
|
-
/* @__PURE__ */ (0,
|
|
708
|
-
/* @__PURE__ */ (0,
|
|
2008
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
2009
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h1", { children: "Verifique seu e-mail" }),
|
|
2010
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { style: { opacity: 0.7 }, children: "Enviamos um link pra redefinir sua senha." }),
|
|
2011
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { "data-testid": "forgot-back-login", type: "button", onClick: () => onNavigate("login"), children: "Voltar pro login" })
|
|
709
2012
|
] });
|
|
710
2013
|
}
|
|
711
|
-
return /* @__PURE__ */ (0,
|
|
712
|
-
/* @__PURE__ */ (0,
|
|
713
|
-
/* @__PURE__ */ (0,
|
|
714
|
-
/* @__PURE__ */ (0,
|
|
2014
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
2015
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
|
|
2016
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Redefinir senha" }),
|
|
2017
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("form", { onSubmit: (e) => {
|
|
715
2018
|
e.preventDefault();
|
|
716
2019
|
void f.submit();
|
|
717
2020
|
}, children: [
|
|
718
|
-
/* @__PURE__ */ (0,
|
|
2021
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
719
2022
|
"E-mail",
|
|
720
|
-
/* @__PURE__ */ (0,
|
|
721
|
-
f.emailError && /* @__PURE__ */ (0,
|
|
2023
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("input", { "data-testid": "forgot-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
|
|
2024
|
+
f.emailError && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("small", { style: { color: "#c00" }, children: f.emailError })
|
|
722
2025
|
] }),
|
|
723
|
-
f.error && /* @__PURE__ */ (0,
|
|
724
|
-
/* @__PURE__ */ (0,
|
|
2026
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
2027
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.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" })
|
|
725
2028
|
] }),
|
|
726
|
-
/* @__PURE__ */ (0,
|
|
2029
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { "data-testid": "forgot-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Voltar pro login" }) })
|
|
727
2030
|
] });
|
|
728
2031
|
}
|
|
729
2032
|
|
|
730
2033
|
// src/hooks/useResetForm.ts
|
|
731
|
-
var
|
|
2034
|
+
var import_react14 = require("react");
|
|
732
2035
|
var import_sdk8 = require("@hook-sdk/sdk");
|
|
733
2036
|
var MIN_PASSWORD3 = 12;
|
|
734
2037
|
function useResetForm() {
|
|
735
2038
|
const { auth } = (0, import_sdk8.useHook)();
|
|
736
|
-
const [token, setToken] = (0,
|
|
737
|
-
const [password, setPassword] = (0,
|
|
738
|
-
const [confirm, setConfirm] = (0,
|
|
739
|
-
const [submitting, setSubmitting] = (0,
|
|
740
|
-
const [done, setDone] = (0,
|
|
741
|
-
const [error, setError] = (0,
|
|
742
|
-
(0,
|
|
2039
|
+
const [token, setToken] = (0, import_react14.useState)(null);
|
|
2040
|
+
const [password, setPassword] = (0, import_react14.useState)("");
|
|
2041
|
+
const [confirm, setConfirm] = (0, import_react14.useState)("");
|
|
2042
|
+
const [submitting, setSubmitting] = (0, import_react14.useState)(false);
|
|
2043
|
+
const [done, setDone] = (0, import_react14.useState)(false);
|
|
2044
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
2045
|
+
(0, import_react14.useEffect)(() => {
|
|
743
2046
|
if (typeof window === "undefined") return;
|
|
744
2047
|
const params = new URLSearchParams(window.location.search);
|
|
745
2048
|
const t = params.get("token");
|
|
746
2049
|
setToken(t && t.length > 0 ? t : null);
|
|
747
2050
|
}, []);
|
|
748
|
-
const passwordError = (0,
|
|
2051
|
+
const passwordError = (0, import_react14.useMemo)(() => {
|
|
749
2052
|
if (password.length === 0) return null;
|
|
750
2053
|
if (password.length < MIN_PASSWORD3) return `M\xEDnimo de ${MIN_PASSWORD3} caracteres.`;
|
|
751
2054
|
return null;
|
|
752
2055
|
}, [password]);
|
|
753
|
-
const confirmError = (0,
|
|
2056
|
+
const confirmError = (0, import_react14.useMemo)(() => {
|
|
754
2057
|
if (confirm.length === 0) return null;
|
|
755
2058
|
if (confirm !== password) return "Senhas n\xE3o coincidem.";
|
|
756
2059
|
return null;
|
|
757
2060
|
}, [confirm, password]);
|
|
758
2061
|
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && passwordError === null && confirmError === null && !submitting && !done;
|
|
759
|
-
const submit = (0,
|
|
2062
|
+
const submit = (0, import_react14.useCallback)(async () => {
|
|
760
2063
|
if (!canSubmit || token === null) return;
|
|
761
2064
|
setSubmitting(true);
|
|
762
2065
|
setError(null);
|
|
@@ -792,67 +2095,67 @@ function useResetForm() {
|
|
|
792
2095
|
}
|
|
793
2096
|
|
|
794
2097
|
// src/defaults/DefaultResetScreen.tsx
|
|
795
|
-
var
|
|
2098
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
796
2099
|
function DefaultResetScreen({ onNavigate }) {
|
|
797
2100
|
const { name } = useTemplateConfig();
|
|
798
2101
|
const f = useResetForm();
|
|
799
2102
|
if (f.done) {
|
|
800
|
-
return /* @__PURE__ */ (0,
|
|
801
|
-
/* @__PURE__ */ (0,
|
|
802
|
-
/* @__PURE__ */ (0,
|
|
803
|
-
/* @__PURE__ */ (0,
|
|
2103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
2104
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { children: "Senha alterada" }),
|
|
2105
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { style: { opacity: 0.7 }, children: "Agora \xE9 s\xF3 fazer login com a nova senha." }),
|
|
2106
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { "data-testid": "reset-back-login", type: "button", onClick: () => onNavigate("login"), children: "Ir pro login" })
|
|
804
2107
|
] });
|
|
805
2108
|
}
|
|
806
2109
|
if (f.token === null) {
|
|
807
|
-
return /* @__PURE__ */ (0,
|
|
808
|
-
/* @__PURE__ */ (0,
|
|
809
|
-
/* @__PURE__ */ (0,
|
|
810
|
-
/* @__PURE__ */ (0,
|
|
2110
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
2111
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { children: "Link inv\xE1lido" }),
|
|
2112
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { style: { opacity: 0.7 }, children: "Pe\xE7a um novo link de reset." }),
|
|
2113
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { "data-testid": "reset-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), children: "Pedir novo link" })
|
|
811
2114
|
] });
|
|
812
2115
|
}
|
|
813
|
-
return /* @__PURE__ */ (0,
|
|
814
|
-
/* @__PURE__ */ (0,
|
|
815
|
-
/* @__PURE__ */ (0,
|
|
816
|
-
/* @__PURE__ */ (0,
|
|
2116
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
2117
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { style: { marginBottom: 8 }, children: name }),
|
|
2118
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Escolha uma nova senha" }),
|
|
2119
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("form", { onSubmit: (e) => {
|
|
817
2120
|
e.preventDefault();
|
|
818
2121
|
void f.submit();
|
|
819
2122
|
}, children: [
|
|
820
|
-
/* @__PURE__ */ (0,
|
|
2123
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
821
2124
|
"Nova senha",
|
|
822
|
-
/* @__PURE__ */ (0,
|
|
823
|
-
f.passwordError && /* @__PURE__ */ (0,
|
|
2125
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.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" }),
|
|
2126
|
+
f.passwordError && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
824
2127
|
] }),
|
|
825
|
-
/* @__PURE__ */ (0,
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
826
2129
|
"Confirmar senha",
|
|
827
|
-
/* @__PURE__ */ (0,
|
|
828
|
-
f.confirmError && /* @__PURE__ */ (0,
|
|
2130
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.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" }),
|
|
2131
|
+
f.confirmError && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("small", { style: { color: "#c00" }, children: f.confirmError })
|
|
829
2132
|
] }),
|
|
830
|
-
f.error && /* @__PURE__ */ (0,
|
|
831
|
-
/* @__PURE__ */ (0,
|
|
2133
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
2134
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.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" })
|
|
832
2135
|
] })
|
|
833
2136
|
] });
|
|
834
2137
|
}
|
|
835
2138
|
|
|
836
2139
|
// src/defaults/DefaultPaywall.tsx
|
|
837
|
-
var
|
|
838
|
-
var
|
|
2140
|
+
var import_react15 = require("react");
|
|
2141
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
839
2142
|
function DefaultPaywall() {
|
|
840
2143
|
const config = useTemplateConfig();
|
|
841
2144
|
const { checkout, opening, error } = usePaywallState();
|
|
842
2145
|
const p = config.subscription.paywall_config;
|
|
843
|
-
const [cpf, setCpf] = (0,
|
|
2146
|
+
const [cpf, setCpf] = (0, import_react15.useState)("");
|
|
844
2147
|
const cpfDigits = cpf.replace(/\D/g, "");
|
|
845
2148
|
const canCheckout = cpfDigits.length === 11 && !opening;
|
|
846
|
-
return /* @__PURE__ */ (0,
|
|
847
|
-
/* @__PURE__ */ (0,
|
|
848
|
-
p.subtitle && /* @__PURE__ */ (0,
|
|
849
|
-
/* @__PURE__ */ (0,
|
|
850
|
-
/* @__PURE__ */ (0,
|
|
851
|
-
/* @__PURE__ */ (0,
|
|
2149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("main", { style: { padding: 24, maxWidth: 440, margin: "0 auto", textAlign: "center" }, children: [
|
|
2150
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h1", { style: { marginBottom: 8 }, children: p.title }),
|
|
2151
|
+
p.subtitle && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { opacity: 0.7, marginBottom: 24 }, children: p.subtitle }),
|
|
2152
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("ul", { style: { listStyle: "none", padding: 0, textAlign: "left", marginBottom: 24 }, children: p.benefits.map((b) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("li", { style: { padding: "8px 0", display: "flex", alignItems: "center" }, children: [
|
|
2153
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "aria-hidden": true, style: { marginRight: 8 }, children: "\u2713" }),
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: b })
|
|
852
2155
|
] }, b)) }),
|
|
853
|
-
/* @__PURE__ */ (0,
|
|
854
|
-
/* @__PURE__ */ (0,
|
|
855
|
-
/* @__PURE__ */ (0,
|
|
2156
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { textAlign: "left", marginBottom: 16 }, children: [
|
|
2157
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { style: { display: "block", fontSize: 14, opacity: 0.7, marginBottom: 4 }, children: "Seu CPF (pra emiss\xE3o de recibo)" }),
|
|
2158
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
856
2159
|
"input",
|
|
857
2160
|
{
|
|
858
2161
|
"data-testid": "paywall-cpf",
|
|
@@ -865,8 +2168,8 @@ function DefaultPaywall() {
|
|
|
865
2168
|
}
|
|
866
2169
|
)
|
|
867
2170
|
] }),
|
|
868
|
-
error && /* @__PURE__ */ (0,
|
|
869
|
-
/* @__PURE__ */ (0,
|
|
2171
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: error.message }),
|
|
2172
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
870
2173
|
"button",
|
|
871
2174
|
{
|
|
872
2175
|
"data-testid": "paywall-cta",
|
|
@@ -887,21 +2190,21 @@ function DefaultPaywall() {
|
|
|
887
2190
|
children: opening ? "Abrindo..." : p.cta
|
|
888
2191
|
}
|
|
889
2192
|
),
|
|
890
|
-
p.priceHint && /* @__PURE__ */ (0,
|
|
891
|
-
p.footerNote && /* @__PURE__ */ (0,
|
|
2193
|
+
p.priceHint && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { opacity: 0.6, marginTop: 12 }, children: p.priceHint }),
|
|
2194
|
+
p.footerNote && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { style: { opacity: 0.5, marginTop: 16, fontSize: 12 }, children: p.footerNote })
|
|
892
2195
|
] });
|
|
893
2196
|
}
|
|
894
2197
|
|
|
895
2198
|
// src/AppRoot.tsx
|
|
896
|
-
var
|
|
2199
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
897
2200
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
898
2201
|
function PaymentReturnHandler({ children }) {
|
|
899
2202
|
const { subscription } = (0, import_sdk9.useHook)();
|
|
900
|
-
const subRef = (0,
|
|
2203
|
+
const subRef = (0, import_react16.useRef)(subscription);
|
|
901
2204
|
subRef.current = subscription;
|
|
902
|
-
const runIdRef = (0,
|
|
903
|
-
const [state, setState] = (0,
|
|
904
|
-
const runPoll = (0,
|
|
2205
|
+
const runIdRef = (0, import_react16.useRef)(0);
|
|
2206
|
+
const [state, setState] = (0, import_react16.useState)("idle");
|
|
2207
|
+
const runPoll = (0, import_react16.useCallback)(() => {
|
|
905
2208
|
const runId = ++runIdRef.current;
|
|
906
2209
|
setState("confirming");
|
|
907
2210
|
let attempts = 0;
|
|
@@ -930,7 +2233,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
930
2233
|
};
|
|
931
2234
|
void tick();
|
|
932
2235
|
}, []);
|
|
933
|
-
(0,
|
|
2236
|
+
(0, import_react16.useEffect)(() => {
|
|
934
2237
|
if (typeof window === "undefined") return;
|
|
935
2238
|
const url = new URL(window.location.href);
|
|
936
2239
|
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
@@ -940,20 +2243,20 @@ function PaymentReturnHandler({ children }) {
|
|
|
940
2243
|
};
|
|
941
2244
|
}, [runPoll]);
|
|
942
2245
|
if (state === "confirming") {
|
|
943
|
-
return /* @__PURE__ */ (0,
|
|
2246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
944
2247
|
"div",
|
|
945
2248
|
{
|
|
946
2249
|
role: "status",
|
|
947
2250
|
"aria-live": "polite",
|
|
948
|
-
style:
|
|
2251
|
+
style: overlayStyle2,
|
|
949
2252
|
children: "Confirmando pagamento\u2026"
|
|
950
2253
|
}
|
|
951
2254
|
);
|
|
952
2255
|
}
|
|
953
2256
|
if (state === "waiting") {
|
|
954
|
-
return /* @__PURE__ */ (0,
|
|
955
|
-
/* @__PURE__ */ (0,
|
|
956
|
-
/* @__PURE__ */ (0,
|
|
2257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2258
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
|
|
2259
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
957
2260
|
"button",
|
|
958
2261
|
{
|
|
959
2262
|
type: "button",
|
|
@@ -964,9 +2267,9 @@ function PaymentReturnHandler({ children }) {
|
|
|
964
2267
|
)
|
|
965
2268
|
] }) });
|
|
966
2269
|
}
|
|
967
|
-
return /* @__PURE__ */ (0,
|
|
2270
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_jsx_runtime25.Fragment, { children });
|
|
968
2271
|
}
|
|
969
|
-
var
|
|
2272
|
+
var overlayStyle2 = {
|
|
970
2273
|
position: "fixed",
|
|
971
2274
|
inset: 0,
|
|
972
2275
|
display: "flex",
|
|
@@ -997,14 +2300,14 @@ function AppRoot({
|
|
|
997
2300
|
Reset = DefaultResetScreen,
|
|
998
2301
|
Paywall = DefaultPaywall
|
|
999
2302
|
}) {
|
|
1000
|
-
return /* @__PURE__ */ (0,
|
|
2303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PaymentReturnHandler, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TemplateConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ErrorBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(InstallGate, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AuthGate, { Login, Signup, Forgot, Reset, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PersistedKeysPrefetch, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(SubscriptionGate, { Paywall, children: [
|
|
1001
2304
|
children,
|
|
1002
|
-
/* @__PURE__ */ (0,
|
|
1003
|
-
] }) }) }) }) }) }) });
|
|
2305
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PushPrompt, {})
|
|
2306
|
+
] }) }) }) }) }) }) }) });
|
|
1004
2307
|
}
|
|
1005
2308
|
|
|
1006
2309
|
// src/hooks/usePush.ts
|
|
1007
|
-
var
|
|
2310
|
+
var import_react17 = require("react");
|
|
1008
2311
|
var import_sdk10 = require("@hook-sdk/sdk");
|
|
1009
2312
|
function detectIosNeedsInstall() {
|
|
1010
2313
|
if (typeof navigator === "undefined" || typeof window === "undefined") return false;
|
|
@@ -1032,11 +2335,11 @@ function deriveState(push) {
|
|
|
1032
2335
|
}
|
|
1033
2336
|
function usePush() {
|
|
1034
2337
|
const { push } = (0, import_sdk10.useHook)();
|
|
1035
|
-
const [state, setState] = (0,
|
|
1036
|
-
(0,
|
|
2338
|
+
const [state, setState] = (0, import_react17.useState)(() => deriveState(push));
|
|
2339
|
+
(0, import_react17.useEffect)(() => {
|
|
1037
2340
|
setState(deriveState(push));
|
|
1038
2341
|
}, [push]);
|
|
1039
|
-
const subscribe = (0,
|
|
2342
|
+
const subscribe = (0, import_react17.useCallback)(async () => {
|
|
1040
2343
|
try {
|
|
1041
2344
|
await push.subscribe();
|
|
1042
2345
|
setState({ kind: "subscribed" });
|
|
@@ -1048,7 +2351,7 @@ function usePush() {
|
|
|
1048
2351
|
throw e;
|
|
1049
2352
|
}
|
|
1050
2353
|
}, [push]);
|
|
1051
|
-
const unsubscribe = (0,
|
|
2354
|
+
const unsubscribe = (0, import_react17.useCallback)(async () => {
|
|
1052
2355
|
try {
|
|
1053
2356
|
await push.unsubscribe();
|
|
1054
2357
|
setState({ kind: "prompt" });
|
|
@@ -1061,31 +2364,31 @@ function usePush() {
|
|
|
1061
2364
|
}
|
|
1062
2365
|
|
|
1063
2366
|
// src/components/PushPrompt.tsx
|
|
1064
|
-
var
|
|
2367
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1065
2368
|
function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
|
|
1066
2369
|
const { state, subscribe } = usePush();
|
|
1067
2370
|
if (state.kind === "subscribed") return null;
|
|
1068
2371
|
if (state.kind === "ios_needs_install") {
|
|
1069
|
-
return /* @__PURE__ */ (0,
|
|
1070
|
-
/* @__PURE__ */ (0,
|
|
1071
|
-
/* @__PURE__ */ (0,
|
|
1072
|
-
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0,
|
|
2372
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { children: texts.iosInstallTitle }),
|
|
2374
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { children: texts.iosInstallBody }),
|
|
2375
|
+
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
1073
2376
|
] });
|
|
1074
2377
|
}
|
|
1075
2378
|
if (state.kind === "denied") {
|
|
1076
|
-
return /* @__PURE__ */ (0,
|
|
1077
|
-
/* @__PURE__ */ (0,
|
|
1078
|
-
/* @__PURE__ */ (0,
|
|
2379
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
|
|
2380
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { children: texts.deniedTitle }),
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { children: texts.deniedBody })
|
|
1079
2382
|
] });
|
|
1080
2383
|
}
|
|
1081
2384
|
if (state.kind === "unsupported") {
|
|
1082
|
-
return /* @__PURE__ */ (0,
|
|
2385
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className, role: "region", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { children: texts.unsupportedBody }) });
|
|
1083
2386
|
}
|
|
1084
2387
|
if (state.kind === "error") {
|
|
1085
|
-
return /* @__PURE__ */ (0,
|
|
2388
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { children: state.message }) });
|
|
1086
2389
|
}
|
|
1087
|
-
return /* @__PURE__ */ (0,
|
|
1088
|
-
/* @__PURE__ */ (0,
|
|
2390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className, role: "region", children: [
|
|
2391
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1089
2392
|
"button",
|
|
1090
2393
|
{
|
|
1091
2394
|
type: "button",
|
|
@@ -1099,27 +2402,27 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
|
|
|
1099
2402
|
children: texts.cta
|
|
1100
2403
|
}
|
|
1101
2404
|
),
|
|
1102
|
-
onDeclined && /* @__PURE__ */ (0,
|
|
2405
|
+
onDeclined && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
|
|
1103
2406
|
] });
|
|
1104
2407
|
}
|
|
1105
2408
|
|
|
1106
2409
|
// src/defaults/EmptyState.tsx
|
|
1107
|
-
var
|
|
2410
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1108
2411
|
function EmptyState({ title, description, action }) {
|
|
1109
|
-
return /* @__PURE__ */ (0,
|
|
1110
|
-
/* @__PURE__ */ (0,
|
|
1111
|
-
description && /* @__PURE__ */ (0,
|
|
1112
|
-
action && /* @__PURE__ */ (0,
|
|
2412
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
2413
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h2", { style: { marginBottom: 8 }, children: title }),
|
|
2414
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { style: { opacity: 0.7 }, children: description }),
|
|
2415
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { style: { marginTop: 16 }, children: action })
|
|
1113
2416
|
] });
|
|
1114
2417
|
}
|
|
1115
2418
|
|
|
1116
2419
|
// src/hooks/useAuthPrimitives.ts
|
|
1117
|
-
var
|
|
2420
|
+
var import_react18 = require("react");
|
|
1118
2421
|
var import_sdk11 = require("@hook-sdk/sdk");
|
|
1119
2422
|
var warned = false;
|
|
1120
2423
|
function useAuthPrimitives() {
|
|
1121
2424
|
const { auth } = (0, import_sdk11.useHook)();
|
|
1122
|
-
(0,
|
|
2425
|
+
(0, import_react18.useEffect)(() => {
|
|
1123
2426
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
1124
2427
|
warned = true;
|
|
1125
2428
|
console.warn(
|
|
@@ -1150,14 +2453,14 @@ function useSubscription() {
|
|
|
1150
2453
|
}
|
|
1151
2454
|
|
|
1152
2455
|
// src/hooks/useReminders.ts
|
|
1153
|
-
var
|
|
2456
|
+
var import_react19 = require("react");
|
|
1154
2457
|
var import_sdk13 = require("@hook-sdk/sdk");
|
|
1155
2458
|
function useReminders() {
|
|
1156
2459
|
const { push } = (0, import_sdk13.useHook)();
|
|
1157
2460
|
const r = push.reminders;
|
|
1158
|
-
const [reminders, setReminders] = (0,
|
|
1159
|
-
const [loading, setLoading] = (0,
|
|
1160
|
-
const reload = (0,
|
|
2461
|
+
const [reminders, setReminders] = (0, import_react19.useState)([]);
|
|
2462
|
+
const [loading, setLoading] = (0, import_react19.useState)(true);
|
|
2463
|
+
const reload = (0, import_react19.useCallback)(async () => {
|
|
1161
2464
|
setLoading(true);
|
|
1162
2465
|
try {
|
|
1163
2466
|
const next = await r.list();
|
|
@@ -1166,38 +2469,38 @@ function useReminders() {
|
|
|
1166
2469
|
setLoading(false);
|
|
1167
2470
|
}
|
|
1168
2471
|
}, [r]);
|
|
1169
|
-
(0,
|
|
2472
|
+
(0, import_react19.useEffect)(() => {
|
|
1170
2473
|
void reload();
|
|
1171
2474
|
}, [reload]);
|
|
1172
|
-
const setReminder = (0,
|
|
2475
|
+
const setReminder = (0, import_react19.useCallback)(async (input) => {
|
|
1173
2476
|
await r.set(input);
|
|
1174
2477
|
await reload();
|
|
1175
2478
|
}, [r, reload]);
|
|
1176
|
-
const deleteReminder = (0,
|
|
2479
|
+
const deleteReminder = (0, import_react19.useCallback)(async (slot) => {
|
|
1177
2480
|
await r.delete(slot);
|
|
1178
2481
|
await reload();
|
|
1179
2482
|
}, [r, reload]);
|
|
1180
|
-
const schedule = (0,
|
|
2483
|
+
const schedule = (0, import_react19.useCallback)(async (items) => {
|
|
1181
2484
|
return r.schedule(items);
|
|
1182
2485
|
}, [r]);
|
|
1183
|
-
const setFallbacks = (0,
|
|
2486
|
+
const setFallbacks = (0, import_react19.useCallback)(async (items) => {
|
|
1184
2487
|
return r.setFallbacks(items);
|
|
1185
2488
|
}, [r]);
|
|
1186
2489
|
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
1187
2490
|
}
|
|
1188
2491
|
|
|
1189
2492
|
// src/hooks/useToast.ts
|
|
1190
|
-
var
|
|
2493
|
+
var import_react20 = require("react");
|
|
1191
2494
|
function useToast() {
|
|
1192
|
-
const [items, setItems] = (0,
|
|
1193
|
-
const show = (0,
|
|
2495
|
+
const [items, setItems] = (0, import_react20.useState)([]);
|
|
2496
|
+
const show = (0, import_react20.useCallback)((message, kind = "info") => {
|
|
1194
2497
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1195
2498
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
1196
2499
|
setTimeout(() => {
|
|
1197
2500
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
1198
2501
|
}, 4e3);
|
|
1199
2502
|
}, []);
|
|
1200
|
-
const dismiss = (0,
|
|
2503
|
+
const dismiss = (0, import_react20.useCallback)((id) => {
|
|
1201
2504
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
1202
2505
|
}, []);
|
|
1203
2506
|
return { items, show, dismiss };
|
|
@@ -1212,11 +2515,21 @@ function useToast() {
|
|
|
1212
2515
|
DefaultSignupScreen,
|
|
1213
2516
|
EmptyState,
|
|
1214
2517
|
ErrorBoundary,
|
|
2518
|
+
InstallGate,
|
|
2519
|
+
InstallSplash,
|
|
1215
2520
|
LoadingState,
|
|
1216
2521
|
PushPrompt,
|
|
2522
|
+
detectAndroidBrowser,
|
|
2523
|
+
detectIOSBrowser,
|
|
2524
|
+
detectInAppApp,
|
|
2525
|
+
detectPlatform,
|
|
2526
|
+
detectStandalone,
|
|
2527
|
+
shouldBlockInstall,
|
|
2528
|
+
shouldShowPermanentOption,
|
|
1217
2529
|
useAuth,
|
|
1218
2530
|
useAuthPrimitives,
|
|
1219
2531
|
useForgotForm,
|
|
2532
|
+
useInstallPrompt,
|
|
1220
2533
|
useLoginForm,
|
|
1221
2534
|
usePaywallState,
|
|
1222
2535
|
usePush,
|