@elvix.is/sdk 0.5.2 → 0.5.4

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 +44 -31
  2. package/dist/react.js +376 -172
  3. package/package.json +2 -2
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as react from 'react';
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { ElvixActionResult } from './index.js';
4
4
  export { ElvixUser, ElvixVerifyResult } from './index.js';
@@ -18,7 +18,7 @@ declare function ElvixCard({ title, footer, className, children, }: {
18
18
  footer?: ReactNode;
19
19
  className?: string;
20
20
  children: ReactNode;
21
- }): react.JSX.Element;
21
+ }): react_jsx_runtime.JSX.Element;
22
22
 
23
23
  /**
24
24
  * Editable sign-in copy.
@@ -84,6 +84,12 @@ type ElvixBrand = {
84
84
  };
85
85
  };
86
86
  type ElvixSignInMethod = "google" | "email_otp" | "passkey" | "username";
87
+ /**
88
+ * The public render envelope `GET /api/v1/bootstrap/<clientId>` returns. Flat
89
+ * to match the wire shape exactly (the provider builds the {light,dark} brand
90
+ * chord from the colour fields). Any field here is already public — it's what
91
+ * the sign-in surface shows.
92
+ */
87
93
  type ElvixBootstrapEnvelope = {
88
94
  applicationId: string;
89
95
  clientId: string;
@@ -93,21 +99,28 @@ type ElvixBootstrapEnvelope = {
93
99
  logoUrlDark: string | null;
94
100
  iconUrl: string | null;
95
101
  iconUrlDark: string | null;
96
- brand: ElvixBrand;
97
- methods: {
98
- google: boolean;
99
- emailOtp: boolean;
100
- passkey: boolean;
101
- username: boolean;
102
- };
103
- legal: {
104
- privacyPolicyUrl: string;
105
- termsOfServiceUrl: string;
106
- supportEmail: string;
107
- supportUrl: string | null;
108
- };
102
+ websiteUrl: string | null;
103
+ privacyPolicyUrl: string;
104
+ termsOfServiceUrl: string;
105
+ supportUrl: string | null;
106
+ brandColor: string;
107
+ brandColorDark: string | null;
108
+ onBrandColor: string;
109
+ onBrandColorDark: string | null;
110
+ brandPreset: string;
111
+ methodGoogle: boolean;
112
+ methodEmailOtp: boolean;
113
+ methodPasskey: boolean;
114
+ methodUsername: boolean;
115
+ layout: string;
116
+ socialLayout: string;
117
+ presentation: string;
118
+ theme: "light" | "dark" | "system";
119
+ showHeader: boolean;
120
+ transparentBg: boolean;
109
121
  signInVerb: "signin" | "login";
110
122
  signinGate: "public" | "private_beta" | "closed";
123
+ archivedAt: string | null;
111
124
  /**
112
125
  * Console-configured sign-in copy overrides. Any subset of the strings the
113
126
  * sign-in surface renders; missing keys fall back to the built-in English
@@ -154,7 +167,7 @@ declare function ElvixProvider({ clientId, theme, brand, baseUrl, children, clas
154
167
  baseUrl?: string;
155
168
  children: ReactNode;
156
169
  className?: string;
157
- }): react.JSX.Element;
170
+ }): react_jsx_runtime.JSX.Element;
158
171
 
159
172
  /**
160
173
  * `<ElvixSignIn>` — drop-in sign-in surface.
@@ -184,7 +197,7 @@ declare function ElvixSignIn({ onResult, redirectAfterSignIn, copy: copyProp, cl
184
197
  */
185
198
  copy?: Partial<ElvixCopy>;
186
199
  className?: string;
187
- }): react.JSX.Element;
200
+ }): react_jsx_runtime.JSX.Element;
188
201
 
189
202
  type ElvixSignInButtonSize = "sm" | "md" | "lg";
190
203
  type ElvixSignInButtonTheme = "light" | "dark" | "auto";
@@ -212,7 +225,7 @@ type ElvixSignInButtonProps = {
212
225
  /** Terminal outcome of mode="embed": success (with token) or error. */
213
226
  onResult?: (result: ElvixSignInResult) => void;
214
227
  };
215
- declare function ElvixSignInButton({ clientId, baseUrl, returnUrl, type, variant, shape, size, theme, preset, label, className, href, mode, onClick, onResult, }: ElvixSignInButtonProps): react.JSX.Element;
228
+ declare function ElvixSignInButton({ clientId, baseUrl, returnUrl, type, variant, shape, size, theme, preset, label, className, href, mode, onClick, onResult, }: ElvixSignInButtonProps): react_jsx_runtime.JSX.Element;
216
229
 
217
230
  type ElvixSecuredBadgeVariant = "white" | "dark" | "outline";
218
231
  type ElvixSecuredBadgeSize = "sm" | "md" | "lg";
@@ -228,7 +241,7 @@ type ElvixSecuredBadgeProps = {
228
241
  href?: string;
229
242
  className?: string;
230
243
  };
231
- declare function ElvixSecuredBadge({ variant, size, theme, accentColor, href, className, }: ElvixSecuredBadgeProps): react.JSX.Element;
244
+ declare function ElvixSecuredBadge({ variant, size, theme, accentColor, href, className, }: ElvixSecuredBadgeProps): react_jsx_runtime.JSX.Element;
232
245
 
