@elvix.is/sdk 0.5.1 → 0.5.2
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 +106 -2
- package/dist/react.js +313 -75
- package/package.json +1 -1
package/dist/react.d.ts
CHANGED
|
@@ -20,11 +20,59 @@ declare function ElvixCard({ title, footer, className, children, }: {
|
|
|
20
20
|
children: ReactNode;
|
|
21
21
|
}): react.JSX.Element;
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Editable sign-in copy.
|
|
25
|
+
*
|
|
26
|
+
* Every user-facing string in the sign-in surface is overridable. Precedence,
|
|
27
|
+
* lowest to highest:
|
|
28
|
+
*
|
|
29
|
+
* built-in English defaults < Console-configured (bootstrap `strings`) < `copy` prop
|
|
30
|
+
*
|
|
31
|
+
* So an integrating developer edits copy in the elvix Console (no redeploy) and
|
|
32
|
+
* can still override per-embed in code. `title` and `submitButton` are left out
|
|
33
|
+
* of the defaults because their built-in value depends on the Application's
|
|
34
|
+
* sign-in verb ("Sign in" vs "Log in"); the component fills them from the verb
|
|
35
|
+
* when neither Console nor prop sets them.
|
|
36
|
+
*
|
|
37
|
+
* Strings may contain `{app}` / `{email}` tokens; `fillCopy` interpolates them.
|
|
38
|
+
*/
|
|
39
|
+
type ElvixCopy = {
|
|
40
|
+
/** Heading. Token: {app}. Built-in: "Sign in to {app}" / "Log in to {app}". */
|
|
41
|
+
title?: string;
|
|
42
|
+
/** Subtitle under the heading. */
|
|
43
|
+
subtitle?: string;
|
|
44
|
+
/** Google factor button. */
|
|
45
|
+
googleButton?: string;
|
|
46
|
+
/** Email field placeholder. */
|
|
47
|
+
emailPlaceholder?: string;
|
|
48
|
+
/** Email submit button (identify step). */
|
|
49
|
+
sendCodeButton?: string;
|
|
50
|
+
/** Email submit button while the request is in flight. */
|
|
51
|
+
sendingLabel?: string;
|
|
52
|
+
/** Code step subtitle. Token: {email}. */
|
|
53
|
+
codeSentSubtitle?: string;
|
|
54
|
+
/** OTP field placeholder. */
|
|
55
|
+
codePlaceholder?: string;
|
|
56
|
+
/** OTP submit button. Built-in: the sign-in verb. */
|
|
57
|
+
submitButton?: string;
|
|
58
|
+
/** OTP submit button while verifying. */
|
|
59
|
+
verifyingLabel?: string;
|
|
60
|
+
/** Terminal "done" pane text. */
|
|
61
|
+
signedInText?: string;
|
|
62
|
+
/** Validation: empty email. */
|
|
63
|
+
errorEnterEmail?: string;
|
|
64
|
+
/** Validation: code not 6 digits. */
|
|
65
|
+
errorEnterCode?: string;
|
|
66
|
+
};
|
|
67
|
+
/** Built-in English defaults for the verb-independent strings. */
|
|
68
|
+
declare const DEFAULT_COPY: ElvixCopy;
|
|
69
|
+
|
|
23
70
|
/**
|
|
24
71
|
* Public types for the React surface. Mirrors the elvix.is bootstrap
|
|
25
72
|
* envelope so customers can type their host code without importing
|
|
26
73
|
* private elvix internals.
|
|
27
74
|
*/
|
|
75
|
+
|
|
28
76
|
type ElvixBrand = {
|
|
29
77
|
light: {
|
|
30
78
|
primary: string;
|
|
@@ -60,6 +108,12 @@ type ElvixBootstrapEnvelope = {
|
|
|
60
108
|
};
|
|
61
109
|
signInVerb: "signin" | "login";
|
|
62
110
|
signinGate: "public" | "private_beta" | "closed";
|
|
111
|
+
/**
|
|
112
|
+
* Console-configured sign-in copy overrides. Any subset of the strings the
|
|
113
|
+
* sign-in surface renders; missing keys fall back to the built-in English
|
|
114
|
+
* defaults. A `copy` prop on the component overrides these in turn.
|
|
115
|
+
*/
|
|
116
|
+
strings?: Partial<ElvixCopy>;
|
|
63
117
|
};
|
|
64
118
|
type ElvixSignInResultOk = {
|
|
65
119
|
ok: true;
|
|
@@ -119,13 +173,63 @@ declare function ElvixProvider({ clientId, theme, brand, baseUrl, children, clas
|
|
|
119
173
|
* exposes. Hosts navigate from the callback; this component never
|
|
120
174
|
* calls `router.push` itself.
|
|
121
175
|
*/
|
|
122
|
-
declare function ElvixSignIn({ onResult, redirectAfterSignIn, className, }: {
|
|
176
|
+
declare function ElvixSignIn({ onResult, redirectAfterSignIn, copy: copyProp, className, }: {
|
|
123
177
|
onResult?: (r: ElvixSignInResult) => void;
|
|
124
178
|
/** Default redirect target on success when the server doesn't echo one. */
|
|
125
179
|
redirectAfterSignIn?: string;
|
|
180
|
+
/**
|
|
181
|
+
* Thin per-embed copy override. The primary way to edit copy is the elvix
|
|
182
|
+
* Console (served live in the bootstrap `strings`); this prop just lets a
|
|
183
|
+
* single embed tweak a string or two without a Console change.
|
|
184
|
+
*/
|
|
185
|
+
copy?: Partial<ElvixCopy>;
|
|
126
186
|
className?: string;
|
|
127
187
|
}): react.JSX.Element;
|
|
128
188
|
|
|
189
|
+
type ElvixSignInButtonSize = "sm" | "md" | "lg";
|
|
190
|
+
type ElvixSignInButtonTheme = "light" | "dark" | "auto";
|
|
191
|
+
type ElvixSignInButtonVariant = "filled" | "filled-black" | "white" | "outline" | "ghost";
|
|
192
|
+
type ElvixSignInButtonShape = "rectangle" | "pill" | "square" | "circle";
|
|
193
|
+
type ElvixSignInButtonType = "standard" | "icon";
|
|
194
|
+
type ElvixSignInButtonMode = "redirect" | "callback" | "embed";
|
|
195
|
+
type ElvixSignInPreset = "sign-in-with-elvix" | "continue-with-elvix" | "sign-up-with-elvix" | "sign-in" | "log-in" | "continue";
|
|
196
|
+
type ElvixSignInButtonProps = {
|
|
197
|
+
clientId?: string;
|
|
198
|
+
/** elvix origin for redirect mode. Defaults to https://elvix.is. */
|
|
199
|
+
baseUrl?: string;
|
|
200
|
+
returnUrl?: string;
|
|
201
|
+
type?: ElvixSignInButtonType;
|
|
202
|
+
variant?: ElvixSignInButtonVariant;
|
|
203
|
+
shape?: ElvixSignInButtonShape;
|
|
204
|
+
size?: ElvixSignInButtonSize;
|
|
205
|
+
theme?: ElvixSignInButtonTheme;
|
|
206
|
+
preset?: ElvixSignInPreset;
|
|
207
|
+
label?: string;
|
|
208
|
+
className?: string;
|
|
209
|
+
href?: string;
|
|
210
|
+
mode?: ElvixSignInButtonMode;
|
|
211
|
+
onClick?: () => void;
|
|
212
|
+
/** Terminal outcome of mode="embed": success (with token) or error. */
|
|
213
|
+
onResult?: (result: ElvixSignInResult) => void;
|
|
214
|
+
};
|
|
215
|
+
declare function ElvixSignInButton({ clientId, baseUrl, returnUrl, type, variant, shape, size, theme, preset, label, className, href, mode, onClick, onResult, }: ElvixSignInButtonProps): react.JSX.Element;
|
|
216
|
+
|
|
217
|
+
type ElvixSecuredBadgeVariant = "white" | "dark" | "outline";
|
|
218
|
+
type ElvixSecuredBadgeSize = "sm" | "md" | "lg";
|
|
219
|
+
type ElvixSecuredBadgeTheme = "light" | "dark";
|
|
220
|
+
type ElvixSecuredBadgeProps = {
|
|
221
|
+
variant?: ElvixSecuredBadgeVariant;
|
|
222
|
+
size?: ElvixSecuredBadgeSize;
|
|
223
|
+
/** Which side of the colour wheel the host page is on (for the outline variant). */
|
|
224
|
+
theme?: ElvixSecuredBadgeTheme;
|
|
225
|
+
/** Active-protection dot colour. Defaults to brand lavender. */
|
|
226
|
+
accentColor?: string;
|
|
227
|
+
/** Where the badge links. Defaults to elvix. */
|
|
228
|
+
href?: string;
|
|
229
|
+
className?: string;
|
|
230
|
+
};
|
|
231
|
+
declare function ElvixSecuredBadge({ variant, size, theme, accentColor, href, className, }: ElvixSecuredBadgeProps): react.JSX.Element;
|
|
232
|
+
|
|
129
233
|
/**
|
|
130
234
|
* Session token store for cross-origin SDK use.
|
|
131
235
|
*
|
|
@@ -280,4 +384,4 @@ declare function ElvixLegalEntities({ onResult, }: {
|
|
|
280
384
|
onResult?: (r: ElvixActionResult) => void;
|
|
281
385
|
}): react.JSX.Element;
|
|
282
386
|
|
|
283
|
-
export { ElvixActionResult, ElvixAddressBook, ElvixAvatar, ElvixBanner, type ElvixBootstrapEnvelope, type ElvixBrand, ElvixCard, ElvixDeactivate, ElvixExport, ElvixIdentityForm, ElvixLanguages, ElvixLeave, ElvixLegalEntities, ElvixLifecycleWatcher, ElvixProvider, ElvixRegion, ElvixSessions, ElvixSignIn, type ElvixSignInMethod, type ElvixSignInResult, type ElvixSignInResultErr, type ElvixSignInResultOk, type ElvixTheme, ElvixUsername, type UseUserListResult, getElvixToken, setElvixToken, useElvixApp, useElvixContext, useUserMemberships, useUserRoles, useUserScopes };
|
|
387
|
+
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
|
@@ -167,6 +167,42 @@ function withAlpha(hex, a) {
|
|
|
167
167
|
// src/react/elvix-sign-in.tsx
|
|
168
168
|
import { useState as useState2 } from "react";
|
|
169
169
|
|
|
170
|
+
// src/react/copy.ts
|
|
171
|
+
var DEFAULT_COPY = {
|
|
172
|
+
subtitle: "Pick how you want to continue.",
|
|
173
|
+
googleButton: "Continue with Google",
|
|
174
|
+
emailPlaceholder: "you@example.com",
|
|
175
|
+
sendCodeButton: "Send code",
|
|
176
|
+
sendingLabel: "Sending\u2026",
|
|
177
|
+
codeSentSubtitle: "We sent a 6-digit code to {email}.",
|
|
178
|
+
codePlaceholder: "123456",
|
|
179
|
+
verifyingLabel: "Verifying\u2026",
|
|
180
|
+
signedInText: "Signed in.",
|
|
181
|
+
errorEnterEmail: "Enter an email.",
|
|
182
|
+
errorEnterCode: "Enter the 6-digit code."
|
|
183
|
+
};
|
|
184
|
+
function resolveCopy(bootstrap, prop) {
|
|
185
|
+
return {
|
|
186
|
+
...DEFAULT_COPY,
|
|
187
|
+
...stripUndefined(bootstrap),
|
|
188
|
+
...stripUndefined(prop)
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function fillCopy(template, tokens) {
|
|
192
|
+
return template.replace(
|
|
193
|
+
/\{(\w+)\}/g,
|
|
194
|
+
(whole, key) => key in tokens ? tokens[key] : whole
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
function stripUndefined(o) {
|
|
198
|
+
if (!o) return {};
|
|
199
|
+
const out = {};
|
|
200
|
+
for (const [k, v] of Object.entries(o)) {
|
|
201
|
+
if (v !== void 0) out[k] = v;
|
|
202
|
+
}
|
|
203
|
+
return out;
|
|
204
|
+
}
|
|
205
|
+
|
|
170
206
|
// src/react/session.ts
|
|
171
207
|
var STORAGE_KEY = "elvix.session.token";
|
|
172
208
|
var memToken = null;
|
|
@@ -207,10 +243,12 @@ function isSameOrigin(baseUrl) {
|
|
|
207
243
|
function ElvixSignIn({
|
|
208
244
|
onResult,
|
|
209
245
|
redirectAfterSignIn,
|
|
246
|
+
copy: copyProp,
|
|
210
247
|
className = ""
|
|
211
248
|
}) {
|
|
212
249
|
const ctx = useElvixContext();
|
|
213
250
|
const app = useElvixApp();
|
|
251
|
+
const copy = resolveCopy(app?.strings, copyProp);
|
|
214
252
|
const [step, setStep] = useState2("identify");
|
|
215
253
|
const [email, setEmail] = useState2("");
|
|
216
254
|
const [code, setCode] = useState2("");
|
|
@@ -218,6 +256,9 @@ function ElvixSignIn({
|
|
|
218
256
|
const [busy, setBusy] = useState2(false);
|
|
219
257
|
const [error, setError] = useState2(null);
|
|
220
258
|
const verb = app?.signInVerb === "login" ? "Log in" : "Sign in";
|
|
259
|
+
const defaultTitle = app?.appName ? `${verb} to ${app.appName}` : verb;
|
|
260
|
+
const title = copy.title ? fillCopy(copy.title, { app: app?.appName ?? "" }) : defaultTitle;
|
|
261
|
+
const submitLabel = copy.submitButton ?? verb;
|
|
221
262
|
function fail(error2, message) {
|
|
222
263
|
setError(message ?? error2);
|
|
223
264
|
onResult?.({ ok: false, error: error2, message });
|
|
@@ -230,7 +271,7 @@ function ElvixSignIn({
|
|
|
230
271
|
}
|
|
231
272
|
async function startOtp(e) {
|
|
232
273
|
e.preventDefault();
|
|
233
|
-
if (!email.trim()) return fail("invalid_input",
|
|
274
|
+
if (!email.trim()) return fail("invalid_input", copy.errorEnterEmail);
|
|
234
275
|
setBusy(true);
|
|
235
276
|
setError(null);
|
|
236
277
|
try {
|
|
@@ -259,7 +300,7 @@ function ElvixSignIn({
|
|
|
259
300
|
async function verifyOtp(e) {
|
|
260
301
|
e.preventDefault();
|
|
261
302
|
if (!challengeId) return;
|
|
262
|
-
if (code.trim().length !== 6) return fail("invalid_input",
|
|
303
|
+
if (code.trim().length !== 6) return fail("invalid_input", copy.errorEnterCode);
|
|
263
304
|
setBusy(true);
|
|
264
305
|
setError(null);
|
|
265
306
|
try {
|
|
@@ -289,9 +330,9 @@ function ElvixSignIn({
|
|
|
289
330
|
}
|
|
290
331
|
const card = `elvix-card ${className}`.trim();
|
|
291
332
|
if (step === "done") {
|
|
292
|
-
return /* @__PURE__ */ React.createElement("div", { className: card, "data-elvix-pane": "done" }, /* @__PURE__ */ React.createElement("p", null,
|
|
333
|
+
return /* @__PURE__ */ React.createElement("div", { className: card, "data-elvix-pane": "done" }, /* @__PURE__ */ React.createElement("p", null, copy.signedInText));
|
|
293
334
|
}
|
|
294
|
-
return /* @__PURE__ */ React.createElement("div", { className: card, "data-elvix-pane": step }, /* @__PURE__ */ React.createElement("h2", { className: "elvix-h" },
|
|
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(
|
|
295
336
|
"button",
|
|
296
337
|
{
|
|
297
338
|
type: "button",
|
|
@@ -300,19 +341,19 @@ function ElvixSignIn({
|
|
|
300
341
|
className: "elvix-btn elvix-btn-google",
|
|
301
342
|
"data-elvix-method": "google"
|
|
302
343
|
},
|
|
303
|
-
|
|
344
|
+
copy.googleButton
|
|
304
345
|
), app?.methods.emailOtp && /* @__PURE__ */ React.createElement("form", { onSubmit: startOtp, "data-elvix-method": "email_otp", className: "elvix-otp-form" }, /* @__PURE__ */ React.createElement(
|
|
305
346
|
"input",
|
|
306
347
|
{
|
|
307
348
|
type: "email",
|
|
308
349
|
value: email,
|
|
309
350
|
onChange: (ev) => setEmail(ev.target.value),
|
|
310
|
-
placeholder:
|
|
351
|
+
placeholder: copy.emailPlaceholder,
|
|
311
352
|
required: true,
|
|
312
353
|
disabled: busy,
|
|
313
354
|
className: "elvix-input"
|
|
314
355
|
}
|
|
315
|
-
), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ?
|
|
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(
|
|
316
357
|
"input",
|
|
317
358
|
{
|
|
318
359
|
type: "text",
|
|
@@ -321,22 +362,216 @@ function ElvixSignIn({
|
|
|
321
362
|
maxLength: 6,
|
|
322
363
|
value: code,
|
|
323
364
|
onChange: (ev) => setCode(ev.target.value.replace(/\D/g, "")),
|
|
324
|
-
placeholder:
|
|
365
|
+
placeholder: copy.codePlaceholder,
|
|
325
366
|
required: true,
|
|
326
367
|
disabled: busy,
|
|
327
368
|
className: "elvix-input"
|
|
328
369
|
}
|
|
329
|
-
), /* @__PURE__ */ React.createElement("button", { type: "submit", disabled: busy, className: "elvix-btn elvix-btn-primary" }, busy ?
|
|
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));
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/react/elvix-sign-in-button.tsx
|
|
374
|
+
import { useState as useState3 } from "react";
|
|
375
|
+
|
|
376
|
+
// src/react/elvix-shield.tsx
|
|
377
|
+
function ElvixShield({
|
|
378
|
+
size,
|
|
379
|
+
fill,
|
|
380
|
+
accent
|
|
381
|
+
}) {
|
|
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 }));
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// src/react/elvix-sign-in-button.tsx
|
|
393
|
+
var ELVIX_URL = "https://elvix.is";
|
|
394
|
+
var PRESET_LABEL = {
|
|
395
|
+
"sign-in-with-elvix": "Sign in with elvix",
|
|
396
|
+
"continue-with-elvix": "Continue with elvix",
|
|
397
|
+
"sign-up-with-elvix": "Sign up with elvix",
|
|
398
|
+
"sign-in": "Sign in",
|
|
399
|
+
"log-in": "Log in",
|
|
400
|
+
continue: "Continue"
|
|
401
|
+
};
|
|
402
|
+
var SIZE_STANDARD = {
|
|
403
|
+
sm: { height: 36, padX: 12, font: 14, gap: 8 },
|
|
404
|
+
md: { height: 40, padX: 12, font: 14, gap: 10 },
|
|
405
|
+
lg: { height: 48, padX: 16, font: 15, gap: 12 }
|
|
406
|
+
};
|
|
407
|
+
var SIZE_ICON = { sm: 36, md: 40, lg: 48 };
|
|
408
|
+
var ICON_SIZE = { sm: 18, md: 20, lg: 22 };
|
|
409
|
+
var RADIUS = { rectangle: 10, pill: 9999, square: 10, circle: 9999 };
|
|
410
|
+
function variantTone(variant, theme) {
|
|
411
|
+
const dark = theme === "dark" || theme === "auto";
|
|
412
|
+
switch (variant) {
|
|
413
|
+
case "filled":
|
|
414
|
+
return { bg: "#6c5ce7", color: "#fff", border: "1px solid rgba(0,0,0,0.1)", shadow: "0 4px 16px -4px rgba(108,92,231,0.45)" };
|
|
415
|
+
case "filled-black":
|
|
416
|
+
return { bg: "#0a0a0b", color: "#fff", border: `1px solid ${dark ? "rgba(255,255,255,0.12)" : "rgba(0,0,0,0.1)"}` };
|
|
417
|
+
case "white":
|
|
418
|
+
return { bg: "#fff", color: "#0a0a0b", border: `1px solid ${dark ? "transparent" : "#e4e4e7"}` };
|
|
419
|
+
case "outline":
|
|
420
|
+
return dark ? { bg: "transparent", color: "#fff", border: "1px solid rgba(142,125,255,0.4)" } : { bg: "#fff", color: "#0a0a0b", border: "1px solid rgba(0,0,0,0.15)" };
|
|
421
|
+
case "ghost":
|
|
422
|
+
return { bg: "transparent", color: dark ? "#fff" : "#0a0a0b", border: "1px solid transparent" };
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function shieldColor(variant, theme) {
|
|
426
|
+
if (variant === "filled" || variant === "filled-black") return "#ffffff";
|
|
427
|
+
if (variant === "white") return "#0a0a0b";
|
|
428
|
+
return theme === "light" ? "#0a0a0b" : "#ffffff";
|
|
429
|
+
}
|
|
430
|
+
function ElvixSignInButton({
|
|
431
|
+
clientId,
|
|
432
|
+
baseUrl = ELVIX_URL,
|
|
433
|
+
returnUrl,
|
|
434
|
+
type = "standard",
|
|
435
|
+
variant = "filled",
|
|
436
|
+
shape = "rectangle",
|
|
437
|
+
size = "md",
|
|
438
|
+
theme = "dark",
|
|
439
|
+
preset = "sign-in-with-elvix",
|
|
440
|
+
label,
|
|
441
|
+
className,
|
|
442
|
+
href,
|
|
443
|
+
mode = "redirect",
|
|
444
|
+
onClick,
|
|
445
|
+
onResult
|
|
446
|
+
}) {
|
|
447
|
+
const [embedOpen, setEmbedOpen] = useState3(false);
|
|
448
|
+
const isIcon = type === "icon";
|
|
449
|
+
const resolvedLabel = label ?? PRESET_LABEL[preset];
|
|
450
|
+
const tone = variantTone(variant, theme);
|
|
451
|
+
const std = SIZE_STANDARD[size];
|
|
452
|
+
const effectiveShape = isIcon ? shape === "pill" || shape === "circle" ? "circle" : "square" : shape;
|
|
453
|
+
const style = {
|
|
454
|
+
display: "inline-flex",
|
|
455
|
+
alignItems: "center",
|
|
456
|
+
justifyContent: "center",
|
|
457
|
+
fontWeight: 500,
|
|
458
|
+
fontSize: std.font,
|
|
459
|
+
cursor: "pointer",
|
|
460
|
+
userSelect: "none",
|
|
461
|
+
textDecoration: "none",
|
|
462
|
+
borderRadius: RADIUS[effectiveShape],
|
|
463
|
+
background: tone.bg,
|
|
464
|
+
color: tone.color,
|
|
465
|
+
border: tone.border,
|
|
466
|
+
boxShadow: tone.shadow,
|
|
467
|
+
transition: "background 0.15s, border-color 0.15s",
|
|
468
|
+
...isIcon ? { height: SIZE_ICON[size], width: SIZE_ICON[size] } : { height: std.height, paddingLeft: std.padX, paddingRight: std.padX, gap: std.gap }
|
|
469
|
+
};
|
|
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));
|
|
471
|
+
if (mode === "callback") {
|
|
472
|
+
return /* @__PURE__ */ React.createElement("button", { type: "button", onClick, className, style, "aria-label": isIcon ? resolvedLabel : void 0 }, content);
|
|
473
|
+
}
|
|
474
|
+
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);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
));
|
|
493
|
+
}
|
|
494
|
+
const destination = (() => {
|
|
495
|
+
if (href) return href;
|
|
496
|
+
const base = clientId ? `${baseUrl}/sign-in/${clientId}` : `${baseUrl}/sign-in`;
|
|
497
|
+
if (!returnUrl) return base;
|
|
498
|
+
const sep = base.includes("?") ? "&" : "?";
|
|
499
|
+
return `${base}${sep}return=${encodeURIComponent(returnUrl)}`;
|
|
500
|
+
})();
|
|
501
|
+
return /* @__PURE__ */ React.createElement("a", { href: destination, className, style, "aria-label": isIcon ? resolvedLabel : void 0 }, content);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// src/react/elvix-secured-badge.tsx
|
|
505
|
+
var ELVIX_URL2 = "https://elvix.is";
|
|
506
|
+
var SIZE = {
|
|
507
|
+
sm: { height: 28, padX: 10, font: 11.5, icon: 14, gap: 6 },
|
|
508
|
+
md: { height: 32, padX: 12, font: 12.5, icon: 16, gap: 7 },
|
|
509
|
+
lg: { height: 36, padX: 14, font: 13, icon: 18, gap: 8 }
|
|
510
|
+
};
|
|
511
|
+
var TONE = {
|
|
512
|
+
white: {
|
|
513
|
+
light: { bg: "#ffffff", border: "#e4e4e7", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" },
|
|
514
|
+
dark: { bg: "#ffffff", border: "transparent", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" }
|
|
515
|
+
},
|
|
516
|
+
dark: {
|
|
517
|
+
light: { bg: "#0a0a0b", border: "rgba(0,0,0,0.1)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" },
|
|
518
|
+
dark: { bg: "#0a0a0b", border: "rgba(255,255,255,0.1)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" }
|
|
519
|
+
},
|
|
520
|
+
outline: {
|
|
521
|
+
light: { bg: "transparent", border: "rgba(0,0,0,0.15)", lead: "#71717a", brand: "#0a0a0b", shield: "#0a0a0b" },
|
|
522
|
+
dark: { bg: "transparent", border: "rgba(142,125,255,0.4)", lead: "#d4d4d8", brand: "#ffffff", shield: "#ffffff" }
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
function ElvixSecuredBadge({
|
|
526
|
+
variant = "white",
|
|
527
|
+
size = "md",
|
|
528
|
+
theme = "dark",
|
|
529
|
+
accentColor = "#8e7dff",
|
|
530
|
+
href = ELVIX_URL2,
|
|
531
|
+
className = ""
|
|
532
|
+
}) {
|
|
533
|
+
const s = SIZE[size];
|
|
534
|
+
const t = TONE[variant][theme];
|
|
535
|
+
const style = {
|
|
536
|
+
display: "inline-flex",
|
|
537
|
+
alignItems: "center",
|
|
538
|
+
gap: s.gap,
|
|
539
|
+
height: s.height,
|
|
540
|
+
paddingLeft: s.padX,
|
|
541
|
+
paddingRight: s.padX,
|
|
542
|
+
fontSize: s.font,
|
|
543
|
+
fontWeight: 500,
|
|
544
|
+
borderRadius: 9999,
|
|
545
|
+
background: t.bg,
|
|
546
|
+
border: `1px solid ${t.border}`,
|
|
547
|
+
color: t.brand,
|
|
548
|
+
textDecoration: "none",
|
|
549
|
+
userSelect: "none",
|
|
550
|
+
lineHeight: 1
|
|
551
|
+
};
|
|
552
|
+
return /* @__PURE__ */ React.createElement(
|
|
553
|
+
"a",
|
|
554
|
+
{
|
|
555
|
+
href,
|
|
556
|
+
target: "_blank",
|
|
557
|
+
rel: "noopener noreferrer",
|
|
558
|
+
className,
|
|
559
|
+
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"))
|
|
564
|
+
);
|
|
330
565
|
}
|
|
331
566
|
|
|
332
567
|
// src/react/hooks.ts
|
|
333
|
-
import { useCallback, useEffect as useEffect2, useState as
|
|
568
|
+
import { useCallback, useEffect as useEffect2, useState as useState4 } from "react";
|
|
334
569
|
var POLL_MS = 7e3;
|
|
335
570
|
function useUserList(kind, opts) {
|
|
336
571
|
const { applicationId, baseUrl = "", pollMs = POLL_MS } = opts;
|
|
337
|
-
const [slugs, setSlugs] =
|
|
338
|
-
const [loading, setLoading] =
|
|
339
|
-
const [error, setError] =
|
|
572
|
+
const [slugs, setSlugs] = useState4([]);
|
|
573
|
+
const [loading, setLoading] = useState4(true);
|
|
574
|
+
const [error, setError] = useState4(null);
|
|
340
575
|
const refresh = useCallback(async () => {
|
|
341
576
|
setError(null);
|
|
342
577
|
try {
|
|
@@ -403,7 +638,7 @@ function ElvixLifecycleWatcher({
|
|
|
403
638
|
}
|
|
404
639
|
|
|
405
640
|
// src/react/elvix-username.tsx
|
|
406
|
-
import { useState as
|
|
641
|
+
import { useState as useState5 } from "react";
|
|
407
642
|
|
|
408
643
|
// src/react/lib.ts
|
|
409
644
|
async function appPost(opts, path, body) {
|
|
@@ -465,10 +700,10 @@ function ElvixUsername({
|
|
|
465
700
|
onResult
|
|
466
701
|
}) {
|
|
467
702
|
const ctx = useElvixContext();
|
|
468
|
-
const [value, setValue] =
|
|
469
|
-
const [busy, setBusy] =
|
|
470
|
-
const [error, setError] =
|
|
471
|
-
const [done, setDone] =
|
|
703
|
+
const [value, setValue] = useState5("");
|
|
704
|
+
const [busy, setBusy] = useState5(false);
|
|
705
|
+
const [error, setError] = useState5(null);
|
|
706
|
+
const [done, setDone] = useState5(null);
|
|
472
707
|
async function submit(e) {
|
|
473
708
|
e.preventDefault();
|
|
474
709
|
if (!ctx.app) return;
|
|
@@ -506,14 +741,14 @@ function ElvixUsername({
|
|
|
506
741
|
}
|
|
507
742
|
|
|
508
743
|
// src/react/elvix-avatar.tsx
|
|
509
|
-
import { useState as
|
|
744
|
+
import { useState as useState6 } from "react";
|
|
510
745
|
function ElvixAvatar({
|
|
511
746
|
onResult
|
|
512
747
|
}) {
|
|
513
748
|
const ctx = useElvixContext();
|
|
514
|
-
const [busy, setBusy] =
|
|
515
|
-
const [error, setError] =
|
|
516
|
-
const [preview, setPreview] =
|
|
749
|
+
const [busy, setBusy] = useState6(false);
|
|
750
|
+
const [error, setError] = useState6(null);
|
|
751
|
+
const [preview, setPreview] = useState6(null);
|
|
517
752
|
async function onFile(e) {
|
|
518
753
|
const file = e.target.files?.[0];
|
|
519
754
|
if (!file || !ctx.app) return;
|
|
@@ -547,14 +782,14 @@ function ElvixAvatar({
|
|
|
547
782
|
}
|
|
548
783
|
|
|
549
784
|
// src/react/elvix-banner.tsx
|
|
550
|
-
import { useState as
|
|
785
|
+
import { useState as useState7 } from "react";
|
|
551
786
|
function ElvixBanner({
|
|
552
787
|
onResult
|
|
553
788
|
}) {
|
|
554
789
|
const ctx = useElvixContext();
|
|
555
|
-
const [busy, setBusy] =
|
|
556
|
-
const [error, setError] =
|
|
557
|
-
const [preview, setPreview] =
|
|
790
|
+
const [busy, setBusy] = useState7(false);
|
|
791
|
+
const [error, setError] = useState7(null);
|
|
792
|
+
const [preview, setPreview] = useState7(null);
|
|
558
793
|
async function onFile(e) {
|
|
559
794
|
const file = e.target.files?.[0];
|
|
560
795
|
if (!file || !ctx.app) return;
|
|
@@ -588,18 +823,18 @@ function ElvixBanner({
|
|
|
588
823
|
}
|
|
589
824
|
|
|
590
825
|
// src/react/elvix-identity-form.tsx
|
|
591
|
-
import { useState as
|
|
826
|
+
import { useState as useState8 } from "react";
|
|
592
827
|
function ElvixIdentityForm({
|
|
593
828
|
initialName = "",
|
|
594
829
|
initialBio = "",
|
|
595
830
|
onResult
|
|
596
831
|
}) {
|
|
597
832
|
const ctx = useElvixContext();
|
|
598
|
-
const [name, setName] =
|
|
599
|
-
const [bio, setBio] =
|
|
600
|
-
const [busy, setBusy] =
|
|
601
|
-
const [error, setError] =
|
|
602
|
-
const [saved, setSaved] =
|
|
833
|
+
const [name, setName] = useState8(initialName);
|
|
834
|
+
const [bio, setBio] = useState8(initialBio);
|
|
835
|
+
const [busy, setBusy] = useState8(false);
|
|
836
|
+
const [error, setError] = useState8(null);
|
|
837
|
+
const [saved, setSaved] = useState8(false);
|
|
603
838
|
async function submit(e) {
|
|
604
839
|
e.preventDefault();
|
|
605
840
|
if (!ctx.app) return;
|
|
@@ -619,18 +854,18 @@ function ElvixIdentityForm({
|
|
|
619
854
|
}
|
|
620
855
|
|
|
621
856
|
// src/react/elvix-region.tsx
|
|
622
|
-
import { useState as
|
|
857
|
+
import { useState as useState9 } from "react";
|
|
623
858
|
function ElvixRegion({
|
|
624
859
|
initialCountry = "",
|
|
625
860
|
initialTimezone = "",
|
|
626
861
|
onResult
|
|
627
862
|
}) {
|
|
628
863
|
const ctx = useElvixContext();
|
|
629
|
-
const [country, setCountry] =
|
|
630
|
-
const [timezone, setTimezone] =
|
|
631
|
-
const [busy, setBusy] =
|
|
632
|
-
const [error, setError] =
|
|
633
|
-
const [saved, setSaved] =
|
|
864
|
+
const [country, setCountry] = useState9(initialCountry);
|
|
865
|
+
const [timezone, setTimezone] = useState9(initialTimezone);
|
|
866
|
+
const [busy, setBusy] = useState9(false);
|
|
867
|
+
const [error, setError] = useState9(null);
|
|
868
|
+
const [saved, setSaved] = useState9(false);
|
|
634
869
|
async function submit(e) {
|
|
635
870
|
e.preventDefault();
|
|
636
871
|
if (!ctx.app) return;
|
|
@@ -650,16 +885,16 @@ function ElvixRegion({
|
|
|
650
885
|
}
|
|
651
886
|
|
|
652
887
|
// src/react/elvix-languages.tsx
|
|
653
|
-
import { useState as
|
|
888
|
+
import { useState as useState10 } from "react";
|
|
654
889
|
function ElvixLanguages({
|
|
655
890
|
initial = [],
|
|
656
891
|
onResult
|
|
657
892
|
}) {
|
|
658
893
|
const ctx = useElvixContext();
|
|
659
|
-
const [raw, setRaw] =
|
|
660
|
-
const [busy, setBusy] =
|
|
661
|
-
const [error, setError] =
|
|
662
|
-
const [saved, setSaved] =
|
|
894
|
+
const [raw, setRaw] = useState10(initial.join(", "));
|
|
895
|
+
const [busy, setBusy] = useState10(false);
|
|
896
|
+
const [error, setError] = useState10(null);
|
|
897
|
+
const [saved, setSaved] = useState10(false);
|
|
663
898
|
async function submit(e) {
|
|
664
899
|
e.preventDefault();
|
|
665
900
|
if (!ctx.app) return;
|
|
@@ -680,14 +915,14 @@ function ElvixLanguages({
|
|
|
680
915
|
}
|
|
681
916
|
|
|
682
917
|
// src/react/elvix-sessions.tsx
|
|
683
|
-
import { useEffect as useEffect4, useState as
|
|
918
|
+
import { useEffect as useEffect4, useState as useState11 } from "react";
|
|
684
919
|
function ElvixSessions({
|
|
685
920
|
onResult
|
|
686
921
|
}) {
|
|
687
922
|
const ctx = useElvixContext();
|
|
688
|
-
const [rows, setRows] =
|
|
689
|
-
const [error, setError] =
|
|
690
|
-
const [busy, setBusy] =
|
|
923
|
+
const [rows, setRows] = useState11(null);
|
|
924
|
+
const [error, setError] = useState11(null);
|
|
925
|
+
const [busy, setBusy] = useState11(false);
|
|
691
926
|
useEffect4(() => {
|
|
692
927
|
if (!ctx.app) return;
|
|
693
928
|
fetch(`${ctx.baseUrl}/api/account/apps/${ctx.app.applicationId}/sessions`, {
|
|
@@ -712,14 +947,14 @@ function ElvixSessions({
|
|
|
712
947
|
}
|
|
713
948
|
|
|
714
949
|
// src/react/elvix-export.tsx
|
|
715
|
-
import { useState as
|
|
950
|
+
import { useState as useState12 } from "react";
|
|
716
951
|
function ElvixExport({
|
|
717
952
|
onResult
|
|
718
953
|
}) {
|
|
719
954
|
const ctx = useElvixContext();
|
|
720
|
-
const [busy, setBusy] =
|
|
721
|
-
const [done, setDone] =
|
|
722
|
-
const [error, setError] =
|
|
955
|
+
const [busy, setBusy] = useState12(false);
|
|
956
|
+
const [done, setDone] = useState12(false);
|
|
957
|
+
const [error, setError] = useState12(null);
|
|
723
958
|
async function start() {
|
|
724
959
|
if (!ctx.app) return;
|
|
725
960
|
setBusy(true);
|
|
@@ -738,16 +973,16 @@ function ElvixExport({
|
|
|
738
973
|
}
|
|
739
974
|
|
|
740
975
|
// src/react/elvix-deactivate.tsx
|
|
741
|
-
import { useState as
|
|
976
|
+
import { useState as useState13 } from "react";
|
|
742
977
|
function ElvixDeactivate({
|
|
743
978
|
onResult
|
|
744
979
|
}) {
|
|
745
980
|
const ctx = useElvixContext();
|
|
746
|
-
const [pane, setPane] =
|
|
747
|
-
const [challengeId, setChallengeId] =
|
|
748
|
-
const [code, setCode] =
|
|
749
|
-
const [busy, setBusy] =
|
|
750
|
-
const [error, setError] =
|
|
981
|
+
const [pane, setPane] = useState13("warn");
|
|
982
|
+
const [challengeId, setChallengeId] = useState13(null);
|
|
983
|
+
const [code, setCode] = useState13("");
|
|
984
|
+
const [busy, setBusy] = useState13(false);
|
|
985
|
+
const [error, setError] = useState13(null);
|
|
751
986
|
async function startChallenge() {
|
|
752
987
|
if (!ctx.app) return;
|
|
753
988
|
setBusy(true);
|
|
@@ -804,16 +1039,16 @@ function ElvixDeactivate({
|
|
|
804
1039
|
}
|
|
805
1040
|
|
|
806
1041
|
// src/react/elvix-leave.tsx
|
|
807
|
-
import { useState as
|
|
1042
|
+
import { useState as useState14 } from "react";
|
|
808
1043
|
function ElvixLeave({
|
|
809
1044
|
onResult
|
|
810
1045
|
}) {
|
|
811
1046
|
const ctx = useElvixContext();
|
|
812
|
-
const [pane, setPane] =
|
|
813
|
-
const [challengeId, setChallengeId] =
|
|
814
|
-
const [code, setCode] =
|
|
815
|
-
const [busy, setBusy] =
|
|
816
|
-
const [error, setError] =
|
|
1047
|
+
const [pane, setPane] = useState14("warn");
|
|
1048
|
+
const [challengeId, setChallengeId] = useState14(null);
|
|
1049
|
+
const [code, setCode] = useState14("");
|
|
1050
|
+
const [busy, setBusy] = useState14(false);
|
|
1051
|
+
const [error, setError] = useState14(null);
|
|
817
1052
|
async function startChallenge() {
|
|
818
1053
|
if (!ctx.app) return;
|
|
819
1054
|
setBusy(true);
|
|
@@ -870,16 +1105,16 @@ function ElvixLeave({
|
|
|
870
1105
|
}
|
|
871
1106
|
|
|
872
1107
|
// src/react/elvix-address-book.tsx
|
|
873
|
-
import { useEffect as useEffect5, useState as
|
|
1108
|
+
import { useEffect as useEffect5, useState as useState15 } from "react";
|
|
874
1109
|
function ElvixAddressBook({
|
|
875
1110
|
onResult
|
|
876
1111
|
}) {
|
|
877
1112
|
const ctx = useElvixContext();
|
|
878
|
-
const [rows, setRows] =
|
|
879
|
-
const [error, setError] =
|
|
880
|
-
const [busy, setBusy] =
|
|
881
|
-
const [adding, setAdding] =
|
|
882
|
-
const [form, setForm] =
|
|
1113
|
+
const [rows, setRows] = useState15(null);
|
|
1114
|
+
const [error, setError] = useState15(null);
|
|
1115
|
+
const [busy, setBusy] = useState15(false);
|
|
1116
|
+
const [adding, setAdding] = useState15(false);
|
|
1117
|
+
const [form, setForm] = useState15({
|
|
883
1118
|
label: "Home",
|
|
884
1119
|
line1: "",
|
|
885
1120
|
postalCode: "",
|
|
@@ -932,16 +1167,16 @@ function ElvixAddressBook({
|
|
|
932
1167
|
}
|
|
933
1168
|
|
|
934
1169
|
// src/react/elvix-legal-entities.tsx
|
|
935
|
-
import { useEffect as useEffect6, useState as
|
|
1170
|
+
import { useEffect as useEffect6, useState as useState16 } from "react";
|
|
936
1171
|
function ElvixLegalEntities({
|
|
937
1172
|
onResult
|
|
938
1173
|
}) {
|
|
939
1174
|
const ctx = useElvixContext();
|
|
940
|
-
const [rows, setRows] =
|
|
941
|
-
const [error, setError] =
|
|
942
|
-
const [busy, setBusy] =
|
|
943
|
-
const [adding, setAdding] =
|
|
944
|
-
const [form, setForm] =
|
|
1175
|
+
const [rows, setRows] = useState16(null);
|
|
1176
|
+
const [error, setError] = useState16(null);
|
|
1177
|
+
const [busy, setBusy] = useState16(false);
|
|
1178
|
+
const [adding, setAdding] = useState16(false);
|
|
1179
|
+
const [form, setForm] = useState16({
|
|
945
1180
|
legalName: "",
|
|
946
1181
|
taxId: "",
|
|
947
1182
|
country: ""
|
|
@@ -991,6 +1226,7 @@ function ElvixLegalEntities({
|
|
|
991
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")));
|
|
992
1227
|
}
|
|
993
1228
|
export {
|
|
1229
|
+
DEFAULT_COPY,
|
|
994
1230
|
ElvixAddressBook,
|
|
995
1231
|
ElvixAvatar,
|
|
996
1232
|
ElvixBanner,
|
|
@@ -1004,8 +1240,10 @@ export {
|
|
|
1004
1240
|
ElvixLifecycleWatcher,
|
|
1005
1241
|
ElvixProvider,
|
|
1006
1242
|
ElvixRegion,
|
|
1243
|
+
ElvixSecuredBadge,
|
|
1007
1244
|
ElvixSessions,
|
|
1008
1245
|
ElvixSignIn,
|
|
1246
|
+
ElvixSignInButton,
|
|
1009
1247
|
ElvixUsername,
|
|
1010
1248
|
getElvixToken,
|
|
1011
1249
|
setElvixToken,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elvix.is/sdk",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
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",
|