@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.cjs CHANGED
@@ -1,8 +1,10 @@
1
1
  "use client";
2
2
  "use strict";
3
+ var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
6
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
9
  var __export = (target, all) => {
8
10
  for (var name in all)
@@ -16,6 +18,14 @@ var __copyProps = (to, from, except, desc) => {
16
18
  }
17
19
  return to;
18
20
  };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
19
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
30
 
21
31
  // index.ts
@@ -704,12 +714,13 @@ function Base316Provider({
704
714
  onTokenChange,
705
715
  appearance: appearance2,
706
716
  tenant,
717
+ organizationId,
707
718
  className,
708
719
  children
709
720
  }) {
710
721
  const client = (0, import_react.useMemo)(
711
- () => new import_sdk.Base316Browser({ publishableKey, baseUrl }),
712
- [publishableKey, baseUrl]
722
+ () => new import_sdk.Base316Browser({ publishableKey, baseUrl, organizationId: organizationId ?? void 0 }),
723
+ [publishableKey, baseUrl, organizationId]
713
724
  );
714
725
  (0, import_react.useEffect)(() => {
715
726
  if (document.getElementById(STYLE_ELEMENT_ID)) {
@@ -2092,7 +2103,9 @@ function SignIn({
2092
2103
  if (cause instanceof DOMException && (cause.name === "NotAllowedError" || cause.name === "AbortError")) {
2093
2104
  return;
2094
2105
  }
2095
- if (!conditional) {
2106
+ if (cause instanceof import_sdk3.Base316Error && cause.reason === "EMAIL_NOT_VERIFIED") {
2107
+ setError(cause.message);
2108
+ } else if (!conditional) {
2096
2109
  console.error("[base316] passkey sign-in failed", cause);
2097
2110
  setError("That passkey did not work.");
2098
2111
  }
@@ -3092,8 +3105,62 @@ function PrivacyControls({
3092
3105
  }
3093
3106
 
3094
3107
  // src/TwoFactorManager.tsx
3108
+ var import_react15 = require("react");
3109
+
3110
+ // src/QrCode.tsx
3111
+ var import_qrcode_generator = __toESM(require("qrcode-generator"));
3095
3112
  var import_react14 = require("react");
3096
3113
  var import_jsx_runtime16 = require("react/jsx-runtime");
3114
+ var QUIET_ZONE = 4;
3115
+ function utf8Binary(value) {
3116
+ let binary = "";
3117
+ for (const byte of new TextEncoder().encode(value)) {
3118
+ binary += String.fromCharCode(byte);
3119
+ }
3120
+ return binary;
3121
+ }
3122
+ function qrPath(value) {
3123
+ const code = (0, import_qrcode_generator.default)(0, "M");
3124
+ code.addData(utf8Binary(value), "Byte");
3125
+ code.make();
3126
+ const modules = code.getModuleCount();
3127
+ let path = "";
3128
+ for (let row = 0; row < modules; row += 1) {
3129
+ for (let col = 0; col < modules; col += 1) {
3130
+ if (code.isDark(row, col)) {
3131
+ path += `M${col + QUIET_ZONE} ${row + QUIET_ZONE}h1v1h-1z`;
3132
+ }
3133
+ }
3134
+ }
3135
+ return { path, modules };
3136
+ }
3137
+ function QrCode({ value, label, size = 180, className }) {
3138
+ const { path, modules } = (0, import_react14.useMemo)(() => qrPath(value), [value]);
3139
+ const extent = modules + QUIET_ZONE * 2;
3140
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3141
+ "svg",
3142
+ {
3143
+ className,
3144
+ role: "img",
3145
+ "aria-label": label,
3146
+ width: size,
3147
+ height: size,
3148
+ viewBox: `0 0 ${extent} ${extent}`,
3149
+ shapeRendering: "crispEdges",
3150
+ xmlns: "http://www.w3.org/2000/svg",
3151
+ children: [
3152
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("rect", { width: extent, height: extent, fill: "#ffffff" }),
3153
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: path, fill: "#000000" })
3154
+ ]
3155
+ }
3156
+ );
3157
+ }
3158
+
3159
+ // src/TwoFactorManager.tsx
3160
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3161
+ function groupKey(secret) {
3162
+ return secret.replace(/\s+/g, "").replace(/(.{4})(?=.)/g, "$1 ");
3163
+ }
3097
3164
  function TwoFactorManager({
3098
3165
  enabled = false,
3099
3166
  allowSms = false,
@@ -3103,12 +3170,12 @@ function TwoFactorManager({
3103
3170
  style
3104
3171
  }) {
3105
3172
  const { client, token } = useBase316();
3106
- const [stage, setStage] = (0, import_react14.useState)({ name: "idle" });
3107
- const [on, setOn] = (0, import_react14.useState)(enabled);
3108
- const [code, setCode] = (0, import_react14.useState)("");
3109
- const [phone, setPhone] = (0, import_react14.useState)("");
3110
- const [error, setError] = (0, import_react14.useState)(null);
3111
- const [busy, setBusy] = (0, import_react14.useState)(false);
3173
+ const [stage, setStage] = (0, import_react15.useState)({ name: "idle" });
3174
+ const [on, setOn] = (0, import_react15.useState)(enabled);
3175
+ const [code, setCode] = (0, import_react15.useState)("");
3176
+ const [phone, setPhone] = (0, import_react15.useState)("");
3177
+ const [error, setError] = (0, import_react15.useState)(null);
3178
+ const [busy, setBusy] = (0, import_react15.useState)(false);
3112
3179
  if (!token) {
3113
3180
  return null;
3114
3181
  }
@@ -3186,17 +3253,17 @@ function TwoFactorManager({
3186
3253
  setBusy(false);
3187
3254
  }
3188
3255
  }
3189
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: cls("b316-card b316-mfa", className), style, children: [
3190
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { className: "b316-mfa-title", children: "Two-factor authentication" }),
3191
- error ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3192
- stage.name === "saved" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-codes", children: [
3193
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("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." }),
3194
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("ul", { className: "b316-mfa-code-list", children: stage.recoveryCodes.map((recovery) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("code", { children: recovery }) }, recovery)) }),
3195
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "b316-button", onClick: () => setStage({ name: "idle" }), children: "I have saved them" })
3196
- ] }) : stage.name === "smsNumber" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-enrol", children: [
3197
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: "We will text a code to this number now, and each time you sign in." }),
3198
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { className: "b316-label", htmlFor: "b316-mfa-phone", children: "Mobile number" }),
3199
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3256
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: cls("b316-card b316-mfa", className), style, children: [
3257
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h3", { className: "b316-mfa-title", children: "Two-factor authentication" }),
3258
+ error ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3259
+ stage.name === "saved" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-codes", children: [
3260
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("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." }),
3261
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("ul", { className: "b316-mfa-code-list", children: stage.recoveryCodes.map((recovery) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("code", { children: recovery }) }, recovery)) }),
3262
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "b316-button", onClick: () => setStage({ name: "idle" }), children: "I have saved them" })
3263
+ ] }) : stage.name === "smsNumber" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-enrol", children: [
3264
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { children: "We will text a code to this number now, and each time you sign in." }),
3265
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { className: "b316-label", htmlFor: "b316-mfa-phone", children: "Mobile number" }),
3266
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3200
3267
  "input",
3201
3268
  {
3202
3269
  id: "b316-mfa-phone",
@@ -3208,8 +3275,8 @@ function TwoFactorManager({
3208
3275
  onChange: (event) => setPhone(event.target.value)
3209
3276
  }
3210
3277
  ),
3211
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-actions", children: [
3212
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3278
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-actions", children: [
3279
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3213
3280
  "button",
3214
3281
  {
3215
3282
  type: "button",
@@ -3218,16 +3285,16 @@ function TwoFactorManager({
3218
3285
  children: "Cancel"
3219
3286
  }
3220
3287
  ),
3221
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "b316-button", disabled: busy, onClick: beginSms, children: busy ? "Sending\u2026" : "Send code" })
3288
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "b316-button", disabled: busy, onClick: beginSms, children: busy ? "Sending\u2026" : "Send code" })
3222
3289
  ] })
3223
- ] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-enrol", children: [
3224
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("p", { children: [
3290
+ ] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-enrol", children: [
3291
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("p", { children: [
3225
3292
  "We sent a code to ",
3226
3293
  stage.destinationHint,
3227
3294
  ". Enter it below to turn this on."
3228
3295
  ] }),
3229
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
3230
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3296
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
3297
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3231
3298
  "input",
3232
3299
  {
3233
3300
  id: "b316-mfa-code",
@@ -3238,8 +3305,8 @@ function TwoFactorManager({
3238
3305
  onChange: (event) => setCode(event.target.value)
3239
3306
  }
3240
3307
  ),
3241
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-actions", children: [
3242
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3308
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-actions", children: [
3309
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3243
3310
  "button",
3244
3311
  {
3245
3312
  type: "button",
@@ -3248,7 +3315,7 @@ function TwoFactorManager({
3248
3315
  children: "Cancel"
3249
3316
  }
3250
3317
  ),
3251
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3318
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3252
3319
  "button",
3253
3320
  {
3254
3321
  type: "button",
@@ -3259,12 +3326,23 @@ function TwoFactorManager({
3259
3326
  }
3260
3327
  )
3261
3328
  ] })
3262
- ] }) : stage.name === "enrolling" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-enrol", children: [
3263
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: "Add this to your authenticator app, then enter the six-digit code it shows." }),
3264
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "b316-mfa-secret", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("code", { children: stage.secret }) }),
3265
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("a", { className: "b316-mfa-uri", href: stage.uri, children: "Open in an authenticator app" }),
3266
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
3267
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3329
+ ] }) : stage.name === "enrolling" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-enrol", children: [
3330
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { children: "Scan this with your authenticator app (Google Authenticator, 1Password, Authy\u2026), then enter the six-digit code it shows." }),
3331
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3332
+ QrCode,
3333
+ {
3334
+ className: "b316-mfa-qr",
3335
+ value: stage.uri,
3336
+ label: "QR code for your authenticator app"
3337
+ }
3338
+ ),
3339
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-secret", children: [
3340
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "b316-label", id: "b316-mfa-manual-key", children: "Can't scan? Enter this key" }),
3341
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("code", { "aria-labelledby": "b316-mfa-manual-key", children: groupKey(stage.secret) })
3342
+ ] }),
3343
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("a", { className: "b316-mfa-uri", href: stage.uri, children: "Open in an authenticator app" }),
3344
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
3345
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3268
3346
  "input",
3269
3347
  {
3270
3348
  id: "b316-mfa-code",
@@ -3275,8 +3353,8 @@ function TwoFactorManager({
3275
3353
  onChange: (event) => setCode(event.target.value)
3276
3354
  }
3277
3355
  ),
3278
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-actions", children: [
3279
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3356
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-actions", children: [
3357
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3280
3358
  "button",
3281
3359
  {
3282
3360
  type: "button",
@@ -3285,7 +3363,7 @@ function TwoFactorManager({
3285
3363
  children: "Cancel"
3286
3364
  }
3287
3365
  ),
3288
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3366
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3289
3367
  "button",
3290
3368
  {
3291
3369
  type: "button",
@@ -3296,9 +3374,9 @@ function TwoFactorManager({
3296
3374
  }
3297
3375
  )
3298
3376
  ] })
3299
- ] }) : on ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-on", children: [
3300
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "b316-muted", children: "On. You will be asked for a code when you sign in." }),
3301
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3377
+ ] }) : on ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-on", children: [
3378
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "b316-muted", children: "On. You will be asked for a code when you sign in." }),
3379
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3302
3380
  ConfirmButton,
3303
3381
  {
3304
3382
  className: "b316-button-quiet b316-danger",
@@ -3308,11 +3386,11 @@ function TwoFactorManager({
3308
3386
  children: "Turn off"
3309
3387
  }
3310
3388
  )
3311
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-off", children: [
3312
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "b316-muted", children: "Off. Turning it on means a code as well as your password, every time you sign in." }),
3313
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "b316-mfa-actions", children: [
3314
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: "b316-button", disabled: busy, onClick: begin, children: busy ? "Starting\u2026" : "Use an authenticator app" }),
3315
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3389
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-off", children: [
3390
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "b316-muted", children: "Off. Turning it on means a code as well as your password, every time you sign in." }),
3391
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-mfa-actions", children: [
3392
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "b316-button", disabled: busy, onClick: begin, children: busy ? "Starting\u2026" : "Use an authenticator app" }),
3393
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3316
3394
  "button",
3317
3395
  {
3318
3396
  type: "button",
@@ -3322,7 +3400,7 @@ function TwoFactorManager({
3322
3400
  children: "Email me a code"
3323
3401
  }
3324
3402
  ),
3325
- allowSms ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3403
+ allowSms ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3326
3404
  "button",
3327
3405
  {
3328
3406
  type: "button",
@@ -3338,14 +3416,14 @@ function TwoFactorManager({
3338
3416
  }
3339
3417
 
3340
3418
  // src/ForgotPassword.tsx
3341
- var import_react15 = require("react");
3342
- var import_jsx_runtime17 = require("react/jsx-runtime");
3419
+ var import_react16 = require("react");
3420
+ var import_jsx_runtime18 = require("react/jsx-runtime");
3343
3421
  function ForgotPassword({ onSent, signInUrl, className, style }) {
3344
3422
  const { client } = useBase316();
3345
- const [email, setEmail] = (0, import_react15.useState)("");
3346
- const [sent, setSent] = (0, import_react15.useState)(false);
3347
- const [busy, setBusy] = (0, import_react15.useState)(false);
3348
- const [error, setError] = (0, import_react15.useState)(null);
3423
+ const [email, setEmail] = (0, import_react16.useState)("");
3424
+ const [sent, setSent] = (0, import_react16.useState)(false);
3425
+ const [busy, setBusy] = (0, import_react16.useState)(false);
3426
+ const [error, setError] = (0, import_react16.useState)(null);
3349
3427
  async function submit(event) {
3350
3428
  event.preventDefault();
3351
3429
  setBusy(true);
@@ -3361,22 +3439,22 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
3361
3439
  }
3362
3440
  }
3363
3441
  if (sent) {
3364
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: cls("b316-card", className), style, children: [
3365
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h3", { className: "b316-form-title", children: "Check your email" }),
3366
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("p", { className: "b316-muted", children: [
3442
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: cls("b316-card", className), style, children: [
3443
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { className: "b316-form-title", children: "Check your email" }),
3444
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { className: "b316-muted", children: [
3367
3445
  "If there is an account for ",
3368
3446
  email.trim(),
3369
3447
  ", a link to set a new password is on its way."
3370
3448
  ] }),
3371
- signInUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
3449
+ signInUrl ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
3372
3450
  ] });
3373
3451
  }
3374
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
3375
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h3", { className: "b316-form-title", children: "Reset your password" }),
3376
- error ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3377
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "b316-field", children: [
3378
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("label", { className: "b316-label", htmlFor: "b316-forgot-email", children: "Email" }),
3379
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3452
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
3453
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { className: "b316-form-title", children: "Reset your password" }),
3454
+ error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3455
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "b316-field", children: [
3456
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { className: "b316-label", htmlFor: "b316-forgot-email", children: "Email" }),
3457
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3380
3458
  "input",
3381
3459
  {
3382
3460
  id: "b316-forgot-email",
@@ -3389,14 +3467,14 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
3389
3467
  }
3390
3468
  )
3391
3469
  ] }),
3392
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Send reset link" }),
3393
- signInUrl ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
3470
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Send reset link" }),
3471
+ signInUrl ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
3394
3472
  ] });
3395
3473
  }
3396
3474
 
3397
3475
  // src/ResetPassword.tsx
3398
- var import_react16 = require("react");
3399
- var import_jsx_runtime18 = require("react/jsx-runtime");
3476
+ var import_react17 = require("react");
3477
+ var import_jsx_runtime19 = require("react/jsx-runtime");
3400
3478
  function ResetPassword({
3401
3479
  token: supplied,
3402
3480
  onReset,
@@ -3405,13 +3483,13 @@ function ResetPassword({
3405
3483
  style
3406
3484
  }) {
3407
3485
  const { client } = useBase316();
3408
- const [token, setToken] = (0, import_react16.useState)(supplied ?? null);
3409
- const [password, setPassword] = (0, import_react16.useState)("");
3410
- const [confirmation, setConfirmation] = (0, import_react16.useState)("");
3411
- const [done, setDone] = (0, import_react16.useState)(false);
3412
- const [busy, setBusy] = (0, import_react16.useState)(false);
3413
- const [error, setError] = (0, import_react16.useState)(null);
3414
- (0, import_react16.useEffect)(() => {
3486
+ const [token, setToken] = (0, import_react17.useState)(supplied ?? null);
3487
+ const [password, setPassword] = (0, import_react17.useState)("");
3488
+ const [confirmation, setConfirmation] = (0, import_react17.useState)("");
3489
+ const [done, setDone] = (0, import_react17.useState)(false);
3490
+ const [busy, setBusy] = (0, import_react17.useState)(false);
3491
+ const [error, setError] = (0, import_react17.useState)(null);
3492
+ (0, import_react17.useEffect)(() => {
3415
3493
  if (supplied || typeof window === "undefined") {
3416
3494
  return;
3417
3495
  }
@@ -3446,24 +3524,24 @@ function ResetPassword({
3446
3524
  }
3447
3525
  }
3448
3526
  if (done) {
3449
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: cls("b316-card", className), style, children: [
3450
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { className: "b316-form-title", children: "Password changed" }),
3451
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "b316-muted", children: "You can sign in with your new password." }),
3452
- signInUrl ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("a", { className: "b316-button-link", href: signInUrl, children: "Sign in" }) : null
3527
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: cls("b316-card", className), style, children: [
3528
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "b316-form-title", children: "Password changed" }),
3529
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "b316-muted", children: "You can sign in with your new password." }),
3530
+ signInUrl ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("a", { className: "b316-button-link", href: signInUrl, children: "Sign in" }) : null
3453
3531
  ] });
3454
3532
  }
3455
3533
  if (!token) {
3456
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: cls("b316-card", className), style, children: [
3457
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { className: "b316-form-title", children: "Nothing to reset" }),
3458
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "b316-muted", children: "This page needs the link from your email. Request a new one if yours has expired." })
3534
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: cls("b316-card", className), style, children: [
3535
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "b316-form-title", children: "Nothing to reset" }),
3536
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "b316-muted", children: "This page needs the link from your email. Request a new one if yours has expired." })
3459
3537
  ] });