233
246
  /**
234
247
  * Session token store for cross-origin SDK use.
@@ -281,7 +294,7 @@ declare function ElvixUsername({ onResult, }: {
281
294
  onResult?: (r: ElvixActionResult<{
282
295
  username: string;
283
296
  }>) => void;
284
- }): react.JSX.Element;
297
+ }): react_jsx_runtime.JSX.Element;
285
298
 
286
299
  /**
287
300
  * `<ElvixAvatar>` — upload / replace the end-user's avatar for this
@@ -291,7 +304,7 @@ declare function ElvixAvatar({ onResult, }: {
291
304
  onResult?: (r: ElvixActionResult<{
292
305
  avatarUrl: string;
293
306
  }>) => void;
294
- }): react.JSX.Element;
307
+ }): react_jsx_runtime.JSX.Element;
295
308
 
296
309
  /**
297
310
  * `<ElvixBanner>` — upload / replace the end-user's profile banner
@@ -301,7 +314,7 @@ declare function ElvixBanner({ onResult, }: {
301
314
  onResult?: (r: ElvixActionResult<{
302
315
  bannerUrl: string;
303
316
  }>) => void;
304
- }): react.JSX.Element;
317
+ }): react_jsx_runtime.JSX.Element;
305
318
 
306
319
  /**
307
320
  * `<ElvixIdentityForm>` — edit the end-user's display name + bio for
@@ -314,7 +327,7 @@ declare function ElvixIdentityForm({ initialName, initialBio, onResult, }: {
314
327
  name: string;
315
328
  bio: string;
316
329
  }>) => void;
317
- }): react.JSX.Element;
330
+ }): react_jsx_runtime.JSX.Element;
318
331
 
319
332
  /**
320
333
  * `<ElvixRegion>` — set the end-user's region (ISO 3166-1 alpha-2
@@ -328,7 +341,7 @@ declare function ElvixRegion({ initialCountry, initialTimezone, onResult, }: {
328
341
  country: string;
329
342
  timezone: string;
330
343
  }>) => void;
331
- }): react.JSX.Element;
344
+ }): react_jsx_runtime.JSX.Element;
332
345
 
333
346
  /**
334
347
  * `<ElvixLanguages>` — set the end-user's preferred languages (BCP-47
@@ -339,13 +352,13 @@ declare function ElvixLanguages({ initial, onResult, }: {
339
352
  onResult?: (r: ElvixActionResult<{
340
353
  languages: string[];
341
354
  }>) => void;
342
- }): react.JSX.Element;
355
+ }): react_jsx_runtime.JSX.Element;
343
356
 
344
357
  declare function ElvixSessions({ onResult, }: {
345
358
  onResult?: (r: ElvixActionResult<{
346
359
  revoked: number;
347
360
  }>) => void;
348
- }): react.JSX.Element;
361
+ }): react_jsx_runtime.JSX.Element;
349
362
 
350
363
  /**
351
364
  * `<ElvixExport>` — GDPR Art. 15 data-export request. Triggers an
@@ -356,15 +369,15 @@ declare function ElvixExport({ onResult, }: {
356
369
  onResult?: (r: ElvixActionResult<{
357
370
  requestId: string;
358
371
  }>) => void;
359
- }): react.JSX.Element;
372
+ }): react_jsx_runtime.JSX.Element;
360
373
 
361
374
  declare function ElvixDeactivate({ onResult, }: {
362
375
  onResult?: (r: ElvixActionResult) => void;
363
- }): react.JSX.Element;
376
+ }): react_jsx_runtime.JSX.Element;
364
377
 
365
378
  declare function ElvixLeave({ onResult, }: {
366
379
  onResult?: (r: ElvixActionResult) => void;
367
- }): react.JSX.Element;
380
+ }): react_jsx_runtime.JSX.Element;
368
381
 
369
382
  /**
370
383
  * `<ElvixAddressBook>` — list / add / remove the end-user's addresses
@@ -373,7 +386,7 @@ declare function ElvixLeave({ onResult, }: {
373
386
  */
374
387
  declare function ElvixAddressBook({ onResult, }: {
375
388
  onResult?: (r: ElvixActionResult) => void;
376
- }): react.JSX.Element;
389
+ }): react_jsx_runtime.JSX.Element;
377
390
 
378
391
  /**
379
392
  * `<ElvixLegalEntities>` — list / add / remove the end-user's legal
@@ -382,6 +395,6 @@ declare function ElvixAddressBook({ onResult, }: {
382
395
  */
383
396
  declare function ElvixLegalEntities({ onResult, }: {
384
397
  onResult?: (r: ElvixActionResult) => void;
385
- }): react.JSX.Element;
398
+ }): react_jsx_runtime.JSX.Element;
386
399
 
387
400
  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, type ElvixSignInMethod, type ElvixSignInResult, type ElvixSignInResultErr, type ElvixSignInResultOk, type ElvixTheme, ElvixUsername, type UseUserListResult, getElvixToken, setElvixToken, useElvixApp, useElvixContext, useUserMemberships, useUserRoles, useUserScopes };
package/dist/react.js CHANGED
@@ -1,11 +1,13 @@
1
+ "use client";
1
2
  // src/react/elvix-card.tsx
