@hook-sdk/template 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1600 -184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +114 -1
- package/dist/index.d.ts +114 -1
- package/dist/index.js +1581 -175
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/AppRoot.tsx
|
|
2
|
-
import { useCallback as
|
|
2
|
+
import { useCallback as useCallback7, useEffect as useEffect7, useRef as useRef2, useState as useState12 } from "react";
|
|
3
3
|
import { useHook as useHook8 } from "@hook-sdk/sdk";
|
|
4
4
|
|
|
5
5
|
// src/internal/TemplateConfigContext.tsx
|
|
@@ -164,9 +164,1225 @@ function PushPrompt() {
|
|
|
164
164
|
return null;
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
// src/components/InstallGate/InstallGate.tsx
|
|
168
|
+
import { useEffect as useEffect4, useRef } from "react";
|
|
169
|
+
|
|
170
|
+
// src/hooks/useInstallPrompt.ts
|
|
171
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useState as useState3 } from "react";
|
|
172
|
+
var IOS_RE = /iPad|iPhone|iPod/;
|
|
173
|
+
var IOS_NON_SAFARI_RE = /CriOS|FxiOS|EdgiOS/;
|
|
174
|
+
var ANDROID_RE = /Android/;
|
|
175
|
+
var IN_APP_RE = /Instagram|FBAN|FBAV|BytedanceWebview|TikTok|Line\/|Twitter|Snapchat|Pinterest|LinkedIn|WhatsApp|MicroMessenger|Telegram/i;
|
|
176
|
+
var PERMANENT_DISMISS_REPROMPT_DAYS = 14;
|
|
177
|
+
var SESSION_SKIPS_BEFORE_PERMANENT_OPTION = 2;
|
|
178
|
+
var storageKey = {
|
|
179
|
+
sessionSkip: (slug) => `install:${slug}:session-skip`,
|
|
180
|
+
dismissedAt: (slug) => `install:${slug}:dismissed-at`,
|
|
181
|
+
installedAt: (slug) => `install:${slug}:installed-at`,
|
|
182
|
+
skipCount: (slug) => `install:${slug}:skip-count`
|
|
183
|
+
};
|
|
184
|
+
function detectPlatform(ua) {
|
|
185
|
+
if (IN_APP_RE.test(ua)) return "in-app";
|
|
186
|
+
const isIOS = IOS_RE.test(ua);
|
|
187
|
+
if (isIOS) {
|
|
188
|
+
const isSafari = /Safari/.test(ua) && !IOS_NON_SAFARI_RE.test(ua);
|
|
189
|
+
return isSafari ? "ios-safari" : "ios-other";
|
|
190
|
+
}
|
|
191
|
+
if (ANDROID_RE.test(ua)) return "android";
|
|
192
|
+
return "desktop";
|
|
193
|
+
}
|
|
194
|
+
function detectIOSBrowser(ua) {
|
|
195
|
+
if (!IOS_RE.test(ua)) return null;
|
|
196
|
+
if (/CriOS/.test(ua)) return "chrome";
|
|
197
|
+
if (/FxiOS/.test(ua)) return "firefox";
|
|
198
|
+
if (/EdgiOS/.test(ua)) return "edge";
|
|
199
|
+
if (/Safari/.test(ua)) return "safari";
|
|
200
|
+
return "other";
|
|
201
|
+
}
|
|
202
|
+
function detectAndroidBrowser(ua) {
|
|
203
|
+
if (!ANDROID_RE.test(ua)) return null;
|
|
204
|
+
if (/EdgA/.test(ua)) return "edge";
|
|
205
|
+
if (/OPR|OPT/.test(ua)) return "opera";
|
|
206
|
+
if (/SamsungBrowser/.test(ua)) return "samsung";
|
|
207
|
+
if (/Firefox/.test(ua)) return "firefox";
|
|
208
|
+
if (/Chrome/.test(ua)) return "chrome";
|
|
209
|
+
return "other";
|
|
210
|
+
}
|
|
211
|
+
function detectInAppApp(ua) {
|
|
212
|
+
if (!IN_APP_RE.test(ua)) return null;
|
|
213
|
+
if (/Instagram/i.test(ua)) return "instagram";
|
|
214
|
+
if (/FBAN|FBAV/.test(ua)) return "facebook";
|
|
215
|
+
if (/BytedanceWebview|TikTok/i.test(ua)) return "tiktok";
|
|
216
|
+
if (/WhatsApp/i.test(ua)) return "whatsapp";
|
|
217
|
+
if (/Twitter/i.test(ua)) return "twitter";
|
|
218
|
+
if (/LinkedIn/i.test(ua)) return "linkedin";
|
|
219
|
+
if (/Telegram/i.test(ua)) return "telegram";
|
|
220
|
+
if (/Line\//i.test(ua)) return "line";
|
|
221
|
+
if (/Snapchat/i.test(ua)) return "snapchat";
|
|
222
|
+
if (/Pinterest/i.test(ua)) return "pinterest";
|
|
223
|
+
if (/MicroMessenger/i.test(ua)) return "wechat";
|
|
224
|
+
return "other";
|
|
225
|
+
}
|
|
226
|
+
function detectStandalone() {
|
|
227
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") {
|
|
228
|
+
return { installed: false, source: null };
|
|
229
|
+
}
|
|
230
|
+
const mm = window.matchMedia?.("(display-mode: standalone)");
|
|
231
|
+
if (mm?.matches) return { installed: true, source: "match_media" };
|
|
232
|
+
const fs = window.matchMedia?.("(display-mode: fullscreen)");
|
|
233
|
+
if (fs?.matches) return { installed: true, source: "match_media" };
|
|
234
|
+
if (navigator.standalone === true) return { installed: true, source: "navigator_standalone" };
|
|
235
|
+
return { installed: false, source: null };
|
|
236
|
+
}
|
|
237
|
+
function track(event, props) {
|
|
238
|
+
if (typeof window === "undefined") return;
|
|
239
|
+
window.posthog?.capture?.(event, props);
|
|
240
|
+
}
|
|
241
|
+
function pickVariant(state) {
|
|
242
|
+
if (state.isInstalled) return "none";
|
|
243
|
+
switch (state.platform) {
|
|
244
|
+
case "android":
|
|
245
|
+
return state.isInstallable ? "android-native" : "android-manual";
|
|
246
|
+
case "ios-safari":
|
|
247
|
+
return "ios-safari";
|
|
248
|
+
case "ios-other":
|
|
249
|
+
return "ios-other";
|
|
250
|
+
case "in-app":
|
|
251
|
+
return "in-app";
|
|
252
|
+
case "desktop":
|
|
253
|
+
return state.isInstallable ? "desktop" : "none";
|
|
254
|
+
default:
|
|
255
|
+
return "none";
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function safeStorage() {
|
|
259
|
+
if (typeof localStorage === "undefined") return null;
|
|
260
|
+
try {
|
|
261
|
+
localStorage.setItem("__install_probe", "1");
|
|
262
|
+
localStorage.removeItem("__install_probe");
|
|
263
|
+
return localStorage;
|
|
264
|
+
} catch {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function readPermanentDismiss(slug) {
|
|
269
|
+
const storage = safeStorage();
|
|
270
|
+
if (!storage) return { dismissed: false, dismissedAt: null };
|
|
271
|
+
const raw = storage.getItem(storageKey.dismissedAt(slug));
|
|
272
|
+
if (!raw) return { dismissed: false, dismissedAt: null };
|
|
273
|
+
const parsed = Date.parse(raw);
|
|
274
|
+
if (Number.isNaN(parsed)) return { dismissed: false, dismissedAt: null };
|
|
275
|
+
const daysAgo = (Date.now() - parsed) / (1e3 * 60 * 60 * 24);
|
|
276
|
+
return { dismissed: daysAgo < PERMANENT_DISMISS_REPROMPT_DAYS, dismissedAt: raw };
|
|
277
|
+
}
|
|
278
|
+
function readInstalledMarker(slug) {
|
|
279
|
+
const storage = safeStorage();
|
|
280
|
+
if (!storage) return false;
|
|
281
|
+
return storage.getItem(storageKey.installedAt(slug)) !== null;
|
|
282
|
+
}
|
|
283
|
+
function readSkipCount(slug) {
|
|
284
|
+
const storage = safeStorage();
|
|
285
|
+
if (!storage) return 0;
|
|
286
|
+
const raw = storage.getItem(storageKey.skipCount(slug));
|
|
287
|
+
const n = raw ? Number.parseInt(raw, 10) : 0;
|
|
288
|
+
return Number.isFinite(n) && n >= 0 ? n : 0;
|
|
289
|
+
}
|
|
290
|
+
function readSessionSkip(slug) {
|
|
291
|
+
if (typeof sessionStorage === "undefined") return false;
|
|
292
|
+
try {
|
|
293
|
+
return sessionStorage.getItem(storageKey.sessionSkip(slug)) === "true";
|
|
294
|
+
} catch {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function useInstallPrompt(slug) {
|
|
299
|
+
const ua = typeof navigator !== "undefined" && typeof navigator.userAgent === "string" ? navigator.userAgent : "";
|
|
300
|
+
const platform = detectPlatform(ua);
|
|
301
|
+
const iosBrowser = detectIOSBrowser(ua);
|
|
302
|
+
const androidBrowser = detectAndroidBrowser(ua);
|
|
303
|
+
const inAppApp = detectInAppApp(ua);
|
|
304
|
+
const [isInstallable, setIsInstallable] = useState3(() => {
|
|
305
|
+
if (typeof window === "undefined") return false;
|
|
306
|
+
return window.__pwaInstallPrompt != null;
|
|
307
|
+
});
|
|
308
|
+
const [isInstalled, setIsInstalled] = useState3(() => {
|
|
309
|
+
const { installed } = detectStandalone();
|
|
310
|
+
return installed || readInstalledMarker(slug);
|
|
311
|
+
});
|
|
312
|
+
const [isDismissedSession, setIsDismissedSession] = useState3(() => readSessionSkip(slug));
|
|
313
|
+
const [isDismissedPermanent, setIsDismissedPermanent] = useState3(() => readPermanentDismiss(slug).dismissed);
|
|
314
|
+
const [skipCount, setSkipCount] = useState3(() => readSkipCount(slug));
|
|
315
|
+
useEffect3(() => {
|
|
316
|
+
if (typeof window === "undefined") return;
|
|
317
|
+
if (window.__pwaInstallPrompt) {
|
|
318
|
+
setIsInstallable(true);
|
|
319
|
+
}
|
|
320
|
+
const onPrompt = (e) => {
|
|
321
|
+
e.preventDefault();
|
|
322
|
+
window.__pwaInstallPrompt = e;
|
|
323
|
+
setIsInstallable(true);
|
|
324
|
+
};
|
|
325
|
+
const onInstalled = () => {
|
|
326
|
+
setIsInstalled(true);
|
|
327
|
+
setIsInstallable(false);
|
|
328
|
+
window.__pwaInstallPrompt = null;
|
|
329
|
+
const storage = safeStorage();
|
|
330
|
+
if (storage) storage.setItem(storageKey.installedAt(slug), (/* @__PURE__ */ new Date()).toISOString());
|
|
331
|
+
};
|
|
332
|
+
window.addEventListener("beforeinstallprompt", onPrompt);
|
|
333
|
+
window.addEventListener("appinstalled", onInstalled);
|
|
334
|
+
return () => {
|
|
335
|
+
window.removeEventListener("beforeinstallprompt", onPrompt);
|
|
336
|
+
window.removeEventListener("appinstalled", onInstalled);
|
|
337
|
+
};
|
|
338
|
+
}, [slug]);
|
|
339
|
+
useEffect3(() => {
|
|
340
|
+
if (typeof window === "undefined") return;
|
|
341
|
+
const mq = window.matchMedia?.("(display-mode: standalone)");
|
|
342
|
+
if (!mq) return;
|
|
343
|
+
const handler = (e) => {
|
|
344
|
+
if (e.matches) {
|
|
345
|
+
setIsInstalled(true);
|
|
346
|
+
track("pwa_install_standalone_detected", { slug, source: "match_media" });
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
mq.addEventListener?.("change", handler);
|
|
350
|
+
return () => mq.removeEventListener?.("change", handler);
|
|
351
|
+
}, [slug]);
|
|
352
|
+
const variant = pickVariant({
|
|
353
|
+
platform,
|
|
354
|
+
iosBrowser,
|
|
355
|
+
androidBrowser,
|
|
356
|
+
inAppApp,
|
|
357
|
+
isInstallable,
|
|
358
|
+
isInstalled,
|
|
359
|
+
isDismissedSession,
|
|
360
|
+
isDismissedPermanent,
|
|
361
|
+
skipCount
|
|
362
|
+
});
|
|
363
|
+
const promptInstall = useCallback2(async () => {
|
|
364
|
+
if (typeof window === "undefined") return false;
|
|
365
|
+
const prompt = window.__pwaInstallPrompt;
|
|
366
|
+
if (!prompt) return false;
|
|
367
|
+
track("pwa_install_prompt_clicked", { slug });
|
|
368
|
+
try {
|
|
369
|
+
await prompt.prompt();
|
|
370
|
+
const { outcome } = await prompt.userChoice;
|
|
371
|
+
track("pwa_install_prompt_outcome", { slug, outcome });
|
|
372
|
+
if (outcome === "accepted") {
|
|
373
|
+
setIsInstalled(true);
|
|
374
|
+
setIsInstallable(false);
|
|
375
|
+
window.__pwaInstallPrompt = null;
|
|
376
|
+
const storage = safeStorage();
|
|
377
|
+
if (storage) storage.setItem(storageKey.installedAt(slug), (/* @__PURE__ */ new Date()).toISOString());
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
return false;
|
|
381
|
+
} catch {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
}, [slug]);
|
|
385
|
+
const dismissSession = useCallback2(() => {
|
|
386
|
+
if (typeof sessionStorage !== "undefined") {
|
|
387
|
+
try {
|
|
388
|
+
sessionStorage.setItem(storageKey.sessionSkip(slug), "true");
|
|
389
|
+
} catch {
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
const storage = safeStorage();
|
|
393
|
+
const newCount = skipCount + 1;
|
|
394
|
+
if (storage) storage.setItem(storageKey.skipCount(slug), String(newCount));
|
|
395
|
+
setSkipCount(newCount);
|
|
396
|
+
setIsDismissedSession(true);
|
|
397
|
+
track("pwa_install_session_skip", { slug, platform, skip_count: newCount });
|
|
398
|
+
}, [slug, skipCount, platform]);
|
|
399
|
+
const dismissPermanent = useCallback2(() => {
|
|
400
|
+
const storage = safeStorage();
|
|
401
|
+
if (storage) storage.setItem(storageKey.dismissedAt(slug), (/* @__PURE__ */ new Date()).toISOString());
|
|
402
|
+
setIsDismissedPermanent(true);
|
|
403
|
+
track("pwa_install_permanent_dismiss", { slug, platform, prior_skip_count: skipCount });
|
|
404
|
+
}, [slug, platform, skipCount]);
|
|
405
|
+
const redirectToSafari = useCallback2(() => {
|
|
406
|
+
if (typeof location === "undefined") return;
|
|
407
|
+
track("pwa_install_redirect_to_safari", { slug });
|
|
408
|
+
const url = `safari-https://${location.host}${location.pathname}${location.search}${location.hash}`;
|
|
409
|
+
try {
|
|
410
|
+
window.location.href = url;
|
|
411
|
+
} catch {
|
|
412
|
+
}
|
|
413
|
+
}, [slug]);
|
|
414
|
+
const copyLink = useCallback2(async () => {
|
|
415
|
+
if (typeof navigator === "undefined" || typeof location === "undefined") return;
|
|
416
|
+
try {
|
|
417
|
+
await navigator.clipboard?.writeText?.(location.href);
|
|
418
|
+
} catch {
|
|
419
|
+
}
|
|
420
|
+
}, []);
|
|
421
|
+
const reset = useCallback2(() => {
|
|
422
|
+
const storage = safeStorage();
|
|
423
|
+
if (storage) {
|
|
424
|
+
storage.removeItem(storageKey.dismissedAt(slug));
|
|
425
|
+
storage.removeItem(storageKey.installedAt(slug));
|
|
426
|
+
storage.removeItem(storageKey.skipCount(slug));
|
|
427
|
+
}
|
|
428
|
+
if (typeof sessionStorage !== "undefined") {
|
|
429
|
+
try {
|
|
430
|
+
sessionStorage.removeItem(storageKey.sessionSkip(slug));
|
|
431
|
+
} catch {
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
setIsDismissedSession(false);
|
|
435
|
+
setIsDismissedPermanent(false);
|
|
436
|
+
setSkipCount(0);
|
|
437
|
+
}, [slug]);
|
|
438
|
+
return {
|
|
439
|
+
platform,
|
|
440
|
+
iosBrowser,
|
|
441
|
+
androidBrowser,
|
|
442
|
+
inAppApp,
|
|
443
|
+
isInstallable,
|
|
444
|
+
isInstalled,
|
|
445
|
+
isDismissedSession,
|
|
446
|
+
isDismissedPermanent,
|
|
447
|
+
skipCount,
|
|
448
|
+
variant,
|
|
449
|
+
promptInstall,
|
|
450
|
+
dismissSession,
|
|
451
|
+
dismissPermanent,
|
|
452
|
+
redirectToSafari,
|
|
453
|
+
copyLink,
|
|
454
|
+
reset
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
function shouldBlockInstall(state, now = Date.now()) {
|
|
458
|
+
if (state.isInstalled) return false;
|
|
459
|
+
if (state.variant === "none") return false;
|
|
460
|
+
if (state.isDismissedSession) return false;
|
|
461
|
+
if (state.isDismissedPermanent) {
|
|
462
|
+
void now;
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
if (state.platform === "desktop" && !state.isInstallable) return false;
|
|
466
|
+
if (state.platform === "unknown") return false;
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
function shouldShowPermanentOption(state) {
|
|
470
|
+
return state.skipCount >= SESSION_SKIPS_BEFORE_PERMANENT_OPTION;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// src/components/InstallGate/copy.ts
|
|
474
|
+
var INSTALL_COPY = {
|
|
475
|
+
android: {
|
|
476
|
+
native: {
|
|
477
|
+
title: "Instale no seu celular",
|
|
478
|
+
subtitle: "Acesso r\xE1pido, sem precisar do navegador",
|
|
479
|
+
cta: "Baixar",
|
|
480
|
+
skip: "Continuar no navegador",
|
|
481
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
482
|
+
},
|
|
483
|
+
manual: {
|
|
484
|
+
title: "Instale em 2 toques",
|
|
485
|
+
subtitle: 'Toque no menu do navegador e escolha "Instalar aplicativo"',
|
|
486
|
+
step1: "Toque no menu do navegador",
|
|
487
|
+
step2: 'Escolha "Instalar aplicativo"',
|
|
488
|
+
cta: "Entendi",
|
|
489
|
+
skip: "Continuar no navegador",
|
|
490
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
iosSafari: {
|
|
494
|
+
title: "Adicione \xE0 sua Tela de In\xEDcio",
|
|
495
|
+
subtitle: "Siga os 3 passos",
|
|
496
|
+
step1: {
|
|
497
|
+
title: "Toque em Compartilhar",
|
|
498
|
+
subtitle: "Na barra inferior do Safari"
|
|
499
|
+
},
|
|
500
|
+
step2: {
|
|
501
|
+
title: 'Role e toque em "Adicionar \xE0 Tela de In\xEDcio"',
|
|
502
|
+
iconLabel: "Adicionar \xE0 Tela de In\xEDcio"
|
|
503
|
+
},
|
|
504
|
+
step3: {
|
|
505
|
+
title: 'Toque em "Adicionar" pra confirmar',
|
|
506
|
+
buttonLabel: "Adicionar"
|
|
507
|
+
},
|
|
508
|
+
skip: "Continuar no Safari",
|
|
509
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
510
|
+
},
|
|
511
|
+
iosOther: {
|
|
512
|
+
title: "Abra no Safari pra instalar",
|
|
513
|
+
subtitle: "No Chrome/Firefox/Edge do iPhone n\xE3o d\xE1 pra instalar PWA. Abra o link no Safari.",
|
|
514
|
+
ctaPrimary: "Abrir no Safari",
|
|
515
|
+
ctaSecondary: "Copiar link",
|
|
516
|
+
copiedToast: "Link copiado. Cole no Safari.",
|
|
517
|
+
skip: "Continuar mesmo assim",
|
|
518
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
519
|
+
},
|
|
520
|
+
inApp: {
|
|
521
|
+
instagram: {
|
|
522
|
+
title: "Pra instalar, abra fora do Instagram",
|
|
523
|
+
step1: "Toque em \u22EF (canto superior direito)",
|
|
524
|
+
step2: 'Escolha "Abrir no navegador externo"'
|
|
525
|
+
},
|
|
526
|
+
facebook: {
|
|
527
|
+
title: "Pra instalar, abra fora do Facebook",
|
|
528
|
+
step1: "Toque em \u22EE",
|
|
529
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
530
|
+
},
|
|
531
|
+
tiktok: {
|
|
532
|
+
title: "Pra instalar, abra fora do TikTok",
|
|
533
|
+
step1: "Toque em \u22EF",
|
|
534
|
+
step2: 'Escolha "Abrir no Safari" (iOS) ou "Abrir no Chrome" (Android)'
|
|
535
|
+
},
|
|
536
|
+
whatsapp: {
|
|
537
|
+
title: "Pra instalar, abra fora do WhatsApp",
|
|
538
|
+
step1: "Toque longo no link",
|
|
539
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
540
|
+
},
|
|
541
|
+
twitter: {
|
|
542
|
+
title: "Pra instalar, abra fora do Twitter",
|
|
543
|
+
step1: "Toque em \u22EF",
|
|
544
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
545
|
+
},
|
|
546
|
+
linkedin: {
|
|
547
|
+
title: "Pra instalar, abra fora do LinkedIn",
|
|
548
|
+
step1: "Toque em \u22EF",
|
|
549
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
550
|
+
},
|
|
551
|
+
telegram: {
|
|
552
|
+
title: "Pra instalar, abra fora do Telegram",
|
|
553
|
+
step1: "Toque em \u22EE",
|
|
554
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
555
|
+
},
|
|
556
|
+
line: {
|
|
557
|
+
title: "Pra instalar, abra fora do LINE",
|
|
558
|
+
step1: "Toque em \u22EF",
|
|
559
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
560
|
+
},
|
|
561
|
+
snapchat: {
|
|
562
|
+
title: "Pra instalar, abra fora do Snapchat",
|
|
563
|
+
step1: "Mantenha pressionado o link",
|
|
564
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
565
|
+
},
|
|
566
|
+
pinterest: {
|
|
567
|
+
title: "Pra instalar, abra fora do Pinterest",
|
|
568
|
+
step1: "Toque em \u22EF",
|
|
569
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
570
|
+
},
|
|
571
|
+
wechat: {
|
|
572
|
+
title: "Pra instalar, abra fora do WeChat",
|
|
573
|
+
step1: "Toque em \u22EF",
|
|
574
|
+
step2: 'Escolha "Abrir no navegador"'
|
|
575
|
+
},
|
|
576
|
+
other: {
|
|
577
|
+
title: "Abra no navegador do celular",
|
|
578
|
+
step1: "Toque no menu do app atual",
|
|
579
|
+
step2: 'Escolha "Abrir no Chrome" ou "Abrir no Safari"'
|
|
580
|
+
},
|
|
581
|
+
copy: "Copiar link",
|
|
582
|
+
copiedToast: "Link copiado. Cole no Chrome/Safari.",
|
|
583
|
+
skip: "Continuar aqui mesmo",
|
|
584
|
+
skipPermanent: "N\xE3o me pergunte mais"
|
|
585
|
+
},
|
|
586
|
+
desktop: {
|
|
587
|
+
title: "Instale no computador",
|
|
588
|
+
subtitle: "Acesso r\xE1pido",
|
|
589
|
+
cta: "Baixar",
|
|
590
|
+
close: "Fechar"
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
// src/components/InstallGate/InstallSplash.tsx
|
|
595
|
+
import { jsx as jsx7, jsxs } from "react/jsx-runtime";
|
|
596
|
+
function InstallSplash({ children, title, subtitle }) {
|
|
597
|
+
const { name, theme } = useTemplateConfig();
|
|
598
|
+
const iconUrl = theme.icon_url || theme.logo_url || null;
|
|
599
|
+
return /* @__PURE__ */ jsx7(
|
|
600
|
+
"div",
|
|
601
|
+
{
|
|
602
|
+
role: "dialog",
|
|
603
|
+
"aria-modal": "true",
|
|
604
|
+
"aria-labelledby": "install-splash-title",
|
|
605
|
+
"aria-describedby": subtitle ? "install-splash-subtitle" : void 0,
|
|
606
|
+
style: overlayStyle,
|
|
607
|
+
children: /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
|
|
608
|
+
/* @__PURE__ */ jsx7("div", { style: { display: "flex", justifyContent: "center", marginBottom: 16 }, children: iconUrl ? /* @__PURE__ */ jsx7(
|
|
609
|
+
"img",
|
|
610
|
+
{
|
|
611
|
+
src: iconUrl,
|
|
612
|
+
alt: `\xCDcone de ${name}`,
|
|
613
|
+
style: { width: 80, height: 80, borderRadius: 20, objectFit: "cover" }
|
|
614
|
+
}
|
|
615
|
+
) : /* @__PURE__ */ jsx7(
|
|
616
|
+
"div",
|
|
617
|
+
{
|
|
618
|
+
style: {
|
|
619
|
+
width: 80,
|
|
620
|
+
height: 80,
|
|
621
|
+
borderRadius: 20,
|
|
622
|
+
background: "var(--hook-color-primary)",
|
|
623
|
+
color: "#fff",
|
|
624
|
+
display: "flex",
|
|
625
|
+
alignItems: "center",
|
|
626
|
+
justifyContent: "center",
|
|
627
|
+
fontSize: 36,
|
|
628
|
+
fontWeight: 700
|
|
629
|
+
},
|
|
630
|
+
children: name.charAt(0).toUpperCase()
|
|
631
|
+
}
|
|
632
|
+
) }),
|
|
633
|
+
/* @__PURE__ */ jsx7("h1", { id: "install-splash-title", style: titleStyle, children: title }),
|
|
634
|
+
subtitle && /* @__PURE__ */ jsx7("p", { id: "install-splash-subtitle", style: subtitleStyle, children: subtitle }),
|
|
635
|
+
/* @__PURE__ */ jsx7("div", { style: { marginTop: 24 }, children }),
|
|
636
|
+
/* @__PURE__ */ jsx7("p", { style: footerStyle, children: "por Hook" })
|
|
637
|
+
] })
|
|
638
|
+
}
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
var primaryButtonStyle = {
|
|
642
|
+
width: "100%",
|
|
643
|
+
padding: "14px 20px",
|
|
644
|
+
background: "var(--hook-color-primary)",
|
|
645
|
+
color: "#fff",
|
|
646
|
+
border: "none",
|
|
647
|
+
borderRadius: 999,
|
|
648
|
+
fontSize: 17,
|
|
649
|
+
fontWeight: 600,
|
|
650
|
+
cursor: "pointer",
|
|
651
|
+
marginBottom: 12
|
|
652
|
+
};
|
|
653
|
+
var secondaryButtonStyle = {
|
|
654
|
+
width: "100%",
|
|
655
|
+
padding: "12px 20px",
|
|
656
|
+
background: "transparent",
|
|
657
|
+
color: "var(--hook-color-primary)",
|
|
658
|
+
border: "1px solid var(--hook-color-primary)",
|
|
659
|
+
borderRadius: 999,
|
|
660
|
+
fontSize: 15,
|
|
661
|
+
fontWeight: 500,
|
|
662
|
+
cursor: "pointer",
|
|
663
|
+
marginBottom: 12
|
|
664
|
+
};
|
|
665
|
+
var skipLinkStyle = {
|
|
666
|
+
display: "block",
|
|
667
|
+
width: "100%",
|
|
668
|
+
padding: "10px",
|
|
669
|
+
marginTop: 8,
|
|
670
|
+
background: "transparent",
|
|
671
|
+
color: "#555",
|
|
672
|
+
border: "none",
|
|
673
|
+
fontSize: 14,
|
|
674
|
+
textDecoration: "underline",
|
|
675
|
+
cursor: "pointer",
|
|
676
|
+
textAlign: "center"
|
|
677
|
+
};
|
|
678
|
+
var skipPermanentLinkStyle = {
|
|
679
|
+
...skipLinkStyle,
|
|
680
|
+
color: "#999",
|
|
681
|
+
fontSize: 13,
|
|
682
|
+
marginTop: 4
|
|
683
|
+
};
|
|
684
|
+
var overlayStyle = {
|
|
685
|
+
position: "fixed",
|
|
686
|
+
inset: 0,
|
|
687
|
+
background: "var(--hook-color-background, #fafafa)",
|
|
688
|
+
zIndex: 1e4,
|
|
689
|
+
display: "flex",
|
|
690
|
+
alignItems: "center",
|
|
691
|
+
justifyContent: "center",
|
|
692
|
+
padding: 20,
|
|
693
|
+
overflow: "auto"
|
|
694
|
+
};
|
|
695
|
+
var cardStyle = {
|
|
696
|
+
width: "100%",
|
|
697
|
+
maxWidth: 420,
|
|
698
|
+
padding: 24,
|
|
699
|
+
textAlign: "center"
|
|
700
|
+
};
|
|
701
|
+
var titleStyle = {
|
|
702
|
+
fontSize: 24,
|
|
703
|
+
fontWeight: 700,
|
|
704
|
+
lineHeight: 1.2,
|
|
705
|
+
margin: "0 0 8px 0",
|
|
706
|
+
color: "#111"
|
|
707
|
+
};
|
|
708
|
+
var subtitleStyle = {
|
|
709
|
+
fontSize: 15,
|
|
710
|
+
lineHeight: 1.4,
|
|
711
|
+
color: "#555",
|
|
712
|
+
margin: 0
|
|
713
|
+
};
|
|
714
|
+
var footerStyle = {
|
|
715
|
+
fontSize: 11,
|
|
716
|
+
color: "#aaa",
|
|
717
|
+
marginTop: 32,
|
|
718
|
+
letterSpacing: 0.5
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
// src/components/InstallGate/icons.tsx
|
|
722
|
+
import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
723
|
+
var defaultSvgProps = (size) => ({
|
|
724
|
+
width: size,
|
|
725
|
+
height: size,
|
|
726
|
+
viewBox: "0 0 24 24",
|
|
727
|
+
fill: "none",
|
|
728
|
+
stroke: "currentColor",
|
|
729
|
+
strokeWidth: 2,
|
|
730
|
+
strokeLinecap: "round",
|
|
731
|
+
strokeLinejoin: "round"
|
|
732
|
+
});
|
|
733
|
+
function ShareIconIOS({ size = 24, style, className }) {
|
|
734
|
+
return /* @__PURE__ */ jsxs2("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
735
|
+
/* @__PURE__ */ jsx8("path", { d: "M12 2L12 15" }),
|
|
736
|
+
/* @__PURE__ */ jsx8("path", { d: "M8 6L12 2L16 6" }),
|
|
737
|
+
/* @__PURE__ */ jsx8("path", { d: "M4 11v9a2 2 0 002 2h12a2 2 0 002-2v-9" })
|
|
738
|
+
] });
|
|
739
|
+
}
|
|
740
|
+
function MenuDotsVerticalIcon({ size = 24, style, className }) {
|
|
741
|
+
return /* @__PURE__ */ jsxs2("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
742
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "5", r: "1.5" }),
|
|
743
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "1.5" }),
|
|
744
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "19", r: "1.5" })
|
|
745
|
+
] });
|
|
746
|
+
}
|
|
747
|
+
function MenuDotsHorizontalIcon({ size = 24, style, className }) {
|
|
748
|
+
return /* @__PURE__ */ jsxs2("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
749
|
+
/* @__PURE__ */ jsx8("circle", { cx: "5", cy: "12", r: "1.5" }),
|
|
750
|
+
/* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "1.5" }),
|
|
751
|
+
/* @__PURE__ */ jsx8("circle", { cx: "19", cy: "12", r: "1.5" })
|
|
752
|
+
] });
|
|
753
|
+
}
|
|
754
|
+
function SquarePlusIcon({ size = 24, style, className }) {
|
|
755
|
+
return /* @__PURE__ */ jsxs2("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
756
|
+
/* @__PURE__ */ jsx8("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
|
|
757
|
+
/* @__PURE__ */ jsx8("path", { d: "M12 8v8" }),
|
|
758
|
+
/* @__PURE__ */ jsx8("path", { d: "M8 12h8" })
|
|
759
|
+
] });
|
|
760
|
+
}
|
|
761
|
+
function DownloadIcon({ size = 24, style, className }) {
|
|
762
|
+
return /* @__PURE__ */ jsxs2("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
763
|
+
/* @__PURE__ */ jsx8("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" }),
|
|
764
|
+
/* @__PURE__ */ jsx8("polyline", { points: "7 10 12 15 17 10" }),
|
|
765
|
+
/* @__PURE__ */ jsx8("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
|
|
766
|
+
] });
|
|
767
|
+
}
|
|
768
|
+
function ExternalLinkIcon({ size = 24, style, className }) {
|
|
769
|
+
return /* @__PURE__ */ jsxs2("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
770
|
+
/* @__PURE__ */ jsx8("path", { d: "M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6" }),
|
|
771
|
+
/* @__PURE__ */ jsx8("polyline", { points: "15 3 21 3 21 9" }),
|
|
772
|
+
/* @__PURE__ */ jsx8("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
|
|
773
|
+
] });
|
|
774
|
+
}
|
|
775
|
+
function XIcon({ size = 20, style, className }) {
|
|
776
|
+
return /* @__PURE__ */ jsxs2("svg", { ...defaultSvgProps(size), style, className, "aria-hidden": "true", children: [
|
|
777
|
+
/* @__PURE__ */ jsx8("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
778
|
+
/* @__PURE__ */ jsx8("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
779
|
+
] });
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// src/components/InstallGate/variants/AndroidNativeVariant.tsx
|
|
783
|
+
import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
784
|
+
function AndroidNativeVariant({
|
|
785
|
+
state,
|
|
786
|
+
actions
|
|
787
|
+
}) {
|
|
788
|
+
const copy = INSTALL_COPY.android.native;
|
|
789
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
790
|
+
return /* @__PURE__ */ jsxs3(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
|
|
791
|
+
/* @__PURE__ */ jsxs3(
|
|
792
|
+
"button",
|
|
793
|
+
{
|
|
794
|
+
"data-testid": "install-prompt-cta-android-native",
|
|
795
|
+
type: "button",
|
|
796
|
+
onClick: () => void actions.promptInstall(),
|
|
797
|
+
style: { ...primaryButtonStyle, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8 },
|
|
798
|
+
children: [
|
|
799
|
+
/* @__PURE__ */ jsx9(DownloadIcon, { size: 18 }),
|
|
800
|
+
copy.cta
|
|
801
|
+
]
|
|
802
|
+
}
|
|
803
|
+
),
|
|
804
|
+
/* @__PURE__ */ jsx9(
|
|
805
|
+
"button",
|
|
806
|
+
{
|
|
807
|
+
"data-testid": "install-prompt-skip-session",
|
|
808
|
+
type: "button",
|
|
809
|
+
onClick: actions.dismissSession,
|
|
810
|
+
style: skipLinkStyle,
|
|
811
|
+
children: copy.skip
|
|
812
|
+
}
|
|
813
|
+
),
|
|
814
|
+
showPermanent && /* @__PURE__ */ jsx9(
|
|
815
|
+
"button",
|
|
816
|
+
{
|
|
817
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
818
|
+
type: "button",
|
|
819
|
+
onClick: actions.dismissPermanent,
|
|
820
|
+
style: skipPermanentLinkStyle,
|
|
821
|
+
children: copy.skipPermanent
|
|
822
|
+
}
|
|
823
|
+
)
|
|
824
|
+
] });
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// src/components/InstallGate/variants/AndroidManualVariant.tsx
|
|
828
|
+
import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
829
|
+
function AndroidManualVariant({
|
|
830
|
+
state,
|
|
831
|
+
actions
|
|
832
|
+
}) {
|
|
833
|
+
const copy = INSTALL_COPY.android.manual;
|
|
834
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
835
|
+
return /* @__PURE__ */ jsxs4(InstallSplash, { title: copy.title, children: [
|
|
836
|
+
/* @__PURE__ */ jsx10(Step, { n: 1, icon: /* @__PURE__ */ jsx10(MenuDotsVerticalIcon, { size: 20 }), children: copy.step1 }),
|
|
837
|
+
/* @__PURE__ */ jsx10(Step, { n: 2, icon: /* @__PURE__ */ jsx10(DownloadIcon, { size: 18 }), children: copy.step2 }),
|
|
838
|
+
/* @__PURE__ */ jsx10(
|
|
839
|
+
"button",
|
|
840
|
+
{
|
|
841
|
+
"data-testid": "install-prompt-cta-android-manual",
|
|
842
|
+
type: "button",
|
|
843
|
+
onClick: actions.dismissSession,
|
|
844
|
+
style: primaryButtonStyle,
|
|
845
|
+
children: copy.cta
|
|
846
|
+
}
|
|
847
|
+
),
|
|
848
|
+
/* @__PURE__ */ jsx10(
|
|
849
|
+
"button",
|
|
850
|
+
{
|
|
851
|
+
"data-testid": "install-prompt-skip-session",
|
|
852
|
+
type: "button",
|
|
853
|
+
onClick: actions.dismissSession,
|
|
854
|
+
style: skipLinkStyle,
|
|
855
|
+
children: copy.skip
|
|
856
|
+
}
|
|
857
|
+
),
|
|
858
|
+
showPermanent && /* @__PURE__ */ jsx10(
|
|
859
|
+
"button",
|
|
860
|
+
{
|
|
861
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
862
|
+
type: "button",
|
|
863
|
+
onClick: actions.dismissPermanent,
|
|
864
|
+
style: skipPermanentLinkStyle,
|
|
865
|
+
children: copy.skipPermanent
|
|
866
|
+
}
|
|
867
|
+
)
|
|
868
|
+
] });
|
|
869
|
+
}
|
|
870
|
+
function Step({ n, icon, children }) {
|
|
871
|
+
return /* @__PURE__ */ jsxs4(
|
|
872
|
+
"div",
|
|
873
|
+
{
|
|
874
|
+
style: {
|
|
875
|
+
display: "flex",
|
|
876
|
+
alignItems: "center",
|
|
877
|
+
gap: 12,
|
|
878
|
+
padding: "12px 14px",
|
|
879
|
+
background: "#f5f5f7",
|
|
880
|
+
borderRadius: 12,
|
|
881
|
+
marginBottom: 10,
|
|
882
|
+
textAlign: "left"
|
|
883
|
+
},
|
|
884
|
+
children: [
|
|
885
|
+
/* @__PURE__ */ jsx10(
|
|
886
|
+
"div",
|
|
887
|
+
{
|
|
888
|
+
style: {
|
|
889
|
+
width: 28,
|
|
890
|
+
height: 28,
|
|
891
|
+
borderRadius: "50%",
|
|
892
|
+
background: "var(--hook-color-primary)",
|
|
893
|
+
color: "#fff",
|
|
894
|
+
display: "flex",
|
|
895
|
+
alignItems: "center",
|
|
896
|
+
justifyContent: "center",
|
|
897
|
+
fontSize: 14,
|
|
898
|
+
fontWeight: 700,
|
|
899
|
+
flexShrink: 0
|
|
900
|
+
},
|
|
901
|
+
children: n
|
|
902
|
+
}
|
|
903
|
+
),
|
|
904
|
+
/* @__PURE__ */ jsx10("div", { style: { flex: 1, fontSize: 15, color: "#333" }, children }),
|
|
905
|
+
/* @__PURE__ */ jsx10("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
|
|
906
|
+
]
|
|
907
|
+
}
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// src/components/InstallGate/variants/IOSafariVariant.tsx
|
|
912
|
+
import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
913
|
+
function IOSafariVariant({
|
|
914
|
+
state,
|
|
915
|
+
actions
|
|
916
|
+
}) {
|
|
917
|
+
const copy = INSTALL_COPY.iosSafari;
|
|
918
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
919
|
+
return /* @__PURE__ */ jsxs5(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
|
|
920
|
+
/* @__PURE__ */ jsx11(
|
|
921
|
+
Step2,
|
|
922
|
+
{
|
|
923
|
+
n: 1,
|
|
924
|
+
title: copy.step1.title,
|
|
925
|
+
subtitle: copy.step1.subtitle,
|
|
926
|
+
visual: /* @__PURE__ */ jsx11(
|
|
927
|
+
"div",
|
|
928
|
+
{
|
|
929
|
+
style: {
|
|
930
|
+
display: "flex",
|
|
931
|
+
justifyContent: "center",
|
|
932
|
+
alignItems: "center",
|
|
933
|
+
background: "#f5f5f7",
|
|
934
|
+
borderRadius: 12,
|
|
935
|
+
padding: "12px 0",
|
|
936
|
+
marginTop: 8
|
|
937
|
+
},
|
|
938
|
+
children: /* @__PURE__ */ jsx11(ShareIconIOS, { size: 32, style: { color: "var(--hook-color-primary)" } })
|
|
939
|
+
}
|
|
940
|
+
)
|
|
941
|
+
}
|
|
942
|
+
),
|
|
943
|
+
/* @__PURE__ */ jsx11(
|
|
944
|
+
Step2,
|
|
945
|
+
{
|
|
946
|
+
n: 2,
|
|
947
|
+
title: copy.step2.title,
|
|
948
|
+
visual: /* @__PURE__ */ jsxs5(
|
|
949
|
+
"div",
|
|
950
|
+
{
|
|
951
|
+
style: {
|
|
952
|
+
display: "flex",
|
|
953
|
+
alignItems: "center",
|
|
954
|
+
gap: 10,
|
|
955
|
+
background: "#f5f5f7",
|
|
956
|
+
borderRadius: 12,
|
|
957
|
+
padding: "12px 14px",
|
|
958
|
+
marginTop: 8
|
|
959
|
+
},
|
|
960
|
+
children: [
|
|
961
|
+
/* @__PURE__ */ jsx11(SquarePlusIcon, { size: 22, style: { color: "#555" } }),
|
|
962
|
+
/* @__PURE__ */ jsx11("span", { style: { fontSize: 14, color: "#333" }, children: copy.step2.iconLabel })
|
|
963
|
+
]
|
|
964
|
+
}
|
|
965
|
+
)
|
|
966
|
+
}
|
|
967
|
+
),
|
|
968
|
+
/* @__PURE__ */ jsx11(
|
|
969
|
+
Step2,
|
|
970
|
+
{
|
|
971
|
+
n: 3,
|
|
972
|
+
title: copy.step3.title,
|
|
973
|
+
visual: /* @__PURE__ */ jsx11(
|
|
974
|
+
"div",
|
|
975
|
+
{
|
|
976
|
+
style: {
|
|
977
|
+
display: "flex",
|
|
978
|
+
justifyContent: "flex-end",
|
|
979
|
+
background: "#f5f5f7",
|
|
980
|
+
borderRadius: 12,
|
|
981
|
+
padding: "10px 14px",
|
|
982
|
+
marginTop: 8
|
|
983
|
+
},
|
|
984
|
+
children: /* @__PURE__ */ jsx11(
|
|
985
|
+
"span",
|
|
986
|
+
{
|
|
987
|
+
style: {
|
|
988
|
+
color: "var(--hook-color-primary)",
|
|
989
|
+
fontSize: 15,
|
|
990
|
+
fontWeight: 600
|
|
991
|
+
},
|
|
992
|
+
children: copy.step3.buttonLabel
|
|
993
|
+
}
|
|
994
|
+
)
|
|
995
|
+
}
|
|
996
|
+
)
|
|
997
|
+
}
|
|
998
|
+
),
|
|
999
|
+
/* @__PURE__ */ jsx11(
|
|
1000
|
+
"button",
|
|
1001
|
+
{
|
|
1002
|
+
"data-testid": "install-prompt-skip-session",
|
|
1003
|
+
type: "button",
|
|
1004
|
+
onClick: actions.dismissSession,
|
|
1005
|
+
style: { ...skipLinkStyle, marginTop: 16 },
|
|
1006
|
+
children: copy.skip
|
|
1007
|
+
}
|
|
1008
|
+
),
|
|
1009
|
+
showPermanent && /* @__PURE__ */ jsx11(
|
|
1010
|
+
"button",
|
|
1011
|
+
{
|
|
1012
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
1013
|
+
type: "button",
|
|
1014
|
+
onClick: actions.dismissPermanent,
|
|
1015
|
+
style: skipPermanentLinkStyle,
|
|
1016
|
+
children: copy.skipPermanent
|
|
1017
|
+
}
|
|
1018
|
+
)
|
|
1019
|
+
] });
|
|
1020
|
+
}
|
|
1021
|
+
function Step2({
|
|
1022
|
+
n,
|
|
1023
|
+
title,
|
|
1024
|
+
subtitle,
|
|
1025
|
+
visual
|
|
1026
|
+
}) {
|
|
1027
|
+
return /* @__PURE__ */ jsxs5(
|
|
1028
|
+
"div",
|
|
1029
|
+
{
|
|
1030
|
+
style: {
|
|
1031
|
+
display: "flex",
|
|
1032
|
+
alignItems: "flex-start",
|
|
1033
|
+
gap: 12,
|
|
1034
|
+
marginBottom: 16,
|
|
1035
|
+
textAlign: "left"
|
|
1036
|
+
},
|
|
1037
|
+
children: [
|
|
1038
|
+
/* @__PURE__ */ jsx11(
|
|
1039
|
+
"div",
|
|
1040
|
+
{
|
|
1041
|
+
style: {
|
|
1042
|
+
width: 32,
|
|
1043
|
+
height: 32,
|
|
1044
|
+
borderRadius: 10,
|
|
1045
|
+
background: "var(--hook-color-primary)",
|
|
1046
|
+
color: "#fff",
|
|
1047
|
+
display: "flex",
|
|
1048
|
+
alignItems: "center",
|
|
1049
|
+
justifyContent: "center",
|
|
1050
|
+
fontSize: 15,
|
|
1051
|
+
fontWeight: 700,
|
|
1052
|
+
flexShrink: 0
|
|
1053
|
+
},
|
|
1054
|
+
children: n
|
|
1055
|
+
}
|
|
1056
|
+
),
|
|
1057
|
+
/* @__PURE__ */ jsxs5("div", { style: { flex: 1 }, children: [
|
|
1058
|
+
/* @__PURE__ */ jsx11("p", { style: { margin: 0, fontSize: 15, fontWeight: 500, color: "#111", lineHeight: 1.3 }, children: title }),
|
|
1059
|
+
subtitle && /* @__PURE__ */ jsx11("p", { style: { margin: "4px 0 0 0", fontSize: 13, color: "#777" }, children: subtitle }),
|
|
1060
|
+
visual
|
|
1061
|
+
] })
|
|
1062
|
+
]
|
|
1063
|
+
}
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// src/components/InstallGate/variants/IOSOtherVariant.tsx
|
|
1068
|
+
import { useState as useState4 } from "react";
|
|
1069
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1070
|
+
function IOSOtherVariant({
|
|
1071
|
+
state,
|
|
1072
|
+
actions
|
|
1073
|
+
}) {
|
|
1074
|
+
const copy = INSTALL_COPY.iosOther;
|
|
1075
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
1076
|
+
const [copied, setCopied] = useState4(false);
|
|
1077
|
+
const handleCopy = async () => {
|
|
1078
|
+
await actions.copyLink();
|
|
1079
|
+
setCopied(true);
|
|
1080
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
1081
|
+
};
|
|
1082
|
+
return /* @__PURE__ */ jsxs6(InstallSplash, { title: copy.title, subtitle: copy.subtitle, children: [
|
|
1083
|
+
/* @__PURE__ */ jsx12(
|
|
1084
|
+
"button",
|
|
1085
|
+
{
|
|
1086
|
+
"data-testid": "install-prompt-cta-ios-other-primary",
|
|
1087
|
+
type: "button",
|
|
1088
|
+
onClick: actions.redirectToSafari,
|
|
1089
|
+
style: primaryButtonStyle,
|
|
1090
|
+
children: copy.ctaPrimary
|
|
1091
|
+
}
|
|
1092
|
+
),
|
|
1093
|
+
/* @__PURE__ */ jsx12(
|
|
1094
|
+
"button",
|
|
1095
|
+
{
|
|
1096
|
+
"data-testid": "install-prompt-cta-ios-other-secondary",
|
|
1097
|
+
type: "button",
|
|
1098
|
+
onClick: () => void handleCopy(),
|
|
1099
|
+
style: secondaryButtonStyle,
|
|
1100
|
+
children: copied ? copy.copiedToast : copy.ctaSecondary
|
|
1101
|
+
}
|
|
1102
|
+
),
|
|
1103
|
+
/* @__PURE__ */ jsx12(
|
|
1104
|
+
"button",
|
|
1105
|
+
{
|
|
1106
|
+
"data-testid": "install-prompt-skip-session",
|
|
1107
|
+
type: "button",
|
|
1108
|
+
onClick: actions.dismissSession,
|
|
1109
|
+
style: skipLinkStyle,
|
|
1110
|
+
children: copy.skip
|
|
1111
|
+
}
|
|
1112
|
+
),
|
|
1113
|
+
showPermanent && /* @__PURE__ */ jsx12(
|
|
1114
|
+
"button",
|
|
1115
|
+
{
|
|
1116
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
1117
|
+
type: "button",
|
|
1118
|
+
onClick: actions.dismissPermanent,
|
|
1119
|
+
style: skipPermanentLinkStyle,
|
|
1120
|
+
children: copy.skipPermanent
|
|
1121
|
+
}
|
|
1122
|
+
)
|
|
1123
|
+
] });
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// src/components/InstallGate/variants/InAppBrowserVariant.tsx
|
|
1127
|
+
import { useState as useState5 } from "react";
|
|
1128
|
+
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1129
|
+
function InAppBrowserVariant({
|
|
1130
|
+
state,
|
|
1131
|
+
actions
|
|
1132
|
+
}) {
|
|
1133
|
+
const app = state.inAppApp ?? "other";
|
|
1134
|
+
const appCopy = INSTALL_COPY.inApp[app] ?? INSTALL_COPY.inApp.other;
|
|
1135
|
+
const copy = INSTALL_COPY.inApp;
|
|
1136
|
+
const showPermanent = shouldShowPermanentOption(state);
|
|
1137
|
+
const [copied, setCopied] = useState5(false);
|
|
1138
|
+
const handleCopy = async () => {
|
|
1139
|
+
await actions.copyLink();
|
|
1140
|
+
setCopied(true);
|
|
1141
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
1142
|
+
};
|
|
1143
|
+
const DotsIcon = app === "facebook" || app === "telegram" ? MenuDotsVerticalIcon : MenuDotsHorizontalIcon;
|
|
1144
|
+
return /* @__PURE__ */ jsxs7(InstallSplash, { title: appCopy.title, children: [
|
|
1145
|
+
/* @__PURE__ */ jsx13(Step3, { n: 1, icon: /* @__PURE__ */ jsx13(DotsIcon, { size: 20 }), children: appCopy.step1 }),
|
|
1146
|
+
/* @__PURE__ */ jsx13(Step3, { n: 2, icon: /* @__PURE__ */ jsx13(ExternalLinkIcon, { size: 18 }), children: appCopy.step2 }),
|
|
1147
|
+
/* @__PURE__ */ jsx13(
|
|
1148
|
+
"button",
|
|
1149
|
+
{
|
|
1150
|
+
"data-testid": "install-prompt-cta-inapp-copy",
|
|
1151
|
+
type: "button",
|
|
1152
|
+
onClick: () => void handleCopy(),
|
|
1153
|
+
style: { ...primaryButtonStyle, marginTop: 8 },
|
|
1154
|
+
children: copied ? copy.copiedToast : copy.copy
|
|
1155
|
+
}
|
|
1156
|
+
),
|
|
1157
|
+
/* @__PURE__ */ jsx13(
|
|
1158
|
+
"button",
|
|
1159
|
+
{
|
|
1160
|
+
"data-testid": "install-prompt-skip-session",
|
|
1161
|
+
type: "button",
|
|
1162
|
+
onClick: actions.dismissSession,
|
|
1163
|
+
style: skipLinkStyle,
|
|
1164
|
+
children: copy.skip
|
|
1165
|
+
}
|
|
1166
|
+
),
|
|
1167
|
+
showPermanent && /* @__PURE__ */ jsx13(
|
|
1168
|
+
"button",
|
|
1169
|
+
{
|
|
1170
|
+
"data-testid": "install-prompt-skip-permanent",
|
|
1171
|
+
type: "button",
|
|
1172
|
+
onClick: actions.dismissPermanent,
|
|
1173
|
+
style: skipPermanentLinkStyle,
|
|
1174
|
+
children: copy.skipPermanent
|
|
1175
|
+
}
|
|
1176
|
+
)
|
|
1177
|
+
] });
|
|
1178
|
+
}
|
|
1179
|
+
function Step3({
|
|
1180
|
+
n,
|
|
1181
|
+
icon,
|
|
1182
|
+
children
|
|
1183
|
+
}) {
|
|
1184
|
+
return /* @__PURE__ */ jsxs7(
|
|
1185
|
+
"div",
|
|
1186
|
+
{
|
|
1187
|
+
style: {
|
|
1188
|
+
display: "flex",
|
|
1189
|
+
alignItems: "center",
|
|
1190
|
+
gap: 12,
|
|
1191
|
+
padding: "12px 14px",
|
|
1192
|
+
background: "#f5f5f7",
|
|
1193
|
+
borderRadius: 12,
|
|
1194
|
+
marginBottom: 10,
|
|
1195
|
+
textAlign: "left"
|
|
1196
|
+
},
|
|
1197
|
+
children: [
|
|
1198
|
+
/* @__PURE__ */ jsx13(
|
|
1199
|
+
"div",
|
|
1200
|
+
{
|
|
1201
|
+
style: {
|
|
1202
|
+
width: 28,
|
|
1203
|
+
height: 28,
|
|
1204
|
+
borderRadius: "50%",
|
|
1205
|
+
background: "var(--hook-color-primary)",
|
|
1206
|
+
color: "#fff",
|
|
1207
|
+
display: "flex",
|
|
1208
|
+
alignItems: "center",
|
|
1209
|
+
justifyContent: "center",
|
|
1210
|
+
fontSize: 14,
|
|
1211
|
+
fontWeight: 700,
|
|
1212
|
+
flexShrink: 0
|
|
1213
|
+
},
|
|
1214
|
+
children: n
|
|
1215
|
+
}
|
|
1216
|
+
),
|
|
1217
|
+
/* @__PURE__ */ jsx13("div", { style: { flex: 1, fontSize: 14, color: "#333" }, children }),
|
|
1218
|
+
/* @__PURE__ */ jsx13("div", { style: { color: "#888", flexShrink: 0 }, children: icon })
|
|
1219
|
+
]
|
|
1220
|
+
}
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
// src/components/InstallGate/variants/DesktopVariant.tsx
|
|
1225
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1226
|
+
function DesktopVariant({
|
|
1227
|
+
state,
|
|
1228
|
+
actions
|
|
1229
|
+
}) {
|
|
1230
|
+
const { name, theme } = useTemplateConfig();
|
|
1231
|
+
const copy = INSTALL_COPY.desktop;
|
|
1232
|
+
const iconUrl = theme.icon_url || theme.logo_url || null;
|
|
1233
|
+
if (!state.isInstallable) return null;
|
|
1234
|
+
return /* @__PURE__ */ jsxs8(
|
|
1235
|
+
"div",
|
|
1236
|
+
{
|
|
1237
|
+
role: "complementary",
|
|
1238
|
+
"aria-label": copy.title,
|
|
1239
|
+
style: bannerStyle,
|
|
1240
|
+
children: [
|
|
1241
|
+
iconUrl ? /* @__PURE__ */ jsx14(
|
|
1242
|
+
"img",
|
|
1243
|
+
{
|
|
1244
|
+
src: iconUrl,
|
|
1245
|
+
alt: "",
|
|
1246
|
+
style: { width: 40, height: 40, borderRadius: 10, objectFit: "cover", flexShrink: 0 }
|
|
1247
|
+
}
|
|
1248
|
+
) : /* @__PURE__ */ jsx14(
|
|
1249
|
+
"div",
|
|
1250
|
+
{
|
|
1251
|
+
style: {
|
|
1252
|
+
width: 40,
|
|
1253
|
+
height: 40,
|
|
1254
|
+
borderRadius: 10,
|
|
1255
|
+
background: "var(--hook-color-primary)",
|
|
1256
|
+
color: "#fff",
|
|
1257
|
+
display: "flex",
|
|
1258
|
+
alignItems: "center",
|
|
1259
|
+
justifyContent: "center",
|
|
1260
|
+
fontSize: 18,
|
|
1261
|
+
fontWeight: 700,
|
|
1262
|
+
flexShrink: 0
|
|
1263
|
+
},
|
|
1264
|
+
children: name.charAt(0).toUpperCase()
|
|
1265
|
+
}
|
|
1266
|
+
),
|
|
1267
|
+
/* @__PURE__ */ jsxs8("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1268
|
+
/* @__PURE__ */ jsx14("div", { style: { fontSize: 14, fontWeight: 600, color: "#111" }, children: copy.title }),
|
|
1269
|
+
/* @__PURE__ */ jsx14("div", { style: { fontSize: 12, color: "#666" }, children: copy.subtitle })
|
|
1270
|
+
] }),
|
|
1271
|
+
/* @__PURE__ */ jsxs8(
|
|
1272
|
+
"button",
|
|
1273
|
+
{
|
|
1274
|
+
"data-testid": "install-prompt-cta-desktop",
|
|
1275
|
+
type: "button",
|
|
1276
|
+
onClick: () => void actions.promptInstall(),
|
|
1277
|
+
style: {
|
|
1278
|
+
padding: "8px 14px",
|
|
1279
|
+
background: "var(--hook-color-primary)",
|
|
1280
|
+
color: "#fff",
|
|
1281
|
+
border: "none",
|
|
1282
|
+
borderRadius: 999,
|
|
1283
|
+
fontSize: 13,
|
|
1284
|
+
fontWeight: 600,
|
|
1285
|
+
cursor: "pointer",
|
|
1286
|
+
display: "inline-flex",
|
|
1287
|
+
alignItems: "center",
|
|
1288
|
+
gap: 6,
|
|
1289
|
+
flexShrink: 0
|
|
1290
|
+
},
|
|
1291
|
+
children: [
|
|
1292
|
+
/* @__PURE__ */ jsx14(DownloadIcon, { size: 14 }),
|
|
1293
|
+
copy.cta
|
|
1294
|
+
]
|
|
1295
|
+
}
|
|
1296
|
+
),
|
|
1297
|
+
/* @__PURE__ */ jsx14(
|
|
1298
|
+
"button",
|
|
1299
|
+
{
|
|
1300
|
+
"data-testid": "install-prompt-desktop-close",
|
|
1301
|
+
type: "button",
|
|
1302
|
+
onClick: actions.dismissPermanent,
|
|
1303
|
+
"aria-label": copy.close,
|
|
1304
|
+
style: {
|
|
1305
|
+
background: "transparent",
|
|
1306
|
+
border: "none",
|
|
1307
|
+
cursor: "pointer",
|
|
1308
|
+
color: "#888",
|
|
1309
|
+
padding: 4,
|
|
1310
|
+
flexShrink: 0
|
|
1311
|
+
},
|
|
1312
|
+
children: /* @__PURE__ */ jsx14(XIcon, { size: 16 })
|
|
1313
|
+
}
|
|
1314
|
+
)
|
|
1315
|
+
]
|
|
1316
|
+
}
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1319
|
+
var bannerStyle = {
|
|
1320
|
+
position: "fixed",
|
|
1321
|
+
bottom: 24,
|
|
1322
|
+
right: 24,
|
|
1323
|
+
zIndex: 1e4,
|
|
1324
|
+
display: "flex",
|
|
1325
|
+
alignItems: "center",
|
|
1326
|
+
gap: 12,
|
|
1327
|
+
padding: "12px 16px",
|
|
1328
|
+
background: "#fff",
|
|
1329
|
+
border: "1px solid rgba(0,0,0,0.08)",
|
|
1330
|
+
borderRadius: 16,
|
|
1331
|
+
boxShadow: "0 10px 30px rgba(0,0,0,0.12)",
|
|
1332
|
+
maxWidth: 400
|
|
1333
|
+
};
|
|
1334
|
+
|
|
1335
|
+
// src/components/InstallGate/InstallGate.tsx
|
|
1336
|
+
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1337
|
+
function InstallGate({ children }) {
|
|
1338
|
+
const { slug, features_enabled } = useTemplateConfig();
|
|
1339
|
+
const enabled = features_enabled.includes("install_prompt");
|
|
1340
|
+
const installState = useInstallPrompt(slug);
|
|
1341
|
+
const shouldBlock = enabled && shouldBlockInstall(installState);
|
|
1342
|
+
const trackedRef = useRef(null);
|
|
1343
|
+
useEffect4(() => {
|
|
1344
|
+
if (!shouldBlock) return;
|
|
1345
|
+
if (typeof window === "undefined") return;
|
|
1346
|
+
const variantKey = `${slug}:${installState.variant}`;
|
|
1347
|
+
if (trackedRef.current === variantKey) return;
|
|
1348
|
+
trackedRef.current = variantKey;
|
|
1349
|
+
window.posthog?.capture?.("pwa_install_splash_shown", {
|
|
1350
|
+
slug,
|
|
1351
|
+
platform: installState.platform,
|
|
1352
|
+
browser: installState.iosBrowser ?? installState.androidBrowser ?? null,
|
|
1353
|
+
in_app_app: installState.inAppApp,
|
|
1354
|
+
variant: installState.variant
|
|
1355
|
+
});
|
|
1356
|
+
}, [shouldBlock, slug, installState.variant, installState.platform, installState.iosBrowser, installState.androidBrowser, installState.inAppApp]);
|
|
1357
|
+
if (!enabled) return /* @__PURE__ */ jsx15(Fragment4, { children });
|
|
1358
|
+
if (installState.isInstalled) return /* @__PURE__ */ jsx15(Fragment4, { children });
|
|
1359
|
+
if (installState.variant === "desktop") {
|
|
1360
|
+
return /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
1361
|
+
children,
|
|
1362
|
+
/* @__PURE__ */ jsx15(DesktopVariant, { state: installState, actions: installState })
|
|
1363
|
+
] });
|
|
1364
|
+
}
|
|
1365
|
+
if (!shouldBlock) return /* @__PURE__ */ jsx15(Fragment4, { children });
|
|
1366
|
+
switch (installState.variant) {
|
|
1367
|
+
case "android-native":
|
|
1368
|
+
return /* @__PURE__ */ jsx15(AndroidNativeVariant, { state: installState, actions: installState });
|
|
1369
|
+
case "android-manual":
|
|
1370
|
+
return /* @__PURE__ */ jsx15(AndroidManualVariant, { state: installState, actions: installState });
|
|
1371
|
+
case "ios-safari":
|
|
1372
|
+
return /* @__PURE__ */ jsx15(IOSafariVariant, { state: installState, actions: installState });
|
|
1373
|
+
case "ios-other":
|
|
1374
|
+
return /* @__PURE__ */ jsx15(IOSOtherVariant, { state: installState, actions: installState });
|
|
1375
|
+
case "in-app":
|
|
1376
|
+
return /* @__PURE__ */ jsx15(InAppBrowserVariant, { state: installState, actions: installState });
|
|
1377
|
+
case "none":
|
|
1378
|
+
default:
|
|
1379
|
+
return /* @__PURE__ */ jsx15(Fragment4, { children });
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
|
|
167
1383
|
// src/defaults/ErrorBoundary.tsx
|
|
168
1384
|
import { Component } from "react";
|
|
169
|
-
import { Fragment as
|
|
1385
|
+
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
170
1386
|
var ErrorBoundary = class extends Component {
|
|
171
1387
|
state = { error: null };
|
|
172
1388
|
static getDerivedStateFromError(error) {
|
|
@@ -177,17 +1393,17 @@ var ErrorBoundary = class extends Component {
|
|
|
177
1393
|
}
|
|
178
1394
|
render() {
|
|
179
1395
|
if (this.state.error) {
|
|
180
|
-
return this.props.fallback ?? /* @__PURE__ */
|
|
181
|
-
/* @__PURE__ */
|
|
182
|
-
/* @__PURE__ */
|
|
1396
|
+
return this.props.fallback ?? /* @__PURE__ */ jsxs10("div", { role: "alert", style: { padding: 24, textAlign: "center" }, children: [
|
|
1397
|
+
/* @__PURE__ */ jsx16("h2", { children: "Algo deu errado" }),
|
|
1398
|
+
/* @__PURE__ */ jsx16("p", { style: { opacity: 0.7 }, children: "Recarregue a p\xE1gina pra tentar de novo." })
|
|
183
1399
|
] });
|
|
184
1400
|
}
|
|
185
|
-
return /* @__PURE__ */
|
|
1401
|
+
return /* @__PURE__ */ jsx16(Fragment5, { children: this.props.children });
|
|
186
1402
|
}
|
|
187
1403
|
};
|
|
188
1404
|
|
|
189
1405
|
// src/hooks/useLoginForm.ts
|
|
190
|
-
import { useCallback as
|
|
1406
|
+
import { useCallback as useCallback3, useMemo as useMemo2, useState as useState6 } from "react";
|
|
191
1407
|
import { useHook as useHook4 } from "@hook-sdk/sdk";
|
|
192
1408
|
|
|
193
1409
|
// src/errors.ts
|
|
@@ -224,10 +1440,10 @@ var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
|
224
1440
|
var MIN_PASSWORD = 8;
|
|
225
1441
|
function useLoginForm() {
|
|
226
1442
|
const { auth } = useHook4();
|
|
227
|
-
const [email, setEmail] =
|
|
228
|
-
const [password, setPassword] =
|
|
229
|
-
const [submitting, setSubmitting] =
|
|
230
|
-
const [error, setError] =
|
|
1443
|
+
const [email, setEmail] = useState6("");
|
|
1444
|
+
const [password, setPassword] = useState6("");
|
|
1445
|
+
const [submitting, setSubmitting] = useState6(false);
|
|
1446
|
+
const [error, setError] = useState6(null);
|
|
231
1447
|
const emailError = useMemo2(() => {
|
|
232
1448
|
if (email.length === 0) return null;
|
|
233
1449
|
if (!EMAIL_RE.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
@@ -239,7 +1455,7 @@ function useLoginForm() {
|
|
|
239
1455
|
return null;
|
|
240
1456
|
}, [password]);
|
|
241
1457
|
const canSubmit = email.length > 0 && password.length >= MIN_PASSWORD && emailError === null && passwordError === null && !submitting;
|
|
242
|
-
const submit =
|
|
1458
|
+
const submit = useCallback3(async () => {
|
|
243
1459
|
if (!canSubmit) return false;
|
|
244
1460
|
setSubmitting(true);
|
|
245
1461
|
setError(null);
|
|
@@ -263,25 +1479,183 @@ function useLoginForm() {
|
|
|
263
1479
|
submit,
|
|
264
1480
|
submitting,
|
|
265
1481
|
canSubmit,
|
|
266
|
-
error
|
|
1482
|
+
error,
|
|
1483
|
+
loginWithGoogle: () => auth.loginWithGoogle()
|
|
267
1484
|
};
|
|
268
1485
|
}
|
|
269
1486
|
|
|
1487
|
+
// src/internal/GoogleSignInButton.tsx
|
|
1488
|
+
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1489
|
+
function GoogleSignInButton({
|
|
1490
|
+
onClick,
|
|
1491
|
+
testId = "oauth-google",
|
|
1492
|
+
label = "Continuar com Google"
|
|
1493
|
+
}) {
|
|
1494
|
+
return /* @__PURE__ */ jsxs11(
|
|
1495
|
+
"button",
|
|
1496
|
+
{
|
|
1497
|
+
"data-testid": testId,
|
|
1498
|
+
type: "button",
|
|
1499
|
+
onClick,
|
|
1500
|
+
style: {
|
|
1501
|
+
width: "100%",
|
|
1502
|
+
padding: "10px 12px",
|
|
1503
|
+
display: "flex",
|
|
1504
|
+
alignItems: "center",
|
|
1505
|
+
justifyContent: "center",
|
|
1506
|
+
gap: 10,
|
|
1507
|
+
background: "#fff",
|
|
1508
|
+
color: "#1f1f1f",
|
|
1509
|
+
border: "1px solid #dadce0",
|
|
1510
|
+
borderRadius: 8,
|
|
1511
|
+
cursor: "pointer",
|
|
1512
|
+
fontSize: 14,
|
|
1513
|
+
fontWeight: 500,
|
|
1514
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
|
|
1515
|
+
},
|
|
1516
|
+
children: [
|
|
1517
|
+
/* @__PURE__ */ jsx17(GoogleGlyph, {}),
|
|
1518
|
+
label
|
|
1519
|
+
]
|
|
1520
|
+
}
|
|
1521
|
+
);
|
|
1522
|
+
}
|
|
1523
|
+
function GoogleGlyph() {
|
|
1524
|
+
return /* @__PURE__ */ jsxs11("svg", { width: "18", height: "18", viewBox: "0 0 18 18", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [
|
|
1525
|
+
/* @__PURE__ */ jsx17(
|
|
1526
|
+
"path",
|
|
1527
|
+
{
|
|
1528
|
+
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",
|
|
1529
|
+
fill: "#4285F4"
|
|
1530
|
+
}
|
|
1531
|
+
),
|
|
1532
|
+
/* @__PURE__ */ jsx17(
|
|
1533
|
+
"path",
|
|
1534
|
+
{
|
|
1535
|
+
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",
|
|
1536
|
+
fill: "#34A853"
|
|
1537
|
+
}
|
|
1538
|
+
),
|
|
1539
|
+
/* @__PURE__ */ jsx17(
|
|
1540
|
+
"path",
|
|
1541
|
+
{
|
|
1542
|
+
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",
|
|
1543
|
+
fill: "#FBBC05"
|
|
1544
|
+
}
|
|
1545
|
+
),
|
|
1546
|
+
/* @__PURE__ */ jsx17(
|
|
1547
|
+
"path",
|
|
1548
|
+
{
|
|
1549
|
+
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",
|
|
1550
|
+
fill: "#EA4335"
|
|
1551
|
+
}
|
|
1552
|
+
)
|
|
1553
|
+
] });
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
// src/internal/OAuthErrorBanner.tsx
|
|
1557
|
+
import { useEffect as useEffect5, useState as useState7 } from "react";
|
|
1558
|
+
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1559
|
+
var ERROR_MESSAGES = {
|
|
1560
|
+
invalid_state: "Sess\xE3o expirou, tente de novo.",
|
|
1561
|
+
access_denied: "Voc\xEA cancelou o login com Google.",
|
|
1562
|
+
provider_error: "O Google recusou a autentica\xE7\xE3o. Tente de novo em alguns segundos.",
|
|
1563
|
+
invalid_return_to: "Link inv\xE1lido. Tente entrar novamente."
|
|
1564
|
+
};
|
|
1565
|
+
function readErrorCode() {
|
|
1566
|
+
if (typeof window === "undefined") return null;
|
|
1567
|
+
const code = new URLSearchParams(window.location.search).get("oauth_error");
|
|
1568
|
+
if (!code) return null;
|
|
1569
|
+
return code;
|
|
1570
|
+
}
|
|
1571
|
+
function stripErrorFromUrl() {
|
|
1572
|
+
if (typeof window === "undefined") return;
|
|
1573
|
+
const url = new URL(window.location.href);
|
|
1574
|
+
url.searchParams.delete("oauth_error");
|
|
1575
|
+
window.history.replaceState({}, "", url.toString());
|
|
1576
|
+
}
|
|
1577
|
+
function OAuthErrorBanner() {
|
|
1578
|
+
const [code, setCode] = useState7(() => readErrorCode());
|
|
1579
|
+
useEffect5(() => {
|
|
1580
|
+
if (code !== null) stripErrorFromUrl();
|
|
1581
|
+
}, [code]);
|
|
1582
|
+
if (!code) return null;
|
|
1583
|
+
const message = ERROR_MESSAGES[code] ?? "N\xE3o conseguimos conectar ao Google. Tente de novo.";
|
|
1584
|
+
return /* @__PURE__ */ jsxs12(
|
|
1585
|
+
"div",
|
|
1586
|
+
{
|
|
1587
|
+
role: "alert",
|
|
1588
|
+
"data-testid": "oauth-error-banner",
|
|
1589
|
+
style: {
|
|
1590
|
+
padding: "10px 12px",
|
|
1591
|
+
marginBottom: 16,
|
|
1592
|
+
background: "#fce8e6",
|
|
1593
|
+
color: "#a50e0e",
|
|
1594
|
+
borderRadius: 8,
|
|
1595
|
+
fontSize: 14
|
|
1596
|
+
},
|
|
1597
|
+
children: [
|
|
1598
|
+
message,
|
|
1599
|
+
/* @__PURE__ */ jsx18(
|
|
1600
|
+
"button",
|
|
1601
|
+
{
|
|
1602
|
+
type: "button",
|
|
1603
|
+
onClick: () => setCode(null),
|
|
1604
|
+
"aria-label": "Fechar",
|
|
1605
|
+
style: {
|
|
1606
|
+
float: "right",
|
|
1607
|
+
background: "none",
|
|
1608
|
+
border: "none",
|
|
1609
|
+
color: "#a50e0e",
|
|
1610
|
+
cursor: "pointer",
|
|
1611
|
+
fontSize: 16,
|
|
1612
|
+
lineHeight: 1,
|
|
1613
|
+
padding: 0
|
|
1614
|
+
},
|
|
1615
|
+
children: "\xD7"
|
|
1616
|
+
}
|
|
1617
|
+
)
|
|
1618
|
+
]
|
|
1619
|
+
}
|
|
1620
|
+
);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
270
1623
|
// src/defaults/DefaultLoginScreen.tsx
|
|
271
|
-
import { jsx as
|
|
1624
|
+
import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
272
1625
|
function DefaultLoginScreen({ onNavigate }) {
|
|
273
1626
|
const { name } = useTemplateConfig();
|
|
274
1627
|
const f = useLoginForm();
|
|
275
|
-
return /* @__PURE__ */
|
|
276
|
-
/* @__PURE__ */
|
|
277
|
-
/* @__PURE__ */
|
|
278
|
-
/* @__PURE__ */
|
|
1628
|
+
return /* @__PURE__ */ jsxs13("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
1629
|
+
/* @__PURE__ */ jsx19("h1", { style: { marginBottom: 8 }, children: name }),
|
|
1630
|
+
/* @__PURE__ */ jsx19("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Entre na sua conta" }),
|
|
1631
|
+
/* @__PURE__ */ jsx19(OAuthErrorBanner, {}),
|
|
1632
|
+
/* @__PURE__ */ jsx19(GoogleSignInButton, { onClick: f.loginWithGoogle, testId: "login-oauth-google" }),
|
|
1633
|
+
/* @__PURE__ */ jsxs13(
|
|
1634
|
+
"div",
|
|
1635
|
+
{
|
|
1636
|
+
"aria-hidden": "true",
|
|
1637
|
+
style: {
|
|
1638
|
+
display: "flex",
|
|
1639
|
+
alignItems: "center",
|
|
1640
|
+
gap: 8,
|
|
1641
|
+
margin: "16px 0",
|
|
1642
|
+
color: "rgba(0,0,0,0.45)",
|
|
1643
|
+
fontSize: 12
|
|
1644
|
+
},
|
|
1645
|
+
children: [
|
|
1646
|
+
/* @__PURE__ */ jsx19("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } }),
|
|
1647
|
+
"ou",
|
|
1648
|
+
/* @__PURE__ */ jsx19("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } })
|
|
1649
|
+
]
|
|
1650
|
+
}
|
|
1651
|
+
),
|
|
1652
|
+
/* @__PURE__ */ jsxs13("form", { onSubmit: (e) => {
|
|
279
1653
|
e.preventDefault();
|
|
280
1654
|
void f.submit();
|
|
281
1655
|
}, children: [
|
|
282
|
-
/* @__PURE__ */
|
|
1656
|
+
/* @__PURE__ */ jsxs13("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
283
1657
|
"E-mail",
|
|
284
|
-
/* @__PURE__ */
|
|
1658
|
+
/* @__PURE__ */ jsx19(
|
|
285
1659
|
"input",
|
|
286
1660
|
{
|
|
287
1661
|
"data-testid": "login-email",
|
|
@@ -291,11 +1665,11 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
291
1665
|
style: { display: "block", width: "100%" }
|
|
292
1666
|
}
|
|
293
1667
|
),
|
|
294
|
-
f.emailError && /* @__PURE__ */
|
|
1668
|
+
f.emailError && /* @__PURE__ */ jsx19("small", { style: { color: "#c00" }, children: f.emailError })
|
|
295
1669
|
] }),
|
|
296
|
-
/* @__PURE__ */
|
|
1670
|
+
/* @__PURE__ */ jsxs13("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
297
1671
|
"Senha",
|
|
298
|
-
/* @__PURE__ */
|
|
1672
|
+
/* @__PURE__ */ jsx19(
|
|
299
1673
|
"input",
|
|
300
1674
|
{
|
|
301
1675
|
"data-testid": "login-password",
|
|
@@ -305,10 +1679,10 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
305
1679
|
style: { display: "block", width: "100%" }
|
|
306
1680
|
}
|
|
307
1681
|
),
|
|
308
|
-
f.passwordError && /* @__PURE__ */
|
|
1682
|
+
f.passwordError && /* @__PURE__ */ jsx19("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
309
1683
|
] }),
|
|
310
|
-
f.error && /* @__PURE__ */
|
|
311
|
-
/* @__PURE__ */
|
|
1684
|
+
f.error && /* @__PURE__ */ jsx19("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
1685
|
+
/* @__PURE__ */ jsx19(
|
|
312
1686
|
"button",
|
|
313
1687
|
{
|
|
314
1688
|
"data-testid": "login-submit",
|
|
@@ -327,25 +1701,25 @@ function DefaultLoginScreen({ onNavigate }) {
|
|
|
327
1701
|
}
|
|
328
1702
|
)
|
|
329
1703
|
] }),
|
|
330
|
-
/* @__PURE__ */
|
|
331
|
-
/* @__PURE__ */
|
|
332
|
-
/* @__PURE__ */
|
|
1704
|
+
/* @__PURE__ */ jsxs13("div", { style: { marginTop: 16, display: "flex", justifyContent: "space-between" }, children: [
|
|
1705
|
+
/* @__PURE__ */ jsx19("button", { "data-testid": "login-goto-signup", type: "button", onClick: () => onNavigate("signup"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Criar conta" }),
|
|
1706
|
+
/* @__PURE__ */ jsx19("button", { "data-testid": "login-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Esqueci senha" })
|
|
333
1707
|
] })
|
|
334
1708
|
] });
|
|
335
1709
|
}
|
|
336
1710
|
|
|
337
1711
|
// src/hooks/useSignupForm.ts
|
|
338
|
-
import { useCallback as
|
|
1712
|
+
import { useCallback as useCallback4, useMemo as useMemo3, useState as useState8 } from "react";
|
|
339
1713
|
import { useHook as useHook5 } from "@hook-sdk/sdk";
|
|
340
1714
|
var EMAIL_RE2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
341
1715
|
var MIN_PASSWORD2 = 8;
|
|
342
1716
|
function useSignupForm() {
|
|
343
1717
|
const { auth } = useHook5();
|
|
344
|
-
const [name, setName] =
|
|
345
|
-
const [email, setEmail] =
|
|
346
|
-
const [password, setPassword] =
|
|
347
|
-
const [submitting, setSubmitting] =
|
|
348
|
-
const [error, setError] =
|
|
1718
|
+
const [name, setName] = useState8("");
|
|
1719
|
+
const [email, setEmail] = useState8("");
|
|
1720
|
+
const [password, setPassword] = useState8("");
|
|
1721
|
+
const [submitting, setSubmitting] = useState8(false);
|
|
1722
|
+
const [error, setError] = useState8(null);
|
|
349
1723
|
const nameError = useMemo3(() => {
|
|
350
1724
|
if (name.length === 0) return null;
|
|
351
1725
|
if (name.trim().length < 2) return "Nome muito curto.";
|
|
@@ -362,7 +1736,7 @@ function useSignupForm() {
|
|
|
362
1736
|
return null;
|
|
363
1737
|
}, [password]);
|
|
364
1738
|
const canSubmit = name.trim().length >= 2 && email.length > 0 && password.length >= MIN_PASSWORD2 && nameError === null && emailError === null && passwordError === null && !submitting;
|
|
365
|
-
const submit =
|
|
1739
|
+
const submit = useCallback4(async () => {
|
|
366
1740
|
if (!canSubmit) return false;
|
|
367
1741
|
setSubmitting(true);
|
|
368
1742
|
setError(null);
|
|
@@ -389,61 +1763,83 @@ function useSignupForm() {
|
|
|
389
1763
|
submit,
|
|
390
1764
|
submitting,
|
|
391
1765
|
canSubmit,
|
|
392
|
-
error
|
|
1766
|
+
error,
|
|
1767
|
+
loginWithGoogle: () => auth.loginWithGoogle()
|
|
393
1768
|
};
|
|
394
1769
|
}
|
|
395
1770
|
|
|
396
1771
|
// src/defaults/DefaultSignupScreen.tsx
|
|
397
|
-
import { jsx as
|
|
1772
|
+
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
398
1773
|
function DefaultSignupScreen({ onNavigate }) {
|
|
399
1774
|
const { name } = useTemplateConfig();
|
|
400
1775
|
const f = useSignupForm();
|
|
401
|
-
return /* @__PURE__ */
|
|
402
|
-
/* @__PURE__ */
|
|
403
|
-
/* @__PURE__ */
|
|
404
|
-
/* @__PURE__ */
|
|
1776
|
+
return /* @__PURE__ */ jsxs14("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
1777
|
+
/* @__PURE__ */ jsx20("h1", { style: { marginBottom: 8 }, children: name }),
|
|
1778
|
+
/* @__PURE__ */ jsx20("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Criar sua conta" }),
|
|
1779
|
+
/* @__PURE__ */ jsx20(OAuthErrorBanner, {}),
|
|
1780
|
+
/* @__PURE__ */ jsx20(GoogleSignInButton, { onClick: f.loginWithGoogle, testId: "signup-oauth-google" }),
|
|
1781
|
+
/* @__PURE__ */ jsxs14(
|
|
1782
|
+
"div",
|
|
1783
|
+
{
|
|
1784
|
+
"aria-hidden": "true",
|
|
1785
|
+
style: {
|
|
1786
|
+
display: "flex",
|
|
1787
|
+
alignItems: "center",
|
|
1788
|
+
gap: 8,
|
|
1789
|
+
margin: "16px 0",
|
|
1790
|
+
color: "rgba(0,0,0,0.45)",
|
|
1791
|
+
fontSize: 12
|
|
1792
|
+
},
|
|
1793
|
+
children: [
|
|
1794
|
+
/* @__PURE__ */ jsx20("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } }),
|
|
1795
|
+
"ou",
|
|
1796
|
+
/* @__PURE__ */ jsx20("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.1)" } })
|
|
1797
|
+
]
|
|
1798
|
+
}
|
|
1799
|
+
),
|
|
1800
|
+
/* @__PURE__ */ jsxs14("form", { onSubmit: (e) => {
|
|
405
1801
|
e.preventDefault();
|
|
406
1802
|
void f.submit();
|
|
407
1803
|
}, children: [
|
|
408
|
-
/* @__PURE__ */
|
|
1804
|
+
/* @__PURE__ */ jsxs14("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
409
1805
|
"Nome",
|
|
410
|
-
/* @__PURE__ */
|
|
411
|
-
f.nameError && /* @__PURE__ */
|
|
1806
|
+
/* @__PURE__ */ jsx20("input", { "data-testid": "signup-name", value: f.name, onChange: (e) => f.setName(e.target.value), style: { display: "block", width: "100%" } }),
|
|
1807
|
+
f.nameError && /* @__PURE__ */ jsx20("small", { style: { color: "#c00" }, children: f.nameError })
|
|
412
1808
|
] }),
|
|
413
|
-
/* @__PURE__ */
|
|
1809
|
+
/* @__PURE__ */ jsxs14("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
414
1810
|
"E-mail",
|
|
415
|
-
/* @__PURE__ */
|
|
416
|
-
f.emailError && /* @__PURE__ */
|
|
1811
|
+
/* @__PURE__ */ jsx20("input", { "data-testid": "signup-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
|
|
1812
|
+
f.emailError && /* @__PURE__ */ jsx20("small", { style: { color: "#c00" }, children: f.emailError })
|
|
417
1813
|
] }),
|
|
418
|
-
/* @__PURE__ */
|
|
1814
|
+
/* @__PURE__ */ jsxs14("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
419
1815
|
"Senha",
|
|
420
|
-
/* @__PURE__ */
|
|
421
|
-
f.passwordError && /* @__PURE__ */
|
|
1816
|
+
/* @__PURE__ */ jsx20("input", { "data-testid": "signup-password", type: "password", value: f.password, onChange: (e) => f.setPassword(e.target.value), style: { display: "block", width: "100%" } }),
|
|
1817
|
+
f.passwordError && /* @__PURE__ */ jsx20("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
422
1818
|
] }),
|
|
423
|
-
f.error && /* @__PURE__ */
|
|
424
|
-
/* @__PURE__ */
|
|
1819
|
+
f.error && /* @__PURE__ */ jsx20("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
1820
|
+
/* @__PURE__ */ jsx20("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" })
|
|
425
1821
|
] }),
|
|
426
|
-
/* @__PURE__ */
|
|
1822
|
+
/* @__PURE__ */ jsx20("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ jsx20("button", { "data-testid": "signup-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "J\xE1 tem conta? Entre" }) })
|
|
427
1823
|
] });
|
|
428
1824
|
}
|
|
429
1825
|
|
|
430
1826
|
// src/hooks/useForgotForm.ts
|
|
431
|
-
import { useCallback as
|
|
1827
|
+
import { useCallback as useCallback5, useMemo as useMemo4, useState as useState9 } from "react";
|
|
432
1828
|
import { useHook as useHook6 } from "@hook-sdk/sdk";
|
|
433
1829
|
var EMAIL_RE3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
434
1830
|
function useForgotForm() {
|
|
435
1831
|
const { auth } = useHook6();
|
|
436
|
-
const [email, setEmail] =
|
|
437
|
-
const [submitting, setSubmitting] =
|
|
438
|
-
const [sent, setSent] =
|
|
439
|
-
const [error, setError] =
|
|
1832
|
+
const [email, setEmail] = useState9("");
|
|
1833
|
+
const [submitting, setSubmitting] = useState9(false);
|
|
1834
|
+
const [sent, setSent] = useState9(false);
|
|
1835
|
+
const [error, setError] = useState9(null);
|
|
440
1836
|
const emailError = useMemo4(() => {
|
|
441
1837
|
if (email.length === 0) return null;
|
|
442
1838
|
if (!EMAIL_RE3.test(email)) return "Formato de e-mail inv\xE1lido.";
|
|
443
1839
|
return null;
|
|
444
1840
|
}, [email]);
|
|
445
1841
|
const canSubmit = email.length > 0 && emailError === null && !submitting;
|
|
446
|
-
const submit =
|
|
1842
|
+
const submit = useCallback5(async () => {
|
|
447
1843
|
if (!canSubmit) return false;
|
|
448
1844
|
setSubmitting(true);
|
|
449
1845
|
setError(null);
|
|
@@ -471,49 +1867,49 @@ function useForgotForm() {
|
|
|
471
1867
|
}
|
|
472
1868
|
|
|
473
1869
|
// src/defaults/DefaultForgotScreen.tsx
|
|
474
|
-
import { jsx as
|
|
1870
|
+
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
475
1871
|
function DefaultForgotScreen({ onNavigate }) {
|
|
476
1872
|
const { name } = useTemplateConfig();
|
|
477
1873
|
const f = useForgotForm();
|
|
478
1874
|
if (f.sent) {
|
|
479
|
-
return /* @__PURE__ */
|
|
480
|
-
/* @__PURE__ */
|
|
481
|
-
/* @__PURE__ */
|
|
482
|
-
/* @__PURE__ */
|
|
1875
|
+
return /* @__PURE__ */ jsxs15("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
1876
|
+
/* @__PURE__ */ jsx21("h1", { children: "Verifique seu e-mail" }),
|
|
1877
|
+
/* @__PURE__ */ jsx21("p", { style: { opacity: 0.7 }, children: "Enviamos um link pra redefinir sua senha." }),
|
|
1878
|
+
/* @__PURE__ */ jsx21("button", { "data-testid": "forgot-back-login", type: "button", onClick: () => onNavigate("login"), children: "Voltar pro login" })
|
|
483
1879
|
] });
|
|
484
1880
|
}
|
|
485
|
-
return /* @__PURE__ */
|
|
486
|
-
/* @__PURE__ */
|
|
487
|
-
/* @__PURE__ */
|
|
488
|
-
/* @__PURE__ */
|
|
1881
|
+
return /* @__PURE__ */ jsxs15("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
1882
|
+
/* @__PURE__ */ jsx21("h1", { style: { marginBottom: 8 }, children: name }),
|
|
1883
|
+
/* @__PURE__ */ jsx21("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Redefinir senha" }),
|
|
1884
|
+
/* @__PURE__ */ jsxs15("form", { onSubmit: (e) => {
|
|
489
1885
|
e.preventDefault();
|
|
490
1886
|
void f.submit();
|
|
491
1887
|
}, children: [
|
|
492
|
-
/* @__PURE__ */
|
|
1888
|
+
/* @__PURE__ */ jsxs15("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
493
1889
|
"E-mail",
|
|
494
|
-
/* @__PURE__ */
|
|
495
|
-
f.emailError && /* @__PURE__ */
|
|
1890
|
+
/* @__PURE__ */ jsx21("input", { "data-testid": "forgot-email", type: "email", value: f.email, onChange: (e) => f.setEmail(e.target.value), style: { display: "block", width: "100%" } }),
|
|
1891
|
+
f.emailError && /* @__PURE__ */ jsx21("small", { style: { color: "#c00" }, children: f.emailError })
|
|
496
1892
|
] }),
|
|
497
|
-
f.error && /* @__PURE__ */
|
|
498
|
-
/* @__PURE__ */
|
|
1893
|
+
f.error && /* @__PURE__ */ jsx21("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
1894
|
+
/* @__PURE__ */ jsx21("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" })
|
|
499
1895
|
] }),
|
|
500
|
-
/* @__PURE__ */
|
|
1896
|
+
/* @__PURE__ */ jsx21("div", { style: { marginTop: 16 }, children: /* @__PURE__ */ jsx21("button", { "data-testid": "forgot-goto-login", type: "button", onClick: () => onNavigate("login"), style: { background: "none", border: "none", cursor: "pointer" }, children: "Voltar pro login" }) })
|
|
501
1897
|
] });
|
|
502
1898
|
}
|
|
503
1899
|
|
|
504
1900
|
// src/hooks/useResetForm.ts
|
|
505
|
-
import { useCallback as
|
|
1901
|
+
import { useCallback as useCallback6, useEffect as useEffect6, useMemo as useMemo5, useState as useState10 } from "react";
|
|
506
1902
|
import { useHook as useHook7 } from "@hook-sdk/sdk";
|
|
507
1903
|
var MIN_PASSWORD3 = 12;
|
|
508
1904
|
function useResetForm() {
|
|
509
1905
|
const { auth } = useHook7();
|
|
510
|
-
const [token, setToken] =
|
|
511
|
-
const [password, setPassword] =
|
|
512
|
-
const [confirm, setConfirm] =
|
|
513
|
-
const [submitting, setSubmitting] =
|
|
514
|
-
const [done, setDone] =
|
|
515
|
-
const [error, setError] =
|
|
516
|
-
|
|
1906
|
+
const [token, setToken] = useState10(null);
|
|
1907
|
+
const [password, setPassword] = useState10("");
|
|
1908
|
+
const [confirm, setConfirm] = useState10("");
|
|
1909
|
+
const [submitting, setSubmitting] = useState10(false);
|
|
1910
|
+
const [done, setDone] = useState10(false);
|
|
1911
|
+
const [error, setError] = useState10(null);
|
|
1912
|
+
useEffect6(() => {
|
|
517
1913
|
if (typeof window === "undefined") return;
|
|
518
1914
|
const params = new URLSearchParams(window.location.search);
|
|
519
1915
|
const t = params.get("token");
|
|
@@ -530,7 +1926,7 @@ function useResetForm() {
|
|
|
530
1926
|
return null;
|
|
531
1927
|
}, [confirm, password]);
|
|
532
1928
|
const canSubmit = token !== null && password.length >= MIN_PASSWORD3 && confirm === password && passwordError === null && confirmError === null && !submitting && !done;
|
|
533
|
-
const submit =
|
|
1929
|
+
const submit = useCallback6(async () => {
|
|
534
1930
|
if (!canSubmit || token === null) return;
|
|
535
1931
|
setSubmitting(true);
|
|
536
1932
|
setError(null);
|
|
@@ -566,67 +1962,67 @@ function useResetForm() {
|
|
|
566
1962
|
}
|
|
567
1963
|
|
|
568
1964
|
// src/defaults/DefaultResetScreen.tsx
|
|
569
|
-
import { jsx as
|
|
1965
|
+
import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
570
1966
|
function DefaultResetScreen({ onNavigate }) {
|
|
571
1967
|
const { name } = useTemplateConfig();
|
|
572
1968
|
const f = useResetForm();
|
|
573
1969
|
if (f.done) {
|
|
574
|
-
return /* @__PURE__ */
|
|
575
|
-
/* @__PURE__ */
|
|
576
|
-
/* @__PURE__ */
|
|
577
|
-
/* @__PURE__ */
|
|
1970
|
+
return /* @__PURE__ */ jsxs16("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
1971
|
+
/* @__PURE__ */ jsx22("h1", { children: "Senha alterada" }),
|
|
1972
|
+
/* @__PURE__ */ jsx22("p", { style: { opacity: 0.7 }, children: "Agora \xE9 s\xF3 fazer login com a nova senha." }),
|
|
1973
|
+
/* @__PURE__ */ jsx22("button", { "data-testid": "reset-back-login", type: "button", onClick: () => onNavigate("login"), children: "Ir pro login" })
|
|
578
1974
|
] });
|
|
579
1975
|
}
|
|
580
1976
|
if (f.token === null) {
|
|
581
|
-
return /* @__PURE__ */
|
|
582
|
-
/* @__PURE__ */
|
|
583
|
-
/* @__PURE__ */
|
|
584
|
-
/* @__PURE__ */
|
|
1977
|
+
return /* @__PURE__ */ jsxs16("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto", textAlign: "center" }, children: [
|
|
1978
|
+
/* @__PURE__ */ jsx22("h1", { children: "Link inv\xE1lido" }),
|
|
1979
|
+
/* @__PURE__ */ jsx22("p", { style: { opacity: 0.7 }, children: "Pe\xE7a um novo link de reset." }),
|
|
1980
|
+
/* @__PURE__ */ jsx22("button", { "data-testid": "reset-goto-forgot", type: "button", onClick: () => onNavigate("forgot"), children: "Pedir novo link" })
|
|
585
1981
|
] });
|
|
586
1982
|
}
|
|
587
|
-
return /* @__PURE__ */
|
|
588
|
-
/* @__PURE__ */
|
|
589
|
-
/* @__PURE__ */
|
|
590
|
-
/* @__PURE__ */
|
|
1983
|
+
return /* @__PURE__ */ jsxs16("main", { style: { padding: 24, maxWidth: 360, margin: "0 auto" }, children: [
|
|
1984
|
+
/* @__PURE__ */ jsx22("h1", { style: { marginBottom: 8 }, children: name }),
|
|
1985
|
+
/* @__PURE__ */ jsx22("p", { style: { opacity: 0.7, marginBottom: 24 }, children: "Escolha uma nova senha" }),
|
|
1986
|
+
/* @__PURE__ */ jsxs16("form", { onSubmit: (e) => {
|
|
591
1987
|
e.preventDefault();
|
|
592
1988
|
void f.submit();
|
|
593
1989
|
}, children: [
|
|
594
|
-
/* @__PURE__ */
|
|
1990
|
+
/* @__PURE__ */ jsxs16("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
595
1991
|
"Nova senha",
|
|
596
|
-
/* @__PURE__ */
|
|
597
|
-
f.passwordError && /* @__PURE__ */
|
|
1992
|
+
/* @__PURE__ */ jsx22("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" }),
|
|
1993
|
+
f.passwordError && /* @__PURE__ */ jsx22("small", { style: { color: "#c00" }, children: f.passwordError })
|
|
598
1994
|
] }),
|
|
599
|
-
/* @__PURE__ */
|
|
1995
|
+
/* @__PURE__ */ jsxs16("label", { style: { display: "block", marginBottom: 12 }, children: [
|
|
600
1996
|
"Confirmar senha",
|
|
601
|
-
/* @__PURE__ */
|
|
602
|
-
f.confirmError && /* @__PURE__ */
|
|
1997
|
+
/* @__PURE__ */ jsx22("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" }),
|
|
1998
|
+
f.confirmError && /* @__PURE__ */ jsx22("small", { style: { color: "#c00" }, children: f.confirmError })
|
|
603
1999
|
] }),
|
|
604
|
-
f.error && /* @__PURE__ */
|
|
605
|
-
/* @__PURE__ */
|
|
2000
|
+
f.error && /* @__PURE__ */ jsx22("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: f.error.message }),
|
|
2001
|
+
/* @__PURE__ */ jsx22("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" })
|
|
606
2002
|
] })
|
|
607
2003
|
] });
|
|
608
2004
|
}
|
|
609
2005
|
|
|
610
2006
|
// src/defaults/DefaultPaywall.tsx
|
|
611
|
-
import { useState as
|
|
612
|
-
import { jsx as
|
|
2007
|
+
import { useState as useState11 } from "react";
|
|
2008
|
+
import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
613
2009
|
function DefaultPaywall() {
|
|
614
2010
|
const config = useTemplateConfig();
|
|
615
2011
|
const { checkout, opening, error } = usePaywallState();
|
|
616
2012
|
const p = config.subscription.paywall_config;
|
|
617
|
-
const [cpf, setCpf] =
|
|
2013
|
+
const [cpf, setCpf] = useState11("");
|
|
618
2014
|
const cpfDigits = cpf.replace(/\D/g, "");
|
|
619
2015
|
const canCheckout = cpfDigits.length === 11 && !opening;
|
|
620
|
-
return /* @__PURE__ */
|
|
621
|
-
/* @__PURE__ */
|
|
622
|
-
p.subtitle && /* @__PURE__ */
|
|
623
|
-
/* @__PURE__ */
|
|
624
|
-
/* @__PURE__ */
|
|
625
|
-
/* @__PURE__ */
|
|
2016
|
+
return /* @__PURE__ */ jsxs17("main", { style: { padding: 24, maxWidth: 440, margin: "0 auto", textAlign: "center" }, children: [
|
|
2017
|
+
/* @__PURE__ */ jsx23("h1", { style: { marginBottom: 8 }, children: p.title }),
|
|
2018
|
+
p.subtitle && /* @__PURE__ */ jsx23("p", { style: { opacity: 0.7, marginBottom: 24 }, children: p.subtitle }),
|
|
2019
|
+
/* @__PURE__ */ jsx23("ul", { style: { listStyle: "none", padding: 0, textAlign: "left", marginBottom: 24 }, children: p.benefits.map((b) => /* @__PURE__ */ jsxs17("li", { style: { padding: "8px 0", display: "flex", alignItems: "center" }, children: [
|
|
2020
|
+
/* @__PURE__ */ jsx23("span", { "aria-hidden": true, style: { marginRight: 8 }, children: "\u2713" }),
|
|
2021
|
+
/* @__PURE__ */ jsx23("span", { children: b })
|
|
626
2022
|
] }, b)) }),
|
|
627
|
-
/* @__PURE__ */
|
|
628
|
-
/* @__PURE__ */
|
|
629
|
-
/* @__PURE__ */
|
|
2023
|
+
/* @__PURE__ */ jsxs17("div", { style: { textAlign: "left", marginBottom: 16 }, children: [
|
|
2024
|
+
/* @__PURE__ */ jsx23("label", { style: { display: "block", fontSize: 14, opacity: 0.7, marginBottom: 4 }, children: "Seu CPF (pra emiss\xE3o de recibo)" }),
|
|
2025
|
+
/* @__PURE__ */ jsx23(
|
|
630
2026
|
"input",
|
|
631
2027
|
{
|
|
632
2028
|
"data-testid": "paywall-cpf",
|
|
@@ -639,8 +2035,8 @@ function DefaultPaywall() {
|
|
|
639
2035
|
}
|
|
640
2036
|
)
|
|
641
2037
|
] }),
|
|
642
|
-
error && /* @__PURE__ */
|
|
643
|
-
/* @__PURE__ */
|
|
2038
|
+
error && /* @__PURE__ */ jsx23("div", { role: "alert", style: { color: "#c00", marginBottom: 12 }, children: error.message }),
|
|
2039
|
+
/* @__PURE__ */ jsx23(
|
|
644
2040
|
"button",
|
|
645
2041
|
{
|
|
646
2042
|
"data-testid": "paywall-cta",
|
|
@@ -661,21 +2057,21 @@ function DefaultPaywall() {
|
|
|
661
2057
|
children: opening ? "Abrindo..." : p.cta
|
|
662
2058
|
}
|
|
663
2059
|
),
|
|
664
|
-
p.priceHint && /* @__PURE__ */
|
|
665
|
-
p.footerNote && /* @__PURE__ */
|
|
2060
|
+
p.priceHint && /* @__PURE__ */ jsx23("p", { style: { opacity: 0.6, marginTop: 12 }, children: p.priceHint }),
|
|
2061
|
+
p.footerNote && /* @__PURE__ */ jsx23("p", { style: { opacity: 0.5, marginTop: 16, fontSize: 12 }, children: p.footerNote })
|
|
666
2062
|
] });
|
|
667
2063
|
}
|
|
668
2064
|
|
|
669
2065
|
// src/AppRoot.tsx
|
|
670
|
-
import { Fragment as
|
|
2066
|
+
import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
671
2067
|
var BACKOFF_MS = [2e3, 5e3, 1e4, 2e4, 4e4];
|
|
672
2068
|
function PaymentReturnHandler({ children }) {
|
|
673
2069
|
const { subscription } = useHook8();
|
|
674
|
-
const subRef =
|
|
2070
|
+
const subRef = useRef2(subscription);
|
|
675
2071
|
subRef.current = subscription;
|
|
676
|
-
const runIdRef =
|
|
677
|
-
const [state, setState] =
|
|
678
|
-
const runPoll =
|
|
2072
|
+
const runIdRef = useRef2(0);
|
|
2073
|
+
const [state, setState] = useState12("idle");
|
|
2074
|
+
const runPoll = useCallback7(() => {
|
|
679
2075
|
const runId = ++runIdRef.current;
|
|
680
2076
|
setState("confirming");
|
|
681
2077
|
let attempts = 0;
|
|
@@ -704,7 +2100,7 @@ function PaymentReturnHandler({ children }) {
|
|
|
704
2100
|
};
|
|
705
2101
|
void tick();
|
|
706
2102
|
}, []);
|
|
707
|
-
|
|
2103
|
+
useEffect7(() => {
|
|
708
2104
|
if (typeof window === "undefined") return;
|
|
709
2105
|
const url = new URL(window.location.href);
|
|
710
2106
|
if (url.searchParams.get("paymentReturn") !== "1") return;
|
|
@@ -714,20 +2110,20 @@ function PaymentReturnHandler({ children }) {
|
|
|
714
2110
|
};
|
|
715
2111
|
}, [runPoll]);
|
|
716
2112
|
if (state === "confirming") {
|
|
717
|
-
return /* @__PURE__ */
|
|
2113
|
+
return /* @__PURE__ */ jsx24(
|
|
718
2114
|
"div",
|
|
719
2115
|
{
|
|
720
2116
|
role: "status",
|
|
721
2117
|
"aria-live": "polite",
|
|
722
|
-
style:
|
|
2118
|
+
style: overlayStyle2,
|
|
723
2119
|
children: "Confirmando pagamento\u2026"
|
|
724
2120
|
}
|
|
725
2121
|
);
|
|
726
2122
|
}
|
|
727
2123
|
if (state === "waiting") {
|
|
728
|
-
return /* @__PURE__ */
|
|
729
|
-
/* @__PURE__ */
|
|
730
|
-
/* @__PURE__ */
|
|
2124
|
+
return /* @__PURE__ */ jsx24("div", { role: "status", "aria-live": "polite", style: overlayStyle2, children: /* @__PURE__ */ jsxs18("div", { style: { maxWidth: 320, textAlign: "center", lineHeight: 1.5 }, children: [
|
|
2125
|
+
/* @__PURE__ */ jsx24("div", { style: { marginBottom: 16 }, children: "Pagamento aceito. Estamos confirmando com o banco \u2014 pode levar alguns minutos." }),
|
|
2126
|
+
/* @__PURE__ */ jsx24(
|
|
731
2127
|
"button",
|
|
732
2128
|
{
|
|
733
2129
|
type: "button",
|
|
@@ -738,9 +2134,9 @@ function PaymentReturnHandler({ children }) {
|
|
|
738
2134
|
)
|
|
739
2135
|
] }) });
|
|
740
2136
|
}
|
|
741
|
-
return /* @__PURE__ */
|
|
2137
|
+
return /* @__PURE__ */ jsx24(Fragment6, { children });
|
|
742
2138
|
}
|
|
743
|
-
var
|
|
2139
|
+
var overlayStyle2 = {
|
|
744
2140
|
position: "fixed",
|
|
745
2141
|
inset: 0,
|
|
746
2142
|
display: "flex",
|
|
@@ -771,14 +2167,14 @@ function AppRoot({
|
|
|
771
2167
|
Reset = DefaultResetScreen,
|
|
772
2168
|
Paywall = DefaultPaywall
|
|
773
2169
|
}) {
|
|
774
|
-
return /* @__PURE__ */
|
|
2170
|
+
return /* @__PURE__ */ jsx24(PaymentReturnHandler, { children: /* @__PURE__ */ jsx24(TemplateConfigProvider, { config, children: /* @__PURE__ */ jsx24(ErrorBoundary, { children: /* @__PURE__ */ jsx24(ThemeProvider, { children: /* @__PURE__ */ jsx24(InstallGate, { children: /* @__PURE__ */ jsx24(AuthGate, { Login, Signup, Forgot, Reset, children: /* @__PURE__ */ jsx24(PersistedKeysPrefetch, { children: /* @__PURE__ */ jsxs18(SubscriptionGate, { Paywall, children: [
|
|
775
2171
|
children,
|
|
776
|
-
/* @__PURE__ */
|
|
777
|
-
] }) }) }) }) }) }) });
|
|
2172
|
+
/* @__PURE__ */ jsx24(PushPrompt, {})
|
|
2173
|
+
] }) }) }) }) }) }) }) });
|
|
778
2174
|
}
|
|
779
2175
|
|
|
780
2176
|
// src/hooks/usePush.ts
|
|
781
|
-
import { useCallback as
|
|
2177
|
+
import { useCallback as useCallback8, useEffect as useEffect8, useState as useState13 } from "react";
|
|
782
2178
|
import { useHook as useHook9 } from "@hook-sdk/sdk";
|
|
783
2179
|
function detectIosNeedsInstall() {
|
|
784
2180
|
if (typeof navigator === "undefined" || typeof window === "undefined") return false;
|
|
@@ -806,11 +2202,11 @@ function deriveState(push) {
|
|
|
806
2202
|
}
|
|
807
2203
|
function usePush() {
|
|
808
2204
|
const { push } = useHook9();
|
|
809
|
-
const [state, setState] =
|
|
810
|
-
|
|
2205
|
+
const [state, setState] = useState13(() => deriveState(push));
|
|
2206
|
+
useEffect8(() => {
|
|
811
2207
|
setState(deriveState(push));
|
|
812
2208
|
}, [push]);
|
|
813
|
-
const subscribe =
|
|
2209
|
+
const subscribe = useCallback8(async () => {
|
|
814
2210
|
try {
|
|
815
2211
|
await push.subscribe();
|
|
816
2212
|
setState({ kind: "subscribed" });
|
|
@@ -822,7 +2218,7 @@ function usePush() {
|
|
|
822
2218
|
throw e;
|
|
823
2219
|
}
|
|
824
2220
|
}, [push]);
|
|
825
|
-
const unsubscribe =
|
|
2221
|
+
const unsubscribe = useCallback8(async () => {
|
|
826
2222
|
try {
|
|
827
2223
|
await push.unsubscribe();
|
|
828
2224
|
setState({ kind: "prompt" });
|
|
@@ -835,31 +2231,31 @@ function usePush() {
|
|
|
835
2231
|
}
|
|
836
2232
|
|
|
837
2233
|
// src/components/PushPrompt.tsx
|
|
838
|
-
import { jsx as
|
|
2234
|
+
import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
839
2235
|
function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, className }) {
|
|
840
2236
|
const { state, subscribe } = usePush();
|
|
841
2237
|
if (state.kind === "subscribed") return null;
|
|
842
2238
|
if (state.kind === "ios_needs_install") {
|
|
843
|
-
return /* @__PURE__ */
|
|
844
|
-
/* @__PURE__ */
|
|
845
|
-
/* @__PURE__ */
|
|
846
|
-
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */
|
|
2239
|
+
return /* @__PURE__ */ jsxs19("div", { className, role: "region", "aria-label": texts.iosInstallTitle, children: [
|
|
2240
|
+
/* @__PURE__ */ jsx25("h3", { children: texts.iosInstallTitle }),
|
|
2241
|
+
/* @__PURE__ */ jsx25("p", { children: texts.iosInstallBody }),
|
|
2242
|
+
onInstallRequested && texts.iosInstallCta && /* @__PURE__ */ jsx25("button", { onClick: onInstallRequested, children: texts.iosInstallCta })
|
|
847
2243
|
] });
|
|
848
2244
|
}
|
|
849
2245
|
if (state.kind === "denied") {
|
|
850
|
-
return /* @__PURE__ */
|
|
851
|
-
/* @__PURE__ */
|
|
852
|
-
/* @__PURE__ */
|
|
2246
|
+
return /* @__PURE__ */ jsxs19("div", { className, role: "region", "aria-label": texts.deniedTitle, children: [
|
|
2247
|
+
/* @__PURE__ */ jsx25("h3", { children: texts.deniedTitle }),
|
|
2248
|
+
/* @__PURE__ */ jsx25("p", { children: texts.deniedBody })
|
|
853
2249
|
] });
|
|
854
2250
|
}
|
|
855
2251
|
if (state.kind === "unsupported") {
|
|
856
|
-
return /* @__PURE__ */
|
|
2252
|
+
return /* @__PURE__ */ jsx25("div", { className, role: "region", children: /* @__PURE__ */ jsx25("p", { children: texts.unsupportedBody }) });
|
|
857
2253
|
}
|
|
858
2254
|
if (state.kind === "error") {
|
|
859
|
-
return /* @__PURE__ */
|
|
2255
|
+
return /* @__PURE__ */ jsx25("div", { className, role: "region", "aria-label": "error", children: /* @__PURE__ */ jsx25("p", { children: state.message }) });
|
|
860
2256
|
}
|
|
861
|
-
return /* @__PURE__ */
|
|
862
|
-
/* @__PURE__ */
|
|
2257
|
+
return /* @__PURE__ */ jsxs19("div", { className, role: "region", children: [
|
|
2258
|
+
/* @__PURE__ */ jsx25(
|
|
863
2259
|
"button",
|
|
864
2260
|
{
|
|
865
2261
|
type: "button",
|
|
@@ -873,27 +2269,27 @@ function PushPrompt2({ texts, onSubscribed, onDeclined, onInstallRequested, clas
|
|
|
873
2269
|
children: texts.cta
|
|
874
2270
|
}
|
|
875
2271
|
),
|
|
876
|
-
onDeclined && /* @__PURE__ */
|
|
2272
|
+
onDeclined && /* @__PURE__ */ jsx25("button", { type: "button", onClick: onDeclined, children: texts.declineCta })
|
|
877
2273
|
] });
|
|
878
2274
|
}
|
|
879
2275
|
|
|
880
2276
|
// src/defaults/EmptyState.tsx
|
|
881
|
-
import { jsx as
|
|
2277
|
+
import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
882
2278
|
function EmptyState({ title, description, action }) {
|
|
883
|
-
return /* @__PURE__ */
|
|
884
|
-
/* @__PURE__ */
|
|
885
|
-
description && /* @__PURE__ */
|
|
886
|
-
action && /* @__PURE__ */
|
|
2279
|
+
return /* @__PURE__ */ jsxs20("div", { role: "status", style: { padding: 32, textAlign: "center" }, children: [
|
|
2280
|
+
/* @__PURE__ */ jsx26("h2", { style: { marginBottom: 8 }, children: title }),
|
|
2281
|
+
description && /* @__PURE__ */ jsx26("p", { style: { opacity: 0.7 }, children: description }),
|
|
2282
|
+
action && /* @__PURE__ */ jsx26("div", { style: { marginTop: 16 }, children: action })
|
|
887
2283
|
] });
|
|
888
2284
|
}
|
|
889
2285
|
|
|
890
2286
|
// src/hooks/useAuthPrimitives.ts
|
|
891
|
-
import { useEffect as
|
|
2287
|
+
import { useEffect as useEffect9 } from "react";
|
|
892
2288
|
import { useHook as useHook10 } from "@hook-sdk/sdk";
|
|
893
2289
|
var warned = false;
|
|
894
2290
|
function useAuthPrimitives() {
|
|
895
2291
|
const { auth } = useHook10();
|
|
896
|
-
|
|
2292
|
+
useEffect9(() => {
|
|
897
2293
|
if (!warned && process.env.NODE_ENV !== "production") {
|
|
898
2294
|
warned = true;
|
|
899
2295
|
console.warn(
|
|
@@ -924,14 +2320,14 @@ function useSubscription() {
|
|
|
924
2320
|
}
|
|
925
2321
|
|
|
926
2322
|
// src/hooks/useReminders.ts
|
|
927
|
-
import { useCallback as
|
|
2323
|
+
import { useCallback as useCallback9, useEffect as useEffect10, useState as useState14 } from "react";
|
|
928
2324
|
import { useHook as useHook12 } from "@hook-sdk/sdk";
|
|
929
2325
|
function useReminders() {
|
|
930
2326
|
const { push } = useHook12();
|
|
931
2327
|
const r = push.reminders;
|
|
932
|
-
const [reminders, setReminders] =
|
|
933
|
-
const [loading, setLoading] =
|
|
934
|
-
const reload =
|
|
2328
|
+
const [reminders, setReminders] = useState14([]);
|
|
2329
|
+
const [loading, setLoading] = useState14(true);
|
|
2330
|
+
const reload = useCallback9(async () => {
|
|
935
2331
|
setLoading(true);
|
|
936
2332
|
try {
|
|
937
2333
|
const next = await r.list();
|
|
@@ -940,38 +2336,38 @@ function useReminders() {
|
|
|
940
2336
|
setLoading(false);
|
|
941
2337
|
}
|
|
942
2338
|
}, [r]);
|
|
943
|
-
|
|
2339
|
+
useEffect10(() => {
|
|
944
2340
|
void reload();
|
|
945
2341
|
}, [reload]);
|
|
946
|
-
const setReminder =
|
|
2342
|
+
const setReminder = useCallback9(async (input) => {
|
|
947
2343
|
await r.set(input);
|
|
948
2344
|
await reload();
|
|
949
2345
|
}, [r, reload]);
|
|
950
|
-
const deleteReminder =
|
|
2346
|
+
const deleteReminder = useCallback9(async (slot) => {
|
|
951
2347
|
await r.delete(slot);
|
|
952
2348
|
await reload();
|
|
953
2349
|
}, [r, reload]);
|
|
954
|
-
const schedule =
|
|
2350
|
+
const schedule = useCallback9(async (items) => {
|
|
955
2351
|
return r.schedule(items);
|
|
956
2352
|
}, [r]);
|
|
957
|
-
const setFallbacks =
|
|
2353
|
+
const setFallbacks = useCallback9(async (items) => {
|
|
958
2354
|
return r.setFallbacks(items);
|
|
959
2355
|
}, [r]);
|
|
960
2356
|
return { reminders, loading, setReminder, deleteReminder, schedule, setFallbacks };
|
|
961
2357
|
}
|
|
962
2358
|
|
|
963
2359
|
// src/hooks/useToast.ts
|
|
964
|
-
import { useCallback as
|
|
2360
|
+
import { useCallback as useCallback10, useState as useState15 } from "react";
|
|
965
2361
|
function useToast() {
|
|
966
|
-
const [items, setItems] =
|
|
967
|
-
const show =
|
|
2362
|
+
const [items, setItems] = useState15([]);
|
|
2363
|
+
const show = useCallback10((message, kind = "info") => {
|
|
968
2364
|
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
969
2365
|
setItems((prev) => [...prev, { id, message, kind }]);
|
|
970
2366
|
setTimeout(() => {
|
|
971
2367
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
972
2368
|
}, 4e3);
|
|
973
2369
|
}, []);
|
|
974
|
-
const dismiss =
|
|
2370
|
+
const dismiss = useCallback10((id) => {
|
|
975
2371
|
setItems((prev) => prev.filter((t) => t.id !== id));
|
|
976
2372
|
}, []);
|
|
977
2373
|
return { items, show, dismiss };
|
|
@@ -985,11 +2381,21 @@ export {
|
|
|
985
2381
|
DefaultSignupScreen,
|
|
986
2382
|
EmptyState,
|
|
987
2383
|
ErrorBoundary,
|
|
2384
|
+
InstallGate,
|
|
2385
|
+
InstallSplash,
|
|
988
2386
|
LoadingState,
|
|
989
2387
|
PushPrompt2 as PushPrompt,
|
|
2388
|
+
detectAndroidBrowser,
|
|
2389
|
+
detectIOSBrowser,
|
|
2390
|
+
detectInAppApp,
|
|
2391
|
+
detectPlatform,
|
|
2392
|
+
detectStandalone,
|
|
2393
|
+
shouldBlockInstall,
|
|
2394
|
+
shouldShowPermanentOption,
|
|
990
2395
|
useAuth,
|
|
991
2396
|
useAuthPrimitives,
|
|
992
2397
|
useForgotForm,
|
|
2398
|
+
useInstallPrompt,
|
|
993
2399
|
useLoginForm,
|
|
994
2400
|
usePaywallState,
|
|
995
2401
|
usePush,
|