3460
3538
  }
3461
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
3462
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h3", { className: "b316-form-title", children: "Choose a new password" }),
3463
- error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3464
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "b316-field", children: [
3465
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { className: "b316-label", htmlFor: "b316-reset-password", children: "New password" }),
3466
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3539
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
3540
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "b316-form-title", children: "Choose a new password" }),
3541
+ error ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3542
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "b316-field", children: [
3543
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { className: "b316-label", htmlFor: "b316-reset-password", children: "New password" }),
3544
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3467
3545
  "input",
3468
3546
  {
3469
3547
  id: "b316-reset-password",
@@ -3476,9 +3554,9 @@ function ResetPassword({
3476
3554
  }
3477
3555
  )
3478
3556
  ] }),
3479
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "b316-field", children: [
3480
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("label", { className: "b316-label", htmlFor: "b316-reset-confirm", children: "Repeat it" }),
3481
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3557
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "b316-field", children: [
3558
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { className: "b316-label", htmlFor: "b316-reset-confirm", children: "Repeat it" }),
3559
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3482
3560
  "input",
3483
3561
  {
3484
3562
  id: "b316-reset-confirm",
@@ -3491,13 +3569,13 @@ function ResetPassword({
3491
3569
  }
3492
3570
  )
3493
3571
  ] }),
3494
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "submit", className: "b316-button", disabled: busy || !password, children: busy ? "Saving\u2026" : "Set password" })
3572
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "submit", className: "b316-button", disabled: busy || !password, children: busy ? "Saving\u2026" : "Set password" })
3495
3573
  ] });
3496
3574
  }
3497
3575
 
3498
3576
  // src/VerifyEmail.tsx
3499
- var import_react17 = require("react");
3500
- var import_jsx_runtime19 = require("react/jsx-runtime");
3577
+ var import_react18 = require("react");
3578
+ var import_jsx_runtime20 = require("react/jsx-runtime");
3501
3579
  function VerifyEmail({
3502
3580
  token: supplied,
3503
3581
  onVerified,
@@ -3506,9 +3584,9 @@ function VerifyEmail({
3506
3584
  style
3507
3585
  }) {
3508
3586
  const { client } = useBase316();
3509
- const [state, setState] = (0, import_react17.useState)("waiting");
3510
- const spent = (0, import_react17.useRef)(false);
3511
- (0, import_react17.useEffect)(() => {
3587
+ const [state, setState] = (0, import_react18.useState)("waiting");
3588
+ const spent = (0, import_react18.useRef)(false);
3589
+ (0, import_react18.useEffect)(() => {
3512
3590
  if (spent.current) {
3513
3591
  return;
3514
3592
  }
@@ -3534,22 +3612,22 @@ function VerifyEmail({
3534
3612
  setState("failed");
3535
3613
  });
3536
3614
  }, [client, supplied, onVerified]);
3537
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cls("b316-card", className), style, children: state === "verified" ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
3538
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "b316-form-title", children: "Email confirmed" }),
3539
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "b316-muted", children: "Thanks \u2014 your address is verified." }),
3540
- continueUrl ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("a", { className: "b316-button-link", href: continueUrl, children: "Continue" }) : null
3541
- ] }) : state === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
3542
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "b316-form-title", children: "That link did not work" }),
3543
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "b316-muted", children: "It may have expired or already been used. Ask for a new one and try again." })
3544
- ] }) : state === "missing" ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
3545
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "b316-form-title", children: "Nothing to confirm" }),
3546
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "b316-muted", children: "This page needs the link from your email." })
3547
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "b316-muted", children: "Confirming your email\u2026" }) });
3615
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cls("b316-card", className), style, children: state === "verified" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
3616
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "b316-form-title", children: "Email confirmed" }),
3617
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "b316-muted", children: "Thanks \u2014 your address is verified." }),
3618
+ continueUrl ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("a", { className: "b316-button-link", href: continueUrl, children: "Continue" }) : null
3619
+ ] }) : state === "failed" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
3620
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "b316-form-title", children: "That link did not work" }),
3621
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "b316-muted", children: "It may have expired or already been used. Ask for a new one and try again." })
3622
+ ] }) : state === "missing" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
3623
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "b316-form-title", children: "Nothing to confirm" }),
3624
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "b316-muted", children: "This page needs the link from your email." })
3625
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "b316-muted", children: "Confirming your email\u2026" }) });
3548
3626
  }
3549
3627
 
3550
3628
  // src/TeamMembers.tsx
3551
- var import_react18 = require("react");
3552
- var import_jsx_runtime20 = require("react/jsx-runtime");
3629
+ var import_react19 = require("react");
3630
+ var import_jsx_runtime21 = require("react/jsx-runtime");
3553
3631
  function TeamMembers({
3554
3632
  organizationId,
3555
3633
  onInvited,
@@ -3559,16 +3637,16 @@ function TeamMembers({
3559
3637
  style
3560
3638
  }) {
3561
3639
  const { client, token, session } = useBase316();
3562
- const [teams, setTeams] = (0, import_react18.useState)(null);
3563
- const [members, setMembers] = (0, import_react18.useState)(null);
3564
- const [invitations, setInvitations] = (0, import_react18.useState)(null);
3565
- const [email, setEmail] = (0, import_react18.useState)("");
3566
- const [busy, setBusy] = (0, import_react18.useState)(false);
3567
- const [error, setError] = (0, import_react18.useState)(null);
3568
- const [copied, setCopied] = (0, import_react18.useState)(null);
3640
+ const [teams, setTeams] = (0, import_react19.useState)(null);
3641
+ const [members, setMembers] = (0, import_react19.useState)(null);
3642
+ const [invitations, setInvitations] = (0, import_react19.useState)(null);
3643
+ const [email, setEmail] = (0, import_react19.useState)("");
3644
+ const [busy, setBusy] = (0, import_react19.useState)(false);
3645
+ const [error, setError] = (0, import_react19.useState)(null);
3646
+ const [copied, setCopied] = (0, import_react19.useState)(null);
3569
3647
  const chosen = organizationId ?? (teams?.length === 1 ? teams[0].id : null);
3570
3648
  const team = teams?.find((candidate) => candidate.id === chosen) ?? null;
3571
- const load = (0, import_react18.useCallback)(() => {
3649
+ const load = (0, import_react19.useCallback)(() => {
3572
3650
  if (!token) {
3573
3651
  return;
3574
3652
  }
@@ -3576,8 +3654,8 @@ function TeamMembers({
3576
3654
  (cause) => setError(cause instanceof Error ? cause.message : "Could not load your teams.")
3577
3655
  );
3578
3656
  }, [client, token]);
3579
- (0, import_react18.useEffect)(load, [load]);
3580
- (0, import_react18.useEffect)(() => {
3657
+ (0, import_react19.useEffect)(load, [load]);
3658
+ (0, import_react19.useEffect)(() => {
3581
3659
  if (!token || !chosen) {
3582
3660
  return;
3583
3661
  }
@@ -3608,10 +3686,10 @@ function TeamMembers({
3608
3686
  return null;
3609
3687
  }
3610
3688
  if (!teams) {
3611
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cls("b316-card", className), style, children: error ?? "Loading\u2026" });
3689
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cls("b316-card", className), style, children: error ?? "Loading\u2026" });
3612
3690
  }
3613
3691
  if (!chosen) {
3614
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("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." });
3692
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("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." });
3615
3693
  }
3616
3694
  const canManage = invitations !== null;
3617
3695
  async function invite(event) {
@@ -3661,30 +3739,30 @@ function TeamMembers({
3661
3739
  setError(cause instanceof Error ? cause.message : "That invitation could not be withdrawn.");
3662
3740
  }
3663
3741
  }
3664
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cls("b316-card b316-team", className), style, children: [
3665
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "b316-team-title", children: team?.name ?? "Team" }),
3742
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cls("b316-card b316-team", className), style, children: [
3743
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "b316-team-title", children: team?.name ?? "Team" }),
3666
3744
  team?.inherited ? (
3667
3745
  // Not a member of this team, so not in the list below and with nothing
3668
3746
  // to leave: access comes from the team that manages it, and ends there.
3669
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "b316-muted", children: [
3747
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "b316-muted", children: [
3670
3748
  "You have access through",
3671
3749
  " ",
3672
3750
  teams.find((candidate) => candidate.id === team.via)?.name ?? "the organization that manages this team",
3673
3751
  "."
3674
3752
  ] })
3675
3753
  ) : null,
3676
- error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3677
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "b316-team-list", children: (members ?? []).map((member) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("li", { className: "b316-team-member", children: [
3678
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { children: [
3679
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: member.user.name ?? member.user.email ?? "Someone" }),
3680
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "b316-muted", children: [
3754
+ error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3755
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "b316-team-list", children: (members ?? []).map((member) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "b316-team-member", children: [
3756
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3757
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: member.user.name ?? member.user.email ?? "Someone" }),
3758
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "b316-muted", children: [
3681
3759
  member.user.email,
3682
3760
  member.user.id === session?.userId ? " \xB7 you" : ""
3683
3761
  ] })
3684
3762
  ] }),
3685
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "b316-team-member-side", children: [
3686
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "b316-chip", children: member.role.name }),
3687
- canManage || member.user.id === session?.userId ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3763
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "b316-team-member-side", children: [
3764
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "b316-chip", children: member.role.name }),
3765
+ canManage || member.user.id === session?.userId ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3688
3766
  ConfirmButton,
3689
3767
  {
3690
3768
  className: "b316-button-quiet b316-danger",
@@ -3696,19 +3774,19 @@ function TeamMembers({
3696
3774
  ) : null
3697
3775
  ] })
3698
3776
  ] }, member.id)) }),
3699
- canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
3700
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h4", { className: "b316-team-subtitle", children: "Invited" }),
3701
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "b316-team-list", children: (invitations ?? []).map((invitation) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("li", { className: "b316-team-member", children: [
3702
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { children: [
3703
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { children: invitation.email }),
3704
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "b316-muted", children: [
3777
+ canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
3778
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h4", { className: "b316-team-subtitle", children: "Invited" }),
3779
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "b316-team-list", children: (invitations ?? []).map((invitation) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "b316-team-member", children: [
3780
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3781
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { children: invitation.email }),
3782
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "b316-muted", children: [
3705
3783
  invitation.role.name,
3706
3784
  " \xB7 expires",
3707
3785
  " ",
3708
3786
  new Date(invitation.expiresAt).toLocaleDateString()
3709
3787
  ] })
3710
3788
  ] }),
3711
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3789
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3712
3790
  "button",
3713
3791
  {
3714
3792
  type: "button",
@@ -3719,10 +3797,10 @@ function TeamMembers({
3719
3797
  )
3720
3798
  ] }, invitation.id)) })
3721
3799
  ] }) : null,
3722
- canManage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("form", { className: "b316-team-invite", onSubmit: invite, children: [
3723
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("label", { className: "b316-label", htmlFor: "b316-invite-email", children: "Invite by email" }),
3724
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "b316-team-invite-row", children: [
3725
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3800
+ canManage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("form", { className: "b316-team-invite", onSubmit: invite, children: [
3801
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { className: "b316-label", htmlFor: "b316-invite-email", children: "Invite by email" }),
3802
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "b316-team-invite-row", children: [
3803
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3726
3804
  "input",
3727
3805
  {
3728
3806
  id: "b316-invite-email",
@@ -3734,19 +3812,19 @@ function TeamMembers({
3734
3812
  onChange: (event) => setEmail(event.target.value)
3735
3813
  }
3736
3814
  ),
3737
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Invite" })
3815
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Invite" })
3738
3816
  ] })
3739
3817
  ] }) : null,
3740
- copied ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "b316-team-link", children: [
3741
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "b316-muted", children: "Send them this link. It is shown once and cannot be fetched again." }),
3742
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("code", { children: copied })
3818
+ copied ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "b316-team-link", children: [
3819
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "b316-muted", children: "Send them this link. It is shown once and cannot be fetched again." }),
3820
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("code", { children: copied })
3743
3821
  ] }) : null
3744
3822
  ] });
3745
3823
  }
3746
3824
 
3747
3825
  // src/AcceptInvitation.tsx