3
+ import { jsx, jsxs } from "react/jsx-runtime";
2
4
  function ElvixCard({
3
5
  title,
4
6
  footer,
5
7
  className = "",
6
8
  children
7
9
  }) {
8
- return /* @__PURE__ */ React.createElement(
10
+ return /* @__PURE__ */ jsxs(
9
11
  "div",
10
12
  {
11
13
  className: `elvix-card ${className}`.trim(),
@@ -18,34 +20,36 @@ function ElvixCard({
18
20
  flexDirection: "column",
19
21
  maxWidth: "440px",
20
22
  width: "100%"
21
- }
22
- },
23
- title && /* @__PURE__ */ React.createElement(
24
- "div",
25
- {
26
- style: {
27
- padding: "20px 24px 0",
28
- fontSize: "16px",
29
- fontWeight: 600,
30
- color: "var(--elvix-primary-strong, #5d4dff)"
31
- }
32
- },
33
- title
34
- ),
35
- /* @__PURE__ */ React.createElement("div", { style: { padding: "16px 24px", flex: 1 } }, children),
36
- footer && /* @__PURE__ */ React.createElement(
37
- "div",
38
- {
39
- style: {
40
- padding: "12px 24px",
41
- borderTop: "1px solid var(--elvix-primary-12, rgba(93,77,255,0.12))",
42
- background: "rgba(0,0,0,0.02)",
43
- fontSize: "12px",
44
- color: "rgba(0,0,0,0.55)"
45
- }
46
23
  },
47
- footer
48
- )
24
+ children: [
25
+ title && /* @__PURE__ */ jsx(
26
+ "div",
27
+ {
28
+ style: {
29
+ padding: "20px 24px 0",
30
+ fontSize: "16px",
31
+ fontWeight: 600,
32
+ color: "var(--elvix-primary-strong, #5d4dff)"
33
+ },
34
+ children: title
35
+ }
36
+ ),
37
+ /* @__PURE__ */ jsx("div", { style: { padding: "16px 24px", flex: 1 }, children }),
38
+ footer && /* @__PURE__ */ jsx(
39
+ "div",
40
+ {
41
+ style: {
42
+ padding: "12px 24px",
43
+ borderTop: "1px solid var(--elvix-primary-12, rgba(93,77,255,0.12))",
44
+ background: "rgba(0,0,0,0.02)",
45
+ fontSize: "12px",
46
+ color: "rgba(0,0,0,0.55)"
47
+ },
48
+ children: footer
49
+ }
50
+ )
51
+ ]
52
+ }
49
53
  );
50
54
  }
51
55
 
@@ -57,6 +61,7 @@ import {
57
61
  useMemo,
58
62
  useState
59
63
  } from "react";
64
+ import { jsx as jsx2 } from "react/jsx-runtime";
60
65
  var ELVIX_DEFAULT_BRAND = {
61
66
  light: { primary: "#5d4dff", on: "#ffffff" },
62
67
  dark: { primary: "#8e7dff", on: "#0a0a0b" }
@@ -140,19 +145,25 @@ function ElvixProvider({
140
145
  appError,
141
146
  resolvedTheme: effectiveTheme
142
147
  };
143
- return /* @__PURE__ */ React.createElement(ElvixContext.Provider, { value }, /* @__PURE__ */ React.createElement(
148
+ return /* @__PURE__ */ jsx2(ElvixContext.Provider, { value, children: /* @__PURE__ */ jsx2(
144
149
  "div",
145
150
  {
146
151
  "data-elvix-theme": effectiveTheme,
147
152
  style: cssVars,
148
- className: (effectiveTheme === "dark" ? "dark " : "") + "elvix-sdk-root " + className
149
- },
150
- children
151
- ));
153
+ className: (effectiveTheme === "dark" ? "dark " : "") + "elvix-sdk-root " + className,
154
+ children
155
+ }
156
+ ) });
152
157
  }
153
158
  function appBrand(app) {
154
- if (!app?.brand) return null;
155
- return app.brand;
159
+ if (!app?.brandColor) return null;
160
+ return {
161
+ light: { primary: app.brandColor, on: app.onBrandColor },
162
+ dark: {
163
+ primary: app.brandColorDark ?? app.brandColor,
164
+ on: app.onBrandColorDark ?? app.onBrandColor
165
+ }
166
+ };
156
167
  }
157
168
  function withAlpha(hex, a) {
158
169
  const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
@@ -240,6 +251,7 @@ function isSameOrigin(baseUrl) {
240
251
  }
241
252
 
242
253
  // src/react/elvix-sign-in.tsx
254
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
243
255
  function ElvixSignIn({
244
256
  onResult,
245
257
  redirectAfterSignIn,
@@ -330,66 +342,87 @@ function ElvixSignIn({
330
342
  }
331
343
  const card = `elvix-card ${className}`.trim();
332
344
  if (step === "done") {
333
- return /* @__PURE__ */ React.createElement("div", { className: card, "data-elvix-pane": "done" }, /* @__PURE__ */ React.createElement("p", null, copy.signedInText));
345
+ return /* @__PURE__ */ jsx3("div", { className: card, "data-elvix-pane": "done", children: /* @__PURE__ */ jsx3("p", { children: copy.signedInText }) });
334
346
  }
335
- return /* @__PURE__ */ React.createElement("div", { className: card, "data-elvix-pane": step }, /* @__PURE__ */ React.createElement("h2", { className: "elvix-h" }, title), copy.subtitle && /* @__PURE__ */ React.createElement("p", { className: "elvix-muted elvix-subtitle" }, copy.subtitle), step === "identify" && /* @__PURE__ */ React.createElement(React.Fragment, null, app?.methods.google && /* @__PURE__ */ React.createElement(
336
- "button",
337
- {
338
- type: "button",
339
- onClick: startGoogle,
340
- disabled: busy,
341
- className: "elvix-btn elvix-btn-google",
342
- "data-elvix-method": "google"
343
- },
344
- copy.googleButton
345
- ), app?.methods.emailOtp && /* @__PURE__ */ React.createElement("form", { onSubmit: startOtp, "data-elvix-method": "email_otp", className: "elvix-otp-form" }, /* @__PURE__ */ React.createElement(
346
- "input",
347
- {
348
- type: "email",
349
- value: email,
350
- onChange: (ev) => setEmail(ev.target.value),
351
- placeholder: copy.emailPlaceholder,
352
- required: true,
353
- disabled: busy,
354
- className: "elvix-input"
355
- }
356
- ), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ? copy.sendingLabel : copy.sendCodeButton))), step === "code" && /* @__PURE__ */ React.createElement("form", { onSubmit: verifyOtp, className: "elvix-otp-form" }, /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, fillCopy(copy.codeSentSubtitle ?? "", { email })), /* @__PURE__ */ React.createElement(
357
- "input",
358
- {
359
- type: "text",
360
- inputMode: "numeric",
361
- pattern: "[0-9]*",
362
- maxLength: 6,
363
- value: code,
364
- onChange: (ev) => setCode(ev.target.value.replace(/\D/g, "")),
365
- placeholder: copy.codePlaceholder,
366
- required: true,
367
- disabled: busy,
368
- className: "elvix-input"
369
- }
370
- ), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ? copy.verifyingLabel : submitLabel)), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error));
347
+ return /* @__PURE__ */ jsxs2("div", { className: card, "data-elvix-pane": step, children: [
348
+ /* @__PURE__ */ jsx3("h2", { className: "elvix-h", children: title }),
349
+ copy.subtitle && /* @__PURE__ */ jsx3("p", { className: "elvix-muted elvix-subtitle", children: copy.subtitle }),
350
+ step === "identify" && /* @__PURE__ */ jsxs2(Fragment, { children: [
351
+ app?.methodGoogle && /* @__PURE__ */ jsx3(
352
+ "button",
353
+ {
354
+ type: "button",
355
+ onClick: startGoogle,
356
+ disabled: busy,
357
+ className: "elvix-btn elvix-btn-google",
358
+ "data-elvix-method": "google",
359
+ children: copy.googleButton
360
+ }
361
+ ),
362
+ app?.methodEmailOtp && /* @__PURE__ */ jsxs2("form", { onSubmit: startOtp, "data-elvix-method": "email_otp", className: "elvix-otp-form", children: [
363
+ /* @__PURE__ */ jsx3(
364
+ "input",
365
+ {
366
+ type: "email",
367
+ value: email,
368
+ onChange: (ev) => setEmail(ev.target.value),
369
+ placeholder: copy.emailPlaceholder,
370
+ required: true,
371
+ disabled: busy,
372
+ className: "elvix-input"
373
+ }
374
+ ),
375
+ /* @__PURE__ */ jsx3("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? copy.sendingLabel : copy.sendCodeButton })
376
+ ] })
377
+ ] }),
378
+ step === "code" && /* @__PURE__ */ jsxs2("form", { onSubmit: verifyOtp, className: "elvix-otp-form", children: [
379
+ /* @__PURE__ */ jsx3("p", { className: "elvix-muted", children: fillCopy(copy.codeSentSubtitle ?? "", { email }) }),
380
+ /* @__PURE__ */ jsx3(
381
+ "input",
382
+ {
383
+ type: "text",
384
+ inputMode: "numeric",
385
+ pattern: "[0-9]*",
386
+ maxLength: 6,
387
+ value: code,
388
+ onChange: (ev) => setCode(ev.target.value.replace(/\D/g, "")),
389
+ placeholder: copy.codePlaceholder,
390
+ required: true,
391
+ disabled: busy,
392
+ className: "elvix-input"
393
+ }
394
+ ),
395
+ /* @__PURE__ */ jsx3("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary", children: busy ? copy.verifyingLabel : submitLabel })
396
+ ] }),
397
+ error && /* @__PURE__ */ jsx3("p", { role: "alert", className: "elvix-error", children: error })
398
+ ] });
371
399
  }
372
400
 
373
401
  // src/react/elvix-sign-in-button.tsx
374
402
  import { useState as useState3 } from "react";
375
403
 
376
404
  // src/react/elvix-shield.tsx
