@elvix.is/sdk 0.5.4 → 0.5.5
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/react.d.ts +90 -34
- package/dist/react.js +798 -283
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
// src/react/size.ts
|
|
3
|
+
function sizeStyle(p) {
|
|
4
|
+
const s = {};
|
|
5
|
+
if (p.width !== void 0) s.width = p.width;
|
|
6
|
+
if (p.height !== void 0) s.height = p.height;
|
|
7
|
+
if (p.minWidth !== void 0) s.minWidth = p.minWidth;
|
|
8
|
+
if (p.maxWidth !== void 0) s.maxWidth = p.maxWidth;
|
|
9
|
+
if (p.minHeight !== void 0) s.minHeight = p.minHeight;
|
|
10
|
+
if (p.maxHeight !== void 0) s.maxHeight = p.maxHeight;
|
|
11
|
+
return s;
|
|
12
|
+
}
|
|
13
|
+
|
|
2
14
|
// src/react/elvix-card.tsx
|
|
3
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
16
|
function ElvixCard({
|
|
5
17
|
title,
|
|
6
18
|
footer,
|
|
7
19
|
className = "",
|
|
8
|
-
|
|
20
|
+
style,
|
|
21
|
+
children,
|
|
22
|
+
width,
|
|
23
|
+
height,
|
|
24
|
+
minWidth,
|
|
25
|
+
maxWidth,
|
|
26
|
+
minHeight,
|
|
27
|
+
maxHeight
|
|
9
28
|
}) {
|
|
29
|
+
const sized = sizeStyle({ width, height, minWidth, maxWidth, minHeight, maxHeight });
|
|
10
30
|
return /* @__PURE__ */ jsxs(
|
|
11
31
|
"div",
|
|
12
32
|
{
|
|
@@ -19,7 +39,9 @@ function ElvixCard({
|
|
|
19
39
|
display: "flex",
|
|
20
40
|
flexDirection: "column",
|
|
21
41
|
maxWidth: "440px",
|
|
22
|
-
width: "100%"
|
|
42
|
+
width: "100%",
|
|
43
|
+
...style,
|
|
44
|
+
...sized
|
|
23
45
|
},
|
|
24
46
|
children: [
|
|
25
47
|
title && /* @__PURE__ */ jsx(
|
|
@@ -256,8 +278,15 @@ function ElvixSignIn({
|
|
|
256
278
|
onResult,
|
|
257
279
|
redirectAfterSignIn,
|
|
258
280
|
copy: copyProp,
|
|
259
|
-
className = ""
|
|
281
|
+
className = "",
|
|
282
|
+
width,
|
|
283
|
+
height,
|
|
284
|
+
minWidth,
|
|
285
|
+
maxWidth,
|
|
286
|
+
minHeight,
|
|
287
|
+
maxHeight
|
|
260
288
|
}) {
|
|
289
|
+
const sized = sizeStyle({ width, height, minWidth, maxWidth, minHeight, maxHeight });
|
|
261
290
|
const ctx = useElvixContext();
|
|
262
291
|
const app = useElvixApp();
|
|
263
292
|
const copy = resolveCopy(app?.strings, copyProp);
|
|
@@ -342,9 +371,9 @@ function ElvixSignIn({
|
|
|
342
371
|
}
|
|
343
372
|
const card = `elvix-card ${className}`.trim();
|
|
344
373
|
if (step === "done") {
|
|
345
|
-
return /* @__PURE__ */ jsx3("div", { className: card, "data-elvix-pane": "done", children: /* @__PURE__ */ jsx3("p", { children: copy.signedInText }) });
|
|
374
|
+
return /* @__PURE__ */ jsx3("div", { className: card, style: sized, "data-elvix-pane": "done", children: /* @__PURE__ */ jsx3("p", { children: copy.signedInText }) });
|
|
346
375
|
}
|
|
347
|
-
return /* @__PURE__ */ jsxs2("div", { className: card, "data-elvix-pane": step, children: [
|
|
376
|
+
return /* @__PURE__ */ jsxs2("div", { className: card, style: sized, "data-elvix-pane": step, children: [
|
|
348
377
|
/* @__PURE__ */ jsx3("h2", { className: "elvix-h", children: title }),
|
|
349
378
|
copy.subtitle && /* @__PURE__ */ jsx3("p", { className: "elvix-muted elvix-subtitle", children: copy.subtitle }),
|
|
350
379
|
step === "identify" && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
@@ -398,8 +427,8 @@ function ElvixSignIn({
|
|
|
398
427
|
] });
|
|
399
428
|
}
|
|
400
429
|
|
|
401
|
-
// src/react/elvix-sign-in-
|
|
402
|
-
import { useState as useState3 } from "react";
|
|
430
|
+
// src/react/elvix-sign-in-form.tsx
|
|
431
|
+
import { useMemo as useMemo2, useState as useState3 } from "react";
|
|
403
432
|
|
|
404
433
|
// src/react/elvix-shield.tsx
|
|
405
434
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -421,9 +450,470 @@ function ElvixShield({
|
|
|
421
450
|
] });
|
|
422
451
|
}
|
|
423
452
|
|
|
424
|
-
// src/react/elvix-
|
|
425
|
-
import {
|
|
453
|
+
// src/react/elvix-secured-badge.tsx
|
|
454
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
426
455
|
var ELVIX_URL = "https://elvix.is";
|
|
456
|
+
var SIZE = {
|
|
457
|
+
sm: { height: 28, padX: 10, font: 11.5, icon: 14, gap: 6 },
|
|
458
|
+
md: { height: 32, padX: 12, font: 12.5, icon: 16, gap: 7 },
|
|
459
|
+
lg: { height: 36, padX: 14, font: 13, icon: 18, gap: 8 }
|
|
460
|
+
};
|
|
461
|
+
var TONE = {
|
|
462
|
+
white: {
|
|
463
|
+
light: { bg: "#ffffff", border: "#e4e4e7", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" },
|
|
464
|
+
dark: { bg: "#ffffff", border: "transparent", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" }
|
|
465
|
+
},
|
|
466
|
+
dark: {
|
|
467
|
+
light: { bg: "#0a0a0b", border: "rgba(0,0,0,0.1)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" },
|
|
468
|
+
dark: { bg: "#0a0a0b", border: "rgba(255,255,255,0.1)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" }
|
|
469
|
+
},
|
|
470
|
+
outline: {
|
|
471
|
+
light: { bg: "transparent", border: "rgba(0,0,0,0.15)", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" },
|
|
472
|
+
dark: { bg: "transparent", border: "rgba(142,125,255,0.4)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" }
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
function ElvixSecuredBadge({
|
|
476
|
+
variant = "white",
|
|
477
|
+
size = "md",
|
|
478
|
+
theme = "dark",
|
|
479
|
+
accentColor = "#8e7dff",
|
|
480
|
+
href = ELVIX_URL,
|
|
481
|
+
className = "",
|
|
482
|
+
width,
|
|
483
|
+
height,
|
|
484
|
+
minWidth,
|
|
485
|
+
maxWidth,
|
|
486
|
+
minHeight,
|
|
487
|
+
maxHeight
|
|
488
|
+
}) {
|
|
489
|
+
const s = SIZE[size];
|
|
490
|
+
const t = TONE[variant][theme];
|
|
491
|
+
const style = {
|
|
492
|
+
display: "inline-flex",
|
|
493
|
+
alignItems: "center",
|
|
494
|
+
gap: s.gap,
|
|
495
|
+
height: s.height,
|
|
496
|
+
paddingLeft: s.padX,
|
|
497
|
+
paddingRight: s.padX,
|
|
498
|
+
fontSize: s.font,
|
|
499
|
+
fontWeight: 500,
|
|
500
|
+
borderRadius: 9999,
|
|
501
|
+
background: t.bg,
|
|
502
|
+
border: `1px solid ${t.border}`,
|
|
503
|
+
color: t.brand,
|
|
504
|
+
textDecoration: "none",
|
|
505
|
+
userSelect: "none",
|
|
506
|
+
lineHeight: 1,
|
|
507
|
+
// Dimensional overrides win over the size preset above.
|
|
508
|
+
...sizeStyle({ width, height, minWidth, maxWidth, minHeight, maxHeight })
|
|
509
|
+
};
|
|
510
|
+
return /* @__PURE__ */ jsxs4(
|
|
511
|
+
"a",
|
|
512
|
+
{
|
|
513
|
+
href,
|
|
514
|
+
target: "_blank",
|
|
515
|
+
rel: "noopener noreferrer",
|
|
516
|
+
className,
|
|
517
|
+
style,
|
|
518
|
+
"data-elvix-secured-badge": "",
|
|
519
|
+
children: [
|
|
520
|
+
/* @__PURE__ */ jsx5(ElvixShield, { size: s.icon, fill: t.shield, accent: accentColor }),
|
|
521
|
+
/* @__PURE__ */ jsxs4("span", { style: { display: "inline-flex", alignItems: "baseline", gap: 4 }, children: [
|
|
522
|
+
/* @__PURE__ */ jsx5("span", { style: { color: t.lead }, children: "Secured by" }),
|
|
523
|
+
/* @__PURE__ */ jsx5("span", { style: { color: t.brand, fontWeight: 600 }, children: "elvix" })
|
|
524
|
+
] })
|
|
525
|
+
]
|
|
526
|
+
}
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/react/elvix-sign-in-form.tsx
|
|
531
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
532
|
+
function GoogleG({ size = 18 }) {
|
|
533
|
+
return /* @__PURE__ */ jsxs5("svg", { width: size, height: size, viewBox: "0 0 18 18", "aria-hidden": true, style: { display: "block" }, children: [
|
|
534
|
+
/* @__PURE__ */ jsx6(
|
|
535
|
+
"path",
|
|
536
|
+
{
|
|
537
|
+
fill: "#4285F4",
|
|
538
|
+
d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62Z"
|
|
539
|
+
}
|
|
540
|
+
),
|
|
541
|
+
/* @__PURE__ */ jsx6(
|
|
542
|
+
"path",
|
|
543
|
+
{
|
|
544
|
+
fill: "#34A853",
|
|
545
|
+
d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"
|
|
546
|
+
}
|
|
547
|
+
),
|
|
548
|
+
/* @__PURE__ */ jsx6(
|
|
549
|
+
"path",
|
|
550
|
+
{
|
|
551
|
+
fill: "#FBBC05",
|
|
552
|
+
d: "M3.97 10.72A5.4 5.4 0 0 1 3.68 9c0-.6.1-1.18.29-1.72V4.95H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.05l3.01-2.33Z"
|
|
553
|
+
}
|
|
554
|
+
),
|
|
555
|
+
/* @__PURE__ */ jsx6(
|
|
556
|
+
"path",
|
|
557
|
+
{
|
|
558
|
+
fill: "#EA4335",
|
|
559
|
+
d: "M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.59C13.46.89 11.43 0 9 0A9 9 0 0 0 .96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58Z"
|
|
560
|
+
}
|
|
561
|
+
)
|
|
562
|
+
] });
|
|
563
|
+
}
|
|
564
|
+
function ElvixSignInForm({
|
|
565
|
+
onResult,
|
|
566
|
+
redirectAfterSignIn,
|
|
567
|
+
copy: copyProp,
|
|
568
|
+
className = "",
|
|
569
|
+
minWidth,
|
|
570
|
+
maxWidth,
|
|
571
|
+
minHeight,
|
|
572
|
+
maxHeight,
|
|
573
|
+
width,
|
|
574
|
+
height
|
|
575
|
+
}) {
|
|
576
|
+
const ctx = useElvixContext();
|
|
577
|
+
const app = useElvixApp();
|
|
578
|
+
const copy = resolveCopy(app?.strings, copyProp);
|
|
579
|
+
const [step, setStep] = useState3("identify");
|
|
580
|
+
const [email, setEmail] = useState3("");
|
|
581
|
+
const [code, setCode] = useState3("");
|
|
582
|
+
const [challengeId, setChallengeId] = useState3(null);
|
|
583
|
+
const [busy, setBusy] = useState3(false);
|
|
584
|
+
const [error, setError] = useState3(null);
|
|
585
|
+
const brand = app?.brandColor || "#6c5ce7";
|
|
586
|
+
const onBrand = app?.onBrandColor || "#fff";
|
|
587
|
+
const appName = app?.appName ?? "your app";
|
|
588
|
+
const verb = app?.signInVerb === "login" ? "Log in" : "Sign in";
|
|
589
|
+
const defaultTitle = app?.appName ? `${verb} to ${app.appName}` : verb;
|
|
590
|
+
const title = copy.title ? fillCopy(copy.title, { app: app?.appName ?? "" }) : defaultTitle;
|
|
591
|
+
const submitLabel = copy.submitButton ?? verb;
|
|
592
|
+
const showGoogle = Boolean(app?.methodGoogle);
|
|
593
|
+
const showEmail = Boolean(app?.methodEmailOtp);
|
|
594
|
+
const showDivider = showGoogle && showEmail;
|
|
595
|
+
const logoSrc = app?.iconUrl || app?.logoUrl || null;
|
|
596
|
+
const privacyUrl = app?.privacyPolicyUrl || null;
|
|
597
|
+
const termsUrl = app?.termsOfServiceUrl || null;
|
|
598
|
+
const hasLegal = Boolean(privacyUrl || termsUrl);
|
|
599
|
+
const cardStyle = useMemo2(
|
|
600
|
+
() => ({
|
|
601
|
+
boxSizing: "border-box",
|
|
602
|
+
// Defaults first; the shared sizeStyle() overrides only the keys the host set,
|
|
603
|
+
// so the form keeps its width "100%" / maxWidth 400 defaults when unsized.
|
|
604
|
+
width: "100%",
|
|
605
|
+
maxWidth: 400,
|
|
606
|
+
...sizeStyle({ width, height, minWidth, maxWidth, minHeight, maxHeight }),
|
|
607
|
+
margin: "0 auto",
|
|
608
|
+
display: "flex",
|
|
609
|
+
flexDirection: "column",
|
|
610
|
+
gap: 18,
|
|
611
|
+
background: "#fff",
|
|
612
|
+
color: "#18181b",
|
|
613
|
+
border: "1px solid rgba(0,0,0,0.08)",
|
|
614
|
+
borderRadius: 16,
|
|
615
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04), 0 12px 32px -12px rgba(0,0,0,0.18)",
|
|
616
|
+
padding: 28,
|
|
617
|
+
fontFamily: "ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
|
|
618
|
+
textAlign: "center"
|
|
619
|
+
}),
|
|
620
|
+
[width, maxWidth, minWidth, height, minHeight, maxHeight]
|
|
621
|
+
);
|
|
622
|
+
function fail(error2, message) {
|
|
623
|
+
setError(message ?? error2);
|
|
624
|
+
onResult?.({ ok: false, error: error2, message });
|
|
625
|
+
}
|
|
626
|
+
async function startGoogle() {
|
|
627
|
+
if (!ctx.clientId) return fail("missing_client_id", "ElvixProvider needs a clientId.");
|
|
628
|
+
window.location.assign(
|
|
629
|
+
`${ctx.baseUrl}/api/auth/google/start?intent=app&clientId=${encodeURIComponent(ctx.clientId)}`
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
async function startOtp(e) {
|
|
633
|
+
e.preventDefault();
|
|
634
|
+
if (!email.trim()) return fail("invalid_input", copy.errorEnterEmail);
|
|
635
|
+
setBusy(true);
|
|
636
|
+
setError(null);
|
|
637
|
+
try {
|
|
638
|
+
const res = await fetch(`${ctx.baseUrl}/api/auth/otp/start`, {
|
|
639
|
+
method: "POST",
|
|
640
|
+
headers: { "content-type": "application/json" },
|
|
641
|
+
credentials: isSameOrigin(ctx.baseUrl) ? "include" : "omit",
|
|
642
|
+
body: JSON.stringify({
|
|
643
|
+
email: email.trim(),
|
|
644
|
+
intent: "app",
|
|
645
|
+
clientId: ctx.clientId
|
|
646
|
+
})
|
|
647
|
+
});
|
|
648
|
+
const body = await res.json();
|
|
649
|
+
if (!res.ok || !body.success || !body.data?.challengeId) {
|
|
650
|
+
return fail(body.errorMessage ?? "otp_start_failed");
|
|
651
|
+
}
|
|
652
|
+
setChallengeId(body.data.challengeId);
|
|
653
|
+
setStep("code");
|
|
654
|
+
} catch (e2) {
|
|
655
|
+
fail("network", e2 instanceof Error ? e2.message : void 0);
|
|
656
|
+
} finally {
|
|
657
|
+
setBusy(false);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
async function verifyOtp(e) {
|
|
661
|
+
e.preventDefault();
|
|
662
|
+
if (!challengeId) return;
|
|
663
|
+
if (code.trim().length !== 6) return fail("invalid_input", copy.errorEnterCode);
|
|
664
|
+
setBusy(true);
|
|
665
|
+
setError(null);
|
|
666
|
+
try {
|
|
667
|
+
const res = await fetch(`${ctx.baseUrl}/api/auth/otp/verify`, {
|
|
668
|
+
method: "POST",
|
|
669
|
+
headers: { "content-type": "application/json" },
|
|
670
|
+
credentials: isSameOrigin(ctx.baseUrl) ? "include" : "omit",
|
|
671
|
+
body: JSON.stringify({ challengeId, code: code.trim() })
|
|
672
|
+
});
|
|
673
|
+
const body = await res.json();
|
|
674
|
+
if (!res.ok || !body.success) {
|
|
675
|
+
return fail(body.errorMessage ?? "otp_verify_failed");
|
|
676
|
+
}
|
|
677
|
+
if (body.data?.token) setElvixToken(body.data.token);
|
|
678
|
+
setStep("done");
|
|
679
|
+
onResult?.({
|
|
680
|
+
ok: true,
|
|
681
|
+
method: "email_otp",
|
|
682
|
+
redirect: body.data?.redirect ?? redirectAfterSignIn,
|
|
683
|
+
token: body.data?.token
|
|
684
|
+
});
|
|
685
|
+
} catch (e2) {
|
|
686
|
+
fail("network", e2 instanceof Error ? e2.message : void 0);
|
|
687
|
+
} finally {
|
|
688
|
+
setBusy(false);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
const labelStyle = {
|
|
692
|
+
display: "block",
|
|
693
|
+
textAlign: "left",
|
|
694
|
+
fontSize: 12.5,
|
|
695
|
+
fontWeight: 500,
|
|
696
|
+
color: "#52525b",
|
|
697
|
+
marginBottom: 6
|
|
698
|
+
};
|
|
699
|
+
const inputStyle = {
|
|
700
|
+
boxSizing: "border-box",
|
|
701
|
+
width: "100%",
|
|
702
|
+
height: 44,
|
|
703
|
+
padding: "0 14px",
|
|
704
|
+
borderRadius: 10,
|
|
705
|
+
border: "1px solid rgba(0,0,0,0.14)",
|
|
706
|
+
background: "#fff",
|
|
707
|
+
color: "#18181b",
|
|
708
|
+
fontSize: 14,
|
|
709
|
+
outline: "none"
|
|
710
|
+
};
|
|
711
|
+
const primaryBtnStyle = {
|
|
712
|
+
boxSizing: "border-box",
|
|
713
|
+
width: "100%",
|
|
714
|
+
height: 44,
|
|
715
|
+
marginTop: 10,
|
|
716
|
+
border: "1px solid rgba(0,0,0,0.08)",
|
|
717
|
+
borderRadius: 10,
|
|
718
|
+
background: brand,
|
|
719
|
+
color: onBrand,
|
|
720
|
+
fontSize: 14,
|
|
721
|
+
fontWeight: 600,
|
|
722
|
+
cursor: busy ? "not-allowed" : "pointer",
|
|
723
|
+
opacity: busy ? 0.65 : 1,
|
|
724
|
+
backgroundImage: "linear-gradient(to bottom, rgba(255,255,255,0.12), rgba(255,255,255,0) 40%)",
|
|
725
|
+
boxShadow: "0 1px 0 rgba(255,255,255,0.06) inset, 0 2px 3px -1px rgba(0,0,0,0.18), 0 0 0 1px rgba(25,28,33,0.06)"
|
|
726
|
+
};
|
|
727
|
+
const googleBtnStyle = {
|
|
728
|
+
boxSizing: "border-box",
|
|
729
|
+
width: "100%",
|
|
730
|
+
height: 44,
|
|
731
|
+
display: "inline-flex",
|
|
732
|
+
alignItems: "center",
|
|
733
|
+
justifyContent: "center",
|
|
734
|
+
gap: 10,
|
|
735
|
+
border: "1px solid rgba(0,0,0,0.14)",
|
|
736
|
+
borderRadius: 10,
|
|
737
|
+
background: "#fff",
|
|
738
|
+
color: "#18181b",
|
|
739
|
+
fontSize: 14,
|
|
740
|
+
fontWeight: 500,
|
|
741
|
+
cursor: busy ? "not-allowed" : "pointer",
|
|
742
|
+
opacity: busy ? 0.65 : 1
|
|
743
|
+
};
|
|
744
|
+
const tileTint = hexToRgba(brand, 0.12);
|
|
745
|
+
const root = `${className}`.trim() || void 0;
|
|
746
|
+
return /* @__PURE__ */ jsxs5("div", { className: root, style: cardStyle, "data-elvix-pane": step, children: [
|
|
747
|
+
/* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
|
|
748
|
+
/* @__PURE__ */ jsx6(
|
|
749
|
+
"div",
|
|
750
|
+
{
|
|
751
|
+
style: {
|
|
752
|
+
width: 52,
|
|
753
|
+
height: 52,
|
|
754
|
+
borderRadius: 14,
|
|
755
|
+
display: "grid",
|
|
756
|
+
placeItems: "center",
|
|
757
|
+
overflow: "hidden",
|
|
758
|
+
background: logoSrc ? "#fff" : tileTint,
|
|
759
|
+
border: "1px solid rgba(0,0,0,0.08)"
|
|
760
|
+
},
|
|
761
|
+
children: logoSrc ? (
|
|
762
|
+
// biome-ignore lint/a11y/useAltText: alt is set
|
|
763
|
+
/* @__PURE__ */ jsx6(
|
|
764
|
+
"img",
|
|
765
|
+
{
|
|
766
|
+
src: logoSrc,
|
|
767
|
+
alt: appName,
|
|
768
|
+
style: { width: "100%", height: "100%", objectFit: "cover" }
|
|
769
|
+
}
|
|
770
|
+
)
|
|
771
|
+
) : /* @__PURE__ */ jsx6("span", { style: { fontSize: 22, fontWeight: 700, color: brand }, children: appName.charAt(0).toUpperCase() || "?" })
|
|
772
|
+
}
|
|
773
|
+
),
|
|
774
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
775
|
+
/* @__PURE__ */ jsx6("h2", { style: { margin: 0, fontSize: 19, fontWeight: 600, letterSpacing: "-0.01em" }, children: step === "code" ? "Check your inbox" : title }),
|
|
776
|
+
step !== "done" && /* @__PURE__ */ jsx6("p", { style: { margin: "4px 0 0", fontSize: 13, color: "#71717a" }, children: step === "code" ? fillCopy(copy.codeSentSubtitle ?? "", { email }) : copy.subtitle })
|
|
777
|
+
] })
|
|
778
|
+
] }),
|
|
779
|
+
step === "done" && /* @__PURE__ */ jsx6("p", { style: { margin: 0, fontSize: 14, color: "#18181b" }, children: copy.signedInText }),
|
|
780
|
+
step === "identify" && /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: 14 }, children: [
|
|
781
|
+
showGoogle && /* @__PURE__ */ jsxs5(
|
|
782
|
+
"button",
|
|
783
|
+
{
|
|
784
|
+
type: "button",
|
|
785
|
+
onClick: startGoogle,
|
|
786
|
+
disabled: busy,
|
|
787
|
+
style: googleBtnStyle,
|
|
788
|
+
"data-elvix-method": "google",
|
|
789
|
+
children: [
|
|
790
|
+
/* @__PURE__ */ jsx6(GoogleG, {}),
|
|
791
|
+
/* @__PURE__ */ jsx6("span", { children: copy.googleButton })
|
|
792
|
+
]
|
|
793
|
+
}
|
|
794
|
+
),
|
|
795
|
+
showDivider && /* @__PURE__ */ jsxs5(
|
|
796
|
+
"div",
|
|
797
|
+
{
|
|
798
|
+
"aria-hidden": true,
|
|
799
|
+
style: { display: "flex", alignItems: "center", gap: 12, color: "#a1a1aa" },
|
|
800
|
+
children: [
|
|
801
|
+
/* @__PURE__ */ jsx6("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.08)" } }),
|
|
802
|
+
/* @__PURE__ */ jsx6("span", { style: { fontSize: 11, fontWeight: 600, letterSpacing: "0.08em" }, children: "OR" }),
|
|
803
|
+
/* @__PURE__ */ jsx6("span", { style: { flex: 1, height: 1, background: "rgba(0,0,0,0.08)" } })
|
|
804
|
+
]
|
|
805
|
+
}
|
|
806
|
+
),
|
|
807
|
+
showEmail && /* @__PURE__ */ jsxs5("form", { onSubmit: startOtp, "data-elvix-method": "email_otp", children: [
|
|
808
|
+
/* @__PURE__ */ jsx6("label", { htmlFor: "elvix-email", style: labelStyle, children: "Email" }),
|
|
809
|
+
/* @__PURE__ */ jsx6(
|
|
810
|
+
"input",
|
|
811
|
+
{
|
|
812
|
+
id: "elvix-email",
|
|
813
|
+
type: "email",
|
|
814
|
+
value: email,
|
|
815
|
+
onChange: (ev) => setEmail(ev.target.value),
|
|
816
|
+
placeholder: copy.emailPlaceholder,
|
|
817
|
+
required: true,
|
|
818
|
+
disabled: busy,
|
|
819
|
+
autoComplete: "email",
|
|
820
|
+
style: inputStyle
|
|
821
|
+
}
|
|
822
|
+
),
|
|
823
|
+
/* @__PURE__ */ jsx6("button", { type: "submit", disabled: busy, style: primaryBtnStyle, children: busy ? copy.sendingLabel : copy.sendCodeButton })
|
|
824
|
+
] })
|
|
825
|
+
] }),
|
|
826
|
+
step === "code" && /* @__PURE__ */ jsxs5("form", { onSubmit: verifyOtp, children: [
|
|
827
|
+
/* @__PURE__ */ jsx6("label", { htmlFor: "elvix-code", style: labelStyle, children: "Verification code" }),
|
|
828
|
+
/* @__PURE__ */ jsx6(
|
|
829
|
+
"input",
|
|
830
|
+
{
|
|
831
|
+
id: "elvix-code",
|
|
832
|
+
type: "text",
|
|
833
|
+
inputMode: "numeric",
|
|
834
|
+
pattern: "[0-9]*",
|
|
835
|
+
maxLength: 6,
|
|
836
|
+
value: code,
|
|
837
|
+
onChange: (ev) => setCode(ev.target.value.replace(/\D/g, "")),
|
|
838
|
+
placeholder: copy.codePlaceholder,
|
|
839
|
+
required: true,
|
|
840
|
+
disabled: busy,
|
|
841
|
+
autoComplete: "one-time-code",
|
|
842
|
+
autoFocus: true,
|
|
843
|
+
style: { ...inputStyle, letterSpacing: "0.3em", textAlign: "center", fontSize: 18 }
|
|
844
|
+
}
|
|
845
|
+
),
|
|
846
|
+
/* @__PURE__ */ jsx6("button", { type: "submit", disabled: busy, style: primaryBtnStyle, children: busy ? copy.verifyingLabel : submitLabel }),
|
|
847
|
+
/* @__PURE__ */ jsx6(
|
|
848
|
+
"button",
|
|
849
|
+
{
|
|
850
|
+
type: "button",
|
|
851
|
+
onClick: () => {
|
|
852
|
+
setStep("identify");
|
|
853
|
+
setCode("");
|
|
854
|
+
setError(null);
|
|
855
|
+
},
|
|
856
|
+
disabled: busy,
|
|
857
|
+
style: {
|
|
858
|
+
marginTop: 12,
|
|
859
|
+
background: "none",
|
|
860
|
+
border: "none",
|
|
861
|
+
color: "#71717a",
|
|
862
|
+
fontSize: 12.5,
|
|
863
|
+
cursor: busy ? "not-allowed" : "pointer"
|
|
864
|
+
},
|
|
865
|
+
children: "Use a different email"
|
|
866
|
+
}
|
|
867
|
+
)
|
|
868
|
+
] }),
|
|
869
|
+
error && /* @__PURE__ */ jsx6("p", { role: "alert", style: { margin: 0, fontSize: 12.5, color: "#dc2626" }, children: error }),
|
|
870
|
+
hasLegal && step !== "done" && /* @__PURE__ */ jsxs5("p", { style: { margin: 0, fontSize: 11.5, lineHeight: 1.5, color: "#a1a1aa" }, children: [
|
|
871
|
+
"By continuing, you agree to ",
|
|
872
|
+
appName,
|
|
873
|
+
"'s",
|
|
874
|
+
" ",
|
|
875
|
+
termsUrl && /* @__PURE__ */ jsx6(
|
|
876
|
+
"a",
|
|
877
|
+
{
|
|
878
|
+
href: termsUrl,
|
|
879
|
+
target: "_blank",
|
|
880
|
+
rel: "noopener noreferrer",
|
|
881
|
+
style: { color: "#71717a", textDecoration: "underline" },
|
|
882
|
+
children: "Terms of Service"
|
|
883
|
+
}
|
|
884
|
+
),
|
|
885
|
+
termsUrl && privacyUrl && " \xB7 ",
|
|
886
|
+
privacyUrl && /* @__PURE__ */ jsx6(
|
|
887
|
+
"a",
|
|
888
|
+
{
|
|
889
|
+
href: privacyUrl,
|
|
890
|
+
target: "_blank",
|
|
891
|
+
rel: "noopener noreferrer",
|
|
892
|
+
style: { color: "#71717a", textDecoration: "underline" },
|
|
893
|
+
children: "Privacy Policy"
|
|
894
|
+
}
|
|
895
|
+
)
|
|
896
|
+
] }),
|
|
897
|
+
/* @__PURE__ */ jsx6("div", { style: { display: "flex", justifyContent: "center", paddingTop: 2 }, children: /* @__PURE__ */ jsx6(ElvixSecuredBadge, { variant: "outline", theme: "light", size: "sm", accentColor: brand }) })
|
|
898
|
+
] });
|
|
899
|
+
}
|
|
900
|
+
function hexToRgba(hex, alpha) {
|
|
901
|
+
const m = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
|
|
902
|
+
if (!m) return hex;
|
|
903
|
+
let h = m[1];
|
|
904
|
+
if (h.length === 3)
|
|
905
|
+
h = h.split("").map((c) => c + c).join("");
|
|
906
|
+
const n = Number.parseInt(h, 16);
|
|
907
|
+
const r = n >> 16 & 255;
|
|
908
|
+
const g = n >> 8 & 255;
|
|
909
|
+
const b = n & 255;
|
|
910
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// src/react/elvix-sign-in-button.tsx
|
|
914
|
+
import { useState as useState4 } from "react";
|
|
915
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
916
|
+
var ELVIX_URL2 = "https://elvix.is";
|
|
427
917
|
var PRESET_LABEL = {
|
|
428
918
|
"sign-in-with-elvix": "Sign in with elvix",
|
|
429
919
|
"continue-with-elvix": "Continue with elvix",
|
|
@@ -462,7 +952,7 @@ function shieldColor(variant, theme) {
|
|
|
462
952
|
}
|
|
463
953
|
function ElvixSignInButton({
|
|
464
954
|
clientId,
|
|
465
|
-
baseUrl =
|
|
955
|
+
baseUrl = ELVIX_URL2,
|
|
466
956
|
returnUrl,
|
|
467
957
|
type = "standard",
|
|
468
958
|
variant = "filled",
|
|
@@ -475,9 +965,16 @@ function ElvixSignInButton({
|
|
|
475
965
|
href,
|
|
476
966
|
mode = "redirect",
|
|
477
967
|
onClick,
|
|
478
|
-
onResult
|
|
968
|
+
onResult,
|
|
969
|
+
width,
|
|
970
|
+
height,
|
|
971
|
+
minWidth,
|
|
972
|
+
maxWidth,
|
|
973
|
+
minHeight,
|
|
974
|
+
maxHeight
|
|
479
975
|
}) {
|
|
480
|
-
const
|
|
976
|
+
const sized = sizeStyle({ width, height, minWidth, maxWidth, minHeight, maxHeight });
|
|
977
|
+
const [embedOpen, setEmbedOpen] = useState4(false);
|
|
481
978
|
const isIcon = type === "icon";
|
|
482
979
|
const resolvedLabel = label ?? PRESET_LABEL[preset];
|
|
483
980
|
const tone = variantTone(variant, theme);
|
|
@@ -498,18 +995,20 @@ function ElvixSignInButton({
|
|
|
498
995
|
border: tone.border,
|
|
499
996
|
boxShadow: tone.shadow,
|
|
500
997
|
transition: "background 0.15s, border-color 0.15s",
|
|
501
|
-
...isIcon ? { height: SIZE_ICON[size], width: SIZE_ICON[size] } : { height: std.height, paddingLeft: std.padX, paddingRight: std.padX, gap: std.gap }
|
|
998
|
+
...isIcon ? { height: SIZE_ICON[size], width: SIZE_ICON[size] } : { height: std.height, paddingLeft: std.padX, paddingRight: std.padX, gap: std.gap },
|
|
999
|
+
// Dimensional overrides win over the size preset above.
|
|
1000
|
+
...sized
|
|
502
1001
|
};
|
|
503
|
-
const content = /* @__PURE__ */
|
|
504
|
-
/* @__PURE__ */
|
|
505
|
-
isIcon ? null : /* @__PURE__ */
|
|
1002
|
+
const content = /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1003
|
+
/* @__PURE__ */ jsx7(ElvixShield, { size: ICON_SIZE[size], fill: shieldColor(variant, theme), accent: "#8e7dff" }),
|
|
1004
|
+
isIcon ? null : /* @__PURE__ */ jsx7("span", { children: resolvedLabel })
|
|
506
1005
|
] });
|
|
507
1006
|
if (mode === "callback") {
|
|
508
|
-
return /* @__PURE__ */
|
|
1007
|
+
return /* @__PURE__ */ jsx7("button", { type: "button", onClick, className, style, "aria-label": isIcon ? resolvedLabel : void 0, children: content });
|
|
509
1008
|
}
|
|
510
1009
|
if (mode === "embed") {
|
|
511
|
-
return /* @__PURE__ */
|
|
512
|
-
!embedOpen && /* @__PURE__ */
|
|
1010
|
+
return /* @__PURE__ */ jsxs6("div", { "data-elvix-signin-button-embed": "", style: sized, children: [
|
|
1011
|
+
!embedOpen && /* @__PURE__ */ jsx7(
|
|
513
1012
|
"button",
|
|
514
1013
|
{
|
|
515
1014
|
type: "button",
|
|
@@ -520,7 +1019,7 @@ function ElvixSignInButton({
|
|
|
520
1019
|
children: content
|
|
521
1020
|
}
|
|
522
1021
|
),
|
|
523
|
-
embedOpen && /* @__PURE__ */
|
|
1022
|
+
embedOpen && /* @__PURE__ */ jsx7(
|
|
524
1023
|
ElvixSignIn,
|
|
525
1024
|
{
|
|
526
1025
|
onResult: (r) => {
|
|
@@ -537,86 +1036,17 @@ function ElvixSignInButton({
|
|
|
537
1036
|
const sep = base.includes("?") ? "&" : "?";
|
|
538
1037
|
return `${base}${sep}return=${encodeURIComponent(returnUrl)}`;
|
|
539
1038
|
})();
|
|
540
|
-
return /* @__PURE__ */
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// src/react/elvix-secured-badge.tsx
|
|
544
|
-
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
545
|
-
var ELVIX_URL2 = "https://elvix.is";
|
|
546
|
-
var SIZE = {
|
|
547
|
-
sm: { height: 28, padX: 10, font: 11.5, icon: 14, gap: 6 },
|
|
548
|
-
md: { height: 32, padX: 12, font: 12.5, icon: 16, gap: 7 },
|
|
549
|
-
lg: { height: 36, padX: 14, font: 13, icon: 18, gap: 8 }
|
|
550
|
-
};
|
|
551
|
-
var TONE = {
|
|
552
|
-
white: {
|
|
553
|
-
light: { bg: "#ffffff", border: "#e4e4e7", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" },
|
|
554
|
-
dark: { bg: "#ffffff", border: "transparent", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" }
|
|
555
|
-
},
|
|
556
|
-
dark: {
|
|
557
|
-
light: { bg: "#0a0a0b", border: "rgba(0,0,0,0.1)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" },
|
|
558
|
-
dark: { bg: "#0a0a0b", border: "rgba(255,255,255,0.1)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" }
|
|
559
|
-
},
|
|
560
|
-
outline: {
|
|
561
|
-
light: { bg: "transparent", border: "rgba(0,0,0,0.15)", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" },
|
|
562
|
-
dark: { bg: "transparent", border: "rgba(142,125,255,0.4)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" }
|
|
563
|
-
}
|
|
564
|
-
};
|
|
565
|
-
function ElvixSecuredBadge({
|
|
566
|
-
variant = "white",
|
|
567
|
-
size = "md",
|
|
568
|
-
theme = "dark",
|
|
569
|
-
accentColor = "#8e7dff",
|
|
570
|
-
href = ELVIX_URL2,
|
|
571
|
-
className = ""
|
|
572
|
-
}) {
|
|
573
|
-
const s = SIZE[size];
|
|
574
|
-
const t = TONE[variant][theme];
|
|
575
|
-
const style = {
|
|
576
|
-
display: "inline-flex",
|
|
577
|
-
alignItems: "center",
|
|
578
|
-
gap: s.gap,
|
|
579
|
-
height: s.height,
|
|
580
|
-
paddingLeft: s.padX,
|
|
581
|
-
paddingRight: s.padX,
|
|
582
|
-
fontSize: s.font,
|
|
583
|
-
fontWeight: 500,
|
|
584
|
-
borderRadius: 9999,
|
|
585
|
-
background: t.bg,
|
|
586
|
-
border: `1px solid ${t.border}`,
|
|
587
|
-
color: t.brand,
|
|
588
|
-
textDecoration: "none",
|
|
589
|
-
userSelect: "none",
|
|
590
|
-
lineHeight: 1
|
|
591
|
-
};
|
|
592
|
-
return /* @__PURE__ */ jsxs5(
|
|
593
|
-
"a",
|
|
594
|
-
{
|
|
595
|
-
href,
|
|
596
|
-
target: "_blank",
|
|
597
|
-
rel: "noopener noreferrer",
|
|
598
|
-
className,
|
|
599
|
-
style,
|
|
600
|
-
"data-elvix-secured-badge": "",
|
|
601
|
-
children: [
|
|
602
|
-
/* @__PURE__ */ jsx6(ElvixShield, { size: s.icon, fill: t.shield, accent: accentColor }),
|
|
603
|
-
/* @__PURE__ */ jsxs5("span", { style: { display: "inline-flex", alignItems: "baseline", gap: 4 }, children: [
|
|
604
|
-
/* @__PURE__ */ jsx6("span", { style: { color: t.lead }, children: "Secured by" }),
|
|
605
|
-
/* @__PURE__ */ jsx6("span", { style: { color: t.brand, fontWeight: 600 }, children: "elvix" })
|
|
606
|
-
] })
|
|
607
|
-
]
|
|
608
|
-
}
|
|
609
|
-
);
|
|
1039
|
+
return /* @__PURE__ */ jsx7("a", { href: destination, className, style, "aria-label": isIcon ? resolvedLabel : void 0, children: content });
|
|
610
1040
|
}
|
|
611
1041
|
|
|
612
1042
|
// src/react/hooks.ts
|
|
613
|
-
import { useCallback, useEffect as useEffect2, useState as
|
|
1043
|
+
import { useCallback, useEffect as useEffect2, useState as useState5 } from "react";
|
|
614
1044
|
var POLL_MS = 7e3;
|
|
615
1045
|
function useUserList(kind, opts) {
|
|
616
1046
|
const { applicationId, baseUrl = "", pollMs = POLL_MS } = opts;
|
|
617
|
-
const [slugs, setSlugs] =
|
|
618
|
-
const [loading, setLoading] =
|
|
619
|
-
const [error, setError] =
|
|
1047
|
+
const [slugs, setSlugs] = useState5([]);
|
|
1048
|
+
const [loading, setLoading] = useState5(true);
|
|
1049
|
+
const [error, setError] = useState5(null);
|
|
620
1050
|
const refresh = useCallback(async () => {
|
|
621
1051
|
setError(null);
|
|
622
1052
|
try {
|
|
@@ -683,7 +1113,7 @@ function ElvixLifecycleWatcher({
|
|
|
683
1113
|
}
|
|
684
1114
|
|
|
685
1115
|
// src/react/elvix-username.tsx
|
|
686
|
-
import { useState as
|
|
1116
|
+
import { useState as useState6 } from "react";
|
|
687
1117
|
|
|
688
1118
|
// src/react/lib.ts
|
|
689
1119
|
async function appPost(opts, path, body) {
|
|
@@ -741,15 +1171,22 @@ async function appDelete(opts, path) {
|
|
|
741
1171
|
}
|
|
742
1172
|
|
|
743
1173
|
// src/react/elvix-username.tsx
|
|
744
|
-
import { jsx as
|
|
1174
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
745
1175
|
function ElvixUsername({
|
|
746
|
-
onResult
|
|
1176
|
+
onResult,
|
|
1177
|
+
width,
|
|
1178
|
+
height,
|
|
1179
|
+
minWidth,
|
|
1180
|
+
maxWidth,
|
|
1181
|
+
minHeight,
|
|
1182
|
+
maxHeight
|
|
747
1183
|
}) {
|
|
1184
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
748
1185
|
const ctx = useElvixContext();
|
|
749
|
-
const [value, setValue] =
|
|
750
|
-
const [busy, setBusy] =
|
|
751
|
-
const [error, setError] =
|
|
752
|
-
const [done, setDone] =
|
|
1186
|
+
const [value, setValue] = useState6("");
|
|
1187
|
+
const [busy, setBusy] = useState6(false);
|
|
1188
|
+
const [error, setError] = useState6(null);
|
|
1189
|
+
const [done, setDone] = useState6(null);
|
|
753
1190
|
async function submit(e) {
|
|
754
1191
|
e.preventDefault();
|
|
755
1192
|
if (!ctx.app) return;
|
|
@@ -769,17 +1206,17 @@ function ElvixUsername({
|
|
|
769
1206
|
onResult?.(result);
|
|
770
1207
|
}
|
|
771
1208
|
if (done) {
|
|
772
|
-
return /* @__PURE__ */
|
|
1209
|
+
return /* @__PURE__ */ jsx8(ElvixCard, { title: "Username saved", ...sizeProps, children: /* @__PURE__ */ jsxs7("p", { children: [
|
|
773
1210
|
"You are now ",
|
|
774
|
-
/* @__PURE__ */
|
|
1211
|
+
/* @__PURE__ */ jsxs7("strong", { children: [
|
|
775
1212
|
"@",
|
|
776
1213
|
done
|
|
777
1214
|
] }),
|
|
778
1215
|
"."
|
|
779
1216
|
] }) });
|
|
780
1217
|
}
|
|
781
|
-
return /* @__PURE__ */
|
|
782
|
-
/* @__PURE__ */
|
|
1218
|
+
return /* @__PURE__ */ jsx8(ElvixCard, { title: "Choose a username", ...sizeProps, children: /* @__PURE__ */ jsxs7("form", { onSubmit: submit, className: "elvix-form", children: [
|
|
1219
|
+
/* @__PURE__ */ jsx8(
|
|
783
1220
|
"input",
|
|
784
1221
|
{
|
|
785
1222
|
type: "text",
|
|
@@ -792,21 +1229,28 @@ function ElvixUsername({
|
|
|
792
1229
|
className: "elvix-input"
|
|
793
1230
|
}
|
|
794
1231
|
),
|
|
795
|
-
/* @__PURE__ */
|
|
796
|
-
error && /* @__PURE__ */
|
|
1232
|
+
/* @__PURE__ */ jsx8("button", { type: "submit", disabled: busy || value.length < 4, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Claim" }),
|
|
1233
|
+
error && /* @__PURE__ */ jsx8("p", { role: "alert", className: "elvix-error", children: error })
|
|
797
1234
|
] }) });
|
|
798
1235
|
}
|
|
799
1236
|
|
|
800
1237
|
// src/react/elvix-avatar.tsx
|
|
801
|
-
import { useState as
|
|
802
|
-
import { jsx as
|
|
1238
|
+
import { useState as useState7 } from "react";
|
|
1239
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
803
1240
|
function ElvixAvatar({
|
|
804
|
-
onResult
|
|
1241
|
+
onResult,
|
|
1242
|
+
width,
|
|
1243
|
+
height,
|
|
1244
|
+
minWidth,
|
|
1245
|
+
maxWidth,
|
|
1246
|
+
minHeight,
|
|
1247
|
+
maxHeight
|
|
805
1248
|
}) {
|
|
1249
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
806
1250
|
const ctx = useElvixContext();
|
|
807
|
-
const [busy, setBusy] =
|
|
808
|
-
const [error, setError] =
|
|
809
|
-
const [preview, setPreview] =
|
|
1251
|
+
const [busy, setBusy] = useState7(false);
|
|
1252
|
+
const [error, setError] = useState7(null);
|
|
1253
|
+
const [preview, setPreview] = useState7(null);
|
|
810
1254
|
async function onFile(e) {
|
|
811
1255
|
const file = e.target.files?.[0];
|
|
812
1256
|
if (!file || !ctx.app) return;
|
|
@@ -829,8 +1273,8 @@ function ElvixAvatar({
|
|
|
829
1273
|
if (!result.ok) setError(result.error);
|
|
830
1274
|
onResult?.(result);
|
|
831
1275
|
}
|
|
832
|
-
return /* @__PURE__ */
|
|
833
|
-
preview && /* @__PURE__ */
|
|
1276
|
+
return /* @__PURE__ */ jsxs8(ElvixCard, { title: "Avatar", ...sizeProps, children: [
|
|
1277
|
+
preview && /* @__PURE__ */ jsx9(
|
|
834
1278
|
"img",
|
|
835
1279
|
{
|
|
836
1280
|
src: preview,
|
|
@@ -838,22 +1282,29 @@ function ElvixAvatar({
|
|
|
838
1282
|
style: { width: 96, height: 96, borderRadius: "50%", objectFit: "cover", marginBottom: 12 }
|
|
839
1283
|
}
|
|
840
1284
|
),
|
|
841
|
-
/* @__PURE__ */
|
|
842
|
-
busy && /* @__PURE__ */
|
|
843
|
-
error && /* @__PURE__ */
|
|
1285
|
+
/* @__PURE__ */ jsx9("input", { type: "file", accept: "image/png,image/jpeg,image/webp", onChange: onFile, disabled: busy }),
|
|
1286
|
+
busy && /* @__PURE__ */ jsx9("p", { children: "Uploading\u2026" }),
|
|
1287
|
+
error && /* @__PURE__ */ jsx9("p", { role: "alert", className: "elvix-error", children: error })
|
|
844
1288
|
] });
|
|
845
1289
|
}
|
|
846
1290
|
|
|
847
1291
|
// src/react/elvix-banner.tsx
|
|
848
|
-
import { useState as
|
|
849
|
-
import { jsx as
|
|
1292
|
+
import { useState as useState8 } from "react";
|
|
1293
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
850
1294
|
function ElvixBanner({
|
|
851
|
-
onResult
|
|
1295
|
+
onResult,
|
|
1296
|
+
width,
|
|
1297
|
+
height,
|
|
1298
|
+
minWidth,
|
|
1299
|
+
maxWidth,
|
|
1300
|
+
minHeight,
|
|
1301
|
+
maxHeight
|
|
852
1302
|
}) {
|
|
1303
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
853
1304
|
const ctx = useElvixContext();
|
|
854
|
-
const [busy, setBusy] =
|
|
855
|
-
const [error, setError] =
|
|
856
|
-
const [preview, setPreview] =
|
|
1305
|
+
const [busy, setBusy] = useState8(false);
|
|
1306
|
+
const [error, setError] = useState8(null);
|
|
1307
|
+
const [preview, setPreview] = useState8(null);
|
|
857
1308
|
async function onFile(e) {
|
|
858
1309
|
const file = e.target.files?.[0];
|
|
859
1310
|
if (!file || !ctx.app) return;
|
|
@@ -876,8 +1327,8 @@ function ElvixBanner({
|
|
|
876
1327
|
if (!result.ok) setError(result.error);
|
|
877
1328
|
onResult?.(result);
|
|
878
1329
|
}
|
|
879
|
-
return /* @__PURE__ */
|
|
880
|
-
preview && /* @__PURE__ */
|
|
1330
|
+
return /* @__PURE__ */ jsxs9(ElvixCard, { title: "Banner", ...sizeProps, children: [
|
|
1331
|
+
preview && /* @__PURE__ */ jsx10(
|
|
881
1332
|
"img",
|
|
882
1333
|
{
|
|
883
1334
|
src: preview,
|
|
@@ -885,26 +1336,33 @@ function ElvixBanner({
|
|
|
885
1336
|
style: { width: "100%", aspectRatio: "16/9", objectFit: "cover", borderRadius: 10, marginBottom: 12 }
|
|
886
1337
|
}
|
|
887
1338
|
),
|
|
888
|
-
/* @__PURE__ */
|
|
889
|
-
busy && /* @__PURE__ */
|
|
890
|
-
error && /* @__PURE__ */
|
|
1339
|
+
/* @__PURE__ */ jsx10("input", { type: "file", accept: "image/png,image/jpeg,image/webp", onChange: onFile, disabled: busy }),
|
|
1340
|
+
busy && /* @__PURE__ */ jsx10("p", { children: "Uploading\u2026" }),
|
|
1341
|
+
error && /* @__PURE__ */ jsx10("p", { role: "alert", className: "elvix-error", children: error })
|
|
891
1342
|
] });
|
|
892
1343
|
}
|
|
893
1344
|
|
|
894
1345
|
// src/react/elvix-identity-form.tsx
|
|
895
|
-
import { useState as
|
|
896
|
-
import { jsx as
|
|
1346
|
+
import { useState as useState9 } from "react";
|
|
1347
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
897
1348
|
function ElvixIdentityForm({
|
|
898
1349
|
initialName = "",
|
|
899
1350
|
initialBio = "",
|
|
900
|
-
onResult
|
|
1351
|
+
onResult,
|
|
1352
|
+
width,
|
|
1353
|
+
height,
|
|
1354
|
+
minWidth,
|
|
1355
|
+
maxWidth,
|
|
1356
|
+
minHeight,
|
|
1357
|
+
maxHeight
|
|
901
1358
|
}) {
|
|
1359
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
902
1360
|
const ctx = useElvixContext();
|
|
903
|
-
const [name, setName] =
|
|
904
|
-
const [bio, setBio] =
|
|
905
|
-
const [busy, setBusy] =
|
|
906
|
-
const [error, setError] =
|
|
907
|
-
const [saved, setSaved] =
|
|
1361
|
+
const [name, setName] = useState9(initialName);
|
|
1362
|
+
const [bio, setBio] = useState9(initialBio);
|
|
1363
|
+
const [busy, setBusy] = useState9(false);
|
|
1364
|
+
const [error, setError] = useState9(null);
|
|
1365
|
+
const [saved, setSaved] = useState9(false);
|
|
908
1366
|
async function submit(e) {
|
|
909
1367
|
e.preventDefault();
|
|
910
1368
|
if (!ctx.app) return;
|
|
@@ -920,35 +1378,42 @@ function ElvixIdentityForm({
|
|
|
920
1378
|
else setSaved(true);
|
|
921
1379
|
onResult?.(result);
|
|
922
1380
|
}
|
|
923
|
-
return /* @__PURE__ */
|
|
924
|
-
/* @__PURE__ */
|
|
1381
|
+
return /* @__PURE__ */ jsx11(ElvixCard, { title: "Identity", ...sizeProps, children: /* @__PURE__ */ jsxs10("form", { onSubmit: submit, className: "elvix-form", children: [
|
|
1382
|
+
/* @__PURE__ */ jsxs10("label", { children: [
|
|
925
1383
|
"Name",
|
|
926
|
-
/* @__PURE__ */
|
|
1384
|
+
/* @__PURE__ */ jsx11("input", { value: name, onChange: (e) => setName(e.target.value), maxLength: 80, disabled: busy, className: "elvix-input" })
|
|
927
1385
|
] }),
|
|
928
|
-
/* @__PURE__ */
|
|
1386
|
+
/* @__PURE__ */ jsxs10("label", { children: [
|
|
929
1387
|
"Bio",
|
|
930
|
-
/* @__PURE__ */
|
|
1388
|
+
/* @__PURE__ */ jsx11("textarea", { value: bio, onChange: (e) => setBio(e.target.value), maxLength: 500, rows: 3, disabled: busy, className: "elvix-input" })
|
|
931
1389
|
] }),
|
|
932
|
-
/* @__PURE__ */
|
|
933
|
-
saved && /* @__PURE__ */
|
|
934
|
-
error && /* @__PURE__ */
|
|
1390
|
+
/* @__PURE__ */ jsx11("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" }),
|
|
1391
|
+
saved && /* @__PURE__ */ jsx11("p", { className: "elvix-muted", children: "Saved." }),
|
|
1392
|
+
error && /* @__PURE__ */ jsx11("p", { role: "alert", className: "elvix-error", children: error })
|
|
935
1393
|
] }) });
|
|
936
1394
|
}
|
|
937
1395
|
|
|
938
1396
|
// src/react/elvix-region.tsx
|
|
939
|
-
import { useState as
|
|
940
|
-
import { jsx as
|
|
1397
|
+
import { useState as useState10 } from "react";
|
|
1398
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
941
1399
|
function ElvixRegion({
|
|
942
1400
|
initialCountry = "",
|
|
943
1401
|
initialTimezone = "",
|
|
944
|
-
onResult
|
|
1402
|
+
onResult,
|
|
1403
|
+
width,
|
|
1404
|
+
height,
|
|
1405
|
+
minWidth,
|
|
1406
|
+
maxWidth,
|
|
1407
|
+
minHeight,
|
|
1408
|
+
maxHeight
|
|
945
1409
|
}) {
|
|
1410
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
946
1411
|
const ctx = useElvixContext();
|
|
947
|
-
const [country, setCountry] =
|
|
948
|
-
const [timezone, setTimezone] =
|
|
949
|
-
const [busy, setBusy] =
|
|
950
|
-
const [error, setError] =
|
|
951
|
-
const [saved, setSaved] =
|
|
1412
|
+
const [country, setCountry] = useState10(initialCountry);
|
|
1413
|
+
const [timezone, setTimezone] = useState10(initialTimezone);
|
|
1414
|
+
const [busy, setBusy] = useState10(false);
|
|
1415
|
+
const [error, setError] = useState10(null);
|
|
1416
|
+
const [saved, setSaved] = useState10(false);
|
|
952
1417
|
async function submit(e) {
|
|
953
1418
|
e.preventDefault();
|
|
954
1419
|
if (!ctx.app) return;
|
|
@@ -964,33 +1429,40 @@ function ElvixRegion({
|
|
|
964
1429
|
else setSaved(true);
|
|
965
1430
|
onResult?.(result);
|
|
966
1431
|
}
|
|
967
|
-
return /* @__PURE__ */
|
|
968
|
-
/* @__PURE__ */
|
|
1432
|
+
return /* @__PURE__ */ jsx12(ElvixCard, { title: "Region", ...sizeProps, children: /* @__PURE__ */ jsxs11("form", { onSubmit: submit, className: "elvix-form", children: [
|
|
1433
|
+
/* @__PURE__ */ jsxs11("label", { children: [
|
|
969
1434
|
"Country (ISO-2)",
|
|
970
|
-
/* @__PURE__ */
|
|
1435
|
+
/* @__PURE__ */ jsx12("input", { value: country, onChange: (e) => setCountry(e.target.value.toUpperCase()), maxLength: 2, pattern: "[A-Z]{2}", disabled: busy, className: "elvix-input" })
|
|
971
1436
|
] }),
|
|
972
|
-
/* @__PURE__ */
|
|
1437
|
+
/* @__PURE__ */ jsxs11("label", { children: [
|
|
973
1438
|
"Timezone",
|
|
974
|
-
/* @__PURE__ */
|
|
1439
|
+
/* @__PURE__ */ jsx12("input", { value: timezone, onChange: (e) => setTimezone(e.target.value), placeholder: "Europe/Berlin", disabled: busy, className: "elvix-input" })
|
|
975
1440
|
] }),
|
|
976
|
-
/* @__PURE__ */
|
|
977
|
-
saved && /* @__PURE__ */
|
|
978
|
-
error && /* @__PURE__ */
|
|
1441
|
+
/* @__PURE__ */ jsx12("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" }),
|
|
1442
|
+
saved && /* @__PURE__ */ jsx12("p", { className: "elvix-muted", children: "Saved." }),
|
|
1443
|
+
error && /* @__PURE__ */ jsx12("p", { role: "alert", className: "elvix-error", children: error })
|
|
979
1444
|
] }) });
|
|
980
1445
|
}
|
|
981
1446
|
|
|
982
1447
|
// src/react/elvix-languages.tsx
|
|
983
|
-
import { useState as
|
|
984
|
-
import { jsx as
|
|
1448
|
+
import { useState as useState11 } from "react";
|
|
1449
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
985
1450
|
function ElvixLanguages({
|
|
986
1451
|
initial = [],
|
|
987
|
-
onResult
|
|
1452
|
+
onResult,
|
|
1453
|
+
width,
|
|
1454
|
+
height,
|
|
1455
|
+
minWidth,
|
|
1456
|
+
maxWidth,
|
|
1457
|
+
minHeight,
|
|
1458
|
+
maxHeight
|
|
988
1459
|
}) {
|
|
1460
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
989
1461
|
const ctx = useElvixContext();
|
|
990
|
-
const [raw, setRaw] =
|
|
991
|
-
const [busy, setBusy] =
|
|
992
|
-
const [error, setError] =
|
|
993
|
-
const [saved, setSaved] =
|
|
1462
|
+
const [raw, setRaw] = useState11(initial.join(", "));
|
|
1463
|
+
const [busy, setBusy] = useState11(false);
|
|
1464
|
+
const [error, setError] = useState11(null);
|
|
1465
|
+
const [saved, setSaved] = useState11(false);
|
|
994
1466
|
async function submit(e) {
|
|
995
1467
|
e.preventDefault();
|
|
996
1468
|
if (!ctx.app) return;
|
|
@@ -1007,27 +1479,34 @@ function ElvixLanguages({
|
|
|
1007
1479
|
else setSaved(true);
|
|
1008
1480
|
onResult?.(result);
|
|
1009
1481
|
}
|
|
1010
|
-
return /* @__PURE__ */
|
|
1011
|
-
/* @__PURE__ */
|
|
1482
|
+
return /* @__PURE__ */ jsx13(ElvixCard, { title: "Languages", ...sizeProps, children: /* @__PURE__ */ jsxs12("form", { onSubmit: submit, className: "elvix-form", children: [
|
|
1483
|
+
/* @__PURE__ */ jsxs12("label", { children: [
|
|
1012
1484
|
"Preferred languages (comma-separated BCP-47 tags)",
|
|
1013
|
-
/* @__PURE__ */
|
|
1485
|
+
/* @__PURE__ */ jsx13("input", { value: raw, onChange: (e) => setRaw(e.target.value), placeholder: "en-GB, de-DE", disabled: busy, className: "elvix-input" })
|
|
1014
1486
|
] }),
|
|
1015
|
-
/* @__PURE__ */
|
|
1016
|
-
saved && /* @__PURE__ */
|
|
1017
|
-
error && /* @__PURE__ */
|
|
1487
|
+
/* @__PURE__ */ jsx13("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" }),
|
|
1488
|
+
saved && /* @__PURE__ */ jsx13("p", { className: "elvix-muted", children: "Saved." }),
|
|
1489
|
+
error && /* @__PURE__ */ jsx13("p", { role: "alert", className: "elvix-error", children: error })
|
|
1018
1490
|
] }) });
|
|
1019
1491
|
}
|
|
1020
1492
|
|
|
1021
1493
|
// src/react/elvix-sessions.tsx
|
|
1022
|
-
import { useEffect as useEffect4, useState as
|
|
1023
|
-
import { jsx as
|
|
1494
|
+
import { useEffect as useEffect4, useState as useState12 } from "react";
|
|
1495
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1024
1496
|
function ElvixSessions({
|
|
1025
|
-
onResult
|
|
1497
|
+
onResult,
|
|
1498
|
+
width,
|
|
1499
|
+
height,
|
|
1500
|
+
minWidth,
|
|
1501
|
+
maxWidth,
|
|
1502
|
+
minHeight,
|
|
1503
|
+
maxHeight
|
|
1026
1504
|
}) {
|
|
1505
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
1027
1506
|
const ctx = useElvixContext();
|
|
1028
|
-
const [rows, setRows] =
|
|
1029
|
-
const [error, setError] =
|
|
1030
|
-
const [busy, setBusy] =
|
|
1507
|
+
const [rows, setRows] = useState12(null);
|
|
1508
|
+
const [error, setError] = useState12(null);
|
|
1509
|
+
const [busy, setBusy] = useState12(false);
|
|
1031
1510
|
useEffect4(() => {
|
|
1032
1511
|
if (!ctx.app) return;
|
|
1033
1512
|
fetch(`${ctx.baseUrl}/api/account/apps/${ctx.app.applicationId}/sessions`, {
|
|
@@ -1048,36 +1527,43 @@ function ElvixSessions({
|
|
|
1048
1527
|
if (result.ok) setRows((prev) => prev?.filter((s) => s.id !== id) ?? null);
|
|
1049
1528
|
onResult?.(result);
|
|
1050
1529
|
}
|
|
1051
|
-
return /* @__PURE__ */
|
|
1052
|
-
error && /* @__PURE__ */
|
|
1053
|
-
!rows && !error && /* @__PURE__ */
|
|
1054
|
-
rows && /* @__PURE__ */
|
|
1055
|
-
/* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
1530
|
+
return /* @__PURE__ */ jsxs13(ElvixCard, { title: "Active sessions", ...sizeProps, children: [
|
|
1531
|
+
error && /* @__PURE__ */ jsx14("p", { role: "alert", className: "elvix-error", children: error }),
|
|
1532
|
+
!rows && !error && /* @__PURE__ */ jsx14("p", { children: "Loading\u2026" }),
|
|
1533
|
+
rows && /* @__PURE__ */ jsx14("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: rows.map((s) => /* @__PURE__ */ jsx14("li", { style: { padding: "10px 0", borderBottom: "1px solid rgba(0,0,0,0.06)" }, children: /* @__PURE__ */ jsxs13("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [
|
|
1534
|
+
/* @__PURE__ */ jsxs13("div", { children: [
|
|
1535
|
+
/* @__PURE__ */ jsxs13("div", { style: { fontSize: 13, fontWeight: 500 }, children: [
|
|
1057
1536
|
s.device,
|
|
1058
|
-
s.current && /* @__PURE__ */
|
|
1537
|
+
s.current && /* @__PURE__ */ jsx14("span", { style: { marginLeft: 8, color: "var(--elvix-primary-strong)", fontSize: 11 }, children: "\xB7 this device" })
|
|
1059
1538
|
] }),
|
|
1060
|
-
/* @__PURE__ */
|
|
1539
|
+
/* @__PURE__ */ jsxs13("div", { style: { fontSize: 11, color: "rgba(0,0,0,0.55)" }, children: [
|
|
1061
1540
|
s.country ?? "\u2014",
|
|
1062
1541
|
" \xB7 since ",
|
|
1063
1542
|
new Date(s.createdAt).toLocaleDateString()
|
|
1064
1543
|
] })
|
|
1065
1544
|
] }),
|
|
1066
|
-
!s.current && /* @__PURE__ */
|
|
1545
|
+
!s.current && /* @__PURE__ */ jsx14("button", { type: "button", disabled: busy, onClick: () => revoke(s.id), className: "elvix-btn elvix-btn-ghost", children: "Revoke" })
|
|
1067
1546
|
] }) }, s.id)) })
|
|
1068
1547
|
] });
|
|
1069
1548
|
}
|
|
1070
1549
|
|
|
1071
1550
|
// src/react/elvix-export.tsx
|
|
1072
|
-
import { useState as
|
|
1073
|
-
import { jsx as
|
|
1551
|
+
import { useState as useState13 } from "react";
|
|
1552
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1074
1553
|
function ElvixExport({
|
|
1075
|
-
onResult
|
|
1554
|
+
onResult,
|
|
1555
|
+
width,
|
|
1556
|
+
height,
|
|
1557
|
+
minWidth,
|
|
1558
|
+
maxWidth,
|
|
1559
|
+
minHeight,
|
|
1560
|
+
maxHeight
|
|
1076
1561
|
}) {
|
|
1562
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
1077
1563
|
const ctx = useElvixContext();
|
|
1078
|
-
const [busy, setBusy] =
|
|
1079
|
-
const [done, setDone] =
|
|
1080
|
-
const [error, setError] =
|
|
1564
|
+
const [busy, setBusy] = useState13(false);
|
|
1565
|
+
const [done, setDone] = useState13(false);
|
|
1566
|
+
const [error, setError] = useState13(null);
|
|
1081
1567
|
async function start() {
|
|
1082
1568
|
if (!ctx.app) return;
|
|
1083
1569
|
setBusy(true);
|
|
@@ -1092,25 +1578,32 @@ function ElvixExport({
|
|
|
1092
1578
|
else setDone(true);
|
|
1093
1579
|
onResult?.(result);
|
|
1094
1580
|
}
|
|
1095
|
-
return /* @__PURE__ */
|
|
1096
|
-
/* @__PURE__ */
|
|
1097
|
-
done ? /* @__PURE__ */
|
|
1098
|
-
error && /* @__PURE__ */
|
|
1581
|
+
return /* @__PURE__ */ jsxs14(ElvixCard, { title: "Export my data", ...sizeProps, children: [
|
|
1582
|
+
/* @__PURE__ */ jsx15("p", { style: { fontSize: 13, color: "rgba(0,0,0,0.6)" }, children: "Request a zip of every record we hold for you in this app. Delivery by email; single-use download link valid for 24h." }),
|
|
1583
|
+
done ? /* @__PURE__ */ jsx15("p", { className: "elvix-muted", children: "Request queued. Check your email." }) : /* @__PURE__ */ jsx15("button", { type: "button", onClick: start, disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Queuing\u2026" : "Request export" }),
|
|
1584
|
+
error && /* @__PURE__ */ jsx15("p", { role: "alert", className: "elvix-error", children: error })
|
|
1099
1585
|
] });
|
|
1100
1586
|
}
|
|
1101
1587
|
|
|
1102
1588
|
// src/react/elvix-deactivate.tsx
|
|
1103
|
-
import { useState as
|
|
1104
|
-
import { Fragment as Fragment3, jsx as
|
|
1589
|
+
import { useState as useState14 } from "react";
|
|
1590
|
+
import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1105
1591
|
function ElvixDeactivate({
|
|
1106
|
-
onResult
|
|
1592
|
+
onResult,
|
|
1593
|
+
width,
|
|
1594
|
+
height,
|
|
1595
|
+
minWidth,
|
|
1596
|
+
maxWidth,
|
|
1597
|
+
minHeight,
|
|
1598
|
+
maxHeight
|
|
1107
1599
|
}) {
|
|
1600
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
1108
1601
|
const ctx = useElvixContext();
|
|
1109
|
-
const [pane, setPane] =
|
|
1110
|
-
const [challengeId, setChallengeId] =
|
|
1111
|
-
const [code, setCode] =
|
|
1112
|
-
const [busy, setBusy] =
|
|
1113
|
-
const [error, setError] =
|
|
1602
|
+
const [pane, setPane] = useState14("warn");
|
|
1603
|
+
const [challengeId, setChallengeId] = useState14(null);
|
|
1604
|
+
const [code, setCode] = useState14("");
|
|
1605
|
+
const [busy, setBusy] = useState14(false);
|
|
1606
|
+
const [error, setError] = useState14(null);
|
|
1114
1607
|
async function startChallenge() {
|
|
1115
1608
|
if (!ctx.app) return;
|
|
1116
1609
|
setBusy(true);
|
|
@@ -1148,16 +1641,16 @@ function ElvixDeactivate({
|
|
|
1148
1641
|
onResult?.(result);
|
|
1149
1642
|
}
|
|
1150
1643
|
if (pane === "done") {
|
|
1151
|
-
return /* @__PURE__ */
|
|
1644
|
+
return /* @__PURE__ */ jsx16(ElvixCard, { title: "Deactivated", ...sizeProps, children: /* @__PURE__ */ jsx16("p", { children: "Your access has been paused. Sign in again to restore it." }) });
|
|
1152
1645
|
}
|
|
1153
|
-
return /* @__PURE__ */
|
|
1154
|
-
pane === "warn" && /* @__PURE__ */
|
|
1155
|
-
/* @__PURE__ */
|
|
1156
|
-
/* @__PURE__ */
|
|
1646
|
+
return /* @__PURE__ */ jsxs15(ElvixCard, { title: "Deactivate account", ...sizeProps, children: [
|
|
1647
|
+
pane === "warn" && /* @__PURE__ */ jsxs15(Fragment3, { children: [
|
|
1648
|
+
/* @__PURE__ */ jsx16("p", { style: { fontSize: 13, color: "rgba(0,0,0,0.6)" }, children: "Pause your membership. You can restore it any time by signing in again. No data is deleted." }),
|
|
1649
|
+
/* @__PURE__ */ jsx16("button", { type: "button", onClick: startChallenge, disabled: busy, className: "elvix-btn elvix-btn-danger", children: busy ? "Sending\u2026" : "Send code" })
|
|
1157
1650
|
] }),
|
|
1158
|
-
pane === "otp" && /* @__PURE__ */
|
|
1159
|
-
/* @__PURE__ */
|
|
1160
|
-
/* @__PURE__ */
|
|
1651
|
+
pane === "otp" && /* @__PURE__ */ jsxs15("form", { onSubmit: confirm, className: "elvix-form", children: [
|
|
1652
|
+
/* @__PURE__ */ jsx16("p", { className: "elvix-muted", children: "We sent a 6-digit code to your email." }),
|
|
1653
|
+
/* @__PURE__ */ jsx16(
|
|
1161
1654
|
"input",
|
|
1162
1655
|
{
|
|
1163
1656
|
type: "text",
|
|
@@ -1171,24 +1664,31 @@ function ElvixDeactivate({
|
|
|
1171
1664
|
className: "elvix-input"
|
|
1172
1665
|
}
|
|
1173
1666
|
),
|
|
1174
|
-
/* @__PURE__ */
|
|
1667
|
+
/* @__PURE__ */ jsx16("button", { type: "submit", disabled: busy || code.length !== 6, className: "elvix-btn elvix-btn-danger", children: busy ? "Deactivating\u2026" : "Confirm" })
|
|
1175
1668
|
] }),
|
|
1176
|
-
error && /* @__PURE__ */
|
|
1669
|
+
error && /* @__PURE__ */ jsx16("p", { role: "alert", className: "elvix-error", children: error })
|
|
1177
1670
|
] });
|
|
1178
1671
|
}
|
|
1179
1672
|
|
|
1180
1673
|
// src/react/elvix-leave.tsx
|
|
1181
|
-
import { useState as
|
|
1182
|
-
import { Fragment as Fragment4, jsx as
|
|
1674
|
+
import { useState as useState15 } from "react";
|
|
1675
|
+
import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1183
1676
|
function ElvixLeave({
|
|
1184
|
-
onResult
|
|
1677
|
+
onResult,
|
|
1678
|
+
width,
|
|
1679
|
+
height,
|
|
1680
|
+
minWidth,
|
|
1681
|
+
maxWidth,
|
|
1682
|
+
minHeight,
|
|
1683
|
+
maxHeight
|
|
1185
1684
|
}) {
|
|
1685
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
1186
1686
|
const ctx = useElvixContext();
|
|
1187
|
-
const [pane, setPane] =
|
|
1188
|
-
const [challengeId, setChallengeId] =
|
|
1189
|
-
const [code, setCode] =
|
|
1190
|
-
const [busy, setBusy] =
|
|
1191
|
-
const [error, setError] =
|
|
1687
|
+
const [pane, setPane] = useState15("warn");
|
|
1688
|
+
const [challengeId, setChallengeId] = useState15(null);
|
|
1689
|
+
const [code, setCode] = useState15("");
|
|
1690
|
+
const [busy, setBusy] = useState15(false);
|
|
1691
|
+
const [error, setError] = useState15(null);
|
|
1192
1692
|
async function startChallenge() {
|
|
1193
1693
|
if (!ctx.app) return;
|
|
1194
1694
|
setBusy(true);
|
|
@@ -1226,16 +1726,16 @@ function ElvixLeave({
|
|
|
1226
1726
|
onResult?.(result);
|
|
1227
1727
|
}
|
|
1228
1728
|
if (pane === "done") {
|
|
1229
|
-
return /* @__PURE__ */
|
|
1729
|
+
return /* @__PURE__ */ jsx17(ElvixCard, { title: "You've left", ...sizeProps, children: /* @__PURE__ */ jsx17("p", { children: "You've left this app. Your data is archived; sign in again to rejoin." }) });
|
|
1230
1730
|
}
|
|
1231
|
-
return /* @__PURE__ */
|
|
1232
|
-
pane === "warn" && /* @__PURE__ */
|
|
1233
|
-
/* @__PURE__ */
|
|
1234
|
-
/* @__PURE__ */
|
|
1731
|
+
return /* @__PURE__ */ jsxs16(ElvixCard, { title: "Leave this app", ...sizeProps, children: [
|
|
1732
|
+
pane === "warn" && /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
1733
|
+
/* @__PURE__ */ jsx17("p", { style: { fontSize: 13, color: "rgba(0,0,0,0.6)" }, children: "Remove yourself from this app. Audit trail is preserved; you can sign back in any time to rejoin." }),
|
|
1734
|
+
/* @__PURE__ */ jsx17("button", { type: "button", onClick: startChallenge, disabled: busy, className: "elvix-btn elvix-btn-danger", children: busy ? "Sending\u2026" : "Send code" })
|
|
1235
1735
|
] }),
|
|
1236
|
-
pane === "otp" && /* @__PURE__ */
|
|
1237
|
-
/* @__PURE__ */
|
|
1238
|
-
/* @__PURE__ */
|
|
1736
|
+
pane === "otp" && /* @__PURE__ */ jsxs16("form", { onSubmit: confirm, className: "elvix-form", children: [
|
|
1737
|
+
/* @__PURE__ */ jsx17("p", { className: "elvix-muted", children: "We sent a 6-digit code to your email." }),
|
|
1738
|
+
/* @__PURE__ */ jsx17(
|
|
1239
1739
|
"input",
|
|
1240
1740
|
{
|
|
1241
1741
|
type: "text",
|
|
@@ -1249,24 +1749,31 @@ function ElvixLeave({
|
|
|
1249
1749
|
className: "elvix-input"
|
|
1250
1750
|
}
|
|
1251
1751
|
),
|
|
1252
|
-
/* @__PURE__ */
|
|
1752
|
+
/* @__PURE__ */ jsx17("button", { type: "submit", disabled: busy || code.length !== 6, className: "elvix-btn elvix-btn-danger", children: busy ? "Leaving\u2026" : "Confirm leave" })
|
|
1253
1753
|
] }),
|
|
1254
|
-
error && /* @__PURE__ */
|
|
1754
|
+
error && /* @__PURE__ */ jsx17("p", { role: "alert", className: "elvix-error", children: error })
|
|
1255
1755
|
] });
|
|
1256
1756
|
}
|
|
1257
1757
|
|
|
1258
1758
|
// src/react/elvix-address-book.tsx
|
|
1259
|
-
import { useEffect as useEffect5, useState as
|
|
1260
|
-
import { jsx as
|
|
1759
|
+
import { useEffect as useEffect5, useState as useState16 } from "react";
|
|
1760
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1261
1761
|
function ElvixAddressBook({
|
|
1262
|
-
onResult
|
|
1762
|
+
onResult,
|
|
1763
|
+
width,
|
|
1764
|
+
height,
|
|
1765
|
+
minWidth,
|
|
1766
|
+
maxWidth,
|
|
1767
|
+
minHeight,
|
|
1768
|
+
maxHeight
|
|
1263
1769
|
}) {
|
|
1770
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
1264
1771
|
const ctx = useElvixContext();
|
|
1265
|
-
const [rows, setRows] =
|
|
1266
|
-
const [error, setError] =
|
|
1267
|
-
const [busy, setBusy] =
|
|
1268
|
-
const [adding, setAdding] =
|
|
1269
|
-
const [form, setForm] =
|
|
1772
|
+
const [rows, setRows] = useState16(null);
|
|
1773
|
+
const [error, setError] = useState16(null);
|
|
1774
|
+
const [busy, setBusy] = useState16(false);
|
|
1775
|
+
const [adding, setAdding] = useState16(false);
|
|
1776
|
+
const [form, setForm] = useState16({
|
|
1270
1777
|
label: "Home",
|
|
1271
1778
|
line1: "",
|
|
1272
1779
|
postalCode: "",
|
|
@@ -1315,14 +1822,14 @@ function ElvixAddressBook({
|
|
|
1315
1822
|
if (result.ok) setRows((prev) => prev?.filter((a) => a.id !== id) ?? null);
|
|
1316
1823
|
onResult?.(result);
|
|
1317
1824
|
}
|
|
1318
|
-
return /* @__PURE__ */
|
|
1319
|
-
error && /* @__PURE__ */
|
|
1320
|
-
!rows && !error && /* @__PURE__ */
|
|
1321
|
-
rows && rows.length === 0 && /* @__PURE__ */
|
|
1322
|
-
rows?.map((a) => /* @__PURE__ */
|
|
1323
|
-
/* @__PURE__ */
|
|
1324
|
-
/* @__PURE__ */
|
|
1325
|
-
/* @__PURE__ */
|
|
1825
|
+
return /* @__PURE__ */ jsxs17(ElvixCard, { title: "Addresses", ...sizeProps, children: [
|
|
1826
|
+
error && /* @__PURE__ */ jsx18("p", { role: "alert", className: "elvix-error", children: error }),
|
|
1827
|
+
!rows && !error && /* @__PURE__ */ jsx18("p", { children: "Loading\u2026" }),
|
|
1828
|
+
rows && rows.length === 0 && /* @__PURE__ */ jsx18("p", { className: "elvix-muted", children: "No addresses yet." }),
|
|
1829
|
+
rows?.map((a) => /* @__PURE__ */ jsxs17("div", { style: { padding: "8px 0", borderBottom: "1px solid rgba(0,0,0,0.06)", display: "flex", justifyContent: "space-between", gap: 12 }, children: [
|
|
1830
|
+
/* @__PURE__ */ jsxs17("div", { style: { fontSize: 13 }, children: [
|
|
1831
|
+
/* @__PURE__ */ jsx18("div", { style: { fontWeight: 500 }, children: a.label }),
|
|
1832
|
+
/* @__PURE__ */ jsxs17("div", { style: { color: "rgba(0,0,0,0.55)" }, children: [
|
|
1326
1833
|
a.line1,
|
|
1327
1834
|
a.line2 ? `, ${a.line2}` : "",
|
|
1328
1835
|
", ",
|
|
@@ -1333,32 +1840,39 @@ function ElvixAddressBook({
|
|
|
1333
1840
|
a.country
|
|
1334
1841
|
] })
|
|
1335
1842
|
] }),
|
|
1336
|
-
/* @__PURE__ */
|
|
1843
|
+
/* @__PURE__ */ jsx18("button", { type: "button", disabled: busy, onClick: () => remove(a.id), className: "elvix-btn elvix-btn-ghost", children: "Remove" })
|
|
1337
1844
|
] }, a.id)),
|
|
1338
|
-
!adding && /* @__PURE__ */
|
|
1339
|
-
adding && /* @__PURE__ */
|
|
1340
|
-
/* @__PURE__ */
|
|
1341
|
-
/* @__PURE__ */
|
|
1342
|
-
/* @__PURE__ */
|
|
1343
|
-
/* @__PURE__ */
|
|
1344
|
-
/* @__PURE__ */
|
|
1345
|
-
/* @__PURE__ */
|
|
1845
|
+
!adding && /* @__PURE__ */ jsx18("button", { type: "button", onClick: () => setAdding(true), className: "elvix-btn elvix-btn-primary", style: { marginTop: 12 }, children: "Add address" }),
|
|
1846
|
+
adding && /* @__PURE__ */ jsxs17("form", { onSubmit: add, className: "elvix-form", style: { marginTop: 12 }, children: [
|
|
1847
|
+
/* @__PURE__ */ jsx18("input", { value: form.label, onChange: (e) => setForm({ ...form, label: e.target.value }), placeholder: "Label", className: "elvix-input" }),
|
|
1848
|
+
/* @__PURE__ */ jsx18("input", { value: form.line1, onChange: (e) => setForm({ ...form, line1: e.target.value }), placeholder: "Street", required: true, className: "elvix-input" }),
|
|
1849
|
+
/* @__PURE__ */ jsx18("input", { value: form.postalCode, onChange: (e) => setForm({ ...form, postalCode: e.target.value }), placeholder: "Postal code", required: true, className: "elvix-input" }),
|
|
1850
|
+
/* @__PURE__ */ jsx18("input", { value: form.city, onChange: (e) => setForm({ ...form, city: e.target.value }), placeholder: "City", required: true, className: "elvix-input" }),
|
|
1851
|
+
/* @__PURE__ */ jsx18("input", { value: form.country, onChange: (e) => setForm({ ...form, country: e.target.value.toUpperCase() }), placeholder: "Country (ISO-2)", maxLength: 2, required: true, className: "elvix-input" }),
|
|
1852
|
+
/* @__PURE__ */ jsx18("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" })
|
|
1346
1853
|
] })
|
|
1347
1854
|
] });
|
|
1348
1855
|
}
|
|
1349
1856
|
|
|
1350
1857
|
// src/react/elvix-legal-entities.tsx
|
|
1351
|
-
import { useEffect as useEffect6, useState as
|
|
1352
|
-
import { jsx as
|
|
1858
|
+
import { useEffect as useEffect6, useState as useState17 } from "react";
|
|
1859
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1353
1860
|
function ElvixLegalEntities({
|
|
1354
|
-
onResult
|
|
1861
|
+
onResult,
|
|
1862
|
+
width,
|
|
1863
|
+
height,
|
|
1864
|
+
minWidth,
|
|
1865
|
+
maxWidth,
|
|
1866
|
+
minHeight,
|
|
1867
|
+
maxHeight
|
|
1355
1868
|
}) {
|
|
1869
|
+
const sizeProps = { width, height, minWidth, maxWidth, minHeight, maxHeight };
|
|
1356
1870
|
const ctx = useElvixContext();
|
|
1357
|
-
const [rows, setRows] =
|
|
1358
|
-
const [error, setError] =
|
|
1359
|
-
const [busy, setBusy] =
|
|
1360
|
-
const [adding, setAdding] =
|
|
1361
|
-
const [form, setForm] =
|
|
1871
|
+
const [rows, setRows] = useState17(null);
|
|
1872
|
+
const [error, setError] = useState17(null);
|
|
1873
|
+
const [busy, setBusy] = useState17(false);
|
|
1874
|
+
const [adding, setAdding] = useState17(false);
|
|
1875
|
+
const [form, setForm] = useState17({
|
|
1362
1876
|
legalName: "",
|
|
1363
1877
|
taxId: "",
|
|
1364
1878
|
country: ""
|
|
@@ -1405,27 +1919,27 @@ function ElvixLegalEntities({
|
|
|
1405
1919
|
if (result.ok) setRows((prev) => prev?.filter((a) => a.id !== id) ?? null);
|
|
1406
1920
|
onResult?.(result);
|
|
1407
1921
|
}
|
|
1408
|
-
return /* @__PURE__ */
|
|
1409
|
-
error && /* @__PURE__ */
|
|
1410
|
-
!rows && !error && /* @__PURE__ */
|
|
1411
|
-
rows && rows.length === 0 && /* @__PURE__ */
|
|
1412
|
-
rows?.map((e) => /* @__PURE__ */
|
|
1413
|
-
/* @__PURE__ */
|
|
1414
|
-
/* @__PURE__ */
|
|
1415
|
-
/* @__PURE__ */
|
|
1922
|
+
return /* @__PURE__ */ jsxs18(ElvixCard, { title: "Legal entities", ...sizeProps, children: [
|
|
1923
|
+
error && /* @__PURE__ */ jsx19("p", { role: "alert", className: "elvix-error", children: error }),
|
|
1924
|
+
!rows && !error && /* @__PURE__ */ jsx19("p", { children: "Loading\u2026" }),
|
|
1925
|
+
rows && rows.length === 0 && /* @__PURE__ */ jsx19("p", { className: "elvix-muted", children: "No legal entities yet." }),
|
|
1926
|
+
rows?.map((e) => /* @__PURE__ */ jsxs18("div", { style: { padding: "8px 0", borderBottom: "1px solid rgba(0,0,0,0.06)", display: "flex", justifyContent: "space-between", gap: 12 }, children: [
|
|
1927
|
+
/* @__PURE__ */ jsxs18("div", { style: { fontSize: 13 }, children: [
|
|
1928
|
+
/* @__PURE__ */ jsx19("div", { style: { fontWeight: 500 }, children: e.legalName }),
|
|
1929
|
+
/* @__PURE__ */ jsxs18("div", { style: { color: "rgba(0,0,0,0.55)" }, children: [
|
|
1416
1930
|
e.taxId,
|
|
1417
1931
|
" \xB7 ",
|
|
1418
1932
|
e.country
|
|
1419
1933
|
] })
|
|
1420
1934
|
] }),
|
|
1421
|
-
/* @__PURE__ */
|
|
1935
|
+
/* @__PURE__ */ jsx19("button", { type: "button", disabled: busy, onClick: () => remove(e.id), className: "elvix-btn elvix-btn-ghost", children: "Remove" })
|
|
1422
1936
|
] }, e.id)),
|
|
1423
|
-
!adding && /* @__PURE__ */
|
|
1424
|
-
adding && /* @__PURE__ */
|
|
1425
|
-
/* @__PURE__ */
|
|
1426
|
-
/* @__PURE__ */
|
|
1427
|
-
/* @__PURE__ */
|
|
1428
|
-
/* @__PURE__ */
|
|
1937
|
+
!adding && /* @__PURE__ */ jsx19("button", { type: "button", onClick: () => setAdding(true), className: "elvix-btn elvix-btn-primary", style: { marginTop: 12 }, children: "Add entity" }),
|
|
1938
|
+
adding && /* @__PURE__ */ jsxs18("form", { onSubmit: add, className: "elvix-form", style: { marginTop: 12 }, children: [
|
|
1939
|
+
/* @__PURE__ */ jsx19("input", { value: form.legalName, onChange: (e) => setForm({ ...form, legalName: e.target.value }), placeholder: "Legal name", required: true, className: "elvix-input" }),
|
|
1940
|
+
/* @__PURE__ */ jsx19("input", { value: form.taxId, onChange: (e) => setForm({ ...form, taxId: e.target.value }), placeholder: "Tax / VAT ID", required: true, className: "elvix-input" }),
|
|
1941
|
+
/* @__PURE__ */ jsx19("input", { value: form.country, onChange: (e) => setForm({ ...form, country: e.target.value.toUpperCase() }), placeholder: "Country (ISO-2)", maxLength: 2, required: true, className: "elvix-input" }),
|
|
1942
|
+
/* @__PURE__ */ jsx19("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" })
|
|
1429
1943
|
] })
|
|
1430
1944
|
] });
|
|
1431
1945
|
}
|
|
@@ -1448,6 +1962,7 @@ export {
|
|
|
1448
1962
|
ElvixSessions,
|
|
1449
1963
|
ElvixSignIn,
|
|
1450
1964
|
ElvixSignInButton,
|
|
1965
|
+
ElvixSignInForm,
|
|
1451
1966
|
ElvixUsername,
|
|
1452
1967
|
getElvixToken,
|
|
1453
1968
|
setElvixToken,
|