@base316/react 0.5.1 → 0.6.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/dist/index.js CHANGED
@@ -642,12 +642,13 @@ function Base316Provider({
642
642
  onTokenChange,
643
643
  appearance: appearance2,
644
644
  tenant,
645
+ organizationId,
645
646
  className,
646
647
  children
647
648
  }) {
648
649
  const client = useMemo(
649
- () => new Base316Browser({ publishableKey, baseUrl }),
650
- [publishableKey, baseUrl]
650
+ () => new Base316Browser({ publishableKey, baseUrl, organizationId: organizationId ?? void 0 }),
651
+ [publishableKey, baseUrl, organizationId]
651
652
  );
652
653
  useEffect(() => {
653
654
  if (document.getElementById(STYLE_ELEMENT_ID)) {
@@ -2037,7 +2038,9 @@ function SignIn({
2037
2038
  if (cause instanceof DOMException && (cause.name === "NotAllowedError" || cause.name === "AbortError")) {
2038
2039
  return;
2039
2040
  }
2040
- if (!conditional) {
2041
+ if (cause instanceof Base316Error2 && cause.reason === "EMAIL_NOT_VERIFIED") {
2042
+ setError(cause.message);
2043
+ } else if (!conditional) {
2041
2044
  console.error("[base316] passkey sign-in failed", cause);
2042
2045
  setError("That passkey did not work.");
2043
2046
  }
@@ -3041,7 +3044,61 @@ function PrivacyControls({
3041
3044
 
3042
3045
  // src/TwoFactorManager.tsx
3043
3046
  import { useState as useState14 } from "react";
3047
+
3048
+ // src/QrCode.tsx
3049
+ import qrcode from "qrcode-generator";
3050
+ import { useMemo as useMemo2 } from "react";
3044
3051
  import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
3052
+ var QUIET_ZONE = 4;
3053
+ function utf8Binary(value) {
3054
+ let binary = "";
3055
+ for (const byte of new TextEncoder().encode(value)) {
3056
+ binary += String.fromCharCode(byte);
3057
+ }
3058
+ return binary;
3059
+ }
3060
+ function qrPath(value) {
3061
+ const code = qrcode(0, "M");
3062
+ code.addData(utf8Binary(value), "Byte");
3063
+ code.make();
3064
+ const modules = code.getModuleCount();
3065
+ let path = "";
3066
+ for (let row = 0; row < modules; row += 1) {
3067
+ for (let col = 0; col < modules; col += 1) {
3068
+ if (code.isDark(row, col)) {
3069
+ path += `M${col + QUIET_ZONE} ${row + QUIET_ZONE}h1v1h-1z`;
3070
+ }
3071
+ }
3072
+ }
3073
+ return { path, modules };
3074
+ }
3075
+ function QrCode({ value, label, size = 180, className }) {
3076
+ const { path, modules } = useMemo2(() => qrPath(value), [value]);
3077
+ const extent = modules + QUIET_ZONE * 2;
3078
+ return /* @__PURE__ */ jsxs15(
3079
+ "svg",
3080
+ {
3081
+ className,
3082
+ role: "img",
3083
+ "aria-label": label,
3084
+ width: size,
3085
+ height: size,
3086
+ viewBox: `0 0 ${extent} ${extent}`,
3087
+ shapeRendering: "crispEdges",
3088
+ xmlns: "http://www.w3.org/2000/svg",
3089
+ children: [
3090
+ /* @__PURE__ */ jsx16("rect", { width: extent, height: extent, fill: "#ffffff" }),
3091
+ /* @__PURE__ */ jsx16("path", { d: path, fill: "#000000" })
3092
+ ]
3093
+ }
3094
+ );
3095
+ }
3096
+
3097
+ // src/TwoFactorManager.tsx
3098
+ import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
3099
+ function groupKey(secret) {
3100
+ return secret.replace(/\s+/g, "").replace(/(.{4})(?=.)/g, "$1 ");
3101
+ }
3045
3102
  function TwoFactorManager({
3046
3103
  enabled = false,
3047
3104
  allowSms = false,
@@ -3134,17 +3191,17 @@ function TwoFactorManager({
3134
3191
  setBusy(false);
3135
3192
  }
3136
3193
  }
3137
- return /* @__PURE__ */ jsxs15("div", { className: cls("b316-card b316-mfa", className), style, children: [
3138
- /* @__PURE__ */ jsx16("h3", { className: "b316-mfa-title", children: "Two-factor authentication" }),
3139
- error ? /* @__PURE__ */ jsx16("div", { className: "b316-error", role: "alert", children: error }) : null,
3140
- stage.name === "saved" ? /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-codes", children: [
3141
- /* @__PURE__ */ jsx16("p", { children: "Save these recovery codes somewhere safe. Each one signs you in once if you lose your authenticator, and they are not shown again." }),
3142
- /* @__PURE__ */ jsx16("ul", { className: "b316-mfa-code-list", children: stage.recoveryCodes.map((recovery) => /* @__PURE__ */ jsx16("li", { children: /* @__PURE__ */ jsx16("code", { children: recovery }) }, recovery)) }),
3143
- /* @__PURE__ */ jsx16("button", { type: "button", className: "b316-button", onClick: () => setStage({ name: "idle" }), children: "I have saved them" })
3144
- ] }) : stage.name === "smsNumber" ? /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-enrol", children: [
3145
- /* @__PURE__ */ jsx16("p", { children: "We will text a code to this number now, and each time you sign in." }),
3146
- /* @__PURE__ */ jsx16("label", { className: "b316-label", htmlFor: "b316-mfa-phone", children: "Mobile number" }),
3147
- /* @__PURE__ */ jsx16(
3194
+ return /* @__PURE__ */ jsxs16("div", { className: cls("b316-card b316-mfa", className), style, children: [
3195
+ /* @__PURE__ */ jsx17("h3", { className: "b316-mfa-title", children: "Two-factor authentication" }),
3196
+ error ? /* @__PURE__ */ jsx17("div", { className: "b316-error", role: "alert", children: error }) : null,
3197
+ stage.name === "saved" ? /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-codes", children: [
3198
+ /* @__PURE__ */ jsx17("p", { children: "Save these recovery codes somewhere safe. Each one signs you in once if you lose your authenticator, and they are not shown again." }),
3199
+ /* @__PURE__ */ jsx17("ul", { className: "b316-mfa-code-list", children: stage.recoveryCodes.map((recovery) => /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsx17("code", { children: recovery }) }, recovery)) }),
3200
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "b316-button", onClick: () => setStage({ name: "idle" }), children: "I have saved them" })
3201
+ ] }) : stage.name === "smsNumber" ? /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-enrol", children: [
3202
+ /* @__PURE__ */ jsx17("p", { children: "We will text a code to this number now, and each time you sign in." }),
3203
+ /* @__PURE__ */ jsx17("label", { className: "b316-label", htmlFor: "b316-mfa-phone", children: "Mobile number" }),
3204
+ /* @__PURE__ */ jsx17(
3148
3205
  "input",
3149
3206
  {
3150
3207
  id: "b316-mfa-phone",
@@ -3156,8 +3213,8 @@ function TwoFactorManager({
3156
3213
  onChange: (event) => setPhone(event.target.value)
3157
3214
  }
3158
3215
  ),
3159
- /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-actions", children: [
3160
- /* @__PURE__ */ jsx16(
3216
+ /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-actions", children: [
3217
+ /* @__PURE__ */ jsx17(
3161
3218
  "button",
3162
3219
  {
3163
3220
  type: "button",
@@ -3166,16 +3223,16 @@ function TwoFactorManager({
3166
3223
  children: "Cancel"
3167
3224
  }
3168
3225
  ),
3169
- /* @__PURE__ */ jsx16("button", { type: "button", className: "b316-button", disabled: busy, onClick: beginSms, children: busy ? "Sending\u2026" : "Send code" })
3226
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "b316-button", disabled: busy, onClick: beginSms, children: busy ? "Sending\u2026" : "Send code" })
3170
3227
  ] })
3171
- ] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-enrol", children: [
3172
- /* @__PURE__ */ jsxs15("p", { children: [
3228
+ ] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-enrol", children: [
3229
+ /* @__PURE__ */ jsxs16("p", { children: [
3173
3230
  "We sent a code to ",
3174
3231
  stage.destinationHint,
3175
3232
  ". Enter it below to turn this on."
3176
3233
  ] }),
3177
- /* @__PURE__ */ jsx16("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
3178
- /* @__PURE__ */ jsx16(
3234
+ /* @__PURE__ */ jsx17("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
3235
+ /* @__PURE__ */ jsx17(
3179
3236
  "input",
3180
3237
  {
3181
3238
  id: "b316-mfa-code",
@@ -3186,8 +3243,8 @@ function TwoFactorManager({
3186
3243
  onChange: (event) => setCode(event.target.value)
3187
3244
  }
3188
3245
  ),
3189
- /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-actions", children: [
3190
- /* @__PURE__ */ jsx16(
3246
+ /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-actions", children: [
3247
+ /* @__PURE__ */ jsx17(
3191
3248
  "button",
3192
3249
  {
3193
3250
  type: "button",
@@ -3196,7 +3253,7 @@ function TwoFactorManager({
3196
3253
  children: "Cancel"
3197
3254
  }
3198
3255
  ),
3199
- /* @__PURE__ */ jsx16(
3256
+ /* @__PURE__ */ jsx17(
3200
3257
  "button",
3201
3258
  {
3202
3259
  type: "button",
@@ -3207,12 +3264,23 @@ function TwoFactorManager({
3207
3264
  }
3208
3265
  )
3209
3266
  ] })
3210
- ] }) : stage.name === "enrolling" ? /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-enrol", children: [
3211
- /* @__PURE__ */ jsx16("p", { children: "Add this to your authenticator app, then enter the six-digit code it shows." }),
3212
- /* @__PURE__ */ jsx16("div", { className: "b316-mfa-secret", children: /* @__PURE__ */ jsx16("code", { children: stage.secret }) }),
3213
- /* @__PURE__ */ jsx16("a", { className: "b316-mfa-uri", href: stage.uri, children: "Open in an authenticator app" }),
3214
- /* @__PURE__ */ jsx16("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
3215
- /* @__PURE__ */ jsx16(
3267
+ ] }) : stage.name === "enrolling" ? /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-enrol", children: [
3268
+ /* @__PURE__ */ jsx17("p", { children: "Scan this with your authenticator app (Google Authenticator, 1Password, Authy\u2026), then enter the six-digit code it shows." }),
3269
+ /* @__PURE__ */ jsx17(
3270
+ QrCode,
3271
+ {
3272
+ className: "b316-mfa-qr",
3273
+ value: stage.uri,
3274
+ label: "QR code for your authenticator app"
3275
+ }
3276
+ ),
3277
+ /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-secret", children: [
3278
+ /* @__PURE__ */ jsx17("span", { className: "b316-label", id: "b316-mfa-manual-key", children: "Can't scan? Enter this key" }),
3279
+ /* @__PURE__ */ jsx17("code", { "aria-labelledby": "b316-mfa-manual-key", children: groupKey(stage.secret) })
3280
+ ] }),
3281
+ /* @__PURE__ */ jsx17("a", { className: "b316-mfa-uri", href: stage.uri, children: "Open in an authenticator app" }),
3282
+ /* @__PURE__ */ jsx17("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
3283
+ /* @__PURE__ */ jsx17(
3216
3284
  "input",
3217
3285
  {
3218
3286
  id: "b316-mfa-code",
@@ -3223,8 +3291,8 @@ function TwoFactorManager({
3223
3291
  onChange: (event) => setCode(event.target.value)
3224
3292
  }
3225
3293
  ),
3226
- /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-actions", children: [
3227
- /* @__PURE__ */ jsx16(
3294
+ /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-actions", children: [
3295
+ /* @__PURE__ */ jsx17(
3228
3296
  "button",
3229
3297
  {
3230
3298
  type: "button",
@@ -3233,7 +3301,7 @@ function TwoFactorManager({
3233
3301
  children: "Cancel"
3234
3302
  }
3235
3303
  ),
3236
- /* @__PURE__ */ jsx16(
3304
+ /* @__PURE__ */ jsx17(
3237
3305
  "button",
3238
3306
  {
3239
3307
  type: "button",
@@ -3244,9 +3312,9 @@ function TwoFactorManager({
3244
3312
  }
3245
3313
  )
3246
3314
  ] })
3247
- ] }) : on ? /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-on", children: [
3248
- /* @__PURE__ */ jsx16("p", { className: "b316-muted", children: "On. You will be asked for a code when you sign in." }),
3249
- /* @__PURE__ */ jsx16(
3315
+ ] }) : on ? /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-on", children: [
3316
+ /* @__PURE__ */ jsx17("p", { className: "b316-muted", children: "On. You will be asked for a code when you sign in." }),
3317
+ /* @__PURE__ */ jsx17(
3250
3318
  ConfirmButton,
3251
3319
  {
3252
3320
  className: "b316-button-quiet b316-danger",
@@ -3256,11 +3324,11 @@ function TwoFactorManager({
3256
3324
  children: "Turn off"
3257
3325
  }
3258
3326
  )
3259
- ] }) : /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-off", children: [
3260
- /* @__PURE__ */ jsx16("p", { className: "b316-muted", children: "Off. Turning it on means a code as well as your password, every time you sign in." }),
3261
- /* @__PURE__ */ jsxs15("div", { className: "b316-mfa-actions", children: [
3262
- /* @__PURE__ */ jsx16("button", { type: "button", className: "b316-button", disabled: busy, onClick: begin, children: busy ? "Starting\u2026" : "Use an authenticator app" }),
3263
- /* @__PURE__ */ jsx16(
3327
+ ] }) : /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-off", children: [
3328
+ /* @__PURE__ */ jsx17("p", { className: "b316-muted", children: "Off. Turning it on means a code as well as your password, every time you sign in." }),
3329
+ /* @__PURE__ */ jsxs16("div", { className: "b316-mfa-actions", children: [
3330
+ /* @__PURE__ */ jsx17("button", { type: "button", className: "b316-button", disabled: busy, onClick: begin, children: busy ? "Starting\u2026" : "Use an authenticator app" }),
3331
+ /* @__PURE__ */ jsx17(
3264
3332
  "button",
3265
3333
  {
3266
3334
  type: "button",
@@ -3270,7 +3338,7 @@ function TwoFactorManager({
3270
3338
  children: "Email me a code"
3271
3339
  }
3272
3340
  ),
3273
- allowSms ? /* @__PURE__ */ jsx16(
3341
+ allowSms ? /* @__PURE__ */ jsx17(
3274
3342
  "button",
3275
3343
  {
3276
3344
  type: "button",
@@ -3287,7 +3355,7 @@ function TwoFactorManager({
3287
3355
 
3288
3356
  // src/ForgotPassword.tsx
3289
3357
  import { useState as useState15 } from "react";
3290
- import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
3358
+ import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
3291
3359
  function ForgotPassword({ onSent, signInUrl, className, style }) {
3292
3360
  const { client } = useBase316();
3293
3361
  const [email, setEmail] = useState15("");
@@ -3309,22 +3377,22 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
3309
3377
  }
3310
3378
  }
3311
3379
  if (sent) {
3312
- return /* @__PURE__ */ jsxs16("div", { className: cls("b316-card", className), style, children: [
3313
- /* @__PURE__ */ jsx17("h3", { className: "b316-form-title", children: "Check your email" }),
3314
- /* @__PURE__ */ jsxs16("p", { className: "b316-muted", children: [
3380
+ return /* @__PURE__ */ jsxs17("div", { className: cls("b316-card", className), style, children: [
3381
+ /* @__PURE__ */ jsx18("h3", { className: "b316-form-title", children: "Check your email" }),
3382
+ /* @__PURE__ */ jsxs17("p", { className: "b316-muted", children: [
3315
3383
  "If there is an account for ",
3316
3384
  email.trim(),
3317
3385
  ", a link to set a new password is on its way."
3318
3386
  ] }),
3319
- signInUrl ? /* @__PURE__ */ jsx17("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
3387
+ signInUrl ? /* @__PURE__ */ jsx18("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
3320
3388
  ] });
3321
3389
  }
3322
- return /* @__PURE__ */ jsxs16("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
3323
- /* @__PURE__ */ jsx17("h3", { className: "b316-form-title", children: "Reset your password" }),
3324
- error ? /* @__PURE__ */ jsx17("div", { className: "b316-error", role: "alert", children: error }) : null,
3325
- /* @__PURE__ */ jsxs16("div", { className: "b316-field", children: [
3326
- /* @__PURE__ */ jsx17("label", { className: "b316-label", htmlFor: "b316-forgot-email", children: "Email" }),
3327
- /* @__PURE__ */ jsx17(
3390
+ return /* @__PURE__ */ jsxs17("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
3391
+ /* @__PURE__ */ jsx18("h3", { className: "b316-form-title", children: "Reset your password" }),
3392
+ error ? /* @__PURE__ */ jsx18("div", { className: "b316-error", role: "alert", children: error }) : null,
3393
+ /* @__PURE__ */ jsxs17("div", { className: "b316-field", children: [
3394
+ /* @__PURE__ */ jsx18("label", { className: "b316-label", htmlFor: "b316-forgot-email", children: "Email" }),
3395
+ /* @__PURE__ */ jsx18(
3328
3396
  "input",
3329
3397
  {
3330
3398
  id: "b316-forgot-email",
@@ -3337,14 +3405,14 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
3337
3405
  }
3338
3406
  )
3339
3407
  ] }),
3340
- /* @__PURE__ */ jsx17("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Send reset link" }),
3341
- signInUrl ? /* @__PURE__ */ jsx17("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
3408
+ /* @__PURE__ */ jsx18("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Send reset link" }),
3409
+ signInUrl ? /* @__PURE__ */ jsx18("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
3342
3410
  ] });
3343
3411
  }
3344
3412
 
3345
3413
  // src/ResetPassword.tsx
3346
3414
  import { useEffect as useEffect12, useState as useState16 } from "react";
3347
- import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
3415
+ import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
3348
3416
  function ResetPassword({
3349
3417
  token: supplied,
3350
3418
  onReset,
@@ -3394,24 +3462,24 @@ function ResetPassword({
3394
3462
  }
3395
3463
  }
3396
3464
  if (done) {
3397
- return /* @__PURE__ */ jsxs17("div", { className: cls("b316-card", className), style, children: [
3398
- /* @__PURE__ */ jsx18("h3", { className: "b316-form-title", children: "Password changed" }),
3399
- /* @__PURE__ */ jsx18("p", { className: "b316-muted", children: "You can sign in with your new password." }),
3400
- signInUrl ? /* @__PURE__ */ jsx18("a", { className: "b316-button-link", href: signInUrl, children: "Sign in" }) : null
3465
+ return /* @__PURE__ */ jsxs18("div", { className: cls("b316-card", className), style, children: [
3466
+ /* @__PURE__ */ jsx19("h3", { className: "b316-form-title", children: "Password changed" }),
3467
+ /* @__PURE__ */ jsx19("p", { className: "b316-muted", children: "You can sign in with your new password." }),
3468
+ signInUrl ? /* @__PURE__ */ jsx19("a", { className: "b316-button-link", href: signInUrl, children: "Sign in" }) : null
3401
3469
  ] });
3402
3470
  }
3403
3471
  if (!token) {
3404
- return /* @__PURE__ */ jsxs17("div", { className: cls("b316-card", className), style, children: [
3405
- /* @__PURE__ */ jsx18("h3", { className: "b316-form-title", children: "Nothing to reset" }),
3406
- /* @__PURE__ */ jsx18("p", { className: "b316-muted", children: "This page needs the link from your email. Request a new one if yours has expired." })
3472
+ return /* @__PURE__ */ jsxs18("div", { className: cls("b316-card", className), style, children: [
3473
+ /* @__PURE__ */ jsx19("h3", { className: "b316-form-title", children: "Nothing to reset" }),
3474
+ /* @__PURE__ */ jsx19("p", { className: "b316-muted", children: "This page needs the link from your email. Request a new one if yours has expired." })
3407
3475
  ] });
3408
3476
  }
3409
- return /* @__PURE__ */ jsxs17("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
3410
- /* @__PURE__ */ jsx18("h3", { className: "b316-form-title", children: "Choose a new password" }),
3411
- error ? /* @__PURE__ */ jsx18("div", { className: "b316-error", role: "alert", children: error }) : null,
3412
- /* @__PURE__ */ jsxs17("div", { className: "b316-field", children: [
3413
- /* @__PURE__ */ jsx18("label", { className: "b316-label", htmlFor: "b316-reset-password", children: "New password" }),
3414
- /* @__PURE__ */ jsx18(
3477
+ return /* @__PURE__ */ jsxs18("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
3478
+ /* @__PURE__ */ jsx19("h3", { className: "b316-form-title", children: "Choose a new password" }),
3479
+ error ? /* @__PURE__ */ jsx19("div", { className: "b316-error", role: "alert", children: error }) : null,
3480
+ /* @__PURE__ */ jsxs18("div", { className: "b316-field", children: [
3481
+ /* @__PURE__ */ jsx19("label", { className: "b316-label", htmlFor: "b316-reset-password", children: "New password" }),
3482
+ /* @__PURE__ */ jsx19(
3415
3483
  "input",
3416
3484
  {
3417
3485
  id: "b316-reset-password",
@@ -3424,9 +3492,9 @@ function ResetPassword({
3424
3492
  }
3425
3493
  )
3426
3494
  ] }),
3427
- /* @__PURE__ */ jsxs17("div", { className: "b316-field", children: [
3428
- /* @__PURE__ */ jsx18("label", { className: "b316-label", htmlFor: "b316-reset-confirm", children: "Repeat it" }),
3429
- /* @__PURE__ */ jsx18(
3495
+ /* @__PURE__ */ jsxs18("div", { className: "b316-field", children: [
3496
+ /* @__PURE__ */ jsx19("label", { className: "b316-label", htmlFor: "b316-reset-confirm", children: "Repeat it" }),
3497
+ /* @__PURE__ */ jsx19(
3430
3498
  "input",
3431
3499
  {
3432
3500
  id: "b316-reset-confirm",
@@ -3439,13 +3507,13 @@ function ResetPassword({
3439
3507
  }
3440
3508
  )
3441
3509
  ] }),
3442
- /* @__PURE__ */ jsx18("button", { type: "submit", className: "b316-button", disabled: busy || !password, children: busy ? "Saving\u2026" : "Set password" })
3510
+ /* @__PURE__ */ jsx19("button", { type: "submit", className: "b316-button", disabled: busy || !password, children: busy ? "Saving\u2026" : "Set password" })
3443
3511
  ] });
3444
3512
  }
3445
3513
 
3446
3514
  // src/VerifyEmail.tsx
3447
3515
  import { useEffect as useEffect13, useRef as useRef4, useState as useState17 } from "react";
3448
- import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
3516
+ import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
3449
3517
  function VerifyEmail({
3450
3518
  token: supplied,
3451
3519
  onVerified,
@@ -3482,22 +3550,22 @@ function VerifyEmail({
3482
3550
  setState("failed");
3483
3551
  });
3484
3552
  }, [client, supplied, onVerified]);
3485
- return /* @__PURE__ */ jsx19("div", { className: cls("b316-card", className), style, children: state === "verified" ? /* @__PURE__ */ jsxs18(Fragment5, { children: [
3486
- /* @__PURE__ */ jsx19("h3", { className: "b316-form-title", children: "Email confirmed" }),
3487
- /* @__PURE__ */ jsx19("p", { className: "b316-muted", children: "Thanks \u2014 your address is verified." }),
3488
- continueUrl ? /* @__PURE__ */ jsx19("a", { className: "b316-button-link", href: continueUrl, children: "Continue" }) : null
3489
- ] }) : state === "failed" ? /* @__PURE__ */ jsxs18(Fragment5, { children: [
3490
- /* @__PURE__ */ jsx19("h3", { className: "b316-form-title", children: "That link did not work" }),
3491
- /* @__PURE__ */ jsx19("p", { className: "b316-muted", children: "It may have expired or already been used. Ask for a new one and try again." })
3492
- ] }) : state === "missing" ? /* @__PURE__ */ jsxs18(Fragment5, { children: [
3493
- /* @__PURE__ */ jsx19("h3", { className: "b316-form-title", children: "Nothing to confirm" }),
3494
- /* @__PURE__ */ jsx19("p", { className: "b316-muted", children: "This page needs the link from your email." })
3495
- ] }) : /* @__PURE__ */ jsx19("p", { className: "b316-muted", children: "Confirming your email\u2026" }) });
3553
+ return /* @__PURE__ */ jsx20("div", { className: cls("b316-card", className), style, children: state === "verified" ? /* @__PURE__ */ jsxs19(Fragment5, { children: [
3554
+ /* @__PURE__ */ jsx20("h3", { className: "b316-form-title", children: "Email confirmed" }),
3555
+ /* @__PURE__ */ jsx20("p", { className: "b316-muted", children: "Thanks \u2014 your address is verified." }),
3556
+ continueUrl ? /* @__PURE__ */ jsx20("a", { className: "b316-button-link", href: continueUrl, children: "Continue" }) : null
3557
+ ] }) : state === "failed" ? /* @__PURE__ */ jsxs19(Fragment5, { children: [
3558
+ /* @__PURE__ */ jsx20("h3", { className: "b316-form-title", children: "That link did not work" }),
3559
+ /* @__PURE__ */ jsx20("p", { className: "b316-muted", children: "It may have expired or already been used. Ask for a new one and try again." })
3560
+ ] }) : state === "missing" ? /* @__PURE__ */ jsxs19(Fragment5, { children: [
3561
+ /* @__PURE__ */ jsx20("h3", { className: "b316-form-title", children: "Nothing to confirm" }),
3562
+ /* @__PURE__ */ jsx20("p", { className: "b316-muted", children: "This page needs the link from your email." })
3563
+ ] }) : /* @__PURE__ */ jsx20("p", { className: "b316-muted", children: "Confirming your email\u2026" }) });
3496
3564
  }
3497
3565
 
3498
3566
  // src/TeamMembers.tsx
3499
3567
  import { useCallback as useCallback7, useEffect as useEffect14, useState as useState18 } from "react";
3500
- import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
3568
+ import { Fragment as Fragment6, jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
3501
3569
  function TeamMembers({
3502
3570
  organizationId,
3503
3571
  onInvited,
@@ -3556,10 +3624,10 @@ function TeamMembers({
3556
3624
  return null;
3557
3625
  }
3558
3626
  if (!teams) {
3559
- return /* @__PURE__ */ jsx20("div", { className: cls("b316-card", className), style, children: error ?? "Loading\u2026" });
3627
+ return /* @__PURE__ */ jsx21("div", { className: cls("b316-card", className), style, children: error ?? "Loading\u2026" });
3560
3628
  }
3561
3629
  if (!chosen) {
3562
- return /* @__PURE__ */ jsx20("div", { className: cls("b316-card", className), style, children: teams.length === 0 ? "You are not in a team yet." : "You are in more than one team. Name which with the organizationId prop." });
3630
+ return /* @__PURE__ */ jsx21("div", { className: cls("b316-card", className), style, children: teams.length === 0 ? "You are not in a team yet." : "You are in more than one team. Name which with the organizationId prop." });
3563
3631
  }
3564
3632
  const canManage = invitations !== null;
3565
3633
  async function invite(event) {
@@ -3609,30 +3677,30 @@ function TeamMembers({
3609
3677
  setError(cause instanceof Error ? cause.message : "That invitation could not be withdrawn.");
3610
3678
  }
3611
3679
  }
3612
- return /* @__PURE__ */ jsxs19("div", { className: cls("b316-card b316-team", className), style, children: [
3613
- /* @__PURE__ */ jsx20("h3", { className: "b316-team-title", children: team?.name ?? "Team" }),
3680
+ return /* @__PURE__ */ jsxs20("div", { className: cls("b316-card b316-team", className), style, children: [
3681
+ /* @__PURE__ */ jsx21("h3", { className: "b316-team-title", children: team?.name ?? "Team" }),
3614
3682
  team?.inherited ? (
3615
3683
  // Not a member of this team, so not in the list below and with nothing
3616
3684
  // to leave: access comes from the team that manages it, and ends there.
3617
- /* @__PURE__ */ jsxs19("div", { className: "b316-muted", children: [
3685
+ /* @__PURE__ */ jsxs20("div", { className: "b316-muted", children: [
3618
3686
  "You have access through",
3619
3687
  " ",
3620
3688
  teams.find((candidate) => candidate.id === team.via)?.name ?? "the organization that manages this team",
3621
3689
  "."
3622
3690
  ] })
3623
3691
  ) : null,
3624
- error ? /* @__PURE__ */ jsx20("div", { className: "b316-error", role: "alert", children: error }) : null,
3625
- /* @__PURE__ */ jsx20("ul", { className: "b316-team-list", children: (members ?? []).map((member) => /* @__PURE__ */ jsxs19("li", { className: "b316-team-member", children: [
3626
- /* @__PURE__ */ jsxs19("div", { children: [
3627
- /* @__PURE__ */ jsx20("div", { children: member.user.name ?? member.user.email ?? "Someone" }),
3628
- /* @__PURE__ */ jsxs19("div", { className: "b316-muted", children: [
3692
+ error ? /* @__PURE__ */ jsx21("div", { className: "b316-error", role: "alert", children: error }) : null,
3693
+ /* @__PURE__ */ jsx21("ul", { className: "b316-team-list", children: (members ?? []).map((member) => /* @__PURE__ */ jsxs20("li", { className: "b316-team-member", children: [
3694
+ /* @__PURE__ */ jsxs20("div", { children: [
3695
+ /* @__PURE__ */ jsx21("div", { children: member.user.name ?? member.user.email ?? "Someone" }),
3696
+ /* @__PURE__ */ jsxs20("div", { className: "b316-muted", children: [
3629
3697
  member.user.email,
3630
3698
  member.user.id === session?.userId ? " \xB7 you" : ""
3631
3699
  ] })
3632
3700
  ] }),
3633
- /* @__PURE__ */ jsxs19("div", { className: "b316-team-member-side", children: [
3634
- /* @__PURE__ */ jsx20("span", { className: "b316-chip", children: member.role.name }),
3635
- canManage || member.user.id === session?.userId ? /* @__PURE__ */ jsx20(
3701
+ /* @__PURE__ */ jsxs20("div", { className: "b316-team-member-side", children: [
3702
+ /* @__PURE__ */ jsx21("span", { className: "b316-chip", children: member.role.name }),
3703
+ canManage || member.user.id === session?.userId ? /* @__PURE__ */ jsx21(
3636
3704
  ConfirmButton,
3637
3705
  {
3638
3706
  className: "b316-button-quiet b316-danger",
@@ -3644,19 +3712,19 @@ function TeamMembers({
3644
3712
  ) : null
3645
3713
  ] })
3646
3714
  ] }, member.id)) }),
3647
- canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */ jsxs19(Fragment6, { children: [
3648
- /* @__PURE__ */ jsx20("h4", { className: "b316-team-subtitle", children: "Invited" }),
3649
- /* @__PURE__ */ jsx20("ul", { className: "b316-team-list", children: (invitations ?? []).map((invitation) => /* @__PURE__ */ jsxs19("li", { className: "b316-team-member", children: [
3650
- /* @__PURE__ */ jsxs19("div", { children: [
3651
- /* @__PURE__ */ jsx20("div", { children: invitation.email }),
3652
- /* @__PURE__ */ jsxs19("div", { className: "b316-muted", children: [
3715
+ canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */ jsxs20(Fragment6, { children: [
3716
+ /* @__PURE__ */ jsx21("h4", { className: "b316-team-subtitle", children: "Invited" }),
3717
+ /* @__PURE__ */ jsx21("ul", { className: "b316-team-list", children: (invitations ?? []).map((invitation) => /* @__PURE__ */ jsxs20("li", { className: "b316-team-member", children: [
3718
+ /* @__PURE__ */ jsxs20("div", { children: [
3719
+ /* @__PURE__ */ jsx21("div", { children: invitation.email }),
3720
+ /* @__PURE__ */ jsxs20("div", { className: "b316-muted", children: [
3653
3721
  invitation.role.name,
3654
3722
  " \xB7 expires",
3655
3723
  " ",
3656
3724
  new Date(invitation.expiresAt).toLocaleDateString()
3657
3725
  ] })
3658
3726
  ] }),
3659
- /* @__PURE__ */ jsx20(
3727
+ /* @__PURE__ */ jsx21(
3660
3728
  "button",
3661
3729
  {
3662
3730
  type: "button",
@@ -3667,10 +3735,10 @@ function TeamMembers({
3667
3735
  )
3668
3736
  ] }, invitation.id)) })
3669
3737
  ] }) : null,
3670
- canManage ? /* @__PURE__ */ jsxs19("form", { className: "b316-team-invite", onSubmit: invite, children: [
3671
- /* @__PURE__ */ jsx20("label", { className: "b316-label", htmlFor: "b316-invite-email", children: "Invite by email" }),
3672
- /* @__PURE__ */ jsxs19("div", { className: "b316-team-invite-row", children: [
3673
- /* @__PURE__ */ jsx20(
3738
+ canManage ? /* @__PURE__ */ jsxs20("form", { className: "b316-team-invite", onSubmit: invite, children: [
3739
+ /* @__PURE__ */ jsx21("label", { className: "b316-label", htmlFor: "b316-invite-email", children: "Invite by email" }),
3740
+ /* @__PURE__ */ jsxs20("div", { className: "b316-team-invite-row", children: [
3741
+ /* @__PURE__ */ jsx21(
3674
3742
  "input",
3675
3743
  {
3676
3744
  id: "b316-invite-email",
@@ -3682,19 +3750,19 @@ function TeamMembers({
3682
3750
  onChange: (event) => setEmail(event.target.value)
3683
3751
  }
3684
3752
  ),
3685
- /* @__PURE__ */ jsx20("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Invite" })
3753
+ /* @__PURE__ */ jsx21("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Invite" })
3686
3754
  ] })
3687
3755
  ] }) : null,
3688
- copied ? /* @__PURE__ */ jsxs19("div", { className: "b316-team-link", children: [
3689
- /* @__PURE__ */ jsx20("div", { className: "b316-muted", children: "Send them this link. It is shown once and cannot be fetched again." }),
3690
- /* @__PURE__ */ jsx20("code", { children: copied })
3756
+ copied ? /* @__PURE__ */ jsxs20("div", { className: "b316-team-link", children: [
3757
+ /* @__PURE__ */ jsx21("div", { className: "b316-muted", children: "Send them this link. It is shown once and cannot be fetched again." }),
3758
+ /* @__PURE__ */ jsx21("code", { children: copied })
3691
3759
  ] }) : null
3692
3760
  ] });
3693
3761
  }
3694
3762
 
3695
3763
  // src/AcceptInvitation.tsx
3696
3764
  import { useEffect as useEffect15, useState as useState19 } from "react";
3697
- import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
3765
+ import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
3698
3766
  function signUpUrlWithInvitation(url, token) {
3699
3767
  const [beforeHash, ...hash] = url.split("#");
3700
3768
  const base = beforeHash ?? "";
@@ -3761,42 +3829,42 @@ function AcceptInvitation({
3761
3829
  }
3762
3830
  }
3763
3831
  if (state === "loading") {
3764
- return /* @__PURE__ */ jsx21("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
3832
+ return /* @__PURE__ */ jsx22("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
3765
3833
  }
3766
3834
  if (state === "invalid") {
3767
- return /* @__PURE__ */ jsxs20("div", { className: cls("b316-card", className), style, children: [
3768
- /* @__PURE__ */ jsx21("h3", { className: "b316-form-title", children: "That invitation is no longer valid" }),
3769
- /* @__PURE__ */ jsx21("p", { className: "b316-muted", children: "It may have expired, been withdrawn, or already been used. Ask for a new one." })
3835
+ return /* @__PURE__ */ jsxs21("div", { className: cls("b316-card", className), style, children: [
3836
+ /* @__PURE__ */ jsx22("h3", { className: "b316-form-title", children: "That invitation is no longer valid" }),
3837
+ /* @__PURE__ */ jsx22("p", { className: "b316-muted", children: "It may have expired, been withdrawn, or already been used. Ask for a new one." })
3770
3838
  ] });
3771
3839
  }
3772
3840
  if (state === "accepted") {
3773
- return /* @__PURE__ */ jsx21("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsxs20("h3", { className: "b316-form-title", children: [
3841
+ return /* @__PURE__ */ jsx22("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsxs21("h3", { className: "b316-form-title", children: [
3774
3842
  "You have joined ",
3775
3843
  preview?.organizationName
3776
3844
  ] }) });
3777
3845
  }
3778
3846
  const matches = !user || (user.user.email ?? "").toLowerCase() === preview?.email.toLowerCase();
3779
- return /* @__PURE__ */ jsxs20("div", { className: cls("b316-card b316-invitation", className), style, children: [
3780
- /* @__PURE__ */ jsxs20("h3", { className: "b316-form-title", children: [
3847
+ return /* @__PURE__ */ jsxs21("div", { className: cls("b316-card b316-invitation", className), style, children: [
3848
+ /* @__PURE__ */ jsxs21("h3", { className: "b316-form-title", children: [
3781
3849
  "Join ",
3782
3850
  preview?.organizationName
3783
3851
  ] }),
3784
- /* @__PURE__ */ jsxs20("p", { className: "b316-muted", children: [
3852
+ /* @__PURE__ */ jsxs21("p", { className: "b316-muted", children: [
3785
3853
  "Invited as ",
3786
3854
  preview?.email,
3787
3855
  " \xB7 ",
3788
3856
  preview?.roleName
3789
3857
  ] }),
3790
- error ? /* @__PURE__ */ jsx21("div", { className: "b316-error", role: "alert", children: error }) : null,
3791
- !session ? /* @__PURE__ */ jsxs20(Fragment7, { children: [
3792
- /* @__PURE__ */ jsxs20("p", { children: [
3858
+ error ? /* @__PURE__ */ jsx22("div", { className: "b316-error", role: "alert", children: error }) : null,
3859
+ !session ? /* @__PURE__ */ jsxs21(Fragment7, { children: [
3860
+ /* @__PURE__ */ jsxs21("p", { children: [
3793
3861
  "Sign in as ",
3794
3862
  preview?.email,
3795
3863
  " to accept."
3796
3864
  ] }),
3797
- /* @__PURE__ */ jsxs20("div", { className: "b316-invitation-actions", children: [
3798
- signInUrl ? /* @__PURE__ */ jsx21("a", { className: "b316-button", href: signInUrl, children: "Sign in" }) : null,
3799
- signUpUrl ? /* @__PURE__ */ jsx21(
3865
+ /* @__PURE__ */ jsxs21("div", { className: "b316-invitation-actions", children: [
3866
+ signInUrl ? /* @__PURE__ */ jsx22("a", { className: "b316-button", href: signInUrl, children: "Sign in" }) : null,
3867
+ signUpUrl ? /* @__PURE__ */ jsx22(
3800
3868
  "a",
3801
3869
  {
3802
3870
  className: "b316-button-link",
@@ -3809,20 +3877,20 @@ function AcceptInvitation({
3809
3877
  // Said before they press anything. The server refuses this, but
3810
3878
  // finding out after a click reads as a broken invitation rather than
3811
3879
  // as being signed in as the wrong person.
3812
- /* @__PURE__ */ jsxs20("p", { children: [
3880
+ /* @__PURE__ */ jsxs21("p", { children: [
3813
3881
  "You are signed in as ",
3814
3882
  user?.user.email,
3815
3883
  ". This invitation was sent to ",
3816
3884
  preview?.email,
3817
3885
  " \u2014 sign in as that address to accept it."
3818
3886
  ] })
3819
- ) : /* @__PURE__ */ jsx21("button", { type: "button", className: "b316-button", disabled: busy, onClick: accept, children: busy ? "Joining\u2026" : `Join ${preview?.organizationName}` })
3887
+ ) : /* @__PURE__ */ jsx22("button", { type: "button", className: "b316-button", disabled: busy, onClick: accept, children: busy ? "Joining\u2026" : `Join ${preview?.organizationName}` })
3820
3888
  ] });
3821
3889
  }
3822
3890
 
3823
3891
  // src/PayInvoice.tsx
3824
3892
  import { useEffect as useEffect16, useRef as useRef5, useState as useState20 } from "react";
3825
- import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
3893
+ import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
3826
3894
  var STRIPE_SRC = "https://js.stripe.com/v3/";
3827
3895
  function loadStripeScript() {
3828
3896
  if (typeof window === "undefined") {
@@ -3914,12 +3982,12 @@ function PayInvoice({
3914
3982
  onPaid?.();
3915
3983
  };
3916
3984
  if (done) {
3917
- return /* @__PURE__ */ jsx22("div", { className: cls("b316-pay", className), style, children: /* @__PURE__ */ jsx22("p", { className: "b316-pay__done", children: "Paid \u2014 thank you." }) });
3985
+ return /* @__PURE__ */ jsx23("div", { className: cls("b316-pay", className), style, children: /* @__PURE__ */ jsx23("p", { className: "b316-pay__done", children: "Paid \u2014 thank you." }) });
3918
3986
  }
3919
- return /* @__PURE__ */ jsxs21("form", { className: cls("b316-pay", className), style, onSubmit: submit, children: [
3920
- error ? /* @__PURE__ */ jsx22("p", { className: "b316-pay__error", role: "alert", children: error }) : null,
3921
- /* @__PURE__ */ jsx22("div", { ref: mountRef, className: "b316-pay__element" }),
3922
- /* @__PURE__ */ jsx22("button", { className: "b316-pay__submit", type: "submit", disabled: !ready || paying, children: paying ? "Paying\u2026" : "Pay" })
3987
+ return /* @__PURE__ */ jsxs22("form", { className: cls("b316-pay", className), style, onSubmit: submit, children: [
3988
+ error ? /* @__PURE__ */ jsx23("p", { className: "b316-pay__error", role: "alert", children: error }) : null,
3989
+ /* @__PURE__ */ jsx23("div", { ref: mountRef, className: "b316-pay__element" }),
3990
+ /* @__PURE__ */ jsx23("button", { className: "b316-pay__submit", type: "submit", disabled: !ready || paying, children: paying ? "Paying\u2026" : "Pay" })
3923
3991
  ] });
3924
3992
  }
3925
3993
 
@@ -4105,7 +4173,7 @@ function usePlans(options = {}) {
4105
4173
  }
4106
4174
 
4107
4175
  // src/PricingTable.tsx
4108
- import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
4176
+ import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
4109
4177
  function formatAmount(amount, currency) {
4110
4178
  if (amount === null) return "Free";
4111
4179
  const value = Number(amount);
@@ -4171,50 +4239,50 @@ function PricingTable({
4171
4239
  }
4172
4240
  }
4173
4241
  if (error) {
4174
- return /* @__PURE__ */ jsx23("div", { className: cls("b316-card", className), style, children: "Plans are unavailable right now." });
4242
+ return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: "Plans are unavailable right now." });
4175
4243
  }
4176
4244
  if (!plans) {
4177
- return /* @__PURE__ */ jsx23("div", { className: cls("b316-card", className), style, children: "Loading plans\u2026" });
4245
+ return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: "Loading plans\u2026" });
4178
4246
  }
4179
4247
  if (plans.length === 0) {
4180
- return /* @__PURE__ */ jsx23("div", { className: cls("b316-card", className), style, children: "No plans are published yet." });
4248
+ return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: "No plans are published yet." });
4181
4249
  }
4182
4250
  const anyTrial = plans.some((plan) => Boolean(plan.trialDays));
4183
4251
  const anyDescription = plans.some((plan) => Boolean(plan.description));
4184
4252
  const anyFeatured = plans.some((plan) => plan.key === featuredPlanKey);
4185
- return /* @__PURE__ */ jsxs22("div", { className: cls("b316-plans", className), style, children: [
4253
+ return /* @__PURE__ */ jsxs23("div", { className: cls("b316-plans", className), style, children: [
4186
4254
  managedBy ? (
4187
4255
  // A client company's plan comes from the firm that runs it. The table
4188
4256
  // still shows what is on offer, with the current plan marked, but
4189
4257
  // nothing here can be bought: it would grant this account nothing.
4190
- /* @__PURE__ */ jsxs22("div", { className: "b316-plans-managed b316-muted", children: [
4258
+ /* @__PURE__ */ jsxs23("div", { className: "b316-plans-managed b316-muted", children: [
4191
4259
  "Your plan is provided by ",
4192
4260
  managedBy.name ?? "the organization that manages your account",
4193
4261
  ". Ask them to change it."
4194
4262
  ] })
4195
- ) : lastError ? /* @__PURE__ */ jsx23("div", { className: "b316-plans-error", role: "alert", children: lastError }) : scheduled ? /* @__PURE__ */ jsx23("div", { className: "b316-plans-managed b316-muted", role: "status", children: scheduled }) : null,
4263
+ ) : lastError ? /* @__PURE__ */ jsx24("div", { className: "b316-plans-error", role: "alert", children: lastError }) : scheduled ? /* @__PURE__ */ jsx24("div", { className: "b316-plans-managed b316-muted", role: "status", children: scheduled }) : null,
4196
4264
  plans.map((plan) => {
4197
4265
  const base = plan.prices.find((price) => price.featureId === null) ?? plan.prices[0];
4198
4266
  const isCurrent = current === plan.planVersionId;
4199
4267
  const featured = featuredPlanKey === plan.key;
4200
- return /* @__PURE__ */ jsxs22(
4268
+ return /* @__PURE__ */ jsxs23(
4201
4269
  "div",
4202
4270
  {
4203
4271
  className: featured ? "b316-card b316-plan b316-plan-featured" : "b316-card b316-plan",
4204
4272
  children: [
4205
- /* @__PURE__ */ jsxs22("div", { className: "b316-plan-head", children: [
4206
- anyFeatured ? /* @__PURE__ */ jsx23("div", { className: featured ? "b316-plan-badge" : "b316-plan-badge-spacer", children: featured ? "Recommended" : "\xA0" }) : null,
4207
- /* @__PURE__ */ jsx23("div", { className: "b316-plan-name", children: plan.name }),
4208
- anyDescription ? /* @__PURE__ */ jsx23("div", { className: "b316-plan-desc", children: plan.description ?? "\xA0" }) : null
4273
+ /* @__PURE__ */ jsxs23("div", { className: "b316-plan-head", children: [
4274
+ anyFeatured ? /* @__PURE__ */ jsx24("div", { className: featured ? "b316-plan-badge" : "b316-plan-badge-spacer", children: featured ? "Recommended" : "\xA0" }) : null,
4275
+ /* @__PURE__ */ jsx24("div", { className: "b316-plan-name", children: plan.name }),
4276
+ anyDescription ? /* @__PURE__ */ jsx24("div", { className: "b316-plan-desc", children: plan.description ?? "\xA0" }) : null
4209
4277
  ] }),
4210
- /* @__PURE__ */ jsxs22("div", { className: "b316-plan-pricing", children: [
4211
- /* @__PURE__ */ jsx23("div", { className: "b316-plan-price", children: formatAmount(base?.amount ?? null, plan.currency) }),
4212
- /* @__PURE__ */ jsx23("div", { className: "b316-plan-cadence", children: cadence(plan, base?.amount ?? null) }),
4213
- anyTrial ? /* @__PURE__ */ jsx23("div", { className: "b316-plan-trial", children: describeTrial(plan, plans) ?? "\xA0" }) : null
4278
+ /* @__PURE__ */ jsxs23("div", { className: "b316-plan-pricing", children: [
4279
+ /* @__PURE__ */ jsx24("div", { className: "b316-plan-price", children: formatAmount(base?.amount ?? null, plan.currency) }),
4280
+ /* @__PURE__ */ jsx24("div", { className: "b316-plan-cadence", children: cadence(plan, base?.amount ?? null) }),
4281
+ anyTrial ? /* @__PURE__ */ jsx24("div", { className: "b316-plan-trial", children: describeTrial(plan, plans) ?? "\xA0" }) : null
4214
4282
  ] }),
4215
- /* @__PURE__ */ jsx23("ul", { className: "b316-plan-features", children: plan.entitlements.filter((entitlement) => entitlement.enabled).map((entitlement) => /* @__PURE__ */ jsxs22("li", { className: "b316-plan-feature", children: [
4216
- /* @__PURE__ */ jsx23("span", { children: entitlement.featureName }),
4217
- /* @__PURE__ */ jsx23("span", { className: "b316-plan-feature-value", children: entitlement.limit === null ? "Unlimited" : (
4283
+ /* @__PURE__ */ jsx24("ul", { className: "b316-plan-features", children: plan.entitlements.filter((entitlement) => entitlement.enabled).map((entitlement) => /* @__PURE__ */ jsxs23("li", { className: "b316-plan-feature", children: [
4284
+ /* @__PURE__ */ jsx24("span", { children: entitlement.featureName }),
4285
+ /* @__PURE__ */ jsx24("span", { className: "b316-plan-feature-value", children: entitlement.limit === null ? "Unlimited" : (
4218
4286
  // A usage price on the feature makes the limit an
4219
4287
  // allowance billed past, not a ceiling — the same
4220
4288
  // rule `check()` applies (any non-FLAT price).
@@ -4223,7 +4291,7 @@ function PricingTable({
4223
4291
  ) ? `${entitlement.limit} included` : entitlement.limit
4224
4292
  ) })
4225
4293
  ] }, entitlement.featureId)) }),
4226
- /* @__PURE__ */ jsx23("div", { className: "b316-plan-action", children: /* @__PURE__ */ jsx23(
4294
+ /* @__PURE__ */ jsx24("div", { className: "b316-plan-action", children: /* @__PURE__ */ jsx24(
4227
4295
  "button",
4228
4296
  {
4229
4297
  type: "button",
@@ -4252,7 +4320,7 @@ import {
4252
4320
  formatAddress,
4253
4321
  specFor
4254
4322
  } from "@base316/sdk";
4255
- import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
4323
+ import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
4256
4324
  function formatNumber(value, fraction = 0) {
4257
4325
  const number = Number(value);
4258
4326
  return Number.isFinite(number) ? new Intl.NumberFormat(void 0, {
@@ -4274,10 +4342,10 @@ function formatDuration(value) {
4274
4342
  }
4275
4343
  function FieldCell({ value, field, related }) {
4276
4344
  if (field.type === "RELATION") {
4277
- return related?.title ?? (related?.id ? /* @__PURE__ */ jsx24("code", { className: "b316-muted", children: related.id }) : "\u2014");
4345
+ return related?.title ?? (related?.id ? /* @__PURE__ */ jsx25("code", { className: "b316-muted", children: related.id }) : "\u2014");
4278
4346
  }
4279
4347
  if (value === null || value === void 0 || value === "") {
4280
- return /* @__PURE__ */ jsx24("span", { className: "b316-muted", children: "\u2014" });
4348
+ return /* @__PURE__ */ jsx25("span", { className: "b316-muted", children: "\u2014" });
4281
4349
  }
4282
4350
  switch (field.type) {
4283
4351
  case "BOOLEAN":
@@ -4290,9 +4358,9 @@ function FieldCell({ value, field, related }) {
4290
4358
  return formatDuration(value);
4291
4359
  case "RATING": {
4292
4360
  const stars = Math.round(Number(value));
4293
- return /* @__PURE__ */ jsxs23("span", { "aria-label": `${stars} out of 5`, children: [
4361
+ return /* @__PURE__ */ jsxs24("span", { "aria-label": `${stars} out of 5`, children: [
4294
4362
  "\u2605".repeat(stars),
4295
- /* @__PURE__ */ jsx24("span", { className: "b316-muted", children: "\u2605".repeat(Math.max(0, 5 - stars)) })
4363
+ /* @__PURE__ */ jsx25("span", { className: "b316-muted", children: "\u2605".repeat(Math.max(0, 5 - stars)) })
4296
4364
  ] });
4297
4365
  }
4298
4366
  case "DATE":
@@ -4300,15 +4368,15 @@ function FieldCell({ value, field, related }) {
4300
4368
  case "DATETIME":
4301
4369
  return new Date(String(value)).toLocaleString();
4302
4370
  case "SELECT":
4303
- return /* @__PURE__ */ jsx24("span", { className: "b316-chip", children: String(value) });
4371
+ return /* @__PURE__ */ jsx25("span", { className: "b316-chip", children: String(value) });
4304
4372
  case "MULTISELECT":
4305
- return /* @__PURE__ */ jsx24("span", { className: "b316-chips", children: (Array.isArray(value) ? value : [value]).map((item) => /* @__PURE__ */ jsx24("span", { className: "b316-chip", children: String(item) }, String(item))) });
4373
+ return /* @__PURE__ */ jsx25("span", { className: "b316-chips", children: (Array.isArray(value) ? value : [value]).map((item) => /* @__PURE__ */ jsx25("span", { className: "b316-chip", children: String(item) }, String(item))) });
4306
4374
  case "URL":
4307
- return /* @__PURE__ */ jsx24("a", { href: String(value), target: "_blank", rel: "noreferrer noopener", children: String(value) });
4375
+ return /* @__PURE__ */ jsx25("a", { href: String(value), target: "_blank", rel: "noreferrer noopener", children: String(value) });
4308
4376
  case "EMAIL":
4309
- return /* @__PURE__ */ jsx24("a", { href: `mailto:${String(value)}`, children: String(value) });
4377
+ return /* @__PURE__ */ jsx25("a", { href: `mailto:${String(value)}`, children: String(value) });
4310
4378
  case "PHONE":
4311
- return /* @__PURE__ */ jsx24("a", { href: `tel:${String(value)}`, children: String(value) });
4379
+ return /* @__PURE__ */ jsx25("a", { href: `tel:${String(value)}`, children: String(value) });
4312
4380
  case "ADDRESS":
4313
4381
  return formatAddress(value);
4314
4382
  case "ATTACHMENT": {
@@ -4320,7 +4388,7 @@ function FieldCell({ value, field, related }) {
4320
4388
  return text.length > 80 ? `${text.slice(0, 80)}\u2026` : text;
4321
4389
  }
4322
4390
  case "JSON":
4323
- return /* @__PURE__ */ jsx24("code", { className: "b316-muted", children: JSON.stringify(value).slice(0, 60) });
4391
+ return /* @__PURE__ */ jsx25("code", { className: "b316-muted", children: JSON.stringify(value).slice(0, 60) });
4324
4392
  default:
4325
4393
  return String(value);
4326
4394
  }
@@ -4341,7 +4409,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4341
4409
  function control() {
4342
4410
  switch (field.type) {
4343
4411
  case "LONGTEXT":
4344
- return /* @__PURE__ */ jsx24(
4412
+ return /* @__PURE__ */ jsx25(
4345
4413
  "textarea",
4346
4414
  {
4347
4415
  ...common,
@@ -4351,7 +4419,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4351
4419
  }
4352
4420
  );
4353
4421
  case "BOOLEAN":
4354
- return /* @__PURE__ */ jsx24(
4422
+ return /* @__PURE__ */ jsx25(
4355
4423
  "input",
4356
4424
  {
4357
4425
  ...common,
@@ -4362,22 +4430,22 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4362
4430
  }
4363
4431
  );
4364
4432
  case "SELECT":
4365
- return /* @__PURE__ */ jsxs23(
4433
+ return /* @__PURE__ */ jsxs24(
4366
4434
  "select",
4367
4435
  {
4368
4436
  ...common,
4369
4437
  value: value === null || value === void 0 ? "" : String(value),
4370
4438
  onChange: (event) => onChange(event.target.value === "" ? null : event.target.value),
4371
4439
  children: [
4372
- field.required ? null : /* @__PURE__ */ jsx24("option", { value: "", children: "\u2014" }),
4373
- (field.options ?? []).map((option) => /* @__PURE__ */ jsx24("option", { value: option, children: option }, option))
4440
+ field.required ? null : /* @__PURE__ */ jsx25("option", { value: "", children: "\u2014" }),
4441
+ (field.options ?? []).map((option) => /* @__PURE__ */ jsx25("option", { value: option, children: option }, option))
4374
4442
  ]
4375
4443
  }
4376
4444
  );
4377
4445
  case "MULTISELECT": {
4378
4446
  const selected = new Set(Array.isArray(value) ? value.map(String) : []);
4379
- return /* @__PURE__ */ jsx24("div", { className: "b316-choices", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxs23("label", { className: "b316-choice", children: [
4380
- /* @__PURE__ */ jsx24(
4447
+ return /* @__PURE__ */ jsx25("div", { className: "b316-choices", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxs24("label", { className: "b316-choice", children: [
4448
+ /* @__PURE__ */ jsx25(
4381
4449
  "input",
4382
4450
  {
4383
4451
  type: "checkbox",
@@ -4400,7 +4468,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4400
4468
  case "NUMBER":
4401
4469
  case "MONEY":
4402
4470
  case "PERCENT":
4403
- return /* @__PURE__ */ jsx24(
4471
+ return /* @__PURE__ */ jsx25(
4404
4472
  "input",
4405
4473
  {
4406
4474
  ...common,
@@ -4411,7 +4479,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4411
4479
  }
4412
4480
  );
4413
4481
  case "RATING":
4414
- return /* @__PURE__ */ jsx24(
4482
+ return /* @__PURE__ */ jsx25(
4415
4483
  "input",
4416
4484
  {
4417
4485
  ...common,
@@ -4425,8 +4493,8 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4425
4493
  );
4426
4494
  case "DURATION": {
4427
4495
  const minutes = value === null || value === void 0 ? "" : String(Number(value) / 60);
4428
- return /* @__PURE__ */ jsxs23("div", { className: "b316-suffixed", children: [
4429
- /* @__PURE__ */ jsx24(
4496
+ return /* @__PURE__ */ jsxs24("div", { className: "b316-suffixed", children: [
4497
+ /* @__PURE__ */ jsx25(
4430
4498
  "input",
4431
4499
  {
4432
4500
  ...common,
@@ -4436,11 +4504,11 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4436
4504
  onChange: (event) => onChange(event.target.value === "" ? null : Number(event.target.value) * 60)
4437
4505
  }
4438
4506
  ),
4439
- /* @__PURE__ */ jsx24("span", { className: "b316-muted", children: "minutes" })
4507
+ /* @__PURE__ */ jsx25("span", { className: "b316-muted", children: "minutes" })
4440
4508
  ] });
4441
4509
  }
4442
4510
  case "DATE":
4443
- return /* @__PURE__ */ jsx24(
4511
+ return /* @__PURE__ */ jsx25(
4444
4512
  "input",
4445
4513
  {
4446
4514
  ...common,
@@ -4450,7 +4518,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4450
4518
  }
4451
4519
  );
4452
4520
  case "DATETIME":
4453
- return /* @__PURE__ */ jsx24(
4521
+ return /* @__PURE__ */ jsx25(
4454
4522
  "input",
4455
4523
  {
4456
4524
  ...common,
@@ -4463,7 +4531,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4463
4531
  );
4464
4532
  case "ADDRESS": {
4465
4533
  const address = value ?? {};
4466
- const part = (key, label) => /* @__PURE__ */ jsx24(
4534
+ const part = (key, label) => /* @__PURE__ */ jsx25(
4467
4535
  "input",
4468
4536
  {
4469
4537
  className: "b316-input",
@@ -4475,7 +4543,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4475
4543
  },
4476
4544
  key
4477
4545
  );
4478
- return /* @__PURE__ */ jsxs23("div", { className: "b316-address", children: [
4546
+ return /* @__PURE__ */ jsxs24("div", { className: "b316-address", children: [
4479
4547
  part("line1", "Address line 1"),
4480
4548
  part("line2", "Address line 2"),
4481
4549
  part("city", "City"),
@@ -4485,7 +4553,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4485
4553
  ] });
4486
4554
  }
4487
4555
  case "EMAIL":
4488
- return /* @__PURE__ */ jsx24(
4556
+ return /* @__PURE__ */ jsx25(
4489
4557
  "input",
4490
4558
  {
4491
4559
  ...common,
@@ -4495,7 +4563,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4495
4563
  }
4496
4564
  );
4497
4565
  case "URL":
4498
- return /* @__PURE__ */ jsx24(
4566
+ return /* @__PURE__ */ jsx25(
4499
4567
  "input",
4500
4568
  {
4501
4569
  ...common,
@@ -4505,7 +4573,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4505
4573
  }
4506
4574
  );
4507
4575
  case "PHONE":
4508
- return /* @__PURE__ */ jsx24(
4576
+ return /* @__PURE__ */ jsx25(
4509
4577
  "input",
4510
4578
  {
4511
4579
  ...common,
@@ -4515,7 +4583,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4515
4583
  }
4516
4584
  );
4517
4585
  default:
4518
- return /* @__PURE__ */ jsx24(
4586
+ return /* @__PURE__ */ jsx25(
4519
4587
  "input",
4520
4588
  {
4521
4589
  ...common,
@@ -4526,14 +4594,14 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4526
4594
  );
4527
4595
  }
4528
4596
  }
4529
- return /* @__PURE__ */ jsxs23("div", { className: "b316-field", children: [
4530
- /* @__PURE__ */ jsxs23("label", { className: "b316-label", htmlFor: id, children: [
4597
+ return /* @__PURE__ */ jsxs24("div", { className: "b316-field", children: [
4598
+ /* @__PURE__ */ jsxs24("label", { className: "b316-label", htmlFor: id, children: [
4531
4599
  field.label,
4532
- field.required ? /* @__PURE__ */ jsx24("span", { "aria-hidden": "true", children: " *" }) : null
4600
+ field.required ? /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: " *" }) : null
4533
4601
  ] }),
4534
4602
  control(),
4535
- field.description ? /* @__PURE__ */ jsx24("div", { className: "b316-hint", children: field.description }) : null,
4536
- error ? /* @__PURE__ */ jsx24("div", { className: "b316-error", id: described, role: "alert", children: error }) : null
4603
+ field.description ? /* @__PURE__ */ jsx25("div", { className: "b316-hint", children: field.description }) : null,
4604
+ error ? /* @__PURE__ */ jsx25("div", { className: "b316-error", id: described, role: "alert", children: error }) : null
4537
4605
  ] });
4538
4606
  }
4539
4607
 
@@ -4543,7 +4611,7 @@ import { useEffect as useEffect21, useState as useState26 } from "react";
4543
4611
 
4544
4612
  // src/RelationPicker.tsx
4545
4613
  import { useEffect as useEffect19, useRef as useRef7, useState as useState24 } from "react";
4546
- import { Fragment as Fragment8, jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
4614
+ import { Fragment as Fragment8, jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
4547
4615
  function RelationPicker({
4548
4616
  field,
4549
4617
  value,
@@ -4614,14 +4682,14 @@ function RelationPicker({
4614
4682
  document.removeEventListener("mousedown", onDocumentClick);
4615
4683
  };
4616
4684
  }, [open]);
4617
- return /* @__PURE__ */ jsxs24("div", { className: "b316-field", ref: box, children: [
4618
- /* @__PURE__ */ jsxs24("label", { className: "b316-label", htmlFor: id, children: [
4685
+ return /* @__PURE__ */ jsxs25("div", { className: "b316-field", ref: box, children: [
4686
+ /* @__PURE__ */ jsxs25("label", { className: "b316-label", htmlFor: id, children: [
4619
4687
  field.label,
4620
- field.required ? /* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: " *" }) : null
4688
+ field.required ? /* @__PURE__ */ jsx26("span", { "aria-hidden": "true", children: " *" }) : null
4621
4689
  ] }),
4622
- value && !open ? /* @__PURE__ */ jsxs24("div", { className: "b316-relation-chosen", children: [
4623
- /* @__PURE__ */ jsx25("span", { children: chosenTitle ?? value }),
4624
- disabled ? null : /* @__PURE__ */ jsx25(
4690
+ value && !open ? /* @__PURE__ */ jsxs25("div", { className: "b316-relation-chosen", children: [
4691
+ /* @__PURE__ */ jsx26("span", { children: chosenTitle ?? value }),
4692
+ disabled ? null : /* @__PURE__ */ jsx26(
4625
4693
  "button",
4626
4694
  {
4627
4695
  type: "button",
@@ -4633,7 +4701,7 @@ function RelationPicker({
4633
4701
  children: "Change"
4634
4702
  }
4635
4703
  ),
4636
- disabled || field.required ? null : /* @__PURE__ */ jsx25(
4704
+ disabled || field.required ? null : /* @__PURE__ */ jsx26(
4637
4705
  "button",
4638
4706
  {
4639
4707
  type: "button",
@@ -4643,8 +4711,8 @@ function RelationPicker({
4643
4711
  children: "Clear"
4644
4712
  }
4645
4713
  )
4646
- ] }) : /* @__PURE__ */ jsxs24(Fragment8, { children: [
4647
- /* @__PURE__ */ jsx25(
4714
+ ] }) : /* @__PURE__ */ jsxs25(Fragment8, { children: [
4715
+ /* @__PURE__ */ jsx26(
4648
4716
  "input",
4649
4717
  {
4650
4718
  id,
@@ -4665,7 +4733,7 @@ function RelationPicker({
4665
4733
  }
4666
4734
  }
4667
4735
  ),
4668
- open ? /* @__PURE__ */ jsx25("ul", { className: "b316-relation-results", id: `${id}-results`, role: "listbox", children: results.length === 0 ? /* @__PURE__ */ jsx25("li", { className: "b316-muted b316-relation-empty", children: "No matches" }) : results.map((result) => /* @__PURE__ */ jsx25("li", { children: /* @__PURE__ */ jsx25(
4736
+ open ? /* @__PURE__ */ jsx26("ul", { className: "b316-relation-results", id: `${id}-results`, role: "listbox", children: results.length === 0 ? /* @__PURE__ */ jsx26("li", { className: "b316-muted b316-relation-empty", children: "No matches" }) : results.map((result) => /* @__PURE__ */ jsx26("li", { children: /* @__PURE__ */ jsx26(
4669
4737
  "button",
4670
4738
  {
4671
4739
  type: "button",
@@ -4681,13 +4749,13 @@ function RelationPicker({
4681
4749
  }
4682
4750
  ) }, result.id)) }) : null
4683
4751
  ] }),
4684
- field.description ? /* @__PURE__ */ jsx25("div", { className: "b316-hint", children: field.description }) : null,
4685
- error ? /* @__PURE__ */ jsx25("div", { className: "b316-error", role: "alert", children: error }) : null
4752
+ field.description ? /* @__PURE__ */ jsx26("div", { className: "b316-hint", children: field.description }) : null,
4753
+ error ? /* @__PURE__ */ jsx26("div", { className: "b316-error", role: "alert", children: error }) : null
4686
4754
  ] });
4687
4755
  }
4688
4756
 
4689
4757
  // src/useCollection.ts
4690
- import { useCallback as useCallback9, useEffect as useEffect20, useMemo as useMemo2, useState as useState25 } from "react";
4758
+ import { useCallback as useCallback9, useEffect as useEffect20, useMemo as useMemo3, useState as useState25 } from "react";
4691
4759
  function fieldErrorFrom(cause) {
4692
4760
  const param = cause?.param;
4693
4761
  const message = cause instanceof Error ? cause.message : "That value was not accepted.";
@@ -4711,7 +4779,7 @@ function useCollection(collection, options = {}) {
4711
4779
  const [saving, setSaving] = useState25(false);
4712
4780
  const { tenant, limit, recordId } = options;
4713
4781
  const fixedFilters = JSON.stringify(options.filters ?? []);
4714
- const scope = useMemo2(() => tenant ? { tenant } : void 0, [tenant]);
4782
+ const scope = useMemo3(() => tenant ? { tenant } : void 0, [tenant]);
4715
4783
  useEffect20(() => {
4716
4784
  if (!token) {
4717
4785
  return;
@@ -4923,7 +4991,7 @@ function useCollection(collection, options = {}) {
4923
4991
  }
4924
4992
 
4925
4993
  // src/RecordForm.tsx
4926
- import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
4994
+ import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
4927
4995
  function RecordForm({
4928
4996
  collection,
4929
4997
  recordId,
@@ -4954,10 +5022,10 @@ function RecordForm({
4954
5022
  }
4955
5023
  }, [existing, loaded]);
4956
5024
  if (error) {
4957
- return /* @__PURE__ */ jsx26("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx26("div", { className: "b316-error", role: "alert", children: error }) });
5025
+ return /* @__PURE__ */ jsx27("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx27("div", { className: "b316-error", role: "alert", children: error }) });
4958
5026
  }
4959
5027
  if (!schema || !loaded) {
4960
- return /* @__PURE__ */ jsx26("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5028
+ return /* @__PURE__ */ jsx27("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
4961
5029
  }
4962
5030
  const editable = schema.fields.filter((field) => !specFor2(field).computed);
4963
5031
  async function submit(event) {
@@ -4967,11 +5035,11 @@ function RecordForm({
4967
5035
  onSaved?.(saved.id);
4968
5036
  }
4969
5037
  }
4970
- return /* @__PURE__ */ jsxs25("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
4971
- /* @__PURE__ */ jsx26("h3", { className: "b316-form-title", children: recordId ? `Edit ${schema.name.toLowerCase()}` : `New ${schema.name.toLowerCase()}` }),
4972
- fieldErrors._ ? /* @__PURE__ */ jsx26("div", { className: "b316-error", role: "alert", children: fieldErrors._ }) : null,
5038
+ return /* @__PURE__ */ jsxs26("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
5039
+ /* @__PURE__ */ jsx27("h3", { className: "b316-form-title", children: recordId ? `Edit ${schema.name.toLowerCase()}` : `New ${schema.name.toLowerCase()}` }),
5040
+ fieldErrors._ ? /* @__PURE__ */ jsx27("div", { className: "b316-error", role: "alert", children: fieldErrors._ }) : null,
4973
5041
  editable.map(
4974
- (field) => field.type === "RELATION" ? /* @__PURE__ */ jsx26(
5042
+ (field) => field.type === "RELATION" ? /* @__PURE__ */ jsx27(
4975
5043
  RelationPicker,
4976
5044
  {
4977
5045
  field,
@@ -4982,7 +5050,7 @@ function RecordForm({
4982
5050
  onChange: (next) => setValues((current) => ({ ...current, [field.key]: next }))
4983
5051
  },
4984
5052
  field.key
4985
- ) : /* @__PURE__ */ jsx26(
5053
+ ) : /* @__PURE__ */ jsx27(
4986
5054
  FieldInput,
4987
5055
  {
4988
5056
  field,
@@ -4994,15 +5062,15 @@ function RecordForm({
4994
5062
  field.key
4995
5063
  )
4996
5064
  ),
4997
- /* @__PURE__ */ jsxs25("div", { className: "b316-form-actions", children: [
4998
- onCancel ? /* @__PURE__ */ jsx26("button", { type: "button", className: "b316-button-quiet", onClick: onCancel, disabled: saving, children: "Cancel" }) : null,
4999
- /* @__PURE__ */ jsx26("button", { type: "submit", className: "b316-button", disabled: saving, children: saving ? "Saving\u2026" : "Save" })
5065
+ /* @__PURE__ */ jsxs26("div", { className: "b316-form-actions", children: [
5066
+ onCancel ? /* @__PURE__ */ jsx27("button", { type: "button", className: "b316-button-quiet", onClick: onCancel, disabled: saving, children: "Cancel" }) : null,
5067
+ /* @__PURE__ */ jsx27("button", { type: "submit", className: "b316-button", disabled: saving, children: saving ? "Saving\u2026" : "Save" })
5000
5068
  ] })
5001
5069
  ] });
5002
5070
  }
5003
5071
 
5004
5072
  // src/DataTable.tsx
5005
- import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
5073
+ import { jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
5006
5074
  function DataTable({
5007
5075
  collection,
5008
5076
  columns,
@@ -5034,10 +5102,10 @@ function DataTable({
5034
5102
  const [editing, setEditing] = useState27(null);
5035
5103
  const [removeFailed, setRemoveFailed] = useState27(null);
5036
5104
  if (error) {
5037
- return /* @__PURE__ */ jsx27("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx27("div", { className: "b316-error", role: "alert", children: error }) });
5105
+ return /* @__PURE__ */ jsx28("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx28("div", { className: "b316-error", role: "alert", children: error }) });
5038
5106
  }
5039
5107
  if (!schema) {
5040
- return /* @__PURE__ */ jsx27("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5108
+ return /* @__PURE__ */ jsx28("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5041
5109
  }
5042
5110
  const shown = columns ? (
5043
5111
  // Ordered by what was asked for, not by the schema: a caller naming
@@ -5046,10 +5114,10 @@ function DataTable({
5046
5114
  ) : schema.fields;
5047
5115
  const searchable = schema.fields.some((field) => specFor3(field).capabilities.searchable);
5048
5116
  const writable = canWrite && !readOnly;
5049
- return /* @__PURE__ */ jsxs26("div", { className: cls("b316-table-wrap", className), style, children: [
5050
- removeFailed ? /* @__PURE__ */ jsx27("div", { className: "b316-error", role: "alert", children: removeFailed }) : null,
5051
- /* @__PURE__ */ jsxs26("div", { className: "b316-table-bar", children: [
5052
- searchable && !hideSearch ? /* @__PURE__ */ jsx27(
5117
+ return /* @__PURE__ */ jsxs27("div", { className: cls("b316-table-wrap", className), style, children: [
5118
+ removeFailed ? /* @__PURE__ */ jsx28("div", { className: "b316-error", role: "alert", children: removeFailed }) : null,
5119
+ /* @__PURE__ */ jsxs27("div", { className: "b316-table-bar", children: [
5120
+ searchable && !hideSearch ? /* @__PURE__ */ jsx28(
5053
5121
  "input",
5054
5122
  {
5055
5123
  type: "search",
@@ -5059,25 +5127,25 @@ function DataTable({
5059
5127
  value: search,
5060
5128
  onChange: (event) => setSearch(event.target.value)
5061
5129
  }
5062
- ) : /* @__PURE__ */ jsx27("span", {}),
5063
- /* @__PURE__ */ jsxs26("div", { className: "b316-table-actions", children: [
5064
- /* @__PURE__ */ jsxs26("span", { className: "b316-muted", children: [
5130
+ ) : /* @__PURE__ */ jsx28("span", {}),
5131
+ /* @__PURE__ */ jsxs27("div", { className: "b316-table-actions", children: [
5132
+ /* @__PURE__ */ jsxs27("span", { className: "b316-muted", children: [
5065
5133
  total,
5066
5134
  " ",
5067
5135
  total === 1 ? schema.name.toLowerCase() : schema.namePlural.toLowerCase()
5068
5136
  ] }),
5069
- writable ? /* @__PURE__ */ jsxs26("button", { type: "button", className: "b316-button", onClick: () => setEditing("new"), children: [
5137
+ writable ? /* @__PURE__ */ jsxs27("button", { type: "button", className: "b316-button", onClick: () => setEditing("new"), children: [
5070
5138
  "New ",
5071
5139
  schema.name.toLowerCase()
5072
5140
  ] }) : null
5073
5141
  ] })
5074
5142
  ] }),
5075
- /* @__PURE__ */ jsx27("div", { className: "b316-table-scroll", children: /* @__PURE__ */ jsxs26("table", { className: "b316-table", children: [
5076
- /* @__PURE__ */ jsx27("thead", { children: /* @__PURE__ */ jsxs26("tr", { children: [
5143
+ /* @__PURE__ */ jsx28("div", { className: "b316-table-scroll", children: /* @__PURE__ */ jsxs27("table", { className: "b316-table", children: [
5144
+ /* @__PURE__ */ jsx28("thead", { children: /* @__PURE__ */ jsxs27("tr", { children: [
5077
5145
  shown.map((field) => {
5078
5146
  const sortable = specFor3(field).capabilities.sortable;
5079
5147
  const active = sort?.field === field.key;
5080
- return /* @__PURE__ */ jsx27("th", { scope: "col", "aria-sort": ariaSort(active, sort?.direction), children: sortable ? /* @__PURE__ */ jsxs26(
5148
+ return /* @__PURE__ */ jsx28("th", { scope: "col", "aria-sort": ariaSort(active, sort?.direction), children: sortable ? /* @__PURE__ */ jsxs27(
5081
5149
  "button",
5082
5150
  {
5083
5151
  type: "button",
@@ -5085,20 +5153,20 @@ function DataTable({
5085
5153
  onClick: () => toggleSort(field.key),
5086
5154
  children: [
5087
5155
  field.label,
5088
- /* @__PURE__ */ jsx27("span", { "aria-hidden": "true", children: active ? sort?.direction === "desc" ? " \u2193" : " \u2191" : " \u2195" })
5156
+ /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: active ? sort?.direction === "desc" ? " \u2193" : " \u2191" : " \u2195" })
5089
5157
  ]
5090
5158
  }
5091
5159
  ) : field.label }, field.key);
5092
5160
  }),
5093
- writable ? /* @__PURE__ */ jsx27("th", { scope: "col", className: "b316-table-rowactions" }) : null
5161
+ writable ? /* @__PURE__ */ jsx28("th", { scope: "col", className: "b316-table-rowactions" }) : null
5094
5162
  ] }) }),
5095
- /* @__PURE__ */ jsx27("tbody", { children: records.map((record) => /* @__PURE__ */ jsxs26(
5163
+ /* @__PURE__ */ jsx28("tbody", { children: records.map((record) => /* @__PURE__ */ jsxs27(
5096
5164
  "tr",
5097
5165
  {
5098
5166
  className: onSelect ? "b316-row-clickable" : void 0,
5099
5167
  onClick: onSelect ? () => onSelect(record) : void 0,
5100
5168
  children: [
5101
- shown.map((field) => /* @__PURE__ */ jsx27("td", { children: renderCell?.(record, field) ?? /* @__PURE__ */ jsx27(
5169
+ shown.map((field) => /* @__PURE__ */ jsx28("td", { children: renderCell?.(record, field) ?? /* @__PURE__ */ jsx28(
5102
5170
  FieldCell,
5103
5171
  {
5104
5172
  value: record.fields[field.key] ?? null,
@@ -5106,8 +5174,8 @@ function DataTable({
5106
5174
  related: record.related[field.key]
5107
5175
  }
5108
5176
  ) }, field.key)),
5109
- writable ? /* @__PURE__ */ jsxs26("td", { className: "b316-table-rowactions", children: [
5110
- /* @__PURE__ */ jsx27(
5177
+ writable ? /* @__PURE__ */ jsxs27("td", { className: "b316-table-rowactions", children: [
5178
+ /* @__PURE__ */ jsx28(
5111
5179
  "button",
5112
5180
  {
5113
5181
  type: "button",
@@ -5119,7 +5187,7 @@ function DataTable({
5119
5187
  children: "Edit"
5120
5188
  }
5121
5189
  ),
5122
- /* @__PURE__ */ jsx27(
5190
+ /* @__PURE__ */ jsx28(
5123
5191
  ConfirmButton,
5124
5192
  {
5125
5193
  className: "b316-button-quiet b316-danger",
@@ -5143,10 +5211,10 @@ function DataTable({
5143
5211
  record.id
5144
5212
  )) })
5145
5213
  ] }) }),
5146
- records.length === 0 && !loading ? /* @__PURE__ */ jsx27("div", { className: "b316-empty", children: emptyState ?? `No ${schema.namePlural.toLowerCase()} yet.` }) : null,
5147
- loading ? /* @__PURE__ */ jsx27("div", { className: "b316-empty", children: "Loading\u2026" }) : null,
5148
- hasMore ? /* @__PURE__ */ jsx27("div", { className: "b316-table-more", children: /* @__PURE__ */ jsx27("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: "Load more" }) }) : null,
5149
- editing ? /* @__PURE__ */ jsx27(
5214
+ records.length === 0 && !loading ? /* @__PURE__ */ jsx28("div", { className: "b316-empty", children: emptyState ?? `No ${schema.namePlural.toLowerCase()} yet.` }) : null,
5215
+ loading ? /* @__PURE__ */ jsx28("div", { className: "b316-empty", children: "Loading\u2026" }) : null,
5216
+ hasMore ? /* @__PURE__ */ jsx28("div", { className: "b316-table-more", children: /* @__PURE__ */ jsx28("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: "Load more" }) }) : null,
5217
+ editing ? /* @__PURE__ */ jsx28(
5150
5218
  RecordForm,
5151
5219
  {
5152
5220
  collection,
@@ -5175,7 +5243,7 @@ import {
5175
5243
  titleFieldOf
5176
5244
  } from "@base316/sdk";
5177
5245
  import { useState as useState28 } from "react";
5178
- import { jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
5246
+ import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
5179
5247
  function Kanban({
5180
5248
  collection,
5181
5249
  groupBy,
@@ -5195,14 +5263,14 @@ function Kanban({
5195
5263
  const [dragging, setDragging] = useState28(null);
5196
5264
  const [over, setOver] = useState28(null);
5197
5265
  if (error) {
5198
- return /* @__PURE__ */ jsx28("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx28("div", { className: "b316-error", role: "alert", children: error }) });
5266
+ return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx29("div", { className: "b316-error", role: "alert", children: error }) });
5199
5267
  }
5200
5268
  if (!schema) {
5201
- return /* @__PURE__ */ jsx28("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5269
+ return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5202
5270
  }
5203
5271
  const field = groupBy ? schema.fields.find((candidate) => candidate.key === groupBy) ?? null : defaultGroupFieldOf(schema.fields);
5204
5272
  if (!field || !specFor4(field).capabilities.groupable) {
5205
- return /* @__PURE__ */ jsx28("div", { className: cls("b316-card", className), style, children: groupBy ? `"${groupBy}" cannot make columns. A board groups by a choice, a yes/no or a date.` : `${schema.namePlural} have no field to group by. Add a choice field \u2014 a status or a stage \u2014 and this board will use it.` });
5273
+ return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: groupBy ? `"${groupBy}" cannot make columns. A board groups by a choice, a yes/no or a date.` : `${schema.namePlural} have no field to group by. Add a choice field \u2014 a status or a stage \u2014 and this board will use it.` });
5206
5274
  }
5207
5275
  const columns = columnsFor(field);
5208
5276
  const shown = cardFields ? cardFields.map((key) => schema.fields.find((candidate) => candidate.key === key)).filter((candidate) => Boolean(candidate)) : (
@@ -5219,12 +5287,12 @@ function Kanban({
5219
5287
  }
5220
5288
  await update(record.id, { [field.key]: value });
5221
5289
  }
5222
- return /* @__PURE__ */ jsxs27("div", { className: cls("b316-board-wrap", className), style, children: [
5223
- /* @__PURE__ */ jsx28("div", { className: "b316-board", role: "list", children: columns.map((column) => {
5290
+ return /* @__PURE__ */ jsxs28("div", { className: cls("b316-board-wrap", className), style, children: [
5291
+ /* @__PURE__ */ jsx29("div", { className: "b316-board", role: "list", children: columns.map((column) => {
5224
5292
  const inColumn = records.filter(
5225
5293
  (record) => String(record.fields[field.key] ?? "") === String(column.value ?? "")
5226
5294
  );
5227
- return /* @__PURE__ */ jsxs27(
5295
+ return /* @__PURE__ */ jsxs28(
5228
5296
  "section",
5229
5297
  {
5230
5298
  className: over === String(column.value) ? "b316-board-column b316-board-over" : "b316-board-column",
@@ -5248,12 +5316,12 @@ function Kanban({
5248
5316
  setDragging(null);
5249
5317
  },
5250
5318
  children: [
5251
- /* @__PURE__ */ jsxs27("header", { className: "b316-board-head", children: [
5252
- /* @__PURE__ */ jsx28("span", { className: "b316-board-title", children: column.label }),
5253
- /* @__PURE__ */ jsx28("span", { className: "b316-muted", children: inColumn.length })
5319
+ /* @__PURE__ */ jsxs28("header", { className: "b316-board-head", children: [
5320
+ /* @__PURE__ */ jsx29("span", { className: "b316-board-title", children: column.label }),
5321
+ /* @__PURE__ */ jsx29("span", { className: "b316-muted", children: inColumn.length })
5254
5322
  ] }),
5255
- /* @__PURE__ */ jsxs27("div", { className: "b316-board-cards", children: [
5256
- inColumn.map((record) => /* @__PURE__ */ jsxs27(
5323
+ /* @__PURE__ */ jsxs28("div", { className: "b316-board-cards", children: [
5324
+ inColumn.map((record) => /* @__PURE__ */ jsxs28(
5257
5325
  "article",
5258
5326
  {
5259
5327
  className: "b316-board-card",
@@ -5265,10 +5333,10 @@ function Kanban({
5265
5333
  },
5266
5334
  onClick: onSelect ? () => onSelect(record) : void 0,
5267
5335
  children: [
5268
- /* @__PURE__ */ jsx28("div", { className: "b316-board-card-title", children: record.title ?? "Untitled" }),
5269
- shown.map((candidate) => /* @__PURE__ */ jsxs27("div", { className: "b316-board-card-field", children: [
5270
- /* @__PURE__ */ jsx28("span", { className: "b316-muted", children: candidate.label }),
5271
- /* @__PURE__ */ jsx28(
5336
+ /* @__PURE__ */ jsx29("div", { className: "b316-board-card-title", children: record.title ?? "Untitled" }),
5337
+ shown.map((candidate) => /* @__PURE__ */ jsxs28("div", { className: "b316-board-card-field", children: [
5338
+ /* @__PURE__ */ jsx29("span", { className: "b316-muted", children: candidate.label }),
5339
+ /* @__PURE__ */ jsx29(
5272
5340
  FieldCell,
5273
5341
  {
5274
5342
  value: record.fields[candidate.key] ?? null,
@@ -5281,9 +5349,9 @@ function Kanban({
5281
5349
  // Dragging is not reachable by keyboard and is awkward on a
5282
5350
  // phone. This is the same action by other means, not a
5283
5351
  // lesser fallback.
5284
- /* @__PURE__ */ jsxs27("label", { className: "b316-board-move", children: [
5285
- /* @__PURE__ */ jsx28("span", { className: "b316-muted", children: "Move to" }),
5286
- /* @__PURE__ */ jsx28(
5352
+ /* @__PURE__ */ jsxs28("label", { className: "b316-board-move", children: [
5353
+ /* @__PURE__ */ jsx29("span", { className: "b316-muted", children: "Move to" }),
5354
+ /* @__PURE__ */ jsx29(
5287
5355
  "select",
5288
5356
  {
5289
5357
  className: "b316-input",
@@ -5295,7 +5363,7 @@ function Kanban({
5295
5363
  );
5296
5364
  void move(record, chosen?.value ?? null);
5297
5365
  },
5298
- children: columns.map((candidate) => /* @__PURE__ */ jsx28("option", { value: String(candidate.value), children: candidate.label }, String(candidate.value)))
5366
+ children: columns.map((candidate) => /* @__PURE__ */ jsx29("option", { value: String(candidate.value), children: candidate.label }, String(candidate.value)))
5299
5367
  }
5300
5368
  )
5301
5369
  ] })
@@ -5304,14 +5372,14 @@ function Kanban({
5304
5372
  },
5305
5373
  record.id
5306
5374
  )),
5307
- inColumn.length === 0 ? /* @__PURE__ */ jsx28("div", { className: "b316-board-empty", children: emptyState ?? "Nothing here" }) : null
5375
+ inColumn.length === 0 ? /* @__PURE__ */ jsx29("div", { className: "b316-board-empty", children: emptyState ?? "Nothing here" }) : null
5308
5376
  ] })
5309
5377
  ]
5310
5378
  },
5311
5379
  String(column.value)
5312
5380
  );
5313
5381
  }) }),
5314
- hasMore ? /* @__PURE__ */ jsx28("div", { className: "b316-table-more", children: /* @__PURE__ */ jsxs27("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: [
5382
+ hasMore ? /* @__PURE__ */ jsx29("div", { className: "b316-table-more", children: /* @__PURE__ */ jsxs28("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: [
5315
5383
  "Showing ",
5316
5384
  records.length,
5317
5385
  " of ",
@@ -5337,8 +5405,8 @@ import {
5337
5405
  fieldsFor,
5338
5406
  specFor as specFor5
5339
5407
  } from "@base316/sdk";
5340
- import { useMemo as useMemo3 } from "react";
5341
- import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
5408
+ import { useMemo as useMemo4 } from "react";
5409
+ import { jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
5342
5410
  function Chart({
5343
5411
  collection,
5344
5412
  x,
@@ -5357,7 +5425,7 @@ function Chart({
5357
5425
  limit: options.limit ?? 200,
5358
5426
  ...options
5359
5427
  });
5360
- const axis = useMemo3(() => {
5428
+ const axis = useMemo4(() => {
5361
5429
  if (!schema) {
5362
5430
  return null;
5363
5431
  }
@@ -5365,35 +5433,35 @@ function Chart({
5365
5433
  const chosen = x ? schema.fields.find((field) => field.key === x) ?? null : timeFields[0] ?? null;
5366
5434
  return chosen && specFor5(chosen).capabilities.timeAxis ? chosen : null;
5367
5435
  }, [schema, x]);
5368
- const measure = useMemo3(() => {
5436
+ const measure = useMemo4(() => {
5369
5437
  if (!schema || !y) {
5370
5438
  return null;
5371
5439
  }
5372
5440
  const candidates = fieldsAggregatableBy(schema.fields, aggregate);
5373
5441
  return candidates.find((field) => field.key === y) ?? null;
5374
5442
  }, [schema, y, aggregate]);
5375
- const buckets = useMemo3(
5443
+ const buckets = useMemo4(
5376
5444
  () => axis ? bucketise(records, axis, measure, y ? aggregate : "count", bucket) : [],
5377
5445
  [records, axis, measure, aggregate, bucket, y]
5378
5446
  );
5379
5447
  if (error) {
5380
- return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx29("div", { className: "b316-error", role: "alert", children: error }) });
5448
+ return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx30("div", { className: "b316-error", role: "alert", children: error }) });
5381
5449
  }
5382
5450
  if (!schema || loading) {
5383
- return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5451
+ return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5384
5452
  }
5385
5453
  if (!axis) {
5386
- return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: x ? `"${x}" is not a date, so it cannot be a time axis.` : `${schema.namePlural} have no date field to chart against. Add one and this chart will use it.` });
5454
+ return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: x ? `"${x}" is not a date, so it cannot be a time axis.` : `${schema.namePlural} have no date field to chart against. Add one and this chart will use it.` });
5387
5455
  }
5388
5456
  if (y && !measure) {
5389
- return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: `"${y}" cannot be ${aggregate === "avg" ? "averaged" : `combined with ${aggregate}`}.` });
5457
+ return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: `"${y}" cannot be ${aggregate === "avg" ? "averaged" : `combined with ${aggregate}`}.` });
5390
5458
  }
5391
5459
  const peak = Math.max(...buckets.map((entry) => entry.value), 0);
5392
5460
  const heading = title ?? `${measure ? `${aggregate} of ${measure.label}` : schema.namePlural} by ${axis.label}`;
5393
- return /* @__PURE__ */ jsxs28("figure", { className: cls("b316-card b316-chart", className), style, children: [
5394
- /* @__PURE__ */ jsx29("figcaption", { className: "b316-chart-title", children: heading }),
5395
- buckets.length === 0 || peak === 0 ? /* @__PURE__ */ jsx29("div", { className: "b316-empty", children: "Nothing to chart yet." }) : /* @__PURE__ */ jsx29("div", { className: "b316-chart-plot", style: { height }, children: buckets.map((entry) => /* @__PURE__ */ jsxs28("div", { className: "b316-chart-col", children: [
5396
- /* @__PURE__ */ jsx29(
5461
+ return /* @__PURE__ */ jsxs29("figure", { className: cls("b316-card b316-chart", className), style, children: [
5462
+ /* @__PURE__ */ jsx30("figcaption", { className: "b316-chart-title", children: heading }),
5463
+ buckets.length === 0 || peak === 0 ? /* @__PURE__ */ jsx30("div", { className: "b316-empty", children: "Nothing to chart yet." }) : /* @__PURE__ */ jsx30("div", { className: "b316-chart-plot", style: { height }, children: buckets.map((entry) => /* @__PURE__ */ jsxs29("div", { className: "b316-chart-col", children: [
5464
+ /* @__PURE__ */ jsx30(
5397
5465
  "div",
5398
5466
  {
5399
5467
  className: "b316-chart-bar",
@@ -5401,18 +5469,18 @@ function Chart({
5401
5469
  title: `${entry.label}: ${format(entry.value)}`
5402
5470
  }
5403
5471
  ),
5404
- /* @__PURE__ */ jsx29("span", { className: "b316-chart-label", children: entry.label })
5472
+ /* @__PURE__ */ jsx30("span", { className: "b316-chart-label", children: entry.label })
5405
5473
  ] }, entry.key)) }),
5406
- /* @__PURE__ */ jsxs28("details", { className: "b316-chart-data", children: [
5407
- /* @__PURE__ */ jsx29("summary", { children: "Values" }),
5408
- /* @__PURE__ */ jsxs28("table", { className: "b316-table", children: [
5409
- /* @__PURE__ */ jsx29("thead", { children: /* @__PURE__ */ jsxs28("tr", { children: [
5410
- /* @__PURE__ */ jsx29("th", { scope: "col", children: axis.label }),
5411
- /* @__PURE__ */ jsx29("th", { scope: "col", children: measure ? measure.label : "Count" })
5474
+ /* @__PURE__ */ jsxs29("details", { className: "b316-chart-data", children: [
5475
+ /* @__PURE__ */ jsx30("summary", { children: "Values" }),
5476
+ /* @__PURE__ */ jsxs29("table", { className: "b316-table", children: [
5477
+ /* @__PURE__ */ jsx30("thead", { children: /* @__PURE__ */ jsxs29("tr", { children: [
5478
+ /* @__PURE__ */ jsx30("th", { scope: "col", children: axis.label }),
5479
+ /* @__PURE__ */ jsx30("th", { scope: "col", children: measure ? measure.label : "Count" })
5412
5480
  ] }) }),
5413
- /* @__PURE__ */ jsx29("tbody", { children: buckets.map((entry) => /* @__PURE__ */ jsxs28("tr", { children: [
5414
- /* @__PURE__ */ jsx29("td", { children: entry.label }),
5415
- /* @__PURE__ */ jsx29("td", { children: format(entry.value) })
5481
+ /* @__PURE__ */ jsx30("tbody", { children: buckets.map((entry) => /* @__PURE__ */ jsxs29("tr", { children: [
5482
+ /* @__PURE__ */ jsx30("td", { children: entry.label }),
5483
+ /* @__PURE__ */ jsx30("td", { children: format(entry.value) })
5416
5484
  ] }, entry.key)) })
5417
5485
  ] })
5418
5486
  ] })
@@ -5472,7 +5540,7 @@ function combine(values, aggregate) {
5472
5540
  // src/RecordDetail.tsx
5473
5541
  import { specFor as specFor6 } from "@base316/sdk";
5474
5542
  import { useState as useState29 } from "react";
5475
- import { jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
5543
+ import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
5476
5544
  function RecordDetail({
5477
5545
  collection,
5478
5546
  recordId,
@@ -5491,20 +5559,20 @@ function RecordDetail({
5491
5559
  const [editing, setEditing] = useState29(false);
5492
5560
  const record = records.find((candidate) => candidate.id === recordId);
5493
5561
  if (error) {
5494
- return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx30("div", { className: "b316-error", role: "alert", children: error }) });
5562
+ return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx31("div", { className: "b316-error", role: "alert", children: error }) });
5495
5563
  }
5496
5564
  if (!schema || loading) {
5497
- return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5565
+ return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5498
5566
  }
5499
5567
  if (!record) {
5500
- return /* @__PURE__ */ jsxs29("div", { className: cls("b316-card", className), style, children: [
5568
+ return /* @__PURE__ */ jsxs30("div", { className: cls("b316-card", className), style, children: [
5501
5569
  "That ",
5502
5570
  schema.name.toLowerCase(),
5503
5571
  " is not available."
5504
5572
  ] });
5505
5573
  }
5506
5574
  if (editing) {
5507
- return /* @__PURE__ */ jsx30(
5575
+ return /* @__PURE__ */ jsx31(
5508
5576
  RecordForm,
5509
5577
  {
5510
5578
  collection,
@@ -5518,12 +5586,12 @@ function RecordDetail({
5518
5586
  );
5519
5587
  }
5520
5588
  const writable = canWrite && !readOnly;
5521
- return /* @__PURE__ */ jsxs29("div", { className: cls("b316-card b316-detail", className), style, children: [
5522
- /* @__PURE__ */ jsxs29("div", { className: "b316-detail-head", children: [
5523
- /* @__PURE__ */ jsx30("h3", { className: "b316-detail-title", children: record.title ?? schema.name }),
5524
- /* @__PURE__ */ jsxs29("div", { className: "b316-detail-actions", children: [
5525
- writable ? /* @__PURE__ */ jsx30("button", { type: "button", className: "b316-button-quiet", onClick: () => setEditing(true), children: "Edit" }) : null,
5526
- writable ? /* @__PURE__ */ jsx30(
5589
+ return /* @__PURE__ */ jsxs30("div", { className: cls("b316-card b316-detail", className), style, children: [
5590
+ /* @__PURE__ */ jsxs30("div", { className: "b316-detail-head", children: [
5591
+ /* @__PURE__ */ jsx31("h3", { className: "b316-detail-title", children: record.title ?? schema.name }),
5592
+ /* @__PURE__ */ jsxs30("div", { className: "b316-detail-actions", children: [
5593
+ writable ? /* @__PURE__ */ jsx31("button", { type: "button", className: "b316-button-quiet", onClick: () => setEditing(true), children: "Edit" }) : null,
5594
+ writable ? /* @__PURE__ */ jsx31(
5527
5595
  ConfirmButton,
5528
5596
  {
5529
5597
  className: "b316-button-quiet b316-danger",
@@ -5536,15 +5604,15 @@ function RecordDetail({
5536
5604
  children: "Delete"
5537
5605
  }
5538
5606
  ) : null,
5539
- onClose ? /* @__PURE__ */ jsx30("button", { type: "button", className: "b316-button-quiet", onClick: onClose, children: "Close" }) : null
5607
+ onClose ? /* @__PURE__ */ jsx31("button", { type: "button", className: "b316-button-quiet", onClick: onClose, children: "Close" }) : null
5540
5608
  ] })
5541
5609
  ] }),
5542
- /* @__PURE__ */ jsx30("dl", { className: "b316-detail-fields", children: schema.fields.map((field) => /* @__PURE__ */ jsxs29("div", { className: "b316-detail-row", children: [
5543
- /* @__PURE__ */ jsxs29("dt", { className: "b316-label", children: [
5610
+ /* @__PURE__ */ jsx31("dl", { className: "b316-detail-fields", children: schema.fields.map((field) => /* @__PURE__ */ jsxs30("div", { className: "b316-detail-row", children: [
5611
+ /* @__PURE__ */ jsxs30("dt", { className: "b316-label", children: [
5544
5612
  field.label,
5545
- specFor6(field).computed ? /* @__PURE__ */ jsx30("span", { className: "b316-muted", children: " (calculated)" }) : null
5613
+ specFor6(field).computed ? /* @__PURE__ */ jsx31("span", { className: "b316-muted", children: " (calculated)" }) : null
5546
5614
  ] }),
5547
- /* @__PURE__ */ jsx30("dd", { children: /* @__PURE__ */ jsx30(
5615
+ /* @__PURE__ */ jsx31("dd", { children: /* @__PURE__ */ jsx31(
5548
5616
  FieldCell,
5549
5617
  {
5550
5618
  value: record.fields[field.key] ?? null,
@@ -5559,11 +5627,40 @@ function RecordDetail({
5559
5627
 
5560
5628
  // src/SubscriptionManager.tsx
5561
5629
  import { useCallback as useCallback10, useEffect as useEffect22, useState as useState30 } from "react";
5562
- import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
5630
+ import { jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
5563
5631
  function statusLabel(status2) {
5564
5632
  const words = status2.toLowerCase().split("_");
5565
5633
  return words.map((w, i) => i === 0 ? w.charAt(0).toUpperCase() + w.slice(1) : w).join(" ");
5566
5634
  }
5635
+ var REASONS = [
5636
+ { value: "TOO_EXPENSIVE", label: "It costs too much" },
5637
+ { value: "NOT_USING", label: "I am not using it enough" },
5638
+ { value: "MISSING_FEATURES", label: "It is missing something I need" },
5639
+ { value: "SWITCHING", label: "I am switching to something else" },
5640
+ { value: "TECHNICAL_ISSUES", label: "It did not work well for me" },
5641
+ { value: "TEMPORARY", label: "I only needed it for a while" },
5642
+ { value: "OTHER", label: "Something else" }
5643
+ ];
5644
+ function describeRetentionOffer(offer, currency) {
5645
+ let amount;
5646
+ if (offer.type === "PERCENTAGE") {
5647
+ amount = `${Number(offer.percentOff ?? "0")}% off`;
5648
+ } else {
5649
+ try {
5650
+ amount = `${new Intl.NumberFormat(void 0, {
5651
+ style: "currency",
5652
+ currency: offer.currency ?? currency
5653
+ }).format(Number(offer.amountOff ?? "0"))} off`;
5654
+ } catch {
5655
+ amount = `${offer.amountOff} ${offer.currency ?? currency} off`;
5656
+ }
5657
+ }
5658
+ if (offer.duration === "FOREVER") {
5659
+ return `${amount} for as long as you stay subscribed`;
5660
+ }
5661
+ const periods = offer.duration === "ONCE" ? 1 : offer.durationInPeriods ?? 1;
5662
+ return periods === 1 ? `${amount} your next invoice` : `${amount} your next ${periods} invoices`;
5663
+ }
5567
5664
  function SubscriptionManager({
5568
5665
  onChange,
5569
5666
  className,
@@ -5576,6 +5673,9 @@ function SubscriptionManager({
5576
5673
  const [schedule, setSchedule] = useState30([]);
5577
5674
  const [busy, setBusy] = useState30(false);
5578
5675
  const [error, setError] = useState30(null);
5676
+ const [step, setStep] = useState30({ kind: "idle" });
5677
+ const [reason, setReason] = useState30(null);
5678
+ const [comment, setComment] = useState30("");
5579
5679
  const load = useCallback10(async () => {
5580
5680
  if (!token) {
5581
5681
  setSubscription(null);
@@ -5612,29 +5712,29 @@ function SubscriptionManager({
5612
5712
  }
5613
5713
  };
5614
5714
  if (sessionLoading || loading) {
5615
- return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5715
+ return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5616
5716
  }
5617
5717
  if (!token) {
5618
- return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: "Sign in to manage your subscription." });
5718
+ return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: "Sign in to manage your subscription." });
5619
5719
  }
5620
5720
  if (error) {
5621
- return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx31("div", { className: "b316-error", role: "alert", children: error }) });
5721
+ return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx32("div", { className: "b316-error", role: "alert", children: error }) });
5622
5722
  }
5623
5723
  if (!subscription) {
5624
- return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: "You are not subscribed to a plan." });
5724
+ return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: "You are not subscribed to a plan." });
5625
5725
  }
5626
5726
  const renews = new Date(subscription.currentPeriodEnd).toLocaleDateString();
5627
5727
  const next = schedule[0] ?? null;
5628
5728
  const nextOn = next?.effectiveAt ? new Date(next.effectiveAt).toLocaleDateString() : renews;
5629
- return /* @__PURE__ */ jsxs30("div", { className: cls("b316-card", className), style, children: [
5630
- error ? /* @__PURE__ */ jsx31("div", { className: "b316-error", role: "alert", children: error }) : null,
5631
- /* @__PURE__ */ jsx31("div", { className: "b316-plan-name", children: subscription.planVersion.plan.name }),
5632
- /* @__PURE__ */ jsxs30("div", { className: "b316-muted", children: [
5729
+ return /* @__PURE__ */ jsxs31("div", { className: cls("b316-card", className), style, children: [
5730
+ error ? /* @__PURE__ */ jsx32("div", { className: "b316-error", role: "alert", children: error }) : null,
5731
+ /* @__PURE__ */ jsx32("div", { className: "b316-plan-name", children: subscription.planVersion.plan.name }),
5732
+ /* @__PURE__ */ jsxs31("div", { className: "b316-muted", children: [
5633
5733
  statusLabel(subscription.status),
5634
5734
  " \xB7 ",
5635
5735
  subscription.cancelAtPeriodEnd ? `Ends ${renews}` : `Renews ${renews}`
5636
5736
  ] }),
5637
- next && !managedBy ? /* @__PURE__ */ jsxs30("div", { className: "b316-muted", role: "status", style: { marginTop: 10 }, children: [
5737
+ next && !managedBy ? /* @__PURE__ */ jsxs31("div", { className: "b316-muted", role: "status", style: { marginTop: 10 }, children: [
5638
5738
  "Moves to ",
5639
5739
  next.plan.name,
5640
5740
  " on ",
@@ -5642,7 +5742,7 @@ function SubscriptionManager({
5642
5742
  ". You keep ",
5643
5743
  subscription.planVersion.plan.name,
5644
5744
  " until then.",
5645
- /* @__PURE__ */ jsx31("div", { children: /* @__PURE__ */ jsx31(
5745
+ /* @__PURE__ */ jsx32("div", { children: /* @__PURE__ */ jsx32(
5646
5746
  "button",
5647
5747
  {
5648
5748
  type: "button",
@@ -5667,17 +5767,17 @@ function SubscriptionManager({
5667
5767
  }
5668
5768
  ) })
5669
5769
  ] }) : null,
5670
- managedBy ? /* @__PURE__ */ jsxs30("p", { className: "b316-muted", children: [
5770
+ managedBy ? /* @__PURE__ */ jsxs31("p", { className: "b316-muted", children: [
5671
5771
  "Provided by ",
5672
5772
  managedBy.name ?? "the organization that manages your account",
5673
5773
  ". Ask them to change or cancel it."
5674
- ] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */ jsxs30("div", { children: [
5675
- /* @__PURE__ */ jsxs30("p", { className: "b316-muted", children: [
5774
+ ] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */ jsxs31("div", { children: [
5775
+ /* @__PURE__ */ jsxs31("p", { className: "b316-muted", children: [
5676
5776
  "This subscription will not renew. You keep access until ",
5677
5777
  renews,
5678
5778
  "."
5679
5779
  ] }),
5680
- /* @__PURE__ */ jsx31(
5780
+ /* @__PURE__ */ jsx32(
5681
5781
  "button",
5682
5782
  {
5683
5783
  type: "button",
@@ -5687,18 +5787,129 @@ function SubscriptionManager({
5687
5787
  children: busy ? "Working\u2026" : "Resume subscription"
5688
5788
  }
5689
5789
  )
5690
- ] }) : /* @__PURE__ */ jsx31("div", { style: { marginTop: 14 }, children: /* @__PURE__ */ jsx31(
5691
- ConfirmButton,
5790
+ ] }) : step.kind === "offer" ? /* @__PURE__ */ jsxs31("section", { style: { marginTop: 14 }, "aria-label": "Retention offer", children: [
5791
+ /* @__PURE__ */ jsx32("div", { className: "b316-plan-name", children: step.cancellation.offer.headline ?? "Before you go" }),
5792
+ /* @__PURE__ */ jsx32("p", { className: "b316-muted", children: step.cancellation.offer.message ?? `Stay on ${subscription.planVersion.plan.name} and get ${describeRetentionOffer(
5793
+ step.cancellation.offer,
5794
+ step.cancellation.currency
5795
+ )}.` }),
5796
+ /* @__PURE__ */ jsxs31("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
5797
+ /* @__PURE__ */ jsx32(
5798
+ "button",
5799
+ {
5800
+ type: "button",
5801
+ className: "b316-button",
5802
+ disabled: busy,
5803
+ onClick: () => void act(async () => {
5804
+ await client.billing.acceptRetentionOffer(token, step.cancellation.id);
5805
+ setStep({ kind: "idle" });
5806
+ }, "Could not apply the offer. Try again."),
5807
+ children: busy ? "Working\u2026" : "Accept offer and stay"
5808
+ }
5809
+ ),
5810
+ /* @__PURE__ */ jsx32(
5811
+ "button",
5812
+ {
5813
+ type: "button",
5814
+ className: "b316-button b316-button-secondary",
5815
+ disabled: busy,
5816
+ onClick: () => void act(async () => {
5817
+ await client.billing.confirmCancellation(token, step.cancellation.id);
5818
+ setStep({ kind: "idle" });
5819
+ }, "Could not cancel. Try again."),
5820
+ children: "No thanks, cancel"
5821
+ }
5822
+ )
5823
+ ] }),
5824
+ /* @__PURE__ */ jsxs31("p", { className: "b316-muted", children: [
5825
+ "If you cancel, you keep access until ",
5826
+ renews,
5827
+ "."
5828
+ ] })
5829
+ ] }) : step.kind === "survey" ? /* @__PURE__ */ jsxs31(
5830
+ "form",
5692
5831
  {
5832
+ style: { marginTop: 14 },
5833
+ onSubmit: (event) => {
5834
+ event.preventDefault();
5835
+ void act(async () => {
5836
+ const started = await client.billing.startCancellation(token, {
5837
+ reason,
5838
+ comment: comment.trim() || null
5839
+ });
5840
+ if (started.offer) {
5841
+ setStep({ kind: "offer", cancellation: { ...started, offer: started.offer } });
5842
+ return;
5843
+ }
5844
+ await client.billing.confirmCancellation(token, started.id);
5845
+ setStep({ kind: "idle" });
5846
+ }, "Could not cancel. Try again.");
5847
+ },
5848
+ children: [
5849
+ /* @__PURE__ */ jsxs31("p", { className: "b316-muted", children: [
5850
+ "You keep access until ",
5851
+ renews,
5852
+ ". It will not renew after that."
5853
+ ] }),
5854
+ /* @__PURE__ */ jsxs31("fieldset", { className: "b316-fieldset", children: [
5855
+ /* @__PURE__ */ jsx32("legend", { className: "b316-label", children: "Why are you leaving? (optional)" }),
5856
+ REASONS.map((option) => /* @__PURE__ */ jsxs31("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
5857
+ /* @__PURE__ */ jsx32(
5858
+ "input",
5859
+ {
5860
+ type: "radio",
5861
+ name: "b316-cancel-reason",
5862
+ value: option.value,
5863
+ checked: reason === option.value,
5864
+ onChange: () => setReason(option.value)
5865
+ }
5866
+ ),
5867
+ /* @__PURE__ */ jsx32("span", { children: option.label })
5868
+ ] }, option.value))
5869
+ ] }),
5870
+ /* @__PURE__ */ jsxs31("label", { className: "b316-field", children: [
5871
+ /* @__PURE__ */ jsx32("span", { className: "b316-label", children: "Anything else? (optional)" }),
5872
+ /* @__PURE__ */ jsx32(
5873
+ "textarea",
5874
+ {
5875
+ className: "b316-input",
5876
+ rows: 3,
5877
+ maxLength: 2e3,
5878
+ value: comment,
5879
+ onChange: (event) => setComment(event.target.value)
5880
+ }
5881
+ )
5882
+ ] }),
5883
+ /* @__PURE__ */ jsxs31("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
5884
+ /* @__PURE__ */ jsx32("button", { type: "submit", className: "b316-button b316-button-secondary", disabled: busy, children: busy ? "Working\u2026" : "Cancel subscription" }),
5885
+ /* @__PURE__ */ jsxs31(
5886
+ "button",
5887
+ {
5888
+ type: "button",
5889
+ className: "b316-button",
5890
+ disabled: busy,
5891
+ onClick: () => setStep({ kind: "idle" }),
5892
+ children: [
5893
+ "Keep ",
5894
+ subscription.planVersion.plan.name
5895
+ ]
5896
+ }
5897
+ )
5898
+ ] })
5899
+ ]
5900
+ }
5901
+ ) : /* @__PURE__ */ jsx32("div", { style: { marginTop: 14 }, children: /* @__PURE__ */ jsx32(
5902
+ "button",
5903
+ {
5904
+ type: "button",
5693
5905
  className: "b316-button b316-button-secondary",
5694
- confirmLabel: `Cancel at the end of the period (${renews})`,
5695
5906
  disabled: busy,
5696
- onConfirm: () => (
5697
- // Cancels at period end: the user paid for the period they
5698
- // are in, and ending it now would forfeit it.
5699
- act(() => client.billing.cancel(token), "Could not cancel. Try again.")
5700
- ),
5701
- children: busy ? "Working\u2026" : "Cancel subscription"
5907
+ onClick: () => {
5908
+ setReason(null);
5909
+ setComment("");
5910
+ setStep({ kind: "survey" });
5911
+ },
5912
+ children: "Cancel subscription"
5702
5913
  }
5703
5914
  ) })
5704
5915
  ] });
@@ -5709,7 +5920,7 @@ import { useCallback as useCallback12, useEffect as useEffect26, useState as use
5709
5920
 
5710
5921
  // src/CreditBalances.tsx
5711
5922
  import { useEffect as useEffect23, useState as useState31 } from "react";
5712
- import { Fragment as Fragment9, jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
5923
+ import { Fragment as Fragment9, jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
5713
5924
  function units(value) {
5714
5925
  return value === null ? "Unlimited" : Number(value).toLocaleString("en");
5715
5926
  }
@@ -5801,33 +6012,33 @@ function Feature({
5801
6012
  setBusy(false);
5802
6013
  }
5803
6014
  };
5804
- return /* @__PURE__ */ jsxs31("div", { className: "b316-card b316-credit-balance", children: [
5805
- /* @__PURE__ */ jsx32("div", { className: "b316-label", children: feature.featureName }),
5806
- /* @__PURE__ */ jsxs31("div", { children: [
5807
- /* @__PURE__ */ jsx32("strong", { children: units(feature.remaining) }),
6015
+ return /* @__PURE__ */ jsxs32("div", { className: "b316-card b316-credit-balance", children: [
6016
+ /* @__PURE__ */ jsx33("div", { className: "b316-label", children: feature.featureName }),
6017
+ /* @__PURE__ */ jsxs32("div", { children: [
6018
+ /* @__PURE__ */ jsx33("strong", { children: units(feature.remaining) }),
5808
6019
  unit,
5809
6020
  " left"
5810
6021
  ] }),
5811
- /* @__PURE__ */ jsxs31("div", { className: "b316-muted", children: [
6022
+ /* @__PURE__ */ jsxs32("div", { className: "b316-muted", children: [
5812
6023
  feature.allowance === null ? "Unlimited allowance" : `${units(feature.allowanceRemaining)} of ${units(feature.allowance)} included this period`,
5813
6024
  " ",
5814
6025
  "\xB7 ",
5815
6026
  units(feature.purchasedRemaining),
5816
6027
  " purchased"
5817
6028
  ] }),
5818
- warning && !managed ? /* @__PURE__ */ jsx32("div", { className: "b316-error", role: "alert", children: warning }) : null,
5819
- error ? /* @__PURE__ */ jsx32("div", { className: "b316-error", role: "alert", children: error }) : null,
5820
- saved ? /* @__PURE__ */ jsx32("div", { className: "b316-notice", role: "status", children: saved }) : null,
5821
- managed || feature.packs.length === 0 ? null : /* @__PURE__ */ jsxs31(Fragment9, { children: [
5822
- /* @__PURE__ */ jsxs31("div", { className: "b316-row", style: { marginTop: 12 }, children: [
5823
- /* @__PURE__ */ jsx32(
6029
+ warning && !managed ? /* @__PURE__ */ jsx33("div", { className: "b316-error", role: "alert", children: warning }) : null,
6030
+ error ? /* @__PURE__ */ jsx33("div", { className: "b316-error", role: "alert", children: error }) : null,
6031
+ saved ? /* @__PURE__ */ jsx33("div", { className: "b316-notice", role: "status", children: saved }) : null,
6032
+ managed || feature.packs.length === 0 ? null : /* @__PURE__ */ jsxs32(Fragment9, { children: [
6033
+ /* @__PURE__ */ jsxs32("div", { className: "b316-row", style: { marginTop: 12 }, children: [
6034
+ /* @__PURE__ */ jsx33(
5824
6035
  "select",
5825
6036
  {
5826
6037
  className: "b316-input",
5827
6038
  "aria-label": "Pack to buy",
5828
6039
  value: pack,
5829
6040
  onChange: (event) => setPack(event.target.value),
5830
- children: feature.packs.map((option) => /* @__PURE__ */ jsxs31("option", { value: option.id, children: [
6041
+ children: feature.packs.map((option) => /* @__PURE__ */ jsxs32("option", { value: option.id, children: [
5831
6042
  option.name,
5832
6043
  " \u2014 ",
5833
6044
  units(option.units),
@@ -5836,7 +6047,7 @@ function Feature({
5836
6047
  ] }, option.id))
5837
6048
  }
5838
6049
  ),
5839
- /* @__PURE__ */ jsx32(
6050
+ /* @__PURE__ */ jsx33(
5840
6051
  "button",
5841
6052
  {
5842
6053
  type: "button",
@@ -5847,19 +6058,19 @@ function Feature({
5847
6058
  }
5848
6059
  )
5849
6060
  ] }),
5850
- /* @__PURE__ */ jsxs31("form", { onSubmit: save, style: { marginTop: 16 }, children: [
5851
- /* @__PURE__ */ jsxs31("label", { className: "b316-checkbox", children: [
5852
- /* @__PURE__ */ jsx32("input", { type: "checkbox", name: "enabled", defaultChecked: setting?.enabled ?? false }),
6061
+ /* @__PURE__ */ jsxs32("form", { onSubmit: save, style: { marginTop: 16 }, children: [
6062
+ /* @__PURE__ */ jsxs32("label", { className: "b316-checkbox", children: [
6063
+ /* @__PURE__ */ jsx33("input", { type: "checkbox", name: "enabled", defaultChecked: setting?.enabled ?? false }),
5853
6064
  " ",
5854
6065
  "Buy credits automatically when my balance runs low"
5855
6066
  ] }),
5856
- /* @__PURE__ */ jsxs31("label", { className: "b316-field", children: [
5857
- /* @__PURE__ */ jsxs31("span", { className: "b316-label", children: [
6067
+ /* @__PURE__ */ jsxs32("label", { className: "b316-field", children: [
6068
+ /* @__PURE__ */ jsxs32("span", { className: "b316-label", children: [
5858
6069
  "When fewer than this many",
5859
6070
  unit,
5860
6071
  " are left"
5861
6072
  ] }),
5862
- /* @__PURE__ */ jsx32(
6073
+ /* @__PURE__ */ jsx33(
5863
6074
  "input",
5864
6075
  {
5865
6076
  className: "b316-input",
@@ -5870,21 +6081,21 @@ function Feature({
5870
6081
  }
5871
6082
  )
5872
6083
  ] }),
5873
- /* @__PURE__ */ jsxs31("label", { className: "b316-field", children: [
5874
- /* @__PURE__ */ jsx32("span", { className: "b316-label", children: "Buy" }),
5875
- /* @__PURE__ */ jsx32(
6084
+ /* @__PURE__ */ jsxs32("label", { className: "b316-field", children: [
6085
+ /* @__PURE__ */ jsx33("span", { className: "b316-label", children: "Buy" }),
6086
+ /* @__PURE__ */ jsx33(
5876
6087
  "select",
5877
6088
  {
5878
6089
  className: "b316-input",
5879
6090
  name: "creditPackId",
5880
6091
  defaultValue: setting?.creditPackId ?? feature.packs[0]?.id,
5881
- children: feature.packs.map((option) => /* @__PURE__ */ jsx32("option", { value: option.id, children: option.name }, option.id))
6092
+ children: feature.packs.map((option) => /* @__PURE__ */ jsx33("option", { value: option.id, children: option.name }, option.id))
5882
6093
  }
5883
6094
  )
5884
6095
  ] }),
5885
- /* @__PURE__ */ jsxs31("label", { className: "b316-field", children: [
5886
- /* @__PURE__ */ jsx32("span", { className: "b316-label", children: "At most this many times a month" }),
5887
- /* @__PURE__ */ jsx32(
6096
+ /* @__PURE__ */ jsxs32("label", { className: "b316-field", children: [
6097
+ /* @__PURE__ */ jsx33("span", { className: "b316-label", children: "At most this many times a month" }),
6098
+ /* @__PURE__ */ jsx33(
5888
6099
  "input",
5889
6100
  {
5890
6101
  className: "b316-input",
@@ -5894,13 +6105,13 @@ function Feature({
5894
6105
  }
5895
6106
  )
5896
6107
  ] }),
5897
- /* @__PURE__ */ jsxs31("label", { className: "b316-field", children: [
5898
- /* @__PURE__ */ jsxs31("span", { className: "b316-label", children: [
6108
+ /* @__PURE__ */ jsxs32("label", { className: "b316-field", children: [
6109
+ /* @__PURE__ */ jsxs32("span", { className: "b316-label", children: [
5899
6110
  "Spending at most (",
5900
6111
  setting?.currency ?? feature.packs[0]?.currency ?? "USD",
5901
6112
  ") a month"
5902
6113
  ] }),
5903
- /* @__PURE__ */ jsx32(
6114
+ /* @__PURE__ */ jsx33(
5904
6115
  "input",
5905
6116
  {
5906
6117
  className: "b316-input",
@@ -5910,7 +6121,7 @@ function Feature({
5910
6121
  }
5911
6122
  )
5912
6123
  ] }),
5913
- /* @__PURE__ */ jsx32("button", { type: "submit", className: "b316-button", disabled: busy, children: "Save auto-recharge" })
6124
+ /* @__PURE__ */ jsx33("button", { type: "submit", className: "b316-button", disabled: busy, children: "Save auto-recharge" })
5914
6125
  ] })
5915
6126
  ] })
5916
6127
  ] });
@@ -5932,24 +6143,24 @@ function CreditBalances({ onChange, className, style }) {
5932
6143
  cancelled = true;
5933
6144
  };
5934
6145
  }, [client, token, version]);
5935
- const wrap = (content) => /* @__PURE__ */ jsx32("div", { className: cls("b316-credit-balances", className), style, children: content });
6146
+ const wrap = (content) => /* @__PURE__ */ jsx33("div", { className: cls("b316-credit-balances", className), style, children: content });
5936
6147
  if (sessionLoading || !token || state.kind === "loading") return null;
5937
6148
  if (state.kind === "error") {
5938
6149
  return wrap(
5939
- /* @__PURE__ */ jsx32("div", { className: "b316-card", children: /* @__PURE__ */ jsx32("div", { className: "b316-error", role: "alert", children: "Could not load your credits." }) })
6150
+ /* @__PURE__ */ jsx33("div", { className: "b316-card", children: /* @__PURE__ */ jsx33("div", { className: "b316-error", role: "alert", children: "Could not load your credits." }) })
5940
6151
  );
5941
6152
  }
5942
6153
  const { credits } = state;
5943
6154
  if (credits.features.length === 0) return null;
5944
6155
  return wrap(
5945
- /* @__PURE__ */ jsxs31(Fragment9, { children: [
5946
- credits.managedBy ? /* @__PURE__ */ jsxs31("p", { className: "b316-muted", children: [
6156
+ /* @__PURE__ */ jsxs32(Fragment9, { children: [
6157
+ credits.managedBy ? /* @__PURE__ */ jsxs32("p", { className: "b316-muted", children: [
5947
6158
  "Credits for this account come from",
5948
6159
  " ",
5949
6160
  credits.managedBy.name ?? "the organization that manages it",
5950
6161
  ", which manages them."
5951
6162
  ] }) : null,
5952
- credits.features.map((feature) => /* @__PURE__ */ jsx32(
6163
+ credits.features.map((feature) => /* @__PURE__ */ jsx33(
5953
6164
  Feature,
5954
6165
  {
5955
6166
  feature,
@@ -5967,7 +6178,7 @@ function CreditBalances({ onChange, className, style }) {
5967
6178
 
5968
6179
  // src/PaymentMethod.tsx
5969
6180
  import { useEffect as useEffect24, useState as useState32 } from "react";
5970
- import { Fragment as Fragment10, jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
6181
+ import { Fragment as Fragment10, jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
5971
6182
  function brandName(brand) {
5972
6183
  if (!brand) return "Card";
5973
6184
  return brand.charAt(0).toUpperCase() + brand.slice(1);
@@ -5994,7 +6205,7 @@ function PaymentMethod({ returnUrl, className, style }) {
5994
6205
  cancelled = true;
5995
6206
  };
5996
6207
  }, [client, token, version]);
5997
- const wrap = (content) => /* @__PURE__ */ jsx33("div", { className: cls("b316-card b316-payment-method", className), style, children: content });
6208
+ const wrap = (content) => /* @__PURE__ */ jsx34("div", { className: cls("b316-card b316-payment-method", className), style, children: content });
5998
6209
  if (sessionLoading) return wrap("Loading\u2026");
5999
6210
  if (!token) return wrap("Sign in to manage your payment method.");
6000
6211
  switch (state.kind) {
@@ -6002,11 +6213,11 @@ function PaymentMethod({ returnUrl, className, style }) {
6002
6213
  return wrap("Loading\u2026");
6003
6214
  case "error":
6004
6215
  return wrap(
6005
- /* @__PURE__ */ jsx33("div", { className: "b316-error", role: "alert", children: "Could not load your payment method." })
6216
+ /* @__PURE__ */ jsx34("div", { className: "b316-error", role: "alert", children: "Could not load your payment method." })
6006
6217
  );
6007
6218
  case "managed":
6008
6219
  return wrap(
6009
- /* @__PURE__ */ jsx33("p", { className: "b316-muted", children: "Your plan is paid for by the organization that manages it." })
6220
+ /* @__PURE__ */ jsx34("p", { className: "b316-muted", children: "Your plan is paid for by the organization that manages it." })
6010
6221
  );
6011
6222
  }
6012
6223
  const card = state.cards.find((saved) => saved.isDefault) ?? null;
@@ -6025,31 +6236,31 @@ function PaymentMethod({ returnUrl, className, style }) {
6025
6236
  }
6026
6237
  };
6027
6238
  return wrap(
6028
- /* @__PURE__ */ jsxs32(Fragment10, { children: [
6029
- /* @__PURE__ */ jsx33("div", { className: "b316-label", children: "Payment method" }),
6030
- card ? /* @__PURE__ */ jsxs32("div", { children: [
6031
- /* @__PURE__ */ jsxs32("div", { children: [
6239
+ /* @__PURE__ */ jsxs33(Fragment10, { children: [
6240
+ /* @__PURE__ */ jsx34("div", { className: "b316-label", children: "Payment method" }),
6241
+ card ? /* @__PURE__ */ jsxs33("div", { children: [
6242
+ /* @__PURE__ */ jsxs33("div", { children: [
6032
6243
  brandName(card.brand),
6033
6244
  " ending ",
6034
6245
  card.last4 ?? "????"
6035
6246
  ] }),
6036
- card.expMonth && card.expYear ? /* @__PURE__ */ jsxs32("div", { className: "b316-muted", children: [
6247
+ card.expMonth && card.expYear ? /* @__PURE__ */ jsxs33("div", { className: "b316-muted", children: [
6037
6248
  "Expires ",
6038
6249
  String(card.expMonth).padStart(2, "0"),
6039
6250
  "/",
6040
6251
  card.expYear
6041
6252
  ] }) : null
6042
- ] }) : /* @__PURE__ */ jsx33("p", { className: "b316-muted", children: "No card on file." }),
6043
- others.length > 0 ? /* @__PURE__ */ jsxs32("div", { style: { marginTop: 12 }, children: [
6044
- /* @__PURE__ */ jsx33("div", { className: "b316-label", children: "Other saved cards" }),
6045
- others.map((saved) => /* @__PURE__ */ jsxs32("div", { className: "b316-row", style: { marginTop: 6 }, children: [
6046
- /* @__PURE__ */ jsxs32("span", { children: [
6253
+ ] }) : /* @__PURE__ */ jsx34("p", { className: "b316-muted", children: "No card on file." }),
6254
+ others.length > 0 ? /* @__PURE__ */ jsxs33("div", { style: { marginTop: 12 }, children: [
6255
+ /* @__PURE__ */ jsx34("div", { className: "b316-label", children: "Other saved cards" }),
6256
+ others.map((saved) => /* @__PURE__ */ jsxs33("div", { className: "b316-row", style: { marginTop: 6 }, children: [
6257
+ /* @__PURE__ */ jsxs33("span", { children: [
6047
6258
  brandName(saved.brand),
6048
6259
  " ending ",
6049
6260
  saved.last4 ?? "????"
6050
6261
  ] }),
6051
- /* @__PURE__ */ jsxs32("span", { children: [
6052
- /* @__PURE__ */ jsx33(
6262
+ /* @__PURE__ */ jsxs33("span", { children: [
6263
+ /* @__PURE__ */ jsx34(
6053
6264
  "button",
6054
6265
  {
6055
6266
  type: "button",
@@ -6063,7 +6274,7 @@ function PaymentMethod({ returnUrl, className, style }) {
6063
6274
  }
6064
6275
  ),
6065
6276
  " ",
6066
- /* @__PURE__ */ jsx33(
6277
+ /* @__PURE__ */ jsx34(
6067
6278
  "button",
6068
6279
  {
6069
6280
  type: "button",
@@ -6079,8 +6290,8 @@ function PaymentMethod({ returnUrl, className, style }) {
6079
6290
  ] })
6080
6291
  ] }, saved.id))
6081
6292
  ] }) : null,
6082
- error ? /* @__PURE__ */ jsx33("div", { className: "b316-error", role: "alert", children: error }) : null,
6083
- /* @__PURE__ */ jsx33(
6293
+ error ? /* @__PURE__ */ jsx34("div", { className: "b316-error", role: "alert", children: error }) : null,
6294
+ /* @__PURE__ */ jsx34(
6084
6295
  "button",
6085
6296
  {
6086
6297
  type: "button",
@@ -6110,7 +6321,7 @@ function PaymentMethod({ returnUrl, className, style }) {
6110
6321
 
6111
6322
  // src/PlanChangeReview.tsx
6112
6323
  import { useCallback as useCallback11, useEffect as useEffect25, useState as useState33 } from "react";
6113
- import { Fragment as Fragment11, jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
6324
+ import { Fragment as Fragment11, jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
6114
6325
  function money5(amount, currency) {
6115
6326
  if (amount === null) return "\u2014";
6116
6327
  const value = Number(amount);
@@ -6200,12 +6411,12 @@ function PlanChangeReview({
6200
6411
  setError("Cards cannot be added here right now.");
6201
6412
  }
6202
6413
  }, [client, token, onNeedsCard]);
6203
- const card = (content) => /* @__PURE__ */ jsx34("div", { className: cls("b316-card b316-plan-review", className), style, children: content });
6414
+ const card = (content) => /* @__PURE__ */ jsx35("div", { className: cls("b316-card b316-plan-review", className), style, children: content });
6204
6415
  if (error && !preview) {
6205
6416
  return card(
6206
- /* @__PURE__ */ jsxs33(Fragment11, { children: [
6207
- /* @__PURE__ */ jsx34("div", { className: "b316-error", role: "alert", children: error }),
6208
- onCancel ? /* @__PURE__ */ jsx34("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: "Back" }) : null
6417
+ /* @__PURE__ */ jsxs34(Fragment11, { children: [
6418
+ /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: error }),
6419
+ onCancel ? /* @__PURE__ */ jsx35("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: "Back" }) : null
6209
6420
  ] })
6210
6421
  );
6211
6422
  }
@@ -6218,26 +6429,26 @@ function PlanChangeReview({
6218
6429
  const otherReason = preview.timings[other]?.reason ?? null;
6219
6430
  const changes = preview.entitlements.filter((change) => change.change !== "UNCHANGED");
6220
6431
  return card(
6221
- /* @__PURE__ */ jsxs33(Fragment11, { children: [
6222
- /* @__PURE__ */ jsxs33("div", { className: "b316-plan-name", children: [
6432
+ /* @__PURE__ */ jsxs34(Fragment11, { children: [
6433
+ /* @__PURE__ */ jsxs34("div", { className: "b316-plan-name", children: [
6223
6434
  "Change to ",
6224
6435
  to.planName
6225
6436
  ] }),
6226
- /* @__PURE__ */ jsxs33("div", { className: "b316-muted", children: [
6437
+ /* @__PURE__ */ jsxs34("div", { className: "b316-muted", children: [
6227
6438
  "From ",
6228
6439
  from.planName
6229
6440
  ] }),
6230
- error ? /* @__PURE__ */ jsx34("div", { className: "b316-error", role: "alert", children: error }) : null,
6231
- changes.length === 0 ? /* @__PURE__ */ jsx34("p", { className: "b316-muted", children: "Every feature stays the same." }) : /* @__PURE__ */ jsxs33("table", { className: "b316-review-table", children: [
6232
- /* @__PURE__ */ jsx34("thead", { children: /* @__PURE__ */ jsxs33("tr", { children: [
6233
- /* @__PURE__ */ jsx34("th", { children: "Feature" }),
6234
- /* @__PURE__ */ jsx34("th", { children: from.planName }),
6235
- /* @__PURE__ */ jsx34("th", { children: to.planName })
6441
+ error ? /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: error }) : null,
6442
+ changes.length === 0 ? /* @__PURE__ */ jsx35("p", { className: "b316-muted", children: "Every feature stays the same." }) : /* @__PURE__ */ jsxs34("table", { className: "b316-review-table", children: [
6443
+ /* @__PURE__ */ jsx35("thead", { children: /* @__PURE__ */ jsxs34("tr", { children: [
6444
+ /* @__PURE__ */ jsx35("th", { children: "Feature" }),
6445
+ /* @__PURE__ */ jsx35("th", { children: from.planName }),
6446
+ /* @__PURE__ */ jsx35("th", { children: to.planName })
6236
6447
  ] }) }),
6237
- /* @__PURE__ */ jsx34("tbody", { children: changes.map((change) => /* @__PURE__ */ jsxs33("tr", { children: [
6238
- /* @__PURE__ */ jsx34("td", { children: change.featureName }),
6239
- /* @__PURE__ */ jsx34("td", { children: limitText(change.before, change.type) }),
6240
- /* @__PURE__ */ jsx34(
6448
+ /* @__PURE__ */ jsx35("tbody", { children: changes.map((change) => /* @__PURE__ */ jsxs34("tr", { children: [
6449
+ /* @__PURE__ */ jsx35("td", { children: change.featureName }),
6450
+ /* @__PURE__ */ jsx35("td", { children: limitText(change.before, change.type) }),
6451
+ /* @__PURE__ */ jsx35(
6241
6452
  "td",
6242
6453
  {
6243
6454
  className: change.change === "GAINED" || change.change === "INCREASED" ? "b316-review-gain" : "b316-review-loss",
@@ -6246,40 +6457,40 @@ function PlanChangeReview({
6246
6457
  )
6247
6458
  ] }, change.featureId)) })
6248
6459
  ] }),
6249
- preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */ jsxs33("p", { children: [
6460
+ preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */ jsxs34("p", { children: [
6250
6461
  "The change happens now. Your trial carries on until ",
6251
6462
  day4(now.trialEndsAt),
6252
6463
  ", and nothing is charged before then."
6253
- ] }) : /* @__PURE__ */ jsxs33("div", { children: [
6254
- Number(now.credit) > 0 ? /* @__PURE__ */ jsxs33("div", { className: "b316-row", children: [
6255
- /* @__PURE__ */ jsxs33("span", { className: "b316-muted", children: [
6464
+ ] }) : /* @__PURE__ */ jsxs34("div", { children: [
6465
+ Number(now.credit) > 0 ? /* @__PURE__ */ jsxs34("div", { className: "b316-row", children: [
6466
+ /* @__PURE__ */ jsxs34("span", { className: "b316-muted", children: [
6256
6467
  "Credit for the unused part of ",
6257
6468
  from.planName
6258
6469
  ] }),
6259
- /* @__PURE__ */ jsxs33("span", { className: "b316-num", children: [
6470
+ /* @__PURE__ */ jsxs34("span", { className: "b316-num", children: [
6260
6471
  "\u2212",
6261
6472
  money5(now.credit, from.currency)
6262
6473
  ] })
6263
6474
  ] }) : null,
6264
- Number(now.closingUsage) > 0 ? /* @__PURE__ */ jsxs33("div", { className: "b316-row", children: [
6265
- /* @__PURE__ */ jsx34("span", { className: "b316-muted", children: "Usage so far this period" }),
6266
- /* @__PURE__ */ jsx34("span", { className: "b316-num", children: money5(now.closingUsage, from.currency) })
6475
+ Number(now.closingUsage) > 0 ? /* @__PURE__ */ jsxs34("div", { className: "b316-row", children: [
6476
+ /* @__PURE__ */ jsx35("span", { className: "b316-muted", children: "Usage so far this period" }),
6477
+ /* @__PURE__ */ jsx35("span", { className: "b316-num", children: money5(now.closingUsage, from.currency) })
6267
6478
  ] }) : null,
6268
- /* @__PURE__ */ jsxs33("div", { className: "b316-row", children: [
6269
- /* @__PURE__ */ jsxs33("span", { className: "b316-muted", children: [
6479
+ /* @__PURE__ */ jsxs34("div", { className: "b316-row", children: [
6480
+ /* @__PURE__ */ jsxs34("span", { className: "b316-muted", children: [
6270
6481
  to.planName,
6271
6482
  ", ",
6272
6483
  day4(now.newPeriod.start),
6273
6484
  " \u2013 ",
6274
6485
  day4(now.newPeriod.end)
6275
6486
  ] }),
6276
- /* @__PURE__ */ jsx34("span", { className: "b316-num", children: money5(now.newPeriodCharge, to.currency) })
6487
+ /* @__PURE__ */ jsx35("span", { className: "b316-num", children: money5(now.newPeriodCharge, to.currency) })
6277
6488
  ] }),
6278
- now.net !== null ? /* @__PURE__ */ jsxs33("div", { className: "b316-row b316-invoice-total", children: [
6279
- /* @__PURE__ */ jsx34("span", { children: "Due now" }),
6280
- /* @__PURE__ */ jsx34("span", { className: "b316-num", children: money5(now.net, to.currency) })
6489
+ now.net !== null ? /* @__PURE__ */ jsxs34("div", { className: "b316-row b316-invoice-total", children: [
6490
+ /* @__PURE__ */ jsx35("span", { children: "Due now" }),
6491
+ /* @__PURE__ */ jsx35("span", { className: "b316-num", children: money5(now.net, to.currency) })
6281
6492
  ] }) : null
6282
- ] }) : /* @__PURE__ */ jsxs33("p", { children: [
6493
+ ] }) : /* @__PURE__ */ jsxs34("p", { children: [
6283
6494
  "You keep ",
6284
6495
  from.planName,
6285
6496
  " until ",
@@ -6292,7 +6503,7 @@ function PlanChangeReview({
6292
6503
  preview.atPeriodEnd.nextInvoice.currency
6293
6504
  )}.` : ""
6294
6505
  ] }),
6295
- otherOpen ? /* @__PURE__ */ jsx34(
6506
+ otherOpen ? /* @__PURE__ */ jsx35(
6296
6507
  "button",
6297
6508
  {
6298
6509
  type: "button",
@@ -6303,12 +6514,12 @@ function PlanChangeReview({
6303
6514
  },
6304
6515
  children: other === "NOW" ? "Change now instead" : "Wait until the end of the period instead"
6305
6516
  }
6306
- ) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */ jsx34("p", { className: "b316-muted", children: TIMING_CLOSED[otherReason] }) : null,
6307
- needsCard ? /* @__PURE__ */ jsxs33("div", { className: "b316-notice", role: "status", children: [
6517
+ ) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */ jsx35("p", { className: "b316-muted", children: TIMING_CLOSED[otherReason] }) : null,
6518
+ needsCard ? /* @__PURE__ */ jsxs34("div", { className: "b316-notice", role: "status", children: [
6308
6519
  "A card is needed for a change that is charged now.",
6309
- /* @__PURE__ */ jsx34("div", { className: "b316-review-actions", children: /* @__PURE__ */ jsx34("button", { type: "button", className: "b316-button", onClick: () => void addCard(), children: "Add a card" }) })
6310
- ] }) : /* @__PURE__ */ jsxs33("div", { className: "b316-review-actions", children: [
6311
- /* @__PURE__ */ jsx34(
6520
+ /* @__PURE__ */ jsx35("div", { className: "b316-review-actions", children: /* @__PURE__ */ jsx35("button", { type: "button", className: "b316-button", onClick: () => void addCard(), children: "Add a card" }) })
6521
+ ] }) : /* @__PURE__ */ jsxs34("div", { className: "b316-review-actions", children: [
6522
+ /* @__PURE__ */ jsx35(
6312
6523
  "button",
6313
6524
  {
6314
6525
  type: "button",
@@ -6318,7 +6529,7 @@ function PlanChangeReview({
6318
6529
  children: busy ? "Working\u2026" : preview.timing === "NOW" ? `Change to ${to.planName} now` : `Schedule ${to.planName}`
6319
6530
  }
6320
6531
  ),
6321
- onCancel ? /* @__PURE__ */ jsxs33("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: [
6532
+ onCancel ? /* @__PURE__ */ jsxs34("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: [
6322
6533
  "Keep ",
6323
6534
  from.planName
6324
6535
  ] }) : null
@@ -6328,7 +6539,7 @@ function PlanChangeReview({
6328
6539
  }
6329
6540
 
6330
6541
  // src/BillingPortal.tsx
6331
- import { Fragment as Fragment12, jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
6542
+ import { Fragment as Fragment12, jsx as jsx36, jsxs as jsxs35 } from "react/jsx-runtime";
6332
6543
  function BillingPortal({
6333
6544
  returnUrl,
6334
6545
  featuredPlanKey,
@@ -6366,24 +6577,24 @@ function BillingPortal({
6366
6577
  setNotice(null);
6367
6578
  setVersion((value) => value + 1);
6368
6579
  }, []);
6369
- const shell = (content) => /* @__PURE__ */ jsx35("div", { className: cls("b316-billing-portal", className), style, children: content });
6370
- if (sessionLoading) return shell(/* @__PURE__ */ jsx35("div", { className: "b316-card", children: "Loading\u2026" }));
6371
- if (!token) return shell(/* @__PURE__ */ jsx35("div", { className: "b316-card", children: "Sign in to manage your billing." }));
6580
+ const shell = (content) => /* @__PURE__ */ jsx36("div", { className: cls("b316-billing-portal", className), style, children: content });
6581
+ if (sessionLoading) return shell(/* @__PURE__ */ jsx36("div", { className: "b316-card", children: "Loading\u2026" }));
6582
+ if (!token) return shell(/* @__PURE__ */ jsx36("div", { className: "b316-card", children: "Sign in to manage your billing." }));
6372
6583
  if (failed) {
6373
6584
  return shell(
6374
- /* @__PURE__ */ jsx35("div", { className: "b316-card", children: /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: "Could not load your billing." }) })
6585
+ /* @__PURE__ */ jsx36("div", { className: "b316-card", children: /* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: "Could not load your billing." }) })
6375
6586
  );
6376
6587
  }
6377
- if (!overview) return shell(/* @__PURE__ */ jsx35("div", { className: "b316-card", children: "Loading\u2026" }));
6588
+ if (!overview) return shell(/* @__PURE__ */ jsx36("div", { className: "b316-card", children: "Loading\u2026" }));
6378
6589
  const { subscription, managedBy, quantityPriced } = overview;
6379
6590
  const canChange = Boolean(subscription) && !managedBy;
6380
6591
  return shell(
6381
- /* @__PURE__ */ jsxs34(Fragment12, { children: [
6382
- notice ? /* @__PURE__ */ jsx35("div", { className: "b316-card b316-notice", role: "status", children: notice }) : null,
6383
- /* @__PURE__ */ jsx35(SubscriptionManager, { onChange: refresh }, `plan-${version}`),
6384
- canChange ? /* @__PURE__ */ jsx35(UpcomingInvoice, {}, `next-${version}`) : null,
6385
- canChange && quantityPriced ? /* @__PURE__ */ jsx35(SeatManager, { unitLabel, onChange: refresh }, `seats-${version}`) : null,
6386
- reviewing ? /* @__PURE__ */ jsx35(
6592
+ /* @__PURE__ */ jsxs35(Fragment12, { children: [
6593
+ notice ? /* @__PURE__ */ jsx36("div", { className: "b316-card b316-notice", role: "status", children: notice }) : null,
6594
+ /* @__PURE__ */ jsx36(SubscriptionManager, { onChange: refresh }, `plan-${version}`),
6595
+ canChange ? /* @__PURE__ */ jsx36(UpcomingInvoice, {}, `next-${version}`) : null,
6596
+ canChange && quantityPriced ? /* @__PURE__ */ jsx36(SeatManager, { unitLabel, onChange: refresh }, `seats-${version}`) : null,
6597
+ reviewing ? /* @__PURE__ */ jsx36(
6387
6598
  PlanChangeReview,
6388
6599
  {
6389
6600
  planVersionId: reviewing,
@@ -6396,9 +6607,9 @@ function BillingPortal({
6396
6607
  );
6397
6608
  }
6398
6609
  }
6399
- ) : /* @__PURE__ */ jsxs34("section", { children: [
6400
- /* @__PURE__ */ jsx35("h2", { className: "b316-billing-portal-section-title", children: subscription ? "Change plan" : "Choose a plan" }),
6401
- /* @__PURE__ */ jsx35(
6610
+ ) : /* @__PURE__ */ jsxs35("section", { children: [
6611
+ /* @__PURE__ */ jsx36("h2", { className: "b316-billing-portal-section-title", children: subscription ? "Change plan" : "Choose a plan" }),
6612
+ /* @__PURE__ */ jsx36(
6402
6613
  PricingTable,
6403
6614
  {
6404
6615
  featuredPlanKey,
@@ -6410,17 +6621,17 @@ function BillingPortal({
6410
6621
  `plans-${version}`
6411
6622
  )
6412
6623
  ] }),
6413
- /* @__PURE__ */ jsx35(CreditBalances, {}, `credits-${version}`),
6414
- managedBy ? null : /* @__PURE__ */ jsx35(PaymentMethod, { returnUrl }, `card-${version}`),
6415
- /* @__PURE__ */ jsx35(Invoices, {}, `invoices-${version}`),
6416
- billingDetails === void 0 ? /* @__PURE__ */ jsx35(BillingDetailsForm, {}, `details-${version}`) : billingDetails
6624
+ /* @__PURE__ */ jsx36(CreditBalances, {}, `credits-${version}`),
6625
+ managedBy ? null : /* @__PURE__ */ jsx36(PaymentMethod, { returnUrl }, `card-${version}`),
6626
+ /* @__PURE__ */ jsx36(Invoices, {}, `invoices-${version}`),
6627
+ billingDetails === void 0 ? /* @__PURE__ */ jsx36(BillingDetailsForm, {}, `details-${version}`) : billingDetails
6417
6628
  ] })
6418
6629
  );
6419
6630
  }
6420
6631
 
6421
6632
  // src/ApiKeyManager.tsx
6422
6633
  import { useCallback as useCallback13, useEffect as useEffect27, useState as useState35 } from "react";
6423
- import { jsx as jsx36, jsxs as jsxs35 } from "react/jsx-runtime";
6634
+ import { jsx as jsx37, jsxs as jsxs36 } from "react/jsx-runtime";
6424
6635
  function duration(seconds) {
6425
6636
  if (seconds % 3600 === 0) {
6426
6637
  return `${seconds / 3600}h`;
@@ -6472,16 +6683,16 @@ function ApiKeyManager({
6472
6683
  void load();
6473
6684
  }, [load]);
6474
6685
  if (sessionLoading || loading) {
6475
- return /* @__PURE__ */ jsx36("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
6686
+ return /* @__PURE__ */ jsx37("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
6476
6687
  }
6477
6688
  if (!token) {
6478
- return /* @__PURE__ */ jsx36("div", { className: cls("b316-card", className), style, children: "Sign in to manage your API keys." });
6689
+ return /* @__PURE__ */ jsx37("div", { className: cls("b316-card", className), style, children: "Sign in to manage your API keys." });
6479
6690
  }
6480
6691
  if (error) {
6481
- return /* @__PURE__ */ jsx36("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: error }) });
6692
+ return /* @__PURE__ */ jsx37("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx37("div", { className: "b316-error", role: "alert", children: error }) });
6482
6693
  }
6483
6694
  if (resources.length === 0) {
6484
- return /* @__PURE__ */ jsx36("div", { className: cls("b316-card", className), style, children: "There are no APIs available to your account." });
6695
+ return /* @__PURE__ */ jsx37("div", { className: cls("b316-card", className), style, children: "There are no APIs available to your account." });
6485
6696
  }
6486
6697
  const resource = resources.find((item) => item.id === resourceId) ?? resources[0];
6487
6698
  const reset = () => {
@@ -6490,37 +6701,37 @@ function ApiKeyManager({
6490
6701
  setChosen([]);
6491
6702
  setIssued(null);
6492
6703
  };
6493
- return /* @__PURE__ */ jsxs35("div", { className: cls("b316-card", className), style, children: [
6494
- error ? /* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: error }) : null,
6495
- resources.length > 1 ? /* @__PURE__ */ jsx36(
6704
+ return /* @__PURE__ */ jsxs36("div", { className: cls("b316-card", className), style, children: [
6705
+ error ? /* @__PURE__ */ jsx37("div", { className: "b316-error", role: "alert", children: error }) : null,
6706
+ resources.length > 1 ? /* @__PURE__ */ jsx37(
6496
6707
  "select",
6497
6708
  {
6498
6709
  className: "b316-input",
6499
6710
  value: resource.id,
6500
6711
  onChange: (event) => setResourceId(event.target.value),
6501
6712
  style: { marginBottom: 14 },
6502
- children: resources.map((item) => /* @__PURE__ */ jsx36("option", { value: item.id, children: item.name }, item.id))
6713
+ children: resources.map((item) => /* @__PURE__ */ jsx37("option", { value: item.id, children: item.name }, item.id))
6503
6714
  }
6504
- ) : /* @__PURE__ */ jsx36("div", { className: "b316-plan-name", children: resource.name }),
6505
- resource.rateLimit ? /* @__PURE__ */ jsxs35("div", { className: "b316-muted", children: [
6715
+ ) : /* @__PURE__ */ jsx37("div", { className: "b316-plan-name", children: resource.name }),
6716
+ resource.rateLimit ? /* @__PURE__ */ jsxs36("div", { className: "b316-muted", children: [
6506
6717
  resource.rateLimit.requestsPerWindow,
6507
6718
  " requests per",
6508
6719
  " ",
6509
6720
  duration(resource.rateLimit.windowSeconds),
6510
6721
  resource.rateLimit.burst > resource.rateLimit.requestsPerWindow ? `, bursting to ${resource.rateLimit.burst}` : null
6511
- ] }) : /* @__PURE__ */ jsx36("div", { className: "b316-muted", children: "No rate limit." }),
6512
- credentials.length === 0 ? /* @__PURE__ */ jsx36("p", { className: "b316-muted", style: { marginTop: 14 }, children: "You have no API keys yet." }) : /* @__PURE__ */ jsx36("ul", { className: "b316-list", style: { marginTop: 14 }, children: credentials.map((credential) => /* @__PURE__ */ jsxs35("li", { className: "b316-list-item", children: [
6513
- /* @__PURE__ */ jsxs35("div", { children: [
6514
- /* @__PURE__ */ jsx36("div", { className: "b316-plan-name", children: credential.name }),
6515
- /* @__PURE__ */ jsxs35("div", { className: "b316-muted", children: [
6516
- /* @__PURE__ */ jsx36("code", { children: credential.clientId }),
6722
+ ] }) : /* @__PURE__ */ jsx37("div", { className: "b316-muted", children: "No rate limit." }),
6723
+ credentials.length === 0 ? /* @__PURE__ */ jsx37("p", { className: "b316-muted", style: { marginTop: 14 }, children: "You have no API keys yet." }) : /* @__PURE__ */ jsx37("ul", { className: "b316-list", style: { marginTop: 14 }, children: credentials.map((credential) => /* @__PURE__ */ jsxs36("li", { className: "b316-list-item", children: [
6724
+ /* @__PURE__ */ jsxs36("div", { children: [
6725
+ /* @__PURE__ */ jsx37("div", { className: "b316-plan-name", children: credential.name }),
6726
+ /* @__PURE__ */ jsxs36("div", { className: "b316-muted", children: [
6727
+ /* @__PURE__ */ jsx37("code", { children: credential.clientId }),
6517
6728
  credential.secretLastFour ? ` \xB7 \u2026${credential.secretLastFour}` : null,
6518
6729
  credential.disabled ? " \xB7 Disabled" : null
6519
6730
  ] }),
6520
- /* @__PURE__ */ jsx36("div", { className: "b316-muted", children: credential.scopes.join(", ") })
6731
+ /* @__PURE__ */ jsx37("div", { className: "b316-muted", children: credential.scopes.join(", ") })
6521
6732
  ] }),
6522
- /* @__PURE__ */ jsxs35("div", { style: { display: "flex", gap: 8 }, children: [
6523
- /* @__PURE__ */ jsx36(
6733
+ /* @__PURE__ */ jsxs36("div", { style: { display: "flex", gap: 8 }, children: [
6734
+ /* @__PURE__ */ jsx37(
6524
6735
  "button",
6525
6736
  {
6526
6737
  type: "button",
@@ -6549,7 +6760,7 @@ function ApiKeyManager({
6549
6760
  children: "Rotate"
6550
6761
  }
6551
6762
  ),
6552
- /* @__PURE__ */ jsx36(
6763
+ /* @__PURE__ */ jsx37(
6553
6764
  ConfirmButton,
6554
6765
  {
6555
6766
  className: "b316-button b316-button-secondary",
@@ -6573,11 +6784,11 @@ function ApiKeyManager({
6573
6784
  )
6574
6785
  ] })
6575
6786
  ] }, credential.clientId)) }),
6576
- issued ? /* @__PURE__ */ jsxs35("div", { className: "b316-notice", style: { marginTop: 14 }, children: [
6577
- /* @__PURE__ */ jsx36("strong", { children: "Copy this now." }),
6787
+ issued ? /* @__PURE__ */ jsxs36("div", { className: "b316-notice", style: { marginTop: 14 }, children: [
6788
+ /* @__PURE__ */ jsx37("strong", { children: "Copy this now." }),
6578
6789
  " It is shown once and cannot be retrieved again.",
6579
- /* @__PURE__ */ jsx36("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx36("code", { style: { wordBreak: "break-all" }, children: issued.secret }) }),
6580
- /* @__PURE__ */ jsx36(
6790
+ /* @__PURE__ */ jsx37("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx37("code", { style: { wordBreak: "break-all" }, children: issued.secret }) }),
6791
+ /* @__PURE__ */ jsx37(
6581
6792
  "button",
6582
6793
  {
6583
6794
  type: "button",
@@ -6590,7 +6801,7 @@ function ApiKeyManager({
6590
6801
  children: "Copy"
6591
6802
  }
6592
6803
  ),
6593
- /* @__PURE__ */ jsx36(
6804
+ /* @__PURE__ */ jsx37(
6594
6805
  "button",
6595
6806
  {
6596
6807
  type: "button",
@@ -6601,8 +6812,8 @@ function ApiKeyManager({
6601
6812
  }
6602
6813
  )
6603
6814
  ] }) : null,
6604
- creating && !issued ? /* @__PURE__ */ jsxs35("div", { style: { marginTop: 14 }, children: [
6605
- /* @__PURE__ */ jsx36(
6815
+ creating && !issued ? /* @__PURE__ */ jsxs36("div", { style: { marginTop: 14 }, children: [
6816
+ /* @__PURE__ */ jsx37(
6606
6817
  "input",
6607
6818
  {
6608
6819
  className: "b316-input",
@@ -6611,9 +6822,9 @@ function ApiKeyManager({
6611
6822
  onChange: (event) => setName(event.target.value)
6612
6823
  }
6613
6824
  ),
6614
- /* @__PURE__ */ jsxs35("div", { style: { marginTop: 10 }, children: [
6615
- resource.availableScopes.map((scope) => /* @__PURE__ */ jsxs35("label", { className: "b316-checkbox", children: [
6616
- /* @__PURE__ */ jsx36(
6825
+ /* @__PURE__ */ jsxs36("div", { style: { marginTop: 10 }, children: [
6826
+ resource.availableScopes.map((scope) => /* @__PURE__ */ jsxs36("label", { className: "b316-checkbox", children: [
6827
+ /* @__PURE__ */ jsx37(
6617
6828
  "input",
6618
6829
  {
6619
6830
  type: "checkbox",
@@ -6623,19 +6834,19 @@ function ApiKeyManager({
6623
6834
  )
6624
6835
  }
6625
6836
  ),
6626
- /* @__PURE__ */ jsx36("code", { children: scope.key }),
6627
- scope.description ? /* @__PURE__ */ jsxs35("span", { className: "b316-muted", children: [
6837
+ /* @__PURE__ */ jsx37("code", { children: scope.key }),
6838
+ scope.description ? /* @__PURE__ */ jsxs36("span", { className: "b316-muted", children: [
6628
6839
  " \u2014 ",
6629
6840
  scope.description
6630
6841
  ] }) : null
6631
6842
  ] }, scope.key)),
6632
- resource.lockedScopes.map((scope) => /* @__PURE__ */ jsxs35("label", { className: "b316-checkbox b316-muted", children: [
6633
- /* @__PURE__ */ jsx36("input", { type: "checkbox", disabled: true }),
6634
- /* @__PURE__ */ jsx36("code", { children: scope.key }),
6635
- /* @__PURE__ */ jsx36("span", { children: " \u2014 not included in your plan" })
6843
+ resource.lockedScopes.map((scope) => /* @__PURE__ */ jsxs36("label", { className: "b316-checkbox b316-muted", children: [
6844
+ /* @__PURE__ */ jsx37("input", { type: "checkbox", disabled: true }),
6845
+ /* @__PURE__ */ jsx37("code", { children: scope.key }),
6846
+ /* @__PURE__ */ jsx37("span", { children: " \u2014 not included in your plan" })
6636
6847
  ] }, scope.key))
6637
6848
  ] }),
6638
- /* @__PURE__ */ jsx36(
6849
+ /* @__PURE__ */ jsx37(
6639
6850
  "button",
6640
6851
  {
6641
6852
  type: "button",
@@ -6669,7 +6880,7 @@ function ApiKeyManager({
6669
6880
  children: "Create key"
6670
6881
  }
6671
6882
  ),
6672
- /* @__PURE__ */ jsx36(
6883
+ /* @__PURE__ */ jsx37(
6673
6884
  "button",
6674
6885
  {
6675
6886
  type: "button",
@@ -6680,7 +6891,7 @@ function ApiKeyManager({
6680
6891
  }
6681
6892
  )
6682
6893
  ] }) : null,
6683
- !creating && !issued ? /* @__PURE__ */ jsx36(
6894
+ !creating && !issued ? /* @__PURE__ */ jsx37(
6684
6895
  "button",
6685
6896
  {
6686
6897
  type: "button",
@@ -6964,7 +7175,7 @@ var MANIFEST = [
6964
7175
  {
6965
7176
  name: "TwoFactorManager",
6966
7177
  kind: "component",
6967
- summary: "Turn two-factor authentication on or off, by authenticator app, a code to the inbox or a code by text message.",
7178
+ summary: "Turn two-factor authentication on or off, by authenticator app (QR code and key), a code to the inbox or a code by text message.",
6968
7179
  useWhen: "A security settings page. The app is strongest; the emailed or texted code is the one people who will not install an app actually use.",
6969
7180
  requires: ["session"],
6970
7181
  props: [
@@ -7108,7 +7319,7 @@ var MANIFEST = [
7108
7319
  {
7109
7320
  name: "SubscriptionManager",
7110
7321
  kind: "component",
7111
- summary: "The current plan, its renewal date, a scheduled plan change with its undo, cancelling at the period end (confirmed in the page) and resuming a cancelled one.",
7322
+ summary: "The current plan, its renewal date, a scheduled plan change with its undo, cancelling at the period end \u2014 asking why, and showing the environment's retention offer when it makes one \u2014 and resuming a cancelled one.",
7112
7323
  useWhen: "A billing settings page.",
7113
7324
  requires: ["session"],
7114
7325
  props: [