405
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
377
406
  function ElvixShield({
378
407
  size,
379
408
  fill,
380
409
  accent
381
410
  }) {
382
- return /* @__PURE__ */ React.createElement("svg", { width: size, height: size, viewBox: "2 2 20 20", "aria-hidden": true, style: { display: "block" } }, /* @__PURE__ */ React.createElement(
383
- "path",
384
- {
385
- fill,
386
- fillRule: "evenodd",
387
- d: "M 6 2.5 C 4.34 2.5 3 3.84 3 5.5 L 3 12.5 C 3 17.5 7 20.7 12 22 C 17 20.7 21 17.5 21 12.5 L 21 5.5 C 21 3.84 19.66 2.5 18 2.5 L 6 2.5 Z M 12 8.4 C 9.79 8.4 8 10.19 8 12.4 C 8 14.61 9.79 16.4 12 16.4 C 13.21 16.4 14.3 15.86 15.04 15 L 13.6 13.77 C 13.21 14.23 12.64 14.5 12 14.5 C 11.04 14.5 10.21 13.86 9.91 13 L 15.95 13 C 15.98 12.8 16 12.6 16 12.4 C 16 10.19 14.21 8.4 12 8.4 Z M 9.91 11.8 L 14.09 11.8 C 13.79 10.94 12.96 10.3 12 10.3 C 11.04 10.3 10.21 10.94 9.91 11.8 Z"
388
- }
389
- ), /* @__PURE__ */ React.createElement("circle", { cx: "19.5", cy: "4.5", r: "2.4", fill: accent }));
411
+ return /* @__PURE__ */ jsxs3("svg", { width: size, height: size, viewBox: "2 2 20 20", "aria-hidden": true, style: { display: "block" }, children: [
412
+ /* @__PURE__ */ jsx4(
413
+ "path",
414
+ {
415
+ fill,
416
+ fillRule: "evenodd",
417
+ d: "M 6 2.5 C 4.34 2.5 3 3.84 3 5.5 L 3 12.5 C 3 17.5 7 20.7 12 22 C 17 20.7 21 17.5 21 12.5 L 21 5.5 C 21 3.84 19.66 2.5 18 2.5 L 6 2.5 Z M 12 8.4 C 9.79 8.4 8 10.19 8 12.4 C 8 14.61 9.79 16.4 12 16.4 C 13.21 16.4 14.3 15.86 15.04 15 L 13.6 13.77 C 13.21 14.23 12.64 14.5 12 14.5 C 11.04 14.5 10.21 13.86 9.91 13 L 15.95 13 C 15.98 12.8 16 12.6 16 12.4 C 16 10.19 14.21 8.4 12 8.4 Z M 9.91 11.8 L 14.09 11.8 C 13.79 10.94 12.96 10.3 12 10.3 C 11.04 10.3 10.21 10.94 9.91 11.8 Z"
418
+ }
419
+ ),
420
+ /* @__PURE__ */ jsx4("circle", { cx: "19.5", cy: "4.5", r: "2.4", fill: accent })
421
+ ] });
390
422
  }
391
423
 
392
424
  // src/react/elvix-sign-in-button.tsx
425
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
393
426
  var ELVIX_URL = "https://elvix.is";
394
427
  var PRESET_LABEL = {
395
428
  "sign-in-with-elvix": "Sign in with elvix",
@@ -467,29 +500,35 @@ function ElvixSignInButton({
467
500
  transition: "background 0.15s, border-color 0.15s",
468
501
  ...isIcon ? { height: SIZE_ICON[size], width: SIZE_ICON[size] } : { height: std.height, paddingLeft: std.padX, paddingRight: std.padX, gap: std.gap }
469
502
  };
470
- const content = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ElvixShield, { size: ICON_SIZE[size], fill: shieldColor(variant, theme), accent: "#8e7dff" }), isIcon ? null : /* @__PURE__ */ React.createElement("span", null, resolvedLabel));
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 })
506
+ ] });
471
507
  if (mode === "callback") {
472
- return /* @__PURE__ */ React.createElement("button", { type: "button", onClick, className, style, "aria-label": isIcon ? resolvedLabel : void 0 }, content);
508
+ return /* @__PURE__ */ jsx5("button", { type: "button", onClick, className, style, "aria-label": isIcon ? resolvedLabel : void 0, children: content });
473
509
  }
