@elvix.is/sdk 0.5.7 → 0.5.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode, CSSProperties } from 'react';
3
- import { ElvixActionResult } from './index.js';
4
- export { ElvixUser, ElvixVerifyResult } from './index.js';
3
+ import { z } from 'zod';
4
+ export { ElvixActionResult, ElvixUser, ElvixVerifyResult } from './index.js';
5
5
 
6
6
  /** Size overrides every <Elvix*> component accepts so hosts can fit it to any slot. */
7
7
  type ElvixSizeProps = {
@@ -184,14 +184,49 @@ type ElvixSignInResult$1 = ElvixSignInResultOk | ElvixSignInResultErr;
184
184
  /** Theme override. Omit to inherit the Console-configured pair. */
185
185
  type ElvixTheme = "light" | "dark" | "system";
186
186
 
187
+ /**
188
+ * Per-app user envelope returned by
189
+ * `GET /api/account/apps/<clientId>/sdk-context`. The provider fetches it on
190
+ * mount alongside the public bootstrap whenever a session is present (cookie
191
+ * same-origin, bearer cross-origin). Mirrors the monorepo `ElvixAppContext`
192
+ * shape exactly so the ported `<Elvix*>` identity / account components read
193
+ * `useElvixAppContext()` and skip the `appId` / `appName` / `current` /
194
+ * `membership` props a host would otherwise thread down. `null` while loading,
195
+ * with no `clientId`, or when there's no user session (the SDK falls back to
196
+ * its empty / "sign in to see this" state).
197
+ */
198
+ type ElvixAppContext = {
199
+ user: {
200
+ id: string;
201
+ name: string | null;
202
+ email: string | null;
203
+ avatarUrl: string | null;
204
+ };
205
+ membership: {
206
+ username: string | null;
207
+ status: string;
208
+ inactiveAt: string | null;
209
+ inactivatedBy: string | null;
210
+ deletedAt: string | null;
211
+ deletedBy: string | null;
212
+ avatarSizes: number[];
213
+ avatarUpdatedAt: string;
214
+ bannerSizes: number[];
215
+ bannerUpdatedAt: string;
216
+ } | null;
217
+ };
187
218
  type ElvixContextValue = {
188
219
  clientId: string | undefined;
189
220
  baseUrl: string;
190
221
  app: ElvixBootstrapEnvelope | null;
191
222
  appError: string | null;
223
+ appContext: ElvixAppContext | null;
192
224
  resolvedTheme: "light" | "dark";
193
225
  };
194
226
  declare function useElvixApp(): ElvixBootstrapEnvelope | null;
227
+ /** Per-app signed-in user envelope (session-bound). `null` while loading,
228
+ * with no clientId, or when there's no user session. */
229
+ declare function useElvixAppContext(): ElvixAppContext | null;
195
230
  declare function useElvixContext(): ElvixContextValue;
196
231
  declare function ElvixProvider({ clientId, theme, brand, baseUrl, children, className, }: {
197
232
  clientId?: string;
@@ -397,6 +432,27 @@ type AuthFormProps = {
397
432
  redirect?: string;
398
433
  token?: string;
399
434
  }) => void;
435
+ /**
436
+ * Where to send the user after EVERY terminal success path. One prop, one
437
+ * destination — no per-method customisation. Applies uniformly to:
438
+ *
439
+ * - OTP verify success (with or without an onboarding step).
440
+ * - Google sign-in (both the GIS credential and the redirect-OAuth
441
+ * return path that consumes `#elvix_token=...` on mount).
442
+ * - Passkey sign-in.
443
+ * - The onboarding "Add a passkey" success.
444
+ * - The onboarding "Skip for now" button on the passkey step.
445
+ * - The onboarding username step success.
446
+ *
447
+ * Resolution order at the moment of navigation:
448
+ * `redirectAfterSignIn ?? <backend-provided redirect> ?? "/"`
449
+ *
450
+ * If a host wants different destinations per method, they should switch
451
+ * on the result inside `onResult`/`onAuthenticated` and call
452
+ * `router.push(...)` themselves; this prop is the single declarative
453
+ * fallback that ALL success paths honour.
454
+ */
455
+ redirectAfterSignIn?: string;
400
456
  /**
401
457
  * Fires on every terminal outcome: success AND every error path
402
458
  * (invalid OTP, expired challenge, rate-limited, network blip,
@@ -472,6 +528,18 @@ declare function ElvixSecuredBadge({ variant, size, theme, accentColor, href, cl
472
528
  declare function getElvixToken(): string | null;
473
529
  /** Store (or clear with null) the session token. Persists to localStorage. */
474
530
  declare function setElvixToken(token: string | null): void;
531
+ /**
532
+ * On the host page, pick up a session token handed back by elvix's Google
533
+ * redirect-callback in the URL fragment, store it, and strip it from the URL
534
+ * so a refresh/back-nav doesn't replay it (and it never leaks into history,
535
+ * referrers, or analytics). Returns the token it consumed, or null.
536
+ *
537
+ * Idempotent and SSR-safe: a no-op (returns null) when there's no `window` or
538
+ * no `#elvix_token=` present. `<ElvixProvider>` calls this automatically on
539
+ * mount; hosts that don't mount the provider at the redirect target can call
540
+ * it directly (it's exported from `@elvix.is/sdk/react`).
541
+ */
542
+ declare function consumeElvixReturnToken(): string | null;
475
543
 
476
544
  type UseUserListResult = {
477
545
  slugs: string[];
@@ -491,125 +559,516 @@ declare const useUserRoles: (opts: Opts) => UseUserListResult;
491
559
  declare const useUserScopes: (opts: Opts) => UseUserListResult;
492
560
  declare const useUserMemberships: (opts: Opts) => UseUserListResult;
493
561
 
494
- declare function ElvixLifecycleWatcher({ baseUrl, pollMs, onSignedOut, }: {
562
+ type ElvixLifecycleWatcherProps = {
495
563
  /** elvix origin. Defaults to "" (same-origin). */
496
564
  baseUrl?: string;
497
- /** Poll interval in ms. Default 7000. */
565
+ /** Poll interval in ms when SSE isn't available. Default 7000. */
498
566
  pollMs?: number;
567
+ /**
568
+ * Application id to subscribe to (SSE mode). When set together with
569
+ * `userId` AND we're same-origin with `baseUrl`, the watcher opens an
570
+ * EventSource on `/api/presence/stream` and skips polling entirely.
571
+ * Omit to force the polling path (the cross-origin SDK case).
572
+ */
573
+ applicationId?: string;
574
+ /** User id to watch — SSE filters by this. Required with `applicationId`. */
575
+ userId?: string;
499
576
  /** Called once with the reason when the session ends. Defaults to a reload. */
500
577
  onSignedOut?: (reason: string) => void;
501
- }): null;
578
+ };
579
+ declare function ElvixLifecycleWatcher({ baseUrl, pollMs, applicationId, userId, onSignedOut, }: ElvixLifecycleWatcherProps): null;
502
580
 
503
- /**
504
- * `<ElvixUsername>` — claim or change the end-user's username for the
505
- * current Application. PATCH /api/account/apps/<appId>/username.
506
- * Render a single in-frame card with two panes: edit + done.
507
- */
508
- declare function ElvixUsername({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
509
- onResult?: (r: ElvixActionResult<{
510
- username: string;
511
- }>) => void;
512
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
581
+ type ElvixUsernameResult = {
582
+ ok: true;
583
+ username: string;
584
+ } | {
585
+ ok: false;
586
+ error: string;
587
+ message?: string;
588
+ };
589
+ declare function ElvixUsername(props: ElvixUsernameProps): react_jsx_runtime.JSX.Element;
590
+ type ElvixUsernameProps = {
591
+ appId?: string;
592
+ appName?: string;
593
+ current?: string | null;
594
+ methodUsername?: boolean;
595
+ supportUrl?: string | null;
596
+ supportEmail?: string | null;
597
+ onSuccess?: (value: string) => void;
598
+ onFail?: (error: string) => void;
599
+ onResult?: (result: ElvixUsernameResult) => void;
600
+ };
513
601
 
514
- /**
515
- * `<ElvixAvatar>` — upload / replace the end-user's avatar for this
516
- * Application. Reads file → base64 → PATCH /api/account/apps/<appId>/avatar.
517
- */
518
- declare function ElvixAvatar({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
519
- onResult?: (r: ElvixActionResult<{
520
- avatarUrl: string;
521
- }>) => void;
522
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
602
+ declare const Shape: {
603
+ readonly CIRCLE: "circle";
604
+ readonly SQUARE: "square";
605
+ };
606
+ type Shape = (typeof Shape)[keyof typeof Shape];
607
+ type UserAvatarProps = {
608
+ /** App slug — Application.urlSlug. */
609
+ appSlug: string;
610
+ userId: string;
611
+ membership: {
612
+ avatarUpdatedAt: Date | number;
613
+ avatarSizes: number[];
614
+ };
615
+ user: {
616
+ name?: string | null;
617
+ email?: string | null;
618
+ avatarUrl?: string | null;
619
+ };
620
+ /** Pixel display size (1× CSS px). srcset handles retina automatically. */
621
+ size?: number;
622
+ className?: string;
623
+ /** Round vs square. Default rounded-full. */
624
+ shape?: Shape;
625
+ };
523
626
 
524
- /**
525
- * `<ElvixBanner>` — upload / replace the end-user's profile banner
526
- * (16:9 cover image) for this Application.
527
- */
528
- declare function ElvixBanner({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
529
- onResult?: (r: ElvixActionResult<{
530
- bannerUrl: string;
531
- }>) => void;
532
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
627
+ type ElvixAvatarResult = {
628
+ ok: true;
629
+ sizes: number[];
630
+ updatedAt: string;
631
+ } | {
632
+ ok: false;
633
+ error: string;
634
+ message?: string;
635
+ };
636
+ type ElvixAvatarProps = Omit<UserAvatarProps, "size"> & {
637
+ applicationId: string;
638
+ /** Diameter (px). Default 128. The widget stays at this size in
639
+ * every state — no expand-on-edit. */
640
+ size?: number;
641
+ /** Fired after a successful upload / remove. */
642
+ onChange?: (next: {
643
+ sizes: number[];
644
+ updatedAt: Date | number;
645
+ }) => void;
646
+ /** Fires on every terminal upload / remove outcome. Safe payload:
647
+ * rendered avatar sizes + updatedAt only (no image bytes). */
648
+ onResult?: (result: ElvixAvatarResult) => void;
649
+ };
650
+ declare function ElvixAvatar(props: Partial<ElvixAvatarProps>): react_jsx_runtime.JSX.Element;
533
651
 
534
- /**
535
- * `<ElvixIdentityForm>` — edit the end-user's display name + bio for
536
- * the current Application. Lightweight per-app profile fields.
537
- */
538
- declare function ElvixIdentityForm({ initialName, initialBio, onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
539
- initialName?: string;
540
- initialBio?: string;
541
- onResult?: (r: ElvixActionResult<{
542
- name: string;
543
- bio: string;
544
- }>) => void;
545
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
652
+ type UserBannerProps = {
653
+ appSlug: string;
654
+ userId: string;
655
+ membership: {
656
+ bannerUpdatedAt: Date | number;
657
+ bannerSizes: number[];
658
+ };
659
+ /** Container max-width in CSS px. Drives `sizes` for srcset. */
660
+ containerPx?: number;
661
+ className?: string;
662
+ /** Class for the empty placeholder background (gradient by default). */
663
+ emptyClassName?: string;
664
+ };
546
665
 
547
- /**
548
- * `<ElvixRegion>` — set the end-user's region (ISO 3166-1 alpha-2
549
- * country code + timezone). Used by elvix for data-residency hints
550
- * and locale defaults.
551
- */
552
- declare function ElvixRegion({ initialCountry, initialTimezone, onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
553
- initialCountry?: string;
554
- initialTimezone?: string;
555
- onResult?: (r: ElvixActionResult<{
556
- country: string;
557
- timezone: string;
558
- }>) => void;
559
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
666
+ type ElvixBannerResult = {
667
+ ok: true;
668
+ sizes: number[];
669
+ updatedAt: string;
670
+ } | {
671
+ ok: false;
672
+ error: string;
673
+ message?: string;
674
+ };
675
+ type ElvixBannerProps = UserBannerProps & {
676
+ applicationId: string;
677
+ /** Corner radius for the frame. Default 14 (matches the SDK card chrome). */
678
+ cornerRadius?: number;
679
+ /** Fired after a successful upload / remove. */
680
+ onChange?: (next: {
681
+ sizes: number[];
682
+ updatedAt: Date | number;
683
+ }) => void;
684
+ /** Fires on every terminal upload / remove outcome. Safe payload:
685
+ * rendered banner sizes + updatedAt only (no image bytes). */
686
+ onResult?: (result: ElvixBannerResult) => void;
687
+ };
688
+ declare function ElvixBanner(props: Partial<ElvixBannerProps>): react_jsx_runtime.JSX.Element;
560
689
 
561
- /**
562
- * `<ElvixLanguages>` — set the end-user's preferred languages (BCP-47
563
- * tag list, ordered by preference). The first entry drives UI locale.
564
- */
565
- declare function ElvixLanguages({ initial, onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
566
- initial?: string[];
567
- onResult?: (r: ElvixActionResult<{
568
- languages: string[];
569
- }>) => void;
570
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
690
+ declare const identitySchema: z.ZodObject<{
691
+ givenName: z.ZodString;
692
+ familyName: z.ZodString;
693
+ birthdate: z.ZodString;
694
+ gender: z.ZodEnum<{
695
+ male: "male";
696
+ female: "female";
697
+ non_binary: "non_binary";
698
+ prefer_not_to_say: "prefer_not_to_say";
699
+ }>;
700
+ pronouns: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
701
+ other: "other";
702
+ prefer_not_to_say: "prefer_not_to_say";
703
+ she_her: "she_her";
704
+ he_him: "he_him";
705
+ they_them: "they_them";
706
+ }>>>;
707
+ }, z.core.$strip>;
708
+ type IdentityInput = z.infer<typeof identitySchema>;
571
709
 
572
- declare function ElvixSessions({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
573
- onResult?: (r: ElvixActionResult<{
574
- revoked: number;
575
- }>) => void;
576
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
710
+ type ElvixIdentityFormResult = {
711
+ ok: true;
712
+ } | {
713
+ ok: false;
714
+ error: string;
715
+ message?: string;
716
+ };
717
+ declare function ElvixIdentityForm({ initial, onResult, }: {
718
+ /**
719
+ * Pre-loaded identity fields. Optional — when omitted, the SDK
720
+ * fetches `/api/account/profile/identity` on mount so the
721
+ * customer doesn't have to thread server-side state in.
722
+ */
723
+ initial?: Partial<IdentityInput>;
724
+ /** Fires on every terminal save outcome. Safe payload: no PII —
725
+ * identity edits are saved, not echoed back to the host. */
726
+ onResult?: (result: ElvixIdentityFormResult) => void;
727
+ }): react_jsx_runtime.JSX.Element;
577
728
 
578
- /**
579
- * `<ElvixExport>` — GDPR Art. 15 data-export request. Triggers an
580
- * async server-side zip + emails a single-use download link to the
581
- * end-user's bound email address.
582
- */
583
- declare function ElvixExport({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
584
- onResult?: (r: ElvixActionResult<{
585
- requestId: string;
586
- }>) => void;
587
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
729
+ type RegionRecord = {
730
+ id: string;
731
+ country: string;
732
+ uiLocale: string | null;
733
+ timeZone: string | null;
734
+ firstDayOfWeek: number;
735
+ timeFormat: string;
736
+ dateFormat: string;
737
+ numberFormat: string;
738
+ currency: string | null;
739
+ measurementSystem: string;
740
+ createdAt: string;
741
+ updatedAt: string;
742
+ };
588
743
 
589
- declare function ElvixDeactivate({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
590
- onResult?: (r: ElvixActionResult) => void;
591
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
744
+ type ElvixRegionResult = {
745
+ ok: true;
746
+ country: string;
747
+ locale: string;
748
+ } | {
749
+ ok: false;
750
+ error: string;
751
+ message?: string;
752
+ };
753
+ type ElvixRegionProps = {
754
+ height?: number;
755
+ minHeight?: number;
756
+ maxHeight?: number;
757
+ width?: number | string;
758
+ onChange?: (region: RegionRecord | null) => void;
759
+ /** Fires on every terminal save outcome. Safe payload: country +
760
+ * locale code only. `onChange` keeps firing too on every refresh. */
761
+ onResult?: (result: ElvixRegionResult) => void;
762
+ };
763
+ declare function ElvixRegion({ height, minHeight, maxHeight, width, onChange, onResult, }: ElvixRegionProps): react_jsx_runtime.JSX.Element;
592
764
 
593
- declare function ElvixLeave({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
594
- onResult?: (r: ElvixActionResult) => void;
595
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
765
+ declare const languageSchema: z.ZodObject<{
766
+ code: z.ZodString;
767
+ level: z.ZodEnum<{
768
+ ELEMENTARY: "ELEMENTARY";
769
+ INTERMEDIATE: "INTERMEDIATE";
770
+ PROFICIENT: "PROFICIENT";
771
+ NATIVE: "NATIVE";
772
+ }>;
773
+ }, z.core.$strip>;
774
+ type LanguageInput = z.infer<typeof languageSchema>;
775
+ type LanguageRecord = LanguageInput & {
776
+ id: string;
777
+ createdAt: string;
778
+ updatedAt: string;
779
+ };
780
+
781
+ type ElvixLanguagesResult = {
782
+ ok: true;
783
+ count: number;
784
+ } | {
785
+ ok: false;
786
+ error: string;
787
+ message?: string;
788
+ };
789
+ type ElvixLanguagesProps = {
790
+ height?: number;
791
+ minHeight?: number;
792
+ maxHeight?: number;
793
+ width?: number | string;
794
+ onChange?: (languages: LanguageRecord[]) => void;
795
+ /** Fires on every terminal save outcome. Safe payload: count only. */
796
+ onResult?: (result: ElvixLanguagesResult) => void;
797
+ };
798
+ declare function ElvixLanguages({ height, minHeight, maxHeight, width, onChange, onResult, }: ElvixLanguagesProps): react_jsx_runtime.JSX.Element;
799
+
800
+ declare const ElvixSessionsAction: {
801
+ readonly REVOKE_ONE: "revoke_one";
802
+ readonly SIGN_OUT_OTHERS: "sign_out_others";
803
+ readonly SIGN_OUT_ALL: "sign_out_all";
804
+ };
805
+ type ElvixSessionsAction = (typeof ElvixSessionsAction)[keyof typeof ElvixSessionsAction];
806
+ type ElvixSessionsResult = {
807
+ ok: true;
808
+ action: ElvixSessionsAction;
809
+ ended?: number;
810
+ } | {
811
+ ok: false;
812
+ error: string;
813
+ message?: string;
814
+ };
815
+ declare function ElvixSessions({ appId, signInUrl, onChanged, onResult, }: {
816
+ /** When set, scopes the list to one customer app. When undefined,
817
+ * lists `surface="account"` sessions. */
818
+ appId?: string;
819
+ /** Where to send the user after a "sign out everywhere too"
820
+ * action. Defaults to elvix's account sign-in. */
821
+ signInUrl?: string;
822
+ onChanged?: () => void;
823
+ /** Fires on every terminal revoke outcome. Safe payload: action
824
+ * kind + count of ended sessions. No session IDs leak to the host. */
825
+ onResult?: (result: ElvixSessionsResult) => void;
826
+ }): react_jsx_runtime.JSX.Element;
827
+
828
+ type ExportTarget = {
829
+ kind: "identity";
830
+ } | {
831
+ kind: "app";
832
+ appId: string;
833
+ appName: string;
834
+ };
835
+ type ElvixExportResult = {
836
+ ok: true;
837
+ downloadId: string;
838
+ deliveredTo: string;
839
+ } | {
840
+ ok: false;
841
+ error: string;
842
+ message?: string;
843
+ };
844
+ declare function ElvixExport({ target, primaryEmail, onSuccess, onFail, onResult, }: {
845
+ /** Scope: identity-level export, or per-app export. Defaults to
846
+ * identity — the most common surface. */
847
+ target?: ExportTarget;
848
+ /** Address the export zip is delivered to. Optional — when
849
+ * omitted, the SDK reads it from the signed-in user's session
850
+ * via `useElvixAppContext().user.email`. */
851
+ primaryEmail?: string;
852
+ onSuccess?: (downloadId: string) => void;
853
+ onFail?: (error: string) => void;
854
+ /** Fires on every terminal export outcome. Safe payload: the
855
+ * single-use downloadId (only redeemable with the OTP-verified
856
+ * session) + the email address the zip was sent to. */
857
+ onResult?: (result: ElvixExportResult) => void;
858
+ }): react_jsx_runtime.JSX.Element;
859
+
860
+ declare const State$1: {
861
+ readonly INACTIVE: "inactive";
862
+ readonly ACTIVE: "active";
863
+ };
864
+ type State$1 = (typeof State$1)[keyof typeof State$1];
865
+ type ElvixDeactivateResult = {
866
+ ok: true;
867
+ state: State$1;
868
+ } | {
869
+ ok: false;
870
+ error: string;
871
+ message?: string;
872
+ };
873
+ declare function ElvixDeactivate(props: {
874
+ appId?: string;
875
+ appName?: string;
876
+ inactive?: boolean;
877
+ inactivatedBy?: string | null;
878
+ onSuccess?: (state: State$1) => void;
879
+ onFail?: (error: string) => void;
880
+ onResult?: (result: ElvixDeactivateResult) => void;
881
+ }): react_jsx_runtime.JSX.Element;
882
+
883
+ declare const State: {
884
+ readonly LEFT: "left";
885
+ readonly RESTORED: "restored";
886
+ };
887
+ type State = (typeof State)[keyof typeof State];
888
+ type ElvixLeaveResult = {
889
+ ok: true;
890
+ state: State;
891
+ } | {
892
+ ok: false;
893
+ error: string;
894
+ message?: string;
895
+ };
896
+ declare function ElvixLeave(props: {
897
+ appId?: string;
898
+ appName?: string;
899
+ deletedAt?: string | null;
900
+ deletedBy?: string | null;
901
+ privacyPolicyUrl?: string | null;
902
+ termsOfServiceUrl?: string | null;
903
+ onSuccess?: (state: State) => void;
904
+ onFail?: (error: string) => void;
905
+ onResult?: (result: ElvixLeaveResult) => void;
906
+ }): react_jsx_runtime.JSX.Element;
596
907
 
597
908
  /**
598
- * `<ElvixAddressBook>` list / add / remove the end-user's addresses
599
- * on this Application. Read uses GET /api/account/apps/<appId>/addresses;
600
- * mutations POST + DELETE on the same path.
909
+ * Address schema for the elvix Profile SDK.
910
+ *
911
+ * Two flavours mirror the basic-info pattern:
912
+ *
913
+ * `addressSchema` — STRICT. SDK form enforces it client-side
914
+ * before submit.
915
+ * `addressPatchSchema` — LOOSE. Server-side accepts partial
916
+ * updates (single field PATCHs from admin
917
+ * tools, Google Places merges, etc.).
918
+ *
919
+ * Field shape mirrors DC EventAddress: country has both ISO code and
920
+ * human name; region has both code (ISO-3166-2) and name; coords are
921
+ * stored alongside Google Places provenance for shipping-zone /
922
+ * delivery-map use without re-geocoding.
601
923
  */
602
- declare function ElvixAddressBook({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
603
- onResult?: (r: ElvixActionResult) => void;
604
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
924
+ declare const ADDRESS_KINDS: readonly ["billing", "shipping"];
925
+ type AddressKind = (typeof ADDRESS_KINDS)[number];
926
+ declare const addressSchema: z.ZodObject<{
927
+ kind: z.ZodEnum<{
928
+ billing: "billing";
929
+ shipping: "shipping";
930
+ }>;
931
+ label: z.ZodNullable<z.ZodOptional<z.ZodString>>;
932
+ isDefault: z.ZodOptional<z.ZodBoolean>;
933
+ recipientName: z.ZodString;
934
+ companyName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
935
+ line1: z.ZodString;
936
+ line2: z.ZodNullable<z.ZodOptional<z.ZodString>>;
937
+ city: z.ZodString;
938
+ regionName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
939
+ regionCode: z.ZodNullable<z.ZodOptional<z.ZodString>>;
940
+ postalCode: z.ZodNullable<z.ZodOptional<z.ZodString>>;
941
+ country: z.ZodString;
942
+ countryName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
943
+ deliveryNotes: z.ZodNullable<z.ZodOptional<z.ZodString>>;
944
+ timezone: z.ZodNullable<z.ZodOptional<z.ZodString>>;
945
+ venueName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
946
+ placeId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
947
+ formattedAddress: z.ZodNullable<z.ZodOptional<z.ZodString>>;
948
+ latitude: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
949
+ longitude: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
950
+ }, z.core.$strip>;
951
+ type AddressInput = z.infer<typeof addressSchema>;
952
+ /** Server response shape — adds id + audit fields. */
953
+ type AddressRecord = AddressInput & {
954
+ id: string;
955
+ createdAt: string;
956
+ updatedAt: string;
957
+ };
958
+
959
+ type ElvixAddressBookResult = {
960
+ ok: true;
961
+ count: number;
962
+ } | {
963
+ ok: false;
964
+ error: string;
965
+ message?: string;
966
+ };
967
+ type ElvixAddressBookProps = {
968
+ kind: AddressKind;
969
+ /** Fixed frame height. Defaults to 520. Takes precedence over min/max. */
970
+ height?: number;
971
+ /** Bottom bound when `height` is unset. */
972
+ minHeight?: number;
973
+ /** Top bound when `height` is unset. */
974
+ maxHeight?: number;
975
+ /** Frame width. Defaults to "100%" so it fills whatever container
976
+ * the host puts it in. Pass a number for a fixed pixel width. */
977
+ width?: number | string;
978
+ /**
979
+ * Signed-in user's display name. Powers the "Me" card on the
980
+ * recipient step so the user can pick their own name with one
981
+ * click. Falls back to email or "You" if the host doesn't provide.
982
+ */
983
+ userDisplayName?: string | null;
984
+ /** Optional callback fired after a successful save / delete. */
985
+ onChange?: (addresses: AddressRecord[]) => void;
986
+ /** Fires on every terminal save / delete outcome. Safe payload:
987
+ * count only — never the address rows themselves. */
988
+ onResult?: (result: ElvixAddressBookResult) => void;
989
+ };
990
+ declare function ElvixAddressBook({ kind, height, minHeight, maxHeight, width, userDisplayName, onChange, onResult, }: ElvixAddressBookProps): react_jsx_runtime.JSX.Element;
605
991
 
606
992
  /**
607
- * `<ElvixLegalEntities>` list / add / remove the end-user's legal
608
- * entities (company names + tax IDs) on this Application. Useful for
609
- * B2B apps that bill at the entity level.
993
+ * Strict schema layered atop the loose shape. The `superRefine` adds
994
+ * the per-type required-field gates the wizard enforces at commit
995
+ * time but server-PATCH endpoints don't want.
610
996
  */
611
- declare function ElvixLegalEntities({ onResult, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
612
- onResult?: (r: ElvixActionResult) => void;
613
- } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
997
+ declare const legalEntitySchema: z.ZodObject<{
998
+ type: z.ZodEnum<{
999
+ company: "company";
1000
+ individual: "individual";
1001
+ sole_prop: "sole_prop";
1002
+ }>;
1003
+ label: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1004
+ isDefault: z.ZodOptional<z.ZodBoolean>;
1005
+ legalName: z.ZodString;
1006
+ tradingName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1007
+ dateOfBirth: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1008
+ placeOfBirth: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1009
+ placeOfBirthPlaceId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1010
+ nationality: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1011
+ taxCountry: z.ZodString;
1012
+ taxId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1013
+ vatId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1014
+ vatIdValidation: z.ZodOptional<z.ZodEnum<{
1015
+ none: "none";
1016
+ format: "format";
1017
+ invalid: "invalid";
1018
+ live: "live";
1019
+ }>>;
1020
+ vatIdValidatedAt: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1021
+ vatIdValidatedName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1022
+ registrationNumber: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1023
+ registrationBody: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1024
+ registeredSince: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1025
+ contactEmail: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1026
+ contactPhone: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1027
+ addressLine1: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1028
+ addressLine2: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1029
+ addressCity: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1030
+ addressRegionName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1031
+ addressRegionCode: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1032
+ addressPostalCode: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1033
+ addressCountry: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1034
+ addressCountryName: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1035
+ addressFormatted: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1036
+ addressPlaceId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1037
+ addressTimezone: z.ZodNullable<z.ZodOptional<z.ZodString>>;
1038
+ addressLatitude: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
1039
+ addressLongitude: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
1040
+ }, z.core.$strip>;
1041
+ type LegalEntityInput = z.infer<typeof legalEntitySchema>;
1042
+ /** Server-emitted record. Adds audit fields, normalises dates to ISO. */
1043
+ type LegalEntityRecord = Omit<LegalEntityInput, "dateOfBirth" | "registeredSince"> & {
1044
+ id: string;
1045
+ dateOfBirth: string | null;
1046
+ registeredSince: string | null;
1047
+ createdAt: string;
1048
+ updatedAt: string;
1049
+ };
1050
+
1051
+ type ElvixLegalEntitiesResult = {
1052
+ ok: true;
1053
+ count: number;
1054
+ } | {
1055
+ ok: false;
1056
+ error: string;
1057
+ message?: string;
1058
+ };
1059
+ type ElvixLegalEntitiesProps = {
1060
+ /** Fixed frame height. Defaults to 580. */
1061
+ height?: number;
1062
+ minHeight?: number;
1063
+ maxHeight?: number;
1064
+ /** Frame width. Defaults to "100%". */
1065
+ width?: number | string;
1066
+ /** Optional callback fired after a successful save / delete. */
1067
+ onChange?: (entities: LegalEntityRecord[]) => void;
1068
+ /** Fires on every terminal save / delete outcome. Safe payload:
1069
+ * count only — never the entity rows themselves. */
1070
+ onResult?: (result: ElvixLegalEntitiesResult) => void;
1071
+ };
1072
+ declare function ElvixLegalEntities({ height, minHeight, maxHeight, width, onChange, onResult, }: ElvixLegalEntitiesProps): react_jsx_runtime.JSX.Element;
614
1073
 
615
- export { DEFAULT_COPY, ElvixActionResult, ElvixAddressBook, ElvixAvatar, ElvixBanner, type ElvixBootstrapEnvelope, type ElvixBrand, ElvixCard, type ElvixCopy, ElvixDeactivate, ElvixExport, ElvixIdentityForm, ElvixLanguages, ElvixLeave, ElvixLegalEntities, ElvixLifecycleWatcher, ElvixProvider, ElvixRegion, ElvixSecuredBadge, ElvixSessions, ElvixSignIn, ElvixSignInButton, ElvixSignInForm, type ElvixSignInMethod, type ElvixSignInResult$1 as ElvixSignInResult, type ElvixSignInResultErr, type ElvixSignInResultOk, type ElvixSizeProps, type ElvixTheme, ElvixUsername, type UseUserListResult, getElvixToken, setElvixToken, useElvixApp, useElvixContext, useUserMemberships, useUserRoles, useUserScopes };
1074
+ export { DEFAULT_COPY, ElvixAddressBook, type ElvixAppContext, ElvixAvatar, ElvixBanner, type ElvixBootstrapEnvelope, type ElvixBrand, ElvixCard, type ElvixCopy, ElvixDeactivate, ElvixExport, ElvixIdentityForm, ElvixLanguages, ElvixLeave, ElvixLegalEntities, ElvixLifecycleWatcher, ElvixProvider, ElvixRegion, ElvixSecuredBadge, ElvixSessions, ElvixSignIn, ElvixSignInButton, ElvixSignInForm, type ElvixSignInMethod, type ElvixSignInResult$1 as ElvixSignInResult, type ElvixSignInResultErr, type ElvixSignInResultOk, type ElvixSizeProps, type ElvixTheme, ElvixUsername, type UseUserListResult, consumeElvixReturnToken, getElvixToken, setElvixToken, useElvixApp, useElvixAppContext, useElvixContext, useUserMemberships, useUserRoles, useUserScopes };