3748
- var import_react19 = require("react");
3749
- var import_jsx_runtime21 = require("react/jsx-runtime");
3826
+ var import_react20 = require("react");
3827
+ var import_jsx_runtime22 = require("react/jsx-runtime");
3750
3828
  function signUpUrlWithInvitation(url, token) {
3751
3829
  const [beforeHash, ...hash] = url.split("#");
3752
3830
  const base = beforeHash ?? "";
@@ -3765,18 +3843,18 @@ function AcceptInvitation({
3765
3843
  style
3766
3844
  }) {
3767
3845
  const { client, token: session, session: user } = useBase316();
3768
- const [invitationToken, setInvitationToken] = (0, import_react19.useState)(supplied ?? null);
3769
- const [preview, setPreview] = (0, import_react19.useState)(null);
3770
- const [state, setState] = (0, import_react19.useState)("loading");
3771
- const [error, setError] = (0, import_react19.useState)(null);
3772
- const [busy, setBusy] = (0, import_react19.useState)(false);
3773
- (0, import_react19.useEffect)(() => {
3846
+ const [invitationToken, setInvitationToken] = (0, import_react20.useState)(supplied ?? null);
3847
+ const [preview, setPreview] = (0, import_react20.useState)(null);
3848
+ const [state, setState] = (0, import_react20.useState)("loading");
3849
+ const [error, setError] = (0, import_react20.useState)(null);
3850
+ const [busy, setBusy] = (0, import_react20.useState)(false);
3851
+ (0, import_react20.useEffect)(() => {
3774
3852
  if (supplied || typeof window === "undefined") {
3775
3853
  return;
3776
3854
  }
3777
3855
  setInvitationToken(new URL(window.location.href).searchParams.get("invitation"));
3778
3856
  }, [supplied]);
3779
- (0, import_react19.useEffect)(() => {
3857
+ (0, import_react20.useEffect)(() => {
3780
3858
  if (!invitationToken) {
3781
3859
  setState(supplied === void 0 ? "loading" : "invalid");
3782
3860
  return;
@@ -3813,42 +3891,42 @@ function AcceptInvitation({
3813
3891
  }
3814
3892
  }
3815
3893
  if (state === "loading") {
3816
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
3894
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
3817
3895
  }
3818
3896
  if (state === "invalid") {
3819
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cls("b316-card", className), style, children: [
3820
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "b316-form-title", children: "That invitation is no longer valid" }),
3821
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "b316-muted", children: "It may have expired, been withdrawn, or already been used. Ask for a new one." })
3897
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: cls("b316-card", className), style, children: [
3898
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { className: "b316-form-title", children: "That invitation is no longer valid" }),
3899
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "b316-muted", children: "It may have expired, been withdrawn, or already been used. Ask for a new one." })
3822
3900
  ] });
3823
3901
  }
3824
3902
  if (state === "accepted") {
3825
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("h3", { className: "b316-form-title", children: [
3903
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("h3", { className: "b316-form-title", children: [
3826
3904
  "You have joined ",
3827
3905
  preview?.organizationName
3828
3906
  ] }) });
3829
3907
  }
3830
3908
  const matches = !user || (user.user.email ?? "").toLowerCase() === preview?.email.toLowerCase();
3831
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cls("b316-card b316-invitation", className), style, children: [
3832
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("h3", { className: "b316-form-title", children: [
3909
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: cls("b316-card b316-invitation", className), style, children: [
3910
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("h3", { className: "b316-form-title", children: [
3833
3911
  "Join ",
3834
3912
  preview?.organizationName
3835
3913
  ] }),
3836
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("p", { className: "b316-muted", children: [
3914
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("p", { className: "b316-muted", children: [
3837
3915
  "Invited as ",
3838
3916
  preview?.email,
3839
3917
  " \xB7 ",
3840
3918
  preview?.roleName
3841
3919
  ] }),
3842
- error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3843
- !session ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
3844
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("p", { children: [
3920
+ error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
3921
+ !session ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
3922
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("p", { children: [
3845
3923
  "Sign in as ",
3846
3924
  preview?.email,
3847
3925
  " to accept."
3848
3926
  ] }),
3849
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "b316-invitation-actions", children: [
3850
- signInUrl ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("a", { className: "b316-button", href: signInUrl, children: "Sign in" }) : null,
3851
- signUpUrl ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
3927
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "b316-invitation-actions", children: [
3928
+ signInUrl ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("a", { className: "b316-button", href: signInUrl, children: "Sign in" }) : null,
3929
+ signUpUrl ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3852
3930
  "a",
3853
3931
  {
3854
3932
  className: "b316-button-link",
@@ -3861,20 +3939,20 @@ function AcceptInvitation({
3861
3939
  // Said before they press anything. The server refuses this, but
3862
3940
  // finding out after a click reads as a broken invitation rather than
3863
3941
  // as being signed in as the wrong person.
3864
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("p", { children: [
3942
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("p", { children: [
3865
3943
  "You are signed in as ",
3866
3944
  user?.user.email,
3867
3945
  ". This invitation was sent to ",
3868
3946
  preview?.email,
3869
3947
  " \u2014 sign in as that address to accept it."
3870
3948
  ] })
3871
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: "b316-button", disabled: busy, onClick: accept, children: busy ? "Joining\u2026" : `Join ${preview?.organizationName}` })
3949
+ ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: "b316-button", disabled: busy, onClick: accept, children: busy ? "Joining\u2026" : `Join ${preview?.organizationName}` })
3872
3950
  ] });
3873
3951
  }
3874
3952
 
3875
3953
  // src/PayInvoice.tsx
3876
- var import_react20 = require("react");
3877
- var import_jsx_runtime22 = require("react/jsx-runtime");
3954
+ var import_react21 = require("react");
3955
+ var import_jsx_runtime23 = require("react/jsx-runtime");
3878
3956
  var STRIPE_SRC = "https://js.stripe.com/v3/";
3879
3957
  function loadStripeScript() {
3880
3958
  if (typeof window === "undefined") {
@@ -3906,14 +3984,14 @@ function PayInvoice({
3906
3984
  style
3907
3985
  }) {
3908
3986
  const { client } = useBase316();
3909
- const mountRef = (0, import_react20.useRef)(null);
3910
- const stripeRef = (0, import_react20.useRef)(null);
3911
- const elementsRef = (0, import_react20.useRef)(null);
3912
- const [ready, setReady] = (0, import_react20.useState)(false);
3913
- const [paying, setPaying] = (0, import_react20.useState)(false);
3914
- const [done, setDone] = (0, import_react20.useState)(false);
3915
- const [error, setError] = (0, import_react20.useState)(null);
3916
- (0, import_react20.useEffect)(() => {
3987
+ const mountRef = (0, import_react21.useRef)(null);
3988
+ const stripeRef = (0, import_react21.useRef)(null);
3989
+ const elementsRef = (0, import_react21.useRef)(null);
3990
+ const [ready, setReady] = (0, import_react21.useState)(false);
3991
+ const [paying, setPaying] = (0, import_react21.useState)(false);
3992
+ const [done, setDone] = (0, import_react21.useState)(false);
3993
+ const [error, setError] = (0, import_react21.useState)(null);
3994
+ (0, import_react21.useEffect)(() => {
3917
3995
  let cancelled = false;
3918
3996
  async function start() {
3919
3997
  const base = `${client.baseUrl}/pay/${encodeURIComponent(environmentId)}/${encodeURIComponent(token)}`;
@@ -3966,17 +4044,17 @@ function PayInvoice({
3966
4044
  onPaid?.();
3967
4045
  };
3968
4046
  if (done) {
3969
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: cls("b316-pay", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "b316-pay__done", children: "Paid \u2014 thank you." }) });
4047
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cls("b316-pay", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "b316-pay__done", children: "Paid \u2014 thank you." }) });
3970
4048
  }
3971
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("form", { className: cls("b316-pay", className), style, onSubmit: submit, children: [
3972
- error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "b316-pay__error", role: "alert", children: error }) : null,
3973
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { ref: mountRef, className: "b316-pay__element" }),
3974
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { className: "b316-pay__submit", type: "submit", disabled: !ready || paying, children: paying ? "Paying\u2026" : "Pay" })
4049
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("form", { className: cls("b316-pay", className), style, onSubmit: submit, children: [
4050
+ error ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "b316-pay__error", role: "alert", children: error }) : null,
4051
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: mountRef, className: "b316-pay__element" }),
4052
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { className: "b316-pay__submit", type: "submit", disabled: !ready || paying, children: paying ? "Paying\u2026" : "Pay" })
3975
4053
  ] });
3976
4054
  }
3977
4055
 
3978
4056
  // src/usePaymentLink.ts
3979
- var import_react21 = require("react");
4057
+ var import_react22 = require("react");
3980
4058
  function usePaymentLink({
3981
4059
  token,
3982
4060
  environmentId,
@@ -3984,10 +4062,10 @@ function usePaymentLink({
3984
4062
  onPaid
3985
4063
  }) {
3986
4064
  const { client } = useBase316();
3987
- const [status2, setStatus] = (0, import_react21.useState)({ state: "loading" });
3988
- const onPaidRef = (0, import_react21.useRef)(onPaid);
4065
+ const [status2, setStatus] = (0, import_react22.useState)({ state: "loading" });
4066
+ const onPaidRef = (0, import_react22.useRef)(onPaid);
3989
4067
  onPaidRef.current = onPaid;
3990
- (0, import_react21.useEffect)(() => {
4068
+ (0, import_react22.useEffect)(() => {
3991
4069
  let stopped = false;
3992
4070
  let timer;
3993
4071
  const statusUrl = `${client.baseUrl}/pay/${encodeURIComponent(environmentId)}/${encodeURIComponent(token)}/status`;
@@ -4036,23 +4114,23 @@ function usePaymentLink({
4036
4114
  }
4037
4115
 
4038
4116
  // src/PricingTable.tsx
4039
- var import_react23 = require("react");
4117
+ var import_react24 = require("react");
4040
4118
 
4041
4119
  // src/usePlans.ts
4042
- var import_react22 = require("react");
4120
+ var import_react23 = require("react");
4043
4121
  var CHECKOUT_STATUSES = /* @__PURE__ */ new Set([402, 409]);
4044
4122
  function usePlans(options = {}) {
4045
4123
  const { client, token } = useBase316();
4046
- const [plans, setPlans] = (0, import_react22.useState)(null);
4047
- const [error, setError] = (0, import_react22.useState)(false);
4048
- const [busyPlanVersionId, setBusy] = (0, import_react22.useState)(null);
4049
- const [lastError, setLastError] = (0, import_react22.useState)(null);
4050
- const [ownPlanVersionId, setOwnPlanVersionId] = (0, import_react22.useState)(null);
4051
- const [managedBy, setManagedBy] = (0, import_react22.useState)(null);
4052
- const [reloadCount, setReloadCount] = (0, import_react22.useState)(0);
4124
+ const [plans, setPlans] = (0, import_react23.useState)(null);
4125
+ const [error, setError] = (0, import_react23.useState)(false);
4126
+ const [busyPlanVersionId, setBusy] = (0, import_react23.useState)(null);
4127
+ const [lastError, setLastError] = (0, import_react23.useState)(null);
4128
+ const [ownPlanVersionId, setOwnPlanVersionId] = (0, import_react23.useState)(null);
4129
+ const [managedBy, setManagedBy] = (0, import_react23.useState)(null);
4130
+ const [reloadCount, setReloadCount] = (0, import_react23.useState)(0);
4053
4131
  const supplied = options.currentPlanVersionId;
4054
4132
  const discover = supplied === void 0;
4055
- (0, import_react22.useEffect)(() => {
4133
+ (0, import_react23.useEffect)(() => {
4056
4134
  let cancelled = false;
4057
4135
  client.billing.plans().then((result) => {
4058
4136
  if (!cancelled) {
@@ -4068,7 +4146,7 @@ function usePlans(options = {}) {
4068
4146
  cancelled = true;
4069
4147
  };
4070
4148
  }, [client, reloadCount]);
4071
- (0, import_react22.useEffect)(() => {
4149
+ (0, import_react23.useEffect)(() => {
4072
4150
  if (!token) {
4073
4151
  return;
4074
4152
  }
@@ -4085,11 +4163,11 @@ function usePlans(options = {}) {
4085
4163
  cancelled = true;
4086
4164
  };
4087
4165
  }, [client, token, discover, reloadCount]);
4088
- const reload = (0, import_react22.useCallback)(() => {
4166
+ const reload = (0, import_react23.useCallback)(() => {
4089
4167
  setError(false);
4090
4168
  setReloadCount((count) => count + 1);
4091
4169
  }, []);
4092
- const selectPlan = (0, import_react22.useCallback)(
4170
+ const selectPlan = (0, import_react23.useCallback)(
4093
4171
  async (plan) => {
4094
4172
  setLastError(null);
4095
4173
  if (managedBy) {
@@ -4157,7 +4235,7 @@ function usePlans(options = {}) {
4157
4235
  }
4158
4236
 
4159
4237
  // src/PricingTable.tsx
4160
- var import_jsx_runtime23 = require("react/jsx-runtime");
4238
+ var import_jsx_runtime24 = require("react/jsx-runtime");
4161
4239
  function formatAmount(amount, currency) {
4162
4240
  if (amount === null) return "Free";
4163
4241
  const value = Number(amount);
@@ -4206,7 +4284,7 @@ function PricingTable({
4206
4284
  managedBy,
4207
4285
  selectPlan
4208
4286
  } = usePlans({ currentPlanVersionId });
4209
- const [scheduled, setScheduled] = (0, import_react23.useState)(null);
4287
+ const [scheduled, setScheduled] = (0, import_react24.useState)(null);
4210
4288
  async function choose(plan) {
4211
4289
  if (onSelectPlan) {
4212
4290
  await onSelectPlan(plan.planVersionId, plan);
@@ -4223,50 +4301,50 @@ function PricingTable({
4223
4301
  }
4224
4302
  }
4225
4303
  if (error) {
4226
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cls("b316-card", className), style, children: "Plans are unavailable right now." });
4304
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cls("b316-card", className), style, children: "Plans are unavailable right now." });
4227
4305
  }
4228
4306
  if (!plans) {
4229
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cls("b316-card", className), style, children: "Loading plans\u2026" });
4307
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cls("b316-card", className), style, children: "Loading plans\u2026" });
4230
4308
  }
4231
4309
  if (plans.length === 0) {
4232
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cls("b316-card", className), style, children: "No plans are published yet." });
4310
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cls("b316-card", className), style, children: "No plans are published yet." });
4233
4311
  }
4234
4312
  const anyTrial = plans.some((plan) => Boolean(plan.trialDays));
4235
4313
  const anyDescription = plans.some((plan) => Boolean(plan.description));
4236
4314
  const anyFeatured = plans.some((plan) => plan.key === featuredPlanKey);
4237
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: cls("b316-plans", className), style, children: [
4315
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: cls("b316-plans", className), style, children: [
4238
4316
  managedBy ? (
4239
4317
  // A client company's plan comes from the firm that runs it. The table
4240
4318
  // still shows what is on offer, with the current plan marked, but
4241
4319
  // nothing here can be bought: it would grant this account nothing.
4242
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "b316-plans-managed b316-muted", children: [
4320
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "b316-plans-managed b316-muted", children: [
4243
4321
  "Your plan is provided by ",
4244
4322
  managedBy.name ?? "the organization that manages your account",
4245
4323
  ". Ask them to change it."
4246
4324
  ] })
4247
- ) : lastError ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "b316-plans-error", role: "alert", children: lastError }) : scheduled ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "b316-plans-managed b316-muted", role: "status", children: scheduled }) : null,
4325
+ ) : lastError ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-plans-error", role: "alert", children: lastError }) : scheduled ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-plans-managed b316-muted", role: "status", children: scheduled }) : null,
4248
4326
  plans.map((plan) => {
4249
4327
  const base = plan.prices.find((price) => price.featureId === null) ?? plan.prices[0];
4250
4328
  const isCurrent = current === plan.planVersionId;
4251
4329
  const featured = featuredPlanKey === plan.key;
4252
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
4330
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
4253
4331
  "div",
4254
4332
  {
4255
4333
  className: featured ? "b316-card b316-plan b316-plan-featured" : "b316-card b316-plan",
4256
4334
  children: [
4257
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "b316-plan-head", children: [
4258
- anyFeatured ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: featured ? "b316-plan-badge" : "b316-plan-badge-spacer", children: featured ? "Recommended" : "\xA0" }) : null,
4259
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "b316-plan-name", children: plan.name }),
4260
- anyDescription ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "b316-plan-desc", children: plan.description ?? "\xA0" }) : null
4335
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "b316-plan-head", children: [
4336
+ anyFeatured ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: featured ? "b316-plan-badge" : "b316-plan-badge-spacer", children: featured ? "Recommended" : "\xA0" }) : null,
4337
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-plan-name", children: plan.name }),
4338
+ anyDescription ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-plan-desc", children: plan.description ?? "\xA0" }) : null
4261
4339
  ] }),
4262
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "b316-plan-pricing", children: [
4263
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "b316-plan-price", children: formatAmount(base?.amount ?? null, plan.currency) }),
4264
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "b316-plan-cadence", children: cadence(plan, base?.amount ?? null) }),
4265
- anyTrial ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "b316-plan-trial", children: describeTrial(plan, plans) ?? "\xA0" }) : null
4340
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "b316-plan-pricing", children: [
4341
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-plan-price", children: formatAmount(base?.amount ?? null, plan.currency) }),
4342
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-plan-cadence", children: cadence(plan, base?.amount ?? null) }),
4343
+ anyTrial ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-plan-trial", children: describeTrial(plan, plans) ?? "\xA0" }) : null
4266
4344
  ] }),
4267
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("ul", { className: "b316-plan-features", children: plan.entitlements.filter((entitlement) => entitlement.enabled).map((entitlement) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("li", { className: "b316-plan-feature", children: [
4268
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: entitlement.featureName }),
4269
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "b316-plan-feature-value", children: entitlement.limit === null ? "Unlimited" : (
4345
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("ul", { className: "b316-plan-features", children: plan.entitlements.filter((entitlement) => entitlement.enabled).map((entitlement) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("li", { className: "b316-plan-feature", children: [
4346
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: entitlement.featureName }),
4347
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "b316-plan-feature-value", children: entitlement.limit === null ? "Unlimited" : (
4270
4348
  // A usage price on the feature makes the limit an
4271
4349
  // allowance billed past, not a ceiling — the same
4272
4350
  // rule `check()` applies (any non-FLAT price).
@@ -4275,7 +4353,7 @@ function PricingTable({
4275
4353
  ) ? `${entitlement.limit} included` : entitlement.limit
4276
4354
  ) })
4277
4355
  ] }, entitlement.featureId)) }),
4278
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "b316-plan-action", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4356
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-plan-action", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4279
4357
  "button",
4280
4358
  {
4281
4359
  type: "button",
@@ -4297,11 +4375,11 @@ function PricingTable({
4297
4375
 
4298
4376
  // src/DataTable.tsx
4299
4377
  var import_sdk8 = require("@base316/sdk");
4300
- var import_react27 = require("react");
4378
+ var import_react28 = require("react");
4301
4379
 
4302
4380
  // src/fields.tsx
4303
4381
  var import_sdk6 = require("@base316/sdk");
4304
- var import_jsx_runtime24 = require("react/jsx-runtime");
4382
+ var import_jsx_runtime25 = require("react/jsx-runtime");
4305
4383
  function formatNumber(value, fraction = 0) {
4306
4384
  const number = Number(value);
4307
4385
  return Number.isFinite(number) ? new Intl.NumberFormat(void 0, {
@@ -4323,10 +4401,10 @@ function formatDuration(value) {
4323
4401
  }
4324
4402
  function FieldCell({ value, field, related }) {
4325
4403
  if (field.type === "RELATION") {
4326
- return related?.title ?? (related?.id ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("code", { className: "b316-muted", children: related.id }) : "\u2014");
4404
+ return related?.title ?? (related?.id ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("code", { className: "b316-muted", children: related.id }) : "\u2014");
4327
4405
  }
4328
4406
  if (value === null || value === void 0 || value === "") {
4329
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "b316-muted", children: "\u2014" });
4407
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "b316-muted", children: "\u2014" });
4330
4408
  }
4331
4409
  switch (field.type) {
4332
4410
  case "BOOLEAN":
@@ -4339,9 +4417,9 @@ function FieldCell({ value, field, related }) {
4339
4417
  return formatDuration(value);
4340
4418
  case "RATING": {
4341
4419
  const stars = Math.round(Number(value));
4342
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { "aria-label": `${stars} out of 5`, children: [
4420
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { "aria-label": `${stars} out of 5`, children: [
4343
4421
  "\u2605".repeat(stars),
4344
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "b316-muted", children: "\u2605".repeat(Math.max(0, 5 - stars)) })
4422
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "b316-muted", children: "\u2605".repeat(Math.max(0, 5 - stars)) })
4345
4423
  ] });
4346
4424
  }
4347
4425
  case "DATE":
@@ -4349,15 +4427,15 @@ function FieldCell({ value, field, related }) {
4349
4427
  case "DATETIME":
4350
4428
  return new Date(String(value)).toLocaleString();
4351
4429
  case "SELECT":
4352
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "b316-chip", children: String(value) });
4430
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "b316-chip", children: String(value) });
4353
4431
  case "MULTISELECT":
4354
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "b316-chips", children: (Array.isArray(value) ? value : [value]).map((item) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "b316-chip", children: String(item) }, String(item))) });
4432
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "b316-chips", children: (Array.isArray(value) ? value : [value]).map((item) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "b316-chip", children: String(item) }, String(item))) });
4355
4433
  case "URL":
4356
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("a", { href: String(value), target: "_blank", rel: "noreferrer noopener", children: String(value) });
4434
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("a", { href: String(value), target: "_blank", rel: "noreferrer noopener", children: String(value) });
4357
4435
  case "EMAIL":
4358
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("a", { href: `mailto:${String(value)}`, children: String(value) });
4436
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("a", { href: `mailto:${String(value)}`, children: String(value) });
4359
4437
  case "PHONE":
4360
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("a", { href: `tel:${String(value)}`, children: String(value) });
4438
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("a", { href: `tel:${String(value)}`, children: String(value) });
4361
4439
  case "ADDRESS":
4362
4440
  return (0, import_sdk6.formatAddress)(value);
4363
4441
  case "ATTACHMENT": {
@@ -4369,7 +4447,7 @@ function FieldCell({ value, field, related }) {
4369
4447
  return text.length > 80 ? `${text.slice(0, 80)}\u2026` : text;
4370
4448
  }
4371
4449
  case "JSON":
4372
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("code", { className: "b316-muted", children: JSON.stringify(value).slice(0, 60) });
4450
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("code", { className: "b316-muted", children: JSON.stringify(value).slice(0, 60) });
4373
4451
  default:
4374
4452
  return String(value);
4375
4453
  }
@@ -4390,7 +4468,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4390
4468
  function control() {
4391
4469
  switch (field.type) {
4392
4470
  case "LONGTEXT":
4393
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4471
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4394
4472
  "textarea",
4395
4473
  {
4396
4474
  ...common,
@@ -4400,7 +4478,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4400
4478
  }
4401
4479
  );
4402
4480
  case "BOOLEAN":
4403
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4481
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4404
4482
  "input",
4405
4483
  {
4406
4484
  ...common,
@@ -4411,22 +4489,22 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4411
4489
  }
4412
4490
  );
4413
4491
  case "SELECT":
4414
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
4492
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
4415
4493
  "select",
4416
4494
  {
4417
4495
  ...common,
4418
4496
  value: value === null || value === void 0 ? "" : String(value),
4419
4497
  onChange: (event) => onChange(event.target.value === "" ? null : event.target.value),
4420
4498
  children: [
4421
- field.required ? null : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "", children: "\u2014" }),
4422
- (field.options ?? []).map((option) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: option, children: option }, option))
4499
+ field.required ? null : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "", children: "\u2014" }),
4500
+ (field.options ?? []).map((option) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: option, children: option }, option))
4423
4501
  ]
4424
4502
  }
4425
4503
  );