474
510
  if (mode === "embed") {
475
- return /* @__PURE__ */ React.createElement("div", { "data-elvix-signin-button-embed": "" }, !embedOpen && /* @__PURE__ */ React.createElement(
476
- "button",
477
- {
478
- type: "button",
479
- onClick: () => setEmbedOpen(true),
480
- className,
481
- style,
482
- "aria-label": isIcon ? resolvedLabel : void 0
483
- },
484
- content
485
- ), embedOpen && /* @__PURE__ */ React.createElement(
486
- ElvixSignIn,
487
- {
488
- onResult: (r) => {
489
- onResult?.(r);
511
+ return /* @__PURE__ */ jsxs4("div", { "data-elvix-signin-button-embed": "", children: [
512
+ !embedOpen && /* @__PURE__ */ jsx5(
513
+ "button",
514
+ {
515
+ type: "button",
516
+ onClick: () => setEmbedOpen(true),
517
+ className,
518
+ style,
519
+ "aria-label": isIcon ? resolvedLabel : void 0,
520
+ children: content
490
521
  }
491
- }
492
- ));
522
+ ),
523
+ embedOpen && /* @__PURE__ */ jsx5(
524
+ ElvixSignIn,
525
+ {
526
+ onResult: (r) => {
527
+ onResult?.(r);
528
+ }
529
+ }
530
+ )
531
+ ] });
493
532
  }
494
533
  const destination = (() => {
495
534
  if (href) return href;
@@ -498,10 +537,11 @@ function ElvixSignInButton({
498
537
  const sep = base.includes("?") ? "&" : "?";
499
538
  return `${base}${sep}return=${encodeURIComponent(returnUrl)}`;
500
539
  })();
501
- return /* @__PURE__ */ React.createElement("a", { href: destination, className, style, "aria-label": isIcon ? resolvedLabel : void 0 }, content);
540
+ return /* @__PURE__ */ jsx5("a", { href: destination, className, style, "aria-label": isIcon ? resolvedLabel : void 0, children: content });
502
541
  }
503
542
 
504
543
  // src/react/elvix-secured-badge.tsx
544
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
505
545
  var ELVIX_URL2 = "https://elvix.is";
506
546
  var SIZE = {
507
547
  sm: { height: 28, padX: 10, font: 11.5, icon: 14, gap: 6 },
@@ -549,7 +589,7 @@ function ElvixSecuredBadge({
549
589
  userSelect: "none",
550
590
  lineHeight: 1
551
591
  };
552
- return /* @__PURE__ */ React.createElement(
592
+ return /* @__PURE__ */ jsxs5(
553
593
  "a",
554
594
  {
555
595
  href,
@@ -557,10 +597,15 @@ function ElvixSecuredBadge({
557
597
  rel: "noopener noreferrer",
558
598
  className,
559
599
  style,
560
- "data-elvix-secured-badge": ""
561
- },
562
- /* @__PURE__ */ React.createElement(ElvixShield, { size: s.icon, fill: t.shield, accent: accentColor }),
563
- /* @__PURE__ */ React.createElement("span", { style: { display: "inline-flex", alignItems: "baseline", gap: 4 } }, /* @__PURE__ */ React.createElement("span", { style: { color: t.lead } }, "Secured by"), /* @__PURE__ */ React.createElement("span", { style: { color: t.brand, fontWeight: 600 } }, "elvix"))
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
+ }
564
609
  );
565
610
  }
566
611
 
@@ -696,6 +741,7 @@ async function appDelete(opts, path) {
696
741
  }
697
742
 
698
743
  // src/react/elvix-username.tsx
744
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
699
745
  function ElvixUsername({
700
746
  onResult
701
747
  }) {
@@ -723,25 +769,37 @@ function ElvixUsername({
723
769
  onResult?.(result);
724
770
  }
725
771
  if (done) {
726
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Username saved" }, /* @__PURE__ */ React.createElement("p", null, "You are now ", /* @__PURE__ */ React.createElement("strong", null, "@", done), "."));
772
+ return /* @__PURE__ */ jsx7(ElvixCard, { title: "Username saved", children: /* @__PURE__ */ jsxs6("p", { children: [
773
+ "You are now ",
774
+ /* @__PURE__ */ jsxs6("strong", { children: [
775
+ "@",
776
+ done
777
+ ] }),
778
+ "."
779
+ ] }) });
727
780
  }
728
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Choose a username" }, /* @__PURE__ */ React.createElement("form", { onSubmit: submit, className: "elvix-form" }, /* @__PURE__ */ React.createElement(
729
- "input",
730
- {
731
- type: "text",
732
- value,
733
- onChange: (e) => setValue(e.target.value.toLowerCase()),
734
- placeholder: "alice",
735
- pattern: "[a-z][a-z0-9._]{2,28}[a-z0-9]",
736
- required: true,
737
- disabled: busy,
738
- className: "elvix-input"
739
- }
740
- ), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy || value.length < 4, className: "elvix-btn elvix-btn-primary" }, busy ? "Saving\u2026" : "Claim"), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error)));
781
+ return /* @__PURE__ */ jsx7(ElvixCard, { title: "Choose a username", children: /* @__PURE__ */ jsxs6("form", { onSubmit: submit, className: "elvix-form", children: [
782
+ /* @__PURE__ */ jsx7(
783
+ "input",
784
+ {
785
+ type: "text",
786
+ value,
787
+ onChange: (e) => setValue(e.target.value.toLowerCase()),
788
+ placeholder: "alice",
789
+ pattern: "[a-z][a-z0-9._]{2,28}[a-z0-9]",
790
+ required: true,
791
+ disabled: busy,
792
+ className: "elvix-input"
793
+ }
794
+ ),
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 })
797
+ ] }) });
741
798
  }
742
799
 
743
800
  // src/react/elvix-avatar.tsx
744
801
  import { useState as useState6 } from "react";
802
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
745
803
  function ElvixAvatar({
746
804
  onResult
747
805
  }) {
@@ -771,18 +829,24 @@ function ElvixAvatar({
771
829
  if (!result.ok) setError(result.error);
772
830
  onResult?.(result);
773
831
  }
774
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Avatar" }, preview && /* @__PURE__ */ React.createElement(
775
- "img",
776
- {
777
- src: preview,
778
- alt: "avatar preview",
779
- style: { width: 96, height: 96, borderRadius: "50%", objectFit: "cover", marginBottom: 12 }
780
- }
781
- ), /* @__PURE__ */ React.createElement("input", { type: "file", accept: "image/png,image/jpeg,image/webp", onChange: onFile, disabled: busy }), busy && /* @__PURE__ */ React.createElement("p", null, "Uploading\u2026"), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error));
832
+ return /* @__PURE__ */ jsxs7(ElvixCard, { title: "Avatar", children: [
833
+ preview && /* @__PURE__ */ jsx8(
834
+ "img",
835
+ {
836
+ src: preview,
837
+ alt: "avatar preview",
838
+ style: { width: 96, height: 96, borderRadius: "50%", objectFit: "cover", marginBottom: 12 }
839
+ }
840
+ ),
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 })
844
+ ] });
782
845
  }
783
846
 
784
847
  // src/react/elvix-banner.tsx
785
848
  import { useState as useState7 } from "react";
849
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
786
850
  function ElvixBanner({
787
851
  onResult
788
852
  }) {
@@ -812,18 +876,24 @@ function ElvixBanner({
812
876
  if (!result.ok) setError(result.error);
813
877
  onResult?.(result);
814
878
  }
815
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Banner" }, preview && /* @__PURE__ */ React.createElement(
816
- "img",
817
- {
818
- src: preview,
819
- alt: "banner preview",
820
- style: { width: "100%", aspectRatio: "16/9", objectFit: "cover", borderRadius: 10, marginBottom: 12 }
821
- }
822
- ), /* @__PURE__ */ React.createElement("input", { type: "file", accept: "image/png,image/jpeg,image/webp", onChange: onFile, disabled: busy }), busy && /* @__PURE__ */ React.createElement("p", null, "Uploading\u2026"), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error));
879
+ return /* @__PURE__ */ jsxs8(ElvixCard, { title: "Banner", children: [
880
+ preview && /* @__PURE__ */ jsx9(
881
+ "img",
882
+ {
883
+ src: preview,
884
+ alt: "banner preview",
885
+ style: { width: "100%", aspectRatio: "16/9", objectFit: "cover", borderRadius: 10, marginBottom: 12 }
886
+ }
887
+ ),
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 })
891
+ ] });
823
892
  }
824
893
 
825
894
  // src/react/elvix-identity-form.tsx
826
895
  import { useState as useState8 } from "react";
