@elvix.is/sdk 0.5.5 → 0.5.7

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
@@ -58,6 +58,8 @@ type ElvixCopy = {
58
58
  subtitle?: string;
59
59
  /** Google factor button. */
60
60
  googleButton?: string;
61
+ /** Passkey factor button. */
62
+ passkeyButton?: string;
61
63
  /** Email field placeholder. */
62
64
  emailPlaceholder?: string;
63
65
  /** Email submit button (identify step). */
@@ -134,6 +136,23 @@ type ElvixBootstrapEnvelope = {
134
136
  showHeader: boolean;
135
137
  transparentBg: boolean;
136
138
  signInVerb: "signin" | "login";
139
+ /**
140
+ * Per-app Google Identity Services config (One Tap / Auto-select / Popup
141
+ * / FedCM). Present on the wire; the SDK's `<ElvixSignInForm>` reads it
142
+ * into its resolved props. When any GIS flag is on AND `googleClientId`
143
+ * is present, the form swaps the static redirect anchor for Google's
144
+ * GIS-rendered personalized button.
145
+ */
146
+ googleConfig: unknown;
147
+ /**
148
+ * Public Google OAuth client id for GIS (the personalized "Continue as
149
+ * <name>" One Tap / renderButton path). In the elvix monorepo this is the
150
+ * build-time `NEXT_PUBLIC_GOOGLE_CLIENT_ID`; for the published SDK it
151
+ * arrives per-app on the bootstrap envelope. When absent, the Google
152
+ * factor degrades to the static redirect anchor (which uses elvix's
153
+ * server-side client id via `/api/auth/google/start`).
154
+ */
155
+ googleClientId?: string;
137
156
  signinGate: "public" | "private_beta" | "closed";
138
157
  archivedAt: string | null;
139
158
  /**
@@ -161,7 +180,7 @@ type ElvixSignInResultErr = {
161
180
  error: string;
162
181
  message?: string;
163
182
  };
164
- type ElvixSignInResult = ElvixSignInResultOk | ElvixSignInResultErr;
183
+ type ElvixSignInResult$1 = ElvixSignInResultOk | ElvixSignInResultErr;
165
184
  /** Theme override. Omit to inherit the Console-configured pair. */
166
185
  type ElvixTheme = "light" | "dark" | "system";
167
186
 
@@ -202,7 +221,7 @@ declare function ElvixProvider({ clientId, theme, brand, baseUrl, children, clas
202
221
  * calls `router.push` itself.
203
222
  */
204
223
  declare function ElvixSignIn({ onResult, redirectAfterSignIn, copy: copyProp, className, width, height, minWidth, maxWidth, minHeight, maxHeight, }: {
205
- onResult?: (r: ElvixSignInResult) => void;
224
+ onResult?: (r: ElvixSignInResult$1) => void;
206
225
  /** Default redirect target on success when the server doesn't echo one. */
207
226
  redirectAfterSignIn?: string;
208
227
  /**
@@ -215,42 +234,182 @@ declare function ElvixSignIn({ onResult, redirectAfterSignIn, copy: copyProp, cl
215
234
  } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
216
235
 
217
236
  /**
218
- * `<ElvixSignInForm>` the polished, fully-styled sign-in surface a
219
- * customer drops onto their own app.
237
+ * Public ResponseDto shape the SDK surfaces to `onResult` listeners.
238
+ * Mirrors the `{ ok: true | false, ... }` envelope every elvix API
239
+ * route returns via `withErrorHandling`. Customers branch on `ok`.
240
+ */
241
+ type ElvixSignInResult = {
242
+ ok: true;
243
+ redirect?: string;
244
+ } | {
245
+ ok: false;
246
+ error: string;
247
+ message?: string;
248
+ status?: number;
249
+ };
250
+ declare const Mode: {
251
+ readonly PREVIEW: "preview";
252
+ readonly INTERACTIVE: "interactive";
253
+ };
254
+ type Mode = (typeof Mode)[keyof typeof Mode];
255
+ declare const Intent: {
256
+ readonly CONSOLE: "console";
257
+ readonly ACCOUNT: "account";
258
+ readonly APP: "app";
259
+ };
260
+ type Intent = (typeof Intent)[keyof typeof Intent];
261
+ declare const Layout: {
262
+ readonly CENTERED: "centered";
263
+ readonly LEFT: "left";
264
+ readonly BANNER: "banner";
265
+ };
266
+ type Layout = (typeof Layout)[keyof typeof Layout];
267
+ declare const SocialLayout: {
268
+ readonly STACKED: "stacked";
269
+ readonly GRID: "grid";
270
+ };
271
+ type SocialLayout = (typeof SocialLayout)[keyof typeof SocialLayout];
272
+ declare const Presentation: {
273
+ readonly CARD: "card";
274
+ readonly DRAWER: "drawer";
275
+ readonly MODAL: "modal";
276
+ };
277
+ type Presentation = (typeof Presentation)[keyof typeof Presentation];
278
+ declare const Theme: {
279
+ readonly LIGHT: "light";
280
+ readonly DARK: "dark";
281
+ readonly AUTO: "auto";
282
+ };
283
+ type Theme = (typeof Theme)[keyof typeof Theme];
284
+ declare const SignInVerb: {
285
+ readonly SIGNIN: "signin";
286
+ readonly LOGIN: "login";
287
+ };
288
+ type SignInVerb = (typeof SignInVerb)[keyof typeof SignInVerb];
289
+ /**
290
+ * One auth surface to rule them all. Same component renders:
220
291
  *
221
- * Where `<ElvixSignIn>` is the bare-bones flow (class-hooked, host paints
222
- * it), this is the finished card: rounded logo tile, "Sign in to {app}"
223
- * heading, "Continue with Google", an OR divider, the email→code OTP
224
- * flow, a legal footer, and a "Secured by elvix" badge. It ships with
225
- * **inline styles only** — no host CSS required, so it looks right the
226
- * moment it mounts on any origin.
292
+ * - The live preview inside the Console (Create app + Sign-in configure).
293
+ * mode="preview" all controls disabled, just visual.
227
294
  *
228
- * Cross-origin correct: OTP start/verify pick credentials from
229
- * `isSameOrigin(baseUrl)` exactly like `<ElvixSignIn>`; on a third-party
230
- * origin the session token comes back in the response body and is stored
231
- * via `setElvixToken`. Google is a top-level redirect.
295
+ * - The actual hosted sign-in at /sign-in/<clientId> for any customer app.
296
+ * mode="interactive" + intent="app:<clientId>" real flows.
232
297
  *
233
- * Reads enabled methods + branding from the Console-configured bootstrap
234
- * envelope (`<ElvixProvider clientId>` must be an ancestor). Renders only
235
- * the factors the Console turned on; never invents UI it denied.
298
+ * - The elvix Console's own sign-in at /sign-in/console.
299
+ * mode="interactive" + intent="console" dogfoods our own auth.
236
300
  *
237
- * `onResult({ ok, ... })` fires on success AND every failure, mirroring
238
- * `<ElvixSignIn>`. The component never navigates the host itself.
301
+ * - The account surface at /sign-in/account.
302
+ * mode="interactive" + intent="account".
303
+ *
304
+ * Sign-in = Sign-up. There's no separate signup route. If you don't exist
305
+ * yet, the first successful auth creates you.
239
306
  */
240
- type ElvixSignInFormProps = {
241
- /** Fires on every terminal outcome — success and failure — like `<ElvixSignIn>`. */
242
- onResult?: (r: ElvixSignInResult) => void;
243
- /** Default redirect target on success when the server doesn't echo one. */
244
- redirectAfterSignIn?: string;
307
+ type AuthFormProps = {
245
308
  /**
246
- * Thin per-embed copy override. The primary way to edit copy is the elvix
247
- * Console (served live in the bootstrap `strings`); this prop just lets a
248
- * single embed tweak a string or two without a Console change.
309
+ * "interactive" (default) hits real auth endpoints.
310
+ * "preview" renders the surface read-only every CTA paints but
311
+ * never makes a request. Console live-preview uses this.
249
312
  */
250
- copy?: Partial<ElvixCopy>;
251
- className?: string;
252
- } & /** Sizing applied to the card root inline style (SDK components are sizable). */ ElvixSizeProps;
253
- declare function ElvixSignInForm({ onResult, redirectAfterSignIn, copy: copyProp, className, minWidth, maxWidth, minHeight, maxHeight, width, height, }: ElvixSignInFormProps): react_jsx_runtime.JSX.Element;
313
+ mode?: Mode;
314
+ /**
315
+ * App display name. Optional when `<ElvixProvider clientId>` is
316
+ * mounted the provider fetches it from the Console-configured
317
+ * Application row. Explicit prop wins (Console passes its unsaved
318
+ * live state here).
319
+ */
320
+ appName?: string;
321
+ logoUrl?: string | null;
322
+ /** Optional dark-mode variant. Used when `theme="dark"`, otherwise we
323
+ * show the same logoUrl in both themes. */
324
+ logoUrlDark?: string | null;
325
+ /** Optional pre-rendered logo node. Wins over logoUrl + letter fallback. */
326
+ logoNode?: React.ReactNode;
327
+ brandColor?: string;
328
+ /** Foreground colour painted on top of brandColor (CTA text/icons). */
329
+ onBrandColor?: string;
330
+ methodGoogle?: boolean;
331
+ methodEmailOtp?: boolean;
332
+ methodPasskey?: boolean;
333
+ methodUsername?: boolean;
334
+ privacyPolicyUrl?: string | null;
335
+ termsOfServiceUrl?: string | null;
336
+ framed?: boolean;
337
+ /** Used in interactive mode to route auth requests. */
338
+ intent?: Intent;
339
+ /** For intent="app": the Application client_id. */
340
+ clientId?: string;
341
+ /** If set, the logo becomes a clickable link to this URL (the app's website). */
342
+ websiteUrl?: string | null;
343
+ /** Visual layout. Three variants today. */
344
+ layout?: Layout;
345
+ /** Social button arrangement: stacked rows (default) or 2-up grid. */
346
+ socialLayout?: SocialLayout;
347
+ /** Surrounding chrome — card / drawer (bottom sheet) / modal overlay. */
348
+ presentation?: Presentation;
349
+ /** Theme override for the form's surface tokens. */
350
+ theme?: Theme;
351
+ /** Hide the built-in header (logo + "Sign in to X" title + subtitle). */
352
+ showHeader?: boolean;
353
+ /** Which verb the customer wants on the CTA + heading. Some brands
354
+ * prefer "Log in" (banks, B2B legacy); SaaS defaults to "Sign in". */
355
+ signInVerb?: SignInVerb;
356
+ /** Strip card bg + border + shadow so the form blends into its host. */
357
+ transparentBg?: boolean;
358
+ /** Optional node rendered directly below the "Pick how you want to
359
+ * continue" subtitle. Used for gate-state badges ("Private beta",
360
+ * "Closed signups") so they sit inline with the form instead of
361
+ * competing as a separate surface above the card. */
362
+ belowHeading?: React.ReactNode;
363
+ /** Optional pre-rendered node injected just under the methods, on
364
+ * the way to the "Secured by elvix" chip. Used for the
365
+ * "Inform me when it goes public" + "Request access" text-links
366
+ * shown on gated hosted surfaces. */
367
+ belowMethods?: React.ReactNode;
368
+ /** Per-app Google Identity Services config. When set + `methodGoogle`
369
+ * is on + we're in interactive mode + a `googleClientId` is available,
370
+ * the ElvixSignInForm loads the GIS client lib and applies One Tap /
371
+ * Auto-select / FedCM / popup ux_mode based on each flag. Falls back to
372
+ * the plain redirect-OAuth anchor otherwise. */
373
+ googleConfig?: {
374
+ oneTap?: boolean;
375
+ autoSelect?: boolean;
376
+ popup?: boolean;
377
+ fedcm?: boolean;
378
+ hostedDomain?: string;
379
+ };
380
+ /** Public Google OAuth client id for the GIS personalized button. In the
381
+ * elvix monorepo this is the build-time `NEXT_PUBLIC_GOOGLE_CLIENT_ID`;
382
+ * the SDK reads it off the bootstrap envelope (`googleClientId`). When
383
+ * absent, the Google factor degrades to the static redirect anchor. */
384
+ googleClientId?: string;
385
+ /**
386
+ * Fires after a successful sign-in (OTP, Google, Passkey) — BEFORE
387
+ * the default redirect runs. When provided, the form will NOT
388
+ * navigate; the host owns post-auth routing. Use this to keep an
389
+ * embedded surface (Drawer/Modal/Card) in place after auth and let
390
+ * the host call `router.push()` itself.
391
+ *
392
+ * Call `GET /api/me` from the host to fetch the authenticated user.
393
+ * The v2 SDK will surface user details directly in the payload.
394
+ */
395
+ onAuthenticated?: (result: {
396
+ ok: true;
397
+ redirect?: string;
398
+ token?: string;
399
+ }) => void;
400
+ /**
401
+ * Fires on every terminal outcome: success AND every error path
402
+ * (invalid OTP, expired challenge, rate-limited, network blip,
403
+ * passkey failure). Mirrors the ResponseDto shape the rest of the
404
+ * elvix API surfaces, so the customer branches on `ok` the same
405
+ * way they would for a `/api/v1/verify` call.
406
+ *
407
+ * Both `onResult` and `onAuthenticated` may be set. `onResult` fires
408
+ * regardless; `onAuthenticated` only on success (legacy contract).
409
+ */
410
+ onResult?: (result: ElvixSignInResult) => void;
411
+ };
412
+ declare function ElvixSignInForm(props: AuthFormProps): react_jsx_runtime.JSX.Element;
254
413
 
255
414
  type ElvixSignInButtonSize = "sm" | "md" | "lg";
256
415
  type ElvixSignInButtonTheme = "light" | "dark" | "auto";
@@ -276,7 +435,7 @@ type ElvixSignInButtonProps = {
276
435
  mode?: ElvixSignInButtonMode;
277
436
  onClick?: () => void;
278
437
  /** Terminal outcome of mode="embed": success (with token) or error. */
279
- onResult?: (result: ElvixSignInResult) => void;
438
+ onResult?: (result: ElvixSignInResult$1) => void;
280
439
  } & /**
281
440
  * Dimensional sizing (width/height/min/max), additive to the `size` preset.
282
441
  * Merged last into the root element so an explicit width/height wins.
@@ -453,4 +612,4 @@ declare function ElvixLegalEntities({ onResult, width, height, minWidth, maxWidt
453
612
  onResult?: (r: ElvixActionResult) => void;
454
613
  } & ElvixSizeProps): react_jsx_runtime.JSX.Element;
455
614
 
456
- 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, type ElvixSignInResultErr, type ElvixSignInResultOk, type ElvixSizeProps, type ElvixTheme, ElvixUsername, type UseUserListResult, getElvixToken, setElvixToken, useElvixApp, useElvixContext, useUserMemberships, useUserRoles, useUserScopes };
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 };