4426
4504
  case "MULTISELECT": {
4427
4505
  const selected = new Set(Array.isArray(value) ? value.map(String) : []);
4428
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-choices", children: (field.options ?? []).map((option) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "b316-choice", children: [
4429
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4506
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "b316-choices", children: (field.options ?? []).map((option) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "b316-choice", children: [
4507
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4430
4508
  "input",
4431
4509
  {
4432
4510
  type: "checkbox",
@@ -4449,7 +4527,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4449
4527
  case "NUMBER":
4450
4528
  case "MONEY":
4451
4529
  case "PERCENT":
4452
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4530
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4453
4531
  "input",
4454
4532
  {
4455
4533
  ...common,
@@ -4460,7 +4538,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4460
4538
  }
4461
4539
  );
4462
4540
  case "RATING":
4463
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4541
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4464
4542
  "input",
4465
4543
  {
4466
4544
  ...common,
@@ -4474,8 +4552,8 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4474
4552
  );
4475
4553
  case "DURATION": {
4476
4554
  const minutes = value === null || value === void 0 ? "" : String(Number(value) / 60);
4477
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "b316-suffixed", children: [
4478
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4555
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "b316-suffixed", children: [
4556
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4479
4557
  "input",
4480
4558
  {
4481
4559
  ...common,
@@ -4485,11 +4563,11 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4485
4563
  onChange: (event) => onChange(event.target.value === "" ? null : Number(event.target.value) * 60)
4486
4564
  }
4487
4565
  ),
4488
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "b316-muted", children: "minutes" })
4566
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "b316-muted", children: "minutes" })
4489
4567
  ] });
4490
4568
  }
4491
4569
  case "DATE":
4492
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4570
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4493
4571
  "input",
4494
4572
  {
4495
4573
  ...common,
@@ -4499,7 +4577,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4499
4577
  }
4500
4578
  );
4501
4579
  case "DATETIME":
4502
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4580
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4503
4581
  "input",
4504
4582
  {
4505
4583
  ...common,
@@ -4512,7 +4590,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4512
4590
  );
4513
4591
  case "ADDRESS": {
4514
4592
  const address = value ?? {};
4515
- const part = (key, label) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4593
+ const part = (key, label) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4516
4594
  "input",
4517
4595
  {
4518
4596
  className: "b316-input",
@@ -4524,7 +4602,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4524
4602
  },
4525
4603
  key
4526
4604
  );
4527
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "b316-address", children: [
4605
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "b316-address", children: [
4528
4606
  part("line1", "Address line 1"),
4529
4607
  part("line2", "Address line 2"),
4530
4608
  part("city", "City"),
@@ -4534,7 +4612,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4534
4612
  ] });
4535
4613
  }
4536
4614
  case "EMAIL":
4537
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4615
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4538
4616
  "input",
4539
4617
  {
4540
4618
  ...common,
@@ -4544,7 +4622,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4544
4622
  }
4545
4623
  );
4546
4624
  case "URL":
4547
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4625
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4548
4626
  "input",
4549
4627
  {
4550
4628
  ...common,
@@ -4554,7 +4632,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4554
4632
  }
4555
4633
  );
4556
4634
  case "PHONE":
4557
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4635
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4558
4636
  "input",
4559
4637
  {
4560
4638
  ...common,
@@ -4564,7 +4642,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4564
4642
  }
4565
4643
  );
4566
4644
  default:
4567
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4645
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4568
4646
  "input",
4569
4647
  {
4570
4648
  ...common,
@@ -4575,24 +4653,24 @@ function FieldInput({ value, field, onChange, error, disabled }) {
4575
4653
  );
4576
4654
  }
4577
4655
  }
4578
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "b316-field", children: [
4579
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "b316-label", htmlFor: id, children: [
4656
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "b316-field", children: [
4657
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "b316-label", htmlFor: id, children: [
4580
4658
  field.label,
4581
- field.required ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "aria-hidden": "true", children: " *" }) : null
4659
+ field.required ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": "true", children: " *" }) : null
4582
4660
  ] }),
4583
4661
  control(),
4584
- field.description ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-hint", children: field.description }) : null,
4585
- error ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "b316-error", id: described, role: "alert", children: error }) : null
4662
+ field.description ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "b316-hint", children: field.description }) : null,
4663
+ error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "b316-error", id: described, role: "alert", children: error }) : null
4586
4664
  ] });
4587
4665
  }
4588
4666
 
4589
4667
  // src/RecordForm.tsx
4590
4668
  var import_sdk7 = require("@base316/sdk");
4591
- var import_react26 = require("react");
4669
+ var import_react27 = require("react");
4592
4670
 
4593
4671
  // src/RelationPicker.tsx
4594
- var import_react24 = require("react");
4595
- var import_jsx_runtime25 = require("react/jsx-runtime");
4672
+ var import_react25 = require("react");
4673
+ var import_jsx_runtime26 = require("react/jsx-runtime");
4596
4674
  function RelationPicker({
4597
4675
  field,
4598
4676
  value,
@@ -4602,13 +4680,13 @@ function RelationPicker({
4602
4680
  tenant
4603
4681
  }) {
4604
4682
  const { client, token } = useBase316();
4605
- const [query, setQuery] = (0, import_react24.useState)("");
4606
- const [results, setResults] = (0, import_react24.useState)([]);
4607
- const [chosenTitle, setChosenTitle] = (0, import_react24.useState)(null);
4608
- const [open, setOpen] = (0, import_react24.useState)(false);
4683
+ const [query, setQuery] = (0, import_react25.useState)("");
4684
+ const [results, setResults] = (0, import_react25.useState)([]);
4685
+ const [chosenTitle, setChosenTitle] = (0, import_react25.useState)(null);
4686
+ const [open, setOpen] = (0, import_react25.useState)(false);
4609
4687
  const id = `b316-field-${field.key}`;
4610
- const box = (0, import_react24.useRef)(null);
4611
- (0, import_react24.useEffect)(() => {
4688
+ const box = (0, import_react25.useRef)(null);
4689
+ (0, import_react25.useEffect)(() => {
4612
4690
  if (!token || !value || !field.relationTo) {
4613
4691
  setChosenTitle(null);
4614
4692
  return;
@@ -4623,7 +4701,7 @@ function RelationPicker({
4623
4701
  cancelled = true;
4624
4702
  };
4625
4703
  }, [client, token, value, field.relationTo, tenant]);
4626
- (0, import_react24.useEffect)(() => {
4704
+ (0, import_react25.useEffect)(() => {
4627
4705
  if (!token || !field.relationTo || !open) {
4628
4706
  return;
4629
4707
  }
@@ -4649,7 +4727,7 @@ function RelationPicker({
4649
4727
  clearTimeout(timer);
4650
4728
  };
4651
4729
  }, [client, token, field.relationTo, query, open, tenant]);
4652
- (0, import_react24.useEffect)(() => {
4730
+ (0, import_react25.useEffect)(() => {
4653
4731
  if (!open || typeof document === "undefined") {
4654
4732
  return;
4655
4733
  }
@@ -4663,14 +4741,14 @@ function RelationPicker({
4663
4741
  document.removeEventListener("mousedown", onDocumentClick);
4664
4742
  };
4665
4743
  }, [open]);
4666
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "b316-field", ref: box, children: [
4667
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "b316-label", htmlFor: id, children: [
4744
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "b316-field", ref: box, children: [
4745
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "b316-label", htmlFor: id, children: [
4668
4746
  field.label,
4669
- field.required ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": "true", children: " *" }) : null
4747
+ field.required ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "aria-hidden": "true", children: " *" }) : null
4670
4748
  ] }),
4671
- value && !open ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "b316-relation-chosen", children: [
4672
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: chosenTitle ?? value }),
4673
- disabled ? null : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4749
+ value && !open ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "b316-relation-chosen", children: [
4750
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: chosenTitle ?? value }),
4751
+ disabled ? null : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4674
4752
  "button",
4675
4753
  {
4676
4754
  type: "button",
@@ -4682,7 +4760,7 @@ function RelationPicker({
4682
4760
  children: "Change"
4683
4761
  }
4684
4762
  ),
4685
- disabled || field.required ? null : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4763
+ disabled || field.required ? null : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4686
4764
  "button",
4687
4765
  {
4688
4766
  type: "button",
@@ -4692,8 +4770,8 @@ function RelationPicker({
4692
4770
  children: "Clear"
4693
4771
  }
4694
4772
  )
4695
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
4696
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4773
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
4774
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4697
4775
  "input",
4698
4776
  {
4699
4777
  id,
@@ -4714,7 +4792,7 @@ function RelationPicker({
4714
4792
  }
4715
4793
  }
4716
4794
  ),
4717
- open ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("ul", { className: "b316-relation-results", id: `${id}-results`, role: "listbox", children: results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { className: "b316-muted b316-relation-empty", children: "No matches" }) : results.map((result) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4795
+ open ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "b316-relation-results", id: `${id}-results`, role: "listbox", children: results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { className: "b316-muted b316-relation-empty", children: "No matches" }) : results.map((result) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4718
4796
  "button",
4719
4797
  {
4720
4798
  type: "button",
@@ -4730,13 +4808,13 @@ function RelationPicker({
4730
4808
  }
4731
4809
  ) }, result.id)) }) : null
4732
4810
  ] }),
4733
- field.description ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "b316-hint", children: field.description }) : null,
4734
- error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null
4811
+ field.description ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "b316-hint", children: field.description }) : null,
4812
+ error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null
4735
4813
  ] });
4736
4814
  }
4737
4815
 
4738
4816
  // src/useCollection.ts
