@kerne/react 0.1.0 → 0.1.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.
@@ -0,0 +1,2984 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+ var _chunk3PROPZWWcjs = require('../chunk-3PROPZWW.cjs');
20
+
21
+ // src/ui/AuthFlow.tsx
22
+ var _react = require('react');
23
+
24
+ // src/ui/useUrlToken.ts
25
+
26
+ function useUrlToken(param = "token", override) {
27
+ const [token, setToken] = _react.useState.call(void 0, _nullishCoalesce(override, () => ( null)));
28
+ _react.useEffect.call(void 0, () => {
29
+ if (override) {
30
+ setToken(override);
31
+ return;
32
+ }
33
+ if (typeof window === "undefined") return;
34
+ setToken(_nullishCoalesce(new URLSearchParams(window.location.search).get(param), () => ( "")));
35
+ }, [param, override]);
36
+ return token;
37
+ }
38
+
39
+ // src/ui/LoginForm.tsx
40
+
41
+
42
+ // src/ui/primitives.tsx
43
+
44
+
45
+ // src/ui/styles.ts
46
+ var STYLE_ELEMENT_ID = "kerne-ui-styles";
47
+ var DARK_TOKENS = `
48
+ --kerne-fg: #f0f1f3;
49
+ --kerne-fg-muted: #9ba2ad;
50
+ --kerne-fg-subtle: #838b96;
51
+ --kerne-border: #2a2e36;
52
+ --kerne-border-strong: #363b45;
53
+ --kerne-panel: #1b1f26;
54
+ --kerne-surface: #14171c;
55
+ --kerne-surface-raised: #2a2f38;
56
+ --kerne-primary: #f0f1f3;
57
+ --kerne-primary-fg: #16181d;
58
+ --kerne-primary-hover: #d8dade;
59
+ --kerne-accent: #91a7ff;
60
+ --kerne-danger: #f0837a;
61
+ --kerne-success: #5cbd8d;
62
+ --kerne-warning: #d9ab5e;
63
+ --kerne-shadow: 0 4px 6px -2px rgba(0,0,0,.4), 0 12px 24px -8px rgba(0,0,0,.6);
64
+ `;
65
+ var CSS = `
66
+ .kerne-root {
67
+ --kerne-fg: #16171a;
68
+ --kerne-fg-muted: #6b7280;
69
+ /* Meets 4.5:1 on white - this carries placeholders and the legal footnote,
70
+ which used to sit around 2.5:1. */
71
+ --kerne-fg-subtle: #6f7681;
72
+ --kerne-border: #e3e5e9;
73
+ --kerne-border-strong: #d6dade;
74
+ --kerne-field-bg: transparent;
75
+ --kerne-panel: #f4f5f7;
76
+ /* The ground the component sits on. Transparent so an embedded instance
77
+ inherits the host's page; set it (appearance.background) when the component
78
+ owns the viewport, so text and background can never resolve independently. */
79
+ --kerne-bg: transparent;
80
+ /* An opaque surface for the things that must not show through: the card
81
+ variant, the dropdown floating over host content, a pressed segment. */
82
+ --kerne-surface: #ffffff;
83
+ --kerne-surface-raised: #ffffff;
84
+ --kerne-primary: #16171a;
85
+ --kerne-primary-fg: #ffffff;
86
+ --kerne-primary-hover: #2c2e33;
87
+ --kerne-accent: #3b5bdb;
88
+ --kerne-danger: #c0392f;
89
+ --kerne-success: #1f7a4d;
90
+ --kerne-warning: #9a6b12;
91
+ --kerne-radius: 8px;
92
+ --kerne-control-height: 44px;
93
+ --kerne-shadow: 0 4px 6px -2px rgba(0,0,0,.06), 0 12px 24px -8px rgba(0,0,0,.16);
94
+ --kerne-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
95
+
96
+ box-sizing: border-box;
97
+ font-family: var(--kerne-font);
98
+ color: var(--kerne-fg);
99
+ background: var(--kerne-bg);
100
+ -webkit-font-smoothing: antialiased;
101
+ display: flex;
102
+ justify-content: center;
103
+ width: 100%;
104
+ }
105
+ .kerne-root *, .kerne-root *::before, .kerne-root *::after { box-sizing: inherit; }
106
+
107
+ .kerne-root[data-kerne-theme="dark"] {${DARK_TOKENS}}
108
+ /* Only an explicit opt-in follows the visitor's OS. Defaulting to it meant a
109
+ light-only host got a dark form on any machine set to dark, without ever
110
+ asking for one - and with no way for the host to know it had happened. */
111
+ @media (prefers-color-scheme: dark) {
112
+ .kerne-root[data-kerne-theme="system"] {${DARK_TOKENS}}
113
+ }
114
+
115
+ .kerne-shell {
116
+ width: 100%;
117
+ max-width: 384px;
118
+ display: flex;
119
+ flex-direction: column;
120
+ }
121
+ /* Auth screens are a single column of fields; an account manager is a
122
+ navigation plus a content pane and suffocates at 384px. */
123
+ .kerne-shell[data-kerne-size="wide"] { max-width: 800px; }
124
+
125
+ .kerne-shell[data-kerne-surface="card"] {
126
+ background: var(--kerne-surface);
127
+ border: 1px solid var(--kerne-border);
128
+ border-radius: calc(var(--kerne-radius) + 6px);
129
+ box-shadow: var(--kerne-shadow);
130
+ padding: 32px 28px;
131
+ /* The card is the ground from here down, so nested surfaces stop inheriting
132
+ the page behind it. */
133
+ --kerne-bg: var(--kerne-surface);
134
+ }
135
+ @media (max-width: 480px) {
136
+ /* Full-bleed on a phone: a card with 16px of page showing on each side wastes
137
+ the only axis a login form has. */
138
+ .kerne-shell[data-kerne-surface="card"] {
139
+ border: none;
140
+ box-shadow: none;
141
+ padding: 8px 0;
142
+ background: transparent;
143
+ /* The card no longer paints, so the ground is the page again. */
144
+ --kerne-bg: transparent;
145
+ }
146
+ }
147
+
148
+ /* ---------- Tabbed account manager ---------- */
149
+ .kerne-profile { display: grid; grid-template-columns: 188px minmax(0, 1fr); gap: 40px; align-items: start; }
150
+ @media (max-width: 640px) { .kerne-profile { grid-template-columns: 1fr; gap: 20px; } }
151
+
152
+ .kerne-nav { display: flex; flex-direction: column; gap: 2px; position: sticky; top: 24px; }
153
+ @media (max-width: 640px) {
154
+ .kerne-nav {
155
+ position: static;
156
+ flex-direction: row;
157
+ overflow-x: auto;
158
+ gap: 4px;
159
+ border-bottom: 1px solid var(--kerne-border);
160
+ padding-bottom: 8px;
161
+ }
162
+ }
163
+ .kerne-nav-item {
164
+ font: inherit; font-size: 14px; text-align: left;
165
+ background: none; border: none; cursor: pointer;
166
+ padding: 8px 12px; border-radius: 6px;
167
+ color: var(--kerne-fg-muted); white-space: nowrap;
168
+ transition: background-color .12s ease, color .12s ease;
169
+ }
170
+ .kerne-nav-item:hover { color: var(--kerne-fg); }
171
+ .kerne-nav-item[aria-current="page"] { background: var(--kerne-panel); color: var(--kerne-fg); font-weight: 500; }
172
+ .kerne-nav-item:focus-visible { outline: 2px solid var(--kerne-accent); outline-offset: 2px; }
173
+
174
+ .kerne-pane { display: flex; flex-direction: column; min-width: 0; }
175
+ .kerne-pane-title { font-size: 20px; font-weight: 600; letter-spacing: -.01em; margin: 0 0 4px; }
176
+ .kerne-pane-desc { font-size: 14px; color: var(--kerne-fg-muted); margin: 0 0 8px; }
177
+
178
+ .kerne-subsection { padding: 24px 0; display: flex; flex-direction: column; gap: 16px; }
179
+ .kerne-subsection:first-of-type { padding-top: 16px; }
180
+ .kerne-subsection + .kerne-subsection { border-top: 1px solid var(--kerne-border); }
181
+ .kerne-subsection-head { display: flex; flex-direction: column; gap: 3px; }
182
+ .kerne-subsection-title { font-size: 15px; font-weight: 600; margin: 0; }
183
+ .kerne-subsection-desc { font-size: 13px; color: var(--kerne-fg-muted); margin: 0; }
184
+ /* Buttons inside a settings pane are actions, not page-wide calls to action. */
185
+ .kerne-subsection .kerne-button { width: auto; align-self: flex-start; }
186
+
187
+ /* ---------- Plan options ---------- */
188
+ .kerne-plan-list { display: flex; flex-direction: column; gap: 10px; }
189
+ .kerne-plan-option {
190
+ display: flex; justify-content: space-between; align-items: center; gap: 16px;
191
+ padding: 14px 16px; border: 1px solid var(--kerne-border); border-radius: var(--kerne-radius);
192
+ }
193
+ .kerne-plan-option[data-current="true"] { border-color: var(--kerne-fg); }
194
+ .kerne-plan-option-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
195
+ .kerne-plan-option-name { font-size: 14px; font-weight: 500; display: flex; align-items: center; gap: 8px; }
196
+ .kerne-plan-option-price { font-size: 13px; color: var(--kerne-fg-muted); font-variant-numeric: tabular-nums; }
197
+ .kerne-plan-option .kerne-button { width: auto; flex-shrink: 0; height: 36px; font-size: 13px; }
198
+
199
+ /* Segmented control for billing interval. */
200
+ .kerne-segmented { display: inline-flex; padding: 3px; gap: 2px; background: var(--kerne-panel); border-radius: var(--kerne-radius); align-self: flex-start; }
201
+ .kerne-segment {
202
+ font: inherit; font-size: 13px; border: none; background: none; cursor: pointer;
203
+ padding: 5px 12px; border-radius: calc(var(--kerne-radius) - 3px); color: var(--kerne-fg-muted);
204
+ }
205
+ .kerne-segment[aria-pressed="true"] { background: var(--kerne-surface-raised); color: var(--kerne-fg); font-weight: 500; }
206
+ .kerne-segment:focus-visible { outline: 2px solid var(--kerne-accent); outline-offset: 2px; }
207
+
208
+ /* ---------- Masthead ---------- */
209
+ .kerne-masthead {
210
+ display: flex;
211
+ flex-direction: column;
212
+ align-items: center;
213
+ gap: 16px;
214
+ text-align: center;
215
+ margin-bottom: 32px;
216
+ }
217
+ .kerne-logo { display: flex; align-items: center; justify-content: center; }
218
+ .kerne-heading { display: flex; flex-direction: column; gap: 6px; }
219
+ .kerne-title {
220
+ margin: 0;
221
+ font-size: 24px;
222
+ font-weight: 600;
223
+ letter-spacing: -.02em;
224
+ line-height: 1.2;
225
+ text-wrap: balance;
226
+ }
227
+ .kerne-subtitle { margin: 0; font-size: 14px; color: var(--kerne-fg-muted); line-height: 1.5; }
228
+
229
+ /* ---------- Stack ---------- */
230
+ .kerne-stack { display: flex; flex-direction: column; gap: 16px; }
231
+ .kerne-form { display: flex; flex-direction: column; gap: 12px; }
232
+ .kerne-field { display: flex; flex-direction: column; gap: 6px; }
233
+ .kerne-label { font-size: 14px; font-weight: 500; color: var(--kerne-fg); }
234
+ .kerne-label-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
235
+
236
+ .kerne-input {
237
+ font: inherit;
238
+ font-size: 14px;
239
+ height: var(--kerne-control-height);
240
+ color: var(--kerne-fg);
241
+ background: var(--kerne-field-bg);
242
+ border: 1px solid var(--kerne-border-strong);
243
+ border-radius: var(--kerne-radius);
244
+ padding: 0 13px;
245
+ width: 100%;
246
+ transition: border-color .12s ease, box-shadow .12s ease;
247
+ }
248
+ .kerne-input::placeholder { color: var(--kerne-fg-subtle); }
249
+ .kerne-input:hover:not(:disabled):not(:focus) { border-color: var(--kerne-fg-subtle); }
250
+ .kerne-input:focus {
251
+ outline: none;
252
+ border-color: var(--kerne-accent);
253
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--kerne-accent) 15%, transparent);
254
+ }
255
+ .kerne-input:disabled { opacity: .6; cursor: not-allowed; }
256
+ .kerne-input[aria-invalid="true"] { border-color: var(--kerne-danger); }
257
+ .kerne-input[data-kerne-code="true"] {
258
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
259
+ letter-spacing: .3em;
260
+ text-transform: uppercase;
261
+ }
262
+
263
+ /* ---------- Buttons ---------- */
264
+ .kerne-button {
265
+ font: inherit;
266
+ font-size: 14px;
267
+ font-weight: 500;
268
+ height: var(--kerne-control-height);
269
+ border-radius: var(--kerne-radius);
270
+ padding: 0 16px;
271
+ cursor: pointer;
272
+ border: 1px solid transparent;
273
+ display: inline-flex;
274
+ align-items: center;
275
+ justify-content: center;
276
+ gap: 10px;
277
+ width: 100%;
278
+ transition: background-color .12s ease, border-color .12s ease, opacity .12s ease;
279
+ }
280
+ .kerne-button:focus-visible { outline: 2px solid var(--kerne-accent); outline-offset: 2px; }
281
+ .kerne-button:disabled { opacity: .5; cursor: not-allowed; }
282
+ .kerne-button-primary { background: var(--kerne-primary); color: var(--kerne-primary-fg); }
283
+ .kerne-button-primary:hover:not(:disabled) { background: var(--kerne-primary-hover); }
284
+ .kerne-button-outline {
285
+ background: transparent;
286
+ color: var(--kerne-fg);
287
+ border-color: var(--kerne-border-strong);
288
+ }
289
+ .kerne-button-outline:hover:not(:disabled) { background: var(--kerne-panel); }
290
+
291
+ /* Method switch - a quiet text control, not a second call to action competing
292
+ with the primary button above it. */
293
+ .kerne-switch {
294
+ font: inherit;
295
+ font-size: 14px;
296
+ width: 100%;
297
+ text-align: center;
298
+ background: none;
299
+ border: none;
300
+ padding: 4px 0;
301
+ cursor: pointer;
302
+ color: var(--kerne-fg-muted);
303
+ text-underline-offset: 4px;
304
+ transition: color .12s ease;
305
+ }
306
+ .kerne-switch:hover { color: var(--kerne-fg); text-decoration: underline; }
307
+ .kerne-switch:focus-visible { outline: 2px solid var(--kerne-accent); outline-offset: 2px; border-radius: 4px; }
308
+
309
+ .kerne-link {
310
+ font-size: inherit;
311
+ color: var(--kerne-accent);
312
+ background: none;
313
+ border: none;
314
+ padding: 0;
315
+ cursor: pointer;
316
+ font-family: inherit;
317
+ text-decoration: none;
318
+ text-underline-offset: 3px;
319
+ }
320
+ .kerne-link:hover { text-decoration: underline; }
321
+ .kerne-link:focus-visible { outline: 2px solid var(--kerne-accent); outline-offset: 2px; border-radius: 2px; }
322
+
323
+ /* ---------- Divider ---------- */
324
+ .kerne-divider {
325
+ display: flex;
326
+ align-items: center;
327
+ gap: 12px;
328
+ color: var(--kerne-fg-muted);
329
+ font-size: 11px;
330
+ text-transform: uppercase;
331
+ letter-spacing: .06em;
332
+ padding: 2px 0;
333
+ }
334
+ .kerne-divider::before, .kerne-divider::after {
335
+ content: "";
336
+ flex: 1;
337
+ height: 1px;
338
+ background: var(--kerne-border);
339
+ }
340
+
341
+ /* ---------- Panels ---------- */
342
+ .kerne-panel {
343
+ display: flex;
344
+ align-items: flex-start;
345
+ gap: 10px;
346
+ font-size: 14px;
347
+ line-height: 1.5;
348
+ padding: 12px 14px;
349
+ border-radius: var(--kerne-radius);
350
+ background: var(--kerne-panel);
351
+ color: var(--kerne-fg-muted);
352
+ }
353
+ .kerne-panel-danger { color: var(--kerne-danger); }
354
+ .kerne-panel-success { color: var(--kerne-success); }
355
+ .kerne-panel svg { flex-shrink: 0; margin-top: 1px; }
356
+ .kerne-panel strong { color: var(--kerne-fg); font-weight: 500; }
357
+
358
+ .kerne-oauth-group { display: flex; flex-direction: column; gap: 10px; }
359
+
360
+ /* A closing line under a form, e.g. "Remembered it? Back to sign in". */
361
+ .kerne-footer { font-size: 14px; color: var(--kerne-fg-muted); text-align: center; margin: 4px 0 0; }
362
+
363
+ /* ---------- Footnotes ---------- */
364
+ .kerne-legal {
365
+ font-size: 12px;
366
+ line-height: 1.5;
367
+ color: var(--kerne-fg-subtle);
368
+ text-align: center;
369
+ margin: 32px 0 0;
370
+ }
371
+ .kerne-branding {
372
+ display: flex;
373
+ align-items: center;
374
+ justify-content: center;
375
+ gap: 5px;
376
+ margin-top: 24px;
377
+ font-size: 12px;
378
+ color: var(--kerne-fg-subtle);
379
+ text-decoration: none;
380
+ }
381
+ .kerne-branding:hover { color: var(--kerne-fg-muted); }
382
+
383
+ /* Centred outcome screen for the flows that resolve on their own (magic-link
384
+ landing, email verification by link) - there is no form to show, only what
385
+ happened. */
386
+ .kerne-status { display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; padding: 8px 0; }
387
+ .kerne-status-icon { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 50%; background: var(--kerne-panel); }
388
+ .kerne-status-icon[data-tone="danger"] { color: var(--kerne-danger); }
389
+ .kerne-status-icon[data-tone="success"] { color: var(--kerne-success); }
390
+ .kerne-status-icon[data-tone="muted"] { color: var(--kerne-fg-muted); }
391
+ .kerne-status-text { font-size: 14px; color: var(--kerne-fg-muted); line-height: 1.5; margin: 0; max-width: 34ch; }
392
+
393
+ .kerne-spinner {
394
+ width: 20px; height: 20px;
395
+ border: 2px solid currentColor;
396
+ border-right-color: transparent;
397
+ border-radius: 50%;
398
+ animation: kerne-spin .6s linear infinite;
399
+ }
400
+ @keyframes kerne-spin { to { transform: rotate(360deg); } }
401
+
402
+ .kerne-button-danger {
403
+ background: transparent;
404
+ color: var(--kerne-danger);
405
+ border-color: color-mix(in srgb, var(--kerne-danger) 40%, transparent);
406
+ }
407
+ .kerne-button-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--kerne-danger) 8%, transparent); }
408
+
409
+ /* ---------- Usage meters ---------- */
410
+ .kerne-meters { display: flex; flex-direction: column; gap: 18px; }
411
+ .kerne-meter { display: flex; flex-direction: column; gap: 7px; }
412
+ .kerne-meter-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
413
+ .kerne-meter-name { font-size: 14px; font-weight: 500; }
414
+ .kerne-meter-value {
415
+ font-size: 13px;
416
+ color: var(--kerne-fg-muted);
417
+ /* Digits line up between rows instead of jittering as counts change. */
418
+ font-variant-numeric: tabular-nums;
419
+ }
420
+ .kerne-meter-track { height: 6px; border-radius: 999px; background: var(--kerne-panel); overflow: hidden; }
421
+ .kerne-meter-fill { height: 100%; border-radius: 999px; background: var(--kerne-fg); transition: width .3s ease; }
422
+ .kerne-meter[data-level="warning"] .kerne-meter-fill { background: var(--kerne-warning); }
423
+ .kerne-meter[data-level="critical"] .kerne-meter-fill { background: var(--kerne-danger); }
424
+ .kerne-meter[data-level="warning"] .kerne-meter-value { color: var(--kerne-warning); }
425
+ .kerne-meter[data-level="critical"] .kerne-meter-value { color: var(--kerne-danger); }
426
+ .kerne-meter-note { font-size: 12px; color: var(--kerne-fg-subtle); margin: 0; }
427
+ @media (prefers-reduced-motion: reduce) { .kerne-meter-fill { transition: none; } }
428
+
429
+ /* ---------- Sections (profile, settings) ---------- */
430
+ .kerne-section-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
431
+ .kerne-section-title { font-size: 15px; font-weight: 600; margin: 0; }
432
+
433
+ .kerne-rows { display: flex; flex-direction: column; gap: 10px; }
434
+ .kerne-row { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; font-size: 14px; }
435
+ .kerne-row dt { color: var(--kerne-fg-muted); margin: 0; }
436
+ .kerne-row dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
437
+
438
+ .kerne-badge {
439
+ display: inline-flex;
440
+ align-items: center;
441
+ font-size: 12px;
442
+ font-weight: 500;
443
+ padding: 2px 8px;
444
+ border-radius: 999px;
445
+ background: var(--kerne-panel);
446
+ color: var(--kerne-fg-muted);
447
+ white-space: nowrap;
448
+ }
449
+ .kerne-badge[data-tone="success"] { color: var(--kerne-success); }
450
+ .kerne-badge[data-tone="warning"] { color: var(--kerne-warning); }
451
+ .kerne-badge[data-tone="danger"] { color: var(--kerne-danger); }
452
+
453
+ /* ---------- Identity ---------- */
454
+ .kerne-avatar {
455
+ width: 32px; height: 32px; border-radius: 50%;
456
+ background: var(--kerne-panel); color: var(--kerne-fg-muted);
457
+ display: flex; align-items: center; justify-content: center;
458
+ font-size: 12px; font-weight: 600; letter-spacing: .02em; flex-shrink: 0;
459
+ object-fit: cover;
460
+ }
461
+ .kerne-identity { display: flex; align-items: center; gap: 12px; }
462
+ .kerne-identity-text { display: flex; flex-direction: column; min-width: 0; }
463
+ .kerne-identity-name { font-size: 14px; font-weight: 500; }
464
+ .kerne-identity-mail { font-size: 13px; color: var(--kerne-fg-muted); overflow: hidden; text-overflow: ellipsis; }
465
+
466
+ .kerne-menu-wrap { position: relative; display: inline-flex; }
467
+ .kerne-menu-trigger {
468
+ background: none; border: none; padding: 0; cursor: pointer;
469
+ border-radius: 50%; display: inline-flex; font: inherit;
470
+ }
471
+ .kerne-menu-trigger:focus-visible { outline: 2px solid var(--kerne-accent); outline-offset: 2px; }
472
+ .kerne-menu {
473
+ position: absolute; top: calc(100% + 8px); right: 0; z-index: 50;
474
+ min-width: 240px; padding: 8px;
475
+ display: flex; flex-direction: column; gap: 2px;
476
+ /* Needs an opaque ground of its own: it floats over host content. */
477
+ background: var(--kerne-surface);
478
+ border: 1px solid var(--kerne-border);
479
+ border-radius: var(--kerne-radius);
480
+ box-shadow: var(--kerne-shadow);
481
+ }
482
+ .kerne-menu-header { padding: 8px 10px 10px; border-bottom: 1px solid var(--kerne-border); margin-bottom: 6px; }
483
+ .kerne-menu-item {
484
+ font: inherit; font-size: 14px; text-align: left;
485
+ background: none; border: none; cursor: pointer;
486
+ padding: 8px 10px; border-radius: 6px; color: var(--kerne-fg);
487
+ display: block; width: 100%; text-decoration: none;
488
+ }
489
+ .kerne-menu-item:hover { background: var(--kerne-panel); }
490
+ .kerne-menu-item:focus-visible { outline: 2px solid var(--kerne-accent); outline-offset: -2px; }
491
+ .kerne-menu-item[data-tone="danger"] { color: var(--kerne-danger); }
492
+
493
+ /* ---------- Loading ---------- */
494
+ .kerne-skeleton {
495
+ background: var(--kerne-panel);
496
+ border-radius: var(--kerne-radius);
497
+ height: var(--kerne-control-height);
498
+ animation: kerne-pulse 1.6s ease-in-out infinite;
499
+ }
500
+ @keyframes kerne-pulse { 50% { opacity: .55; } }
501
+ @media (prefers-reduced-motion: reduce) {
502
+ .kerne-skeleton { animation: none; }
503
+ .kerne-spinner { animation-duration: 2s; }
504
+ .kerne-input, .kerne-button, .kerne-switch { transition: none; }
505
+ }
506
+ `;
507
+ function ensureStylesInjected() {
508
+ if (typeof document === "undefined") return;
509
+ if (document.getElementById(STYLE_ELEMENT_ID)) return;
510
+ const style = document.createElement("style");
511
+ style.id = STYLE_ELEMENT_ID;
512
+ style.textContent = CSS;
513
+ document.head.appendChild(style);
514
+ }
515
+ function parseColor(input) {
516
+ const value = input.trim();
517
+ const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(value);
518
+ if (hex) {
519
+ const digits = hex[1].length === 3 ? hex[1].split("").map((c) => c + c).join("") : hex[1];
520
+ return [
521
+ parseInt(digits.slice(0, 2), 16),
522
+ parseInt(digits.slice(2, 4), 16),
523
+ parseInt(digits.slice(4, 6), 16)
524
+ ];
525
+ }
526
+ const rgb = /^rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)/i.exec(value);
527
+ if (rgb) return [Number(rgb[1]), Number(rgb[2]), Number(rgb[3])];
528
+ return null;
529
+ }
530
+ function luminance([r, g, b]) {
531
+ const channel = (v) => {
532
+ const s = Math.min(Math.max(v, 0), 255) / 255;
533
+ return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
534
+ };
535
+ return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
536
+ }
537
+ function toHex([r, g, b]) {
538
+ const pair = (v) => Math.round(Math.min(Math.max(v, 0), 255)).toString(16).padStart(2, "0");
539
+ return `#${pair(r)}${pair(g)}${pair(b)}`;
540
+ }
541
+ function mix(color, toward, amount) {
542
+ return color.map((c) => c + (toward - c) * amount);
543
+ }
544
+ var LABEL_CROSSOVER = 0.2;
545
+ function appearanceToStyle(appearance) {
546
+ if (!appearance) return {};
547
+ const vars = {};
548
+ if (appearance.primaryColor) {
549
+ vars["--kerne-primary"] = appearance.primaryColor;
550
+ vars["--kerne-accent"] = _nullishCoalesce(appearance.accentColor, () => ( appearance.primaryColor));
551
+ const rgb = parseColor(appearance.primaryColor);
552
+ if (rgb) {
553
+ const light = luminance(rgb) > LABEL_CROSSOVER;
554
+ vars["--kerne-primary-fg"] = _nullishCoalesce(appearance.primaryTextColor, () => ( (light ? "#16171a" : "#ffffff")));
555
+ vars["--kerne-primary-hover"] = toHex(mix(rgb, light ? 0 : 255, 0.14));
556
+ } else if (appearance.primaryTextColor) {
557
+ vars["--kerne-primary-fg"] = appearance.primaryTextColor;
558
+ }
559
+ } else {
560
+ if (appearance.accentColor) vars["--kerne-accent"] = appearance.accentColor;
561
+ if (appearance.primaryTextColor) vars["--kerne-primary-fg"] = appearance.primaryTextColor;
562
+ }
563
+ if (appearance.textColor) vars["--kerne-fg"] = appearance.textColor;
564
+ if (appearance.borderColor) vars["--kerne-border-strong"] = appearance.borderColor;
565
+ if (appearance.panelColor) vars["--kerne-panel"] = appearance.panelColor;
566
+ if (appearance.background) vars["--kerne-bg"] = appearance.background;
567
+ if (appearance.surfaceColor) {
568
+ vars["--kerne-surface"] = appearance.surfaceColor;
569
+ vars["--kerne-surface-raised"] = appearance.surfaceColor;
570
+ }
571
+ if (appearance.fontFamily) vars["--kerne-font"] = appearance.fontFamily;
572
+ if (appearance.radius) vars["--kerne-radius"] = appearance.radius;
573
+ if (appearance.controlHeight) vars["--kerne-control-height"] = appearance.controlHeight;
574
+ return vars;
575
+ }
576
+ function resolveTheme(appearance) {
577
+ return _nullishCoalesce(_optionalChain([appearance, 'optionalAccess', _ => _.theme]), () => ( "light"));
578
+ }
579
+
580
+ // src/ui/primitives.tsx
581
+ var _jsxruntime = require('react/jsx-runtime');
582
+ var InsideShell = _react.createContext.call(void 0, false);
583
+ function Shell({
584
+ appearance,
585
+ className,
586
+ size = "auth",
587
+ children
588
+ }) {
589
+ ensureStylesInjected();
590
+ const nested = _react.useContext.call(void 0, InsideShell);
591
+ if (nested) {
592
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className, children });
593
+ }
594
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InsideShell.Provider, { value: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
595
+ "div",
596
+ {
597
+ className: `kerne-root${className ? ` ${className}` : ""}`,
598
+ style: appearanceToStyle(appearance),
599
+ "data-kerne-theme": resolveTheme(appearance),
600
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
601
+ "div",
602
+ {
603
+ className: "kerne-shell",
604
+ "data-kerne-size": size === "wide" ? "wide" : void 0,
605
+ "data-kerne-surface": _optionalChain([appearance, 'optionalAccess', _2 => _2.surface]) === "card" ? "card" : void 0,
606
+ children
607
+ }
608
+ )
609
+ }
610
+ ) });
611
+ }
612
+ function Subsection({
613
+ title,
614
+ description,
615
+ children
616
+ }) {
617
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "section", { className: "kerne-subsection", children: [
618
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-subsection-head", children: [
619
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "kerne-subsection-title", children: title }),
620
+ description ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-subsection-desc", children: description }) : null
621
+ ] }),
622
+ children
623
+ ] });
624
+ }
625
+ function Masthead({
626
+ logo,
627
+ title,
628
+ subtitle
629
+ }) {
630
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-masthead", children: [
631
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-logo", children: logo }) : null,
632
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-heading", children: [
633
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { className: "kerne-title", children: title }),
634
+ subtitle ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-subtitle", children: subtitle }) : null
635
+ ] })
636
+ ] });
637
+ }
638
+ function Field({
639
+ label,
640
+ type,
641
+ value,
642
+ onChange,
643
+ autoComplete,
644
+ placeholder,
645
+ disabled,
646
+ required,
647
+ invalid,
648
+ action,
649
+ code,
650
+ autoFocus
651
+ }) {
652
+ const id = _react.useId.call(void 0, );
653
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-field", children: [
654
+ action ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-label-row", children: [
655
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { className: "kerne-label", htmlFor: id, children: label }),
656
+ action
657
+ ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { className: "kerne-label", htmlFor: id, children: label }),
658
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
659
+ "input",
660
+ {
661
+ id,
662
+ className: "kerne-input",
663
+ type,
664
+ value,
665
+ onChange: (e) => onChange(e.target.value),
666
+ autoComplete,
667
+ placeholder,
668
+ disabled,
669
+ required,
670
+ "aria-invalid": invalid || void 0,
671
+ "data-kerne-code": code ? "true" : void 0,
672
+ autoFocus
673
+ }
674
+ )
675
+ ] });
676
+ }
677
+ function Button({
678
+ children,
679
+ variant = "primary",
680
+ disabled,
681
+ type = "submit",
682
+ onClick,
683
+ ariaLabel
684
+ }) {
685
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
686
+ "button",
687
+ {
688
+ type,
689
+ className: `kerne-button kerne-button-${variant}`,
690
+ disabled,
691
+ onClick,
692
+ "aria-label": ariaLabel,
693
+ children
694
+ }
695
+ );
696
+ }
697
+ function MethodSwitch({
698
+ onClick,
699
+ children
700
+ }) {
701
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "kerne-switch", onClick, children });
702
+ }
703
+ function AlertIcon() {
704
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
705
+ "svg",
706
+ {
707
+ width: "16",
708
+ height: "16",
709
+ viewBox: "0 0 24 24",
710
+ fill: "none",
711
+ stroke: "currentColor",
712
+ strokeWidth: "2",
713
+ "aria-hidden": "true",
714
+ children: [
715
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "12", cy: "12", r: "10" }),
716
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M12 8v4M12 16h.01", strokeLinecap: "round" })
717
+ ]
718
+ }
719
+ );
720
+ }
721
+ function MailIcon() {
722
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
723
+ "svg",
724
+ {
725
+ width: "16",
726
+ height: "16",
727
+ viewBox: "0 0 24 24",
728
+ fill: "none",
729
+ stroke: "currentColor",
730
+ strokeWidth: "2",
731
+ "aria-hidden": "true",
732
+ children: [
733
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "rect", { x: "2", y: "4", width: "20", height: "16", rx: "2" }),
734
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "m2 7 10 6 10-6", strokeLinecap: "round", strokeLinejoin: "round" })
735
+ ]
736
+ }
737
+ );
738
+ }
739
+ function Panel({
740
+ children,
741
+ variant = "info"
742
+ }) {
743
+ const danger = variant === "danger";
744
+ const icon = danger ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertIcon, {}) : variant === "success" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CheckIcon, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MailIcon, {});
745
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
746
+ "div",
747
+ {
748
+ className: `kerne-panel${danger ? " kerne-panel-danger" : ""}${variant === "success" ? " kerne-panel-success" : ""}`,
749
+ ...danger ? { role: "alert" } : {},
750
+ children: [
751
+ icon,
752
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children })
753
+ ]
754
+ }
755
+ );
756
+ }
757
+ function CheckIcon() {
758
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
759
+ "svg",
760
+ {
761
+ width: "16",
762
+ height: "16",
763
+ viewBox: "0 0 24 24",
764
+ fill: "none",
765
+ stroke: "currentColor",
766
+ strokeWidth: "2",
767
+ "aria-hidden": "true",
768
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "m5 13 4 4L19 7", strokeLinecap: "round", strokeLinejoin: "round" })
769
+ }
770
+ );
771
+ }
772
+ function Status({
773
+ tone,
774
+ title,
775
+ children,
776
+ action
777
+ }) {
778
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-status", ...tone === "danger" ? { role: "alert" } : {}, children: [
779
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-status-icon", "data-tone": tone === "loading" ? "muted" : tone, children: tone === "loading" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-spinner", "aria-hidden": "true" }) : tone === "success" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CheckIcon, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertIcon, {}) }),
780
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-heading", children: [
781
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { className: "kerne-title", children: title }),
782
+ children ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-status-text", children }) : null
783
+ ] }),
784
+ action
785
+ ] });
786
+ }
787
+ function Divider({ label }) {
788
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-divider", children: label });
789
+ }
790
+ function TextLink({
791
+ href,
792
+ onClick,
793
+ children
794
+ }) {
795
+ if (onClick) {
796
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "kerne-link", onClick, children });
797
+ }
798
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { className: "kerne-link", href: _nullishCoalesce(href, () => ( "#")), children });
799
+ }
800
+ var OAUTH_LABELS = {
801
+ google: "Google",
802
+ github: "GitHub",
803
+ microsoft: "Microsoft",
804
+ apple: "Apple",
805
+ gitlab: "GitLab",
806
+ discord: "Discord"
807
+ };
808
+ function OAuthIcon({ provider }) {
809
+ const common = { width: 18, height: 18, viewBox: "0 0 24 24", "aria-hidden": true };
810
+ switch (provider) {
811
+ case "google":
812
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { ...common, children: [
813
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
814
+ "path",
815
+ {
816
+ fill: "#4285F4",
817
+ d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
818
+ }
819
+ ),
820
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
821
+ "path",
822
+ {
823
+ fill: "#34A853",
824
+ d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
825
+ }
826
+ ),
827
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
828
+ "path",
829
+ {
830
+ fill: "#FBBC05",
831
+ d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
832
+ }
833
+ ),
834
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
835
+ "path",
836
+ {
837
+ fill: "#EA4335",
838
+ d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
839
+ }
840
+ )
841
+ ] });
842
+ case "github":
843
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { ...common, fill: "currentColor", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.26.8-.57v-2c-3.34.72-4.04-1.61-4.04-1.61-.55-1.39-1.34-1.76-1.34-1.76-1.09-.75.08-.73.08-.73 1.2.09 1.84 1.24 1.84 1.24 1.07 1.83 2.81 1.3 3.5 1 .1-.78.42-1.31.76-1.61-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1-.32 3.3 1.23a11.5 11.5 0 0 1 6 0c2.28-1.55 3.29-1.23 3.29-1.23.64 1.66.24 2.88.12 3.18.77.84 1.23 1.91 1.23 3.22 0 4.61-2.8 5.63-5.48 5.92.43.37.81 1.1.81 2.22v3.29c0 .31.2.68.81.57A12 12 0 0 0 12 .3z" }) });
844
+ case "apple":
845
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { ...common, fill: "currentColor", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M17.05 12.75c-.03-2.6 2.12-3.85 2.22-3.91-1.21-1.77-3.09-2.01-3.76-2.04-1.6-.16-3.12.94-3.93.94-.81 0-2.06-.92-3.39-.9-1.74.03-3.35 1.01-4.25 2.57-1.81 3.14-.46 7.79 1.3 10.34.86 1.25 1.89 2.65 3.24 2.6 1.3-.05 1.79-.84 3.36-.84 1.57 0 2.01.84 3.38.81 1.4-.02 2.28-1.27 3.13-2.53.99-1.45 1.4-2.86 1.42-2.93-.03-.01-2.72-1.04-2.75-4.13zM14.5 4.9c.71-.87 1.19-2.07 1.06-3.27-1.02.04-2.26.68-3 1.55-.66.76-1.24 1.98-1.09 3.15 1.14.09 2.31-.58 3.03-1.43z" }) });
846
+ default:
847
+ return null;
848
+ }
849
+ }
850
+ function OAuthButtons({
851
+ providers,
852
+ disabled,
853
+ onSelect
854
+ }) {
855
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
856
+ if (providers.length === 0) return null;
857
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-oauth-group", children: providers.map((provider) => {
858
+ const label = _chunk3PROPZWWcjs.fill.call(void 0, l10n.common.continueWith, {
859
+ provider: _nullishCoalesce(OAUTH_LABELS[provider], () => ( provider))
860
+ });
861
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
862
+ "button",
863
+ {
864
+ type: "button",
865
+ className: "kerne-button kerne-button-outline",
866
+ disabled,
867
+ onClick: () => _optionalChain([onSelect, 'optionalCall', _3 => _3(provider)]),
868
+ "aria-label": label,
869
+ children: [
870
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, OAuthIcon, { provider }),
871
+ label
872
+ ]
873
+ },
874
+ provider
875
+ );
876
+ }) });
877
+ }
878
+ function KerneBranding({ show }) {
879
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
880
+ if (!show) return null;
881
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { className: "kerne-branding", href: "https://kerne.io", target: "_blank", rel: "noopener noreferrer", children: l10n.common.securedByKerne });
882
+ }
883
+ function FormSkeleton() {
884
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
885
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-form", "aria-busy": "true", "aria-label": l10n.common.loading, children: [
886
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton" }),
887
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton" })
888
+ ] });
889
+ }
890
+
891
+ // src/ui/LoginForm.tsx
892
+
893
+ function LoginForm({
894
+ onSuccess,
895
+ redirectUrl,
896
+ magicLinkCallbackUrl,
897
+ signUpUrl,
898
+ onSignUpClick,
899
+ forgotPasswordUrl,
900
+ onForgotPasswordClick,
901
+ onOAuthSelect,
902
+ title,
903
+ subtitle,
904
+ legal,
905
+ appearance,
906
+ logo,
907
+ className
908
+ }) {
909
+ const client = _chunk3PROPZWWcjs.useClient.call(void 0, );
910
+ const { login, startPasswordless } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
911
+ const { config, isLoading: configLoading, error: configError } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
912
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
913
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
914
+ const [email, setEmail] = _react.useState.call(void 0, "");
915
+ const [password, setPassword] = _react.useState.call(void 0, "");
916
+ const [submitting, setSubmitting] = _react.useState.call(void 0, false);
917
+ const [error, setError] = _react.useState.call(void 0, null);
918
+ const [linkSentTo, setLinkSentTo] = _react.useState.call(void 0, null);
919
+ const [passwordMode, setPasswordMode] = _react.useState.call(void 0, false);
920
+ const shell = (children) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, children });
921
+ const hasOAuth = (_nullishCoalesce(_optionalChain([config, 'optionalAccess', _4 => _4.oauth_providers, 'access', _5 => _5.length]), () => ( 0))) > 0;
922
+ const hasCredentials = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _6 => _6.enable_credentials]), () => ( false));
923
+ const hasMagicLink = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _7 => _7.enable_magic_link]), () => ( false));
924
+ const hasEmailMethod = hasCredentials || hasMagicLink;
925
+ const usePassword = passwordMode || !hasMagicLink && hasCredentials;
926
+ const handleSubmit = async (e) => {
927
+ e.preventDefault();
928
+ setError(null);
929
+ setSubmitting(true);
930
+ try {
931
+ if (usePassword) {
932
+ await login({ email, password });
933
+ if (redirectUrl) {
934
+ await client.redirectWithSession(redirectUrl);
935
+ } else {
936
+ _optionalChain([onSuccess, 'optionalCall', _8 => _8()]);
937
+ }
938
+ } else {
939
+ await startPasswordless(email, magicLinkCallbackUrl);
940
+ setLinkSentTo(email);
941
+ }
942
+ } catch (err) {
943
+ setError(showError(err));
944
+ setSubmitting(false);
945
+ }
946
+ };
947
+ const appName = _optionalChain([config, 'optionalAccess', _9 => _9.app_name]);
948
+ const heading = _nullishCoalesce(title, () => ( l10n.signIn.title));
949
+ if (configLoading) {
950
+ return shell(
951
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
952
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
953
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FormSkeleton, {})
954
+ ] })
955
+ );
956
+ }
957
+ if (configError || !config) {
958
+ return shell(
959
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
960
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
961
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: l10n.signIn.loadFailed })
962
+ ] })
963
+ );
964
+ }
965
+ if (!hasEmailMethod && !hasOAuth) {
966
+ return shell(
967
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
968
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
969
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: l10n.signIn.unavailable })
970
+ ] })
971
+ );
972
+ }
973
+ const canSignUp = config.registration_mode !== "CLOSED";
974
+ const signUpLine = canSignUp && (signUpUrl || onSignUpClick) ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
975
+ l10n.signIn.signUpPrompt,
976
+ " ",
977
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TextLink, { href: signUpUrl, onClick: onSignUpClick, children: appName ? _chunk3PROPZWWcjs.fill.call(void 0, l10n.signIn.signUpForApp, { app: appName }) : l10n.signIn.signUpLink }),
978
+ "."
979
+ ] }) : void 0;
980
+ const submitLabel = submitting ? usePassword ? l10n.signIn.submitting : l10n.signIn.magicSubmitting : usePassword ? l10n.signIn.submit : l10n.signIn.magicSubmit;
981
+ return shell(
982
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
983
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading, subtitle: _nullishCoalesce(subtitle, () => ( signUpLine)) }),
984
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
985
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
986
+ linkSentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: _chunk3PROPZWWcjs.fillNode.call(void 0, l10n.signIn.linkSent, { email: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: linkSentTo }) }) }) : hasEmailMethod ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSubmit, children: [
987
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
988
+ Field,
989
+ {
990
+ label: l10n.common.email,
991
+ type: "email",
992
+ value: email,
993
+ onChange: setEmail,
994
+ autoComplete: "email",
995
+ placeholder: l10n.common.emailPlaceholder,
996
+ disabled: submitting,
997
+ required: true,
998
+ autoFocus: true
999
+ }
1000
+ ),
1001
+ usePassword ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1002
+ Field,
1003
+ {
1004
+ label: l10n.common.password,
1005
+ type: "password",
1006
+ value: password,
1007
+ onChange: setPassword,
1008
+ autoComplete: "current-password",
1009
+ placeholder: l10n.common.passwordPlaceholder,
1010
+ disabled: submitting,
1011
+ required: true,
1012
+ action: forgotPasswordUrl || onForgotPasswordClick ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TextLink, { href: forgotPasswordUrl, onClick: onForgotPasswordClick, children: l10n.signIn.forgotPassword }) : void 0
1013
+ }
1014
+ ) : null,
1015
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { disabled: submitting || !email || usePassword && !password, children: submitLabel }),
1016
+ hasCredentials && hasMagicLink ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1017
+ MethodSwitch,
1018
+ {
1019
+ onClick: () => {
1020
+ setPasswordMode((v) => !v);
1021
+ setError(null);
1022
+ },
1023
+ children: usePassword ? l10n.signIn.useMagicLink : l10n.signIn.usePassword
1024
+ }
1025
+ ) : null
1026
+ ] }) : null,
1027
+ hasOAuth && hasEmailMethod ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Divider, { label: l10n.common.or }) : null,
1028
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1029
+ OAuthButtons,
1030
+ {
1031
+ providers: config.oauth_providers,
1032
+ disabled: submitting,
1033
+ onSelect: onOAuthSelect
1034
+ }
1035
+ )
1036
+ ] }),
1037
+ legal ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-legal", children: legal }) : null,
1038
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: config.show_kerne_branding })
1039
+ ] })
1040
+ );
1041
+ }
1042
+
1043
+ // src/ui/RegisterForm.tsx
1044
+
1045
+
1046
+ function RegisterForm({
1047
+ onSuccess,
1048
+ redirectUrl,
1049
+ magicLinkCallbackUrl,
1050
+ invitationToken: invitationTokenProp,
1051
+ signInUrl,
1052
+ onSignInClick,
1053
+ onOAuthSelect,
1054
+ title,
1055
+ subtitle,
1056
+ legal,
1057
+ collectName = true,
1058
+ appearance,
1059
+ logo,
1060
+ className
1061
+ }) {
1062
+ const client = _chunk3PROPZWWcjs.useClient.call(void 0, );
1063
+ const { register, startPasswordless } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
1064
+ const { config, isLoading: configLoading, error: configError } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
1065
+ const invitationToken = useUrlToken("token", invitationTokenProp) || void 0;
1066
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
1067
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
1068
+ const [email, setEmail] = _react.useState.call(void 0, "");
1069
+ const [password, setPassword] = _react.useState.call(void 0, "");
1070
+ const [name, setName] = _react.useState.call(void 0, "");
1071
+ const [invitationCode, setInvitationCode] = _react.useState.call(void 0, "");
1072
+ const [submitting, setSubmitting] = _react.useState.call(void 0, false);
1073
+ const [error, setError] = _react.useState.call(void 0, null);
1074
+ const [linkSentTo, setLinkSentTo] = _react.useState.call(void 0, null);
1075
+ const [passwordMode, setPasswordMode] = _react.useState.call(void 0, false);
1076
+ const shell = (children) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, children });
1077
+ const appName = _optionalChain([config, 'optionalAccess', _10 => _10.app_name]);
1078
+ const heading = _nullishCoalesce(title, () => ( (appName ? _chunk3PROPZWWcjs.fill.call(void 0, l10n.signUp.titleWithApp, { app: appName }) : l10n.signUp.title)));
1079
+ const signInLine = signInUrl || onSignInClick ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1080
+ l10n.signUp.signInPrompt,
1081
+ " ",
1082
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TextLink, { href: signInUrl, onClick: onSignInClick, children: l10n.signUp.signInLink }),
1083
+ "."
1084
+ ] }) : void 0;
1085
+ if (configLoading) {
1086
+ return shell(
1087
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1088
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
1089
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FormSkeleton, {})
1090
+ ] })
1091
+ );
1092
+ }
1093
+ if (configError || !config) {
1094
+ return shell(
1095
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1096
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
1097
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: l10n.signUp.loadFailed })
1098
+ ] })
1099
+ );
1100
+ }
1101
+ if (config.registration_mode === "CLOSED") {
1102
+ return shell(
1103
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1104
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: l10n.signUp.closedTitle, subtitle: signInLine }),
1105
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: _chunk3PROPZWWcjs.fill.call(void 0, l10n.signUp.closedBody, { app: _nullishCoalesce(appName, () => ( l10n.common.thisApp)) }) }),
1106
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: config.show_kerne_branding })
1107
+ ] })
1108
+ );
1109
+ }
1110
+ const hasOAuth = config.oauth_providers.length > 0;
1111
+ const hasCredentials = config.enable_credentials;
1112
+ const hasMagicLink = config.enable_magic_link;
1113
+ const hasEmailMethod = hasCredentials || hasMagicLink;
1114
+ const usePassword = passwordMode || !hasMagicLink && hasCredentials;
1115
+ const needsCode = config.registration_mode === "INVITE_ONLY" && !invitationToken;
1116
+ const handleSubmit = async (e) => {
1117
+ e.preventDefault();
1118
+ setError(null);
1119
+ setSubmitting(true);
1120
+ try {
1121
+ if (usePassword) {
1122
+ await register({
1123
+ email,
1124
+ password,
1125
+ name: collectName && name ? name : void 0,
1126
+ invitationToken,
1127
+ invitationCode: invitationCode || void 0
1128
+ });
1129
+ if (redirectUrl) {
1130
+ await client.redirectWithSession(redirectUrl);
1131
+ } else {
1132
+ _optionalChain([onSuccess, 'optionalCall', _11 => _11()]);
1133
+ }
1134
+ } else {
1135
+ await startPasswordless(email, magicLinkCallbackUrl, {
1136
+ invitationToken,
1137
+ invitationCode: invitationCode || void 0
1138
+ });
1139
+ setLinkSentTo(email);
1140
+ }
1141
+ } catch (err) {
1142
+ setError(showError(err));
1143
+ setSubmitting(false);
1144
+ }
1145
+ };
1146
+ if (!hasEmailMethod && !hasOAuth) {
1147
+ return shell(
1148
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1149
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
1150
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: l10n.signUp.unavailable })
1151
+ ] })
1152
+ );
1153
+ }
1154
+ const submitLabel = submitting ? usePassword ? l10n.signUp.submitting : l10n.signUp.magicSubmitting : usePassword ? l10n.signUp.submit : l10n.signUp.magicSubmit;
1155
+ return shell(
1156
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1157
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1158
+ Masthead,
1159
+ {
1160
+ logo,
1161
+ title: heading,
1162
+ subtitle: _nullishCoalesce(subtitle, () => ( (needsCode ? l10n.signUp.invitationNeeded : signInLine)))
1163
+ }
1164
+ ),
1165
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
1166
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
1167
+ linkSentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: _chunk3PROPZWWcjs.fillNode.call(void 0, l10n.signUp.linkSent, { email: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: linkSentTo }) }) }) : hasEmailMethod ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSubmit, children: [
1168
+ needsCode ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1169
+ Field,
1170
+ {
1171
+ label: l10n.signUp.invitationCode,
1172
+ type: "text",
1173
+ value: invitationCode,
1174
+ onChange: setInvitationCode,
1175
+ placeholder: "XXXXXX",
1176
+ autoComplete: "one-time-code",
1177
+ disabled: submitting,
1178
+ required: true,
1179
+ code: true,
1180
+ autoFocus: true
1181
+ }
1182
+ ) : null,
1183
+ collectName && usePassword ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1184
+ Field,
1185
+ {
1186
+ label: l10n.common.name,
1187
+ type: "text",
1188
+ value: name,
1189
+ onChange: setName,
1190
+ autoComplete: "name",
1191
+ placeholder: l10n.common.namePlaceholder,
1192
+ disabled: submitting
1193
+ }
1194
+ ) : null,
1195
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1196
+ Field,
1197
+ {
1198
+ label: l10n.common.email,
1199
+ type: "email",
1200
+ value: email,
1201
+ onChange: setEmail,
1202
+ autoComplete: "email",
1203
+ placeholder: l10n.common.emailPlaceholder,
1204
+ disabled: submitting,
1205
+ required: true,
1206
+ autoFocus: !needsCode
1207
+ }
1208
+ ),
1209
+ usePassword ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1210
+ Field,
1211
+ {
1212
+ label: l10n.common.password,
1213
+ type: "password",
1214
+ value: password,
1215
+ onChange: setPassword,
1216
+ autoComplete: "new-password",
1217
+ placeholder: l10n.common.passwordPlaceholder,
1218
+ disabled: submitting,
1219
+ required: true
1220
+ }
1221
+ ) : null,
1222
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1223
+ Button,
1224
+ {
1225
+ disabled: submitting || !email || needsCode && !invitationCode || usePassword && !password,
1226
+ children: submitLabel
1227
+ }
1228
+ ),
1229
+ hasCredentials && hasMagicLink ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1230
+ MethodSwitch,
1231
+ {
1232
+ onClick: () => {
1233
+ setPasswordMode((v) => !v);
1234
+ setError(null);
1235
+ },
1236
+ children: usePassword ? l10n.signUp.useMagicLink : l10n.signUp.usePassword
1237
+ }
1238
+ ) : null
1239
+ ] }) : null,
1240
+ hasOAuth && hasEmailMethod ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Divider, { label: l10n.common.or }) : null,
1241
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1242
+ OAuthButtons,
1243
+ {
1244
+ providers: config.oauth_providers,
1245
+ disabled: submitting,
1246
+ onSelect: onOAuthSelect
1247
+ }
1248
+ )
1249
+ ] }),
1250
+ legal ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-legal", children: legal }) : null,
1251
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: config.show_kerne_branding })
1252
+ ] })
1253
+ );
1254
+ }
1255
+
1256
+ // src/ui/ForgotPasswordForm.tsx
1257
+
1258
+
1259
+ function ForgotPasswordForm({
1260
+ callbackUrl,
1261
+ signInUrl,
1262
+ onSignInClick,
1263
+ onSent,
1264
+ title,
1265
+ subtitle,
1266
+ appearance,
1267
+ logo,
1268
+ className
1269
+ }) {
1270
+ const { requestPasswordReset } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
1271
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
1272
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
1273
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
1274
+ const [email, setEmail] = _react.useState.call(void 0, "");
1275
+ const [submitting, setSubmitting] = _react.useState.call(void 0, false);
1276
+ const [error, setError] = _react.useState.call(void 0, null);
1277
+ const [sentTo, setSentTo] = _react.useState.call(void 0, null);
1278
+ const handleSubmit = async (e) => {
1279
+ e.preventDefault();
1280
+ setError(null);
1281
+ setSubmitting(true);
1282
+ try {
1283
+ await requestPasswordReset(email, callbackUrl);
1284
+ setSentTo(email);
1285
+ _optionalChain([onSent, 'optionalCall', _12 => _12(email)]);
1286
+ } catch (err) {
1287
+ setError(showError(err));
1288
+ } finally {
1289
+ setSubmitting(false);
1290
+ }
1291
+ };
1292
+ const backLine = signInUrl || onSignInClick ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1293
+ l10n.resetPassword.rememberedPrompt,
1294
+ " ",
1295
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TextLink, { href: signInUrl, onClick: onSignInClick, children: l10n.common.backToSignIn }),
1296
+ "."
1297
+ ] }) : void 0;
1298
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1299
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1300
+ Masthead,
1301
+ {
1302
+ logo,
1303
+ title: _nullishCoalesce(title, () => ( l10n.resetPassword.requestTitle)),
1304
+ subtitle: _nullishCoalesce(subtitle, () => ( (sentTo ? backLine : l10n.resetPassword.requestSubtitle)))
1305
+ }
1306
+ ),
1307
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
1308
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
1309
+ sentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: _chunk3PROPZWWcjs.fillNode.call(void 0, l10n.resetPassword.requestSent, { email: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: sentTo }) }) }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSubmit, children: [
1310
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1311
+ Field,
1312
+ {
1313
+ label: l10n.common.email,
1314
+ type: "email",
1315
+ value: email,
1316
+ onChange: setEmail,
1317
+ autoComplete: "email",
1318
+ placeholder: l10n.common.emailPlaceholder,
1319
+ disabled: submitting,
1320
+ required: true,
1321
+ autoFocus: true
1322
+ }
1323
+ ),
1324
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { disabled: submitting || !email, children: submitting ? l10n.resetPassword.requestSubmitting : l10n.resetPassword.requestSubmit }),
1325
+ backLine ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-footer", children: backLine }) : null
1326
+ ] })
1327
+ ] }),
1328
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _13 => _13.show_kerne_branding]), () => ( false)) })
1329
+ ] });
1330
+ }
1331
+
1332
+ // src/ui/ResetPasswordForm.tsx
1333
+
1334
+
1335
+ function ResetPasswordForm({
1336
+ token: tokenProp,
1337
+ signInUrl,
1338
+ onSignInClick,
1339
+ onSuccess,
1340
+ title,
1341
+ subtitle,
1342
+ appearance,
1343
+ logo,
1344
+ className
1345
+ }) {
1346
+ const { confirmPasswordReset } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
1347
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
1348
+ const token = useUrlToken("token", tokenProp);
1349
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
1350
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
1351
+ const [password, setPassword] = _react.useState.call(void 0, "");
1352
+ const [confirm, setConfirm] = _react.useState.call(void 0, "");
1353
+ const [submitting, setSubmitting] = _react.useState.call(void 0, false);
1354
+ const [error, setError] = _react.useState.call(void 0, null);
1355
+ const [done, setDone] = _react.useState.call(void 0, false);
1356
+ const heading = _nullishCoalesce(title, () => ( l10n.resetPassword.title));
1357
+ const mismatch = confirm.length > 0 && password !== confirm;
1358
+ const signInAction = signInUrl || onSignInClick ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1359
+ Button,
1360
+ {
1361
+ type: "button",
1362
+ onClick: _nullishCoalesce(onSignInClick, () => ( (() => {
1363
+ if (signInUrl) window.location.href = signInUrl;
1364
+ }))),
1365
+ children: l10n.signIn.submit
1366
+ }
1367
+ ) : void 0;
1368
+ const handleSubmit = async (e) => {
1369
+ e.preventDefault();
1370
+ if (mismatch || !token) return;
1371
+ setError(null);
1372
+ setSubmitting(true);
1373
+ try {
1374
+ await confirmPasswordReset(token, password);
1375
+ setDone(true);
1376
+ _optionalChain([onSuccess, 'optionalCall', _14 => _14()]);
1377
+ } catch (err) {
1378
+ setError(showError(err));
1379
+ } finally {
1380
+ setSubmitting(false);
1381
+ }
1382
+ };
1383
+ if (token === null) {
1384
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1385
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
1386
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FormSkeleton, {})
1387
+ ] });
1388
+ }
1389
+ if (token === "") {
1390
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1391
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
1392
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "danger", title: l10n.resetPassword.incompleteTitle, action: signInAction, children: l10n.resetPassword.incompleteBody }),
1393
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _15 => _15.show_kerne_branding]), () => ( false)) })
1394
+ ] });
1395
+ }
1396
+ if (done) {
1397
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1398
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
1399
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "success", title: l10n.resetPassword.doneTitle, action: signInAction, children: l10n.resetPassword.doneBody }),
1400
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _16 => _16.show_kerne_branding]), () => ( false)) })
1401
+ ] });
1402
+ }
1403
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1404
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading, subtitle: _nullishCoalesce(subtitle, () => ( l10n.resetPassword.subtitle)) }),
1405
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
1406
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
1407
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSubmit, children: [
1408
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1409
+ Field,
1410
+ {
1411
+ label: l10n.resetPassword.newPassword,
1412
+ type: "password",
1413
+ value: password,
1414
+ onChange: setPassword,
1415
+ autoComplete: "new-password",
1416
+ placeholder: l10n.common.passwordPlaceholder,
1417
+ disabled: submitting,
1418
+ required: true,
1419
+ autoFocus: true
1420
+ }
1421
+ ),
1422
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1423
+ Field,
1424
+ {
1425
+ label: l10n.resetPassword.confirmPassword,
1426
+ type: "password",
1427
+ value: confirm,
1428
+ onChange: setConfirm,
1429
+ autoComplete: "new-password",
1430
+ placeholder: l10n.common.passwordPlaceholder,
1431
+ disabled: submitting,
1432
+ required: true,
1433
+ invalid: mismatch
1434
+ }
1435
+ ),
1436
+ mismatch ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-footer", children: l10n.resetPassword.mismatch }) : null,
1437
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { disabled: submitting || !password || !confirm || mismatch, children: submitting ? l10n.resetPassword.submitting : l10n.resetPassword.submit }),
1438
+ signInUrl || onSignInClick ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-footer", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TextLink, { href: signInUrl, onClick: onSignInClick, children: l10n.common.backToSignIn }) }) : null
1439
+ ] })
1440
+ ] }),
1441
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _17 => _17.show_kerne_branding]), () => ( false)) })
1442
+ ] });
1443
+ }
1444
+
1445
+ // src/ui/MagicLinkCallback.tsx
1446
+
1447
+
1448
+ function MagicLinkCallback({
1449
+ token: tokenProp,
1450
+ onSuccess,
1451
+ redirectUrl,
1452
+ signInUrl,
1453
+ onSignInClick,
1454
+ appearance,
1455
+ logo,
1456
+ className
1457
+ }) {
1458
+ const client = _chunk3PROPZWWcjs.useClient.call(void 0, );
1459
+ const { loginWithMagicLink } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
1460
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
1461
+ const token = useUrlToken("token", tokenProp);
1462
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
1463
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
1464
+ const [state, setState] = _react.useState.call(void 0, "pending");
1465
+ const [message, setMessage] = _react.useState.call(void 0, null);
1466
+ const consumed = _react.useRef.call(void 0, false);
1467
+ _react.useEffect.call(void 0, () => {
1468
+ if (token === null || consumed.current) return;
1469
+ if (token === "") {
1470
+ setState("failed");
1471
+ return;
1472
+ }
1473
+ consumed.current = true;
1474
+ loginWithMagicLink(token).then(async () => {
1475
+ setState("done");
1476
+ if (redirectUrl) {
1477
+ await client.redirectWithSession(redirectUrl);
1478
+ } else {
1479
+ _optionalChain([onSuccess, 'optionalCall', _18 => _18()]);
1480
+ }
1481
+ }).catch((e) => {
1482
+ setState("failed");
1483
+ setMessage(showError(e));
1484
+ });
1485
+ }, [token, loginWithMagicLink, redirectUrl, client, onSuccess]);
1486
+ const retry = signInUrl || onSignInClick ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1487
+ Button,
1488
+ {
1489
+ variant: "outline",
1490
+ type: "button",
1491
+ onClick: _nullishCoalesce(onSignInClick, () => ( (() => {
1492
+ if (signInUrl) window.location.href = signInUrl;
1493
+ }))),
1494
+ children: l10n.common.backToSignIn
1495
+ }
1496
+ ) : void 0;
1497
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1498
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
1499
+ state === "pending" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "loading", title: l10n.magicLink.pendingTitle, children: l10n.magicLink.pendingBody }) : state === "done" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "success", title: l10n.magicLink.doneTitle, children: l10n.magicLink.doneBody }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "danger", title: l10n.magicLink.failedTitle, action: retry, children: _nullishCoalesce(message, () => ( l10n.magicLink.missingToken)) }),
1500
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _19 => _19.show_kerne_branding]), () => ( false)) })
1501
+ ] });
1502
+ }
1503
+
1504
+ // src/ui/VerifyEmailForm.tsx
1505
+
1506
+
1507
+ function VerifyEmailForm({
1508
+ token: tokenProp,
1509
+ callbackUrl,
1510
+ onVerified,
1511
+ title,
1512
+ subtitle,
1513
+ appearance,
1514
+ logo,
1515
+ className
1516
+ }) {
1517
+ const { verifyEmailWithCode, verifyEmailWithLink, sendVerificationEmail, refreshToken } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
1518
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
1519
+ const token = useUrlToken("token", tokenProp);
1520
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
1521
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
1522
+ const [code, setCode] = _react.useState.call(void 0, "");
1523
+ const [submitting, setSubmitting] = _react.useState.call(void 0, false);
1524
+ const [error, setError] = _react.useState.call(void 0, null);
1525
+ const [resent, setResent] = _react.useState.call(void 0, false);
1526
+ const [linkState, setLinkState] = _react.useState.call(void 0, "idle");
1527
+ const [verified, setVerified] = _react.useState.call(void 0, false);
1528
+ const consumed = _react.useRef.call(void 0, false);
1529
+ const heading = _nullishCoalesce(title, () => ( l10n.verifyEmail.title));
1530
+ const settle = async (needsTokenRefresh) => {
1531
+ if (needsTokenRefresh) {
1532
+ await refreshToken().catch(() => void 0);
1533
+ }
1534
+ setVerified(true);
1535
+ _optionalChain([onVerified, 'optionalCall', _20 => _20()]);
1536
+ };
1537
+ _react.useEffect.call(void 0, () => {
1538
+ if (token === null || token === "" || consumed.current) return;
1539
+ consumed.current = true;
1540
+ setLinkState("pending");
1541
+ verifyEmailWithLink(token).then(async (r) => {
1542
+ await settle(r.needsTokenRefresh);
1543
+ setLinkState("done");
1544
+ }).catch((e) => {
1545
+ setLinkState("failed");
1546
+ setError(showError(e));
1547
+ });
1548
+ }, [token, verifyEmailWithLink]);
1549
+ const handleSubmit = async (e) => {
1550
+ e.preventDefault();
1551
+ setError(null);
1552
+ setSubmitting(true);
1553
+ try {
1554
+ const r = await verifyEmailWithCode(code);
1555
+ await settle(r.needsTokenRefresh);
1556
+ } catch (err) {
1557
+ setError(showError(err));
1558
+ } finally {
1559
+ setSubmitting(false);
1560
+ }
1561
+ };
1562
+ const handleResend = async () => {
1563
+ setError(null);
1564
+ try {
1565
+ await sendVerificationEmail("code", callbackUrl);
1566
+ setResent(true);
1567
+ } catch (err) {
1568
+ setError(showError(err));
1569
+ }
1570
+ };
1571
+ if (verified) {
1572
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1573
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
1574
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "success", title: l10n.verifyEmail.doneTitle, children: l10n.verifyEmail.doneBody }),
1575
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _21 => _21.show_kerne_branding]), () => ( false)) })
1576
+ ] });
1577
+ }
1578
+ if (linkState === "pending") {
1579
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1580
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
1581
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "loading", title: l10n.verifyEmail.verifyingTitle, children: l10n.verifyEmail.verifyingBody })
1582
+ ] });
1583
+ }
1584
+ if (linkState === "failed") {
1585
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1586
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
1587
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1588
+ Status,
1589
+ {
1590
+ tone: "danger",
1591
+ title: l10n.verifyEmail.failedTitle,
1592
+ action: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", type: "button", onClick: handleResend, children: l10n.verifyEmail.newCode }),
1593
+ children: error
1594
+ }
1595
+ ),
1596
+ resent ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "success", children: l10n.verifyEmail.resent }) : null,
1597
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _22 => _22.show_kerne_branding]), () => ( false)) })
1598
+ ] });
1599
+ }
1600
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1601
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading, subtitle: _nullishCoalesce(subtitle, () => ( l10n.verifyEmail.subtitle)) }),
1602
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
1603
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
1604
+ resent ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "success", children: l10n.verifyEmail.resent }) : null,
1605
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSubmit, children: [
1606
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1607
+ Field,
1608
+ {
1609
+ label: l10n.verifyEmail.code,
1610
+ type: "text",
1611
+ value: code,
1612
+ onChange: setCode,
1613
+ autoComplete: "one-time-code",
1614
+ placeholder: "000000",
1615
+ disabled: submitting,
1616
+ required: true,
1617
+ code: true,
1618
+ autoFocus: true
1619
+ }
1620
+ ),
1621
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { disabled: submitting || !code, children: submitting ? l10n.verifyEmail.submitting : l10n.verifyEmail.submit }),
1622
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MethodSwitch, { onClick: handleResend, children: l10n.verifyEmail.resend })
1623
+ ] })
1624
+ ] }),
1625
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _23 => _23.show_kerne_branding]), () => ( false)) })
1626
+ ] });
1627
+ }
1628
+
1629
+ // src/ui/ActivateAccountForm.tsx
1630
+
1631
+
1632
+ function ActivateAccountForm({
1633
+ token: tokenProp,
1634
+ onSuccess,
1635
+ redirectUrl,
1636
+ signInUrl,
1637
+ onSignInClick,
1638
+ title,
1639
+ appearance,
1640
+ logo,
1641
+ className
1642
+ }) {
1643
+ const client = _chunk3PROPZWWcjs.useClient.call(void 0, );
1644
+ const { getActivationContext, completeActivation } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
1645
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
1646
+ const token = useUrlToken("token", tokenProp);
1647
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
1648
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
1649
+ const [context, setContext] = _react.useState.call(void 0, null);
1650
+ const [loadError, setLoadError] = _react.useState.call(void 0, null);
1651
+ const [password, setPassword] = _react.useState.call(void 0, "");
1652
+ const [confirm, setConfirm] = _react.useState.call(void 0, "");
1653
+ const [submitting, setSubmitting] = _react.useState.call(void 0, false);
1654
+ const [error, setError] = _react.useState.call(void 0, null);
1655
+ const heading = _nullishCoalesce(title, () => ( l10n.activate.title));
1656
+ const mismatch = confirm.length > 0 && password !== confirm;
1657
+ _react.useEffect.call(void 0, () => {
1658
+ if (!token) return;
1659
+ let mounted = true;
1660
+ getActivationContext(token).then((c) => mounted && setContext(c)).catch((e) => mounted && setLoadError(showError(e)));
1661
+ return () => {
1662
+ mounted = false;
1663
+ };
1664
+ }, [token, getActivationContext]);
1665
+ const signInAction = signInUrl || onSignInClick ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1666
+ Button,
1667
+ {
1668
+ type: "button",
1669
+ onClick: _nullishCoalesce(onSignInClick, () => ( (() => {
1670
+ if (signInUrl) window.location.href = signInUrl;
1671
+ }))),
1672
+ children: l10n.activate.goToSignIn
1673
+ }
1674
+ ) : void 0;
1675
+ const handleSubmit = async (e) => {
1676
+ e.preventDefault();
1677
+ if (!token || mismatch) return;
1678
+ setError(null);
1679
+ setSubmitting(true);
1680
+ try {
1681
+ await completeActivation(token, _optionalChain([context, 'optionalAccess', _24 => _24.mode]) === "credentials" ? password : void 0);
1682
+ if (redirectUrl) {
1683
+ await client.redirectWithSession(redirectUrl);
1684
+ } else {
1685
+ _optionalChain([onSuccess, 'optionalCall', _25 => _25()]);
1686
+ }
1687
+ } catch (err) {
1688
+ setError(showError(err));
1689
+ setSubmitting(false);
1690
+ }
1691
+ };
1692
+ if (token === null) {
1693
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1694
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
1695
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FormSkeleton, {})
1696
+ ] });
1697
+ }
1698
+ if (token === "" || loadError) {
1699
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1700
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
1701
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "danger", title: l10n.activate.failedTitle, action: signInAction, children: _nullishCoalesce(loadError, () => ( l10n.activate.missingToken)) }),
1702
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _26 => _26.show_kerne_branding]), () => ( false)) })
1703
+ ] });
1704
+ }
1705
+ if (!context) {
1706
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1707
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading }),
1708
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FormSkeleton, {})
1709
+ ] });
1710
+ }
1711
+ const credentialsMode = context.mode === "credentials";
1712
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1713
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1714
+ Masthead,
1715
+ {
1716
+ logo,
1717
+ title: heading,
1718
+ subtitle: _chunk3PROPZWWcjs.fillNode.call(void 0,
1719
+ credentialsMode ? l10n.activate.credentialsSubtitle : l10n.activate.magicSubtitle,
1720
+ { email: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: context.email }) }
1721
+ )
1722
+ }
1723
+ ),
1724
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
1725
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
1726
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSubmit, children: [
1727
+ credentialsMode ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1728
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1729
+ Field,
1730
+ {
1731
+ label: l10n.common.password,
1732
+ type: "password",
1733
+ value: password,
1734
+ onChange: setPassword,
1735
+ autoComplete: "new-password",
1736
+ placeholder: l10n.common.passwordPlaceholder,
1737
+ disabled: submitting,
1738
+ required: true,
1739
+ autoFocus: true
1740
+ }
1741
+ ),
1742
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1743
+ Field,
1744
+ {
1745
+ label: l10n.activate.confirmPassword,
1746
+ type: "password",
1747
+ value: confirm,
1748
+ onChange: setConfirm,
1749
+ autoComplete: "new-password",
1750
+ placeholder: l10n.common.passwordPlaceholder,
1751
+ disabled: submitting,
1752
+ required: true,
1753
+ invalid: mismatch
1754
+ }
1755
+ ),
1756
+ mismatch ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-footer", children: l10n.activate.mismatch }) : null
1757
+ ] }) : null,
1758
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { disabled: submitting || credentialsMode && (!password || !confirm || mismatch), children: submitting ? l10n.activate.submitting : l10n.activate.submit })
1759
+ ] })
1760
+ ] }),
1761
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _27 => _27.show_kerne_branding]), () => ( false)) })
1762
+ ] });
1763
+ }
1764
+
1765
+ // src/ui/AuthFlow.tsx
1766
+
1767
+ var TOKEN_STEPS = ["reset-password", "magic-link", "activate", "verify-email"];
1768
+ function AuthFlow({
1769
+ initialStep,
1770
+ step: controlledStep,
1771
+ onStepChange,
1772
+ onSuccess,
1773
+ redirectUrl,
1774
+ magicLinkCallbackUrl,
1775
+ resetPasswordCallbackUrl,
1776
+ verificationCallbackUrl,
1777
+ allowSignUp = true,
1778
+ legal,
1779
+ appearance,
1780
+ logo,
1781
+ className
1782
+ }) {
1783
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
1784
+ const token = useUrlToken("token");
1785
+ const [internalStep, setInternalStep] = _react.useState.call(void 0, null);
1786
+ const go = (next) => {
1787
+ if (controlledStep === void 0) setInternalStep(next);
1788
+ _optionalChain([onStepChange, 'optionalCall', _28 => _28(next)]);
1789
+ };
1790
+ const tokenStep = token && (initialStep === void 0 || TOKEN_STEPS.includes(initialStep)) ? _nullishCoalesce(initialStep, () => ( "magic-link")) : null;
1791
+ const step = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(controlledStep, () => ( internalStep)), () => ( tokenStep)), () => ( initialStep)), () => ( "sign-in"));
1792
+ const canSignUp = allowSignUp && _optionalChain([config, 'optionalAccess', _29 => _29.registration_mode]) !== "CLOSED";
1793
+ const shared = { appearance, logo, className };
1794
+ switch (step) {
1795
+ case "sign-up":
1796
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1797
+ RegisterForm,
1798
+ {
1799
+ ...shared,
1800
+ onSuccess,
1801
+ redirectUrl,
1802
+ magicLinkCallbackUrl,
1803
+ onSignInClick: () => go("sign-in"),
1804
+ legal
1805
+ }
1806
+ );
1807
+ case "forgot-password":
1808
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1809
+ ForgotPasswordForm,
1810
+ {
1811
+ ...shared,
1812
+ callbackUrl: resetPasswordCallbackUrl,
1813
+ onSignInClick: () => go("sign-in")
1814
+ }
1815
+ );
1816
+ case "reset-password":
1817
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ResetPasswordForm, { ...shared, onSignInClick: () => go("sign-in"), onSuccess });
1818
+ case "magic-link":
1819
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1820
+ MagicLinkCallback,
1821
+ {
1822
+ ...shared,
1823
+ onSuccess,
1824
+ redirectUrl,
1825
+ onSignInClick: () => go("sign-in")
1826
+ }
1827
+ );
1828
+ case "verify-email":
1829
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, VerifyEmailForm, { ...shared, callbackUrl: verificationCallbackUrl, onVerified: onSuccess });
1830
+ case "activate":
1831
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1832
+ ActivateAccountForm,
1833
+ {
1834
+ ...shared,
1835
+ onSuccess,
1836
+ redirectUrl,
1837
+ onSignInClick: () => go("sign-in")
1838
+ }
1839
+ );
1840
+ case "sign-in":
1841
+ default:
1842
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1843
+ LoginForm,
1844
+ {
1845
+ ...shared,
1846
+ onSuccess,
1847
+ redirectUrl,
1848
+ magicLinkCallbackUrl,
1849
+ onSignUpClick: canSignUp ? () => go("sign-up") : void 0,
1850
+ onForgotPasswordClick: () => go("forgot-password"),
1851
+ legal
1852
+ }
1853
+ );
1854
+ }
1855
+ }
1856
+
1857
+ // src/ui/ChangePasswordForm.tsx
1858
+
1859
+
1860
+ function ChangePasswordForm({
1861
+ onSuccess,
1862
+ title,
1863
+ appearance,
1864
+ className
1865
+ }) {
1866
+ const { updatePassword } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
1867
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
1868
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
1869
+ const heading = title === null ? null : _nullishCoalesce(title, () => ( l10n.security.submit));
1870
+ const [currentPassword, setCurrentPassword] = _react.useState.call(void 0, "");
1871
+ const [newPassword, setNewPassword] = _react.useState.call(void 0, "");
1872
+ const [confirm, setConfirm] = _react.useState.call(void 0, "");
1873
+ const [submitting, setSubmitting] = _react.useState.call(void 0, false);
1874
+ const [error, setError] = _react.useState.call(void 0, null);
1875
+ const [done, setDone] = _react.useState.call(void 0, false);
1876
+ const mismatch = confirm.length > 0 && newPassword !== confirm;
1877
+ const unchanged = newPassword.length > 0 && newPassword === currentPassword;
1878
+ const handleSubmit = async (e) => {
1879
+ e.preventDefault();
1880
+ if (mismatch || unchanged) return;
1881
+ setError(null);
1882
+ setDone(false);
1883
+ setSubmitting(true);
1884
+ try {
1885
+ await updatePassword({ currentPassword, newPassword });
1886
+ setDone(true);
1887
+ setCurrentPassword("");
1888
+ setNewPassword("");
1889
+ setConfirm("");
1890
+ _optionalChain([onSuccess, 'optionalCall', _30 => _30()]);
1891
+ } catch (err) {
1892
+ setError(showError(err));
1893
+ } finally {
1894
+ setSubmitting(false);
1895
+ }
1896
+ };
1897
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
1898
+ heading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-heading", style: { marginBottom: 20 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h1", { className: "kerne-title", children: heading }) }) : null,
1899
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
1900
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
1901
+ done ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "success", children: l10n.security.changed }) : null,
1902
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSubmit, children: [
1903
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1904
+ Field,
1905
+ {
1906
+ label: l10n.security.currentPassword,
1907
+ type: "password",
1908
+ value: currentPassword,
1909
+ onChange: setCurrentPassword,
1910
+ autoComplete: "current-password",
1911
+ placeholder: l10n.common.passwordPlaceholder,
1912
+ disabled: submitting,
1913
+ required: true
1914
+ }
1915
+ ),
1916
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1917
+ Field,
1918
+ {
1919
+ label: l10n.security.newPassword,
1920
+ type: "password",
1921
+ value: newPassword,
1922
+ onChange: setNewPassword,
1923
+ autoComplete: "new-password",
1924
+ placeholder: l10n.common.passwordPlaceholder,
1925
+ disabled: submitting,
1926
+ required: true,
1927
+ invalid: unchanged
1928
+ }
1929
+ ),
1930
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1931
+ Field,
1932
+ {
1933
+ label: l10n.security.confirmPassword,
1934
+ type: "password",
1935
+ value: confirm,
1936
+ onChange: setConfirm,
1937
+ autoComplete: "new-password",
1938
+ placeholder: l10n.common.passwordPlaceholder,
1939
+ disabled: submitting,
1940
+ required: true,
1941
+ invalid: mismatch
1942
+ }
1943
+ ),
1944
+ unchanged ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-footer", children: l10n.security.sameAsCurrent }) : mismatch ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-footer", children: l10n.security.mismatch }) : null,
1945
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1946
+ Button,
1947
+ {
1948
+ disabled: submitting || !currentPassword || !newPassword || !confirm || mismatch || unchanged,
1949
+ children: submitting ? l10n.security.submitting : l10n.security.submit
1950
+ }
1951
+ )
1952
+ ] })
1953
+ ] })
1954
+ ] });
1955
+ }
1956
+
1957
+ // src/ui/WaitlistForm.tsx
1958
+
1959
+
1960
+ function WaitlistForm({
1961
+ title,
1962
+ subtitle,
1963
+ collectName = false,
1964
+ metadata,
1965
+ submitLabel,
1966
+ successMessage,
1967
+ onJoined,
1968
+ legal,
1969
+ appearance,
1970
+ logo,
1971
+ className
1972
+ }) {
1973
+ const { join } = _chunk3PROPZWWcjs.useWaitlist.call(void 0, );
1974
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
1975
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
1976
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
1977
+ const [email, setEmail] = _react.useState.call(void 0, "");
1978
+ const [name, setName] = _react.useState.call(void 0, "");
1979
+ const [submitting, setSubmitting] = _react.useState.call(void 0, false);
1980
+ const [error, setError] = _react.useState.call(void 0, null);
1981
+ const [joined, setJoined] = _react.useState.call(void 0, false);
1982
+ const handleSubmit = async (e) => {
1983
+ e.preventDefault();
1984
+ setError(null);
1985
+ setSubmitting(true);
1986
+ try {
1987
+ await join({
1988
+ email,
1989
+ name: collectName && name ? name : void 0,
1990
+ metadata
1991
+ });
1992
+ setJoined(true);
1993
+ _optionalChain([onJoined, 'optionalCall', _31 => _31(email)]);
1994
+ } catch (err) {
1995
+ setError(showError(err));
1996
+ } finally {
1997
+ setSubmitting(false);
1998
+ }
1999
+ };
2000
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
2001
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2002
+ Masthead,
2003
+ {
2004
+ logo,
2005
+ title: _nullishCoalesce(title, () => ( l10n.waitlist.title)),
2006
+ subtitle: joined ? void 0 : _nullishCoalesce(subtitle, () => ( l10n.waitlist.subtitle))
2007
+ }
2008
+ ),
2009
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
2010
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
2011
+ joined ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "success", children: _nullishCoalesce(successMessage, () => ( l10n.waitlist.joined)) }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSubmit, children: [
2012
+ collectName ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2013
+ Field,
2014
+ {
2015
+ label: l10n.common.name,
2016
+ type: "text",
2017
+ value: name,
2018
+ onChange: setName,
2019
+ autoComplete: "name",
2020
+ placeholder: l10n.common.namePlaceholder,
2021
+ disabled: submitting
2022
+ }
2023
+ ) : null,
2024
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2025
+ Field,
2026
+ {
2027
+ label: l10n.common.email,
2028
+ type: "email",
2029
+ value: email,
2030
+ onChange: setEmail,
2031
+ autoComplete: "email",
2032
+ placeholder: l10n.common.emailPlaceholder,
2033
+ disabled: submitting,
2034
+ required: true,
2035
+ autoFocus: true
2036
+ }
2037
+ ),
2038
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { disabled: submitting || !email, children: submitting ? l10n.waitlist.submitting : _nullishCoalesce(submitLabel, () => ( l10n.waitlist.submit)) })
2039
+ ] })
2040
+ ] }),
2041
+ legal ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-legal", children: legal }) : null,
2042
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _32 => _32.show_kerne_branding]), () => ( false)) })
2043
+ ] });
2044
+ }
2045
+
2046
+ // src/ui/UserButton.tsx
2047
+
2048
+
2049
+ function SignOutButton({
2050
+ children,
2051
+ onSignedOut,
2052
+ redirectUrl,
2053
+ className,
2054
+ appearance
2055
+ }) {
2056
+ ensureStylesInjected();
2057
+ const { logout } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
2058
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2059
+ const handle = () => {
2060
+ logout();
2061
+ _optionalChain([onSignedOut, 'optionalCall', _33 => _33()]);
2062
+ if (redirectUrl && typeof window !== "undefined") window.location.href = redirectUrl;
2063
+ };
2064
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2065
+ "div",
2066
+ {
2067
+ className: "kerne-root",
2068
+ style: { ...appearanceToStyle(appearance), display: "inline-flex", width: "auto" },
2069
+ "data-kerne-theme": resolveTheme(appearance),
2070
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2071
+ "button",
2072
+ {
2073
+ type: "button",
2074
+ className: `kerne-button kerne-button-outline${className ? ` ${className}` : ""}`,
2075
+ style: { width: "auto" },
2076
+ onClick: handle,
2077
+ children: _nullishCoalesce(children, () => ( l10n.account.signOut))
2078
+ }
2079
+ )
2080
+ }
2081
+ );
2082
+ }
2083
+ function UserButton({
2084
+ items = [],
2085
+ onSignedOut,
2086
+ signOutRedirectUrl,
2087
+ signedOutFallback = null,
2088
+ appearance,
2089
+ className
2090
+ }) {
2091
+ ensureStylesInjected();
2092
+ const { logout, isAuthenticated } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
2093
+ const { user, fullName, initials, email } = _chunk3PROPZWWcjs.useUser.call(void 0, );
2094
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2095
+ const [open, setOpen] = _react.useState.call(void 0, false);
2096
+ const wrapRef = _react.useRef.call(void 0, null);
2097
+ _react.useEffect.call(void 0, () => {
2098
+ if (!open) return;
2099
+ const onPointerDown = (e) => {
2100
+ if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
2101
+ };
2102
+ const onKeyDown = (e) => {
2103
+ if (e.key === "Escape") setOpen(false);
2104
+ };
2105
+ document.addEventListener("mousedown", onPointerDown);
2106
+ document.addEventListener("keydown", onKeyDown);
2107
+ return () => {
2108
+ document.removeEventListener("mousedown", onPointerDown);
2109
+ document.removeEventListener("keydown", onKeyDown);
2110
+ };
2111
+ }, [open]);
2112
+ if (!isAuthenticated) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: signedOutFallback });
2113
+ const handleSignOut = () => {
2114
+ setOpen(false);
2115
+ logout();
2116
+ _optionalChain([onSignedOut, 'optionalCall', _34 => _34()]);
2117
+ if (signOutRedirectUrl && typeof window !== "undefined") {
2118
+ window.location.href = signOutRedirectUrl;
2119
+ }
2120
+ };
2121
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2122
+ "div",
2123
+ {
2124
+ className: `kerne-root${className ? ` ${className}` : ""}`,
2125
+ style: { ...appearanceToStyle(appearance), display: "inline-flex", width: "auto" },
2126
+ "data-kerne-theme": resolveTheme(appearance),
2127
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-menu-wrap", ref: wrapRef, children: [
2128
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2129
+ "button",
2130
+ {
2131
+ type: "button",
2132
+ className: "kerne-menu-trigger",
2133
+ "aria-haspopup": "menu",
2134
+ "aria-expanded": open,
2135
+ "aria-label": l10n.account.menuLabel,
2136
+ onClick: () => setOpen((v) => !v),
2137
+ children: _optionalChain([user, 'optionalAccess', _35 => _35.avatar]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { className: "kerne-avatar", src: user.avatar, alt: "" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-avatar", children: initials || _optionalChain([email, 'optionalAccess', _36 => _36[0], 'optionalAccess', _37 => _37.toUpperCase, 'call', _38 => _38()]) || "?" })
2138
+ }
2139
+ ),
2140
+ open ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-menu", role: "menu", children: [
2141
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-menu-header", children: [
2142
+ fullName ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-identity-name", children: fullName }) : null,
2143
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-identity-mail", children: email })
2144
+ ] }),
2145
+ items.map(
2146
+ (item) => item.href ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { role: "menuitem", className: "kerne-menu-item", href: item.href, children: item.label }, item.label) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2147
+ "button",
2148
+ {
2149
+ type: "button",
2150
+ role: "menuitem",
2151
+ className: "kerne-menu-item",
2152
+ onClick: () => {
2153
+ setOpen(false);
2154
+ _optionalChain([item, 'access', _39 => _39.onClick, 'optionalCall', _40 => _40()]);
2155
+ },
2156
+ children: item.label
2157
+ },
2158
+ item.label
2159
+ )
2160
+ ),
2161
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2162
+ "button",
2163
+ {
2164
+ type: "button",
2165
+ role: "menuitem",
2166
+ className: "kerne-menu-item",
2167
+ "data-tone": "danger",
2168
+ onClick: handleSignOut,
2169
+ children: l10n.account.signOut
2170
+ }
2171
+ )
2172
+ ] }) : null
2173
+ ] })
2174
+ }
2175
+ );
2176
+ }
2177
+
2178
+ // src/ui/UserProfile.tsx
2179
+
2180
+
2181
+ // src/ui/profile/ProfileSection.tsx
2182
+
2183
+
2184
+ function ProfileSection({ verificationCallbackUrl, onSaved }) {
2185
+ const { updateProfile, sendVerificationEmail, getVerificationStatus } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
2186
+ const { user, fullName, initials, email } = _chunk3PROPZWWcjs.useUser.call(void 0, );
2187
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2188
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
2189
+ const [firstName, setFirstName] = _react.useState.call(void 0, "");
2190
+ const [lastName, setLastName] = _react.useState.call(void 0, "");
2191
+ const [saving, setSaving] = _react.useState.call(void 0, false);
2192
+ const [saved, setSaved] = _react.useState.call(void 0, false);
2193
+ const [error, setError] = _react.useState.call(void 0, null);
2194
+ const [verified, setVerified] = _react.useState.call(void 0, null);
2195
+ const [sending, setSending] = _react.useState.call(void 0, false);
2196
+ const [sent, setSent] = _react.useState.call(void 0, false);
2197
+ _react.useEffect.call(void 0, () => {
2198
+ if (!user) return;
2199
+ setFirstName(_nullishCoalesce(user.first_name, () => ( "")));
2200
+ setLastName(_nullishCoalesce(user.last_name, () => ( "")));
2201
+ }, [user]);
2202
+ _react.useEffect.call(void 0, () => {
2203
+ let mounted = true;
2204
+ getVerificationStatus().then((s) => mounted && setVerified(s.emailVerified)).catch(() => mounted && setVerified(null));
2205
+ return () => {
2206
+ mounted = false;
2207
+ };
2208
+ }, [getVerificationStatus]);
2209
+ const handleSave = async (e) => {
2210
+ e.preventDefault();
2211
+ setError(null);
2212
+ setSaved(false);
2213
+ setSaving(true);
2214
+ try {
2215
+ await updateProfile({ first_name: firstName, last_name: lastName });
2216
+ setSaved(true);
2217
+ _optionalChain([onSaved, 'optionalCall', _41 => _41()]);
2218
+ } catch (err) {
2219
+ setError(showError(err));
2220
+ } finally {
2221
+ setSaving(false);
2222
+ }
2223
+ };
2224
+ const handleResend = async () => {
2225
+ setError(null);
2226
+ setSending(true);
2227
+ try {
2228
+ await sendVerificationEmail("link", verificationCallbackUrl);
2229
+ setSent(true);
2230
+ } catch (err) {
2231
+ setError(showError(err));
2232
+ } finally {
2233
+ setSending(false);
2234
+ }
2235
+ };
2236
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2237
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Subsection, { title: l10n.profile.profileTitle, children: [
2238
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-identity", children: [
2239
+ _optionalChain([user, 'optionalAccess', _42 => _42.avatar]) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { className: "kerne-avatar", src: user.avatar, alt: "" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-avatar", "aria-hidden": "true", children: initials || _optionalChain([email, 'optionalAccess', _43 => _43[0], 'optionalAccess', _44 => _44.toUpperCase, 'call', _45 => _45()]) || "?" }),
2240
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-identity-text", children: [
2241
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-identity-name", children: fullName || l10n.profile.unnamed }),
2242
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-identity-mail", children: email })
2243
+ ] })
2244
+ ] }),
2245
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
2246
+ saved ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "success", children: l10n.profile.saved }) : null,
2247
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { className: "kerne-form", onSubmit: handleSave, children: [
2248
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2249
+ Field,
2250
+ {
2251
+ label: l10n.profile.firstName,
2252
+ type: "text",
2253
+ value: firstName,
2254
+ onChange: setFirstName,
2255
+ autoComplete: "given-name",
2256
+ placeholder: l10n.profile.firstNamePlaceholder,
2257
+ disabled: saving
2258
+ }
2259
+ ),
2260
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2261
+ Field,
2262
+ {
2263
+ label: l10n.profile.lastName,
2264
+ type: "text",
2265
+ value: lastName,
2266
+ onChange: setLastName,
2267
+ autoComplete: "family-name",
2268
+ placeholder: l10n.profile.lastNamePlaceholder,
2269
+ disabled: saving
2270
+ }
2271
+ ),
2272
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { disabled: saving, children: saving ? l10n.profile.saving : l10n.profile.save })
2273
+ ] })
2274
+ ] }),
2275
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2276
+ Subsection,
2277
+ {
2278
+ title: l10n.profile.emailSectionTitle,
2279
+ description: l10n.profile.emailSectionDesc,
2280
+ children: [
2281
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-plan-option", children: [
2282
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-plan-option-text", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "kerne-plan-option-name", children: [
2283
+ email,
2284
+ verified === true ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-badge", "data-tone": "success", children: l10n.profile.verified }) : verified === false ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-badge", "data-tone": "warning", children: l10n.profile.unverified }) : null
2285
+ ] }) }),
2286
+ verified === false ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", type: "button", onClick: handleResend, disabled: sending, children: sending ? l10n.common.sending : l10n.profile.verify }) : null
2287
+ ] }),
2288
+ sent ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "success", children: l10n.profile.verificationSent }) : null
2289
+ ]
2290
+ }
2291
+ )
2292
+ ] });
2293
+ }
2294
+
2295
+ // src/ui/profile/SecuritySection.tsx
2296
+
2297
+
2298
+ function SecuritySection({ showDeleteAccount = true, onDeleted }) {
2299
+ const { requestAccountDeletion } = _chunk3PROPZWWcjs.useAuth.call(void 0, );
2300
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
2301
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2302
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
2303
+ const [error, setError] = _react.useState.call(void 0, null);
2304
+ const [confirmingDelete, setConfirmingDelete] = _react.useState.call(void 0, false);
2305
+ const [deleting, setDeleting] = _react.useState.call(void 0, false);
2306
+ const hasPassword = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _46 => _46.enable_credentials]), () => ( true));
2307
+ const handleDelete = async () => {
2308
+ setError(null);
2309
+ setDeleting(true);
2310
+ try {
2311
+ await requestAccountDeletion();
2312
+ _optionalChain([onDeleted, 'optionalCall', _47 => _47()]);
2313
+ } catch (err) {
2314
+ setError(showError(err));
2315
+ setDeleting(false);
2316
+ }
2317
+ };
2318
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2319
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
2320
+ hasPassword ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Subsection, { title: l10n.security.passwordTitle, description: l10n.security.passwordDesc, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChangePasswordForm, { title: null }) }) : null,
2321
+ showDeleteAccount ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Subsection, { title: l10n.security.deleteTitle, description: l10n.security.deleteDesc, children: confirmingDelete ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", gap: 10, flexWrap: "wrap" }, children: [
2322
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "danger", type: "button", onClick: handleDelete, disabled: deleting, children: deleting ? l10n.security.deleting : l10n.security.deleteConfirm }),
2323
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2324
+ Button,
2325
+ {
2326
+ variant: "outline",
2327
+ type: "button",
2328
+ onClick: () => setConfirmingDelete(false),
2329
+ disabled: deleting,
2330
+ children: l10n.common.cancel
2331
+ }
2332
+ )
2333
+ ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "danger", type: "button", onClick: () => setConfirmingDelete(true), children: l10n.security.deleteAction }) }) : null
2334
+ ] });
2335
+ }
2336
+
2337
+ // src/ui/profile/BillingSection.tsx
2338
+
2339
+
2340
+ // src/ui/format.ts
2341
+ function humanizeFeatureKey(key) {
2342
+ const words = key.replace(/[_-]+/g, " ").trim();
2343
+ return words.charAt(0).toUpperCase() + words.slice(1);
2344
+ }
2345
+ function formatMoney(amountMinorUnits, currency) {
2346
+ try {
2347
+ return new Intl.NumberFormat(void 0, {
2348
+ style: "currency",
2349
+ currency: currency.toUpperCase(),
2350
+ // Whole amounts read better without ".00" on a pricing surface, but a
2351
+ // real fractional price must never be rounded away.
2352
+ minimumFractionDigits: amountMinorUnits % 100 === 0 ? 0 : 2
2353
+ }).format(amountMinorUnits / 100);
2354
+ } catch (e2) {
2355
+ return `${(amountMinorUnits / 100).toFixed(2)} ${currency.toUpperCase()}`;
2356
+ }
2357
+ }
2358
+ function formatNumber(value) {
2359
+ return new Intl.NumberFormat().format(value);
2360
+ }
2361
+ function formatDate(iso) {
2362
+ if (!iso) return null;
2363
+ const d = new Date(iso);
2364
+ if (Number.isNaN(d.getTime())) return null;
2365
+ return new Intl.DateTimeFormat(void 0, {
2366
+ year: "numeric",
2367
+ month: "short",
2368
+ day: "numeric"
2369
+ }).format(d);
2370
+ }
2371
+ var ENCODED_INTERVAL = /^([1-9]\d*)([DMY])$/;
2372
+ function formatInterval(interval, labels) {
2373
+ const encoded = ENCODED_INTERVAL.exec(interval);
2374
+ if (encoded) {
2375
+ const count = parseInt(encoded[1], 10);
2376
+ const unitLabel = { D: labels.intervalDay, M: labels.intervalMonth, Y: labels.intervalYear }[encoded[2]];
2377
+ return count === 1 ? unitLabel : `${count} ${unitLabel}`;
2378
+ }
2379
+ switch (interval.toLowerCase()) {
2380
+ case "month":
2381
+ case "monthly":
2382
+ return labels.intervalMonth;
2383
+ case "year":
2384
+ case "yearly":
2385
+ case "annual":
2386
+ return labels.intervalYear;
2387
+ case "week":
2388
+ case "weekly":
2389
+ return labels.intervalWeek;
2390
+ case "day":
2391
+ case "daily":
2392
+ return labels.intervalDay;
2393
+ default:
2394
+ return interval;
2395
+ }
2396
+ }
2397
+
2398
+ // src/ui/UsageMeters.tsx
2399
+
2400
+ function levelFor(ratio, overageAllowed) {
2401
+ if (overageAllowed) return ratio >= 1 ? "warning" : "normal";
2402
+ if (ratio >= 0.9) return "critical";
2403
+ if (ratio >= 0.75) return "warning";
2404
+ return "normal";
2405
+ }
2406
+ function UsageMeters({
2407
+ title,
2408
+ featureKeys,
2409
+ showUnlimited = false,
2410
+ limit: maxRows,
2411
+ labels,
2412
+ emptyState,
2413
+ appearance,
2414
+ className
2415
+ }) {
2416
+ const { entitlements, isLoading, error } = _chunk3PROPZWWcjs.useEntitlements.call(void 0, );
2417
+ const { subscription } = _chunk3PROPZWWcjs.useSubscription.call(void 0, );
2418
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2419
+ const heading = title === null ? null : _nullishCoalesce(title, () => ( l10n.usage.title));
2420
+ const nameFor = (key) => {
2421
+ if (_optionalChain([labels, 'optionalAccess', _48 => _48[key]])) return labels[key];
2422
+ const fromPlan = _optionalChain([subscription, 'optionalAccess', _49 => _49.entitlements, 'access', _50 => _50.find, 'call', _51 => _51((e) => e.feature_key === key), 'optionalAccess', _52 => _52.feature_name]);
2423
+ return _nullishCoalesce(fromPlan, () => ( humanizeFeatureKey(key)));
2424
+ };
2425
+ const shell = (children) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
2426
+ heading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-section-head", style: { marginBottom: 16 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "kerne-section-title", children: heading }) }) : null,
2427
+ children
2428
+ ] });
2429
+ if (isLoading) {
2430
+ return shell(
2431
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-meters", "aria-busy": "true", "aria-label": l10n.usage.loading, children: [
2432
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton", style: { height: 34 } }),
2433
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton", style: { height: 34 } })
2434
+ ] })
2435
+ );
2436
+ }
2437
+ if (error || !entitlements) {
2438
+ return shell(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: l10n.usage.loadFailed }));
2439
+ }
2440
+ const metered = entitlements.entitlements.filter((e) => {
2441
+ if (e.feature_type !== "QUOTA") return false;
2442
+ if (featureKeys && !featureKeys.includes(e.feature_key)) return false;
2443
+ if (!showUnlimited && (e.limit === null || e.limit === void 0)) return false;
2444
+ return typeof e.used === "number";
2445
+ }).sort((a, b) => {
2446
+ if (featureKeys) {
2447
+ return featureKeys.indexOf(a.feature_key) - featureKeys.indexOf(b.feature_key);
2448
+ }
2449
+ const ratio = (e) => e.limit ? e.used / e.limit : -1;
2450
+ return ratio(b) - ratio(a);
2451
+ });
2452
+ const rows = maxRows ? metered.slice(0, maxRows) : metered;
2453
+ if (rows.length === 0) {
2454
+ return shell(_nullishCoalesce(emptyState, () => ( /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-meter-note", children: l10n.usage.nothingMetered }))));
2455
+ }
2456
+ return shell(
2457
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-meters", children: rows.map((e) => {
2458
+ const unlimited = e.limit === null || e.limit === void 0;
2459
+ const overageAllowed = e.overage_behavior === "ALLOW";
2460
+ const ratio = unlimited ? 0 : Math.min(e.used / e.limit, 1);
2461
+ const level = unlimited ? "normal" : levelFor(e.used / e.limit, overageAllowed);
2462
+ const over = !unlimited && e.used > e.limit;
2463
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-meter", "data-level": level, children: [
2464
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-meter-head", children: [
2465
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-meter-name", children: nameFor(e.feature_key) }),
2466
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-meter-value", children: unlimited ? _chunk3PROPZWWcjs.fill.call(void 0, l10n.usage.used, { count: formatNumber(e.used) }) : `${formatNumber(e.used)} / ${formatNumber(e.limit)}` })
2467
+ ] }),
2468
+ !unlimited ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2469
+ "div",
2470
+ {
2471
+ className: "kerne-meter-track",
2472
+ role: "progressbar",
2473
+ "aria-valuenow": e.used,
2474
+ "aria-valuemin": 0,
2475
+ "aria-valuemax": e.limit,
2476
+ "aria-label": nameFor(e.feature_key),
2477
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-meter-fill", style: { width: `${ratio * 100}%` } })
2478
+ }
2479
+ ) : null,
2480
+ over && overageAllowed ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-meter-note", children: _chunk3PROPZWWcjs.fill.call(void 0, l10n.usage.overage, {
2481
+ count: formatNumber(e.used - e.limit)
2482
+ }) }) : over ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-meter-note", children: l10n.usage.limitReached }) : null
2483
+ ] }, e.feature_key);
2484
+ }) })
2485
+ );
2486
+ }
2487
+
2488
+ // src/ui/SubscriptionCard.tsx
2489
+
2490
+
2491
+ var STATUS_TONES = {
2492
+ ACTIVE: "success",
2493
+ TRIALING: "success",
2494
+ PAST_DUE: "warning",
2495
+ CANCELED: void 0,
2496
+ UNPAID: "danger",
2497
+ PAUSED: "warning"
2498
+ };
2499
+ function SubscriptionCard({
2500
+ productSlug,
2501
+ title,
2502
+ portalReturnUrl,
2503
+ upgradeUrl,
2504
+ onUpgradeClick,
2505
+ hidePortalButton = false,
2506
+ appearance,
2507
+ className
2508
+ }) {
2509
+ const { subscription, isLoading, error } = _chunk3PROPZWWcjs.useSubscription.call(void 0, productSlug);
2510
+ const { openPortal } = _chunk3PROPZWWcjs.usePortal.call(void 0, );
2511
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2512
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
2513
+ const heading = title === null ? null : _nullishCoalesce(title, () => ( l10n.billing.plan));
2514
+ const statusLabels = {
2515
+ ACTIVE: l10n.billing.statusActive,
2516
+ TRIALING: l10n.billing.statusTrialing,
2517
+ PAST_DUE: l10n.billing.statusPastDue,
2518
+ CANCELED: l10n.billing.statusCanceled,
2519
+ UNPAID: l10n.billing.statusUnpaid,
2520
+ PAUSED: l10n.billing.statusPaused
2521
+ };
2522
+ const [opening, setOpening] = _react.useState.call(void 0, false);
2523
+ const [portalError, setPortalError] = _react.useState.call(void 0, null);
2524
+ const handlePortal = async () => {
2525
+ setPortalError(null);
2526
+ setOpening(true);
2527
+ try {
2528
+ await openPortal(portalReturnUrl);
2529
+ } catch (e) {
2530
+ setPortalError(showError(e));
2531
+ setOpening(false);
2532
+ }
2533
+ };
2534
+ const shell = (children) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
2535
+ heading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "kerne-section-title", children: heading }) : null,
2536
+ children
2537
+ ] }) });
2538
+ if (isLoading) {
2539
+ return shell(
2540
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-rows", "aria-busy": "true", "aria-label": l10n.billing.loadingPlan, children: [
2541
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton", style: { height: 20 } }),
2542
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton", style: { height: 20 } })
2543
+ ] })
2544
+ );
2545
+ }
2546
+ if (error) {
2547
+ return shell(/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: l10n.billing.loadFailed }));
2548
+ }
2549
+ if (!subscription) {
2550
+ return shell(
2551
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2552
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-subsection-desc", children: l10n.billing.freePlan }),
2553
+ upgradeUrl || onUpgradeClick ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2554
+ Button,
2555
+ {
2556
+ type: "button",
2557
+ onClick: _nullishCoalesce(onUpgradeClick, () => ( (() => {
2558
+ if (upgradeUrl) window.location.href = upgradeUrl;
2559
+ }))),
2560
+ children: l10n.billing.seePlans
2561
+ }
2562
+ ) : null
2563
+ ] })
2564
+ );
2565
+ }
2566
+ const { plan, plan_price, status, current_period_end, trial_end, canceled_at } = subscription;
2567
+ const renews = formatDate(current_period_end);
2568
+ const trialEnds = formatDate(trial_end);
2569
+ return shell(
2570
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2571
+ portalError ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: portalError }) : null,
2572
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "dl", { className: "kerne-rows", children: [
2573
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-row", children: [
2574
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dt", { children: l10n.billing.plan }),
2575
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dd", { children: plan.name })
2576
+ ] }),
2577
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-row", children: [
2578
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dt", { children: l10n.billing.price }),
2579
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "dd", { children: [
2580
+ formatMoney(plan_price.amount, plan_price.currency),
2581
+ " /",
2582
+ " ",
2583
+ formatInterval(plan_price.interval, l10n.billing)
2584
+ ] })
2585
+ ] }),
2586
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-row", children: [
2587
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dt", { children: l10n.billing.status }),
2588
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dd", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-badge", "data-tone": STATUS_TONES[status], children: _nullishCoalesce(statusLabels[status], () => ( status)) }) })
2589
+ ] }),
2590
+ status === "TRIALING" && trialEnds ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-row", children: [
2591
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dt", { children: l10n.billing.trialEnds }),
2592
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dd", { children: trialEnds })
2593
+ ] }) : renews ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-row", children: [
2594
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dt", { children: canceled_at ? l10n.billing.ends : l10n.billing.renews }),
2595
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "dd", { children: renews })
2596
+ ] }) : null
2597
+ ] }),
2598
+ canceled_at ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: l10n.billing.cancelNotice }) : null,
2599
+ !hidePortalButton ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", type: "button", onClick: handlePortal, disabled: opening, children: opening ? l10n.billing.opening : l10n.billing.managePortal }) : null
2600
+ ] })
2601
+ );
2602
+ }
2603
+
2604
+ // src/ui/profile/BillingSection.tsx
2605
+
2606
+ function intervalsOf(plans) {
2607
+ const seen = [];
2608
+ for (const plan of plans) {
2609
+ for (const price of plan.prices) {
2610
+ if (!seen.includes(price.interval)) seen.push(price.interval);
2611
+ }
2612
+ }
2613
+ return seen;
2614
+ }
2615
+ function BillingSection({
2616
+ productSlug,
2617
+ pricingProductIdOrSlug,
2618
+ portalReturnUrl,
2619
+ checkoutSuccessUrl,
2620
+ checkoutCancelUrl,
2621
+ showPlanSwitcher = true,
2622
+ showUsage = true,
2623
+ usageFeatureKeys,
2624
+ usageLabels
2625
+ }) {
2626
+ const { subscription } = _chunk3PROPZWWcjs.useSubscription.call(void 0, productSlug);
2627
+ const { plans, isLoading: plansLoading } = _chunk3PROPZWWcjs.usePlans.call(void 0, pricingProductIdOrSlug);
2628
+ const { openCheckout } = _chunk3PROPZWWcjs.useCheckout.call(void 0, );
2629
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2630
+ const showError = _chunk3PROPZWWcjs.useErrorResolver.call(void 0, );
2631
+ const [busy, setBusy] = _react.useState.call(void 0, null);
2632
+ const [error, setError] = _react.useState.call(void 0, null);
2633
+ const intervals = _react.useMemo.call(void 0, () => intervalsOf(plans), [plans]);
2634
+ const [interval, setInterval] = _react.useState.call(void 0, null);
2635
+ const activeInterval = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(interval, () => ( _optionalChain([subscription, 'optionalAccess', _53 => _53.plan_price, 'access', _54 => _54.interval]))), () => ( intervals[0])), () => ( null));
2636
+ const handleSwitch = async (planPriceId) => {
2637
+ setError(null);
2638
+ setBusy(planPriceId);
2639
+ try {
2640
+ await openCheckout(planPriceId, {
2641
+ successUrl: checkoutSuccessUrl,
2642
+ cancelUrl: checkoutCancelUrl
2643
+ });
2644
+ } catch (e) {
2645
+ setError(showError(e));
2646
+ setBusy(null);
2647
+ }
2648
+ };
2649
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2650
+ error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
2651
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Subsection, { title: l10n.billing.currentPlan, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2652
+ SubscriptionCard,
2653
+ {
2654
+ title: null,
2655
+ productSlug,
2656
+ portalReturnUrl
2657
+ }
2658
+ ) }),
2659
+ showUsage ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Subsection, { title: l10n.usage.title, description: l10n.usage.subtitle, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, UsageMeters, { title: null, featureKeys: usageFeatureKeys, labels: usageLabels }) }) : null,
2660
+ showPlanSwitcher ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Subsection, { title: l10n.billing.changePlan, children: plansLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2661
+ "div",
2662
+ {
2663
+ className: "kerne-skeleton",
2664
+ style: { height: 64 },
2665
+ "aria-label": l10n.billing.loadingPlans
2666
+ }
2667
+ ) : plans.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-subsection-desc", children: l10n.billing.noPlans }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2668
+ intervals.length > 1 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2669
+ "div",
2670
+ {
2671
+ className: "kerne-segmented",
2672
+ role: "group",
2673
+ "aria-label": l10n.billing.intervalGroupLabel,
2674
+ children: intervals.map((i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2675
+ "button",
2676
+ {
2677
+ type: "button",
2678
+ className: "kerne-segment",
2679
+ "aria-pressed": i === activeInterval,
2680
+ onClick: () => setInterval(i),
2681
+ children: formatInterval(i, l10n.billing)
2682
+ },
2683
+ i
2684
+ ))
2685
+ }
2686
+ ) : null,
2687
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-plan-list", children: plans.map((plan) => {
2688
+ const price = _nullishCoalesce(plan.prices.find((p) => p.interval === activeInterval), () => ( plan.prices[0]));
2689
+ const isCurrent = _optionalChain([subscription, 'optionalAccess', _55 => _55.plan, 'access', _56 => _56.slug]) === plan.slug;
2690
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
2691
+ "div",
2692
+ {
2693
+ className: "kerne-plan-option",
2694
+ "data-current": isCurrent ? "true" : void 0,
2695
+ children: [
2696
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-plan-option-text", children: [
2697
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "kerne-plan-option-name", children: [
2698
+ plan.name,
2699
+ isCurrent ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-badge", children: l10n.billing.current }) : null
2700
+ ] }),
2701
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-plan-option-price", children: price ? `${formatMoney(price.amount, price.currency)} / ${formatInterval(price.interval, l10n.billing)}` : l10n.billing.notOnInterval })
2702
+ ] }),
2703
+ !isCurrent && price ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2704
+ Button,
2705
+ {
2706
+ variant: "outline",
2707
+ type: "button",
2708
+ onClick: () => handleSwitch(price.id),
2709
+ disabled: busy !== null,
2710
+ children: busy === price.id ? l10n.billing.opening : l10n.billing.switchTo
2711
+ }
2712
+ ) : null
2713
+ ]
2714
+ },
2715
+ plan.id
2716
+ );
2717
+ }) })
2718
+ ] }) }) : null
2719
+ ] });
2720
+ }
2721
+
2722
+ // src/ui/UserProfile.tsx
2723
+
2724
+ function UserProfile({
2725
+ tabs = ["profile", "security", "billing"],
2726
+ extraTabs = [],
2727
+ defaultTab,
2728
+ activeTab: controlledTab,
2729
+ onTabChange,
2730
+ showDeleteAccount = true,
2731
+ onSaved,
2732
+ onDeleted,
2733
+ productSlug,
2734
+ pricingProductIdOrSlug,
2735
+ portalReturnUrl,
2736
+ checkoutSuccessUrl,
2737
+ checkoutCancelUrl,
2738
+ showPlanSwitcher = true,
2739
+ showUsage = true,
2740
+ usageFeatureKeys,
2741
+ usageLabels,
2742
+ verificationCallbackUrl,
2743
+ appearance,
2744
+ className
2745
+ }) {
2746
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2747
+ const builtins = {
2748
+ profile: {
2749
+ label: l10n.profile.tabProfile,
2750
+ title: l10n.profile.profileTitle,
2751
+ description: l10n.profile.profileDesc
2752
+ },
2753
+ security: {
2754
+ label: l10n.profile.tabSecurity,
2755
+ title: l10n.profile.securityTitle,
2756
+ description: l10n.profile.securityDesc
2757
+ },
2758
+ billing: {
2759
+ label: l10n.profile.tabBilling,
2760
+ title: l10n.profile.billingTitle,
2761
+ description: l10n.profile.billingDesc
2762
+ }
2763
+ };
2764
+ const allTabs = [
2765
+ ...tabs.map((id) => ({ id, ...builtins[id] })),
2766
+ ...extraTabs.map((t) => ({
2767
+ id: t.id,
2768
+ label: t.label,
2769
+ title: _nullishCoalesce(t.title, () => ( t.label)),
2770
+ description: t.description
2771
+ }))
2772
+ ];
2773
+ const [internalTab, setInternalTab] = _react.useState.call(void 0, _nullishCoalesce(_nullishCoalesce(defaultTab, () => ( _optionalChain([allTabs, 'access', _57 => _57[0], 'optionalAccess', _58 => _58.id]))), () => ( "profile")));
2774
+ const current = _nullishCoalesce(controlledTab, () => ( internalTab));
2775
+ const select = (id) => {
2776
+ if (controlledTab === void 0) setInternalTab(id);
2777
+ _optionalChain([onTabChange, 'optionalCall', _59 => _59(id)]);
2778
+ };
2779
+ const active = _nullishCoalesce(allTabs.find((t) => t.id === current), () => ( allTabs[0]));
2780
+ const renderPane = () => {
2781
+ switch (_optionalChain([active, 'optionalAccess', _60 => _60.id])) {
2782
+ case "profile":
2783
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ProfileSection, { verificationCallbackUrl, onSaved });
2784
+ case "security":
2785
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SecuritySection, { showDeleteAccount, onDeleted });
2786
+ case "billing":
2787
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2788
+ BillingSection,
2789
+ {
2790
+ productSlug,
2791
+ pricingProductIdOrSlug,
2792
+ portalReturnUrl,
2793
+ checkoutSuccessUrl,
2794
+ checkoutCancelUrl,
2795
+ showPlanSwitcher,
2796
+ showUsage,
2797
+ usageFeatureKeys,
2798
+ usageLabels
2799
+ }
2800
+ );
2801
+ default:
2802
+ return _nullishCoalesce(_optionalChain([extraTabs, 'access', _61 => _61.find, 'call', _62 => _62((t) => t.id === _optionalChain([active, 'optionalAccess', _63 => _63.id])), 'optionalAccess', _64 => _64.content]), () => ( null));
2803
+ }
2804
+ };
2805
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, size: "wide", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-profile", children: [
2806
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "nav", { className: "kerne-nav", "aria-label": l10n.profile.navLabel, children: allTabs.map((tab) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2807
+ "button",
2808
+ {
2809
+ type: "button",
2810
+ className: "kerne-nav-item",
2811
+ "aria-current": tab.id === _optionalChain([active, 'optionalAccess', _65 => _65.id]) ? "page" : void 0,
2812
+ onClick: () => select(tab.id),
2813
+ children: tab.label
2814
+ },
2815
+ tab.id
2816
+ )) }),
2817
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-pane", children: [
2818
+ active ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
2819
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "kerne-pane-title", children: active.title }),
2820
+ active.description ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-pane-desc", children: active.description }) : null
2821
+ ] }) : null,
2822
+ renderPane()
2823
+ ] })
2824
+ ] }) });
2825
+ }
2826
+
2827
+ // src/ui/CheckoutResult.tsx
2828
+
2829
+
2830
+ var POLL_INTERVAL_MS = 1500;
2831
+ function CheckoutResult({
2832
+ outcome = "success",
2833
+ productSlug,
2834
+ continueUrl,
2835
+ onContinue,
2836
+ pricingUrl,
2837
+ onRetry,
2838
+ onConfirmed,
2839
+ confirmTimeoutMs = 15e3,
2840
+ appearance,
2841
+ logo,
2842
+ className
2843
+ }) {
2844
+ const client = _chunk3PROPZWWcjs.useClient.call(void 0, );
2845
+ const { config } = _chunk3PROPZWWcjs.useAuthConfig.call(void 0, );
2846
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2847
+ const [state, setState] = _react.useState.call(void 0, "checking");
2848
+ const confirmed = _react.useRef.call(void 0, false);
2849
+ _react.useEffect.call(void 0, () => {
2850
+ if (outcome !== "success") return;
2851
+ let stopped = false;
2852
+ const startedAt = Date.now();
2853
+ const poll = async () => {
2854
+ if (stopped || confirmed.current) return;
2855
+ try {
2856
+ const sub = await client.getSubscription(productSlug);
2857
+ if (sub && !stopped) {
2858
+ confirmed.current = true;
2859
+ setState("confirmed");
2860
+ _optionalChain([onConfirmed, 'optionalCall', _66 => _66(sub)]);
2861
+ return;
2862
+ }
2863
+ } catch (e3) {
2864
+ }
2865
+ if (stopped) return;
2866
+ if (Date.now() - startedAt >= confirmTimeoutMs) {
2867
+ setState("pending");
2868
+ return;
2869
+ }
2870
+ window.setTimeout(poll, POLL_INTERVAL_MS);
2871
+ };
2872
+ void poll();
2873
+ return () => {
2874
+ stopped = true;
2875
+ };
2876
+ }, [outcome, productSlug, client, confirmTimeoutMs, onConfirmed]);
2877
+ const go = (url, handler) => _nullishCoalesce(handler, () => ( (() => {
2878
+ if (url) window.location.href = url;
2879
+ })));
2880
+ const continueAction = continueUrl || onContinue ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { type: "button", onClick: go(continueUrl, onContinue), children: l10n.common.continue }) : void 0;
2881
+ const shell = (children) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
2882
+ logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
2883
+ children,
2884
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _67 => _67.show_kerne_branding]), () => ( false)) })
2885
+ ] });
2886
+ if (outcome === "cancel") {
2887
+ return shell(
2888
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2889
+ Status,
2890
+ {
2891
+ tone: "danger",
2892
+ title: l10n.checkout.cancelTitle,
2893
+ action: pricingUrl || onRetry ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", type: "button", onClick: go(pricingUrl, onRetry), children: l10n.checkout.backToPlans }) : void 0,
2894
+ children: l10n.checkout.cancelBody
2895
+ }
2896
+ )
2897
+ );
2898
+ }
2899
+ if (state === "checking") {
2900
+ return shell(
2901
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "loading", title: l10n.checkout.confirmingTitle, children: l10n.checkout.confirmingBody })
2902
+ );
2903
+ }
2904
+ if (state === "pending") {
2905
+ return shell(
2906
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "success", title: l10n.checkout.pendingTitle, action: continueAction, children: l10n.checkout.pendingBody })
2907
+ );
2908
+ }
2909
+ return shell(
2910
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Status, { tone: "success", title: l10n.checkout.doneTitle, action: continueAction, children: l10n.checkout.doneBody })
2911
+ );
2912
+ }
2913
+
2914
+ // src/ui/UpgradePrompt.tsx
2915
+
2916
+ function UpgradePrompt({
2917
+ featureKey,
2918
+ requested,
2919
+ featureName,
2920
+ children,
2921
+ upgradeUrl,
2922
+ onUpgradeClick,
2923
+ upgradeLabel,
2924
+ title,
2925
+ description,
2926
+ hideWhileLoading = false,
2927
+ appearance,
2928
+ className
2929
+ }) {
2930
+ const { details, allowed, isLoading } = _chunk3PROPZWWcjs.useAccess.call(void 0, featureKey, requested);
2931
+ const l10n = _chunk3PROPZWWcjs.useLocalization.call(void 0, );
2932
+ if (isLoading) {
2933
+ if (hideWhileLoading) return null;
2934
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton", style: { height: 80 }, "aria-label": l10n.upgrade.checking }) });
2935
+ }
2936
+ if (allowed) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children });
2937
+ const name = _nullishCoalesce(featureName, () => ( humanizeFeatureKey(featureKey).toLowerCase()));
2938
+ const quotaExhausted = _optionalChain([details, 'optionalAccess', _68 => _68.feature_type]) === "QUOTA" && typeof details.limit === "number" && typeof details.used === "number";
2939
+ const heading = _nullishCoalesce(title, () => ( _chunk3PROPZWWcjs.fill.call(void 0, quotaExhausted ? l10n.upgrade.quotaTitle : l10n.upgrade.featureTitle, { feature: name })));
2940
+ const body = _nullishCoalesce(description, () => ( (quotaExhausted ? _chunk3PROPZWWcjs.fill.call(void 0, l10n.upgrade.quotaBody, {
2941
+ used: formatNumber(details.used),
2942
+ limit: formatNumber(details.limit)
2943
+ }) : _chunk3PROPZWWcjs.fill.call(void 0, l10n.upgrade.featureBody, { feature: name }))));
2944
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-status", children: [
2945
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-heading", children: [
2946
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "kerne-section-title", style: { fontSize: 17 }, children: heading }),
2947
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-status-text", children: body })
2948
+ ] }),
2949
+ upgradeUrl || onUpgradeClick ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
2950
+ Button,
2951
+ {
2952
+ type: "button",
2953
+ onClick: _nullishCoalesce(onUpgradeClick, () => ( (() => {
2954
+ if (upgradeUrl) window.location.href = upgradeUrl;
2955
+ }))),
2956
+ children: _nullishCoalesce(upgradeLabel, () => ( l10n.upgrade.action))
2957
+ }
2958
+ ) : null
2959
+ ] }) });
2960
+ }
2961
+
2962
+
2963
+
2964
+
2965
+
2966
+
2967
+
2968
+
2969
+
2970
+
2971
+
2972
+
2973
+
2974
+
2975
+
2976
+
2977
+
2978
+
2979
+
2980
+
2981
+
2982
+
2983
+
2984
+ exports.ActivateAccountForm = ActivateAccountForm; exports.AuthFlow = AuthFlow; exports.BillingSection = BillingSection; exports.ChangePasswordForm = ChangePasswordForm; exports.CheckoutResult = CheckoutResult; exports.ForgotPasswordForm = ForgotPasswordForm; exports.LoginForm = LoginForm; exports.MagicLinkCallback = MagicLinkCallback; exports.ProfileSection = ProfileSection; exports.RegisterForm = RegisterForm; exports.ResetPasswordForm = ResetPasswordForm; exports.SecuritySection = SecuritySection; exports.SignOutButton = SignOutButton; exports.SubscriptionCard = SubscriptionCard; exports.UpgradePrompt = UpgradePrompt; exports.UsageMeters = UsageMeters; exports.UserButton = UserButton; exports.UserProfile = UserProfile; exports.VerifyEmailForm = VerifyEmailForm; exports.WaitlistForm = WaitlistForm; exports.defaultLocalization = _chunk3PROPZWWcjs.defaultLocalization; exports.useLocalization = _chunk3PROPZWWcjs.useLocalization;