896
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
827
897
  function ElvixIdentityForm({
828
898
  initialName = "",
829
899
  initialBio = "",
@@ -850,11 +920,24 @@ function ElvixIdentityForm({
850
920
  else setSaved(true);
851
921
  onResult?.(result);
852
922
  }
853
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Identity" }, /* @__PURE__ */ React.createElement("form", { onSubmit: submit, className: "elvix-form" }, /* @__PURE__ */ React.createElement("label", null, "Name", /* @__PURE__ */ React.createElement("input", { value: name, onChange: (e) => setName(e.target.value), maxLength: 80, disabled: busy, className: "elvix-input" })), /* @__PURE__ */ React.createElement("label", null, "Bio", /* @__PURE__ */ React.createElement("textarea", { value: bio, onChange: (e) => setBio(e.target.value), maxLength: 500, rows: 3, disabled: busy, className: "elvix-input" })), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ? "Saving\u2026" : "Save"), saved && /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, "Saved."), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error)));
923
+ return /* @__PURE__ */ jsx10(ElvixCard, { title: "Identity", children: /* @__PURE__ */ jsxs9("form", { onSubmit: submit, className: "elvix-form", children: [
924
+ /* @__PURE__ */ jsxs9("label", { children: [
925
+ "Name",
926
+ /* @__PURE__ */ jsx10("input", { value: name, onChange: (e) => setName(e.target.value), maxLength: 80, disabled: busy, className: "elvix-input" })
927
+ ] }),
928
+ /* @__PURE__ */ jsxs9("label", { children: [
929
+ "Bio",
930
+ /* @__PURE__ */ jsx10("textarea", { value: bio, onChange: (e) => setBio(e.target.value), maxLength: 500, rows: 3, disabled: busy, className: "elvix-input" })
931
+ ] }),
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 })
935
+ ] }) });
854
936
  }
855
937
 
856
938
  // src/react/elvix-region.tsx
857
939
  import { useState as useState9 } from "react";
940
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
858
941
  function ElvixRegion({
859
942
  initialCountry = "",
860
943
  initialTimezone = "",
@@ -881,11 +964,24 @@ function ElvixRegion({
881
964
  else setSaved(true);
882
965
  onResult?.(result);
883
966
  }
884
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Region" }, /* @__PURE__ */ React.createElement("form", { onSubmit: submit, className: "elvix-form" }, /* @__PURE__ */ React.createElement("label", null, "Country (ISO-2)", /* @__PURE__ */ React.createElement("input", { value: country, onChange: (e) => setCountry(e.target.value.toUpperCase()), maxLength: 2, pattern: "[A-Z]{2}", disabled: busy, className: "elvix-input" })), /* @__PURE__ */ React.createElement("label", null, "Timezone", /* @__PURE__ */ React.createElement("input", { value: timezone, onChange: (e) => setTimezone(e.target.value), placeholder: "Europe/Berlin", disabled: busy, className: "elvix-input" })), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ? "Saving\u2026" : "Save"), saved && /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, "Saved."), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error)));
967
+ return /* @__PURE__ */ jsx11(ElvixCard, { title: "Region", children: /* @__PURE__ */ jsxs10("form", { onSubmit: submit, className: "elvix-form", children: [
968
+ /* @__PURE__ */ jsxs10("label", { children: [
969
+ "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" })
971
+ ] }),
972
+ /* @__PURE__ */ jsxs10("label", { children: [
973
+ "Timezone",
974
+ /* @__PURE__ */ jsx11("input", { value: timezone, onChange: (e) => setTimezone(e.target.value), placeholder: "Europe/Berlin", disabled: busy, className: "elvix-input" })
975
+ ] }),
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 })
979
+ ] }) });
885
980
  }
886
981
 
887
982
  // src/react/elvix-languages.tsx
888
983
  import { useState as useState10 } from "react";
984
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
889
985
  function ElvixLanguages({
890
986
  initial = [],
891
987
  onResult
@@ -911,11 +1007,20 @@ function ElvixLanguages({
911
1007
  else setSaved(true);
912
1008
  onResult?.(result);
913
1009
  }
914
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Languages" }, /* @__PURE__ */ React.createElement("form", { onSubmit: submit, className: "elvix-form" }, /* @__PURE__ */ React.createElement("label", null, "Preferred languages (comma-separated BCP-47 tags)", /* @__PURE__ */ React.createElement("input", { value: raw, onChange: (e) => setRaw(e.target.value), placeholder: "en-GB, de-DE", disabled: busy, className: "elvix-input" })), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ? "Saving\u2026" : "Save"), saved && /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, "Saved."), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error)));
1010
+ return /* @__PURE__ */ jsx12(ElvixCard, { title: "Languages", children: /* @__PURE__ */ jsxs11("form", { onSubmit: submit, className: "elvix-form", children: [
1011
+ /* @__PURE__ */ jsxs11("label", { children: [
1012
+ "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" })
1014
+ ] }),
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 })
1018
+ ] }) });
915
1019
  }
916
1020
 
917
1021
  // src/react/elvix-sessions.tsx
918
1022
  import { useEffect as useEffect4, useState as useState11 } from "react";
1023
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
919
1024
  function ElvixSessions({
920
1025
  onResult
921
1026
  }) {
@@ -943,11 +1048,29 @@ function ElvixSessions({
943
1048
  if (result.ok) setRows((prev) => prev?.filter((s) => s.id !== id) ?? null);
944
1049
  onResult?.(result);
945
1050
  }
946
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Active sessions" }, error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error), !rows && !error && /* @__PURE__ */ React.createElement("p", null, "Loading\u2026"), rows && /* @__PURE__ */ React.createElement("ul", { style: { listStyle: "none", padding: 0, margin: 0 } }, rows.map((s) => /* @__PURE__ */ React.createElement("li", { key: s.id, style: { padding: "10px 0", borderBottom: "1px solid rgba(0,0,0,0.06)" } }, /* @__PURE__ */ React.createElement("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 } }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { style: { fontSize: 13, fontWeight: 500 } }, s.device, s.current && /* @__PURE__ */ React.createElement("span", { style: { marginLeft: 8, color: "var(--elvix-primary-strong)", fontSize: 11 } }, "\xB7 this device")), /* @__PURE__ */ React.createElement("div", { style: { fontSize: 11, color: "rgba(0,0,0,0.55)" } }, s.country ?? "\u2014", " \xB7 since ", new Date(s.createdAt).toLocaleDateString())), !s.current && /* @__PURE__ */ React.createElement("button", { type: "button", disabled: busy, onClick: () => revoke(s.id), className: "elvix-btn elvix-btn-ghost" }, "Revoke"))))));
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: [
1057
+ s.device,
1058
+ s.current && /* @__PURE__ */ jsx13("span", { style: { marginLeft: 8, color: "var(--elvix-primary-strong)", fontSize: 11 }, children: "\xB7 this device" })
1059
+ ] }),
1060
+ /* @__PURE__ */ jsxs12("div", { style: { fontSize: 11, color: "rgba(0,0,0,0.55)" }, children: [
1061
+ s.country ?? "\u2014",
1062
+ " \xB7 since ",
1063
+ new Date(s.createdAt).toLocaleDateString()
1064
+ ] })
1065
+ ] }),
1066
+ !s.current && /* @__PURE__ */ jsx13("button", { type: "button", disabled: busy, onClick: () => revoke(s.id), className: "elvix-btn elvix-btn-ghost", children: "Revoke" })
1067
+ ] }) }, s.id)) })
1068
+ ] });
947
1069
  }
948
1070
 
949
1071
  // src/react/elvix-export.tsx
950
1072
  import { useState as useState12 } from "react";
