@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.
Files changed (3) hide show
  1. package/dist/react.d.ts +90 -34
  2. package/dist/react.js +798 -283
  3. 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
- children
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-button.tsx
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-sign-in-button.tsx
425
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
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 = ELVIX_URL,
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 [embedOpen, setEmbedOpen] = useState3(false);
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__ */ jsxs4(Fragment2, { children: [
504
- /* @__PURE__ */ jsx5(ElvixShield, { size: ICON_SIZE[size], fill: shieldColor(variant, theme), accent: "#8e7dff" }),
505
- isIcon ? null : /* @__PURE__ */ jsx5("span", { children: resolvedLabel })
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__ */ jsx5("button", { type: "button", onClick, className, style, "aria-label": isIcon ? resolvedLabel : void 0, children: content });
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__ */ jsxs4("div", { "data-elvix-signin-button-embed": "", children: [
512
- !embedOpen && /* @__PURE__ */ jsx5(
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__ */ jsx5(
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__ */ jsx5("a", { href: destination, className, style, "aria-label": isIcon ? resolvedLabel : void 0, children: content });
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 useState4 } from "react";
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] = useState4([]);
618
- const [loading, setLoading] = useState4(true);
619
- const [error, setError] = useState4(null);
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 useState5 } from "react";
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 jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
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] = useState5("");
750
- const [busy, setBusy] = useState5(false);
751
- const [error, setError] = useState5(null);
752
- const [done, setDone] = useState5(null);
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__ */ jsx7(ElvixCard, { title: "Username saved", children: /* @__PURE__ */ jsxs6("p", { children: [
1209
+ return /* @__PURE__ */ jsx8(ElvixCard, { title: "Username saved", ...sizeProps, children: /* @__PURE__ */ jsxs7("p", { children: [
773
1210
  "You are now ",
774
- /* @__PURE__ */ jsxs6("strong", { children: [
1211
+ /* @__PURE__ */ jsxs7("strong", { children: [
775
1212
  "@",
776
1213
  done
777
1214
  ] }),
778
1215
  "."
779
1216
  ] }) });
780
1217
  }
781
- return /* @__PURE__ */ jsx7(ElvixCard, { title: "Choose a username", children: /* @__PURE__ */ jsxs6("form", { onSubmit: submit, className: "elvix-form", children: [
782
- /* @__PURE__ */ jsx7(
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__ */ jsx7("button", { type: "submit", disabled: busy || value.length < 4, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Claim" }),
796
- error && /* @__PURE__ */ jsx7("p", { role: "alert", className: "elvix-error", children: error })
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 useState6 } from "react";
802
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
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] = useState6(false);
808
- const [error, setError] = useState6(null);
809
- const [preview, setPreview] = useState6(null);
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__ */ jsxs7(ElvixCard, { title: "Avatar", children: [
833
- preview && /* @__PURE__ */ jsx8(
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__ */ jsx8("input", { type: "file", accept: "image/png,image/jpeg,image/webp", onChange: onFile, disabled: busy }),
842
- busy && /* @__PURE__ */ jsx8("p", { children: "Uploading\u2026" }),
843
- error && /* @__PURE__ */ jsx8("p", { role: "alert", className: "elvix-error", children: error })
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 useState7 } from "react";
849
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
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] = useState7(false);
855
- const [error, setError] = useState7(null);
856
- const [preview, setPreview] = useState7(null);
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__ */ jsxs8(ElvixCard, { title: "Banner", children: [
880
- preview && /* @__PURE__ */ jsx9(
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__ */ jsx9("input", { type: "file", accept: "image/png,image/jpeg,image/webp", onChange: onFile, disabled: busy }),
889
- busy && /* @__PURE__ */ jsx9("p", { children: "Uploading\u2026" }),
890
- error && /* @__PURE__ */ jsx9("p", { role: "alert", className: "elvix-error", children: error })
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 useState8 } from "react";
896
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
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] = useState8(initialName);
904
- const [bio, setBio] = useState8(initialBio);
905
- const [busy, setBusy] = useState8(false);
906
- const [error, setError] = useState8(null);
907
- const [saved, setSaved] = useState8(false);
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__ */ jsx10(ElvixCard, { title: "Identity", children: /* @__PURE__ */ jsxs9("form", { onSubmit: submit, className: "elvix-form", children: [
924
- /* @__PURE__ */ jsxs9("label", { children: [
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__ */ jsx10("input", { value: name, onChange: (e) => setName(e.target.value), maxLength: 80, disabled: busy, className: "elvix-input" })
1384
+ /* @__PURE__ */ jsx11("input", { value: name, onChange: (e) => setName(e.target.value), maxLength: 80, disabled: busy, className: "elvix-input" })
927
1385
  ] }),
928
- /* @__PURE__ */ jsxs9("label", { children: [
1386
+ /* @__PURE__ */ jsxs10("label", { children: [
929
1387
  "Bio",
930
- /* @__PURE__ */ jsx10("textarea", { value: bio, onChange: (e) => setBio(e.target.value), maxLength: 500, rows: 3, disabled: busy, className: "elvix-input" })
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__ */ jsx10("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" }),
933
- saved && /* @__PURE__ */ jsx10("p", { className: "elvix-muted", children: "Saved." }),
934
- error && /* @__PURE__ */ jsx10("p", { role: "alert", className: "elvix-error", children: error })
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 useState9 } from "react";
940
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
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] = useState9(initialCountry);
948
- const [timezone, setTimezone] = useState9(initialTimezone);
949
- const [busy, setBusy] = useState9(false);
950
- const [error, setError] = useState9(null);
951
- const [saved, setSaved] = useState9(false);
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__ */ jsx11(ElvixCard, { title: "Region", children: /* @__PURE__ */ jsxs10("form", { onSubmit: submit, className: "elvix-form", children: [
968
- /* @__PURE__ */ jsxs10("label", { children: [
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__ */ jsx11("input", { value: country, onChange: (e) => setCountry(e.target.value.toUpperCase()), maxLength: 2, pattern: "[A-Z]{2}", disabled: busy, className: "elvix-input" })
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__ */ jsxs10("label", { children: [
1437
+ /* @__PURE__ */ jsxs11("label", { children: [
973
1438
  "Timezone",
974
- /* @__PURE__ */ jsx11("input", { value: timezone, onChange: (e) => setTimezone(e.target.value), placeholder: "Europe/Berlin", disabled: busy, className: "elvix-input" })
1439
+ /* @__PURE__ */ jsx12("input", { value: timezone, onChange: (e) => setTimezone(e.target.value), placeholder: "Europe/Berlin", disabled: busy, className: "elvix-input" })
975
1440
  ] }),
976
- /* @__PURE__ */ jsx11("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" }),
977
- saved && /* @__PURE__ */ jsx11("p", { className: "elvix-muted", children: "Saved." }),
978
- error && /* @__PURE__ */ jsx11("p", { role: "alert", className: "elvix-error", children: error })
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 useState10 } from "react";
984
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
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] = useState10(initial.join(", "));
991
- const [busy, setBusy] = useState10(false);
992
- const [error, setError] = useState10(null);
993
- const [saved, setSaved] = useState10(false);
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__ */ jsx12(ElvixCard, { title: "Languages", children: /* @__PURE__ */ jsxs11("form", { onSubmit: submit, className: "elvix-form", children: [
1011
- /* @__PURE__ */ jsxs11("label", { children: [
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__ */ jsx12("input", { value: raw, onChange: (e) => setRaw(e.target.value), placeholder: "en-GB, de-DE", disabled: busy, className: "elvix-input" })
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__ */ jsx12("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" }),
1016
- saved && /* @__PURE__ */ jsx12("p", { className: "elvix-muted", children: "Saved." }),
1017
- error && /* @__PURE__ */ jsx12("p", { role: "alert", className: "elvix-error", children: error })
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 useState11 } from "react";
1023
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
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] = useState11(null);
1029
- const [error, setError] = useState11(null);
1030
- const [busy, setBusy] = useState11(false);
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__ */ jsxs12(ElvixCard, { title: "Active sessions", children: [
1052
- error && /* @__PURE__ */ jsx13("p", { role: "alert", className: "elvix-error", children: error }),
1053
- !rows && !error && /* @__PURE__ */ jsx13("p", { children: "Loading\u2026" }),
1054
- rows && /* @__PURE__ */ jsx13("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: rows.map((s) => /* @__PURE__ */ jsx13("li", { style: { padding: "10px 0", borderBottom: "1px solid rgba(0,0,0,0.06)" }, children: /* @__PURE__ */ jsxs12("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [
1055
- /* @__PURE__ */ jsxs12("div", { children: [
1056
- /* @__PURE__ */ jsxs12("div", { style: { fontSize: 13, fontWeight: 500 }, children: [
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__ */ jsx13("span", { style: { marginLeft: 8, color: "var(--elvix-primary-strong)", fontSize: 11 }, children: "\xB7 this device" })
1537
+ s.current && /* @__PURE__ */ jsx14("span", { style: { marginLeft: 8, color: "var(--elvix-primary-strong)", fontSize: 11 }, children: "\xB7 this device" })
1059
1538
  ] }),
1060
- /* @__PURE__ */ jsxs12("div", { style: { fontSize: 11, color: "rgba(0,0,0,0.55)" }, children: [
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__ */ jsx13("button", { type: "button", disabled: busy, onClick: () => revoke(s.id), className: "elvix-btn elvix-btn-ghost", children: "Revoke" })
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 useState12 } from "react";
1073
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
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] = useState12(false);
1079
- const [done, setDone] = useState12(false);
1080
- const [error, setError] = useState12(null);
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__ */ jsxs13(ElvixCard, { title: "Export my data", children: [
1096
- /* @__PURE__ */ jsx14("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." }),
1097
- done ? /* @__PURE__ */ jsx14("p", { className: "elvix-muted", children: "Request queued. Check your email." }) : /* @__PURE__ */ jsx14("button", { type: "button", onClick: start, disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Queuing\u2026" : "Request export" }),
1098
- error && /* @__PURE__ */ jsx14("p", { role: "alert", className: "elvix-error", children: error })
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 useState13 } from "react";
1104
- import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
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] = useState13("warn");
1110
- const [challengeId, setChallengeId] = useState13(null);
1111
- const [code, setCode] = useState13("");
1112
- const [busy, setBusy] = useState13(false);
1113
- const [error, setError] = useState13(null);
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__ */ jsx15(ElvixCard, { title: "Deactivated", children: /* @__PURE__ */ jsx15("p", { children: "Your access has been paused. Sign in again to restore it." }) });
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__ */ jsxs14(ElvixCard, { title: "Deactivate account", children: [
1154
- pane === "warn" && /* @__PURE__ */ jsxs14(Fragment3, { children: [
1155
- /* @__PURE__ */ jsx15("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." }),
1156
- /* @__PURE__ */ jsx15("button", { type: "button", onClick: startChallenge, disabled: busy, className: "elvix-btn elvix-btn-danger", children: busy ? "Sending\u2026" : "Send code" })
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__ */ jsxs14("form", { onSubmit: confirm, className: "elvix-form", children: [
1159
- /* @__PURE__ */ jsx15("p", { className: "elvix-muted", children: "We sent a 6-digit code to your email." }),
1160
- /* @__PURE__ */ jsx15(
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__ */ jsx15("button", { type: "submit", disabled: busy || code.length !== 6, className: "elvix-btn elvix-btn-danger", children: busy ? "Deactivating\u2026" : "Confirm" })
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__ */ jsx15("p", { role: "alert", className: "elvix-error", children: error })
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 useState14 } from "react";
1182
- import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
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] = useState14("warn");
1188
- const [challengeId, setChallengeId] = useState14(null);
1189
- const [code, setCode] = useState14("");
1190
- const [busy, setBusy] = useState14(false);
1191
- const [error, setError] = useState14(null);
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__ */ jsx16(ElvixCard, { title: "You've left", children: /* @__PURE__ */ jsx16("p", { children: "You've left this app. Your data is archived; sign in again to rejoin." }) });
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__ */ jsxs15(ElvixCard, { title: "Leave this app", children: [
1232
- pane === "warn" && /* @__PURE__ */ jsxs15(Fragment4, { children: [
1233
- /* @__PURE__ */ jsx16("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." }),
1234
- /* @__PURE__ */ jsx16("button", { type: "button", onClick: startChallenge, disabled: busy, className: "elvix-btn elvix-btn-danger", children: busy ? "Sending\u2026" : "Send code" })
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__ */ jsxs15("form", { onSubmit: confirm, className: "elvix-form", children: [
1237
- /* @__PURE__ */ jsx16("p", { className: "elvix-muted", children: "We sent a 6-digit code to your email." }),
1238
- /* @__PURE__ */ jsx16(
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__ */ jsx16("button", { type: "submit", disabled: busy || code.length !== 6, className: "elvix-btn elvix-btn-danger", children: busy ? "Leaving\u2026" : "Confirm leave" })
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__ */ jsx16("p", { role: "alert", className: "elvix-error", children: error })
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 useState15 } from "react";
1260
- import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
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] = useState15(null);
1266
- const [error, setError] = useState15(null);
1267
- const [busy, setBusy] = useState15(false);
1268
- const [adding, setAdding] = useState15(false);
1269
- const [form, setForm] = useState15({
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__ */ jsxs16(ElvixCard, { title: "Addresses", children: [
1319
- error && /* @__PURE__ */ jsx17("p", { role: "alert", className: "elvix-error", children: error }),
1320
- !rows && !error && /* @__PURE__ */ jsx17("p", { children: "Loading\u2026" }),
1321
- rows && rows.length === 0 && /* @__PURE__ */ jsx17("p", { className: "elvix-muted", children: "No addresses yet." }),
1322
- rows?.map((a) => /* @__PURE__ */ jsxs16("div", { style: { padding: "8px 0", borderBottom: "1px solid rgba(0,0,0,0.06)", display: "flex", justifyContent: "space-between", gap: 12 }, children: [
1323
- /* @__PURE__ */ jsxs16("div", { style: { fontSize: 13 }, children: [
1324
- /* @__PURE__ */ jsx17("div", { style: { fontWeight: 500 }, children: a.label }),
1325
- /* @__PURE__ */ jsxs16("div", { style: { color: "rgba(0,0,0,0.55)" }, children: [
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__ */ jsx17("button", { type: "button", disabled: busy, onClick: () => remove(a.id), className: "elvix-btn elvix-btn-ghost", children: "Remove" })
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__ */ jsx17("button", { type: "button", onClick: () => setAdding(true), className: "elvix-btn elvix-btn-primary", style: { marginTop: 12 }, children: "Add address" }),
1339
- adding && /* @__PURE__ */ jsxs16("form", { onSubmit: add, className: "elvix-form", style: { marginTop: 12 }, children: [
1340
- /* @__PURE__ */ jsx17("input", { value: form.label, onChange: (e) => setForm({ ...form, label: e.target.value }), placeholder: "Label", className: "elvix-input" }),
1341
- /* @__PURE__ */ jsx17("input", { value: form.line1, onChange: (e) => setForm({ ...form, line1: e.target.value }), placeholder: "Street", required: true, className: "elvix-input" }),
1342
- /* @__PURE__ */ jsx17("input", { value: form.postalCode, onChange: (e) => setForm({ ...form, postalCode: e.target.value }), placeholder: "Postal code", required: true, className: "elvix-input" }),
1343
- /* @__PURE__ */ jsx17("input", { value: form.city, onChange: (e) => setForm({ ...form, city: e.target.value }), placeholder: "City", required: true, className: "elvix-input" }),
1344
- /* @__PURE__ */ jsx17("input", { value: form.country, onChange: (e) => setForm({ ...form, country: e.target.value.toUpperCase() }), placeholder: "Country (ISO-2)", maxLength: 2, required: true, className: "elvix-input" }),
1345
- /* @__PURE__ */ jsx17("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" })
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 useState16 } from "react";
1352
- import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
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] = useState16(null);
1358
- const [error, setError] = useState16(null);
1359
- const [busy, setBusy] = useState16(false);
1360
- const [adding, setAdding] = useState16(false);
1361
- const [form, setForm] = useState16({
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__ */ jsxs17(ElvixCard, { title: "Legal entities", children: [
1409
- error && /* @__PURE__ */ jsx18("p", { role: "alert", className: "elvix-error", children: error }),
1410
- !rows && !error && /* @__PURE__ */ jsx18("p", { children: "Loading\u2026" }),
1411
- rows && rows.length === 0 && /* @__PURE__ */ jsx18("p", { className: "elvix-muted", children: "No legal entities yet." }),
1412
- rows?.map((e) => /* @__PURE__ */ jsxs17("div", { style: { padding: "8px 0", borderBottom: "1px solid rgba(0,0,0,0.06)", display: "flex", justifyContent: "space-between", gap: 12 }, children: [
1413
- /* @__PURE__ */ jsxs17("div", { style: { fontSize: 13 }, children: [
1414
- /* @__PURE__ */ jsx18("div", { style: { fontWeight: 500 }, children: e.legalName }),
1415
- /* @__PURE__ */ jsxs17("div", { style: { color: "rgba(0,0,0,0.55)" }, children: [
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__ */ jsx18("button", { type: "button", disabled: busy, onClick: () => remove(e.id), className: "elvix-btn elvix-btn-ghost", children: "Remove" })
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__ */ jsx18("button", { type: "button", onClick: () => setAdding(true), className: "elvix-btn elvix-btn-primary", style: { marginTop: 12 }, children: "Add entity" }),
1424
- adding && /* @__PURE__ */ jsxs17("form", { onSubmit: add, className: "elvix-form", style: { marginTop: 12 }, children: [
1425
- /* @__PURE__ */ jsx18("input", { value: form.legalName, onChange: (e) => setForm({ ...form, legalName: e.target.value }), placeholder: "Legal name", required: true, className: "elvix-input" }),
1426
- /* @__PURE__ */ jsx18("input", { value: form.taxId, onChange: (e) => setForm({ ...form, taxId: e.target.value }), placeholder: "Tax / VAT ID", required: true, className: "elvix-input" }),
1427
- /* @__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" }),
1428
- /* @__PURE__ */ jsx18("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? "Saving\u2026" : "Save" })
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,