4739
- var import_react25 = require("react");
4817
+ var import_react26 = require("react");
4740
4818
  function fieldErrorFrom(cause) {
4741
4819
  const param = cause?.param;
4742
4820
  const message = cause instanceof Error ? cause.message : "That value was not accepted.";
@@ -4744,24 +4822,24 @@ function fieldErrorFrom(cause) {
4744
4822
  }
4745
4823
  function useCollection(collection, options = {}) {
4746
4824
  const { client, token } = useBase316();
4747
- const [schema, setSchema] = (0, import_react25.useState)(null);
4748
- const [records, setRecords] = (0, import_react25.useState)([]);
4749
- const [error, setError] = (0, import_react25.useState)(null);
4750
- const [loading, setLoading] = (0, import_react25.useState)(true);
4751
- const [total, setTotal] = (0, import_react25.useState)(0);
4752
- const [cursor, setCursor] = (0, import_react25.useState)(null);
4753
- const [reloadCount, setReloadCount] = (0, import_react25.useState)(0);
4754
- const [search, setSearch] = (0, import_react25.useState)("");
4755
- const [filters, setFilters] = (0, import_react25.useState)([]);
4756
- const [sort, setSort] = (0, import_react25.useState)(
4825
+ const [schema, setSchema] = (0, import_react26.useState)(null);
4826
+ const [records, setRecords] = (0, import_react26.useState)([]);
4827
+ const [error, setError] = (0, import_react26.useState)(null);
4828
+ const [loading, setLoading] = (0, import_react26.useState)(true);
4829
+ const [total, setTotal] = (0, import_react26.useState)(0);
4830
+ const [cursor, setCursor] = (0, import_react26.useState)(null);
4831
+ const [reloadCount, setReloadCount] = (0, import_react26.useState)(0);
4832
+ const [search, setSearch] = (0, import_react26.useState)("");
4833
+ const [filters, setFilters] = (0, import_react26.useState)([]);
4834
+ const [sort, setSort] = (0, import_react26.useState)(
4757
4835
  options.sort ?? null
4758
4836
  );
4759
- const [fieldErrors, setFieldErrors] = (0, import_react25.useState)({});
4760
- const [saving, setSaving] = (0, import_react25.useState)(false);
4837
+ const [fieldErrors, setFieldErrors] = (0, import_react26.useState)({});
4838
+ const [saving, setSaving] = (0, import_react26.useState)(false);
4761
4839
  const { tenant, limit, recordId } = options;
4762
4840
  const fixedFilters = JSON.stringify(options.filters ?? []);
4763
- const scope = (0, import_react25.useMemo)(() => tenant ? { tenant } : void 0, [tenant]);
4764
- (0, import_react25.useEffect)(() => {
4841
+ const scope = (0, import_react26.useMemo)(() => tenant ? { tenant } : void 0, [tenant]);
4842
+ (0, import_react26.useEffect)(() => {
4765
4843
  if (!token) {
4766
4844
  return;
4767
4845
  }
@@ -4780,7 +4858,7 @@ function useCollection(collection, options = {}) {
4780
4858
  cancelled = true;
4781
4859
  };
4782
4860
  }, [client, token, collection, scope]);
4783
- (0, import_react25.useEffect)(() => {
4861
+ (0, import_react26.useEffect)(() => {
4784
4862
  if (!token || !schema) {
4785
4863
  return;
4786
4864
  }
@@ -4850,10 +4928,10 @@ function useCollection(collection, options = {}) {
4850
4928
  scope,
4851
4929
  reloadCount
4852
4930
  ]);
4853
- const reload = (0, import_react25.useCallback)(() => {
4931
+ const reload = (0, import_react26.useCallback)(() => {
4854
4932
  setReloadCount((count) => count + 1);
4855
4933
  }, []);
4856
- const loadMore = (0, import_react25.useCallback)(() => {
4934
+ const loadMore = (0, import_react26.useCallback)(() => {
4857
4935
  if (!token || !cursor) {
4858
4936
  return;
4859
4937
  }
@@ -4877,7 +4955,7 @@ function useCollection(collection, options = {}) {
4877
4955
  setLoading(false);
4878
4956
  });
4879
4957
  }, [client, token, collection, cursor, fixedFilters, filters, search, sort, limit, scope]);
4880
- const toggleSort = (0, import_react25.useCallback)((field) => {
4958
+ const toggleSort = (0, import_react26.useCallback)((field) => {
4881
4959
  setSort((current) => {
4882
4960
  if (current?.field !== field) {
4883
4961
  return { field, direction: "asc" };
@@ -4885,7 +4963,7 @@ function useCollection(collection, options = {}) {
4885
4963
  return current.direction === "asc" ? { field, direction: "desc" } : null;
4886
4964
  });
4887
4965
  }, []);
4888
- const create = (0, import_react25.useCallback)(
4966
+ const create = (0, import_react26.useCallback)(
4889
4967
  async (fields) => {
4890
4968
  if (!token) {
4891
4969
  return null;
@@ -4905,7 +4983,7 @@ function useCollection(collection, options = {}) {
4905
4983
  },
4906
4984
  [client, token, collection, scope, reload]
4907
4985
  );
4908
- const update = (0, import_react25.useCallback)(
4986
+ const update = (0, import_react26.useCallback)(
4909
4987
  async (id, fields) => {
4910
4988
  if (!token) {
4911
4989
  return null;
@@ -4927,7 +5005,7 @@ function useCollection(collection, options = {}) {
4927
5005
  },
4928
5006
  [client, token, collection, scope]
4929
5007
  );
4930
- const remove = (0, import_react25.useCallback)(
5008
+ const remove = (0, import_react26.useCallback)(
4931
5009
  async (id) => {
4932
5010
  if (!token) {
4933
5011
  return false;
@@ -4972,7 +5050,7 @@ function useCollection(collection, options = {}) {
4972
5050
  }
4973
5051
 
4974
5052
  // src/RecordForm.tsx
4975
- var import_jsx_runtime26 = require("react/jsx-runtime");
5053
+ var import_jsx_runtime27 = require("react/jsx-runtime");
4976
5054
  function RecordForm({
4977
5055
  collection,
4978
5056
  recordId,
@@ -4993,20 +5071,20 @@ function RecordForm({
4993
5071
  recordId
4994
5072
  }
4995
5073
  );
4996
- const [values, setValues] = (0, import_react26.useState)(defaults ?? {});
4997
- const [loaded, setLoaded] = (0, import_react26.useState)(!recordId);
5074
+ const [values, setValues] = (0, import_react27.useState)(defaults ?? {});
5075
+ const [loaded, setLoaded] = (0, import_react27.useState)(!recordId);
4998
5076
  const existing = recordId ? records.find((record) => record.id === recordId) : void 0;
4999
- (0, import_react26.useEffect)(() => {
5077
+ (0, import_react27.useEffect)(() => {
5000
5078
  if (existing && !loaded) {
5001
5079
  setValues(existing.fields);
5002
5080
  setLoaded(true);
5003
5081
  }
5004
5082
  }, [existing, loaded]);
5005
5083
  if (error) {
5006
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5084
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5007
5085
  }
5008
5086
  if (!schema || !loaded) {
5009
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5087
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5010
5088
  }
5011
5089
  const editable = schema.fields.filter((field) => !(0, import_sdk7.specFor)(field).computed);
5012
5090
  async function submit(event) {
@@ -5016,11 +5094,11 @@ function RecordForm({
5016
5094
  onSaved?.(saved.id);
5017
5095
  }
5018
5096
  }
5019
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
5020
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "b316-form-title", children: recordId ? `Edit ${schema.name.toLowerCase()}` : `New ${schema.name.toLowerCase()}` }),
5021
- fieldErrors._ ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "b316-error", role: "alert", children: fieldErrors._ }) : null,
5097
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
5098
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h3", { className: "b316-form-title", children: recordId ? `Edit ${schema.name.toLowerCase()}` : `New ${schema.name.toLowerCase()}` }),
5099
+ fieldErrors._ ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "b316-error", role: "alert", children: fieldErrors._ }) : null,
5022
5100
  editable.map(
5023
- (field) => field.type === "RELATION" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5101
+ (field) => field.type === "RELATION" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5024
5102
  RelationPicker,
5025
5103
  {
5026
5104
  field,
@@ -5031,7 +5109,7 @@ function RecordForm({
5031
5109
  onChange: (next) => setValues((current) => ({ ...current, [field.key]: next }))
5032
5110
  },
5033
5111
  field.key
5034
- ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5112
+ ) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5035
5113
  FieldInput,
5036
5114
  {
5037
5115
  field,
@@ -5043,15 +5121,15 @@ function RecordForm({
5043
5121
  field.key
5044
5122
  )
5045
5123
  ),
5046
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "b316-form-actions", children: [
5047
- onCancel ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "b316-button-quiet", onClick: onCancel, disabled: saving, children: "Cancel" }) : null,
5048
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "submit", className: "b316-button", disabled: saving, children: saving ? "Saving\u2026" : "Save" })
5124
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "b316-form-actions", children: [
5125
+ onCancel ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: "b316-button-quiet", onClick: onCancel, disabled: saving, children: "Cancel" }) : null,
5126
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "submit", className: "b316-button", disabled: saving, children: saving ? "Saving\u2026" : "Save" })
5049
5127
  ] })
5050
5128
  ] });
5051
5129
  }
5052
5130
 
5053
5131
  // src/DataTable.tsx
5054
- var import_jsx_runtime27 = require("react/jsx-runtime");
5132
+ var import_jsx_runtime28 = require("react/jsx-runtime");
5055
5133
  function DataTable({
5056
5134
  collection,
5057
5135
  columns,
@@ -5080,13 +5158,13 @@ function DataTable({
5080
5158
  loadMore,
5081
5159
  remove
5082
5160
  } = useCollection(collection, options);
5083
- const [editing, setEditing] = (0, import_react27.useState)(null);
5084
- const [removeFailed, setRemoveFailed] = (0, import_react27.useState)(null);
5161
+ const [editing, setEditing] = (0, import_react28.useState)(null);
5162
+ const [removeFailed, setRemoveFailed] = (0, import_react28.useState)(null);
5085
5163
  if (error) {
5086
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5164
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5087
5165
  }
5088
5166
  if (!schema) {
5089
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5167
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5090
5168
  }
5091
5169
  const shown = columns ? (
5092
5170
  // Ordered by what was asked for, not by the schema: a caller naming
@@ -5095,10 +5173,10 @@ function DataTable({
5095
5173
  ) : schema.fields;
5096
5174
  const searchable = schema.fields.some((field) => (0, import_sdk8.specFor)(field).capabilities.searchable);
5097
5175
  const writable = canWrite && !readOnly;
5098
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cls("b316-table-wrap", className), style, children: [
5099
- removeFailed ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "b316-error", role: "alert", children: removeFailed }) : null,
5100
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "b316-table-bar", children: [
5101
- searchable && !hideSearch ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5176
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cls("b316-table-wrap", className), style, children: [
5177
+ removeFailed ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-error", role: "alert", children: removeFailed }) : null,
5178
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "b316-table-bar", children: [
5179
+ searchable && !hideSearch ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5102
5180
  "input",
5103
5181
  {
5104
5182
  type: "search",
@@ -5108,25 +5186,25 @@ function DataTable({
5108
5186
  value: search,
5109
5187
  onChange: (event) => setSearch(event.target.value)
5110
5188
  }
5111
- ) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", {}),
5112
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "b316-table-actions", children: [
5113
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "b316-muted", children: [
5189
+ ) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", {}),
5190
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "b316-table-actions", children: [
5191
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "b316-muted", children: [
5114
5192
  total,
5115
5193
  " ",
5116
5194
  total === 1 ? schema.name.toLowerCase() : schema.namePlural.toLowerCase()
5117
5195
  ] }),
5118
- writable ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("button", { type: "button", className: "b316-button", onClick: () => setEditing("new"), children: [
5196
+ writable ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("button", { type: "button", className: "b316-button", onClick: () => setEditing("new"), children: [
5119
5197
  "New ",
5120
5198
  schema.name.toLowerCase()
5121
5199
  ] }) : null
5122
5200
  ] })
5123
5201
  ] }),
5124
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "b316-table-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("table", { className: "b316-table", children: [
5125
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("tr", { children: [
5202
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-table-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("table", { className: "b316-table", children: [
5203
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("tr", { children: [
5126
5204
  shown.map((field) => {
5127
5205
  const sortable = (0, import_sdk8.specFor)(field).capabilities.sortable;
5128
5206
  const active = sort?.field === field.key;
5129
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("th", { scope: "col", "aria-sort": ariaSort(active, sort?.direction), children: sortable ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5207
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("th", { scope: "col", "aria-sort": ariaSort(active, sort?.direction), children: sortable ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
5130
5208
  "button",
5131
5209
  {
5132
5210
  type: "button",
@@ -5134,20 +5212,20 @@ function DataTable({
5134
5212
  onClick: () => toggleSort(field.key),
5135
5213
  children: [
5136
5214
  field.label,
5137
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": "true", children: active ? sort?.direction === "desc" ? " \u2193" : " \u2191" : " \u2195" })
5215
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { "aria-hidden": "true", children: active ? sort?.direction === "desc" ? " \u2193" : " \u2191" : " \u2195" })
5138
5216
  ]
5139
5217
  }
5140
5218
  ) : field.label }, field.key);
5141
5219
  }),
5142
- writable ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("th", { scope: "col", className: "b316-table-rowactions" }) : null
5220
+ writable ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("th", { scope: "col", className: "b316-table-rowactions" }) : null
5143
5221
  ] }) }),
5144
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("tbody", { children: records.map((record) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5222
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("tbody", { children: records.map((record) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
5145
5223
  "tr",
5146
5224
  {
5147
5225
  className: onSelect ? "b316-row-clickable" : void 0,
5148
5226
  onClick: onSelect ? () => onSelect(record) : void 0,
5149
5227
  children: [
5150
- shown.map((field) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("td", { children: renderCell?.(record, field) ?? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5228
+ shown.map((field) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("td", { children: renderCell?.(record, field) ?? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5151
5229
  FieldCell,
5152
5230
  {
5153
5231
  value: record.fields[field.key] ?? null,
@@ -5155,8 +5233,8 @@ function DataTable({
5155
5233
  related: record.related[field.key]
5156
5234
  }
5157
5235
  ) }, field.key)),
5158
- writable ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("td", { className: "b316-table-rowactions", children: [
5159
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5236
+ writable ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("td", { className: "b316-table-rowactions", children: [
5237
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5160
5238
  "button",
5161
5239
  {
5162
5240
  type: "button",
@@ -5168,7 +5246,7 @@ function DataTable({
5168
5246
  children: "Edit"
5169
5247
  }
5170
5248
  ),
5171
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5249
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5172
5250
  ConfirmButton,
5173
5251
  {
5174
5252
  className: "b316-button-quiet b316-danger",
@@ -5192,10 +5270,10 @@ function DataTable({
5192
5270
  record.id
5193
5271
  )) })
5194
5272
  ] }) }),
5195
- records.length === 0 && !loading ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "b316-empty", children: emptyState ?? `No ${schema.namePlural.toLowerCase()} yet.` }) : null,
5196
- loading ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "b316-empty", children: "Loading\u2026" }) : null,
5197
- hasMore ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "b316-table-more", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: "Load more" }) }) : null,
5198
- editing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5273
+ records.length === 0 && !loading ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-empty", children: emptyState ?? `No ${schema.namePlural.toLowerCase()} yet.` }) : null,
5274
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-empty", children: "Loading\u2026" }) : null,
5275
+ hasMore ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-table-more", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: "Load more" }) }) : null,
5276
+ editing ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5199
5277
  RecordForm,
5200
5278
  {
5201
5279
  collection,
@@ -5219,8 +5297,8 @@ function ariaSort(active, direction) {
5219
5297
 
5220
5298
  // src/Kanban.tsx
5221
5299
  var import_sdk9 = require("@base316/sdk");
5222
- var import_react28 = require("react");
5223
- var import_jsx_runtime28 = require("react/jsx-runtime");
5300
+ var import_react29 = require("react");
5301
+ var import_jsx_runtime29 = require("react/jsx-runtime");
5224
5302
  function Kanban({
5225
5303
  collection,
5226
5304
  groupBy,
@@ -5237,17 +5315,17 @@ function Kanban({
5237
5315
  limit: options.limit ?? 100,
5238
5316
  ...options
5239
5317
  });
5240
- const [dragging, setDragging] = (0, import_react28.useState)(null);
5241
- const [over, setOver] = (0, import_react28.useState)(null);
5318
+ const [dragging, setDragging] = (0, import_react29.useState)(null);
5319
+ const [over, setOver] = (0, import_react29.useState)(null);
5242
5320
  if (error) {
5243
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5321
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5244
5322
  }
5245
5323
  if (!schema) {
5246
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5324
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5247
5325
  }
5248
5326
  const field = groupBy ? schema.fields.find((candidate) => candidate.key === groupBy) ?? null : (0, import_sdk9.defaultGroupFieldOf)(schema.fields);
5249
5327
  if (!field || !(0, import_sdk9.specFor)(field).capabilities.groupable) {
5250
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("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.` });
5328
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("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.` });
5251
5329
  }
5252
5330
  const columns = columnsFor(field);
5253
5331
  const shown = cardFields ? cardFields.map((key) => schema.fields.find((candidate) => candidate.key === key)).filter((candidate) => Boolean(candidate)) : (
@@ -5264,12 +5342,12 @@ function Kanban({
5264
5342
  }
5265
5343
  await update(record.id, { [field.key]: value });
5266
5344
  }
5267
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cls("b316-board-wrap", className), style, children: [
5268
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-board", role: "list", children: columns.map((column) => {
5345
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cls("b316-board-wrap", className), style, children: [
5346
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "b316-board", role: "list", children: columns.map((column) => {
5269
5347
  const inColumn = records.filter(
5270
5348
  (record) => String(record.fields[field.key] ?? "") === String(column.value ?? "")
5271
5349
  );
5272
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
5350
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
5273
5351
  "section",
5274
5352
  {
5275
5353
  className: over === String(column.value) ? "b316-board-column b316-board-over" : "b316-board-column",
@@ -5293,12 +5371,12 @@ function Kanban({
5293
5371
  setDragging(null);
5294
5372
  },
5295
5373
  children: [
5296
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("header", { className: "b316-board-head", children: [
5297
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "b316-board-title", children: column.label }),
5298
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "b316-muted", children: inColumn.length })
5374
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("header", { className: "b316-board-head", children: [
5375
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "b316-board-title", children: column.label }),
5376
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "b316-muted", children: inColumn.length })
5299
5377
  ] }),
5300
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "b316-board-cards", children: [
5301
- inColumn.map((record) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
5378
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "b316-board-cards", children: [
5379
+ inColumn.map((record) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
5302
5380
  "article",
5303
5381
  {
5304
5382
  className: "b316-board-card",
@@ -5310,10 +5388,10 @@ function Kanban({
5310
5388
  },
5311
5389
  onClick: onSelect ? () => onSelect(record) : void 0,
5312
5390
  children: [
5313
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-board-card-title", children: record.title ?? "Untitled" }),
5314
- shown.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "b316-board-card-field", children: [
5315
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "b316-muted", children: candidate.label }),
5316
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5391
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "b316-board-card-title", children: record.title ?? "Untitled" }),
5392
+ shown.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "b316-board-card-field", children: [
5393
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "b316-muted", children: candidate.label }),
5394
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5317
5395
  FieldCell,
5318
5396
  {
5319
5397
  value: record.fields[candidate.key] ?? null,
@@ -5326,9 +5404,9 @@ function Kanban({
5326
5404
  // Dragging is not reachable by keyboard and is awkward on a
5327
5405
  // phone. This is the same action by other means, not a
5328
5406
  // lesser fallback.
5329
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "b316-board-move", children: [
5330
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "b316-muted", children: "Move to" }),
5331
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5407
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "b316-board-move", children: [
5408
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "b316-muted", children: "Move to" }),
5409
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5332
5410
  "select",
5333
5411
  {
5334
5412
  className: "b316-input",
@@ -5340,7 +5418,7 @@ function Kanban({
5340
5418
  );
5341
5419
  void move(record, chosen?.value ?? null);
5342
5420
  },
5343
- children: columns.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("option", { value: String(candidate.value), children: candidate.label }, String(candidate.value)))
5421
+ children: columns.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: String(candidate.value), children: candidate.label }, String(candidate.value)))
5344
5422
  }
5345
5423
  )
5346
5424
  ] })
@@ -5349,14 +5427,14 @@ function Kanban({
5349
5427
  },
5350
5428
  record.id
5351
5429
  )),
5352
- inColumn.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-board-empty", children: emptyState ?? "Nothing here" }) : null
5430
+ inColumn.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "b316-board-empty", children: emptyState ?? "Nothing here" }) : null
5353
5431
  ] })
5354
5432
  ]
5355
5433
  },
5356
5434
  String(column.value)
5357
5435
  );
5358
5436
  }) }),
5359
- hasMore ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "b316-table-more", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: [
5437
+ hasMore ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "b316-table-more", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: [
5360
5438
  "Showing ",
5361
5439
  records.length,
5362
5440
  " of ",
@@ -5378,8 +5456,8 @@ function columnsFor(field) {
5378
5456
 
5379
5457
  // src/Chart.tsx
5380
5458
  var import_sdk10 = require("@base316/sdk");
5381
- var import_react29 = require("react");
5382
- var import_jsx_runtime29 = require("react/jsx-runtime");
5459
+ var import_react30 = require("react");
5460
+ var import_jsx_runtime30 = require("react/jsx-runtime");
5383
5461
  function Chart({
5384
5462
  collection,
5385
5463
  x,
@@ -5398,7 +5476,7 @@ function Chart({
5398
5476
  limit: options.limit ?? 200,
5399
5477
  ...options
5400
5478
  });
5401
- const axis = (0, import_react29.useMemo)(() => {
5479
+ const axis = (0, import_react30.useMemo)(() => {
5402
5480
  if (!schema) {
5403
5481
  return null;
5404
5482
  }
@@ -5406,35 +5484,35 @@ function Chart({
5406
5484
  const chosen = x ? schema.fields.find((field) => field.key === x) ?? null : timeFields[0] ?? null;
5407
5485
  return chosen && (0, import_sdk10.specFor)(chosen).capabilities.timeAxis ? chosen : null;
5408
5486
  }, [schema, x]);
5409
- const measure = (0, import_react29.useMemo)(() => {
5487
+ const measure = (0, import_react30.useMemo)(() => {
5410
5488
  if (!schema || !y) {
5411
5489
  return null;
5412
5490
  }
5413
5491
  const candidates = (0, import_sdk10.fieldsAggregatableBy)(schema.fields, aggregate);
5414
5492
  return candidates.find((field) => field.key === y) ?? null;
5415
5493
  }, [schema, y, aggregate]);
5416
- const buckets = (0, import_react29.useMemo)(
5494
+ const buckets = (0, import_react30.useMemo)(
5417
5495
  () => axis ? bucketise(records, axis, measure, y ? aggregate : "count", bucket) : [],
5418
5496
  [records, axis, measure, aggregate, bucket, y]
5419
5497
  );
5420
5498
  if (error) {
5421
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5499
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5422
5500
  }
5423
5501
  if (!schema || loading) {
5424
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5502
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5425
5503
  }
5426
5504
  if (!axis) {
5427
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("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.` });
5505
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("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.` });
5428
5506
  }
5429
5507
  if (y && !measure) {
5430
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cls("b316-card", className), style, children: `"${y}" cannot be ${aggregate === "avg" ? "averaged" : `combined with ${aggregate}`}.` });
5508
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: cls("b316-card", className), style, children: `"${y}" cannot be ${aggregate === "avg" ? "averaged" : `combined with ${aggregate}`}.` });
5431
5509
  }
5432
5510
  const peak = Math.max(...buckets.map((entry) => entry.value), 0);
5433
5511
  const heading = title ?? `${measure ? `${aggregate} of ${measure.label}` : schema.namePlural} by ${axis.label}`;
5434
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("figure", { className: cls("b316-card b316-chart", className), style, children: [
5435
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("figcaption", { className: "b316-chart-title", children: heading }),
5436
- buckets.length === 0 || peak === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "b316-empty", children: "Nothing to chart yet." }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "b316-chart-plot", style: { height }, children: buckets.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "b316-chart-col", children: [
5437
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5512
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("figure", { className: cls("b316-card b316-chart", className), style, children: [
5513
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("figcaption", { className: "b316-chart-title", children: heading }),
5514
+ buckets.length === 0 || peak === 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "b316-empty", children: "Nothing to chart yet." }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "b316-chart-plot", style: { height }, children: buckets.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "b316-chart-col", children: [
5515
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5438
5516
  "div",
5439
5517
  {
5440
5518
  className: "b316-chart-bar",
@@ -5442,18 +5520,18 @@ function Chart({
5442
5520
  title: `${entry.label}: ${format(entry.value)}`
5443
5521
  }
5444
5522
  ),
5445
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "b316-chart-label", children: entry.label })
5523
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "b316-chart-label", children: entry.label })
5446
5524
  ] }, entry.key)) }),
5447
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("details", { className: "b316-chart-data", children: [
5448
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("summary", { children: "Values" }),
5449
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("table", { className: "b316-table", children: [
5450
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("tr", { children: [
5451
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("th", { scope: "col", children: axis.label }),
5452
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("th", { scope: "col", children: measure ? measure.label : "Count" })
5525
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("details", { className: "b316-chart-data", children: [
5526
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("summary", { children: "Values" }),
5527
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("table", { className: "b316-table", children: [
5528
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("tr", { children: [
5529
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("th", { scope: "col", children: axis.label }),
5530
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("th", { scope: "col", children: measure ? measure.label : "Count" })
5453
5531
  ] }) }),
5454
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("tbody", { children: buckets.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("tr", { children: [
5455
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("td", { children: entry.label }),
5456
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("td", { children: format(entry.value) })
5532
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("tbody", { children: buckets.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("tr", { children: [
5533
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { children: entry.label }),
5534
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { children: format(entry.value) })
5457
5535
  ] }, entry.key)) })
5458
5536
  ] })
5459
5537
  ] })
@@ -5512,8 +5590,8 @@ function combine(values, aggregate) {
5512
5590
 
5513
5591
  // src/RecordDetail.tsx
5514
5592
  var import_sdk11 = require("@base316/sdk");
5515
- var import_react30 = require("react");
5516
- var import_jsx_runtime30 = require("react/jsx-runtime");
5593
+ var import_react31 = require("react");
5594
+ var import_jsx_runtime31 = require("react/jsx-runtime");
5517
5595
  function RecordDetail({
5518
5596
  collection,
5519
5597
  recordId,
@@ -5529,23 +5607,23 @@ function RecordDetail({
5529
5607
  tenant,
5530
5608
  recordId
5531
5609
  });
5532
- const [editing, setEditing] = (0, import_react30.useState)(false);
5610
+ const [editing, setEditing] = (0, import_react31.useState)(false);
5533
5611
  const record = records.find((candidate) => candidate.id === recordId);
5534
5612
  if (error) {
5535
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5613
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5536
5614
  }
5537
5615
  if (!schema || loading) {
5538
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5616
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5539
5617
  }
5540
5618
  if (!record) {
5541
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: cls("b316-card", className), style, children: [
5619
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cls("b316-card", className), style, children: [
5542
5620
  "That ",
5543
5621
  schema.name.toLowerCase(),
5544
5622
  " is not available."
5545
5623
  ] });
5546
5624
  }
5547
5625
  if (editing) {
5548
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5626
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5549
5627
  RecordForm,
5550
5628
  {
5551
5629
  collection,
@@ -5559,12 +5637,12 @@ function RecordDetail({
5559
5637
  );
5560
5638
  }
5561
5639
  const writable = canWrite && !readOnly;
5562
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: cls("b316-card b316-detail", className), style, children: [
5563
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "b316-detail-head", children: [
5564
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h3", { className: "b316-detail-title", children: record.title ?? schema.name }),
5565
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "b316-detail-actions", children: [
5566
- writable ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", className: "b316-button-quiet", onClick: () => setEditing(true), children: "Edit" }) : null,
5567
- writable ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5640
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cls("b316-card b316-detail", className), style, children: [
5641
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "b316-detail-head", children: [
5642
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("h3", { className: "b316-detail-title", children: record.title ?? schema.name }),
5643
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "b316-detail-actions", children: [
5644
+ writable ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: "b316-button-quiet", onClick: () => setEditing(true), children: "Edit" }) : null,
5645
+ writable ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5568
5646
  ConfirmButton,
5569
5647
  {
5570
5648
  className: "b316-button-quiet b316-danger",
@@ -5577,15 +5655,15 @@ function RecordDetail({
5577
5655
  children: "Delete"
5578
5656
  }
5579
5657
  ) : null,
5580
- onClose ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", className: "b316-button-quiet", onClick: onClose, children: "Close" }) : null
5658
+ onClose ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: "b316-button-quiet", onClick: onClose, children: "Close" }) : null
5581
5659
  ] })
5582
5660
  ] }),
5583
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dl", { className: "b316-detail-fields", children: schema.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "b316-detail-row", children: [
5584
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("dt", { className: "b316-label", children: [
5661
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dl", { className: "b316-detail-fields", children: schema.fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "b316-detail-row", children: [
5662
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("dt", { className: "b316-label", children: [
5585
5663
  field.label,
5586
- (0, import_sdk11.specFor)(field).computed ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "b316-muted", children: " (calculated)" }) : null
5664
+ (0, import_sdk11.specFor)(field).computed ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "b316-muted", children: " (calculated)" }) : null
5587
5665
  ] }),
5588
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5666
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5589
5667
  FieldCell,
5590
5668
  {
5591
5669
  value: record.fields[field.key] ?? null,
@@ -5599,25 +5677,57 @@ function RecordDetail({
5599
5677
  }
5600
5678
 
5601
5679
  // src/SubscriptionManager.tsx
5602
- var import_react31 = require("react");
5603
- var import_jsx_runtime31 = require("react/jsx-runtime");
5680
+ var import_react32 = require("react");
5681
+ var import_jsx_runtime32 = require("react/jsx-runtime");
5604
5682
  function statusLabel(status2) {
5605
5683
  const words = status2.toLowerCase().split("_");
5606
5684
  return words.map((w, i) => i === 0 ? w.charAt(0).toUpperCase() + w.slice(1) : w).join(" ");
5607
5685
  }
5686
+ var REASONS = [
5687
+ { value: "TOO_EXPENSIVE", label: "It costs too much" },
5688
+ { value: "NOT_USING", label: "I am not using it enough" },
5689
+ { value: "MISSING_FEATURES", label: "It is missing something I need" },
5690
+ { value: "SWITCHING", label: "I am switching to something else" },
5691
+ { value: "TECHNICAL_ISSUES", label: "It did not work well for me" },
5692
+ { value: "TEMPORARY", label: "I only needed it for a while" },
5693
+ { value: "OTHER", label: "Something else" }
5694
+ ];
5695
+ function describeRetentionOffer(offer, currency) {
5696
+ let amount;
5697
+ if (offer.type === "PERCENTAGE") {
5698
+ amount = `${Number(offer.percentOff ?? "0")}% off`;
5699
+ } else {
5700
+ try {
5701
+ amount = `${new Intl.NumberFormat(void 0, {
5702
+ style: "currency",
5703
+ currency: offer.currency ?? currency
5704
+ }).format(Number(offer.amountOff ?? "0"))} off`;
5705
+ } catch {
5706
+ amount = `${offer.amountOff} ${offer.currency ?? currency} off`;
5707
+ }
5708
+ }
5709
+ if (offer.duration === "FOREVER") {
5710
+ return `${amount} for as long as you stay subscribed`;
5711
+ }
5712
+ const periods = offer.duration === "ONCE" ? 1 : offer.durationInPeriods ?? 1;
5713
+ return periods === 1 ? `${amount} your next invoice` : `${amount} your next ${periods} invoices`;
5714
+ }
5608
5715
  function SubscriptionManager({
5609
5716
  onChange,
5610
5717
  className,
5611
5718
  style
5612
5719
  }) {
5613
5720
  const { client, token, loading: sessionLoading } = useBase316();
5614
- const [subscription, setSubscription] = (0, import_react31.useState)(null);
5615
- const [loading, setLoading] = (0, import_react31.useState)(true);
5616
- const [managedBy, setManagedBy] = (0, import_react31.useState)(null);
5617
- const [schedule, setSchedule] = (0, import_react31.useState)([]);
5618
- const [busy, setBusy] = (0, import_react31.useState)(false);
5619
- const [error, setError] = (0, import_react31.useState)(null);
5620
- const load = (0, import_react31.useCallback)(async () => {
5721
+ const [subscription, setSubscription] = (0, import_react32.useState)(null);
5722
+ const [loading, setLoading] = (0, import_react32.useState)(true);
5723
+ const [managedBy, setManagedBy] = (0, import_react32.useState)(null);
5724
+ const [schedule, setSchedule] = (0, import_react32.useState)([]);
5725
+ const [busy, setBusy] = (0, import_react32.useState)(false);
5726
+ const [error, setError] = (0, import_react32.useState)(null);
5727
+ const [step, setStep] = (0, import_react32.useState)({ kind: "idle" });
5728
+ const [reason, setReason] = (0, import_react32.useState)(null);
5729
+ const [comment, setComment] = (0, import_react32.useState)("");
5730
+ const load = (0, import_react32.useCallback)(async () => {
5621
5731
  if (!token) {
5622
5732
  setSubscription(null);
5623
5733
  setLoading(false);
@@ -5635,7 +5745,7 @@ function SubscriptionManager({
5635
5745
  setLoading(false);
5636
5746
  }
5637
5747
  }, [client, token]);
5638
- (0, import_react31.useEffect)(() => {
5748
+ (0, import_react32.useEffect)(() => {
5639
5749
  void load();
5640
5750
  }, [load]);
5641
5751
  const act = async (change, failure) => {
@@ -5653,29 +5763,29 @@ function SubscriptionManager({
5653
5763
  }
5654
5764
  };
5655
5765
  if (sessionLoading || loading) {
5656
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5766
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
5657
5767
  }
5658
5768
  if (!token) {
5659
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cls("b316-card", className), style, children: "Sign in to manage your subscription." });
5769
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cls("b316-card", className), style, children: "Sign in to manage your subscription." });
5660
5770
  }
5661
5771
  if (error) {
5662
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5772
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
5663
5773
  }
5664
5774
  if (!subscription) {
5665
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cls("b316-card", className), style, children: "You are not subscribed to a plan." });
5775
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cls("b316-card", className), style, children: "You are not subscribed to a plan." });
5666
5776
  }
5667
5777
  const renews = new Date(subscription.currentPeriodEnd).toLocaleDateString();
5668
5778
  const next = schedule[0] ?? null;
5669
5779
  const nextOn = next?.effectiveAt ? new Date(next.effectiveAt).toLocaleDateString() : renews;
5670
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cls("b316-card", className), style, children: [
5671
- error ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
5672
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "b316-plan-name", children: subscription.planVersion.plan.name }),
5673
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "b316-muted", children: [
5780
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: cls("b316-card", className), style, children: [
5781
+ error ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
5782
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-plan-name", children: subscription.planVersion.plan.name }),
5783
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "b316-muted", children: [
5674
5784
  statusLabel(subscription.status),
5675
5785
  " \xB7 ",
5676
5786
  subscription.cancelAtPeriodEnd ? `Ends ${renews}` : `Renews ${renews}`
5677
5787
  ] }),
5678
- next && !managedBy ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "b316-muted", role: "status", style: { marginTop: 10 }, children: [
5788
+ next && !managedBy ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "b316-muted", role: "status", style: { marginTop: 10 }, children: [
5679
5789
  "Moves to ",
5680
5790
  next.plan.name,
5681
5791
  " on ",
@@ -5683,7 +5793,7 @@ function SubscriptionManager({
5683
5793
  ". You keep ",
5684
5794
  subscription.planVersion.plan.name,
5685
5795
  " until then.",
5686
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5796
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5687
5797
  "button",
5688
5798
  {
5689
5799
  type: "button",
@@ -5708,17 +5818,17 @@ function SubscriptionManager({
5708
5818
  }
5709
5819
  ) })
5710
5820
  ] }) : null,
5711
- managedBy ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { className: "b316-muted", children: [
5821
+ managedBy ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("p", { className: "b316-muted", children: [
5712
5822
  "Provided by ",
5713
5823
  managedBy.name ?? "the organization that manages your account",
5714
5824
  ". Ask them to change or cancel it."
5715
- ] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { children: [
5716
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { className: "b316-muted", children: [
5825
+ ] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { children: [
5826
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("p", { className: "b316-muted", children: [
5717
5827
  "This subscription will not renew. You keep access until ",
5718
5828
  renews,
5719
5829
  "."
5720
5830
  ] }),
5721
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5831
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5722
5832
  "button",
5723
5833
  {
5724
5834
  type: "button",
@@ -5728,29 +5838,140 @@ function SubscriptionManager({
5728
5838
  children: busy ? "Working\u2026" : "Resume subscription"
5729
5839
  }
5730
5840
  )
5731
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { style: { marginTop: 14 }, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5732
- ConfirmButton,
5841
+ ] }) : step.kind === "offer" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("section", { style: { marginTop: 14 }, "aria-label": "Retention offer", children: [
5842
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-plan-name", children: step.cancellation.offer.headline ?? "Before you go" }),
5843
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "b316-muted", children: step.cancellation.offer.message ?? `Stay on ${subscription.planVersion.plan.name} and get ${describeRetentionOffer(
5844
+ step.cancellation.offer,
5845
+ step.cancellation.currency
5846
+ )}.` }),
5847
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
5848
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5849
+ "button",
5850
+ {
5851
+ type: "button",
5852
+ className: "b316-button",
5853
+ disabled: busy,
5854
+ onClick: () => void act(async () => {
5855
+ await client.billing.acceptRetentionOffer(token, step.cancellation.id);
5856
+ setStep({ kind: "idle" });
5857
+ }, "Could not apply the offer. Try again."),
5858
+ children: busy ? "Working\u2026" : "Accept offer and stay"
5859
+ }
5860
+ ),
5861
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5862
+ "button",
5863
+ {
5864
+ type: "button",
5865
+ className: "b316-button b316-button-secondary",
5866
+ disabled: busy,
5867
+ onClick: () => void act(async () => {
5868
+ await client.billing.confirmCancellation(token, step.cancellation.id);
5869
+ setStep({ kind: "idle" });
5870
+ }, "Could not cancel. Try again."),
5871
+ children: "No thanks, cancel"
5872
+ }
5873
+ )
5874
+ ] }),
5875
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("p", { className: "b316-muted", children: [
5876
+ "If you cancel, you keep access until ",
5877
+ renews,
5878
+ "."
5879
+ ] })
5880
+ ] }) : step.kind === "survey" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
5881
+ "form",
5882
+ {
5883
+ style: { marginTop: 14 },
5884
+ onSubmit: (event) => {
5885
+ event.preventDefault();
5886
+ void act(async () => {
5887
+ const started = await client.billing.startCancellation(token, {
5888
+ reason,
5889
+ comment: comment.trim() || null
5890
+ });
5891
+ if (started.offer) {
5892
+ setStep({ kind: "offer", cancellation: { ...started, offer: started.offer } });
5893
+ return;
5894
+ }
5895
+ await client.billing.confirmCancellation(token, started.id);
5896
+ setStep({ kind: "idle" });
5897
+ }, "Could not cancel. Try again.");
5898
+ },
5899
+ children: [
5900
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("p", { className: "b316-muted", children: [
5901
+ "You keep access until ",
5902
+ renews,
5903
+ ". It will not renew after that."
5904
+ ] }),
5905
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("fieldset", { className: "b316-fieldset", children: [
5906
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("legend", { className: "b316-label", children: "Why are you leaving? (optional)" }),
5907
+ REASONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
5908
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5909
+ "input",
5910
+ {
5911
+ type: "radio",
5912
+ name: "b316-cancel-reason",
5913
+ value: option.value,
5914
+ checked: reason === option.value,
5915
+ onChange: () => setReason(option.value)
5916
+ }
5917
+ ),
5918
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: option.label })
5919
+ ] }, option.value))
5920
+ ] }),
5921
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "b316-field", children: [
5922
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "b316-label", children: "Anything else? (optional)" }),
5923
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5924
+ "textarea",
5925
+ {
5926
+ className: "b316-input",
5927
+ rows: 3,
5928
+ maxLength: 2e3,
5929
+ value: comment,
5930
+ onChange: (event) => setComment(event.target.value)
5931
+ }
5932
+ )
5933
+ ] }),
5934
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
5935
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "submit", className: "b316-button b316-button-secondary", disabled: busy, children: busy ? "Working\u2026" : "Cancel subscription" }),
5936
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
5937
+ "button",
5938
+ {
5939
+ type: "button",
5940
+ className: "b316-button",
5941
+ disabled: busy,
5942
+ onClick: () => setStep({ kind: "idle" }),
5943
+ children: [
5944
+ "Keep ",
5945
+ subscription.planVersion.plan.name
5946
+ ]
5947
+ }
5948
+ )
5949
+ ] })
5950
+ ]
5951
+ }
5952
+ ) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { style: { marginTop: 14 }, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
5953
+ "button",
5733
5954
  {
5955
+ type: "button",
5734
5956
  className: "b316-button b316-button-secondary",
5735
- confirmLabel: `Cancel at the end of the period (${renews})`,
5736
5957
  disabled: busy,
5737
- onConfirm: () => (
5738
- // Cancels at period end: the user paid for the period they
5739
- // are in, and ending it now would forfeit it.
5740
- act(() => client.billing.cancel(token), "Could not cancel. Try again.")
5741
- ),
5742
- children: busy ? "Working\u2026" : "Cancel subscription"
5958
+ onClick: () => {
5959
+ setReason(null);
5960
+ setComment("");
5961
+ setStep({ kind: "survey" });
5962
+ },
5963
+ children: "Cancel subscription"
5743
5964
  }
5744
5965
  ) })
5745
5966
  ] });
5746
5967
  }
5747
5968
 
5748
5969
  // src/BillingPortal.tsx
5749
- var import_react35 = require("react");
5970
+ var import_react36 = require("react");
5750
5971
 
5751
5972
  // src/CreditBalances.tsx
5752
- var import_react32 = require("react");
5753
- var import_jsx_runtime32 = require("react/jsx-runtime");
5973
+ var import_react33 = require("react");
5974
+ var import_jsx_runtime33 = require("react/jsx-runtime");
5754
5975
  function units(value) {
5755
5976
  return value === null ? "Unlimited" : Number(value).toLocaleString("en");
5756
5977
  }
@@ -5785,10 +6006,10 @@ function Feature({
5785
6006
  }) {
5786
6007
  const { client, token } = useBase316();
5787
6008
  const setting = feature.autoRecharge;
5788
- const [busy, setBusy] = (0, import_react32.useState)(false);
5789
- const [error, setError] = (0, import_react32.useState)(null);
5790
- const [saved, setSaved] = (0, import_react32.useState)(null);
5791
- const [pack, setPack] = (0, import_react32.useState)(feature.packs[0]?.id ?? "");
6009
+ const [busy, setBusy] = (0, import_react33.useState)(false);
6010
+ const [error, setError] = (0, import_react33.useState)(null);
6011
+ const [saved, setSaved] = (0, import_react33.useState)(null);
6012
+ const [pack, setPack] = (0, import_react33.useState)(feature.packs[0]?.id ?? "");
5792
6013
  const unit = feature.unit ? ` ${feature.unit}` : "";
5793
6014
  const warning = status(feature);
5794
6015
  const buy = async () => {
@@ -5842,33 +6063,33 @@ function Feature({
5842
6063
  setBusy(false);
5843
6064
  }
5844
6065
  };
5845
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "b316-card b316-credit-balance", children: [
5846
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-label", children: feature.featureName }),
5847
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { children: [
5848
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("strong", { children: units(feature.remaining) }),
6066
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "b316-card b316-credit-balance", children: [
6067
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-label", children: feature.featureName }),
6068
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { children: [
6069
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("strong", { children: units(feature.remaining) }),
5849
6070
  unit,
5850
6071
  " left"
5851
6072
  ] }),
5852
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "b316-muted", children: [
6073
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "b316-muted", children: [
5853
6074
  feature.allowance === null ? "Unlimited allowance" : `${units(feature.allowanceRemaining)} of ${units(feature.allowance)} included this period`,
5854
6075
  " ",
5855
6076
  "\xB7 ",
5856
6077
  units(feature.purchasedRemaining),
5857
6078
  " purchased"
5858
6079
  ] }),
5859
- warning && !managed ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-error", role: "alert", children: warning }) : null,
5860
- error ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
5861
- saved ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-notice", role: "status", children: saved }) : null,
5862
- managed || feature.packs.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
5863
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "b316-row", style: { marginTop: 12 }, children: [
5864
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6080
+ warning && !managed ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-error", role: "alert", children: warning }) : null,
6081
+ error ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
6082
+ saved ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-notice", role: "status", children: saved }) : null,
6083
+ managed || feature.packs.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
6084
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "b316-row", style: { marginTop: 12 }, children: [
6085
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5865
6086
  "select",
5866
6087
  {
5867
6088
  className: "b316-input",
5868
6089
  "aria-label": "Pack to buy",
5869
6090
  value: pack,
5870
6091
  onChange: (event) => setPack(event.target.value),
5871
- children: feature.packs.map((option) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("option", { value: option.id, children: [
6092
+ children: feature.packs.map((option) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("option", { value: option.id, children: [
5872
6093
  option.name,
5873
6094
  " \u2014 ",
5874
6095
  units(option.units),
@@ -5877,7 +6098,7 @@ function Feature({
5877
6098
  ] }, option.id))
5878
6099
  }
5879
6100
  ),
5880
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6101
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5881
6102
  "button",
5882
6103
  {
5883
6104
  type: "button",
@@ -5888,19 +6109,19 @@ function Feature({
5888
6109
  }
5889
6110
  )
5890
6111
  ] }),
5891
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("form", { onSubmit: save, style: { marginTop: 16 }, children: [
5892
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "b316-checkbox", children: [
5893
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("input", { type: "checkbox", name: "enabled", defaultChecked: setting?.enabled ?? false }),
6112
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("form", { onSubmit: save, style: { marginTop: 16 }, children: [
6113
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("label", { className: "b316-checkbox", children: [
6114
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("input", { type: "checkbox", name: "enabled", defaultChecked: setting?.enabled ?? false }),
5894
6115
  " ",
5895
6116
  "Buy credits automatically when my balance runs low"
5896
6117
  ] }),
5897
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "b316-field", children: [
5898
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "b316-label", children: [
6118
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("label", { className: "b316-field", children: [
6119
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "b316-label", children: [
5899
6120
  "When fewer than this many",
5900
6121
  unit,
5901
6122
  " are left"
5902
6123
  ] }),
5903
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6124
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5904
6125
  "input",
5905
6126
  {
5906
6127
  className: "b316-input",
@@ -5911,21 +6132,21 @@ function Feature({
5911
6132
  }
5912
6133
  )
5913
6134
  ] }),
5914
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "b316-field", children: [
5915
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "b316-label", children: "Buy" }),
5916
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6135
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("label", { className: "b316-field", children: [
6136
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "b316-label", children: "Buy" }),
6137
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5917
6138
  "select",
5918
6139
  {
5919
6140
  className: "b316-input",
5920
6141
  name: "creditPackId",
5921
6142
  defaultValue: setting?.creditPackId ?? feature.packs[0]?.id,
5922
- children: feature.packs.map((option) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: option.id, children: option.name }, option.id))
6143
+ children: feature.packs.map((option) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("option", { value: option.id, children: option.name }, option.id))
5923
6144
  }
5924
6145
  )
5925
6146
  ] }),
5926
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "b316-field", children: [
5927
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "b316-label", children: "At most this many times a month" }),
5928
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6147
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("label", { className: "b316-field", children: [
6148
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "b316-label", children: "At most this many times a month" }),
6149
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5929
6150
  "input",
5930
6151
  {
5931
6152
  className: "b316-input",
@@ -5935,13 +6156,13 @@ function Feature({
5935
6156
  }
5936
6157
  )
5937
6158
  ] }),
5938
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "b316-field", children: [
5939
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "b316-label", children: [
6159
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("label", { className: "b316-field", children: [
6160
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "b316-label", children: [
5940
6161
  "Spending at most (",
5941
6162
  setting?.currency ?? feature.packs[0]?.currency ?? "USD",
5942
6163
  ") a month"
5943
6164
  ] }),
5944
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6165
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5945
6166
  "input",
5946
6167
  {
5947
6168
  className: "b316-input",
@@ -5951,16 +6172,16 @@ function Feature({
5951
6172
  }
5952
6173
  )
5953
6174
  ] }),
5954
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "submit", className: "b316-button", disabled: busy, children: "Save auto-recharge" })
6175
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "submit", className: "b316-button", disabled: busy, children: "Save auto-recharge" })
5955
6176
  ] })
5956
6177
  ] })
5957
6178
  ] });
5958
6179
  }
5959
6180
  function CreditBalances({ onChange, className, style }) {
5960
6181
  const { client, token, loading: sessionLoading } = useBase316();
5961
- const [state, setState] = (0, import_react32.useState)({ kind: "loading" });
5962
- const [version, setVersion] = (0, import_react32.useState)(0);
5963
- (0, import_react32.useEffect)(() => {
6182
+ const [state, setState] = (0, import_react33.useState)({ kind: "loading" });
6183
+ const [version, setVersion] = (0, import_react33.useState)(0);
6184
+ (0, import_react33.useEffect)(() => {
5964
6185
  if (!token) return;
5965
6186
  let cancelled = false;
5966
6187
  client.billing.credits(token).then((credits2) => {
@@ -5973,24 +6194,24 @@ function CreditBalances({ onChange, className, style }) {
5973
6194
  cancelled = true;
5974
6195
  };
5975
6196
  }, [client, token, version]);
5976
- const wrap = (content) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cls("b316-credit-balances", className), style, children: content });
6197
+ const wrap = (content) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cls("b316-credit-balances", className), style, children: content });
5977
6198
  if (sessionLoading || !token || state.kind === "loading") return null;
5978
6199
  if (state.kind === "error") {
5979
6200
  return wrap(
5980
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-card", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "b316-error", role: "alert", children: "Could not load your credits." }) })
6201
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-card", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-error", role: "alert", children: "Could not load your credits." }) })
5981
6202
  );
5982
6203
  }
5983
6204
  const { credits } = state;
5984
6205
  if (credits.features.length === 0) return null;
5985
6206
  return wrap(
5986
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
5987
- credits.managedBy ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("p", { className: "b316-muted", children: [
6207
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
6208
+ credits.managedBy ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("p", { className: "b316-muted", children: [
5988
6209
  "Credits for this account come from",
5989
6210
  " ",
5990
6211
  credits.managedBy.name ?? "the organization that manages it",
5991
6212
  ", which manages them."
5992
6213
  ] }) : null,
5993
- credits.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6214
+ credits.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
5994
6215
  Feature,
5995
6216
  {
5996
6217
  feature,
@@ -6007,19 +6228,19 @@ function CreditBalances({ onChange, className, style }) {
6007
6228
  }
6008
6229
 
6009
6230
  // src/PaymentMethod.tsx
6010
- var import_react33 = require("react");
6011
- var import_jsx_runtime33 = require("react/jsx-runtime");
6231
+ var import_react34 = require("react");
6232
+ var import_jsx_runtime34 = require("react/jsx-runtime");
6012
6233
  function brandName(brand) {
6013
6234
  if (!brand) return "Card";
6014
6235
  return brand.charAt(0).toUpperCase() + brand.slice(1);
6015
6236
  }
6016
6237
  function PaymentMethod({ returnUrl, className, style }) {
6017
6238
  const { client, token, loading: sessionLoading } = useBase316();
6018
- const [state, setState] = (0, import_react33.useState)({ kind: "loading" });
6019
- const [busy, setBusy] = (0, import_react33.useState)(false);
6020
- const [error, setError] = (0, import_react33.useState)(null);
6021
- const [version, setVersion] = (0, import_react33.useState)(0);
6022
- (0, import_react33.useEffect)(() => {
6239
+ const [state, setState] = (0, import_react34.useState)({ kind: "loading" });
6240
+ const [busy, setBusy] = (0, import_react34.useState)(false);
6241
+ const [error, setError] = (0, import_react34.useState)(null);
6242
+ const [version, setVersion] = (0, import_react34.useState)(0);
6243
+ (0, import_react34.useEffect)(() => {
6023
6244
  if (!token) return;
6024
6245
  let cancelled = false;
6025
6246
  client.billing.paymentMethods(token).then((result) => {
@@ -6035,7 +6256,7 @@ function PaymentMethod({ returnUrl, className, style }) {
6035
6256
  cancelled = true;
6036
6257
  };
6037
6258
  }, [client, token, version]);
6038
- const wrap = (content) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: cls("b316-card b316-payment-method", className), style, children: content });
6259
+ const wrap = (content) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: cls("b316-card b316-payment-method", className), style, children: content });
6039
6260
  if (sessionLoading) return wrap("Loading\u2026");
6040
6261
  if (!token) return wrap("Sign in to manage your payment method.");
6041
6262
  switch (state.kind) {
@@ -6043,11 +6264,11 @@ function PaymentMethod({ returnUrl, className, style }) {
6043
6264
  return wrap("Loading\u2026");
6044
6265
  case "error":
6045
6266
  return wrap(
6046
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-error", role: "alert", children: "Could not load your payment method." })
6267
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "b316-error", role: "alert", children: "Could not load your payment method." })
6047
6268
  );
6048
6269
  case "managed":
6049
6270
  return wrap(
6050
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "b316-muted", children: "Your plan is paid for by the organization that manages it." })
6271
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "b316-muted", children: "Your plan is paid for by the organization that manages it." })
6051
6272
  );
6052
6273
  }
6053
6274
  const card = state.cards.find((saved) => saved.isDefault) ?? null;
@@ -6066,31 +6287,31 @@ function PaymentMethod({ returnUrl, className, style }) {
6066
6287
  }
6067
6288
  };
6068
6289
  return wrap(
6069
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
6070
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-label", children: "Payment method" }),
6071
- card ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { children: [
6072
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { children: [
6290
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
6291
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "b316-label", children: "Payment method" }),
6292
+ card ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { children: [
6293
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { children: [
6073
6294
  brandName(card.brand),
6074
6295
  " ending ",
6075
6296
  card.last4 ?? "????"
6076
6297
  ] }),
6077
- card.expMonth && card.expYear ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "b316-muted", children: [
6298
+ card.expMonth && card.expYear ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-muted", children: [
6078
6299
  "Expires ",
6079
6300
  String(card.expMonth).padStart(2, "0"),
6080
6301
  "/",
6081
6302
  card.expYear
6082
6303
  ] }) : null
6083
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "b316-muted", children: "No card on file." }),
6084
- others.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { style: { marginTop: 12 }, children: [
6085
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-label", children: "Other saved cards" }),
6086
- others.map((saved) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "b316-row", style: { marginTop: 6 }, children: [
6087
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { children: [
6304
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "b316-muted", children: "No card on file." }),
6305
+ others.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { style: { marginTop: 12 }, children: [
6306
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "b316-label", children: "Other saved cards" }),
6307
+ others.map((saved) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-row", style: { marginTop: 6 }, children: [
6308
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { children: [
6088
6309
  brandName(saved.brand),
6089
6310
  " ending ",
6090
6311
  saved.last4 ?? "????"
6091
6312
  ] }),
6092
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { children: [
6093
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
6313
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { children: [
6314
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
6094
6315
  "button",
6095
6316
  {
6096
6317
  type: "button",
@@ -6104,7 +6325,7 @@ function PaymentMethod({ returnUrl, className, style }) {
6104
6325
  }
6105
6326
  ),
6106
6327
  " ",
6107
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
6328
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
6108
6329
  "button",
6109
6330
  {
6110
6331
  type: "button",
@@ -6120,8 +6341,8 @@ function PaymentMethod({ returnUrl, className, style }) {
6120
6341
  ] })
6121
6342
  ] }, saved.id))
6122
6343
  ] }) : null,
6123
- error ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
6124
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
6344
+ error ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
6345
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
6125
6346
  "button",
6126
6347
  {
6127
6348
  type: "button",
@@ -6150,8 +6371,8 @@ function PaymentMethod({ returnUrl, className, style }) {
6150
6371
  }
6151
6372
 
6152
6373
  // src/PlanChangeReview.tsx
6153
- var import_react34 = require("react");
6154
- var import_jsx_runtime34 = require("react/jsx-runtime");
6374
+ var import_react35 = require("react");
6375
+ var import_jsx_runtime35 = require("react/jsx-runtime");
6155
6376
  function money5(amount, currency) {
6156
6377
  if (amount === null) return "\u2014";
6157
6378
  const value = Number(amount);
@@ -6184,12 +6405,12 @@ function PlanChangeReview({
6184
6405
  style
6185
6406
  }) {
6186
6407
  const { client, token } = useBase316();
6187
- const [timing, setTiming] = (0, import_react34.useState)(void 0);
6188
- const [preview, setPreview] = (0, import_react34.useState)(null);
6189
- const [error, setError] = (0, import_react34.useState)(null);
6190
- const [needsCard, setNeedsCard] = (0, import_react34.useState)(false);
6191
- const [busy, setBusy] = (0, import_react34.useState)(false);
6192
- (0, import_react34.useEffect)(() => {
6408
+ const [timing, setTiming] = (0, import_react35.useState)(void 0);
6409
+ const [preview, setPreview] = (0, import_react35.useState)(null);
6410
+ const [error, setError] = (0, import_react35.useState)(null);
6411
+ const [needsCard, setNeedsCard] = (0, import_react35.useState)(false);
6412
+ const [busy, setBusy] = (0, import_react35.useState)(false);
6413
+ (0, import_react35.useEffect)(() => {
6193
6414
  if (!token) return;
6194
6415
  let cancelled = false;
6195
6416
  client.billing.previewPlanChange(token, planVersionId, timing).then((result) => {
@@ -6206,7 +6427,7 @@ function PlanChangeReview({
6206
6427
  cancelled = true;
6207
6428
  };
6208
6429
  }, [client, token, planVersionId, timing]);
6209
- const confirm = (0, import_react34.useCallback)(async () => {
6430
+ const confirm = (0, import_react35.useCallback)(async () => {
6210
6431
  if (!token || !preview) return;
6211
6432
  setBusy(true);
6212
6433
  setError(null);
@@ -6227,7 +6448,7 @@ function PlanChangeReview({
6227
6448
  setBusy(false);
6228
6449
  }
6229
6450
  }, [client, token, preview, planVersionId, onDone]);
6230
- const addCard = (0, import_react34.useCallback)(async () => {
6451
+ const addCard = (0, import_react35.useCallback)(async () => {
6231
6452
  if (onNeedsCard) {
6232
6453
  onNeedsCard();
6233
6454
  return;
@@ -6241,12 +6462,12 @@ function PlanChangeReview({
6241
6462
  setError("Cards cannot be added here right now.");
6242
6463
  }
6243
6464
  }, [client, token, onNeedsCard]);
6244
- const card = (content) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: cls("b316-card b316-plan-review", className), style, children: content });
6465
+ const card = (content) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: cls("b316-card b316-plan-review", className), style, children: content });
6245
6466
  if (error && !preview) {
6246
6467
  return card(
6247
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
6248
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "b316-error", role: "alert", children: error }),
6249
- onCancel ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: "Back" }) : null
6468
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
6469
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-error", role: "alert", children: error }),
6470
+ onCancel ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: "Back" }) : null
6250
6471
  ] })
6251
6472
  );
6252
6473
  }
@@ -6259,26 +6480,26 @@ function PlanChangeReview({
6259
6480
  const otherReason = preview.timings[other]?.reason ?? null;
6260
6481
  const changes = preview.entitlements.filter((change) => change.change !== "UNCHANGED");
6261
6482
  return card(
6262
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
6263
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-plan-name", children: [
6483
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
6484
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "b316-plan-name", children: [
6264
6485
  "Change to ",
6265
6486
  to.planName
6266
6487
  ] }),
6267
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-muted", children: [
6488
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "b316-muted", children: [
6268
6489
  "From ",
6269
6490
  from.planName
6270
6491
  ] }),
6271
- error ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
6272
- changes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "b316-muted", children: "Every feature stays the same." }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("table", { className: "b316-review-table", children: [
6273
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("tr", { children: [
6274
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("th", { children: "Feature" }),
6275
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("th", { children: from.planName }),
6276
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("th", { children: to.planName })
6492
+ error ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
6493
+ changes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "b316-muted", children: "Every feature stays the same." }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("table", { className: "b316-review-table", children: [
6494
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("tr", { children: [
6495
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("th", { children: "Feature" }),
6496
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("th", { children: from.planName }),
6497
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("th", { children: to.planName })
6277
6498
  ] }) }),
6278
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("tbody", { children: changes.map((change) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("tr", { children: [
6279
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("td", { children: change.featureName }),
6280
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("td", { children: limitText(change.before, change.type) }),
6281
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
6499
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("tbody", { children: changes.map((change) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("tr", { children: [
6500
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("td", { children: change.featureName }),
6501
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("td", { children: limitText(change.before, change.type) }),
6502
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
6282
6503
  "td",
6283
6504
  {
6284
6505
  className: change.change === "GAINED" || change.change === "INCREASED" ? "b316-review-gain" : "b316-review-loss",
@@ -6287,40 +6508,40 @@ function PlanChangeReview({
6287
6508
  )
6288
6509
  ] }, change.featureId)) })
6289
6510
  ] }),
6290
- preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { children: [
6511
+ preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("p", { children: [
6291
6512
  "The change happens now. Your trial carries on until ",
6292
6513
  day4(now.trialEndsAt),
6293
6514
  ", and nothing is charged before then."
6294
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { children: [
6295
- Number(now.credit) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-row", children: [
6296
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "b316-muted", children: [
6515
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { children: [
6516
+ Number(now.credit) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "b316-row", children: [
6517
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "b316-muted", children: [
6297
6518
  "Credit for the unused part of ",
6298
6519
  from.planName
6299
6520
  ] }),
6300
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "b316-num", children: [
6521
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "b316-num", children: [
6301
6522
  "\u2212",
6302
6523
  money5(now.credit, from.currency)
6303
6524
  ] })
6304
6525
  ] }) : null,
6305
- Number(now.closingUsage) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-row", children: [
6306
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "b316-muted", children: "Usage so far this period" }),
6307
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "b316-num", children: money5(now.closingUsage, from.currency) })
6526
+ Number(now.closingUsage) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "b316-row", children: [
6527
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "b316-muted", children: "Usage so far this period" }),
6528
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "b316-num", children: money5(now.closingUsage, from.currency) })
6308
6529
  ] }) : null,
6309
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-row", children: [
6310
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "b316-muted", children: [
6530
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "b316-row", children: [
6531
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "b316-muted", children: [
6311
6532
  to.planName,
6312
6533
  ", ",
6313
6534
  day4(now.newPeriod.start),
6314
6535
  " \u2013 ",
6315
6536
  day4(now.newPeriod.end)
6316
6537
  ] }),
6317
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "b316-num", children: money5(now.newPeriodCharge, to.currency) })
6538
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "b316-num", children: money5(now.newPeriodCharge, to.currency) })
6318
6539
  ] }),
6319
- now.net !== null ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-row b316-invoice-total", children: [
6320
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: "Due now" }),
6321
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "b316-num", children: money5(now.net, to.currency) })
6540
+ now.net !== null ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "b316-row b316-invoice-total", children: [
6541
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: "Due now" }),
6542
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "b316-num", children: money5(now.net, to.currency) })
6322
6543
  ] }) : null