1073
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
951
1074
  function ElvixExport({
952
1075
  onResult
953
1076
  }) {
@@ -969,11 +1092,16 @@ function ElvixExport({
969
1092
  else setDone(true);
970
1093
  onResult?.(result);
971
1094
  }
972
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Export my data" }, /* @__PURE__ */ React.createElement("p", { style: { fontSize: 13, color: "rgba(0,0,0,0.6)" } }, "Request a zip of every record we hold for you in this app. Delivery by email; single-use download link valid for 24h."), done ? /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, "Request queued. Check your email.") : /* @__PURE__ */ React.createElement("button", { type: "button", onClick: start, disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ? "Queuing\u2026" : "Request export"), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error));
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 })
1099
+ ] });
973
1100
  }
974
1101
 
975
1102
  // src/react/elvix-deactivate.tsx
976
1103
  import { useState as useState13 } from "react";
1104
+ import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
977
1105
  function ElvixDeactivate({
978
1106
  onResult
979
1107
  }) {
@@ -1020,26 +1148,38 @@ function ElvixDeactivate({
1020
1148
  onResult?.(result);
1021
1149
  }
1022
1150
  if (pane === "done") {
1023
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Deactivated" }, /* @__PURE__ */ React.createElement("p", null, "Your access has been paused. Sign in again to restore it."));
1151
+ return /* @__PURE__ */ jsx15(ElvixCard, { title: "Deactivated", children: /* @__PURE__ */ jsx15("p", { children: "Your access has been paused. Sign in again to restore it." }) });
1024
1152
  }
1025
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Deactivate account" }, pane === "warn" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("p", { style: { fontSize: 13, color: "rgba(0,0,0,0.6)" } }, "Pause your membership. You can restore it any time by signing in again. No data is deleted."), /* @__PURE__ */ React.createElement("button", { type: "button", onClick: startChallenge, disabled: busy, className: "elvix-btn elvix-btn-danger" }, busy ? "Sending\u2026" : "Send code")), pane === "otp" && /* @__PURE__ */ React.createElement("form", { onSubmit: confirm, className: "elvix-form" }, /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, "We sent a 6-digit code to your email."), /* @__PURE__ */ React.createElement(
1026
- "input",
1027
- {
1028
- type: "text",
1029
- inputMode: "numeric",
1030
- pattern: "[0-9]*",
1031
- maxLength: 6,
1032
- value: code,
1033
- onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
1034
- required: true,
1035
- disabled: busy,
1036
- className: "elvix-input"
1037
- }
1038
- ), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy || code.length !== 6, className: "elvix-btn elvix-btn-danger" }, busy ? "Deactivating\u2026" : "Confirm")), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error));
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" })
1157
+ ] }),
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(
1161
+ "input",
1162
+ {
1163
+ type: "text",
1164
+ inputMode: "numeric",
1165
+ pattern: "[0-9]*",
1166
+ maxLength: 6,
1167
+ value: code,
1168
+ onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
1169
+ required: true,
1170
+ disabled: busy,
1171
+ className: "elvix-input"
1172
+ }
1173
+ ),
1174
+ /* @__PURE__ */ jsx15("button", { type: "submit", disabled: busy || code.length !== 6, className: "elvix-btn elvix-btn-danger", children: busy ? "Deactivating\u2026" : "Confirm" })
1175
+ ] }),
1176
+ error && /* @__PURE__ */ jsx15("p", { role: "alert", className: "elvix-error", children: error })
1177
+ ] });
1039
1178
  }
1040
1179
 
1041
1180
  // src/react/elvix-leave.tsx
1042
1181
  import { useState as useState14 } from "react";
1182
+ import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
1043
1183
  function ElvixLeave({
1044
1184
  onResult
1045
1185
  }) {
@@ -1086,26 +1226,38 @@ function ElvixLeave({
1086
1226
  onResult?.(result);
1087
1227
  }
1088
1228
  if (pane === "done") {
1089
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "You've left" }, /* @__PURE__ */ React.createElement("p", null, "You've left this app. Your data is archived; sign in again to rejoin."));
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." }) });
1090
1230
  }
1091
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Leave this app" }, pane === "warn" && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("p", { style: { fontSize: 13, color: "rgba(0,0,0,0.6)" } }, "Remove yourself from this app. Audit trail is preserved; you can sign back in any time to rejoin."), /* @__PURE__ */ React.createElement("button", { type: "button", onClick: startChallenge, disabled: busy, className: "elvix-btn elvix-btn-danger" }, busy ? "Sending\u2026" : "Send code")), pane === "otp" && /* @__PURE__ */ React.createElement("form", { onSubmit: confirm, className: "elvix-form" }, /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, "We sent a 6-digit code to your email."), /* @__PURE__ */ React.createElement(
1092
- "input",
1093
- {
1094
- type: "text",
1095
- inputMode: "numeric",
1096
- pattern: "[0-9]*",
1097
- maxLength: 6,
1098
- value: code,
1099
- onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
1100
- required: true,
1101
- disabled: busy,
1102
- className: "elvix-input"
1103
- }
1104
- ), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy || code.length !== 6, className: "elvix-btn elvix-btn-danger" }, busy ? "Leaving\u2026" : "Confirm leave")), error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error));
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" })
1235
+ ] }),
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(
1239
+ "input",
1240
+ {
1241
+ type: "text",
1242
+ inputMode: "numeric",
1243
+ pattern: "[0-9]*",
1244
+ maxLength: 6,
1245
+ value: code,
1246
+ onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
1247
+ required: true,
1248
+ disabled: busy,
1249
+ className: "elvix-input"
1250
+ }
1251
+ ),
1252
+ /* @__PURE__ */ jsx16("button", { type: "submit", disabled: busy || code.length !== 6, className: "elvix-btn elvix-btn-danger", children: busy ? "Leaving\u2026" : "Confirm leave" })
1253
+ ] }),
1254
+ error && /* @__PURE__ */ jsx16("p", { role: "alert", className: "elvix-error", children: error })
1255
+ ] });
1105
1256
  }
1106
1257
 
1107
1258
  // src/react/elvix-address-book.tsx
1108
1259
  import { useEffect as useEffect5, useState as useState15 } from "react";
