@kerne/react 0.1.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -5
- package/dist/{chunk-F6NV76OR.js → chunk-IZMRK3WK.js} +150 -16
- package/dist/{chunk-7U3QBMA7.cjs → chunk-TYNZ2WU7.cjs} +156 -22
- package/dist/{i18n-BWTT1DWD.d.cts → i18n-QilNgwqe.d.cts} +33 -0
- package/dist/{i18n-BWTT1DWD.d.ts → i18n-QilNgwqe.d.ts} +33 -0
- package/dist/index.cjs +18 -20
- package/dist/index.d.cts +97 -13
- package/dist/index.d.ts +97 -13
- package/dist/index.js +13 -15
- package/dist/ui/index.cjs +669 -131
- package/dist/ui/index.d.cts +139 -4
- package/dist/ui/index.d.ts +139 -4
- package/dist/ui/index.js +602 -64
- package/package.json +3 -3
package/dist/ui/index.cjs
CHANGED
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
var _chunkTYNZ2WU7cjs = require('../chunk-TYNZ2WU7.cjs');
|
|
20
21
|
|
|
21
22
|
// src/ui/AuthFlow.tsx
|
|
22
23
|
var _react = require('react');
|
|
@@ -246,6 +247,7 @@ var CSS = `
|
|
|
246
247
|
|
|
247
248
|
/* ---------- Stack ---------- */
|
|
248
249
|
.kerne-stack { display: flex; flex-direction: column; gap: 16px; }
|
|
250
|
+
.kerne-inline-actions { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
249
251
|
.kerne-form { display: flex; flex-direction: column; gap: 12px; }
|
|
250
252
|
.kerne-field { display: flex; flex-direction: column; gap: 6px; }
|
|
251
253
|
.kerne-label { font-size: 14px; font-weight: 500; color: var(--kerne-fg); }
|
|
@@ -512,6 +514,126 @@ var CSS = `
|
|
|
512
514
|
.kerne-meter-note { font-size: 12px; color: var(--kerne-fg-subtle); margin: 0; }
|
|
513
515
|
@media (prefers-reduced-motion: reduce) { .kerne-meter-fill { transition: none; } }
|
|
514
516
|
|
|
517
|
+
/* ---------- Pricing table ---------- */
|
|
518
|
+
.kerne-pricing-skeleton { width: 100%; }
|
|
519
|
+
|
|
520
|
+
.kerne-pricing-switch-wrap { display: flex; justify-content: center; }
|
|
521
|
+
.kerne-pricing-switch {
|
|
522
|
+
position: relative;
|
|
523
|
+
display: inline-flex;
|
|
524
|
+
gap: 2px;
|
|
525
|
+
padding: 4px;
|
|
526
|
+
background: var(--kerne-panel);
|
|
527
|
+
border-radius: 999px;
|
|
528
|
+
}
|
|
529
|
+
.kerne-pricing-switch-thumb {
|
|
530
|
+
position: absolute;
|
|
531
|
+
top: 4px;
|
|
532
|
+
bottom: 4px;
|
|
533
|
+
left: 0;
|
|
534
|
+
border-radius: 999px;
|
|
535
|
+
background: var(--kerne-surface);
|
|
536
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
537
|
+
transition: transform 0.32s cubic-bezier(0.16, 1, 0.3, 1), width 0.32s cubic-bezier(0.16, 1, 0.3, 1);
|
|
538
|
+
}
|
|
539
|
+
.kerne-pricing-switch-option {
|
|
540
|
+
position: relative;
|
|
541
|
+
z-index: 1;
|
|
542
|
+
display: inline-flex;
|
|
543
|
+
align-items: center;
|
|
544
|
+
gap: 7px;
|
|
545
|
+
font: inherit;
|
|
546
|
+
font-size: 13.5px;
|
|
547
|
+
font-weight: 500;
|
|
548
|
+
white-space: nowrap;
|
|
549
|
+
color: var(--kerne-fg-muted);
|
|
550
|
+
background: none;
|
|
551
|
+
border: none;
|
|
552
|
+
border-radius: 999px;
|
|
553
|
+
padding: 7px 16px;
|
|
554
|
+
cursor: pointer;
|
|
555
|
+
transition: color 0.18s ease;
|
|
556
|
+
}
|
|
557
|
+
.kerne-pricing-switch-option[aria-pressed="true"] { color: var(--kerne-fg); }
|
|
558
|
+
.kerne-pricing-switch-option:focus-visible { outline: 2px solid var(--kerne-accent); outline-offset: 2px; }
|
|
559
|
+
.kerne-pricing-switch-save {
|
|
560
|
+
font-size: 10.5px;
|
|
561
|
+
font-weight: 600;
|
|
562
|
+
letter-spacing: 0.01em;
|
|
563
|
+
color: var(--kerne-success);
|
|
564
|
+
background: color-mix(in srgb, var(--kerne-success) 14%, transparent);
|
|
565
|
+
padding: 2px 6px;
|
|
566
|
+
border-radius: 999px;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.kerne-pricing-grid {
|
|
570
|
+
display: grid;
|
|
571
|
+
grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
|
|
572
|
+
gap: 20px;
|
|
573
|
+
align-items: stretch;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
.kerne-pricing-card {
|
|
577
|
+
position: relative;
|
|
578
|
+
display: flex;
|
|
579
|
+
flex-direction: column;
|
|
580
|
+
gap: 24px;
|
|
581
|
+
height: 100%;
|
|
582
|
+
padding: 28px 26px;
|
|
583
|
+
background: var(--kerne-surface);
|
|
584
|
+
border: 1px solid var(--kerne-border);
|
|
585
|
+
border-radius: calc(var(--kerne-radius) + 8px);
|
|
586
|
+
}
|
|
587
|
+
.kerne-pricing-card[data-featured="true"] {
|
|
588
|
+
background: var(--kerne-surface-raised);
|
|
589
|
+
border-color: var(--kerne-fg);
|
|
590
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 24px 48px -28px rgba(0, 0, 0, 0.22);
|
|
591
|
+
}
|
|
592
|
+
.kerne-pricing-card[data-current="true"]:not([data-featured="true"]) { border-color: var(--kerne-border-strong); }
|
|
593
|
+
|
|
594
|
+
/* A quiet inline pill, not a loud badge escaping the card border - that
|
|
595
|
+
shouted-uppercase-chip-on-the-edge look is the single most template-y
|
|
596
|
+
tell a pricing page can have. Reads as confirmation of what the card's
|
|
597
|
+
own elevation already signals, never as the primary signal itself. */
|
|
598
|
+
.kerne-pricing-badge {
|
|
599
|
+
align-self: flex-start;
|
|
600
|
+
font-size: 11.5px;
|
|
601
|
+
font-weight: 600;
|
|
602
|
+
letter-spacing: 0.01em;
|
|
603
|
+
color: var(--kerne-fg);
|
|
604
|
+
background: var(--kerne-panel);
|
|
605
|
+
padding: 3px 9px;
|
|
606
|
+
border-radius: 999px;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
.kerne-pricing-card-head { display: flex; flex-direction: column; gap: 8px; }
|
|
610
|
+
.kerne-pricing-card-name { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
|
|
611
|
+
.kerne-pricing-card-desc { margin: 0; font-size: 13px; line-height: 1.5; color: var(--kerne-fg-muted); }
|
|
612
|
+
|
|
613
|
+
.kerne-pricing-price { display: flex; flex-direction: column; gap: 3px; min-height: 52px; justify-content: center; }
|
|
614
|
+
.kerne-pricing-price-row { display: flex; align-items: baseline; gap: 5px; }
|
|
615
|
+
.kerne-pricing-amount {
|
|
616
|
+
font-size: 38px;
|
|
617
|
+
font-weight: 600;
|
|
618
|
+
letter-spacing: -0.025em;
|
|
619
|
+
line-height: 1;
|
|
620
|
+
font-variant-numeric: tabular-nums;
|
|
621
|
+
}
|
|
622
|
+
.kerne-pricing-interval { font-size: 14px; color: var(--kerne-fg-muted); }
|
|
623
|
+
.kerne-pricing-billed { margin: 0; font-size: 12px; color: var(--kerne-fg-subtle); }
|
|
624
|
+
|
|
625
|
+
.kerne-pricing-features { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; flex: 1; }
|
|
626
|
+
.kerne-pricing-feature { display: flex; align-items: flex-start; gap: 9px; font-size: 13.5px; line-height: 1.4; color: var(--kerne-fg); }
|
|
627
|
+
.kerne-pricing-feature svg { flex-shrink: 0; margin-top: 2px; color: var(--kerne-fg-subtle); }
|
|
628
|
+
.kerne-pricing-feature-more { font-size: 12.5px; color: var(--kerne-fg-subtle); padding-left: 24px; }
|
|
629
|
+
|
|
630
|
+
.kerne-pricing-cta { margin-top: auto; }
|
|
631
|
+
.kerne-pricing-cta .kerne-button { width: 100%; }
|
|
632
|
+
|
|
633
|
+
@media (prefers-reduced-motion: reduce) {
|
|
634
|
+
.kerne-pricing-switch-thumb { transition: none; }
|
|
635
|
+
}
|
|
636
|
+
|
|
515
637
|
/* ---------- Sections (profile, settings) ---------- */
|
|
516
638
|
.kerne-section-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
|
|
517
639
|
.kerne-section-title { font-size: 15px; font-weight: 600; margin: 0; }
|
|
@@ -781,7 +903,7 @@ function Field({
|
|
|
781
903
|
const id = _react.useId.call(void 0, );
|
|
782
904
|
const errorId = `${id}-error`;
|
|
783
905
|
const noteId = `${id}-note`;
|
|
784
|
-
const l10n =
|
|
906
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
785
907
|
const isPassword = type === "password";
|
|
786
908
|
const [revealed, setRevealed] = _react.useState.call(void 0, false);
|
|
787
909
|
const [capsLock, setCapsLock] = _react.useState.call(void 0, false);
|
|
@@ -909,11 +1031,11 @@ function PasswordStrength({
|
|
|
909
1031
|
password,
|
|
910
1032
|
policy
|
|
911
1033
|
}) {
|
|
912
|
-
const l10n =
|
|
1034
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
913
1035
|
const resolved = _nullishCoalesce(policy, () => ( resolvePolicy(null)));
|
|
914
1036
|
if (!meetsPolicy(password, resolved)) {
|
|
915
1037
|
const labels2 = {
|
|
916
|
-
min_length:
|
|
1038
|
+
min_length: _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.common.passwordHint, { count: resolved.min_length }),
|
|
917
1039
|
require_uppercase: l10n.common.passwordRequireUppercase,
|
|
918
1040
|
require_number: l10n.common.passwordRequireNumber,
|
|
919
1041
|
require_symbol: l10n.common.passwordRequireSymbol
|
|
@@ -1109,10 +1231,10 @@ function OAuthButtons({
|
|
|
1109
1231
|
disabled,
|
|
1110
1232
|
onSelect
|
|
1111
1233
|
}) {
|
|
1112
|
-
const l10n =
|
|
1234
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1113
1235
|
if (providers.length === 0) return null;
|
|
1114
1236
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-oauth-group", children: providers.map((provider) => {
|
|
1115
|
-
const label =
|
|
1237
|
+
const label = _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.common.continueWith, {
|
|
1116
1238
|
provider: _nullishCoalesce(OAUTH_LABELS[provider], () => ( provider))
|
|
1117
1239
|
});
|
|
1118
1240
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
@@ -1133,12 +1255,12 @@ function OAuthButtons({
|
|
|
1133
1255
|
}) });
|
|
1134
1256
|
}
|
|
1135
1257
|
function KerneBranding({ show }) {
|
|
1136
|
-
const l10n =
|
|
1258
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1137
1259
|
if (!show) return null;
|
|
1138
1260
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "a", { className: "kerne-branding", href: "https://kerne.io", target: "_blank", rel: "noopener noreferrer", children: l10n.common.securedByKerne });
|
|
1139
1261
|
}
|
|
1140
1262
|
function FormSkeleton() {
|
|
1141
|
-
const l10n =
|
|
1263
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1142
1264
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-form", "aria-busy": "true", "aria-label": l10n.common.loading, children: [
|
|
1143
1265
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton" }),
|
|
1144
1266
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton" })
|
|
@@ -1163,11 +1285,11 @@ function LoginForm({
|
|
|
1163
1285
|
logo,
|
|
1164
1286
|
className
|
|
1165
1287
|
}) {
|
|
1166
|
-
const client =
|
|
1167
|
-
const { login, startPasswordless } =
|
|
1168
|
-
const { config, isLoading: configLoading, error: configError } =
|
|
1169
|
-
const l10n =
|
|
1170
|
-
const showError =
|
|
1288
|
+
const client = _chunkTYNZ2WU7cjs.useClient.call(void 0, );
|
|
1289
|
+
const { login, startPasswordless } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
1290
|
+
const { config, isLoading: configLoading, error: configError } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
1291
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1292
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
1171
1293
|
const [email, setEmail] = _react.useState.call(void 0, "");
|
|
1172
1294
|
const [password, setPassword] = _react.useState.call(void 0, "");
|
|
1173
1295
|
const [submitting, setSubmitting] = _react.useState.call(void 0, false);
|
|
@@ -1231,7 +1353,7 @@ function LoginForm({
|
|
|
1231
1353
|
const signUpLine = canSignUp && (signUpUrl || onSignUpClick) ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
1232
1354
|
l10n.signIn.signUpPrompt,
|
|
1233
1355
|
" ",
|
|
1234
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, TextLink, { href: signUpUrl, onClick: onSignUpClick, children: appName ?
|
|
1356
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, TextLink, { href: signUpUrl, onClick: onSignUpClick, children: appName ? _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.signIn.signUpForApp, { app: appName }) : l10n.signIn.signUpLink }),
|
|
1235
1357
|
"."
|
|
1236
1358
|
] }) : void 0;
|
|
1237
1359
|
const submitLabel = submitting ? usePassword ? l10n.signIn.submitting : l10n.signIn.magicSubmitting : usePassword ? l10n.signIn.submit : l10n.signIn.magicSubmit;
|
|
@@ -1240,7 +1362,7 @@ function LoginForm({
|
|
|
1240
1362
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: heading, subtitle: _nullishCoalesce(subtitle, () => ( signUpLine)) }),
|
|
1241
1363
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
|
|
1242
1364
|
error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
|
|
1243
|
-
linkSentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children:
|
|
1365
|
+
linkSentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: _chunkTYNZ2WU7cjs.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: [
|
|
1244
1366
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1245
1367
|
Field,
|
|
1246
1368
|
{
|
|
@@ -1316,13 +1438,13 @@ function RegisterForm({
|
|
|
1316
1438
|
logo,
|
|
1317
1439
|
className
|
|
1318
1440
|
}) {
|
|
1319
|
-
const client =
|
|
1320
|
-
const { register, startPasswordless } =
|
|
1321
|
-
const { config, isLoading: configLoading, error: configError } =
|
|
1441
|
+
const client = _chunkTYNZ2WU7cjs.useClient.call(void 0, );
|
|
1442
|
+
const { register, startPasswordless } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
1443
|
+
const { config, isLoading: configLoading, error: configError } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
1322
1444
|
const policy = resolvePolicy(config);
|
|
1323
1445
|
const invitationToken = useUrlToken("token", invitationTokenProp) || void 0;
|
|
1324
|
-
const l10n =
|
|
1325
|
-
const showError =
|
|
1446
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1447
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
1326
1448
|
const [email, setEmail] = _react.useState.call(void 0, "");
|
|
1327
1449
|
const [password, setPassword] = _react.useState.call(void 0, "");
|
|
1328
1450
|
const [name, setName] = _react.useState.call(void 0, "");
|
|
@@ -1333,7 +1455,7 @@ function RegisterForm({
|
|
|
1333
1455
|
const [passwordMode, setPasswordMode] = _react.useState.call(void 0, false);
|
|
1334
1456
|
const shell = (children) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, children });
|
|
1335
1457
|
const appName = _optionalChain([config, 'optionalAccess', _13 => _13.app_name]);
|
|
1336
|
-
const heading = _nullishCoalesce(title, () => ( (appName ?
|
|
1458
|
+
const heading = _nullishCoalesce(title, () => ( (appName ? _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.signUp.titleWithApp, { app: appName }) : l10n.signUp.title)));
|
|
1337
1459
|
const signInLine = signInUrl || onSignInClick ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
1338
1460
|
l10n.signUp.signInPrompt,
|
|
1339
1461
|
" ",
|
|
@@ -1360,7 +1482,7 @@ function RegisterForm({
|
|
|
1360
1482
|
return shell(
|
|
1361
1483
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
1362
1484
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Masthead, { logo, title: l10n.signUp.closedTitle, subtitle: signInLine }),
|
|
1363
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children:
|
|
1485
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.signUp.closedBody, { app: _nullishCoalesce(appName, () => ( l10n.common.thisApp)) }) }),
|
|
1364
1486
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: config.show_kerne_branding })
|
|
1365
1487
|
] })
|
|
1366
1488
|
);
|
|
@@ -1422,7 +1544,7 @@ function RegisterForm({
|
|
|
1422
1544
|
),
|
|
1423
1545
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
|
|
1424
1546
|
error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
|
|
1425
|
-
linkSentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children:
|
|
1547
|
+
linkSentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: _chunkTYNZ2WU7cjs.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: [
|
|
1426
1548
|
needsCode ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1427
1549
|
Field,
|
|
1428
1550
|
{
|
|
@@ -1527,10 +1649,10 @@ function ForgotPasswordForm({
|
|
|
1527
1649
|
logo,
|
|
1528
1650
|
className
|
|
1529
1651
|
}) {
|
|
1530
|
-
const { requestPasswordReset } =
|
|
1531
|
-
const { config } =
|
|
1532
|
-
const l10n =
|
|
1533
|
-
const showError =
|
|
1652
|
+
const { requestPasswordReset } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
1653
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
1654
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1655
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
1534
1656
|
const [email, setEmail] = _react.useState.call(void 0, "");
|
|
1535
1657
|
const [submitting, setSubmitting] = _react.useState.call(void 0, false);
|
|
1536
1658
|
const [error, setError] = _react.useState.call(void 0, null);
|
|
@@ -1566,7 +1688,7 @@ function ForgotPasswordForm({
|
|
|
1566
1688
|
),
|
|
1567
1689
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
|
|
1568
1690
|
error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
|
|
1569
|
-
sentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children:
|
|
1691
|
+
sentTo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: _chunkTYNZ2WU7cjs.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: [
|
|
1570
1692
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
1571
1693
|
Field,
|
|
1572
1694
|
{
|
|
@@ -1603,12 +1725,12 @@ function ResetPasswordForm({
|
|
|
1603
1725
|
logo,
|
|
1604
1726
|
className
|
|
1605
1727
|
}) {
|
|
1606
|
-
const { confirmPasswordReset } =
|
|
1607
|
-
const { config } =
|
|
1728
|
+
const { confirmPasswordReset } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
1729
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
1608
1730
|
const policy = resolvePolicy(config);
|
|
1609
1731
|
const token = useUrlToken("token", tokenProp);
|
|
1610
|
-
const l10n =
|
|
1611
|
-
const showError =
|
|
1732
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1733
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
1612
1734
|
const [password, setPassword] = _react.useState.call(void 0, "");
|
|
1613
1735
|
const [confirm, setConfirm] = _react.useState.call(void 0, "");
|
|
1614
1736
|
const [submitting, setSubmitting] = _react.useState.call(void 0, false);
|
|
@@ -1723,12 +1845,12 @@ function MagicLinkCallback({
|
|
|
1723
1845
|
logo,
|
|
1724
1846
|
className
|
|
1725
1847
|
}) {
|
|
1726
|
-
const client =
|
|
1727
|
-
const { loginWithMagicLink } =
|
|
1728
|
-
const { config } =
|
|
1848
|
+
const client = _chunkTYNZ2WU7cjs.useClient.call(void 0, );
|
|
1849
|
+
const { loginWithMagicLink } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
1850
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
1729
1851
|
const token = useUrlToken("token", tokenProp);
|
|
1730
|
-
const l10n =
|
|
1731
|
-
const showError =
|
|
1852
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1853
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
1732
1854
|
const [state, setState] = _react.useState.call(void 0, "pending");
|
|
1733
1855
|
const [message, setMessage] = _react.useState.call(void 0, null);
|
|
1734
1856
|
const consumed = _react.useRef.call(void 0, false);
|
|
@@ -1782,11 +1904,11 @@ function VerifyEmailForm({
|
|
|
1782
1904
|
logo,
|
|
1783
1905
|
className
|
|
1784
1906
|
}) {
|
|
1785
|
-
const { verifyEmailWithCode, verifyEmailWithLink, sendVerificationEmail, refreshToken } =
|
|
1786
|
-
const { config } =
|
|
1907
|
+
const { verifyEmailWithCode, verifyEmailWithLink, sendVerificationEmail, refreshToken } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
1908
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
1787
1909
|
const token = useUrlToken("token", tokenProp);
|
|
1788
|
-
const l10n =
|
|
1789
|
-
const showError =
|
|
1910
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
1911
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
1790
1912
|
const [code, setCode] = _react.useState.call(void 0, "");
|
|
1791
1913
|
const [submitting, setSubmitting] = _react.useState.call(void 0, false);
|
|
1792
1914
|
const [error, setError] = _react.useState.call(void 0, null);
|
|
@@ -1908,13 +2030,13 @@ function ActivateAccountForm({
|
|
|
1908
2030
|
logo,
|
|
1909
2031
|
className
|
|
1910
2032
|
}) {
|
|
1911
|
-
const client =
|
|
1912
|
-
const { getActivationContext, completeActivation } =
|
|
1913
|
-
const { config } =
|
|
2033
|
+
const client = _chunkTYNZ2WU7cjs.useClient.call(void 0, );
|
|
2034
|
+
const { getActivationContext, completeActivation } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
2035
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
1914
2036
|
const policy = resolvePolicy(config);
|
|
1915
2037
|
const token = useUrlToken("token", tokenProp);
|
|
1916
|
-
const l10n =
|
|
1917
|
-
const showError =
|
|
2038
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2039
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
1918
2040
|
const [context, setContext] = _react.useState.call(void 0, null);
|
|
1919
2041
|
const [loadError, setLoadError] = _react.useState.call(void 0, null);
|
|
1920
2042
|
const [password, setPassword] = _react.useState.call(void 0, "");
|
|
@@ -1984,7 +2106,7 @@ function ActivateAccountForm({
|
|
|
1984
2106
|
{
|
|
1985
2107
|
logo,
|
|
1986
2108
|
title: heading,
|
|
1987
|
-
subtitle:
|
|
2109
|
+
subtitle: _chunkTYNZ2WU7cjs.fillNode.call(void 0,
|
|
1988
2110
|
credentialsMode ? l10n.activate.credentialsSubtitle : l10n.activate.magicSubtitle,
|
|
1989
2111
|
{ email: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: context.email }) }
|
|
1990
2112
|
)
|
|
@@ -2056,7 +2178,7 @@ function AuthFlow({
|
|
|
2056
2178
|
logo,
|
|
2057
2179
|
className
|
|
2058
2180
|
}) {
|
|
2059
|
-
const { config } =
|
|
2181
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
2060
2182
|
const token = useUrlToken("token");
|
|
2061
2183
|
const [internalStep, setInternalStep] = _react.useState.call(void 0, null);
|
|
2062
2184
|
const go = (next) => {
|
|
@@ -2143,11 +2265,11 @@ function ChangePasswordForm({
|
|
|
2143
2265
|
appearance,
|
|
2144
2266
|
className
|
|
2145
2267
|
}) {
|
|
2146
|
-
const { updatePassword } =
|
|
2147
|
-
const { config } =
|
|
2268
|
+
const { updatePassword } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
2269
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
2148
2270
|
const policy = resolvePolicy(config);
|
|
2149
|
-
const l10n =
|
|
2150
|
-
const showError =
|
|
2271
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2272
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
2151
2273
|
const heading = title === null ? null : _nullishCoalesce(title, () => ( l10n.security.submit));
|
|
2152
2274
|
const [currentPassword, setCurrentPassword] = _react.useState.call(void 0, "");
|
|
2153
2275
|
const [newPassword, setNewPassword] = _react.useState.call(void 0, "");
|
|
@@ -2253,10 +2375,10 @@ function WaitlistForm({
|
|
|
2253
2375
|
logo,
|
|
2254
2376
|
className
|
|
2255
2377
|
}) {
|
|
2256
|
-
const { join } =
|
|
2257
|
-
const { config } =
|
|
2258
|
-
const l10n =
|
|
2259
|
-
const showError =
|
|
2378
|
+
const { join } = _chunkTYNZ2WU7cjs.useWaitlist.call(void 0, );
|
|
2379
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
2380
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2381
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
2260
2382
|
const [email, setEmail] = _react.useState.call(void 0, "");
|
|
2261
2383
|
const [name, setName] = _react.useState.call(void 0, "");
|
|
2262
2384
|
const [submitting, setSubmitting] = _react.useState.call(void 0, false);
|
|
@@ -2337,8 +2459,8 @@ function SignOutButton({
|
|
|
2337
2459
|
appearance
|
|
2338
2460
|
}) {
|
|
2339
2461
|
ensureStylesInjected();
|
|
2340
|
-
const { logout } =
|
|
2341
|
-
const l10n =
|
|
2462
|
+
const { logout } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
2463
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2342
2464
|
const handle = () => {
|
|
2343
2465
|
logout();
|
|
2344
2466
|
_optionalChain([onSignedOut, 'optionalCall', _36 => _36()]);
|
|
@@ -2372,9 +2494,9 @@ function UserButton({
|
|
|
2372
2494
|
className
|
|
2373
2495
|
}) {
|
|
2374
2496
|
ensureStylesInjected();
|
|
2375
|
-
const { logout, isAuthenticated } =
|
|
2376
|
-
const { user, fullName, initials, email } =
|
|
2377
|
-
const l10n =
|
|
2497
|
+
const { logout, isAuthenticated } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
2498
|
+
const { user, fullName, initials, email } = _chunkTYNZ2WU7cjs.useUser.call(void 0, );
|
|
2499
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2378
2500
|
const [open, setOpen] = _react.useState.call(void 0, false);
|
|
2379
2501
|
const wrapRef = _react.useRef.call(void 0, null);
|
|
2380
2502
|
_react.useEffect.call(void 0, () => {
|
|
@@ -2465,10 +2587,10 @@ function UserButton({
|
|
|
2465
2587
|
|
|
2466
2588
|
|
|
2467
2589
|
function ProfileSection({ verificationCallbackUrl, onSaved }) {
|
|
2468
|
-
const { updateProfile, sendVerificationEmail, getVerificationStatus } =
|
|
2469
|
-
const { user, fullName, initials, email } =
|
|
2470
|
-
const l10n =
|
|
2471
|
-
const showError =
|
|
2590
|
+
const { updateProfile, sendVerificationEmail, getVerificationStatus } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
2591
|
+
const { user, fullName, initials, email } = _chunkTYNZ2WU7cjs.useUser.call(void 0, );
|
|
2592
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2593
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
2472
2594
|
const [firstName, setFirstName] = _react.useState.call(void 0, "");
|
|
2473
2595
|
const [lastName, setLastName] = _react.useState.call(void 0, "");
|
|
2474
2596
|
const [saving, setSaving] = _react.useState.call(void 0, false);
|
|
@@ -2579,10 +2701,10 @@ function ProfileSection({ verificationCallbackUrl, onSaved }) {
|
|
|
2579
2701
|
|
|
2580
2702
|
|
|
2581
2703
|
function SecuritySection({ showDeleteAccount = true, onDeleted }) {
|
|
2582
|
-
const { requestAccountDeletion } =
|
|
2583
|
-
const { config } =
|
|
2584
|
-
const l10n =
|
|
2585
|
-
const showError =
|
|
2704
|
+
const { requestAccountDeletion } = _chunkTYNZ2WU7cjs.useAuth.call(void 0, );
|
|
2705
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
2706
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2707
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
2586
2708
|
const [error, setError] = _react.useState.call(void 0, null);
|
|
2587
2709
|
const [confirmingDelete, setConfirmingDelete] = _react.useState.call(void 0, false);
|
|
2588
2710
|
const [deleting, setDeleting] = _react.useState.call(void 0, false);
|
|
@@ -2677,15 +2799,83 @@ function formatInterval(interval, labels) {
|
|
|
2677
2799
|
return interval;
|
|
2678
2800
|
}
|
|
2679
2801
|
}
|
|
2802
|
+
var ENCODED_INTERVAL_UNIT = { D: 12 / 365, M: 1, Y: 12 };
|
|
2803
|
+
function approxMonths(value) {
|
|
2804
|
+
const match = ENCODED_INTERVAL.exec(value);
|
|
2805
|
+
if (!match) return 0;
|
|
2806
|
+
return parseInt(match[1], 10) * ENCODED_INTERVAL_UNIT[match[2]];
|
|
2807
|
+
}
|
|
2808
|
+
function resolvePriceDisplay(price, displayInterval) {
|
|
2809
|
+
if (!displayInterval || displayInterval === price.interval) {
|
|
2810
|
+
return {
|
|
2811
|
+
billedAmount: price.amount,
|
|
2812
|
+
billedInterval: price.interval,
|
|
2813
|
+
displayAmount: price.amount,
|
|
2814
|
+
displayInterval: price.interval
|
|
2815
|
+
};
|
|
2816
|
+
}
|
|
2817
|
+
const ratio = approxMonths(displayInterval) / approxMonths(price.interval);
|
|
2818
|
+
return {
|
|
2819
|
+
billedAmount: price.amount,
|
|
2820
|
+
billedInterval: price.interval,
|
|
2821
|
+
displayAmount: Math.round(price.amount * ratio),
|
|
2822
|
+
displayInterval
|
|
2823
|
+
};
|
|
2824
|
+
}
|
|
2825
|
+
function collectPriceLabels(plans) {
|
|
2826
|
+
const bySlug = /* @__PURE__ */ new Map();
|
|
2827
|
+
for (const plan of plans) {
|
|
2828
|
+
for (const price of plan.prices) {
|
|
2829
|
+
if (!bySlug.has(price.label.slug)) bySlug.set(price.label.slug, price.label);
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
return Array.from(bySlug.values()).sort(
|
|
2833
|
+
(a, b) => a.sort_order - b.sort_order || a.name.localeCompare(b.name)
|
|
2834
|
+
);
|
|
2835
|
+
}
|
|
2836
|
+
function resolveLabelSavings(plans, labels) {
|
|
2837
|
+
if (labels.length < 2) return null;
|
|
2838
|
+
const priceFor = (labelSlug) => {
|
|
2839
|
+
for (const plan of plans) {
|
|
2840
|
+
const price = plan.prices.find((p) => p.label.slug === labelSlug);
|
|
2841
|
+
if (price) return price;
|
|
2842
|
+
}
|
|
2843
|
+
return void 0;
|
|
2844
|
+
};
|
|
2845
|
+
const sorted = [...labels].sort(
|
|
2846
|
+
(a, b) => approxMonths(_nullishCoalesce(_optionalChain([priceFor, 'call', _51 => _51(a.slug), 'optionalAccess', _52 => _52.interval]), () => ( "1M"))) - approxMonths(_nullishCoalesce(_optionalChain([priceFor, 'call', _53 => _53(b.slug), 'optionalAccess', _54 => _54.interval]), () => ( "1M")))
|
|
2847
|
+
);
|
|
2848
|
+
const shortest = sorted[0];
|
|
2849
|
+
const longest = sorted[sorted.length - 1];
|
|
2850
|
+
if (shortest.slug === longest.slug) return null;
|
|
2851
|
+
for (const plan of plans) {
|
|
2852
|
+
const shortPrice = plan.prices.find((p) => p.label.slug === shortest.slug);
|
|
2853
|
+
const longPrice = plan.prices.find((p) => p.label.slug === longest.slug);
|
|
2854
|
+
if (!_optionalChain([shortPrice, 'optionalAccess', _55 => _55.amount]) || !longPrice) continue;
|
|
2855
|
+
const shortMonths = approxMonths(shortPrice.interval);
|
|
2856
|
+
const longMonths = approxMonths(longPrice.interval);
|
|
2857
|
+
if (!shortMonths || !longMonths) continue;
|
|
2858
|
+
const savings = 1 - longPrice.amount / longMonths / (shortPrice.amount / shortMonths);
|
|
2859
|
+
if (savings > 0.01) return { labelSlug: longest.slug, percent: Math.round(savings * 100) };
|
|
2860
|
+
}
|
|
2861
|
+
return null;
|
|
2862
|
+
}
|
|
2680
2863
|
|
|
2681
2864
|
// src/ui/UsageMeters.tsx
|
|
2682
2865
|
|
|
2683
|
-
function
|
|
2684
|
-
|
|
2866
|
+
function isSoftOverage(overage) {
|
|
2867
|
+
return overage === "ALLOW" || overage === "BILL";
|
|
2868
|
+
}
|
|
2869
|
+
function levelFor(ratio, softOverage) {
|
|
2870
|
+
if (softOverage) return ratio >= 1 ? "warning" : "normal";
|
|
2685
2871
|
if (ratio >= 0.9) return "critical";
|
|
2686
2872
|
if (ratio >= 0.75) return "warning";
|
|
2687
2873
|
return "normal";
|
|
2688
2874
|
}
|
|
2875
|
+
function quotaRatio(used, limit) {
|
|
2876
|
+
if (limit <= 0) return used > 0 ? 1 : 0;
|
|
2877
|
+
return Math.min(used / limit, 1);
|
|
2878
|
+
}
|
|
2689
2879
|
function UsageMeters({
|
|
2690
2880
|
title,
|
|
2691
2881
|
featureKeys,
|
|
@@ -2696,13 +2886,13 @@ function UsageMeters({
|
|
|
2696
2886
|
appearance,
|
|
2697
2887
|
className
|
|
2698
2888
|
}) {
|
|
2699
|
-
const { entitlements, isLoading, error } =
|
|
2700
|
-
const { subscription } =
|
|
2701
|
-
const l10n =
|
|
2889
|
+
const { entitlements, isLoading, error } = _chunkTYNZ2WU7cjs.useEntitlements.call(void 0, );
|
|
2890
|
+
const { subscription } = _chunkTYNZ2WU7cjs.useSubscription.call(void 0, );
|
|
2891
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2702
2892
|
const heading = title === null ? null : _nullishCoalesce(title, () => ( l10n.usage.title));
|
|
2703
2893
|
const nameFor = (key) => {
|
|
2704
|
-
if (_optionalChain([labels, 'optionalAccess',
|
|
2705
|
-
const fromPlan = _optionalChain([subscription, 'optionalAccess',
|
|
2894
|
+
if (_optionalChain([labels, 'optionalAccess', _56 => _56[key]])) return labels[key];
|
|
2895
|
+
const fromPlan = _optionalChain([subscription, 'optionalAccess', _57 => _57.entitlements, 'access', _58 => _58.find, 'call', _59 => _59((e) => e.feature_key === key), 'optionalAccess', _60 => _60.feature_name]);
|
|
2706
2896
|
return _nullishCoalesce(fromPlan, () => ( humanizeFeatureKey(key)));
|
|
2707
2897
|
};
|
|
2708
2898
|
const shell = (children) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
|
|
@@ -2739,14 +2929,17 @@ function UsageMeters({
|
|
|
2739
2929
|
return shell(
|
|
2740
2930
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-meters", children: rows.map((e) => {
|
|
2741
2931
|
const unlimited = e.limit === null || e.limit === void 0;
|
|
2742
|
-
const
|
|
2743
|
-
const
|
|
2744
|
-
const
|
|
2932
|
+
const softOverage = isSoftOverage(e.overage_behavior);
|
|
2933
|
+
const billed = e.overage_behavior === "BILL";
|
|
2934
|
+
const ratio = unlimited ? 0 : quotaRatio(e.used, e.limit);
|
|
2935
|
+
const level = unlimited ? "normal" : levelFor(ratio, softOverage);
|
|
2745
2936
|
const over = !unlimited && e.used > e.limit;
|
|
2937
|
+
const standing = billed ? _optionalChain([subscription, 'optionalAccess', _61 => _61.entitlements, 'access', _62 => _62.find, 'call', _63 => _63((se) => se.feature_key === e.feature_key)]) : void 0;
|
|
2938
|
+
const capReached = billed && (_nullishCoalesce(_optionalChain([standing, 'optionalAccess', _64 => _64.cap_reached]), () => ( false)));
|
|
2746
2939
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-meter", "data-level": level, children: [
|
|
2747
2940
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-meter-head", children: [
|
|
2748
2941
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-meter-name", children: nameFor(e.feature_key) }),
|
|
2749
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-meter-value", children: unlimited ?
|
|
2942
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-meter-value", children: unlimited ? _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.usage.used, { count: formatNumber(e.used) }) : `${formatNumber(e.used)} / ${formatNumber(e.limit)}` })
|
|
2750
2943
|
] }),
|
|
2751
2944
|
!unlimited ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
2752
2945
|
"div",
|
|
@@ -2760,9 +2953,18 @@ function UsageMeters({
|
|
|
2760
2953
|
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-meter-fill", style: { width: `${ratio * 100}%` } })
|
|
2761
2954
|
}
|
|
2762
2955
|
) : null,
|
|
2763
|
-
over &&
|
|
2764
|
-
|
|
2765
|
-
|
|
2956
|
+
over && softOverage ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
2957
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-meter-note", children: _chunkTYNZ2WU7cjs.fill.call(void 0,
|
|
2958
|
+
// capReached inverts overageBilled's meaning (billing stopped,
|
|
2959
|
+
// access didn't) - a variant string would say the opposite of
|
|
2960
|
+
// the truth for the one plan that just stopped costing money.
|
|
2961
|
+
capReached ? l10n.usage.capReached : billed ? l10n.usage.overageBilled : l10n.usage.overage,
|
|
2962
|
+
{ count: formatNumber(e.used - e.limit) }
|
|
2963
|
+
) }),
|
|
2964
|
+
billed && _optionalChain([standing, 'optionalAccess', _65 => _65.billed_amount]) != null && standing.currency ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-meter-note kerne-meter-cost", children: _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.usage.billedAmount, {
|
|
2965
|
+
amount: formatMoney(standing.billed_amount, standing.currency)
|
|
2966
|
+
}) }) : null
|
|
2967
|
+
] }) : over ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-meter-note", children: l10n.usage.limitReached }) : null
|
|
2766
2968
|
] }, e.feature_key);
|
|
2767
2969
|
}) })
|
|
2768
2970
|
);
|
|
@@ -2786,13 +2988,15 @@ function SubscriptionCard({
|
|
|
2786
2988
|
upgradeUrl,
|
|
2787
2989
|
onUpgradeClick,
|
|
2788
2990
|
hidePortalButton = false,
|
|
2991
|
+
hideCancelButton = false,
|
|
2789
2992
|
appearance,
|
|
2790
2993
|
className
|
|
2791
2994
|
}) {
|
|
2792
|
-
const { subscription, isLoading, error } =
|
|
2793
|
-
const { openPortal } =
|
|
2794
|
-
const
|
|
2795
|
-
const
|
|
2995
|
+
const { subscription, isLoading, error, refetch } = _chunkTYNZ2WU7cjs.useSubscription.call(void 0, productSlug);
|
|
2996
|
+
const { openPortal } = _chunkTYNZ2WU7cjs.usePortal.call(void 0, );
|
|
2997
|
+
const { cancelSubscription, isCanceling } = _chunkTYNZ2WU7cjs.useCancelSubscription.call(void 0, );
|
|
2998
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
2999
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
2796
3000
|
const heading = title === null ? null : _nullishCoalesce(title, () => ( l10n.billing.plan));
|
|
2797
3001
|
const statusLabels = {
|
|
2798
3002
|
ACTIVE: l10n.billing.statusActive,
|
|
@@ -2804,6 +3008,8 @@ function SubscriptionCard({
|
|
|
2804
3008
|
};
|
|
2805
3009
|
const [opening, setOpening] = _react.useState.call(void 0, false);
|
|
2806
3010
|
const [portalError, setPortalError] = _react.useState.call(void 0, null);
|
|
3011
|
+
const [confirmingCancel, setConfirmingCancel] = _react.useState.call(void 0, false);
|
|
3012
|
+
const [cancelError, setCancelError] = _react.useState.call(void 0, null);
|
|
2807
3013
|
const handlePortal = async () => {
|
|
2808
3014
|
setPortalError(null);
|
|
2809
3015
|
setOpening(true);
|
|
@@ -2814,6 +3020,17 @@ function SubscriptionCard({
|
|
|
2814
3020
|
setOpening(false);
|
|
2815
3021
|
}
|
|
2816
3022
|
};
|
|
3023
|
+
const handleCancel = async () => {
|
|
3024
|
+
if (!subscription) return;
|
|
3025
|
+
setCancelError(null);
|
|
3026
|
+
try {
|
|
3027
|
+
await cancelSubscription(subscription.id, false);
|
|
3028
|
+
setConfirmingCancel(false);
|
|
3029
|
+
refetch();
|
|
3030
|
+
} catch (e) {
|
|
3031
|
+
setCancelError(showError(e));
|
|
3032
|
+
}
|
|
3033
|
+
};
|
|
2817
3034
|
const shell = (children) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-stack", children: [
|
|
2818
3035
|
heading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "kerne-section-title", children: heading }) : null,
|
|
2819
3036
|
children
|
|
@@ -2879,7 +3096,27 @@ function SubscriptionCard({
|
|
|
2879
3096
|
] }) : null
|
|
2880
3097
|
] }),
|
|
2881
3098
|
canceled_at ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { children: l10n.billing.cancelNotice }) : null,
|
|
2882
|
-
|
|
3099
|
+
cancelError ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: cancelError }) : null,
|
|
3100
|
+
confirmingCancel ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Panel, { children: [
|
|
3101
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { children: l10n.billing.cancelConfirmTitle }),
|
|
3102
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-subsection-desc", children: l10n.billing.cancelConfirmBody }),
|
|
3103
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-inline-actions", children: [
|
|
3104
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
3105
|
+
Button,
|
|
3106
|
+
{
|
|
3107
|
+
variant: "outline",
|
|
3108
|
+
type: "button",
|
|
3109
|
+
onClick: () => setConfirmingCancel(false),
|
|
3110
|
+
disabled: isCanceling,
|
|
3111
|
+
children: l10n.billing.cancelConfirmDismiss
|
|
3112
|
+
}
|
|
3113
|
+
),
|
|
3114
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { type: "button", onClick: handleCancel, loading: isCanceling, children: isCanceling ? l10n.billing.canceling : l10n.billing.cancelConfirmButton })
|
|
3115
|
+
] })
|
|
3116
|
+
] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-inline-actions", children: [
|
|
3117
|
+
!hidePortalButton ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", type: "button", onClick: handlePortal, loading: opening, children: opening ? l10n.billing.opening : l10n.billing.managePortal }) : null,
|
|
3118
|
+
!hideCancelButton && !canceled_at && status !== "CANCELED" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", type: "button", onClick: () => setConfirmingCancel(true), children: l10n.billing.cancelSubscription }) : null
|
|
3119
|
+
] })
|
|
2883
3120
|
] })
|
|
2884
3121
|
);
|
|
2885
3122
|
}
|
|
@@ -2906,31 +3143,37 @@ function BillingSection({
|
|
|
2906
3143
|
usageFeatureKeys,
|
|
2907
3144
|
usageLabels
|
|
2908
3145
|
}) {
|
|
2909
|
-
const { subscription } =
|
|
2910
|
-
const { plans, isLoading: plansLoading } =
|
|
2911
|
-
const
|
|
2912
|
-
const
|
|
2913
|
-
const
|
|
2914
|
-
|
|
2915
|
-
|
|
3146
|
+
const { subscription, refetch: refetchSubscription } = _chunkTYNZ2WU7cjs.useSubscription.call(void 0, productSlug);
|
|
3147
|
+
const { plans, isLoading: plansLoading } = _chunkTYNZ2WU7cjs.usePlans.call(void 0, pricingProductIdOrSlug);
|
|
3148
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
3149
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
3150
|
+
const {
|
|
3151
|
+
pending: pendingPlan,
|
|
3152
|
+
switching,
|
|
3153
|
+
switchError,
|
|
3154
|
+
checkoutPriceId: busy,
|
|
3155
|
+
checkoutError,
|
|
3156
|
+
selectPlan,
|
|
3157
|
+
confirmSwitch,
|
|
3158
|
+
dismissSwitch
|
|
3159
|
+
} = _chunkTYNZ2WU7cjs.usePlanSwitch.call(void 0, subscription, refetchSubscription, {
|
|
3160
|
+
successUrl: checkoutSuccessUrl,
|
|
3161
|
+
cancelUrl: checkoutCancelUrl
|
|
3162
|
+
});
|
|
3163
|
+
const error = _nullishCoalesce(checkoutError, () => ( switchError));
|
|
2916
3164
|
const intervals = _react.useMemo.call(void 0, () => intervalsOf(plans), [plans]);
|
|
2917
3165
|
const [interval, setInterval] = _react.useState.call(void 0, null);
|
|
2918
|
-
const activeInterval = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(interval, () => ( _optionalChain([subscription, 'optionalAccess',
|
|
2919
|
-
const handleSwitch = async (planPriceId) => {
|
|
2920
|
-
setError(null);
|
|
2921
|
-
setBusy(planPriceId);
|
|
2922
|
-
try {
|
|
2923
|
-
await openCheckout(planPriceId, {
|
|
2924
|
-
successUrl: checkoutSuccessUrl,
|
|
2925
|
-
cancelUrl: checkoutCancelUrl
|
|
2926
|
-
});
|
|
2927
|
-
} catch (e) {
|
|
2928
|
-
setError(showError(e));
|
|
2929
|
-
setBusy(null);
|
|
2930
|
-
}
|
|
2931
|
-
};
|
|
3166
|
+
const activeInterval = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(interval, () => ( _optionalChain([subscription, 'optionalAccess', _66 => _66.plan_price, 'access', _67 => _67.interval]))), () => ( intervals[0])), () => ( null));
|
|
2932
3167
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
2933
|
-
error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: error }) : null,
|
|
3168
|
+
error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: showError(error) }) : null,
|
|
3169
|
+
pendingPlan ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Panel, { children: [
|
|
3170
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { children: _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.billing.switchConfirmTitle, { plan: pendingPlan.plan.name }) }),
|
|
3171
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-subsection-desc", children: l10n.billing.switchConfirmBody }),
|
|
3172
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-inline-actions", children: [
|
|
3173
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", type: "button", onClick: dismissSwitch, disabled: switching, children: l10n.billing.switchConfirmDismiss }),
|
|
3174
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { type: "button", onClick: confirmSwitch, loading: switching, children: switching ? l10n.billing.switching : l10n.billing.switchConfirmButton })
|
|
3175
|
+
] })
|
|
3176
|
+
] }) : null,
|
|
2934
3177
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Subsection, { title: l10n.billing.currentPlan, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
2935
3178
|
SubscriptionCard,
|
|
2936
3179
|
{
|
|
@@ -2969,7 +3212,7 @@ function BillingSection({
|
|
|
2969
3212
|
) : null,
|
|
2970
3213
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-plan-list", children: plans.map((plan) => {
|
|
2971
3214
|
const price = _nullishCoalesce(plan.prices.find((p) => p.interval === activeInterval), () => ( plan.prices[0]));
|
|
2972
|
-
const isCurrent = _optionalChain([subscription, 'optionalAccess',
|
|
3215
|
+
const isCurrent = _optionalChain([subscription, 'optionalAccess', _68 => _68.plan, 'access', _69 => _69.slug]) === plan.slug;
|
|
2973
3216
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
2974
3217
|
"div",
|
|
2975
3218
|
{
|
|
@@ -2988,7 +3231,7 @@ function BillingSection({
|
|
|
2988
3231
|
{
|
|
2989
3232
|
variant: "outline",
|
|
2990
3233
|
type: "button",
|
|
2991
|
-
onClick: () =>
|
|
3234
|
+
onClick: () => selectPlan(plan, price),
|
|
2992
3235
|
loading: busy === price.id,
|
|
2993
3236
|
disabled: busy !== null,
|
|
2994
3237
|
children: busy === price.id ? l10n.billing.opening : l10n.billing.switchTo
|
|
@@ -3027,7 +3270,7 @@ function UserProfile({
|
|
|
3027
3270
|
appearance,
|
|
3028
3271
|
className
|
|
3029
3272
|
}) {
|
|
3030
|
-
const l10n =
|
|
3273
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
3031
3274
|
const builtins = {
|
|
3032
3275
|
profile: {
|
|
3033
3276
|
label: l10n.profile.tabProfile,
|
|
@@ -3054,15 +3297,15 @@ function UserProfile({
|
|
|
3054
3297
|
description: t.description
|
|
3055
3298
|
}))
|
|
3056
3299
|
];
|
|
3057
|
-
const [internalTab, setInternalTab] = _react.useState.call(void 0, _nullishCoalesce(_nullishCoalesce(defaultTab, () => ( _optionalChain([allTabs, 'access',
|
|
3300
|
+
const [internalTab, setInternalTab] = _react.useState.call(void 0, _nullishCoalesce(_nullishCoalesce(defaultTab, () => ( _optionalChain([allTabs, 'access', _70 => _70[0], 'optionalAccess', _71 => _71.id]))), () => ( "profile")));
|
|
3058
3301
|
const current = _nullishCoalesce(controlledTab, () => ( internalTab));
|
|
3059
3302
|
const select = (id) => {
|
|
3060
3303
|
if (controlledTab === void 0) setInternalTab(id);
|
|
3061
|
-
_optionalChain([onTabChange, 'optionalCall',
|
|
3304
|
+
_optionalChain([onTabChange, 'optionalCall', _72 => _72(id)]);
|
|
3062
3305
|
};
|
|
3063
3306
|
const active = _nullishCoalesce(allTabs.find((t) => t.id === current), () => ( allTabs[0]));
|
|
3064
3307
|
const renderPane = () => {
|
|
3065
|
-
switch (_optionalChain([active, 'optionalAccess',
|
|
3308
|
+
switch (_optionalChain([active, 'optionalAccess', _73 => _73.id])) {
|
|
3066
3309
|
case "profile":
|
|
3067
3310
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ProfileSection, { verificationCallbackUrl, onSaved });
|
|
3068
3311
|
case "security":
|
|
@@ -3083,7 +3326,7 @@ function UserProfile({
|
|
|
3083
3326
|
}
|
|
3084
3327
|
);
|
|
3085
3328
|
default:
|
|
3086
|
-
return _nullishCoalesce(_optionalChain([extraTabs, 'access',
|
|
3329
|
+
return _nullishCoalesce(_optionalChain([extraTabs, 'access', _74 => _74.find, 'call', _75 => _75((t) => t.id === _optionalChain([active, 'optionalAccess', _76 => _76.id])), 'optionalAccess', _77 => _77.content]), () => ( null));
|
|
3087
3330
|
}
|
|
3088
3331
|
};
|
|
3089
3332
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, size: "wide", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-profile", children: [
|
|
@@ -3092,7 +3335,7 @@ function UserProfile({
|
|
|
3092
3335
|
{
|
|
3093
3336
|
type: "button",
|
|
3094
3337
|
className: "kerne-nav-item",
|
|
3095
|
-
"aria-current": tab.id === _optionalChain([active, 'optionalAccess',
|
|
3338
|
+
"aria-current": tab.id === _optionalChain([active, 'optionalAccess', _78 => _78.id]) ? "page" : void 0,
|
|
3096
3339
|
onClick: () => select(tab.id),
|
|
3097
3340
|
children: tab.label
|
|
3098
3341
|
},
|
|
@@ -3108,6 +3351,288 @@ function UserProfile({
|
|
|
3108
3351
|
] }) });
|
|
3109
3352
|
}
|
|
3110
3353
|
|
|
3354
|
+
// src/ui/PricingTable.tsx
|
|
3355
|
+
|
|
3356
|
+
|
|
3357
|
+
function formatEntitlement(e, unlimitedLabel) {
|
|
3358
|
+
if (e.feature_type === "BOOLEAN") return e.feature_name;
|
|
3359
|
+
if (e.feature_type === "STATIC")
|
|
3360
|
+
return e.value ? `${e.feature_name}: ${e.value}` : e.feature_name;
|
|
3361
|
+
if (e.limit === null) return e.feature_name;
|
|
3362
|
+
if (e.limit === -1) return `${unlimitedLabel} ${e.feature_name.toLowerCase()}`;
|
|
3363
|
+
return `${formatNumber(e.limit)} ${e.feature_name.toLowerCase()}`;
|
|
3364
|
+
}
|
|
3365
|
+
var PricingTableContext = _react.createContext.call(void 0, null);
|
|
3366
|
+
function usePricingTable() {
|
|
3367
|
+
const ctx = _react.useContext.call(void 0, PricingTableContext);
|
|
3368
|
+
if (!ctx) {
|
|
3369
|
+
throw new Error("usePricingTable() must be called inside <PricingTable>.");
|
|
3370
|
+
}
|
|
3371
|
+
return ctx;
|
|
3372
|
+
}
|
|
3373
|
+
function PricingTable({
|
|
3374
|
+
product,
|
|
3375
|
+
defaultLabel,
|
|
3376
|
+
checkoutSuccessUrl,
|
|
3377
|
+
checkoutCancelUrl,
|
|
3378
|
+
onSelectPlan,
|
|
3379
|
+
appearance,
|
|
3380
|
+
className,
|
|
3381
|
+
children
|
|
3382
|
+
}) {
|
|
3383
|
+
const { plans, isLoading, error } = _chunkTYNZ2WU7cjs.usePlans.call(void 0, product);
|
|
3384
|
+
const { subscription, refetch: refetchSubscription } = _chunkTYNZ2WU7cjs.useSubscription.call(void 0, product);
|
|
3385
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
3386
|
+
const showError = _chunkTYNZ2WU7cjs.useErrorResolver.call(void 0, );
|
|
3387
|
+
const [selectedLabelSlug, setSelectedLabelSlug] = _react.useState.call(void 0, _nullishCoalesce(defaultLabel, () => ( null)));
|
|
3388
|
+
const {
|
|
3389
|
+
pending: pendingSwitch,
|
|
3390
|
+
switching,
|
|
3391
|
+
switchError,
|
|
3392
|
+
checkoutPriceId: busyPriceId,
|
|
3393
|
+
checkoutError,
|
|
3394
|
+
selectPlan,
|
|
3395
|
+
confirmSwitch,
|
|
3396
|
+
dismissSwitch
|
|
3397
|
+
} = _chunkTYNZ2WU7cjs.usePlanSwitch.call(void 0, subscription, refetchSubscription, {
|
|
3398
|
+
successUrl: checkoutSuccessUrl,
|
|
3399
|
+
cancelUrl: checkoutCancelUrl
|
|
3400
|
+
});
|
|
3401
|
+
const labels = _react.useMemo.call(void 0, () => collectPriceLabels(plans), [plans]);
|
|
3402
|
+
const savings = _react.useMemo.call(void 0, () => resolveLabelSavings(plans, labels), [plans, labels]);
|
|
3403
|
+
_react.useEffect.call(void 0, () => {
|
|
3404
|
+
if (labels.length === 0) return;
|
|
3405
|
+
if (selectedLabelSlug && labels.some((l) => l.slug === selectedLabelSlug)) return;
|
|
3406
|
+
setSelectedLabelSlug(labels[0].slug);
|
|
3407
|
+
}, [labels]);
|
|
3408
|
+
const handleSelectPlan = (plan) => {
|
|
3409
|
+
const price = _nullishCoalesce(plan.prices.find((p) => p.label.slug === selectedLabelSlug), () => ( plan.prices[0]));
|
|
3410
|
+
if (!price) return;
|
|
3411
|
+
if (onSelectPlan) {
|
|
3412
|
+
onSelectPlan(plan, price);
|
|
3413
|
+
return;
|
|
3414
|
+
}
|
|
3415
|
+
void selectPlan(plan, price);
|
|
3416
|
+
};
|
|
3417
|
+
const ctx = {
|
|
3418
|
+
plans,
|
|
3419
|
+
labels,
|
|
3420
|
+
selectedLabelSlug,
|
|
3421
|
+
setSelectedLabelSlug,
|
|
3422
|
+
savings,
|
|
3423
|
+
currentPlanId: _nullishCoalesce(_optionalChain([subscription, 'optionalAccess', _79 => _79.plan, 'optionalAccess', _80 => _80.id]), () => ( null)),
|
|
3424
|
+
busyPriceId,
|
|
3425
|
+
onSelectPlan: handleSelectPlan
|
|
3426
|
+
};
|
|
3427
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, size: "wide", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-pricing-skeleton", "aria-busy": "true", "aria-label": l10n.pricing.loading, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-skeleton", style: { height: 320 } }) }) : error ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: l10n.pricing.loadFailed }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, PricingTableContext.Provider, { value: ctx, children: [
|
|
3428
|
+
checkoutError ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: showError(checkoutError) }) : null,
|
|
3429
|
+
pendingSwitch ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Panel, { children: [
|
|
3430
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { children: _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.billing.switchConfirmTitle, { plan: pendingSwitch.plan.name }) }),
|
|
3431
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-subsection-desc", children: l10n.billing.switchConfirmBody }),
|
|
3432
|
+
switchError ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Panel, { variant: "danger", children: showError(switchError) }) : null,
|
|
3433
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-inline-actions", children: [
|
|
3434
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
3435
|
+
Button,
|
|
3436
|
+
{
|
|
3437
|
+
variant: "outline",
|
|
3438
|
+
type: "button",
|
|
3439
|
+
onClick: dismissSwitch,
|
|
3440
|
+
disabled: switching,
|
|
3441
|
+
children: l10n.billing.switchConfirmDismiss
|
|
3442
|
+
}
|
|
3443
|
+
),
|
|
3444
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { type: "button", onClick: confirmSwitch, loading: switching, children: switching ? l10n.billing.switching : l10n.billing.switchConfirmButton })
|
|
3445
|
+
] })
|
|
3446
|
+
] }) : null,
|
|
3447
|
+
children
|
|
3448
|
+
] }) });
|
|
3449
|
+
}
|
|
3450
|
+
function LabelSwitch() {
|
|
3451
|
+
const { labels, selectedLabelSlug, setSelectedLabelSlug, savings } = usePricingTable();
|
|
3452
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
3453
|
+
const containerRef = _react.useRef.call(void 0, null);
|
|
3454
|
+
const buttonRefs = _react.useRef.call(void 0, /* @__PURE__ */ new Map());
|
|
3455
|
+
const [thumb, setThumb] = _react.useState.call(void 0, null);
|
|
3456
|
+
_react.useEffect.call(void 0, () => {
|
|
3457
|
+
const measure = () => {
|
|
3458
|
+
const container = containerRef.current;
|
|
3459
|
+
const button = selectedLabelSlug ? buttonRefs.current.get(selectedLabelSlug) : null;
|
|
3460
|
+
if (!container || !button) return;
|
|
3461
|
+
const containerBox = container.getBoundingClientRect();
|
|
3462
|
+
const buttonBox = button.getBoundingClientRect();
|
|
3463
|
+
setThumb({ left: buttonBox.left - containerBox.left, width: buttonBox.width });
|
|
3464
|
+
};
|
|
3465
|
+
measure();
|
|
3466
|
+
window.addEventListener("resize", measure);
|
|
3467
|
+
return () => window.removeEventListener("resize", measure);
|
|
3468
|
+
}, [selectedLabelSlug, labels]);
|
|
3469
|
+
if (labels.length < 2) return null;
|
|
3470
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-pricing-switch-wrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
3471
|
+
"div",
|
|
3472
|
+
{
|
|
3473
|
+
ref: containerRef,
|
|
3474
|
+
className: "kerne-pricing-switch",
|
|
3475
|
+
role: "group",
|
|
3476
|
+
"aria-label": l10n.billing.intervalGroupLabel,
|
|
3477
|
+
children: [
|
|
3478
|
+
thumb ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
3479
|
+
"span",
|
|
3480
|
+
{
|
|
3481
|
+
className: "kerne-pricing-switch-thumb",
|
|
3482
|
+
style: { transform: `translateX(${thumb.left}px)`, width: `${thumb.width}px` },
|
|
3483
|
+
"aria-hidden": "true"
|
|
3484
|
+
}
|
|
3485
|
+
) : null,
|
|
3486
|
+
labels.map((label) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
3487
|
+
"button",
|
|
3488
|
+
{
|
|
3489
|
+
ref: (el) => {
|
|
3490
|
+
if (el) buttonRefs.current.set(label.slug, el);
|
|
3491
|
+
else buttonRefs.current.delete(label.slug);
|
|
3492
|
+
},
|
|
3493
|
+
type: "button",
|
|
3494
|
+
className: "kerne-pricing-switch-option",
|
|
3495
|
+
"aria-pressed": label.slug === selectedLabelSlug,
|
|
3496
|
+
onClick: () => setSelectedLabelSlug(label.slug),
|
|
3497
|
+
children: [
|
|
3498
|
+
label.name,
|
|
3499
|
+
savings && savings.labelSlug === label.slug ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-pricing-switch-save", children: _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.pricing.save, { percent: savings.percent }) }) : null
|
|
3500
|
+
]
|
|
3501
|
+
},
|
|
3502
|
+
label.slug
|
|
3503
|
+
))
|
|
3504
|
+
]
|
|
3505
|
+
}
|
|
3506
|
+
) });
|
|
3507
|
+
}
|
|
3508
|
+
function useAnimatedAmount(target, durationMs = 420) {
|
|
3509
|
+
const [displayed, setDisplayed] = _react.useState.call(void 0, target);
|
|
3510
|
+
const displayedRef = _react.useRef.call(void 0, target);
|
|
3511
|
+
const frameRef = _react.useRef.call(void 0, );
|
|
3512
|
+
_react.useEffect.call(void 0, () => {
|
|
3513
|
+
if (displayedRef.current === target) return;
|
|
3514
|
+
const reduceMotion = typeof window !== "undefined" && _optionalChain([window, 'access', _81 => _81.matchMedia, 'optionalCall', _82 => _82("(prefers-reduced-motion: reduce)"), 'access', _83 => _83.matches]);
|
|
3515
|
+
if (reduceMotion) {
|
|
3516
|
+
displayedRef.current = target;
|
|
3517
|
+
setDisplayed(target);
|
|
3518
|
+
return;
|
|
3519
|
+
}
|
|
3520
|
+
const from = displayedRef.current;
|
|
3521
|
+
const start = performance.now();
|
|
3522
|
+
const tick = (now) => {
|
|
3523
|
+
const t = Math.min((now - start) / durationMs, 1);
|
|
3524
|
+
const eased = 1 - Math.pow(1 - t, 3);
|
|
3525
|
+
const value = Math.round(from + (target - from) * eased);
|
|
3526
|
+
displayedRef.current = value;
|
|
3527
|
+
setDisplayed(value);
|
|
3528
|
+
if (t < 1) frameRef.current = requestAnimationFrame(tick);
|
|
3529
|
+
};
|
|
3530
|
+
frameRef.current = requestAnimationFrame(tick);
|
|
3531
|
+
return () => {
|
|
3532
|
+
if (frameRef.current) cancelAnimationFrame(frameRef.current);
|
|
3533
|
+
};
|
|
3534
|
+
}, [target, durationMs]);
|
|
3535
|
+
return displayed;
|
|
3536
|
+
}
|
|
3537
|
+
function Plan({ slug, featured, badge, maxFeatures }) {
|
|
3538
|
+
const { plans, selectedLabelSlug, currentPlanId, busyPriceId, onSelectPlan } = usePricingTable();
|
|
3539
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
3540
|
+
const plan = plans.find((p) => p.slug === slug);
|
|
3541
|
+
_react.useEffect.call(void 0, () => {
|
|
3542
|
+
if (!plan && process.env.NODE_ENV === "development") {
|
|
3543
|
+
console.warn(
|
|
3544
|
+
`[Kerne] <PricingTable.Plan slug="${slug}"> - no plan with this slug on the loaded product.`
|
|
3545
|
+
);
|
|
3546
|
+
}
|
|
3547
|
+
}, [plan, slug]);
|
|
3548
|
+
const price = _nullishCoalesce(_optionalChain([plan, 'optionalAccess', _84 => _84.prices, 'access', _85 => _85.find, 'call', _86 => _86((p) => p.label.slug === selectedLabelSlug)]), () => ( _optionalChain([plan, 'optionalAccess', _87 => _87.prices, 'access', _88 => _88[0]])));
|
|
3549
|
+
const resolved = price ? resolvePriceDisplay(price, price.label.display_interval) : null;
|
|
3550
|
+
const animatedAmount = useAnimatedAmount(_nullishCoalesce(_optionalChain([resolved, 'optionalAccess', _89 => _89.displayAmount]), () => ( 0)));
|
|
3551
|
+
if (!plan) return null;
|
|
3552
|
+
const isCurrent = plan.id === currentPlanId;
|
|
3553
|
+
const isBusy = !!price && busyPriceId === price.id;
|
|
3554
|
+
const shownEntitlements = maxFeatures ? plan.entitlements.slice(0, maxFeatures) : plan.entitlements;
|
|
3555
|
+
const remaining = plan.entitlements.length - shownEntitlements.length;
|
|
3556
|
+
const billedCaption = resolved && resolved.displayInterval !== resolved.billedInterval ? _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.pricing.billedAt, {
|
|
3557
|
+
amount: formatMoney(resolved.billedAmount, price.currency),
|
|
3558
|
+
interval: formatInterval(resolved.billedInterval, l10n.billing)
|
|
3559
|
+
}) : null;
|
|
3560
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
3561
|
+
"div",
|
|
3562
|
+
{
|
|
3563
|
+
className: "kerne-pricing-card",
|
|
3564
|
+
"data-featured": featured ? "true" : void 0,
|
|
3565
|
+
"data-current": isCurrent ? "true" : void 0,
|
|
3566
|
+
children: [
|
|
3567
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-pricing-card-head", children: [
|
|
3568
|
+
badge ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-pricing-badge", children: badge }) : null,
|
|
3569
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-pricing-card-name", children: plan.name }),
|
|
3570
|
+
plan.description ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-pricing-card-desc", children: plan.description }) : null
|
|
3571
|
+
] }),
|
|
3572
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-pricing-price", children: resolved ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
3573
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-pricing-price-row", children: [
|
|
3574
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "kerne-pricing-amount", children: formatMoney(animatedAmount, price.currency) }),
|
|
3575
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "kerne-pricing-interval", children: [
|
|
3576
|
+
"/ ",
|
|
3577
|
+
formatInterval(resolved.displayInterval, l10n.billing)
|
|
3578
|
+
] })
|
|
3579
|
+
] }),
|
|
3580
|
+
billedCaption ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-pricing-billed", children: billedCaption }) : null
|
|
3581
|
+
] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "kerne-pricing-billed", children: l10n.billing.notOnInterval }) }),
|
|
3582
|
+
shownEntitlements.length > 0 ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "ul", { className: "kerne-pricing-features", children: [
|
|
3583
|
+
shownEntitlements.map((e) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "li", { className: "kerne-pricing-feature", children: [
|
|
3584
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, CheckIcon2, {}),
|
|
3585
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: formatEntitlement(e, l10n.pricing.unlimited) })
|
|
3586
|
+
] }, e.feature_key)),
|
|
3587
|
+
remaining > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { className: "kerne-pricing-feature-more", children: _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.pricing.moreFeatures, { count: remaining }) }) : null
|
|
3588
|
+
] }) : null,
|
|
3589
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-pricing-cta", children: isCurrent ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "outline", type: "button", disabled: true, children: l10n.billing.current }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
3590
|
+
Button,
|
|
3591
|
+
{
|
|
3592
|
+
variant: featured ? "primary" : "outline",
|
|
3593
|
+
type: "button",
|
|
3594
|
+
disabled: !price || busyPriceId !== null && !isBusy,
|
|
3595
|
+
loading: isBusy,
|
|
3596
|
+
onClick: () => onSelectPlan(plan),
|
|
3597
|
+
children: currentPlanId ? l10n.billing.switchTo : l10n.pricing.getStarted
|
|
3598
|
+
}
|
|
3599
|
+
) })
|
|
3600
|
+
]
|
|
3601
|
+
}
|
|
3602
|
+
);
|
|
3603
|
+
}
|
|
3604
|
+
function CheckIcon2() {
|
|
3605
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
3606
|
+
"svg",
|
|
3607
|
+
{
|
|
3608
|
+
width: "15",
|
|
3609
|
+
height: "15",
|
|
3610
|
+
viewBox: "0 0 24 24",
|
|
3611
|
+
fill: "none",
|
|
3612
|
+
stroke: "currentColor",
|
|
3613
|
+
strokeWidth: "2",
|
|
3614
|
+
"aria-hidden": "true",
|
|
3615
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "m5 13 4 4L19 7", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
3616
|
+
}
|
|
3617
|
+
);
|
|
3618
|
+
}
|
|
3619
|
+
function Plans({ featuredSlug, featuredBadge, maxFeatures }) {
|
|
3620
|
+
const { plans } = usePricingTable();
|
|
3621
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-pricing-grid", children: plans.map((plan) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
3622
|
+
Plan,
|
|
3623
|
+
{
|
|
3624
|
+
slug: plan.slug,
|
|
3625
|
+
featured: plan.slug === featuredSlug,
|
|
3626
|
+
badge: plan.slug === featuredSlug ? featuredBadge : void 0,
|
|
3627
|
+
maxFeatures
|
|
3628
|
+
},
|
|
3629
|
+
plan.id
|
|
3630
|
+
)) });
|
|
3631
|
+
}
|
|
3632
|
+
PricingTable.LabelSwitch = LabelSwitch;
|
|
3633
|
+
PricingTable.Plan = Plan;
|
|
3634
|
+
PricingTable.Plans = Plans;
|
|
3635
|
+
|
|
3111
3636
|
// src/ui/CheckoutResult.tsx
|
|
3112
3637
|
|
|
3113
3638
|
|
|
@@ -3125,9 +3650,9 @@ function CheckoutResult({
|
|
|
3125
3650
|
logo,
|
|
3126
3651
|
className
|
|
3127
3652
|
}) {
|
|
3128
|
-
const client =
|
|
3129
|
-
const { config } =
|
|
3130
|
-
const l10n =
|
|
3653
|
+
const client = _chunkTYNZ2WU7cjs.useClient.call(void 0, );
|
|
3654
|
+
const { config } = _chunkTYNZ2WU7cjs.useAuthConfig.call(void 0, );
|
|
3655
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
3131
3656
|
const [state, setState] = _react.useState.call(void 0, "checking");
|
|
3132
3657
|
const confirmed = _react.useRef.call(void 0, false);
|
|
3133
3658
|
_react.useEffect.call(void 0, () => {
|
|
@@ -3141,7 +3666,7 @@ function CheckoutResult({
|
|
|
3141
3666
|
if (sub && !stopped) {
|
|
3142
3667
|
confirmed.current = true;
|
|
3143
3668
|
setState("confirmed");
|
|
3144
|
-
_optionalChain([onConfirmed, 'optionalCall',
|
|
3669
|
+
_optionalChain([onConfirmed, 'optionalCall', _90 => _90(sub)]);
|
|
3145
3670
|
return;
|
|
3146
3671
|
}
|
|
3147
3672
|
} catch (e3) {
|
|
@@ -3165,7 +3690,7 @@ function CheckoutResult({
|
|
|
3165
3690
|
const shell = (children) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Shell, { appearance, className, children: [
|
|
3166
3691
|
logo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "kerne-masthead", children: logo }) : null,
|
|
3167
3692
|
children,
|
|
3168
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess',
|
|
3693
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, KerneBranding, { show: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _91 => _91.show_kerne_branding]), () => ( false)) })
|
|
3169
3694
|
] });
|
|
3170
3695
|
if (outcome === "cancel") {
|
|
3171
3696
|
return shell(
|
|
@@ -3211,20 +3736,23 @@ function UpgradePrompt({
|
|
|
3211
3736
|
appearance,
|
|
3212
3737
|
className
|
|
3213
3738
|
}) {
|
|
3214
|
-
const { details, allowed, isLoading } =
|
|
3215
|
-
const l10n =
|
|
3739
|
+
const { details, allowed, isLoading } = _chunkTYNZ2WU7cjs.useAccess.call(void 0, featureKey, requested);
|
|
3740
|
+
const l10n = _chunkTYNZ2WU7cjs.useLocalization.call(void 0, );
|
|
3216
3741
|
if (isLoading) {
|
|
3217
3742
|
if (hideWhileLoading) return null;
|
|
3218
3743
|
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 }) });
|
|
3219
3744
|
}
|
|
3220
3745
|
if (allowed) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children });
|
|
3221
3746
|
const name = _nullishCoalesce(featureName, () => ( humanizeFeatureKey(featureKey).toLowerCase()));
|
|
3222
|
-
const quotaExhausted = _optionalChain([details, 'optionalAccess',
|
|
3223
|
-
const heading = _nullishCoalesce(title, () => (
|
|
3224
|
-
const body = _nullishCoalesce(description, () => ( (quotaExhausted ?
|
|
3747
|
+
const quotaExhausted = _optionalChain([details, 'optionalAccess', _92 => _92.feature_type]) === "QUOTA" && typeof details.limit === "number" && typeof details.used === "number";
|
|
3748
|
+
const heading = _nullishCoalesce(title, () => ( _chunkTYNZ2WU7cjs.fill.call(void 0, quotaExhausted ? l10n.upgrade.quotaTitle : l10n.upgrade.featureTitle, { feature: name })));
|
|
3749
|
+
const body = _nullishCoalesce(description, () => ( (quotaExhausted ? _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.upgrade.quotaBody, {
|
|
3225
3750
|
used: formatNumber(details.used),
|
|
3226
|
-
limit
|
|
3227
|
-
|
|
3751
|
+
// `access_limit` is where access actually stops; `limit` is only the
|
|
3752
|
+
// included allocation and can understate it past an overage ceiling.
|
|
3753
|
+
// Falls back to `limit` defensively - should never be needed here.
|
|
3754
|
+
limit: formatNumber(_nullishCoalesce(details.access_limit, () => ( details.limit)))
|
|
3755
|
+
}) : _chunkTYNZ2WU7cjs.fill.call(void 0, l10n.upgrade.featureBody, { feature: name }))));
|
|
3228
3756
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Shell, { appearance, className, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-status", children: [
|
|
3229
3757
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "kerne-heading", children: [
|
|
3230
3758
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "kerne-section-title", style: { fontSize: 17 }, children: heading }),
|
|
@@ -3265,4 +3793,14 @@ function UpgradePrompt({
|
|
|
3265
3793
|
|
|
3266
3794
|
|
|
3267
3795
|
|
|
3268
|
-
|
|
3796
|
+
|
|
3797
|
+
|
|
3798
|
+
|
|
3799
|
+
|
|
3800
|
+
|
|
3801
|
+
|
|
3802
|
+
|
|
3803
|
+
|
|
3804
|
+
|
|
3805
|
+
|
|
3806
|
+
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.PricingTable = PricingTable; 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.collectPriceLabels = collectPriceLabels; exports.defaultLocalization = _chunkTYNZ2WU7cjs.defaultLocalization; exports.formatDate = formatDate; exports.formatInterval = formatInterval; exports.formatMoney = formatMoney; exports.formatNumber = formatNumber; exports.humanizeFeatureKey = humanizeFeatureKey; exports.resolveLabelSavings = resolveLabelSavings; exports.resolvePriceDisplay = resolvePriceDisplay; exports.useLocalization = _chunkTYNZ2WU7cjs.useLocalization; exports.usePricingTable = usePricingTable;
|