6323
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { children: [
6544
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("p", { children: [
6324
6545
  "You keep ",
6325
6546
  from.planName,
6326
6547
  " until ",
@@ -6333,7 +6554,7 @@ function PlanChangeReview({
6333
6554
  preview.atPeriodEnd.nextInvoice.currency
6334
6555
  )}.` : ""
6335
6556
  ] }),
6336
- otherOpen ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
6557
+ otherOpen ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
6337
6558
  "button",
6338
6559
  {
6339
6560
  type: "button",
@@ -6344,12 +6565,12 @@ function PlanChangeReview({
6344
6565
  },
6345
6566
  children: other === "NOW" ? "Change now instead" : "Wait until the end of the period instead"
6346
6567
  }
6347
- ) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "b316-muted", children: TIMING_CLOSED[otherReason] }) : null,
6348
- needsCard ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-notice", role: "status", children: [
6568
+ ) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "b316-muted", children: TIMING_CLOSED[otherReason] }) : null,
6569
+ needsCard ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "b316-notice", role: "status", children: [
6349
6570
  "A card is needed for a change that is charged now.",
6350
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "b316-review-actions", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: "b316-button", onClick: () => void addCard(), children: "Add a card" }) })
6351
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "b316-review-actions", children: [
6352
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
6571
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-review-actions", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("button", { type: "button", className: "b316-button", onClick: () => void addCard(), children: "Add a card" }) })
6572
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "b316-review-actions", children: [
6573
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
6353
6574
  "button",
6354
6575
  {
6355
6576
  type: "button",
@@ -6359,7 +6580,7 @@ function PlanChangeReview({
6359
6580
  children: busy ? "Working\u2026" : preview.timing === "NOW" ? `Change to ${to.planName} now` : `Schedule ${to.planName}`
6360
6581
  }
6361
6582
  ),
6362
- onCancel ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: [
6583
+ onCancel ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: [
6363
6584
  "Keep ",
6364
6585
  from.planName
6365
6586
  ] }) : null
@@ -6369,7 +6590,7 @@ function PlanChangeReview({
6369
6590
  }
6370
6591
 
6371
6592
  // src/BillingPortal.tsx
6372
- var import_jsx_runtime35 = require("react/jsx-runtime");
6593
+ var import_jsx_runtime36 = require("react/jsx-runtime");
6373
6594
  function BillingPortal({
6374
6595
  returnUrl,
6375
6596
  featuredPlanKey,
@@ -6379,12 +6600,12 @@ function BillingPortal({
6379
6600
  style
6380
6601
  }) {
6381
6602
  const { client, token, loading: sessionLoading } = useBase316();
6382
- const [overview, setOverview] = (0, import_react35.useState)(null);
6383
- const [failed, setFailed] = (0, import_react35.useState)(false);
6384
- const [version, setVersion] = (0, import_react35.useState)(0);
6385
- const [reviewing, setReviewing] = (0, import_react35.useState)(null);
6386
- const [notice, setNotice] = (0, import_react35.useState)(null);
6387
- (0, import_react35.useEffect)(() => {
6603
+ const [overview, setOverview] = (0, import_react36.useState)(null);
6604
+ const [failed, setFailed] = (0, import_react36.useState)(false);
6605
+ const [version, setVersion] = (0, import_react36.useState)(0);
6606
+ const [reviewing, setReviewing] = (0, import_react36.useState)(null);
6607
+ const [notice, setNotice] = (0, import_react36.useState)(null);
6608
+ (0, import_react36.useEffect)(() => {
6388
6609
  if (!token) return;
6389
6610
  let cancelled = false;
6390
6611
  client.billing.subscription(token).then((result) => {
@@ -6403,28 +6624,28 @@ function BillingPortal({
6403
6624
  cancelled = true;
6404
6625
  };
6405
6626
  }, [client, token, version]);
6406
- const refresh = (0, import_react35.useCallback)(() => {
6627
+ const refresh = (0, import_react36.useCallback)(() => {
6407
6628
  setNotice(null);
6408
6629
  setVersion((value) => value + 1);
6409
6630
  }, []);
6410
- const shell = (content) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: cls("b316-billing-portal", className), style, children: content });
6411
- if (sessionLoading) return shell(/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-card", children: "Loading\u2026" }));
6412
- if (!token) return shell(/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-card", children: "Sign in to manage your billing." }));
6631
+ const shell = (content) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: cls("b316-billing-portal", className), style, children: content });
6632
+ if (sessionLoading) return shell(/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-card", children: "Loading\u2026" }));
6633
+ if (!token) return shell(/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-card", children: "Sign in to manage your billing." }));
6413
6634
  if (failed) {
6414
6635
  return shell(
6415
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-card", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-error", role: "alert", children: "Could not load your billing." }) })
6636
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-card", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-error", role: "alert", children: "Could not load your billing." }) })
6416
6637
  );
6417
6638
  }
6418
- if (!overview) return shell(/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-card", children: "Loading\u2026" }));
6639
+ if (!overview) return shell(/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-card", children: "Loading\u2026" }));
6419
6640
  const { subscription, managedBy, quantityPriced } = overview;
6420
6641
  const canChange = Boolean(subscription) && !managedBy;
6421
6642
  return shell(
6422
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
6423
- notice ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "b316-card b316-notice", role: "status", children: notice }) : null,
6424
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(SubscriptionManager, { onChange: refresh }, `plan-${version}`),
6425
- canChange ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(UpcomingInvoice, {}, `next-${version}`) : null,
6426
- canChange && quantityPriced ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(SeatManager, { unitLabel, onChange: refresh }, `seats-${version}`) : null,
6427
- reviewing ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
6643
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
6644
+ notice ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-card b316-notice", role: "status", children: notice }) : null,
6645
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(SubscriptionManager, { onChange: refresh }, `plan-${version}`),
6646
+ canChange ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(UpcomingInvoice, {}, `next-${version}`) : null,
6647
+ canChange && quantityPriced ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(SeatManager, { unitLabel, onChange: refresh }, `seats-${version}`) : null,
6648
+ reviewing ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6428
6649
  PlanChangeReview,
6429
6650
  {
6430
6651
  planVersionId: reviewing,
@@ -6437,9 +6658,9 @@ function BillingPortal({
6437
6658
  );
6438
6659
  }
6439
6660
  }
6440
- ) : /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("section", { children: [
6441
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("h2", { className: "b316-billing-portal-section-title", children: subscription ? "Change plan" : "Choose a plan" }),
6442
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
6661
+ ) : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("section", { children: [
6662
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h2", { className: "b316-billing-portal-section-title", children: subscription ? "Change plan" : "Choose a plan" }),
6663
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6443
6664
  PricingTable,
6444
6665
  {
6445
6666
  featuredPlanKey,
@@ -6451,17 +6672,17 @@ function BillingPortal({
6451
6672
  `plans-${version}`
6452
6673
  )
6453
6674
  ] }),
6454
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(CreditBalances, {}, `credits-${version}`),
6455
- managedBy ? null : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(PaymentMethod, { returnUrl }, `card-${version}`),
6456
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Invoices, {}, `invoices-${version}`),
6457
- billingDetails === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(BillingDetailsForm, {}, `details-${version}`) : billingDetails
6675
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(CreditBalances, {}, `credits-${version}`),
6676
+ managedBy ? null : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(PaymentMethod, { returnUrl }, `card-${version}`),
6677
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Invoices, {}, `invoices-${version}`),
6678
+ billingDetails === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(BillingDetailsForm, {}, `details-${version}`) : billingDetails
6458
6679
  ] })
6459
6680
  );
6460
6681
  }
6461
6682
 
6462
6683
  // src/ApiKeyManager.tsx
6463
- var import_react36 = require("react");
6464
- var import_jsx_runtime36 = require("react/jsx-runtime");
6684
+ var import_react37 = require("react");
6685
+ var import_jsx_runtime37 = require("react/jsx-runtime");
6465
6686
  function duration(seconds) {
6466
6687
  if (seconds % 3600 === 0) {
6467
6688
  return `${seconds / 3600}h`;
@@ -6478,17 +6699,17 @@ function ApiKeyManager({
6478
6699
  audience
6479
6700
  }) {
6480
6701
  const { client, token, loading: sessionLoading } = useBase316();
6481
- const [resources, setResources] = (0, import_react36.useState)([]);
6482
- const [credentials, setCredentials] = (0, import_react36.useState)([]);
6483
- const [loading, setLoading] = (0, import_react36.useState)(true);
6484
- const [busy, setBusy] = (0, import_react36.useState)(false);
6485
- const [error, setError] = (0, import_react36.useState)(null);
6486
- const [creating, setCreating] = (0, import_react36.useState)(false);
6487
- const [name, setName] = (0, import_react36.useState)("");
6488
- const [chosen, setChosen] = (0, import_react36.useState)([]);
6489
- const [resourceId, setResourceId] = (0, import_react36.useState)(null);
6490
- const [issued, setIssued] = (0, import_react36.useState)(null);
6491
- const load = (0, import_react36.useCallback)(async () => {
6702
+ const [resources, setResources] = (0, import_react37.useState)([]);
6703
+ const [credentials, setCredentials] = (0, import_react37.useState)([]);
6704
+ const [loading, setLoading] = (0, import_react37.useState)(true);
6705
+ const [busy, setBusy] = (0, import_react37.useState)(false);
6706
+ const [error, setError] = (0, import_react37.useState)(null);
6707
+ const [creating, setCreating] = (0, import_react37.useState)(false);
6708
+ const [name, setName] = (0, import_react37.useState)("");
6709
+ const [chosen, setChosen] = (0, import_react37.useState)([]);
6710
+ const [resourceId, setResourceId] = (0, import_react37.useState)(null);
6711
+ const [issued, setIssued] = (0, import_react37.useState)(null);
6712
+ const load = (0, import_react37.useCallback)(async () => {
6492
6713
  if (!token) {
6493
6714
  setLoading(false);
6494
6715
  return;
@@ -6509,20 +6730,20 @@ function ApiKeyManager({
6509
6730
  setLoading(false);
6510
6731
  }
6511
6732
  }, [client, token, audience]);
6512
- (0, import_react36.useEffect)(() => {
6733
+ (0, import_react37.useEffect)(() => {
6513
6734
  void load();
6514
6735
  }, [load]);
6515
6736
  if (sessionLoading || loading) {
6516
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
6737
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
6517
6738
  }
6518
6739
  if (!token) {
6519
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: cls("b316-card", className), style, children: "Sign in to manage your API keys." });
6740
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cls("b316-card", className), style, children: "Sign in to manage your API keys." });
6520
6741
  }
6521
6742
  if (error) {
6522
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
6743
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "b316-error", role: "alert", children: error }) });
6523
6744
  }
6524
6745
  if (resources.length === 0) {
6525
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: cls("b316-card", className), style, children: "There are no APIs available to your account." });
6746
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cls("b316-card", className), style, children: "There are no APIs available to your account." });
6526
6747
  }
6527
6748
  const resource = resources.find((item) => item.id === resourceId) ?? resources[0];
6528
6749
  const reset = () => {
@@ -6531,37 +6752,37 @@ function ApiKeyManager({
6531
6752
  setChosen([]);
6532
6753
  setIssued(null);
6533
6754
  };
6534
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: cls("b316-card", className), style, children: [
6535
- error ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
6536
- resources.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6755
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cls("b316-card", className), style, children: [
6756
+ error ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "b316-error", role: "alert", children: error }) : null,
6757
+ resources.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6537
6758
  "select",
6538
6759
  {
6539
6760
  className: "b316-input",
6540
6761
  value: resource.id,
6541
6762
  onChange: (event) => setResourceId(event.target.value),
6542
6763
  style: { marginBottom: 14 },
6543
- children: resources.map((item) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: item.id, children: item.name }, item.id))
6764
+ children: resources.map((item) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: item.id, children: item.name }, item.id))
6544
6765
  }
6545
- ) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-plan-name", children: resource.name }),
6546
- resource.rateLimit ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "b316-muted", children: [
6766
+ ) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "b316-plan-name", children: resource.name }),
6767
+ resource.rateLimit ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "b316-muted", children: [
6547
6768
  resource.rateLimit.requestsPerWindow,
6548
6769
  " requests per",
6549
6770
  " ",
6550
6771
  duration(resource.rateLimit.windowSeconds),
6551
6772
  resource.rateLimit.burst > resource.rateLimit.requestsPerWindow ? `, bursting to ${resource.rateLimit.burst}` : null
6552
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-muted", children: "No rate limit." }),
6553
- credentials.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "b316-muted", style: { marginTop: 14 }, children: "You have no API keys yet." }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { className: "b316-list", style: { marginTop: 14 }, children: credentials.map((credential) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("li", { className: "b316-list-item", children: [
6554
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { children: [
6555
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-plan-name", children: credential.name }),
6556
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "b316-muted", children: [
6557
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("code", { children: credential.clientId }),
6773
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "b316-muted", children: "No rate limit." }),
6774
+ credentials.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "b316-muted", style: { marginTop: 14 }, children: "You have no API keys yet." }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { className: "b316-list", style: { marginTop: 14 }, children: credentials.map((credential) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("li", { className: "b316-list-item", children: [
6775
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { children: [
6776
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "b316-plan-name", children: credential.name }),
6777
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "b316-muted", children: [
6778
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("code", { children: credential.clientId }),
6558
6779
  credential.secretLastFour ? ` \xB7 \u2026${credential.secretLastFour}` : null,
6559
6780
  credential.disabled ? " \xB7 Disabled" : null
6560
6781
  ] }),
6561
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "b316-muted", children: credential.scopes.join(", ") })
6782
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "b316-muted", children: credential.scopes.join(", ") })
6562
6783
  ] }),
6563
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
6564
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6784
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
6785
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6565
6786
  "button",
6566
6787
  {
6567
6788
  type: "button",
@@ -6590,7 +6811,7 @@ function ApiKeyManager({
6590
6811
  children: "Rotate"
6591
6812
  }
6592
6813
  ),
6593
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6814
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6594
6815
  ConfirmButton,
6595
6816
  {
6596
6817
  className: "b316-button b316-button-secondary",
@@ -6614,11 +6835,11 @@ function ApiKeyManager({
6614
6835
  )
6615
6836
  ] })
6616
6837
  ] }, credential.clientId)) }),
6617
- issued ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "b316-notice", style: { marginTop: 14 }, children: [
6618
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("strong", { children: "Copy this now." }),
6838
+ issued ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "b316-notice", style: { marginTop: 14 }, children: [
6839
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("strong", { children: "Copy this now." }),
6619
6840
  " It is shown once and cannot be retrieved again.",
6620
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("code", { style: { wordBreak: "break-all" }, children: issued.secret }) }),
6621
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6841
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("code", { style: { wordBreak: "break-all" }, children: issued.secret }) }),
6842
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6622
6843
  "button",
6623
6844
  {
6624
6845
  type: "button",
@@ -6631,7 +6852,7 @@ function ApiKeyManager({
6631
6852
  children: "Copy"
6632
6853
  }
6633
6854
  ),
6634
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6855
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6635
6856
  "button",
6636
6857
  {
6637
6858
  type: "button",
@@ -6642,8 +6863,8 @@ function ApiKeyManager({
6642
6863
  }
6643
6864
  )
6644
6865
  ] }) : null,
6645
- creating && !issued ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { style: { marginTop: 14 }, children: [
6646
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6866
+ creating && !issued ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { marginTop: 14 }, children: [
6867
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6647
6868
  "input",
6648
6869
  {
6649
6870
  className: "b316-input",
@@ -6652,9 +6873,9 @@ function ApiKeyManager({
6652
6873
  onChange: (event) => setName(event.target.value)
6653
6874
  }
6654
6875
  ),
6655
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { style: { marginTop: 10 }, children: [
6656
- resource.availableScopes.map((scope) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "b316-checkbox", children: [
6657
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6876
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { style: { marginTop: 10 }, children: [
6877
+ resource.availableScopes.map((scope) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("label", { className: "b316-checkbox", children: [
6878
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6658
6879
  "input",
6659
6880
  {
6660
6881
  type: "checkbox",
@@ -6664,19 +6885,19 @@ function ApiKeyManager({
6664
6885
  )
6665
6886
  }
6666
6887
  ),
6667
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("code", { children: scope.key }),
6668
- scope.description ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "b316-muted", children: [
6888
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("code", { children: scope.key }),
6889
+ scope.description ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "b316-muted", children: [
6669
6890
  " \u2014 ",
6670
6891
  scope.description
6671
6892
  ] }) : null
6672
6893
  ] }, scope.key)),
6673
- resource.lockedScopes.map((scope) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("label", { className: "b316-checkbox b316-muted", children: [
6674
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("input", { type: "checkbox", disabled: true }),
6675
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("code", { children: scope.key }),
6676
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: " \u2014 not included in your plan" })
6894
+ resource.lockedScopes.map((scope) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("label", { className: "b316-checkbox b316-muted", children: [
6895
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("input", { type: "checkbox", disabled: true }),
6896
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("code", { children: scope.key }),
6897
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { children: " \u2014 not included in your plan" })
6677
6898
  ] }, scope.key))
6678
6899
  ] }),
6679
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6900
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6680
6901
  "button",
6681
6902
  {
6682
6903
  type: "button",
@@ -6710,7 +6931,7 @@ function ApiKeyManager({
6710
6931
  children: "Create key"
6711
6932
  }
6712
6933
  ),
6713
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6934
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6714
6935
  "button",
6715
6936
  {
6716
6937
  type: "button",
@@ -6721,7 +6942,7 @@ function ApiKeyManager({
6721
6942
  }
6722
6943
  )
6723
6944
  ] }) : null,
6724
- !creating && !issued ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
6945
+ !creating && !issued ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
6725
6946
  "button",
6726
6947
  {
6727
6948
  type: "button",
@@ -7005,7 +7226,7 @@ var MANIFEST = [
7005
7226
  {
7006
7227
  name: "TwoFactorManager",
7007
7228
  kind: "component",
7008
- summary: "Turn two-factor authentication on or off, by authenticator app, a code to the inbox or a code by text message.",
7229
+ 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.",
7009
7230
  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.",
7010
7231
  requires: ["session"],
7011
7232
  props: [
@@ -7149,7 +7370,7 @@ var MANIFEST = [
7149
7370
  {
7150
7371
  name: "SubscriptionManager",
7151
7372
  kind: "component",
7152
- 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.",
7373
+ 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.",
7153
7374
  useWhen: "A billing settings page.",
7154
7375
  requires: ["session"],
7155
7376
  props: [