1260
+ import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
1109
1261
  function ElvixAddressBook({
1110
1262
  onResult
1111
1263
  }) {
@@ -1163,11 +1315,41 @@ function ElvixAddressBook({
1163
1315
  if (result.ok) setRows((prev) => prev?.filter((a) => a.id !== id) ?? null);
1164
1316
  onResult?.(result);
1165
1317
  }
1166
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Addresses" }, error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error), !rows && !error && /* @__PURE__ */ React.createElement("p", null, "Loading\u2026"), rows && rows.length === 0 && /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, "No addresses yet."), rows?.map((a) => /* @__PURE__ */ React.createElement("div", { key: a.id, style: { padding: "8px 0", borderBottom: "1px solid rgba(0,0,0,0.06)", display: "flex", justifyContent: "space-between", gap: 12 } }, /* @__PURE__ */ React.createElement("div", { style: { fontSize: 13 } }, /* @__PURE__ */ React.createElement("div", { style: { fontWeight: 500 } }, a.label), /* @__PURE__ */ React.createElement("div", { style: { color: "rgba(0,0,0,0.55)" } }, a.line1, a.line2 ? `, ${a.line2}` : "", ", ", a.postalCode, " ", a.city, ", ", a.country)), /* @__PURE__ */ React.createElement("button", { type: "button", disabled: busy, onClick: () => remove(a.id), className: "elvix-btn elvix-btn-ghost" }, "Remove"))), !adding && /* @__PURE__ */ React.createElement("button", { type: "button", onClick: () => setAdding(true), className: "elvix-btn elvix-btn-primary", style: { marginTop: 12 } }, "Add address"), adding && /* @__PURE__ */ React.createElement("form", { onSubmit: add, className: "elvix-form", style: { marginTop: 12 } }, /* @__PURE__ */ React.createElement("input", { value: form.label, onChange: (e) => setForm({ ...form, label: e.target.value }), placeholder: "Label", className: "elvix-input" }), /* @__PURE__ */ React.createElement("input", { value: form.line1, onChange: (e) => setForm({ ...form, line1: e.target.value }), placeholder: "Street", required: true, className: "elvix-input" }), /* @__PURE__ */ React.createElement("input", { value: form.postalCode, onChange: (e) => setForm({ ...form, postalCode: e.target.value }), placeholder: "Postal code", required: true, className: "elvix-input" }), /* @__PURE__ */ React.createElement("input", { value: form.city, onChange: (e) => setForm({ ...form, city: e.target.value }), placeholder: "City", required: true, className: "elvix-input" }), /* @__PURE__ */ React.createElement("input", { value: form.country, onChange: (e) => setForm({ ...form, country: e.target.value.toUpperCase() }), placeholder: "Country (ISO-2)", maxLength: 2, required: true, className: "elvix-input" }), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ? "Saving\u2026" : "Save")));
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: [
1326
+ a.line1,
1327
+ a.line2 ? `, ${a.line2}` : "",
1328
+ ", ",
1329
+ a.postalCode,
1330
+ " ",
1331
+ a.city,
1332
+ ", ",
1333
+ a.country
1334
+ ] })
1335
+ ] }),
1336
+ /* @__PURE__ */ jsx17("button", { type: "button", disabled: busy, onClick: () => remove(a.id), className: "elvix-btn elvix-btn-ghost", children: "Remove" })
1337
+ ] }, 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" })
1346
+ ] })
1347
+ ] });
1167
1348
  }
1168
1349
 
1169
1350
  // src/react/elvix-legal-entities.tsx
1170
1351
  import { useEffect as useEffect6, useState as useState16 } from "react";
1352
+ import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
1171
1353
  function ElvixLegalEntities({
1172
1354
  onResult
1173
1355
  }) {
@@ -1223,7 +1405,29 @@ function ElvixLegalEntities({
1223
1405
  if (result.ok) setRows((prev) => prev?.filter((a) => a.id !== id) ?? null);
1224
1406
  onResult?.(result);
1225
1407
  }
1226
- return /* @__PURE__ */ React.createElement(ElvixCard, { title: "Legal entities" }, error && /* @__PURE__ */ React.createElement("p", { role: "alert", className: "elvix-error" }, error), !rows && !error && /* @__PURE__ */ React.createElement("p", null, "Loading\u2026"), rows && rows.length === 0 && /* @__PURE__ */ React.createElement("p", { className: "elvix-muted" }, "No legal entities yet."), rows?.map((e) => /* @__PURE__ */ React.createElement("div", { key: e.id, style: { padding: "8px 0", borderBottom: "1px solid rgba(0,0,0,0.06)", display: "flex", justifyContent: "space-between", gap: 12 } }, /* @__PURE__ */ React.createElement("div", { style: { fontSize: 13 } }, /* @__PURE__ */ React.createElement("div", { style: { fontWeight: 500 } }, e.legalName), /* @__PURE__ */ React.createElement("div", { style: { color: "rgba(0,0,0,0.55)" } }, e.taxId, " \xB7 ", e.country)), /* @__PURE__ */ React.createElement("button", { type: "button", disabled: busy, onClick: () => remove(e.id), className: "elvix-btn elvix-btn-ghost" }, "Remove"))), !adding && /* @__PURE__ */ React.createElement("button", { type: "button", onClick: () => setAdding(true), className: "elvix-btn elvix-btn-primary", style: { marginTop: 12 } }, "Add entity"), adding && /* @__PURE__ */ React.createElement("form", { onSubmit: add, className: "elvix-form", style: { marginTop: 12 } }, /* @__PURE__ */ React.createElement("input", { value: form.legalName, onChange: (e) => setForm({ ...form, legalName: e.target.value }), placeholder: "Legal name", required: true, className: "elvix-input" }), /* @__PURE__ */ React.createElement("input", { value: form.taxId, onChange: (e) => setForm({ ...form, taxId: e.target.value }), placeholder: "Tax / VAT ID", required: true, className: "elvix-input" }), /* @__PURE__ */ React.createElement("input", { value: form.country, onChange: (e) => setForm({ ...form, country: e.target.value.toUpperCase() }), placeholder: "Country (ISO-2)", maxLength: 2, required: true, className: "elvix-input" }), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ? "Saving\u2026" : "Save")));
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: [
1416
+ e.taxId,
1417
+ " \xB7 ",
1418
+ e.country
1419
+ ] })
1420
+ ] }),
1421
+ /* @__PURE__ */ jsx18("button", { type: "button", disabled: busy, onClick: () => remove(e.id), className: "elvix-btn elvix-btn-ghost", children: "Remove" })
1422
+ ] }, 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" })
1429
+ ] })
1430
+ ] });
1227
1431
  }
1228
1432
  export {
1229
1433
  DEFAULT_COPY,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elvix.is/sdk",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "Official elvix SDK. Drop-in React components, server helpers, and an MCP server so AI coding agents integrate elvix on the first try.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://elvix.is",
@@ -52,7 +52,7 @@
52
52
  "LICENSE"
53
53
  ],
54
54
  "scripts": {
55
- "build": "tsup src/index.ts src/react.ts src/server.ts src/types.ts src/mcp/index.ts src/mcp/bin.ts src/cli/index.ts src/cli/doctor.ts --format esm --dts --clean --external react --external next",
55
+ "build": "tsup src/index.ts src/react.ts src/server.ts src/types.ts src/mcp/index.ts src/mcp/bin.ts src/cli/index.ts src/cli/doctor.ts --format esm --dts --clean --external react --external react/jsx-runtime --external next && node scripts/postbuild.mjs",
56
56
  "typecheck": "tsc --noEmit",
57
57
  "test": "vitest run"
58
58
  },