@base316/react 0.6.0 → 0.7.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/CHANGELOG.md +36 -0
- package/dist/index.cjs +1389 -973
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1330 -912
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +97 -4
- package/dist/src/SignIn.d.ts +78 -17
- package/dist/src/SignIn.d.ts.map +1 -1
- package/dist/src/SignUp.d.ts +25 -1
- package/dist/src/SignUp.d.ts.map +1 -1
- package/dist/src/SocialButtons.d.ts +16 -0
- package/dist/src/SocialButtons.d.ts.map +1 -0
- package/dist/src/SocialSignIn.d.ts +32 -0
- package/dist/src/SocialSignIn.d.ts.map +1 -0
- package/dist/src/appearance.d.ts +1 -1
- package/dist/src/appearance.d.ts.map +1 -1
- package/dist/src/manifest.d.ts.map +1 -1
- package/dist/src/sign-in-methods.d.ts +66 -0
- package/dist/src/sign-in-methods.d.ts.map +1 -0
- package/dist/src/social-icons.d.ts +11 -0
- package/dist/src/social-icons.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -325,6 +325,23 @@ var STYLESHEET_EXTRA = `
|
|
|
325
325
|
border-bottom: 2px solid transparent; margin-bottom: -1px;
|
|
326
326
|
}
|
|
327
327
|
.b316-tab-on { color: var(--b316-color-text); border-bottom-color: var(--b316-color-primary); }
|
|
328
|
+
.b316-social { display: flex; flex-direction: column; gap: 8px; }
|
|
329
|
+
.b316-social-button {
|
|
330
|
+
display: flex; align-items: center; justify-content: center; gap: 10px;
|
|
331
|
+
width: 100%; min-height: 40px; padding: 9px 14px;
|
|
332
|
+
border: 1px solid; border-radius: calc(var(--b316-radius) / 1.6);
|
|
333
|
+
font: inherit; font-weight: 500; cursor: pointer;
|
|
334
|
+
}
|
|
335
|
+
.b316-social-button:hover:not([disabled]) { filter: brightness(.96); }
|
|
336
|
+
.b316-social-button:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }
|
|
337
|
+
.b316-social-button[disabled] { opacity: .55; cursor: not-allowed; }
|
|
338
|
+
.b316-social-icon { display: inline-flex; width: 18px; height: 18px; flex: none; }
|
|
339
|
+
.b316-social-icon svg { width: 18px; height: 18px; }
|
|
340
|
+
.b316-divider {
|
|
341
|
+
display: flex; align-items: center; gap: 10px; margin: 14px 0;
|
|
342
|
+
color: var(--b316-color-muted); font-size: .87em;
|
|
343
|
+
}
|
|
344
|
+
.b316-divider::before, .b316-divider::after { content: ""; flex: 1; border-top: 1px solid var(--b316-color-border); }
|
|
328
345
|
.b316-branding { display: flex; flex-direction: column; gap: 4px; }
|
|
329
346
|
.b316-branding-logo { max-height: 40px; width: auto; align-self: flex-start; }
|
|
330
347
|
.b316-branding-name { font-size: 1.5em; font-weight: 650; letter-spacing: -.01em; }
|
|
@@ -1607,7 +1624,7 @@ import {
|
|
|
1607
1624
|
isPasskeySupported,
|
|
1608
1625
|
needsSecondFactor
|
|
1609
1626
|
} from "@base316/sdk";
|
|
1610
|
-
import { useEffect as
|
|
1627
|
+
import { useEffect as useEffect8, useRef as useRef2, useState as useState8 } from "react";
|
|
1611
1628
|
|
|
1612
1629
|
// src/SecondFactorStep.tsx
|
|
1613
1630
|
import {
|
|
@@ -1998,33 +2015,233 @@ function SecondFactorStep({
|
|
|
1998
2015
|
return /* @__PURE__ */ jsx7("div", { className: cls("b316-mfa", className), style, children: body });
|
|
1999
2016
|
}
|
|
2000
2017
|
|
|
2018
|
+
// src/sign-in-methods.ts
|
|
2019
|
+
import {
|
|
2020
|
+
OAUTH_STATE_COOKIE,
|
|
2021
|
+
createOAuthState
|
|
2022
|
+
} from "@base316/sdk";
|
|
2023
|
+
import { useEffect as useEffect7, useState as useState7 } from "react";
|
|
2024
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
2025
|
+
function loadSignInMethods(client) {
|
|
2026
|
+
let pending = cache.get(client);
|
|
2027
|
+
if (!pending) {
|
|
2028
|
+
pending = client.auth.methods();
|
|
2029
|
+
cache.set(client, pending);
|
|
2030
|
+
pending.catch(() => cache.delete(client));
|
|
2031
|
+
}
|
|
2032
|
+
return pending;
|
|
2033
|
+
}
|
|
2034
|
+
function useSignInMethods(client) {
|
|
2035
|
+
const [state, setState] = useState7({ status: "loading", methods: null });
|
|
2036
|
+
useEffect7(() => {
|
|
2037
|
+
let cancelled = false;
|
|
2038
|
+
loadSignInMethods(client).then((methods) => {
|
|
2039
|
+
if (!cancelled) setState({ status: "ready", methods });
|
|
2040
|
+
}).catch(() => {
|
|
2041
|
+
if (!cancelled) setState({ status: "unavailable", methods: null });
|
|
2042
|
+
});
|
|
2043
|
+
return () => {
|
|
2044
|
+
cancelled = true;
|
|
2045
|
+
};
|
|
2046
|
+
}, [client]);
|
|
2047
|
+
return state;
|
|
2048
|
+
}
|
|
2049
|
+
function resolveMethods(methods, props, currentPage) {
|
|
2050
|
+
if (!methods) {
|
|
2051
|
+
return {
|
|
2052
|
+
password: props.password !== false,
|
|
2053
|
+
passkeys: props.passkeys !== false,
|
|
2054
|
+
magicLink: props.magicLink !== false ? props.magicLinkRedirectUrl ?? null : null,
|
|
2055
|
+
phone: props.phone === true,
|
|
2056
|
+
social: [],
|
|
2057
|
+
sso: false,
|
|
2058
|
+
signUp: true,
|
|
2059
|
+
hostedUrl: void 0
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2062
|
+
const redirect = props.socialRedirectUrl;
|
|
2063
|
+
const only = Array.isArray(props.social) ? new Set(props.social.map((entry) => entry.toLowerCase())) : null;
|
|
2064
|
+
return {
|
|
2065
|
+
password: methods.password && props.password !== false,
|
|
2066
|
+
passkeys: methods.passkeys && props.passkeys !== false,
|
|
2067
|
+
magicLink: methods.magicLink && props.magicLink !== false ? props.magicLinkRedirectUrl ?? currentPage : null,
|
|
2068
|
+
phone: methods.phone && props.phone !== false,
|
|
2069
|
+
social: redirect && props.social !== false ? methods.social.filter(
|
|
2070
|
+
(option) => !only || only.has(option.slug.toLowerCase()) || only.has(option.provider.toLowerCase())
|
|
2071
|
+
) : [],
|
|
2072
|
+
sso: Boolean(redirect) && methods.sso && props.sso !== false,
|
|
2073
|
+
signUp: methods.signUp,
|
|
2074
|
+
hostedUrl: methods.hostedUrl
|
|
2075
|
+
};
|
|
2076
|
+
}
|
|
2077
|
+
function beginRedirect(build, appState) {
|
|
2078
|
+
const { state, nonce } = createOAuthState(appState);
|
|
2079
|
+
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
2080
|
+
document.cookie = `${OAUTH_STATE_COOKIE}=${nonce}; Path=/; Max-Age=600; SameSite=Lax${secure}`;
|
|
2081
|
+
window.location.assign(build(state));
|
|
2082
|
+
}
|
|
2083
|
+
function currentPageUrl() {
|
|
2084
|
+
if (typeof window === "undefined") {
|
|
2085
|
+
return null;
|
|
2086
|
+
}
|
|
2087
|
+
return `${window.location.origin}${window.location.pathname}`;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
// src/social-icons.ts
|
|
2091
|
+
var PROVIDER_ICON = {
|
|
2092
|
+
GOOGLE: `<svg viewBox="0 0 18 18" aria-hidden="true"><path fill="#4285F4" d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62Z"/><path fill="#34A853" d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"/><path fill="#FBBC05" d="M3.97 10.72a5.4 5.4 0 0 1 0-3.44V4.95H.96a9 9 0 0 0 0 8.1l3.01-2.33Z"/><path fill="#EA4335" d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58C13.46.9 11.43 0 9 0A9 9 0 0 0 .96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58Z"/></svg>`,
|
|
2093
|
+
FACEBOOK: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M24 12.07C24 5.4 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.05V9.41c0-3.02 1.79-4.69 4.53-4.69 1.31 0 2.68.24 2.68.24v2.96h-1.51c-1.49 0-1.96.93-1.96 1.89v2.26h3.33l-.53 3.49h-2.8V24C19.61 23.1 24 18.1 24 12.07Z"/></svg>`,
|
|
2094
|
+
APPLE: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M17.05 12.54c-.03-2.74 2.24-4.06 2.34-4.12-1.28-1.86-3.26-2.12-3.96-2.15-1.69-.17-3.29 1-4.14 1-.85 0-2.17-.98-3.57-.95-1.83.03-3.53 1.07-4.47 2.71-1.91 3.31-.49 8.2 1.37 10.88.91 1.31 1.99 2.78 3.42 2.73 1.37-.06 1.89-.89 3.55-.89 1.66 0 2.13.89 3.58.86 1.48-.03 2.41-1.34 3.31-2.65 1.04-1.52 1.47-2.99 1.5-3.07-.03-.01-2.88-1.1-2.91-4.37ZM14.3 4.44c.75-.92 1.26-2.19 1.12-3.44-1.08.04-2.4.72-3.18 1.63-.7.81-1.31 2.11-1.15 3.35 1.21.09 2.45-.61 3.21-1.54Z"/></svg>`,
|
|
2095
|
+
MICROSOFT: `<svg viewBox="0 0 23 23" aria-hidden="true"><path fill="#f25022" d="M1 1h10v10H1z"/><path fill="#7fba00" d="M12 1h10v10H12z"/><path fill="#00a4ef" d="M1 12h10v10H1z"/><path fill="#ffb900" d="M12 12h10v10H12z"/></svg>`,
|
|
2096
|
+
GITHUB: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 0-.8.4-1.3.7-1.6-2.7-.3-5.5-1.3-5.5-5.9 0-1.3.5-2.4 1.2-3.2 0-.4-.5-1.6.2-3.2 0 0 1-.3 3.3 1.2a11.5 11.5 0 0 1 6 0C17.4 4.6 18.4 5 18.4 5c.7 1.6.2 2.8.1 3.2.8.8 1.2 1.9 1.2 3.2 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.2v3.3c0 .3.2.7.8.6A12 12 0 0 0 12 .3Z"/></svg>`,
|
|
2097
|
+
GITLAB: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#e24329" d="m12 22.5-3.7-11.3h7.4L12 22.5Z"/><path fill="#fc6d26" d="M12 22.5 8.3 11.2H3.1L12 22.5Z"/><path fill="#fca326" d="M3.1 11.2 2 14.7a.8.8 0 0 0 .3.8l9.7 7-8.9-11.3Z"/><path fill="#e24329" d="M3.1 11.2h5.2L6.1 4.3a.4.4 0 0 0-.8 0l-2.2 6.9Z"/><path fill="#fc6d26" d="M12 22.5l3.7-11.3h5.2L12 22.5Z"/><path fill="#fca326" d="m20.9 11.2 1.1 3.5a.8.8 0 0 1-.3.8l-9.7 7 8.9-11.3Z"/><path fill="#e24329" d="M20.9 11.2h-5.2l2.2-6.9a.4.4 0 0 1 .8 0l2.2 6.9Z"/></svg>`,
|
|
2098
|
+
LINKEDIN: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M20.45 20.45h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.41v1.56h.05a3.74 3.74 0 0 1 3.37-1.85c3.6 0 4.27 2.37 4.27 5.46v6.28ZM5.34 7.43a2.07 2.07 0 1 1 0-4.13 2.07 2.07 0 0 1 0 4.13Zm1.78 13.02H3.55V9h3.57v11.45ZM22.22 0H1.77C.79 0 0 .77 0 1.72v20.56C0 23.23.79 24 1.77 24h20.45c.98 0 1.78-.77 1.78-1.72V1.72C24 .77 23.2 0 22.22 0Z"/></svg>`,
|
|
2099
|
+
// The four below are the Simple Icons marks (CC0), https://simpleicons.org.
|
|
2100
|
+
DISCORD: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/></svg>`,
|
|
2101
|
+
TWITTER: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"/></svg>`,
|
|
2102
|
+
TWITCH: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0L1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143l-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714Z"/></svg>`,
|
|
2103
|
+
ROBLOX: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M18.926 23.998 0 18.892 5.075.002 24 5.108ZM15.348 10.09l-5.282-1.453-1.414 5.273 5.282 1.453z"/></svg>`,
|
|
2104
|
+
SLACK: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#e01e5a" d="M5.04 15.17a2.53 2.53 0 1 1-2.52-2.53h2.52v2.53Zm1.27 0a2.53 2.53 0 1 1 5.05 0v6.31a2.53 2.53 0 1 1-5.05 0v-6.31Z"/><path fill="#36c5f0" d="M8.83 5.04a2.53 2.53 0 1 1 2.53-2.52v2.52H8.83Zm0 1.28a2.53 2.53 0 1 1 0 5.05H2.52a2.53 2.53 0 1 1 0-5.05h6.31Z"/><path fill="#2eb67d" d="M18.96 8.83a2.53 2.53 0 1 1 2.52 2.53h-2.52V8.83Zm-1.27 0a2.53 2.53 0 1 1-5.05 0V2.52a2.53 2.53 0 1 1 5.05 0v6.31Z"/><path fill="#ecb22e" d="M15.17 18.96a2.53 2.53 0 1 1-2.53 2.52v-2.52h2.53Zm0-1.27a2.53 2.53 0 1 1 0-5.05h6.31a2.53 2.53 0 1 1 0 5.05h-6.31Z"/></svg>`
|
|
2105
|
+
};
|
|
2106
|
+
|
|
2107
|
+
// src/SocialButtons.tsx
|
|
2108
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2109
|
+
function SocialButtons({
|
|
2110
|
+
options,
|
|
2111
|
+
continueWith,
|
|
2112
|
+
disabled,
|
|
2113
|
+
onChoose
|
|
2114
|
+
}) {
|
|
2115
|
+
if (options.length === 0) {
|
|
2116
|
+
return null;
|
|
2117
|
+
}
|
|
2118
|
+
return /* @__PURE__ */ jsx8("div", { className: "b316-social", children: options.map((option) => {
|
|
2119
|
+
const icon = PROVIDER_ICON[option.provider];
|
|
2120
|
+
const light = /^#f{3}(f{3})?$/i.test(option.buttonColor);
|
|
2121
|
+
return /* @__PURE__ */ jsxs7(
|
|
2122
|
+
"button",
|
|
2123
|
+
{
|
|
2124
|
+
type: "button",
|
|
2125
|
+
className: "b316-social-button",
|
|
2126
|
+
"data-provider": option.slug,
|
|
2127
|
+
disabled,
|
|
2128
|
+
style: {
|
|
2129
|
+
background: option.buttonColor,
|
|
2130
|
+
color: option.buttonTextColor,
|
|
2131
|
+
borderColor: light ? "#747775" : option.buttonColor
|
|
2132
|
+
},
|
|
2133
|
+
onClick: () => onChoose(option),
|
|
2134
|
+
children: [
|
|
2135
|
+
icon ? /* @__PURE__ */ jsx8(
|
|
2136
|
+
"span",
|
|
2137
|
+
{
|
|
2138
|
+
className: "b316-social-icon",
|
|
2139
|
+
"aria-hidden": "true",
|
|
2140
|
+
dangerouslySetInnerHTML: { __html: icon }
|
|
2141
|
+
}
|
|
2142
|
+
) : null,
|
|
2143
|
+
/* @__PURE__ */ jsx8("span", { children: continueWith(option.name, option.provider) })
|
|
2144
|
+
]
|
|
2145
|
+
},
|
|
2146
|
+
option.slug
|
|
2147
|
+
);
|
|
2148
|
+
}) });
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2001
2151
|
// src/SignIn.tsx
|
|
2002
|
-
import { Fragment as Fragment4, jsx as
|
|
2152
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2153
|
+
var DEFAULT_SIGN_IN_LABELS = {
|
|
2154
|
+
email: "Email",
|
|
2155
|
+
password: "Password",
|
|
2156
|
+
mobileNumber: "Mobile number",
|
|
2157
|
+
code: "Code",
|
|
2158
|
+
tabPassword: "Password",
|
|
2159
|
+
tabMagicLink: "Magic link",
|
|
2160
|
+
tabPhone: "Text message",
|
|
2161
|
+
submit: "Sign in",
|
|
2162
|
+
working: "Working\u2026",
|
|
2163
|
+
emailMeALink: "Email me a link",
|
|
2164
|
+
textMeACode: "Text me a code",
|
|
2165
|
+
includeCountryCode: "Include the country code.",
|
|
2166
|
+
codeSent: (destination) => `We sent a code to ${destination}. It expires in ten minutes.`,
|
|
2167
|
+
useDifferentNumber: "Use a different number",
|
|
2168
|
+
or: "or",
|
|
2169
|
+
passkey: "Sign in with a passkey",
|
|
2170
|
+
continueWith: (name) => `Continue with ${name}`,
|
|
2171
|
+
sso: "Sign in with SSO",
|
|
2172
|
+
ssoEmail: "Work email",
|
|
2173
|
+
ssoContinue: "Continue",
|
|
2174
|
+
back: "Back",
|
|
2175
|
+
checkEmailTitle: "Check your email",
|
|
2176
|
+
checkEmail: (email) => `If an account exists for ${email}, a sign-in link is on its way. It expires shortly and can be used once.`,
|
|
2177
|
+
backToSignIn: "Back to sign in",
|
|
2178
|
+
wrongPassword: "That email and password did not match.",
|
|
2179
|
+
passkeyFailed: "That passkey did not work.",
|
|
2180
|
+
linkInvalid: "That sign-in link is no longer valid. Ask for a new one.",
|
|
2181
|
+
linkFailed: "We could not send that link. Try again.",
|
|
2182
|
+
wrongCode: "That code did not work. Check it, or ask for a new one.",
|
|
2183
|
+
codeFailed: "We could not send a code. Try again.",
|
|
2184
|
+
noMethods: "Signing in is not available right now."
|
|
2185
|
+
};
|
|
2003
2186
|
function SignIn({
|
|
2004
2187
|
onSignedIn,
|
|
2005
|
-
|
|
2188
|
+
password: passwordProp,
|
|
2189
|
+
passkeys: passkeysProp,
|
|
2190
|
+
magicLink: magicLinkProp,
|
|
2006
2191
|
magicLinkRedirectUrl,
|
|
2007
|
-
phone
|
|
2192
|
+
phone: phoneProp,
|
|
2193
|
+
social: socialProp,
|
|
2194
|
+
sso: ssoProp,
|
|
2195
|
+
socialRedirectUrl,
|
|
2196
|
+
socialState,
|
|
2197
|
+
labels: overrides,
|
|
2008
2198
|
secondFactorLabels,
|
|
2009
2199
|
className,
|
|
2010
2200
|
style
|
|
2011
2201
|
}) {
|
|
2202
|
+
const labels = { ...DEFAULT_SIGN_IN_LABELS, ...overrides };
|
|
2012
2203
|
const { client, setToken } = useBase316();
|
|
2013
|
-
const
|
|
2014
|
-
const [
|
|
2015
|
-
const [
|
|
2016
|
-
const [
|
|
2204
|
+
const loaded = useSignInMethods(client);
|
|
2205
|
+
const [currentPage, setCurrentPage] = useState8(null);
|
|
2206
|
+
const [email, setEmail] = useState8("");
|
|
2207
|
+
const [password, setPassword] = useState8("");
|
|
2208
|
+
const [code, setCode] = useState8("");
|
|
2209
|
+
const [pending, setPending] = useState8(null);
|
|
2017
2210
|
const pendingChallenge = pending?.challengeToken ?? null;
|
|
2018
|
-
const [phoneNumber, setPhoneNumber] =
|
|
2019
|
-
const [phoneChallenge, setPhoneChallenge] =
|
|
2211
|
+
const [phoneNumber, setPhoneNumber] = useState8("");
|
|
2212
|
+
const [phoneChallenge, setPhoneChallenge] = useState8(
|
|
2020
2213
|
null
|
|
2021
2214
|
);
|
|
2022
|
-
const [error, setError] =
|
|
2023
|
-
const [busy, setBusy] =
|
|
2024
|
-
const [passkeyReady, setPasskeyReady] =
|
|
2025
|
-
const [
|
|
2026
|
-
const [linkSent, setLinkSent] =
|
|
2215
|
+
const [error, setError] = useState8(null);
|
|
2216
|
+
const [busy, setBusy] = useState8(false);
|
|
2217
|
+
const [passkeyReady, setPasskeyReady] = useState8(false);
|
|
2218
|
+
const [chosenMode, setMode] = useState8(null);
|
|
2219
|
+
const [linkSent, setLinkSent] = useState8(false);
|
|
2027
2220
|
const abortRef = useRef2(null);
|
|
2221
|
+
useEffect8(() => {
|
|
2222
|
+
setCurrentPage(currentPageUrl());
|
|
2223
|
+
}, []);
|
|
2224
|
+
const offered = resolveMethods(
|
|
2225
|
+
loaded.methods,
|
|
2226
|
+
{
|
|
2227
|
+
password: passwordProp,
|
|
2228
|
+
passkeys: passkeysProp,
|
|
2229
|
+
magicLink: magicLinkProp,
|
|
2230
|
+
magicLinkRedirectUrl,
|
|
2231
|
+
phone: phoneProp,
|
|
2232
|
+
social: socialProp,
|
|
2233
|
+
sso: ssoProp,
|
|
2234
|
+
socialRedirectUrl
|
|
2235
|
+
},
|
|
2236
|
+
currentPage
|
|
2237
|
+
);
|
|
2238
|
+
const tabs = [
|
|
2239
|
+
...offered.password ? ["password"] : [],
|
|
2240
|
+
...offered.magicLink ? ["magic"] : [],
|
|
2241
|
+
...offered.phone ? ["phone"] : []
|
|
2242
|
+
];
|
|
2243
|
+
const mode = chosenMode && (chosenMode === "sso" ? offered.sso : tabs.includes(chosenMode)) ? chosenMode : tabs[0] ?? null;
|
|
2244
|
+
const passkeysWanted = loaded.status !== "loading" && offered.passkeys;
|
|
2028
2245
|
const signInWithPasskey = async (conditional, signal) => {
|
|
2029
2246
|
if (!conditional) {
|
|
2030
2247
|
setBusy(true);
|
|
@@ -2042,7 +2259,7 @@ function SignIn({
|
|
|
2042
2259
|
setError(cause.message);
|
|
2043
2260
|
} else if (!conditional) {
|
|
2044
2261
|
console.error("[base316] passkey sign-in failed", cause);
|
|
2045
|
-
setError(
|
|
2262
|
+
setError(labels.passkeyFailed);
|
|
2046
2263
|
}
|
|
2047
2264
|
} finally {
|
|
2048
2265
|
if (!conditional) {
|
|
@@ -2050,8 +2267,9 @@ function SignIn({
|
|
|
2050
2267
|
}
|
|
2051
2268
|
}
|
|
2052
2269
|
};
|
|
2053
|
-
|
|
2054
|
-
if (!
|
|
2270
|
+
useEffect8(() => {
|
|
2271
|
+
if (!passkeysWanted || !isPasskeySupported() || pendingChallenge) {
|
|
2272
|
+
setPasskeyReady(false);
|
|
2055
2273
|
return;
|
|
2056
2274
|
}
|
|
2057
2275
|
setPasskeyReady(true);
|
|
@@ -2065,8 +2283,8 @@ function SignIn({
|
|
|
2065
2283
|
return () => {
|
|
2066
2284
|
controller.abort();
|
|
2067
2285
|
};
|
|
2068
|
-
}, [
|
|
2069
|
-
|
|
2286
|
+
}, [passkeysWanted, pendingChallenge]);
|
|
2287
|
+
useEffect8(() => {
|
|
2070
2288
|
if (typeof window === "undefined") {
|
|
2071
2289
|
return;
|
|
2072
2290
|
}
|
|
@@ -2090,7 +2308,7 @@ function SignIn({
|
|
|
2090
2308
|
onSignedIn?.();
|
|
2091
2309
|
}).catch(() => {
|
|
2092
2310
|
if (!cancelled) {
|
|
2093
|
-
setError(
|
|
2311
|
+
setError(labels.linkInvalid);
|
|
2094
2312
|
}
|
|
2095
2313
|
});
|
|
2096
2314
|
return () => {
|
|
@@ -2098,23 +2316,44 @@ function SignIn({
|
|
|
2098
2316
|
};
|
|
2099
2317
|
}, []);
|
|
2100
2318
|
async function sendLink() {
|
|
2101
|
-
if (!
|
|
2319
|
+
if (!offered.magicLink) {
|
|
2102
2320
|
return;
|
|
2103
2321
|
}
|
|
2104
2322
|
setBusy(true);
|
|
2105
2323
|
setError(null);
|
|
2106
2324
|
try {
|
|
2107
|
-
await client.auth.magicLink.request({ email, redirectUrl:
|
|
2325
|
+
await client.auth.magicLink.request({ email, redirectUrl: offered.magicLink });
|
|
2108
2326
|
setLinkSent(true);
|
|
2109
2327
|
} catch (cause) {
|
|
2110
2328
|
console.error("[base316] magic link request failed", cause);
|
|
2111
|
-
setError(
|
|
2329
|
+
setError(
|
|
2330
|
+
cause instanceof Base316Error2 && cause.code === "INVALID_REQUEST" && cause.message ? cause.message : labels.linkFailed
|
|
2331
|
+
);
|
|
2112
2332
|
} finally {
|
|
2113
2333
|
setBusy(false);
|
|
2114
2334
|
}
|
|
2115
2335
|
}
|
|
2336
|
+
function leaveForSso() {
|
|
2337
|
+
if (!socialRedirectUrl) {
|
|
2338
|
+
return;
|
|
2339
|
+
}
|
|
2340
|
+
setBusy(true);
|
|
2341
|
+
beginRedirect(
|
|
2342
|
+
(state) => client.ssoSignInUrl({
|
|
2343
|
+
email,
|
|
2344
|
+
redirectUri: socialRedirectUrl,
|
|
2345
|
+
state,
|
|
2346
|
+
hostedUrl: offered.hostedUrl
|
|
2347
|
+
}),
|
|
2348
|
+
socialState
|
|
2349
|
+
);
|
|
2350
|
+
}
|
|
2116
2351
|
async function submit(event) {
|
|
2117
2352
|
event.preventDefault();
|
|
2353
|
+
if (mode === "sso") {
|
|
2354
|
+
leaveForSso();
|
|
2355
|
+
return;
|
|
2356
|
+
}
|
|
2118
2357
|
setBusy(true);
|
|
2119
2358
|
setError(null);
|
|
2120
2359
|
try {
|
|
@@ -2151,25 +2390,23 @@ function SignIn({
|
|
|
2151
2390
|
} catch (cause) {
|
|
2152
2391
|
console.error("[base316] sign-in failed", cause);
|
|
2153
2392
|
setError(
|
|
2154
|
-
mode === "phone" ? phoneChallenge ?
|
|
2393
|
+
mode === "phone" ? phoneChallenge ? labels.wrongCode : (
|
|
2155
2394
|
// Why a text could not be sent is worth saying — a number in the
|
|
2156
2395
|
// wrong format, or too many requests — and the server words it
|
|
2157
2396
|
// without saying anything about accounts.
|
|
2158
|
-
cause instanceof Error && cause.message ? cause.message :
|
|
2397
|
+
cause instanceof Error && cause.message ? cause.message : labels.codeFailed
|
|
2159
2398
|
) : (
|
|
2160
2399
|
// An unconfirmed address and a throttle are worth naming; the
|
|
2161
2400
|
// server words both without saying whether an account exists.
|
|
2162
|
-
cause instanceof Base316Error2 && (cause.reason === "EMAIL_NOT_VERIFIED" || cause.code === "RATE_LIMITED") ? cause.message :
|
|
2401
|
+
cause instanceof Base316Error2 && (cause.reason === "EMAIL_NOT_VERIFIED" || cause.code === "RATE_LIMITED") ? cause.message : labels.wrongPassword
|
|
2163
2402
|
)
|
|
2164
2403
|
);
|
|
2165
2404
|
} finally {
|
|
2166
2405
|
setBusy(false);
|
|
2167
2406
|
}
|
|
2168
2407
|
}
|
|
2169
|
-
const magicAvailable = Boolean(magicLinkRedirectUrl) && !pendingChallenge;
|
|
2170
|
-
const tabsShown = (magicAvailable || phone) && !pendingChallenge;
|
|
2171
2408
|
if (pending) {
|
|
2172
|
-
return /* @__PURE__ */
|
|
2409
|
+
return /* @__PURE__ */ jsx9("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx9(
|
|
2173
2410
|
SecondFactorStep,
|
|
2174
2411
|
{
|
|
2175
2412
|
pending,
|
|
@@ -2185,59 +2422,68 @@ function SignIn({
|
|
|
2185
2422
|
) });
|
|
2186
2423
|
}
|
|
2187
2424
|
if (linkSent) {
|
|
2188
|
-
return /* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
/* @__PURE__ */
|
|
2191
|
-
|
|
2192
|
-
email,
|
|
2193
|
-
", a sign-in link is on its way. It expires shortly and can be used once."
|
|
2194
|
-
] }),
|
|
2195
|
-
/* @__PURE__ */ jsx8(
|
|
2425
|
+
return /* @__PURE__ */ jsxs8("div", { className: cls("b316-card", className), style, children: [
|
|
2426
|
+
/* @__PURE__ */ jsx9("div", { style: { fontWeight: 600, marginBottom: 6 }, children: labels.checkEmailTitle }),
|
|
2427
|
+
/* @__PURE__ */ jsx9("div", { className: "b316-muted", children: labels.checkEmail(email) }),
|
|
2428
|
+
/* @__PURE__ */ jsx9(
|
|
2196
2429
|
"button",
|
|
2197
2430
|
{
|
|
2198
2431
|
type: "button",
|
|
2199
2432
|
className: "b316-button b316-button-secondary",
|
|
2200
2433
|
style: { marginTop: 16 },
|
|
2201
2434
|
onClick: () => setLinkSent(false),
|
|
2202
|
-
children:
|
|
2435
|
+
children: labels.backToSignIn
|
|
2203
2436
|
}
|
|
2204
2437
|
)
|
|
2205
2438
|
] });
|
|
2206
2439
|
}
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2440
|
+
const hasForm = mode !== null;
|
|
2441
|
+
const hasButtons = offered.social.length > 0 || passkeyReady || offered.sso && mode !== "sso";
|
|
2442
|
+
if (!hasForm && !hasButtons) {
|
|
2443
|
+
return /* @__PURE__ */ jsx9("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx9("div", { className: "b316-error", role: "alert", children: error ?? labels.noMethods }) });
|
|
2444
|
+
}
|
|
2445
|
+
const tabsShown = tabs.length > 1 && mode !== "sso";
|
|
2446
|
+
return /* @__PURE__ */ jsxs8("form", { onSubmit: submit, className: cls("b316-card", className), style, children: [
|
|
2447
|
+
error ? /* @__PURE__ */ jsx9("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
2448
|
+
offered.social.length > 0 && mode !== "sso" ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
2449
|
+
/* @__PURE__ */ jsx9(
|
|
2450
|
+
SocialButtons,
|
|
2212
2451
|
{
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2452
|
+
options: offered.social,
|
|
2453
|
+
continueWith: labels.continueWith,
|
|
2454
|
+
disabled: busy,
|
|
2455
|
+
onChoose: (option) => {
|
|
2456
|
+
if (!socialRedirectUrl) {
|
|
2457
|
+
return;
|
|
2458
|
+
}
|
|
2459
|
+
setBusy(true);
|
|
2460
|
+
beginRedirect(
|
|
2461
|
+
(state) => client.socialSignInUrl({
|
|
2462
|
+
provider: option.slug,
|
|
2463
|
+
redirectUri: socialRedirectUrl,
|
|
2464
|
+
state,
|
|
2465
|
+
hostedUrl: offered.hostedUrl
|
|
2466
|
+
}),
|
|
2467
|
+
socialState
|
|
2468
|
+
);
|
|
2469
|
+
}
|
|
2217
2470
|
}
|
|
2218
2471
|
),
|
|
2219
|
-
|
|
2220
|
-
"button",
|
|
2221
|
-
{
|
|
2222
|
-
type: "button",
|
|
2223
|
-
className: cls("b316-tab", mode === "magic" ? "b316-tab-on" : void 0),
|
|
2224
|
-
onClick: () => setMode("magic"),
|
|
2225
|
-
children: "Magic link"
|
|
2226
|
-
}
|
|
2227
|
-
) : null,
|
|
2228
|
-
phone ? /* @__PURE__ */ jsx8(
|
|
2229
|
-
"button",
|
|
2230
|
-
{
|
|
2231
|
-
type: "button",
|
|
2232
|
-
className: cls("b316-tab", mode === "phone" ? "b316-tab-on" : void 0),
|
|
2233
|
-
onClick: () => setMode("phone"),
|
|
2234
|
-
children: "Text message"
|
|
2235
|
-
}
|
|
2236
|
-
) : null
|
|
2472
|
+
hasForm ? /* @__PURE__ */ jsx9("div", { className: "b316-divider", children: labels.or }) : null
|
|
2237
2473
|
] }) : null,
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2474
|
+
tabsShown ? /* @__PURE__ */ jsx9("div", { className: "b316-tabs", children: tabs.map((tab) => /* @__PURE__ */ jsx9(
|
|
2475
|
+
"button",
|
|
2476
|
+
{
|
|
2477
|
+
type: "button",
|
|
2478
|
+
className: cls("b316-tab", mode === tab ? "b316-tab-on" : void 0),
|
|
2479
|
+
onClick: () => setMode(tab),
|
|
2480
|
+
children: tab === "password" ? labels.tabPassword : tab === "magic" ? labels.tabMagicLink : labels.tabPhone
|
|
2481
|
+
},
|
|
2482
|
+
tab
|
|
2483
|
+
)) }) : null,
|
|
2484
|
+
mode === "phone" ? phoneChallenge ? /* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2485
|
+
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-phone-code", children: labels.code }),
|
|
2486
|
+
/* @__PURE__ */ jsx9(
|
|
2241
2487
|
"input",
|
|
2242
2488
|
{
|
|
2243
2489
|
id: "b316-phone-code",
|
|
@@ -2249,12 +2495,10 @@ function SignIn({
|
|
|
2249
2495
|
required: true
|
|
2250
2496
|
}
|
|
2251
2497
|
),
|
|
2252
|
-
/* @__PURE__ */
|
|
2253
|
-
|
|
2254
|
-
phoneChallenge.hint,
|
|
2255
|
-
". It expires in ten minutes.",
|
|
2498
|
+
/* @__PURE__ */ jsxs8("span", { className: "b316-muted", children: [
|
|
2499
|
+
labels.codeSent(phoneChallenge.hint),
|
|
2256
2500
|
" ",
|
|
2257
|
-
/* @__PURE__ */
|
|
2501
|
+
/* @__PURE__ */ jsx9(
|
|
2258
2502
|
"button",
|
|
2259
2503
|
{
|
|
2260
2504
|
type: "button",
|
|
@@ -2263,13 +2507,13 @@ function SignIn({
|
|
|
2263
2507
|
setPhoneChallenge(null);
|
|
2264
2508
|
setCode("");
|
|
2265
2509
|
},
|
|
2266
|
-
children:
|
|
2510
|
+
children: labels.useDifferentNumber
|
|
2267
2511
|
}
|
|
2268
2512
|
)
|
|
2269
2513
|
] })
|
|
2270
|
-
] }) : /* @__PURE__ */
|
|
2271
|
-
/* @__PURE__ */
|
|
2272
|
-
/* @__PURE__ */
|
|
2514
|
+
] }) : /* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2515
|
+
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-phone", children: labels.mobileNumber }),
|
|
2516
|
+
/* @__PURE__ */ jsx9(
|
|
2273
2517
|
"input",
|
|
2274
2518
|
{
|
|
2275
2519
|
id: "b316-phone",
|
|
@@ -2282,11 +2526,11 @@ function SignIn({
|
|
|
2282
2526
|
required: true
|
|
2283
2527
|
}
|
|
2284
2528
|
),
|
|
2285
|
-
/* @__PURE__ */
|
|
2286
|
-
] }) : /* @__PURE__ */
|
|
2287
|
-
/* @__PURE__ */
|
|
2288
|
-
/* @__PURE__ */
|
|
2289
|
-
/* @__PURE__ */
|
|
2529
|
+
/* @__PURE__ */ jsx9("span", { className: "b316-muted", children: labels.includeCountryCode })
|
|
2530
|
+
] }) : mode !== null ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
2531
|
+
/* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2532
|
+
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-email", children: mode === "sso" ? labels.ssoEmail : labels.email }),
|
|
2533
|
+
/* @__PURE__ */ jsx9(
|
|
2290
2534
|
"input",
|
|
2291
2535
|
{
|
|
2292
2536
|
id: "b316-email",
|
|
@@ -2294,14 +2538,14 @@ function SignIn({
|
|
|
2294
2538
|
type: "email",
|
|
2295
2539
|
value: email,
|
|
2296
2540
|
onChange: (event) => setEmail(event.target.value),
|
|
2297
|
-
autoComplete: passkeyReady ? "email webauthn" : "email",
|
|
2541
|
+
autoComplete: passkeyReady && mode !== "sso" ? "email webauthn" : "email",
|
|
2298
2542
|
required: true
|
|
2299
2543
|
}
|
|
2300
2544
|
)
|
|
2301
2545
|
] }),
|
|
2302
|
-
mode === "password" ? /* @__PURE__ */
|
|
2303
|
-
/* @__PURE__ */
|
|
2304
|
-
/* @__PURE__ */
|
|
2546
|
+
mode === "password" ? /* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2547
|
+
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-password", children: labels.password }),
|
|
2548
|
+
/* @__PURE__ */ jsx9(
|
|
2305
2549
|
"input",
|
|
2306
2550
|
{
|
|
2307
2551
|
id: "b316-password",
|
|
@@ -2314,34 +2558,101 @@ function SignIn({
|
|
|
2314
2558
|
}
|
|
2315
2559
|
)
|
|
2316
2560
|
] }) : null
|
|
2317
|
-
] }),
|
|
2318
|
-
/* @__PURE__ */
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2561
|
+
] }) : null,
|
|
2562
|
+
mode !== null ? /* @__PURE__ */ jsx9("button", { className: "b316-button", type: "submit", disabled: busy, children: busy ? labels.working : mode === "magic" ? labels.emailMeALink : mode === "phone" && !phoneChallenge ? labels.textMeACode : mode === "sso" ? labels.ssoContinue : labels.submit }) : null,
|
|
2563
|
+
mode === "sso" ? /* @__PURE__ */ jsx9(
|
|
2564
|
+
"button",
|
|
2565
|
+
{
|
|
2566
|
+
type: "button",
|
|
2567
|
+
className: "b316-button b316-button-secondary",
|
|
2568
|
+
style: { marginTop: 10, width: "100%" },
|
|
2569
|
+
disabled: busy,
|
|
2570
|
+
onClick: () => setMode(null),
|
|
2571
|
+
children: labels.back
|
|
2572
|
+
}
|
|
2573
|
+
) : null,
|
|
2574
|
+
(passkeyReady || offered.sso) && mode !== "sso" ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
2575
|
+
hasForm ? /* @__PURE__ */ jsx9("div", { className: "b316-divider", children: labels.or }) : null,
|
|
2576
|
+
passkeyReady ? /* @__PURE__ */ jsx9(
|
|
2322
2577
|
"button",
|
|
2323
2578
|
{
|
|
2324
2579
|
type: "button",
|
|
2325
2580
|
className: "b316-button b316-button-secondary",
|
|
2581
|
+
style: { width: "100%" },
|
|
2326
2582
|
disabled: busy,
|
|
2327
2583
|
onClick: () => {
|
|
2328
2584
|
abortRef.current?.abort();
|
|
2329
2585
|
void signInWithPasskey(false);
|
|
2330
2586
|
},
|
|
2331
|
-
children:
|
|
2587
|
+
children: labels.passkey
|
|
2332
2588
|
}
|
|
2333
|
-
)
|
|
2589
|
+
) : null,
|
|
2590
|
+
offered.sso ? /* @__PURE__ */ jsx9(
|
|
2591
|
+
"button",
|
|
2592
|
+
{
|
|
2593
|
+
type: "button",
|
|
2594
|
+
className: "b316-button b316-button-secondary",
|
|
2595
|
+
style: { width: "100%", marginTop: passkeyReady ? 8 : 0 },
|
|
2596
|
+
disabled: busy,
|
|
2597
|
+
onClick: () => {
|
|
2598
|
+
abortRef.current?.abort();
|
|
2599
|
+
setError(null);
|
|
2600
|
+
setMode("sso");
|
|
2601
|
+
},
|
|
2602
|
+
children: labels.sso
|
|
2603
|
+
}
|
|
2604
|
+
) : null
|
|
2334
2605
|
] }) : null
|
|
2335
2606
|
] });
|
|
2336
2607
|
}
|
|
2337
2608
|
|
|
2609
|
+
// src/SocialSignIn.tsx
|
|
2610
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2611
|
+
function SocialSignIn({
|
|
2612
|
+
socialRedirectUrl,
|
|
2613
|
+
socialState,
|
|
2614
|
+
social,
|
|
2615
|
+
intent = "sign-in",
|
|
2616
|
+
divider = false,
|
|
2617
|
+
labels
|
|
2618
|
+
}) {
|
|
2619
|
+
const { client } = useBase316();
|
|
2620
|
+
const loaded = useSignInMethods(client);
|
|
2621
|
+
if (!loaded.methods || intent === "sign-up" && !loaded.methods.signUp) {
|
|
2622
|
+
return null;
|
|
2623
|
+
}
|
|
2624
|
+
const offered = resolveMethods(loaded.methods, { social, socialRedirectUrl }, null);
|
|
2625
|
+
if (!socialRedirectUrl || offered.social.length === 0) {
|
|
2626
|
+
return null;
|
|
2627
|
+
}
|
|
2628
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2629
|
+
/* @__PURE__ */ jsx10(
|
|
2630
|
+
SocialButtons,
|
|
2631
|
+
{
|
|
2632
|
+
options: offered.social,
|
|
2633
|
+
continueWith: labels?.continueWith ?? ((name) => `Continue with ${name}`),
|
|
2634
|
+
onChoose: (option) => beginRedirect(
|
|
2635
|
+
(state) => client.socialSignInUrl({
|
|
2636
|
+
provider: option.slug,
|
|
2637
|
+
redirectUri: socialRedirectUrl,
|
|
2638
|
+
state,
|
|
2639
|
+
hostedUrl: offered.hostedUrl
|
|
2640
|
+
}),
|
|
2641
|
+
socialState
|
|
2642
|
+
)
|
|
2643
|
+
}
|
|
2644
|
+
),
|
|
2645
|
+
divider ? /* @__PURE__ */ jsx10("div", { className: "b316-divider", children: labels?.or ?? "or" }) : null
|
|
2646
|
+
] });
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2338
2649
|
// src/SignUp.tsx
|
|
2339
2650
|
import {
|
|
2340
2651
|
Base316Error as Base316Error3,
|
|
2341
2652
|
needsSecondFactor as needsSecondFactor2
|
|
2342
2653
|
} from "@base316/sdk";
|
|
2343
|
-
import { useEffect as
|
|
2344
|
-
import { jsx as
|
|
2654
|
+
import { useEffect as useEffect9, useState as useState9 } from "react";
|
|
2655
|
+
import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2345
2656
|
var DEFAULT_SIGN_UP_LABELS = {
|
|
2346
2657
|
name: "Name",
|
|
2347
2658
|
email: "Email",
|
|
@@ -2358,7 +2669,10 @@ var DEFAULT_SIGN_UP_LABELS = {
|
|
|
2358
2669
|
confirmEmail: (email) => `Your account is ready. We sent a confirmation link to ${email} \u2014 open it, then sign in.`,
|
|
2359
2670
|
createdSignInFailed: (reason) => `Your account was created, but we could not sign you in: ${reason}`,
|
|
2360
2671
|
genericError: "We could not create that account. Try again.",
|
|
2361
|
-
joining: (organizationName, roleName) => `You are joining ${organizationName} as ${roleName}. Sign up with the address the invitation was sent to
|
|
2672
|
+
joining: (organizationName, roleName) => `You are joining ${organizationName} as ${roleName}. Sign up with the address the invitation was sent to.`,
|
|
2673
|
+
continueWith: (name) => `Continue with ${name}`,
|
|
2674
|
+
or: "or",
|
|
2675
|
+
closed: "This application is not accepting new accounts right now."
|
|
2362
2676
|
};
|
|
2363
2677
|
function describeRules(policy, labels) {
|
|
2364
2678
|
const extras = [
|
|
@@ -2377,30 +2691,35 @@ function SignUp({
|
|
|
2377
2691
|
onJoined,
|
|
2378
2692
|
labels: overrides,
|
|
2379
2693
|
secondFactorLabels,
|
|
2694
|
+
social,
|
|
2695
|
+
socialRedirectUrl,
|
|
2696
|
+
socialState,
|
|
2380
2697
|
className,
|
|
2381
2698
|
style
|
|
2382
2699
|
}) {
|
|
2383
2700
|
const labels = { ...DEFAULT_SIGN_UP_LABELS, ...overrides };
|
|
2384
2701
|
const { client, setToken } = useBase316();
|
|
2385
|
-
const
|
|
2386
|
-
const
|
|
2387
|
-
const [
|
|
2388
|
-
const [
|
|
2389
|
-
const [
|
|
2390
|
-
const [
|
|
2391
|
-
const [
|
|
2392
|
-
const [
|
|
2393
|
-
const [
|
|
2394
|
-
const [
|
|
2702
|
+
const methodsState = useSignInMethods(client);
|
|
2703
|
+
const offered = resolveMethods(methodsState.methods, { social, socialRedirectUrl }, null);
|
|
2704
|
+
const [name, setName] = useState9("");
|
|
2705
|
+
const [email, setEmail] = useState9("");
|
|
2706
|
+
const [password, setPassword] = useState9("");
|
|
2707
|
+
const [error, setError] = useState9(null);
|
|
2708
|
+
const [busy, setBusy] = useState9(false);
|
|
2709
|
+
const [policy, setPolicy] = useState9(null);
|
|
2710
|
+
const [pending, setPending] = useState9(null);
|
|
2711
|
+
const [confirmEmail, setConfirmEmail] = useState9(false);
|
|
2712
|
+
const [urlInvitation, setUrlInvitation] = useState9(null);
|
|
2713
|
+
const [loaded, setLoaded] = useState9(null);
|
|
2395
2714
|
const invitation = suppliedInvitation === void 0 ? urlInvitation : suppliedInvitation;
|
|
2396
2715
|
const preview = loaded && loaded.token === invitation ? loaded.preview : null;
|
|
2397
|
-
|
|
2716
|
+
useEffect9(() => {
|
|
2398
2717
|
if (suppliedInvitation !== void 0 || typeof window === "undefined") {
|
|
2399
2718
|
return;
|
|
2400
2719
|
}
|
|
2401
2720
|
setUrlInvitation(new URL(window.location.href).searchParams.get("invitation"));
|
|
2402
2721
|
}, [suppliedInvitation]);
|
|
2403
|
-
|
|
2722
|
+
useEffect9(() => {
|
|
2404
2723
|
if (!invitation) {
|
|
2405
2724
|
return;
|
|
2406
2725
|
}
|
|
@@ -2415,7 +2734,7 @@ function SignUp({
|
|
|
2415
2734
|
cancelled = true;
|
|
2416
2735
|
};
|
|
2417
2736
|
}, [client, invitation]);
|
|
2418
|
-
|
|
2737
|
+
useEffect9(() => {
|
|
2419
2738
|
let cancelled = false;
|
|
2420
2739
|
client.auth.passwordPolicy().then((loaded2) => {
|
|
2421
2740
|
if (!cancelled) {
|
|
@@ -2473,86 +2792,118 @@ function SignUp({
|
|
|
2473
2792
|
}
|
|
2474
2793
|
}
|
|
2475
2794
|
if (pending) {
|
|
2476
|
-
return /* @__PURE__ */
|
|
2795
|
+
return /* @__PURE__ */ jsx11("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx11(SecondFactorStep, { pending, labels: secondFactorLabels, onSignedIn: onSignedUp }) });
|
|
2477
2796
|
}
|
|
2478
2797
|
if (confirmEmail) {
|
|
2479
|
-
return /* @__PURE__ */
|
|
2480
|
-
/* @__PURE__ */
|
|
2481
|
-
/* @__PURE__ */
|
|
2798
|
+
return /* @__PURE__ */ jsxs10("div", { className: cls("b316-card", className), style, children: [
|
|
2799
|
+
/* @__PURE__ */ jsx11("h3", { className: "b316-form-title", children: labels.confirmEmailTitle }),
|
|
2800
|
+
/* @__PURE__ */ jsx11("output", { className: "b316-muted", children: labels.confirmEmail(email) })
|
|
2482
2801
|
] });
|
|
2483
2802
|
}
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
id: "b316-name",
|
|
2493
|
-
className: "b316-input",
|
|
2494
|
-
value: name,
|
|
2495
|
-
onChange: (event) => setName(event.target.value),
|
|
2496
|
-
autoComplete: "name"
|
|
2497
|
-
}
|
|
2498
|
-
)
|
|
2499
|
-
] }),
|
|
2500
|
-
/* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2501
|
-
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-signup-email", children: labels.email }),
|
|
2502
|
-
/* @__PURE__ */ jsx9(
|
|
2503
|
-
"input",
|
|
2504
|
-
{
|
|
2505
|
-
id: "b316-signup-email",
|
|
2506
|
-
className: "b316-input",
|
|
2507
|
-
type: "email",
|
|
2508
|
-
value: email,
|
|
2509
|
-
onChange: (event) => setEmail(event.target.value),
|
|
2510
|
-
autoComplete: "email",
|
|
2511
|
-
required: true
|
|
2512
|
-
}
|
|
2513
|
-
)
|
|
2514
|
-
] }),
|
|
2515
|
-
/* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2516
|
-
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-signup-password", children: labels.password }),
|
|
2517
|
-
/* @__PURE__ */ jsx9(
|
|
2518
|
-
"input",
|
|
2803
|
+
if (!offered.signUp && !invitation) {
|
|
2804
|
+
return /* @__PURE__ */ jsx11("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx11("output", { className: "b316-muted", children: labels.closed }) });
|
|
2805
|
+
}
|
|
2806
|
+
const socialOptions = invitation ? [] : offered.social;
|
|
2807
|
+
return /* @__PURE__ */ jsxs10("form", { onSubmit: submit, className: cls("b316-card", className), style, children: [
|
|
2808
|
+
socialOptions.length > 0 ? /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
2809
|
+
/* @__PURE__ */ jsx11(
|
|
2810
|
+
SocialButtons,
|
|
2519
2811
|
{
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2812
|
+
options: socialOptions,
|
|
2813
|
+
continueWith: labels.continueWith,
|
|
2814
|
+
disabled: busy,
|
|
2815
|
+
onChoose: (option) => {
|
|
2816
|
+
if (!socialRedirectUrl) {
|
|
2817
|
+
return;
|
|
2818
|
+
}
|
|
2819
|
+
setBusy(true);
|
|
2820
|
+
beginRedirect(
|
|
2821
|
+
(state) => client.socialSignInUrl({
|
|
2822
|
+
provider: option.slug,
|
|
2823
|
+
redirectUri: socialRedirectUrl,
|
|
2824
|
+
state,
|
|
2825
|
+
hostedUrl: offered.hostedUrl
|
|
2826
|
+
}),
|
|
2827
|
+
socialState
|
|
2828
|
+
);
|
|
2829
|
+
}
|
|
2530
2830
|
}
|
|
2531
2831
|
),
|
|
2532
|
-
|
|
2533
|
-
] }),
|
|
2534
|
-
/* @__PURE__ */
|
|
2832
|
+
offered.password ? /* @__PURE__ */ jsx11("div", { className: "b316-divider", children: labels.or }) : null
|
|
2833
|
+
] }) : null,
|
|
2834
|
+
preview ? /* @__PURE__ */ jsx11("p", { className: "b316-muted", children: labels.joining(preview.organizationName, preview.roleName) }) : null,
|
|
2835
|
+
error ? /* @__PURE__ */ jsx11("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
2836
|
+
offered.password || socialOptions.length === 0 ? /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
2837
|
+
/* @__PURE__ */ jsxs10("div", { className: "b316-field", children: [
|
|
2838
|
+
/* @__PURE__ */ jsx11("label", { className: "b316-label", htmlFor: "b316-name", children: labels.name }),
|
|
2839
|
+
/* @__PURE__ */ jsx11(
|
|
2840
|
+
"input",
|
|
2841
|
+
{
|
|
2842
|
+
id: "b316-name",
|
|
2843
|
+
className: "b316-input",
|
|
2844
|
+
value: name,
|
|
2845
|
+
onChange: (event) => setName(event.target.value),
|
|
2846
|
+
autoComplete: "name"
|
|
2847
|
+
}
|
|
2848
|
+
)
|
|
2849
|
+
] }),
|
|
2850
|
+
/* @__PURE__ */ jsxs10("div", { className: "b316-field", children: [
|
|
2851
|
+
/* @__PURE__ */ jsx11("label", { className: "b316-label", htmlFor: "b316-signup-email", children: labels.email }),
|
|
2852
|
+
/* @__PURE__ */ jsx11(
|
|
2853
|
+
"input",
|
|
2854
|
+
{
|
|
2855
|
+
id: "b316-signup-email",
|
|
2856
|
+
className: "b316-input",
|
|
2857
|
+
type: "email",
|
|
2858
|
+
value: email,
|
|
2859
|
+
onChange: (event) => setEmail(event.target.value),
|
|
2860
|
+
autoComplete: "email",
|
|
2861
|
+
required: true
|
|
2862
|
+
}
|
|
2863
|
+
)
|
|
2864
|
+
] }),
|
|
2865
|
+
/* @__PURE__ */ jsxs10("div", { className: "b316-field", children: [
|
|
2866
|
+
/* @__PURE__ */ jsx11("label", { className: "b316-label", htmlFor: "b316-signup-password", children: labels.password }),
|
|
2867
|
+
/* @__PURE__ */ jsx11(
|
|
2868
|
+
"input",
|
|
2869
|
+
{
|
|
2870
|
+
id: "b316-signup-password",
|
|
2871
|
+
className: "b316-input",
|
|
2872
|
+
type: "password",
|
|
2873
|
+
value: password,
|
|
2874
|
+
onChange: (event) => setPassword(event.target.value),
|
|
2875
|
+
autoComplete: "new-password",
|
|
2876
|
+
minLength: policy?.minLength,
|
|
2877
|
+
maxLength: policy?.maxLength,
|
|
2878
|
+
"aria-describedby": policy ? "b316-signup-password-rules" : void 0,
|
|
2879
|
+
required: true
|
|
2880
|
+
}
|
|
2881
|
+
),
|
|
2882
|
+
policy ? /* @__PURE__ */ jsx11("span", { id: "b316-signup-password-rules", className: "b316-muted", children: describeRules(policy, labels) }) : null
|
|
2883
|
+
] }),
|
|
2884
|
+
/* @__PURE__ */ jsx11("button", { className: "b316-button", type: "submit", disabled: busy, children: busy ? labels.working : labels.submit })
|
|
2885
|
+
] }) : null
|
|
2535
2886
|
] });
|
|
2536
2887
|
}
|
|
2537
2888
|
|
|
2538
2889
|
// src/UserProfile.tsx
|
|
2539
|
-
import { jsx as
|
|
2890
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2540
2891
|
function UserProfile({ className, style }) {
|
|
2541
2892
|
const { session, loading, signOut } = useBase316();
|
|
2542
2893
|
if (loading) {
|
|
2543
|
-
return /* @__PURE__ */
|
|
2894
|
+
return /* @__PURE__ */ jsx12("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
2544
2895
|
}
|
|
2545
2896
|
if (!session) {
|
|
2546
|
-
return /* @__PURE__ */
|
|
2897
|
+
return /* @__PURE__ */ jsx12("div", { className: cls("b316-card", className), style, children: "Not signed in." });
|
|
2547
2898
|
}
|
|
2548
2899
|
const user = session.user ?? {};
|
|
2549
|
-
return /* @__PURE__ */
|
|
2550
|
-
/* @__PURE__ */
|
|
2551
|
-
/* @__PURE__ */
|
|
2552
|
-
user.name && user.email ? /* @__PURE__ */
|
|
2553
|
-
user.emailVerified === false ? /* @__PURE__ */
|
|
2900
|
+
return /* @__PURE__ */ jsx12("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsxs11("div", { className: "b316-row", children: [
|
|
2901
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
2902
|
+
/* @__PURE__ */ jsx12("div", { style: { fontWeight: 600 }, children: user.name || user.email || "Signed in" }),
|
|
2903
|
+
user.name && user.email ? /* @__PURE__ */ jsx12("div", { className: "b316-muted", children: user.email }) : null,
|
|
2904
|
+
user.emailVerified === false ? /* @__PURE__ */ jsx12("div", { className: "b316-muted", children: "Email not verified" }) : null
|
|
2554
2905
|
] }),
|
|
2555
|
-
/* @__PURE__ */
|
|
2906
|
+
/* @__PURE__ */ jsx12(
|
|
2556
2907
|
"button",
|
|
2557
2908
|
{
|
|
2558
2909
|
type: "button",
|
|
@@ -2566,11 +2917,11 @@ function UserProfile({ className, style }) {
|
|
|
2566
2917
|
|
|
2567
2918
|
// src/PasskeyManager.tsx
|
|
2568
2919
|
import { isPasskeySupported as isPasskeySupported2 } from "@base316/sdk";
|
|
2569
|
-
import { useCallback as useCallback5, useEffect as
|
|
2920
|
+
import { useCallback as useCallback5, useEffect as useEffect11, useState as useState11 } from "react";
|
|
2570
2921
|
|
|
2571
2922
|
// src/confirm.tsx
|
|
2572
|
-
import { useEffect as
|
|
2573
|
-
import { jsx as
|
|
2923
|
+
import { useEffect as useEffect10, useRef as useRef3, useState as useState10 } from "react";
|
|
2924
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2574
2925
|
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
2575
2926
|
function ConfirmButton({
|
|
2576
2927
|
children,
|
|
@@ -2580,9 +2931,9 @@ function ConfirmButton({
|
|
|
2580
2931
|
disabled,
|
|
2581
2932
|
timeoutMs = DEFAULT_TIMEOUT_MS
|
|
2582
2933
|
}) {
|
|
2583
|
-
const [armed, setArmed] =
|
|
2934
|
+
const [armed, setArmed] = useState10(false);
|
|
2584
2935
|
const confirmRef = useRef3(null);
|
|
2585
|
-
|
|
2936
|
+
useEffect10(() => {
|
|
2586
2937
|
if (!armed) {
|
|
2587
2938
|
return;
|
|
2588
2939
|
}
|
|
@@ -2591,7 +2942,7 @@ function ConfirmButton({
|
|
|
2591
2942
|
return () => clearTimeout(timer);
|
|
2592
2943
|
}, [armed, timeoutMs]);
|
|
2593
2944
|
if (!armed) {
|
|
2594
|
-
return /* @__PURE__ */
|
|
2945
|
+
return /* @__PURE__ */ jsx13(
|
|
2595
2946
|
"button",
|
|
2596
2947
|
{
|
|
2597
2948
|
type: "button",
|
|
@@ -2605,8 +2956,8 @@ function ConfirmButton({
|
|
|
2605
2956
|
return (
|
|
2606
2957
|
// No `role="group"`: both buttons already say what they do, and the
|
|
2607
2958
|
// grouping would only repeat the question a screen reader has just read.
|
|
2608
|
-
/* @__PURE__ */
|
|
2609
|
-
/* @__PURE__ */
|
|
2959
|
+
/* @__PURE__ */ jsxs12("span", { className: "b316-confirm", children: [
|
|
2960
|
+
/* @__PURE__ */ jsx13(
|
|
2610
2961
|
"button",
|
|
2611
2962
|
{
|
|
2612
2963
|
ref: confirmRef,
|
|
@@ -2620,7 +2971,7 @@ function ConfirmButton({
|
|
|
2620
2971
|
children: confirmLabel
|
|
2621
2972
|
}
|
|
2622
2973
|
),
|
|
2623
|
-
/* @__PURE__ */
|
|
2974
|
+
/* @__PURE__ */ jsx13(
|
|
2624
2975
|
"button",
|
|
2625
2976
|
{
|
|
2626
2977
|
type: "button",
|
|
@@ -2634,18 +2985,18 @@ function ConfirmButton({
|
|
|
2634
2985
|
}
|
|
2635
2986
|
|
|
2636
2987
|
// src/PasskeyManager.tsx
|
|
2637
|
-
import { jsx as
|
|
2988
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2638
2989
|
function PasskeyManager({
|
|
2639
2990
|
className,
|
|
2640
2991
|
style,
|
|
2641
2992
|
title = "Passkeys"
|
|
2642
2993
|
}) {
|
|
2643
2994
|
const { client, token, session } = useBase316();
|
|
2644
|
-
const [passkeys, setPasskeys] =
|
|
2645
|
-
const [busy, setBusy] =
|
|
2646
|
-
const [error, setError] =
|
|
2647
|
-
const [name, setName] =
|
|
2648
|
-
const [supported, setSupported] =
|
|
2995
|
+
const [passkeys, setPasskeys] = useState11(null);
|
|
2996
|
+
const [busy, setBusy] = useState11(false);
|
|
2997
|
+
const [error, setError] = useState11(null);
|
|
2998
|
+
const [name, setName] = useState11("");
|
|
2999
|
+
const [supported, setSupported] = useState11(false);
|
|
2649
3000
|
const load = useCallback5(async () => {
|
|
2650
3001
|
if (!token) {
|
|
2651
3002
|
return;
|
|
@@ -2659,7 +3010,7 @@ function PasskeyManager({
|
|
|
2659
3010
|
setPasskeys(null);
|
|
2660
3011
|
}
|
|
2661
3012
|
}, [client, token]);
|
|
2662
|
-
|
|
3013
|
+
useEffect11(() => {
|
|
2663
3014
|
if (!isPasskeySupported2()) {
|
|
2664
3015
|
return;
|
|
2665
3016
|
}
|
|
@@ -2695,18 +3046,18 @@ function PasskeyManager({
|
|
|
2695
3046
|
setError(caught instanceof Error ? caught.message : "That did not work.");
|
|
2696
3047
|
}
|
|
2697
3048
|
};
|
|
2698
|
-
return /* @__PURE__ */
|
|
2699
|
-
/* @__PURE__ */
|
|
2700
|
-
/* @__PURE__ */
|
|
2701
|
-
passkeys === null ? /* @__PURE__ */
|
|
2702
|
-
/* @__PURE__ */
|
|
2703
|
-
/* @__PURE__ */
|
|
2704
|
-
/* @__PURE__ */
|
|
3049
|
+
return /* @__PURE__ */ jsxs13("div", { className: cls("b316-card", className), style, children: [
|
|
3050
|
+
/* @__PURE__ */ jsx14("div", { style: { fontWeight: 600, marginBottom: 4 }, children: title }),
|
|
3051
|
+
/* @__PURE__ */ jsx14("div", { className: "b316-muted", style: { marginBottom: 12 }, children: "Sign in with your fingerprint, face or a security key \u2014 nothing to type and nothing to remember." }),
|
|
3052
|
+
passkeys === null ? /* @__PURE__ */ jsx14("div", { className: "b316-muted", children: "Loading\u2026" }) : passkeys.length === 0 ? /* @__PURE__ */ jsx14("div", { className: "b316-muted", children: "No passkeys yet." }) : /* @__PURE__ */ jsx14("ul", { style: { listStyle: "none", margin: 0, padding: 0 }, children: passkeys.map((passkey) => /* @__PURE__ */ jsxs13("li", { className: "b316-row", style: { padding: "8px 0" }, children: [
|
|
3053
|
+
/* @__PURE__ */ jsxs13("div", { children: [
|
|
3054
|
+
/* @__PURE__ */ jsx14("div", { children: passkey.name || "Passkey" }),
|
|
3055
|
+
/* @__PURE__ */ jsxs13("div", { className: "b316-muted", children: [
|
|
2705
3056
|
passkey.lastUsedAt ? `Last used ${formatDate(passkey.lastUsedAt)}` : `Added ${formatDate(passkey.createdAt)}`,
|
|
2706
3057
|
passkey.backedUp ? "" : " \xB7 this device only"
|
|
2707
3058
|
] })
|
|
2708
3059
|
] }),
|
|
2709
|
-
/* @__PURE__ */
|
|
3060
|
+
/* @__PURE__ */ jsx14(
|
|
2710
3061
|
ConfirmButton,
|
|
2711
3062
|
{
|
|
2712
3063
|
className: "b316-button b316-button-secondary",
|
|
@@ -2716,9 +3067,9 @@ function PasskeyManager({
|
|
|
2716
3067
|
}
|
|
2717
3068
|
)
|
|
2718
3069
|
] }, passkey.id)) }),
|
|
2719
|
-
error ? /* @__PURE__ */
|
|
2720
|
-
/* @__PURE__ */
|
|
2721
|
-
/* @__PURE__ */
|
|
3070
|
+
error ? /* @__PURE__ */ jsx14("div", { className: "b316-error", role: "alert", style: { marginTop: 12 }, children: error }) : null,
|
|
3071
|
+
/* @__PURE__ */ jsxs13("div", { className: "b316-row", style: { marginTop: 12, gap: 8 }, children: [
|
|
3072
|
+
/* @__PURE__ */ jsx14(
|
|
2722
3073
|
"input",
|
|
2723
3074
|
{
|
|
2724
3075
|
className: "b316-input",
|
|
@@ -2727,7 +3078,7 @@ function PasskeyManager({
|
|
|
2727
3078
|
onChange: (event) => setName(event.target.value)
|
|
2728
3079
|
}
|
|
2729
3080
|
),
|
|
2730
|
-
/* @__PURE__ */
|
|
3081
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "b316-button", disabled: busy, onClick: () => void add(), children: busy ? "Waiting\u2026" : "Add a passkey" })
|
|
2731
3082
|
] })
|
|
2732
3083
|
] });
|
|
2733
3084
|
}
|
|
@@ -2737,8 +3088,8 @@ function formatDate(value) {
|
|
|
2737
3088
|
}
|
|
2738
3089
|
|
|
2739
3090
|
// src/ActiveSessions.tsx
|
|
2740
|
-
import { useCallback as useCallback6, useEffect as
|
|
2741
|
-
import { jsx as
|
|
3091
|
+
import { useCallback as useCallback6, useEffect as useEffect12, useState as useState12 } from "react";
|
|
3092
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2742
3093
|
function describeDevice(userAgent) {
|
|
2743
3094
|
if (!userAgent) {
|
|
2744
3095
|
return null;
|
|
@@ -2756,9 +3107,9 @@ function when(value) {
|
|
|
2756
3107
|
}
|
|
2757
3108
|
function ActiveSessions({ onRevoked, className, style }) {
|
|
2758
3109
|
const { client, token } = useBase316();
|
|
2759
|
-
const [sessions, setSessions] =
|
|
2760
|
-
const [error, setError] =
|
|
2761
|
-
const [busy, setBusy] =
|
|
3110
|
+
const [sessions, setSessions] = useState12(null);
|
|
3111
|
+
const [error, setError] = useState12(null);
|
|
3112
|
+
const [busy, setBusy] = useState12(false);
|
|
2762
3113
|
const load = useCallback6(() => {
|
|
2763
3114
|
if (!token) {
|
|
2764
3115
|
return;
|
|
@@ -2770,15 +3121,15 @@ function ActiveSessions({ onRevoked, className, style }) {
|
|
|
2770
3121
|
setError(cause instanceof Error ? cause.message : "Could not load your sessions.");
|
|
2771
3122
|
});
|
|
2772
3123
|
}, [client, token]);
|
|
2773
|
-
|
|
3124
|
+
useEffect12(load, [load]);
|
|
2774
3125
|
if (!token) {
|
|
2775
3126
|
return null;
|
|
2776
3127
|
}
|
|
2777
3128
|
if (error) {
|
|
2778
|
-
return /* @__PURE__ */
|
|
3129
|
+
return /* @__PURE__ */ jsx15("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx15("div", { className: "b316-error", role: "alert", children: error }) });
|
|
2779
3130
|
}
|
|
2780
3131
|
if (!sessions) {
|
|
2781
|
-
return /* @__PURE__ */
|
|
3132
|
+
return /* @__PURE__ */ jsx15("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
2782
3133
|
}
|
|
2783
3134
|
async function revokeOthers() {
|
|
2784
3135
|
setBusy(true);
|
|
@@ -2792,32 +3143,32 @@ function ActiveSessions({ onRevoked, className, style }) {
|
|
|
2792
3143
|
setBusy(false);
|
|
2793
3144
|
}
|
|
2794
3145
|
}
|
|
2795
|
-
return /* @__PURE__ */
|
|
2796
|
-
/* @__PURE__ */
|
|
2797
|
-
/* @__PURE__ */
|
|
2798
|
-
sessions.length > 1 ? /* @__PURE__ */
|
|
3146
|
+
return /* @__PURE__ */ jsxs14("div", { className: cls("b316-card b316-sessions", className), style, children: [
|
|
3147
|
+
/* @__PURE__ */ jsxs14("div", { className: "b316-sessions-head", children: [
|
|
3148
|
+
/* @__PURE__ */ jsx15("h3", { className: "b316-sessions-title", children: "Where you are signed in" }),
|
|
3149
|
+
sessions.length > 1 ? /* @__PURE__ */ jsx15("button", { type: "button", className: "b316-button", disabled: busy, onClick: revokeOthers, children: busy ? "Ending\u2026" : "Sign out other devices" }) : null
|
|
2799
3150
|
] }),
|
|
2800
|
-
/* @__PURE__ */
|
|
2801
|
-
/* @__PURE__ */
|
|
3151
|
+
/* @__PURE__ */ jsx15("ul", { className: "b316-sessions-list", children: sessions.map((session) => /* @__PURE__ */ jsxs14("li", { className: "b316-session", children: [
|
|
3152
|
+
/* @__PURE__ */ jsxs14("div", { className: "b316-session-device", children: [
|
|
2802
3153
|
describeDevice(session.userAgent) ?? "Unknown device",
|
|
2803
3154
|
session.impersonatedBy ? (
|
|
2804
3155
|
// Worth saying loudly: somebody is acting as this account.
|
|
2805
|
-
/* @__PURE__ */
|
|
3156
|
+
/* @__PURE__ */ jsx15("span", { className: "b316-chip", children: " Support access" })
|
|
2806
3157
|
) : null
|
|
2807
3158
|
] }),
|
|
2808
|
-
/* @__PURE__ */
|
|
3159
|
+
/* @__PURE__ */ jsxs14("div", { className: "b316-muted", children: [
|
|
2809
3160
|
session.ipAddress ? `${session.ipAddress} \xB7 ` : "",
|
|
2810
3161
|
"last used ",
|
|
2811
3162
|
when(session.lastSeenAt)
|
|
2812
3163
|
] })
|
|
2813
3164
|
] }, session.id)) }),
|
|
2814
|
-
sessions.length === 0 ? /* @__PURE__ */
|
|
3165
|
+
sessions.length === 0 ? /* @__PURE__ */ jsx15("div", { className: "b316-muted", children: "No active sessions." }) : null
|
|
2815
3166
|
] });
|
|
2816
3167
|
}
|
|
2817
3168
|
|
|
2818
3169
|
// src/DeviceApproval.tsx
|
|
2819
|
-
import { useState as
|
|
2820
|
-
import { jsx as
|
|
3170
|
+
import { useState as useState13 } from "react";
|
|
3171
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2821
3172
|
function DeviceApproval({
|
|
2822
3173
|
userCode = "",
|
|
2823
3174
|
onDecided,
|
|
@@ -2825,11 +3176,11 @@ function DeviceApproval({
|
|
|
2825
3176
|
style
|
|
2826
3177
|
}) {
|
|
2827
3178
|
const { client, token } = useBase316();
|
|
2828
|
-
const [code, setCode] =
|
|
2829
|
-
const [request, setRequest] =
|
|
2830
|
-
const [decided, setDecided] =
|
|
2831
|
-
const [error, setError] =
|
|
2832
|
-
const [busy, setBusy] =
|
|
3179
|
+
const [code, setCode] = useState13(userCode);
|
|
3180
|
+
const [request, setRequest] = useState13(null);
|
|
3181
|
+
const [decided, setDecided] = useState13(null);
|
|
3182
|
+
const [error, setError] = useState13(null);
|
|
3183
|
+
const [busy, setBusy] = useState13(false);
|
|
2833
3184
|
if (!token) {
|
|
2834
3185
|
return null;
|
|
2835
3186
|
}
|
|
@@ -2862,25 +3213,25 @@ function DeviceApproval({
|
|
|
2862
3213
|
}
|
|
2863
3214
|
}
|
|
2864
3215
|
if (decided !== null) {
|
|
2865
|
-
return /* @__PURE__ */
|
|
2866
|
-
/* @__PURE__ */
|
|
2867
|
-
/* @__PURE__ */
|
|
3216
|
+
return /* @__PURE__ */ jsxs15("div", { className: cls("b316-card b316-device", className), style, children: [
|
|
3217
|
+
/* @__PURE__ */ jsx16("h3", { className: "b316-device-title", children: decided ? "You're all set" : "Not approved" }),
|
|
3218
|
+
/* @__PURE__ */ jsx16("p", { className: "b316-muted", children: decided ? "You can close this page and go back to your device." : "Nothing was granted. You can close this page." })
|
|
2868
3219
|
] });
|
|
2869
3220
|
}
|
|
2870
3221
|
if (request) {
|
|
2871
|
-
return /* @__PURE__ */
|
|
2872
|
-
/* @__PURE__ */
|
|
3222
|
+
return /* @__PURE__ */ jsxs15("div", { className: cls("b316-card b316-device", className), style, children: [
|
|
3223
|
+
/* @__PURE__ */ jsxs15("h3", { className: "b316-device-title", children: [
|
|
2873
3224
|
"Sign in to ",
|
|
2874
3225
|
request.clientName
|
|
2875
3226
|
] }),
|
|
2876
|
-
/* @__PURE__ */
|
|
3227
|
+
/* @__PURE__ */ jsxs15("p", { className: "b316-muted", children: [
|
|
2877
3228
|
request.clientName,
|
|
2878
3229
|
" is asking to sign in as you."
|
|
2879
3230
|
] }),
|
|
2880
|
-
request.scopes.length > 0 ? /* @__PURE__ */
|
|
2881
|
-
error ? /* @__PURE__ */
|
|
2882
|
-
/* @__PURE__ */
|
|
2883
|
-
/* @__PURE__ */
|
|
3231
|
+
request.scopes.length > 0 ? /* @__PURE__ */ jsx16("ul", { className: "b316-device-scopes", children: request.scopes.map((scope) => /* @__PURE__ */ jsx16("li", { children: scope }, scope)) }) : null,
|
|
3232
|
+
error ? /* @__PURE__ */ jsx16("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3233
|
+
/* @__PURE__ */ jsxs15("div", { className: "b316-device-actions", children: [
|
|
3234
|
+
/* @__PURE__ */ jsx16(
|
|
2884
3235
|
"button",
|
|
2885
3236
|
{
|
|
2886
3237
|
type: "button",
|
|
@@ -2890,7 +3241,7 @@ function DeviceApproval({
|
|
|
2890
3241
|
children: busy ? "Approving\u2026" : "Approve"
|
|
2891
3242
|
}
|
|
2892
3243
|
),
|
|
2893
|
-
/* @__PURE__ */
|
|
3244
|
+
/* @__PURE__ */ jsx16(
|
|
2894
3245
|
"button",
|
|
2895
3246
|
{
|
|
2896
3247
|
type: "button",
|
|
@@ -2903,11 +3254,11 @@ function DeviceApproval({
|
|
|
2903
3254
|
] })
|
|
2904
3255
|
] });
|
|
2905
3256
|
}
|
|
2906
|
-
return /* @__PURE__ */
|
|
2907
|
-
/* @__PURE__ */
|
|
2908
|
-
/* @__PURE__ */
|
|
2909
|
-
error ? /* @__PURE__ */
|
|
2910
|
-
/* @__PURE__ */
|
|
3257
|
+
return /* @__PURE__ */ jsxs15("form", { className: cls("b316-card b316-device", className), style, onSubmit: lookUp, children: [
|
|
3258
|
+
/* @__PURE__ */ jsx16("h3", { className: "b316-device-title", children: "Connect your device" }),
|
|
3259
|
+
/* @__PURE__ */ jsx16("p", { className: "b316-muted", children: "Enter the code shown on your device." }),
|
|
3260
|
+
error ? /* @__PURE__ */ jsx16("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3261
|
+
/* @__PURE__ */ jsx16(
|
|
2911
3262
|
"input",
|
|
2912
3263
|
{
|
|
2913
3264
|
className: "b316-input",
|
|
@@ -2920,13 +3271,13 @@ function DeviceApproval({
|
|
|
2920
3271
|
"aria-label": "Device code"
|
|
2921
3272
|
}
|
|
2922
3273
|
),
|
|
2923
|
-
/* @__PURE__ */
|
|
3274
|
+
/* @__PURE__ */ jsx16("button", { type: "submit", className: "b316-button", disabled: busy || code.trim().length < 4, children: busy ? "Checking\u2026" : "Continue" })
|
|
2924
3275
|
] });
|
|
2925
3276
|
}
|
|
2926
3277
|
|
|
2927
3278
|
// src/PrivacyControls.tsx
|
|
2928
|
-
import { useState as
|
|
2929
|
-
import { jsx as
|
|
3279
|
+
import { useState as useState14 } from "react";
|
|
3280
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2930
3281
|
function PrivacyControls({
|
|
2931
3282
|
confirmWord = "DELETE",
|
|
2932
3283
|
onErased,
|
|
@@ -2934,10 +3285,10 @@ function PrivacyControls({
|
|
|
2934
3285
|
style
|
|
2935
3286
|
}) {
|
|
2936
3287
|
const { client, token } = useBase316();
|
|
2937
|
-
const [confirming, setConfirming] =
|
|
2938
|
-
const [typed, setTyped] =
|
|
2939
|
-
const [error, setError] =
|
|
2940
|
-
const [busy, setBusy] =
|
|
3288
|
+
const [confirming, setConfirming] = useState14(false);
|
|
3289
|
+
const [typed, setTyped] = useState14("");
|
|
3290
|
+
const [error, setError] = useState14(null);
|
|
3291
|
+
const [busy, setBusy] = useState14(false);
|
|
2941
3292
|
if (!token) {
|
|
2942
3293
|
return null;
|
|
2943
3294
|
}
|
|
@@ -2972,22 +3323,22 @@ function PrivacyControls({
|
|
|
2972
3323
|
setBusy(false);
|
|
2973
3324
|
}
|
|
2974
3325
|
}
|
|
2975
|
-
return /* @__PURE__ */
|
|
2976
|
-
/* @__PURE__ */
|
|
2977
|
-
error ? /* @__PURE__ */
|
|
2978
|
-
/* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
2980
|
-
/* @__PURE__ */
|
|
2981
|
-
/* @__PURE__ */
|
|
3326
|
+
return /* @__PURE__ */ jsxs16("div", { className: cls("b316-card b316-privacy", className), style, children: [
|
|
3327
|
+
/* @__PURE__ */ jsx17("h3", { className: "b316-privacy-title", children: "Your data" }),
|
|
3328
|
+
error ? /* @__PURE__ */ jsx17("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3329
|
+
/* @__PURE__ */ jsxs16("div", { className: "b316-privacy-row", children: [
|
|
3330
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
3331
|
+
/* @__PURE__ */ jsx17("p", { children: "Download a copy" }),
|
|
3332
|
+
/* @__PURE__ */ jsx17("p", { className: "b316-muted", children: "Everything we hold about you, as a file. Passwords and security keys are not included \u2014 they are what protect the account rather than anything you can use." })
|
|
2982
3333
|
] }),
|
|
2983
|
-
/* @__PURE__ */
|
|
3334
|
+
/* @__PURE__ */ jsx17("button", { type: "button", className: "b316-button-quiet", disabled: busy, onClick: download, children: busy ? "Preparing\u2026" : "Download" })
|
|
2984
3335
|
] }),
|
|
2985
|
-
/* @__PURE__ */
|
|
2986
|
-
/* @__PURE__ */
|
|
2987
|
-
/* @__PURE__ */
|
|
2988
|
-
/* @__PURE__ */
|
|
3336
|
+
/* @__PURE__ */ jsxs16("div", { className: "b316-privacy-row", children: [
|
|
3337
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
3338
|
+
/* @__PURE__ */ jsx17("p", { children: "Delete your account" }),
|
|
3339
|
+
/* @__PURE__ */ jsx17("p", { className: "b316-muted", children: "Permanent. Invoices already raised are kept, because the law requires it; everything that identifies you is removed from them." })
|
|
2989
3340
|
] }),
|
|
2990
|
-
confirming ? null : /* @__PURE__ */
|
|
3341
|
+
confirming ? null : /* @__PURE__ */ jsx17(
|
|
2991
3342
|
"button",
|
|
2992
3343
|
{
|
|
2993
3344
|
type: "button",
|
|
@@ -2998,13 +3349,13 @@ function PrivacyControls({
|
|
|
2998
3349
|
}
|
|
2999
3350
|
)
|
|
3000
3351
|
] }),
|
|
3001
|
-
confirming ? /* @__PURE__ */
|
|
3002
|
-
/* @__PURE__ */
|
|
3352
|
+
confirming ? /* @__PURE__ */ jsxs16("div", { className: "b316-privacy-confirm", children: [
|
|
3353
|
+
/* @__PURE__ */ jsxs16("label", { className: "b316-label", htmlFor: "b316-privacy-confirm", children: [
|
|
3003
3354
|
"Type ",
|
|
3004
3355
|
confirmWord,
|
|
3005
3356
|
" to confirm"
|
|
3006
3357
|
] }),
|
|
3007
|
-
/* @__PURE__ */
|
|
3358
|
+
/* @__PURE__ */ jsx17(
|
|
3008
3359
|
"input",
|
|
3009
3360
|
{
|
|
3010
3361
|
id: "b316-privacy-confirm",
|
|
@@ -3014,8 +3365,8 @@ function PrivacyControls({
|
|
|
3014
3365
|
onChange: (event) => setTyped(event.target.value)
|
|
3015
3366
|
}
|
|
3016
3367
|
),
|
|
3017
|
-
/* @__PURE__ */
|
|
3018
|
-
/* @__PURE__ */
|
|
3368
|
+
/* @__PURE__ */ jsxs16("div", { className: "b316-privacy-actions", children: [
|
|
3369
|
+
/* @__PURE__ */ jsx17(
|
|
3019
3370
|
"button",
|
|
3020
3371
|
{
|
|
3021
3372
|
type: "button",
|
|
@@ -3027,7 +3378,7 @@ function PrivacyControls({
|
|
|
3027
3378
|
children: "Cancel"
|
|
3028
3379
|
}
|
|
3029
3380
|
),
|
|
3030
|
-
/* @__PURE__ */
|
|
3381
|
+
/* @__PURE__ */ jsx17(
|
|
3031
3382
|
"button",
|
|
3032
3383
|
{
|
|
3033
3384
|
type: "button",
|
|
@@ -3043,12 +3394,12 @@ function PrivacyControls({
|
|
|
3043
3394
|
}
|
|
3044
3395
|
|
|
3045
3396
|
// src/TwoFactorManager.tsx
|
|
3046
|
-
import { useState as
|
|
3397
|
+
import { useState as useState15 } from "react";
|
|
3047
3398
|
|
|
3048
3399
|
// src/QrCode.tsx
|
|
3049
3400
|
import qrcode from "qrcode-generator";
|
|
3050
3401
|
import { useMemo as useMemo2 } from "react";
|
|
3051
|
-
import { jsx as
|
|
3402
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3052
3403
|
var QUIET_ZONE = 4;
|
|
3053
3404
|
function utf8Binary(value) {
|
|
3054
3405
|
let binary = "";
|
|
@@ -3075,7 +3426,7 @@ function qrPath(value) {
|
|
|
3075
3426
|
function QrCode({ value, label, size = 180, className }) {
|
|
3076
3427
|
const { path, modules } = useMemo2(() => qrPath(value), [value]);
|
|
3077
3428
|
const extent = modules + QUIET_ZONE * 2;
|
|
3078
|
-
return /* @__PURE__ */
|
|
3429
|
+
return /* @__PURE__ */ jsxs17(
|
|
3079
3430
|
"svg",
|
|
3080
3431
|
{
|
|
3081
3432
|
className,
|
|
@@ -3087,15 +3438,15 @@ function QrCode({ value, label, size = 180, className }) {
|
|
|
3087
3438
|
shapeRendering: "crispEdges",
|
|
3088
3439
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3089
3440
|
children: [
|
|
3090
|
-
/* @__PURE__ */
|
|
3091
|
-
/* @__PURE__ */
|
|
3441
|
+
/* @__PURE__ */ jsx18("rect", { width: extent, height: extent, fill: "#ffffff" }),
|
|
3442
|
+
/* @__PURE__ */ jsx18("path", { d: path, fill: "#000000" })
|
|
3092
3443
|
]
|
|
3093
3444
|
}
|
|
3094
3445
|
);
|
|
3095
3446
|
}
|
|
3096
3447
|
|
|
3097
3448
|
// src/TwoFactorManager.tsx
|
|
3098
|
-
import { jsx as
|
|
3449
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3099
3450
|
function groupKey(secret) {
|
|
3100
3451
|
return secret.replace(/\s+/g, "").replace(/(.{4})(?=.)/g, "$1 ");
|
|
3101
3452
|
}
|
|
@@ -3108,12 +3459,12 @@ function TwoFactorManager({
|
|
|
3108
3459
|
style
|
|
3109
3460
|
}) {
|
|
3110
3461
|
const { client, token } = useBase316();
|
|
3111
|
-
const [stage, setStage] =
|
|
3112
|
-
const [on, setOn] =
|
|
3113
|
-
const [code, setCode] =
|
|
3114
|
-
const [phone, setPhone] =
|
|
3115
|
-
const [error, setError] =
|
|
3116
|
-
const [busy, setBusy] =
|
|
3462
|
+
const [stage, setStage] = useState15({ name: "idle" });
|
|
3463
|
+
const [on, setOn] = useState15(enabled);
|
|
3464
|
+
const [code, setCode] = useState15("");
|
|
3465
|
+
const [phone, setPhone] = useState15("");
|
|
3466
|
+
const [error, setError] = useState15(null);
|
|
3467
|
+
const [busy, setBusy] = useState15(false);
|
|
3117
3468
|
if (!token) {
|
|
3118
3469
|
return null;
|
|
3119
3470
|
}
|
|
@@ -3191,17 +3542,17 @@ function TwoFactorManager({
|
|
|
3191
3542
|
setBusy(false);
|
|
3192
3543
|
}
|
|
3193
3544
|
}
|
|
3194
|
-
return /* @__PURE__ */
|
|
3195
|
-
/* @__PURE__ */
|
|
3196
|
-
error ? /* @__PURE__ */
|
|
3197
|
-
stage.name === "saved" ? /* @__PURE__ */
|
|
3198
|
-
/* @__PURE__ */
|
|
3199
|
-
/* @__PURE__ */
|
|
3200
|
-
/* @__PURE__ */
|
|
3201
|
-
] }) : stage.name === "smsNumber" ? /* @__PURE__ */
|
|
3202
|
-
/* @__PURE__ */
|
|
3203
|
-
/* @__PURE__ */
|
|
3204
|
-
/* @__PURE__ */
|
|
3545
|
+
return /* @__PURE__ */ jsxs18("div", { className: cls("b316-card b316-mfa", className), style, children: [
|
|
3546
|
+
/* @__PURE__ */ jsx19("h3", { className: "b316-mfa-title", children: "Two-factor authentication" }),
|
|
3547
|
+
error ? /* @__PURE__ */ jsx19("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3548
|
+
stage.name === "saved" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-codes", children: [
|
|
3549
|
+
/* @__PURE__ */ jsx19("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." }),
|
|
3550
|
+
/* @__PURE__ */ jsx19("ul", { className: "b316-mfa-code-list", children: stage.recoveryCodes.map((recovery) => /* @__PURE__ */ jsx19("li", { children: /* @__PURE__ */ jsx19("code", { children: recovery }) }, recovery)) }),
|
|
3551
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "b316-button", onClick: () => setStage({ name: "idle" }), children: "I have saved them" })
|
|
3552
|
+
] }) : stage.name === "smsNumber" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-enrol", children: [
|
|
3553
|
+
/* @__PURE__ */ jsx19("p", { children: "We will text a code to this number now, and each time you sign in." }),
|
|
3554
|
+
/* @__PURE__ */ jsx19("label", { className: "b316-label", htmlFor: "b316-mfa-phone", children: "Mobile number" }),
|
|
3555
|
+
/* @__PURE__ */ jsx19(
|
|
3205
3556
|
"input",
|
|
3206
3557
|
{
|
|
3207
3558
|
id: "b316-mfa-phone",
|
|
@@ -3213,8 +3564,8 @@ function TwoFactorManager({
|
|
|
3213
3564
|
onChange: (event) => setPhone(event.target.value)
|
|
3214
3565
|
}
|
|
3215
3566
|
),
|
|
3216
|
-
/* @__PURE__ */
|
|
3217
|
-
/* @__PURE__ */
|
|
3567
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3568
|
+
/* @__PURE__ */ jsx19(
|
|
3218
3569
|
"button",
|
|
3219
3570
|
{
|
|
3220
3571
|
type: "button",
|
|
@@ -3223,16 +3574,16 @@ function TwoFactorManager({
|
|
|
3223
3574
|
children: "Cancel"
|
|
3224
3575
|
}
|
|
3225
3576
|
),
|
|
3226
|
-
/* @__PURE__ */
|
|
3577
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "b316-button", disabled: busy, onClick: beginSms, children: busy ? "Sending\u2026" : "Send code" })
|
|
3227
3578
|
] })
|
|
3228
|
-
] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */
|
|
3229
|
-
/* @__PURE__ */
|
|
3579
|
+
] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-enrol", children: [
|
|
3580
|
+
/* @__PURE__ */ jsxs18("p", { children: [
|
|
3230
3581
|
"We sent a code to ",
|
|
3231
3582
|
stage.destinationHint,
|
|
3232
3583
|
". Enter it below to turn this on."
|
|
3233
3584
|
] }),
|
|
3234
|
-
/* @__PURE__ */
|
|
3235
|
-
/* @__PURE__ */
|
|
3585
|
+
/* @__PURE__ */ jsx19("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
|
|
3586
|
+
/* @__PURE__ */ jsx19(
|
|
3236
3587
|
"input",
|
|
3237
3588
|
{
|
|
3238
3589
|
id: "b316-mfa-code",
|
|
@@ -3243,8 +3594,8 @@ function TwoFactorManager({
|
|
|
3243
3594
|
onChange: (event) => setCode(event.target.value)
|
|
3244
3595
|
}
|
|
3245
3596
|
),
|
|
3246
|
-
/* @__PURE__ */
|
|
3247
|
-
/* @__PURE__ */
|
|
3597
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3598
|
+
/* @__PURE__ */ jsx19(
|
|
3248
3599
|
"button",
|
|
3249
3600
|
{
|
|
3250
3601
|
type: "button",
|
|
@@ -3253,7 +3604,7 @@ function TwoFactorManager({
|
|
|
3253
3604
|
children: "Cancel"
|
|
3254
3605
|
}
|
|
3255
3606
|
),
|
|
3256
|
-
/* @__PURE__ */
|
|
3607
|
+
/* @__PURE__ */ jsx19(
|
|
3257
3608
|
"button",
|
|
3258
3609
|
{
|
|
3259
3610
|
type: "button",
|
|
@@ -3264,9 +3615,9 @@ function TwoFactorManager({
|
|
|
3264
3615
|
}
|
|
3265
3616
|
)
|
|
3266
3617
|
] })
|
|
3267
|
-
] }) : stage.name === "enrolling" ? /* @__PURE__ */
|
|
3268
|
-
/* @__PURE__ */
|
|
3269
|
-
/* @__PURE__ */
|
|
3618
|
+
] }) : stage.name === "enrolling" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-enrol", children: [
|
|
3619
|
+
/* @__PURE__ */ jsx19("p", { children: "Scan this with your authenticator app (Google Authenticator, 1Password, Authy\u2026), then enter the six-digit code it shows." }),
|
|
3620
|
+
/* @__PURE__ */ jsx19(
|
|
3270
3621
|
QrCode,
|
|
3271
3622
|
{
|
|
3272
3623
|
className: "b316-mfa-qr",
|
|
@@ -3274,13 +3625,13 @@ function TwoFactorManager({
|
|
|
3274
3625
|
label: "QR code for your authenticator app"
|
|
3275
3626
|
}
|
|
3276
3627
|
),
|
|
3277
|
-
/* @__PURE__ */
|
|
3278
|
-
/* @__PURE__ */
|
|
3279
|
-
/* @__PURE__ */
|
|
3628
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-secret", children: [
|
|
3629
|
+
/* @__PURE__ */ jsx19("span", { className: "b316-label", id: "b316-mfa-manual-key", children: "Can't scan? Enter this key" }),
|
|
3630
|
+
/* @__PURE__ */ jsx19("code", { "aria-labelledby": "b316-mfa-manual-key", children: groupKey(stage.secret) })
|
|
3280
3631
|
] }),
|
|
3281
|
-
/* @__PURE__ */
|
|
3282
|
-
/* @__PURE__ */
|
|
3283
|
-
/* @__PURE__ */
|
|
3632
|
+
/* @__PURE__ */ jsx19("a", { className: "b316-mfa-uri", href: stage.uri, children: "Open in an authenticator app" }),
|
|
3633
|
+
/* @__PURE__ */ jsx19("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
|
|
3634
|
+
/* @__PURE__ */ jsx19(
|
|
3284
3635
|
"input",
|
|
3285
3636
|
{
|
|
3286
3637
|
id: "b316-mfa-code",
|
|
@@ -3291,8 +3642,8 @@ function TwoFactorManager({
|
|
|
3291
3642
|
onChange: (event) => setCode(event.target.value)
|
|
3292
3643
|
}
|
|
3293
3644
|
),
|
|
3294
|
-
/* @__PURE__ */
|
|
3295
|
-
/* @__PURE__ */
|
|
3645
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3646
|
+
/* @__PURE__ */ jsx19(
|
|
3296
3647
|
"button",
|
|
3297
3648
|
{
|
|
3298
3649
|
type: "button",
|
|
@@ -3301,7 +3652,7 @@ function TwoFactorManager({
|
|
|
3301
3652
|
children: "Cancel"
|
|
3302
3653
|
}
|
|
3303
3654
|
),
|
|
3304
|
-
/* @__PURE__ */
|
|
3655
|
+
/* @__PURE__ */ jsx19(
|
|
3305
3656
|
"button",
|
|
3306
3657
|
{
|
|
3307
3658
|
type: "button",
|
|
@@ -3312,9 +3663,9 @@ function TwoFactorManager({
|
|
|
3312
3663
|
}
|
|
3313
3664
|
)
|
|
3314
3665
|
] })
|
|
3315
|
-
] }) : on ? /* @__PURE__ */
|
|
3316
|
-
/* @__PURE__ */
|
|
3317
|
-
/* @__PURE__ */
|
|
3666
|
+
] }) : on ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-on", children: [
|
|
3667
|
+
/* @__PURE__ */ jsx19("p", { className: "b316-muted", children: "On. You will be asked for a code when you sign in." }),
|
|
3668
|
+
/* @__PURE__ */ jsx19(
|
|
3318
3669
|
ConfirmButton,
|
|
3319
3670
|
{
|
|
3320
3671
|
className: "b316-button-quiet b316-danger",
|
|
@@ -3324,11 +3675,11 @@ function TwoFactorManager({
|
|
|
3324
3675
|
children: "Turn off"
|
|
3325
3676
|
}
|
|
3326
3677
|
)
|
|
3327
|
-
] }) : /* @__PURE__ */
|
|
3328
|
-
/* @__PURE__ */
|
|
3329
|
-
/* @__PURE__ */
|
|
3330
|
-
/* @__PURE__ */
|
|
3331
|
-
/* @__PURE__ */
|
|
3678
|
+
] }) : /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-off", children: [
|
|
3679
|
+
/* @__PURE__ */ jsx19("p", { className: "b316-muted", children: "Off. Turning it on means a code as well as your password, every time you sign in." }),
|
|
3680
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3681
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "b316-button", disabled: busy, onClick: begin, children: busy ? "Starting\u2026" : "Use an authenticator app" }),
|
|
3682
|
+
/* @__PURE__ */ jsx19(
|
|
3332
3683
|
"button",
|
|
3333
3684
|
{
|
|
3334
3685
|
type: "button",
|
|
@@ -3338,7 +3689,7 @@ function TwoFactorManager({
|
|
|
3338
3689
|
children: "Email me a code"
|
|
3339
3690
|
}
|
|
3340
3691
|
),
|
|
3341
|
-
allowSms ? /* @__PURE__ */
|
|
3692
|
+
allowSms ? /* @__PURE__ */ jsx19(
|
|
3342
3693
|
"button",
|
|
3343
3694
|
{
|
|
3344
3695
|
type: "button",
|
|
@@ -3354,14 +3705,14 @@ function TwoFactorManager({
|
|
|
3354
3705
|
}
|
|
3355
3706
|
|
|
3356
3707
|
// src/ForgotPassword.tsx
|
|
3357
|
-
import { useState as
|
|
3358
|
-
import { jsx as
|
|
3708
|
+
import { useState as useState16 } from "react";
|
|
3709
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3359
3710
|
function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
3360
3711
|
const { client } = useBase316();
|
|
3361
|
-
const [email, setEmail] =
|
|
3362
|
-
const [sent, setSent] =
|
|
3363
|
-
const [busy, setBusy] =
|
|
3364
|
-
const [error, setError] =
|
|
3712
|
+
const [email, setEmail] = useState16("");
|
|
3713
|
+
const [sent, setSent] = useState16(false);
|
|
3714
|
+
const [busy, setBusy] = useState16(false);
|
|
3715
|
+
const [error, setError] = useState16(null);
|
|
3365
3716
|
async function submit(event) {
|
|
3366
3717
|
event.preventDefault();
|
|
3367
3718
|
setBusy(true);
|
|
@@ -3377,22 +3728,22 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
|
3377
3728
|
}
|
|
3378
3729
|
}
|
|
3379
3730
|
if (sent) {
|
|
3380
|
-
return /* @__PURE__ */
|
|
3381
|
-
/* @__PURE__ */
|
|
3382
|
-
/* @__PURE__ */
|
|
3731
|
+
return /* @__PURE__ */ jsxs19("div", { className: cls("b316-card", className), style, children: [
|
|
3732
|
+
/* @__PURE__ */ jsx20("h3", { className: "b316-form-title", children: "Check your email" }),
|
|
3733
|
+
/* @__PURE__ */ jsxs19("p", { className: "b316-muted", children: [
|
|
3383
3734
|
"If there is an account for ",
|
|
3384
3735
|
email.trim(),
|
|
3385
3736
|
", a link to set a new password is on its way."
|
|
3386
3737
|
] }),
|
|
3387
|
-
signInUrl ? /* @__PURE__ */
|
|
3738
|
+
signInUrl ? /* @__PURE__ */ jsx20("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
|
|
3388
3739
|
] });
|
|
3389
3740
|
}
|
|
3390
|
-
return /* @__PURE__ */
|
|
3391
|
-
/* @__PURE__ */
|
|
3392
|
-
error ? /* @__PURE__ */
|
|
3393
|
-
/* @__PURE__ */
|
|
3394
|
-
/* @__PURE__ */
|
|
3395
|
-
/* @__PURE__ */
|
|
3741
|
+
return /* @__PURE__ */ jsxs19("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
|
|
3742
|
+
/* @__PURE__ */ jsx20("h3", { className: "b316-form-title", children: "Reset your password" }),
|
|
3743
|
+
error ? /* @__PURE__ */ jsx20("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3744
|
+
/* @__PURE__ */ jsxs19("div", { className: "b316-field", children: [
|
|
3745
|
+
/* @__PURE__ */ jsx20("label", { className: "b316-label", htmlFor: "b316-forgot-email", children: "Email" }),
|
|
3746
|
+
/* @__PURE__ */ jsx20(
|
|
3396
3747
|
"input",
|
|
3397
3748
|
{
|
|
3398
3749
|
id: "b316-forgot-email",
|
|
@@ -3405,14 +3756,14 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
|
3405
3756
|
}
|
|
3406
3757
|
)
|
|
3407
3758
|
] }),
|
|
3408
|
-
/* @__PURE__ */
|
|
3409
|
-
signInUrl ? /* @__PURE__ */
|
|
3759
|
+
/* @__PURE__ */ jsx20("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Send reset link" }),
|
|
3760
|
+
signInUrl ? /* @__PURE__ */ jsx20("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
|
|
3410
3761
|
] });
|
|
3411
3762
|
}
|
|
3412
3763
|
|
|
3413
3764
|
// src/ResetPassword.tsx
|
|
3414
|
-
import { useEffect as
|
|
3415
|
-
import { jsx as
|
|
3765
|
+
import { useEffect as useEffect13, useState as useState17 } from "react";
|
|
3766
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3416
3767
|
function ResetPassword({
|
|
3417
3768
|
token: supplied,
|
|
3418
3769
|
onReset,
|
|
@@ -3421,13 +3772,13 @@ function ResetPassword({
|
|
|
3421
3772
|
style
|
|
3422
3773
|
}) {
|
|
3423
3774
|
const { client } = useBase316();
|
|
3424
|
-
const [token, setToken] =
|
|
3425
|
-
const [password, setPassword] =
|
|
3426
|
-
const [confirmation, setConfirmation] =
|
|
3427
|
-
const [done, setDone] =
|
|
3428
|
-
const [busy, setBusy] =
|
|
3429
|
-
const [error, setError] =
|
|
3430
|
-
|
|
3775
|
+
const [token, setToken] = useState17(supplied ?? null);
|
|
3776
|
+
const [password, setPassword] = useState17("");
|
|
3777
|
+
const [confirmation, setConfirmation] = useState17("");
|
|
3778
|
+
const [done, setDone] = useState17(false);
|
|
3779
|
+
const [busy, setBusy] = useState17(false);
|
|
3780
|
+
const [error, setError] = useState17(null);
|
|
3781
|
+
useEffect13(() => {
|
|
3431
3782
|
if (supplied || typeof window === "undefined") {
|
|
3432
3783
|
return;
|
|
3433
3784
|
}
|
|
@@ -3462,24 +3813,24 @@ function ResetPassword({
|
|
|
3462
3813
|
}
|
|
3463
3814
|
}
|
|
3464
3815
|
if (done) {
|
|
3465
|
-
return /* @__PURE__ */
|
|
3466
|
-
/* @__PURE__ */
|
|
3467
|
-
/* @__PURE__ */
|
|
3468
|
-
signInUrl ? /* @__PURE__ */
|
|
3816
|
+
return /* @__PURE__ */ jsxs20("div", { className: cls("b316-card", className), style, children: [
|
|
3817
|
+
/* @__PURE__ */ jsx21("h3", { className: "b316-form-title", children: "Password changed" }),
|
|
3818
|
+
/* @__PURE__ */ jsx21("p", { className: "b316-muted", children: "You can sign in with your new password." }),
|
|
3819
|
+
signInUrl ? /* @__PURE__ */ jsx21("a", { className: "b316-button-link", href: signInUrl, children: "Sign in" }) : null
|
|
3469
3820
|
] });
|
|
3470
3821
|
}
|
|
3471
3822
|
if (!token) {
|
|
3472
|
-
return /* @__PURE__ */
|
|
3473
|
-
/* @__PURE__ */
|
|
3474
|
-
/* @__PURE__ */
|
|
3823
|
+
return /* @__PURE__ */ jsxs20("div", { className: cls("b316-card", className), style, children: [
|
|
3824
|
+
/* @__PURE__ */ jsx21("h3", { className: "b316-form-title", children: "Nothing to reset" }),
|
|
3825
|
+
/* @__PURE__ */ jsx21("p", { className: "b316-muted", children: "This page needs the link from your email. Request a new one if yours has expired." })
|
|
3475
3826
|
] });
|
|
3476
3827
|
}
|
|
3477
|
-
return /* @__PURE__ */
|
|
3478
|
-
/* @__PURE__ */
|
|
3479
|
-
error ? /* @__PURE__ */
|
|
3480
|
-
/* @__PURE__ */
|
|
3481
|
-
/* @__PURE__ */
|
|
3482
|
-
/* @__PURE__ */
|
|
3828
|
+
return /* @__PURE__ */ jsxs20("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
|
|
3829
|
+
/* @__PURE__ */ jsx21("h3", { className: "b316-form-title", children: "Choose a new password" }),
|
|
3830
|
+
error ? /* @__PURE__ */ jsx21("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3831
|
+
/* @__PURE__ */ jsxs20("div", { className: "b316-field", children: [
|
|
3832
|
+
/* @__PURE__ */ jsx21("label", { className: "b316-label", htmlFor: "b316-reset-password", children: "New password" }),
|
|
3833
|
+
/* @__PURE__ */ jsx21(
|
|
3483
3834
|
"input",
|
|
3484
3835
|
{
|
|
3485
3836
|
id: "b316-reset-password",
|
|
@@ -3492,9 +3843,9 @@ function ResetPassword({
|
|
|
3492
3843
|
}
|
|
3493
3844
|
)
|
|
3494
3845
|
] }),
|
|
3495
|
-
/* @__PURE__ */
|
|
3496
|
-
/* @__PURE__ */
|
|
3497
|
-
/* @__PURE__ */
|
|
3846
|
+
/* @__PURE__ */ jsxs20("div", { className: "b316-field", children: [
|
|
3847
|
+
/* @__PURE__ */ jsx21("label", { className: "b316-label", htmlFor: "b316-reset-confirm", children: "Repeat it" }),
|
|
3848
|
+
/* @__PURE__ */ jsx21(
|
|
3498
3849
|
"input",
|
|
3499
3850
|
{
|
|
3500
3851
|
id: "b316-reset-confirm",
|
|
@@ -3507,13 +3858,13 @@ function ResetPassword({
|
|
|
3507
3858
|
}
|
|
3508
3859
|
)
|
|
3509
3860
|
] }),
|
|
3510
|
-
/* @__PURE__ */
|
|
3861
|
+
/* @__PURE__ */ jsx21("button", { type: "submit", className: "b316-button", disabled: busy || !password, children: busy ? "Saving\u2026" : "Set password" })
|
|
3511
3862
|
] });
|
|
3512
3863
|
}
|
|
3513
3864
|
|
|
3514
3865
|
// src/VerifyEmail.tsx
|
|
3515
|
-
import { useEffect as
|
|
3516
|
-
import { Fragment as
|
|
3866
|
+
import { useEffect as useEffect14, useRef as useRef4, useState as useState18 } from "react";
|
|
3867
|
+
import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3517
3868
|
function VerifyEmail({
|
|
3518
3869
|
token: supplied,
|
|
3519
3870
|
onVerified,
|
|
@@ -3522,9 +3873,9 @@ function VerifyEmail({
|
|
|
3522
3873
|
style
|
|
3523
3874
|
}) {
|
|
3524
3875
|
const { client } = useBase316();
|
|
3525
|
-
const [state, setState] =
|
|
3876
|
+
const [state, setState] = useState18("waiting");
|
|
3526
3877
|
const spent = useRef4(false);
|
|
3527
|
-
|
|
3878
|
+
useEffect14(() => {
|
|
3528
3879
|
if (spent.current) {
|
|
3529
3880
|
return;
|
|
3530
3881
|
}
|
|
@@ -3550,22 +3901,22 @@ function VerifyEmail({
|
|
|
3550
3901
|
setState("failed");
|
|
3551
3902
|
});
|
|
3552
3903
|
}, [client, supplied, onVerified]);
|
|
3553
|
-
return /* @__PURE__ */
|
|
3554
|
-
/* @__PURE__ */
|
|
3555
|
-
/* @__PURE__ */
|
|
3556
|
-
continueUrl ? /* @__PURE__ */
|
|
3557
|
-
] }) : state === "failed" ? /* @__PURE__ */
|
|
3558
|
-
/* @__PURE__ */
|
|
3559
|
-
/* @__PURE__ */
|
|
3560
|
-
] }) : state === "missing" ? /* @__PURE__ */
|
|
3561
|
-
/* @__PURE__ */
|
|
3562
|
-
/* @__PURE__ */
|
|
3563
|
-
] }) : /* @__PURE__ */
|
|
3904
|
+
return /* @__PURE__ */ jsx22("div", { className: cls("b316-card", className), style, children: state === "verified" ? /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
3905
|
+
/* @__PURE__ */ jsx22("h3", { className: "b316-form-title", children: "Email confirmed" }),
|
|
3906
|
+
/* @__PURE__ */ jsx22("p", { className: "b316-muted", children: "Thanks \u2014 your address is verified." }),
|
|
3907
|
+
continueUrl ? /* @__PURE__ */ jsx22("a", { className: "b316-button-link", href: continueUrl, children: "Continue" }) : null
|
|
3908
|
+
] }) : state === "failed" ? /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
3909
|
+
/* @__PURE__ */ jsx22("h3", { className: "b316-form-title", children: "That link did not work" }),
|
|
3910
|
+
/* @__PURE__ */ jsx22("p", { className: "b316-muted", children: "It may have expired or already been used. Ask for a new one and try again." })
|
|
3911
|
+
] }) : state === "missing" ? /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
3912
|
+
/* @__PURE__ */ jsx22("h3", { className: "b316-form-title", children: "Nothing to confirm" }),
|
|
3913
|
+
/* @__PURE__ */ jsx22("p", { className: "b316-muted", children: "This page needs the link from your email." })
|
|
3914
|
+
] }) : /* @__PURE__ */ jsx22("p", { className: "b316-muted", children: "Confirming your email\u2026" }) });
|
|
3564
3915
|
}
|
|
3565
3916
|
|
|
3566
3917
|
// src/TeamMembers.tsx
|
|
3567
|
-
import { useCallback as useCallback7, useEffect as
|
|
3568
|
-
import { Fragment as
|
|
3918
|
+
import { useCallback as useCallback7, useEffect as useEffect15, useState as useState19 } from "react";
|
|
3919
|
+
import { Fragment as Fragment8, jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3569
3920
|
function TeamMembers({
|
|
3570
3921
|
organizationId,
|
|
3571
3922
|
onInvited,
|
|
@@ -3575,13 +3926,13 @@ function TeamMembers({
|
|
|
3575
3926
|
style
|
|
3576
3927
|
}) {
|
|
3577
3928
|
const { client, token, session } = useBase316();
|
|
3578
|
-
const [teams, setTeams] =
|
|
3579
|
-
const [members, setMembers] =
|
|
3580
|
-
const [invitations, setInvitations] =
|
|
3581
|
-
const [email, setEmail] =
|
|
3582
|
-
const [busy, setBusy] =
|
|
3583
|
-
const [error, setError] =
|
|
3584
|
-
const [copied, setCopied] =
|
|
3929
|
+
const [teams, setTeams] = useState19(null);
|
|
3930
|
+
const [members, setMembers] = useState19(null);
|
|
3931
|
+
const [invitations, setInvitations] = useState19(null);
|
|
3932
|
+
const [email, setEmail] = useState19("");
|
|
3933
|
+
const [busy, setBusy] = useState19(false);
|
|
3934
|
+
const [error, setError] = useState19(null);
|
|
3935
|
+
const [copied, setCopied] = useState19(null);
|
|
3585
3936
|
const chosen = organizationId ?? (teams?.length === 1 ? teams[0].id : null);
|
|
3586
3937
|
const team = teams?.find((candidate) => candidate.id === chosen) ?? null;
|
|
3587
3938
|
const load = useCallback7(() => {
|
|
@@ -3592,8 +3943,8 @@ function TeamMembers({
|
|
|
3592
3943
|
(cause) => setError(cause instanceof Error ? cause.message : "Could not load your teams.")
|
|
3593
3944
|
);
|
|
3594
3945
|
}, [client, token]);
|
|
3595
|
-
|
|
3596
|
-
|
|
3946
|
+
useEffect15(load, [load]);
|
|
3947
|
+
useEffect15(() => {
|
|
3597
3948
|
if (!token || !chosen) {
|
|
3598
3949
|
return;
|
|
3599
3950
|
}
|
|
@@ -3624,10 +3975,10 @@ function TeamMembers({
|
|
|
3624
3975
|
return null;
|
|
3625
3976
|
}
|
|
3626
3977
|
if (!teams) {
|
|
3627
|
-
return /* @__PURE__ */
|
|
3978
|
+
return /* @__PURE__ */ jsx23("div", { className: cls("b316-card", className), style, children: error ?? "Loading\u2026" });
|
|
3628
3979
|
}
|
|
3629
3980
|
if (!chosen) {
|
|
3630
|
-
return /* @__PURE__ */
|
|
3981
|
+
return /* @__PURE__ */ jsx23("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." });
|
|
3631
3982
|
}
|
|
3632
3983
|
const canManage = invitations !== null;
|
|
3633
3984
|
async function invite(event) {
|
|
@@ -3677,30 +4028,30 @@ function TeamMembers({
|
|
|
3677
4028
|
setError(cause instanceof Error ? cause.message : "That invitation could not be withdrawn.");
|
|
3678
4029
|
}
|
|
3679
4030
|
}
|
|
3680
|
-
return /* @__PURE__ */
|
|
3681
|
-
/* @__PURE__ */
|
|
4031
|
+
return /* @__PURE__ */ jsxs22("div", { className: cls("b316-card b316-team", className), style, children: [
|
|
4032
|
+
/* @__PURE__ */ jsx23("h3", { className: "b316-team-title", children: team?.name ?? "Team" }),
|
|
3682
4033
|
team?.inherited ? (
|
|
3683
4034
|
// Not a member of this team, so not in the list below and with nothing
|
|
3684
4035
|
// to leave: access comes from the team that manages it, and ends there.
|
|
3685
|
-
/* @__PURE__ */
|
|
4036
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-muted", children: [
|
|
3686
4037
|
"You have access through",
|
|
3687
4038
|
" ",
|
|
3688
4039
|
teams.find((candidate) => candidate.id === team.via)?.name ?? "the organization that manages this team",
|
|
3689
4040
|
"."
|
|
3690
4041
|
] })
|
|
3691
4042
|
) : null,
|
|
3692
|
-
error ? /* @__PURE__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
3696
|
-
/* @__PURE__ */
|
|
4043
|
+
error ? /* @__PURE__ */ jsx23("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
4044
|
+
/* @__PURE__ */ jsx23("ul", { className: "b316-team-list", children: (members ?? []).map((member) => /* @__PURE__ */ jsxs22("li", { className: "b316-team-member", children: [
|
|
4045
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
4046
|
+
/* @__PURE__ */ jsx23("div", { children: member.user.name ?? member.user.email ?? "Someone" }),
|
|
4047
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-muted", children: [
|
|
3697
4048
|
member.user.email,
|
|
3698
4049
|
member.user.id === session?.userId ? " \xB7 you" : ""
|
|
3699
4050
|
] })
|
|
3700
4051
|
] }),
|
|
3701
|
-
/* @__PURE__ */
|
|
3702
|
-
/* @__PURE__ */
|
|
3703
|
-
canManage || member.user.id === session?.userId ? /* @__PURE__ */
|
|
4052
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-team-member-side", children: [
|
|
4053
|
+
/* @__PURE__ */ jsx23("span", { className: "b316-chip", children: member.role.name }),
|
|
4054
|
+
canManage || member.user.id === session?.userId ? /* @__PURE__ */ jsx23(
|
|
3704
4055
|
ConfirmButton,
|
|
3705
4056
|
{
|
|
3706
4057
|
className: "b316-button-quiet b316-danger",
|
|
@@ -3712,19 +4063,19 @@ function TeamMembers({
|
|
|
3712
4063
|
) : null
|
|
3713
4064
|
] })
|
|
3714
4065
|
] }, member.id)) }),
|
|
3715
|
-
canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */
|
|
3716
|
-
/* @__PURE__ */
|
|
3717
|
-
/* @__PURE__ */
|
|
3718
|
-
/* @__PURE__ */
|
|
3719
|
-
/* @__PURE__ */
|
|
3720
|
-
/* @__PURE__ */
|
|
4066
|
+
canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */ jsxs22(Fragment8, { children: [
|
|
4067
|
+
/* @__PURE__ */ jsx23("h4", { className: "b316-team-subtitle", children: "Invited" }),
|
|
4068
|
+
/* @__PURE__ */ jsx23("ul", { className: "b316-team-list", children: (invitations ?? []).map((invitation) => /* @__PURE__ */ jsxs22("li", { className: "b316-team-member", children: [
|
|
4069
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
4070
|
+
/* @__PURE__ */ jsx23("div", { children: invitation.email }),
|
|
4071
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-muted", children: [
|
|
3721
4072
|
invitation.role.name,
|
|
3722
4073
|
" \xB7 expires",
|
|
3723
4074
|
" ",
|
|
3724
4075
|
new Date(invitation.expiresAt).toLocaleDateString()
|
|
3725
4076
|
] })
|
|
3726
4077
|
] }),
|
|
3727
|
-
/* @__PURE__ */
|
|
4078
|
+
/* @__PURE__ */ jsx23(
|
|
3728
4079
|
"button",
|
|
3729
4080
|
{
|
|
3730
4081
|
type: "button",
|
|
@@ -3735,10 +4086,10 @@ function TeamMembers({
|
|
|
3735
4086
|
)
|
|
3736
4087
|
] }, invitation.id)) })
|
|
3737
4088
|
] }) : null,
|
|
3738
|
-
canManage ? /* @__PURE__ */
|
|
3739
|
-
/* @__PURE__ */
|
|
3740
|
-
/* @__PURE__ */
|
|
3741
|
-
/* @__PURE__ */
|
|
4089
|
+
canManage ? /* @__PURE__ */ jsxs22("form", { className: "b316-team-invite", onSubmit: invite, children: [
|
|
4090
|
+
/* @__PURE__ */ jsx23("label", { className: "b316-label", htmlFor: "b316-invite-email", children: "Invite by email" }),
|
|
4091
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-team-invite-row", children: [
|
|
4092
|
+
/* @__PURE__ */ jsx23(
|
|
3742
4093
|
"input",
|
|
3743
4094
|
{
|
|
3744
4095
|
id: "b316-invite-email",
|
|
@@ -3750,19 +4101,19 @@ function TeamMembers({
|
|
|
3750
4101
|
onChange: (event) => setEmail(event.target.value)
|
|
3751
4102
|
}
|
|
3752
4103
|
),
|
|
3753
|
-
/* @__PURE__ */
|
|
4104
|
+
/* @__PURE__ */ jsx23("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Invite" })
|
|
3754
4105
|
] })
|
|
3755
4106
|
] }) : null,
|
|
3756
|
-
copied ? /* @__PURE__ */
|
|
3757
|
-
/* @__PURE__ */
|
|
3758
|
-
/* @__PURE__ */
|
|
4107
|
+
copied ? /* @__PURE__ */ jsxs22("div", { className: "b316-team-link", children: [
|
|
4108
|
+
/* @__PURE__ */ jsx23("div", { className: "b316-muted", children: "Send them this link. It is shown once and cannot be fetched again." }),
|
|
4109
|
+
/* @__PURE__ */ jsx23("code", { children: copied })
|
|
3759
4110
|
] }) : null
|
|
3760
4111
|
] });
|
|
3761
4112
|
}
|
|
3762
4113
|
|
|
3763
4114
|
// src/AcceptInvitation.tsx
|
|
3764
|
-
import { useEffect as
|
|
3765
|
-
import { Fragment as
|
|
4115
|
+
import { useEffect as useEffect16, useState as useState20 } from "react";
|
|
4116
|
+
import { Fragment as Fragment9, jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3766
4117
|
function signUpUrlWithInvitation(url, token) {
|
|
3767
4118
|
const [beforeHash, ...hash] = url.split("#");
|
|
3768
4119
|
const base = beforeHash ?? "";
|
|
@@ -3781,18 +4132,18 @@ function AcceptInvitation({
|
|
|
3781
4132
|
style
|
|
3782
4133
|
}) {
|
|
3783
4134
|
const { client, token: session, session: user } = useBase316();
|
|
3784
|
-
const [invitationToken, setInvitationToken] =
|
|
3785
|
-
const [preview, setPreview] =
|
|
3786
|
-
const [state, setState] =
|
|
3787
|
-
const [error, setError] =
|
|
3788
|
-
const [busy, setBusy] =
|
|
3789
|
-
|
|
4135
|
+
const [invitationToken, setInvitationToken] = useState20(supplied ?? null);
|
|
4136
|
+
const [preview, setPreview] = useState20(null);
|
|
4137
|
+
const [state, setState] = useState20("loading");
|
|
4138
|
+
const [error, setError] = useState20(null);
|
|
4139
|
+
const [busy, setBusy] = useState20(false);
|
|
4140
|
+
useEffect16(() => {
|
|
3790
4141
|
if (supplied || typeof window === "undefined") {
|
|
3791
4142
|
return;
|
|
3792
4143
|
}
|
|
3793
4144
|
setInvitationToken(new URL(window.location.href).searchParams.get("invitation"));
|
|
3794
4145
|
}, [supplied]);
|
|
3795
|
-
|
|
4146
|
+
useEffect16(() => {
|
|
3796
4147
|
if (!invitationToken) {
|
|
3797
4148
|
setState(supplied === void 0 ? "loading" : "invalid");
|
|
3798
4149
|
return;
|
|
@@ -3829,42 +4180,42 @@ function AcceptInvitation({
|
|
|
3829
4180
|
}
|
|
3830
4181
|
}
|
|
3831
4182
|
if (state === "loading") {
|
|
3832
|
-
return /* @__PURE__ */
|
|
4183
|
+
return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
3833
4184
|
}
|
|
3834
4185
|
if (state === "invalid") {
|
|
3835
|
-
return /* @__PURE__ */
|
|
3836
|
-
/* @__PURE__ */
|
|
3837
|
-
/* @__PURE__ */
|
|
4186
|
+
return /* @__PURE__ */ jsxs23("div", { className: cls("b316-card", className), style, children: [
|
|
4187
|
+
/* @__PURE__ */ jsx24("h3", { className: "b316-form-title", children: "That invitation is no longer valid" }),
|
|
4188
|
+
/* @__PURE__ */ jsx24("p", { className: "b316-muted", children: "It may have expired, been withdrawn, or already been used. Ask for a new one." })
|
|
3838
4189
|
] });
|
|
3839
4190
|
}
|
|
3840
4191
|
if (state === "accepted") {
|
|
3841
|
-
return /* @__PURE__ */
|
|
4192
|
+
return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsxs23("h3", { className: "b316-form-title", children: [
|
|
3842
4193
|
"You have joined ",
|
|
3843
4194
|
preview?.organizationName
|
|
3844
4195
|
] }) });
|
|
3845
4196
|
}
|
|
3846
4197
|
const matches = !user || (user.user.email ?? "").toLowerCase() === preview?.email.toLowerCase();
|
|
3847
|
-
return /* @__PURE__ */
|
|
3848
|
-
/* @__PURE__ */
|
|
4198
|
+
return /* @__PURE__ */ jsxs23("div", { className: cls("b316-card b316-invitation", className), style, children: [
|
|
4199
|
+
/* @__PURE__ */ jsxs23("h3", { className: "b316-form-title", children: [
|
|
3849
4200
|
"Join ",
|
|
3850
4201
|
preview?.organizationName
|
|
3851
4202
|
] }),
|
|
3852
|
-
/* @__PURE__ */
|
|
4203
|
+
/* @__PURE__ */ jsxs23("p", { className: "b316-muted", children: [
|
|
3853
4204
|
"Invited as ",
|
|
3854
4205
|
preview?.email,
|
|
3855
4206
|
" \xB7 ",
|
|
3856
4207
|
preview?.roleName
|
|
3857
4208
|
] }),
|
|
3858
|
-
error ? /* @__PURE__ */
|
|
3859
|
-
!session ? /* @__PURE__ */
|
|
3860
|
-
/* @__PURE__ */
|
|
4209
|
+
error ? /* @__PURE__ */ jsx24("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
4210
|
+
!session ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
|
|
4211
|
+
/* @__PURE__ */ jsxs23("p", { children: [
|
|
3861
4212
|
"Sign in as ",
|
|
3862
4213
|
preview?.email,
|
|
3863
4214
|
" to accept."
|
|
3864
4215
|
] }),
|
|
3865
|
-
/* @__PURE__ */
|
|
3866
|
-
signInUrl ? /* @__PURE__ */
|
|
3867
|
-
signUpUrl ? /* @__PURE__ */
|
|
4216
|
+
/* @__PURE__ */ jsxs23("div", { className: "b316-invitation-actions", children: [
|
|
4217
|
+
signInUrl ? /* @__PURE__ */ jsx24("a", { className: "b316-button", href: signInUrl, children: "Sign in" }) : null,
|
|
4218
|
+
signUpUrl ? /* @__PURE__ */ jsx24(
|
|
3868
4219
|
"a",
|
|
3869
4220
|
{
|
|
3870
4221
|
className: "b316-button-link",
|
|
@@ -3877,20 +4228,20 @@ function AcceptInvitation({
|
|
|
3877
4228
|
// Said before they press anything. The server refuses this, but
|
|
3878
4229
|
// finding out after a click reads as a broken invitation rather than
|
|
3879
4230
|
// as being signed in as the wrong person.
|
|
3880
|
-
/* @__PURE__ */
|
|
4231
|
+
/* @__PURE__ */ jsxs23("p", { children: [
|
|
3881
4232
|
"You are signed in as ",
|
|
3882
4233
|
user?.user.email,
|
|
3883
4234
|
". This invitation was sent to ",
|
|
3884
4235
|
preview?.email,
|
|
3885
4236
|
" \u2014 sign in as that address to accept it."
|
|
3886
4237
|
] })
|
|
3887
|
-
) : /* @__PURE__ */
|
|
4238
|
+
) : /* @__PURE__ */ jsx24("button", { type: "button", className: "b316-button", disabled: busy, onClick: accept, children: busy ? "Joining\u2026" : `Join ${preview?.organizationName}` })
|
|
3888
4239
|
] });
|
|
3889
4240
|
}
|
|
3890
4241
|
|
|
3891
4242
|
// src/PayInvoice.tsx
|
|
3892
|
-
import { useEffect as
|
|
3893
|
-
import { jsx as
|
|
4243
|
+
import { useEffect as useEffect17, useRef as useRef5, useState as useState21 } from "react";
|
|
4244
|
+
import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3894
4245
|
var STRIPE_SRC = "https://js.stripe.com/v3/";
|
|
3895
4246
|
function loadStripeScript() {
|
|
3896
4247
|
if (typeof window === "undefined") {
|
|
@@ -3925,11 +4276,11 @@ function PayInvoice({
|
|
|
3925
4276
|
const mountRef = useRef5(null);
|
|
3926
4277
|
const stripeRef = useRef5(null);
|
|
3927
4278
|
const elementsRef = useRef5(null);
|
|
3928
|
-
const [ready, setReady] =
|
|
3929
|
-
const [paying, setPaying] =
|
|
3930
|
-
const [done, setDone] =
|
|
3931
|
-
const [error, setError] =
|
|
3932
|
-
|
|
4279
|
+
const [ready, setReady] = useState21(false);
|
|
4280
|
+
const [paying, setPaying] = useState21(false);
|
|
4281
|
+
const [done, setDone] = useState21(false);
|
|
4282
|
+
const [error, setError] = useState21(null);
|
|
4283
|
+
useEffect17(() => {
|
|
3933
4284
|
let cancelled = false;
|
|
3934
4285
|
async function start() {
|
|
3935
4286
|
const base = `${client.baseUrl}/pay/${encodeURIComponent(environmentId)}/${encodeURIComponent(token)}`;
|
|
@@ -3982,17 +4333,17 @@ function PayInvoice({
|
|
|
3982
4333
|
onPaid?.();
|
|
3983
4334
|
};
|
|
3984
4335
|
if (done) {
|
|
3985
|
-
return /* @__PURE__ */
|
|
4336
|
+
return /* @__PURE__ */ jsx25("div", { className: cls("b316-pay", className), style, children: /* @__PURE__ */ jsx25("p", { className: "b316-pay__done", children: "Paid \u2014 thank you." }) });
|
|
3986
4337
|
}
|
|
3987
|
-
return /* @__PURE__ */
|
|
3988
|
-
error ? /* @__PURE__ */
|
|
3989
|
-
/* @__PURE__ */
|
|
3990
|
-
/* @__PURE__ */
|
|
4338
|
+
return /* @__PURE__ */ jsxs24("form", { className: cls("b316-pay", className), style, onSubmit: submit, children: [
|
|
4339
|
+
error ? /* @__PURE__ */ jsx25("p", { className: "b316-pay__error", role: "alert", children: error }) : null,
|
|
4340
|
+
/* @__PURE__ */ jsx25("div", { ref: mountRef, className: "b316-pay__element" }),
|
|
4341
|
+
/* @__PURE__ */ jsx25("button", { className: "b316-pay__submit", type: "submit", disabled: !ready || paying, children: paying ? "Paying\u2026" : "Pay" })
|
|
3991
4342
|
] });
|
|
3992
4343
|
}
|
|
3993
4344
|
|
|
3994
4345
|
// src/usePaymentLink.ts
|
|
3995
|
-
import { useEffect as
|
|
4346
|
+
import { useEffect as useEffect18, useRef as useRef6, useState as useState22 } from "react";
|
|
3996
4347
|
function usePaymentLink({
|
|
3997
4348
|
token,
|
|
3998
4349
|
environmentId,
|
|
@@ -4000,10 +4351,10 @@ function usePaymentLink({
|
|
|
4000
4351
|
onPaid
|
|
4001
4352
|
}) {
|
|
4002
4353
|
const { client } = useBase316();
|
|
4003
|
-
const [status2, setStatus] =
|
|
4354
|
+
const [status2, setStatus] = useState22({ state: "loading" });
|
|
4004
4355
|
const onPaidRef = useRef6(onPaid);
|
|
4005
4356
|
onPaidRef.current = onPaid;
|
|
4006
|
-
|
|
4357
|
+
useEffect18(() => {
|
|
4007
4358
|
let stopped = false;
|
|
4008
4359
|
let timer;
|
|
4009
4360
|
const statusUrl = `${client.baseUrl}/pay/${encodeURIComponent(environmentId)}/${encodeURIComponent(token)}/status`;
|
|
@@ -4052,23 +4403,23 @@ function usePaymentLink({
|
|
|
4052
4403
|
}
|
|
4053
4404
|
|
|
4054
4405
|
// src/PricingTable.tsx
|
|
4055
|
-
import { useState as
|
|
4406
|
+
import { useState as useState24 } from "react";
|
|
4056
4407
|
|
|
4057
4408
|
// src/usePlans.ts
|
|
4058
|
-
import { useCallback as useCallback8, useEffect as
|
|
4409
|
+
import { useCallback as useCallback8, useEffect as useEffect19, useState as useState23 } from "react";
|
|
4059
4410
|
var CHECKOUT_STATUSES = /* @__PURE__ */ new Set([402, 409]);
|
|
4060
4411
|
function usePlans(options = {}) {
|
|
4061
4412
|
const { client, token } = useBase316();
|
|
4062
|
-
const [plans, setPlans] =
|
|
4063
|
-
const [error, setError] =
|
|
4064
|
-
const [busyPlanVersionId, setBusy] =
|
|
4065
|
-
const [lastError, setLastError] =
|
|
4066
|
-
const [ownPlanVersionId, setOwnPlanVersionId] =
|
|
4067
|
-
const [managedBy, setManagedBy] =
|
|
4068
|
-
const [reloadCount, setReloadCount] =
|
|
4413
|
+
const [plans, setPlans] = useState23(null);
|
|
4414
|
+
const [error, setError] = useState23(false);
|
|
4415
|
+
const [busyPlanVersionId, setBusy] = useState23(null);
|
|
4416
|
+
const [lastError, setLastError] = useState23(null);
|
|
4417
|
+
const [ownPlanVersionId, setOwnPlanVersionId] = useState23(null);
|
|
4418
|
+
const [managedBy, setManagedBy] = useState23(null);
|
|
4419
|
+
const [reloadCount, setReloadCount] = useState23(0);
|
|
4069
4420
|
const supplied = options.currentPlanVersionId;
|
|
4070
4421
|
const discover = supplied === void 0;
|
|
4071
|
-
|
|
4422
|
+
useEffect19(() => {
|
|
4072
4423
|
let cancelled = false;
|
|
4073
4424
|
client.billing.plans().then((result) => {
|
|
4074
4425
|
if (!cancelled) {
|
|
@@ -4084,7 +4435,7 @@ function usePlans(options = {}) {
|
|
|
4084
4435
|
cancelled = true;
|
|
4085
4436
|
};
|
|
4086
4437
|
}, [client, reloadCount]);
|
|
4087
|
-
|
|
4438
|
+
useEffect19(() => {
|
|
4088
4439
|
if (!token) {
|
|
4089
4440
|
return;
|
|
4090
4441
|
}
|
|
@@ -4173,7 +4524,7 @@ function usePlans(options = {}) {
|
|
|
4173
4524
|
}
|
|
4174
4525
|
|
|
4175
4526
|
// src/PricingTable.tsx
|
|
4176
|
-
import { jsx as
|
|
4527
|
+
import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
4177
4528
|
function formatAmount(amount, currency) {
|
|
4178
4529
|
if (amount === null) return "Free";
|
|
4179
4530
|
const value = Number(amount);
|
|
@@ -4222,7 +4573,7 @@ function PricingTable({
|
|
|
4222
4573
|
managedBy,
|
|
4223
4574
|
selectPlan
|
|
4224
4575
|
} = usePlans({ currentPlanVersionId });
|
|
4225
|
-
const [scheduled, setScheduled] =
|
|
4576
|
+
const [scheduled, setScheduled] = useState24(null);
|
|
4226
4577
|
async function choose(plan) {
|
|
4227
4578
|
if (onSelectPlan) {
|
|
4228
4579
|
await onSelectPlan(plan.planVersionId, plan);
|
|
@@ -4239,50 +4590,50 @@ function PricingTable({
|
|
|
4239
4590
|
}
|
|
4240
4591
|
}
|
|
4241
4592
|
if (error) {
|
|
4242
|
-
return /* @__PURE__ */
|
|
4593
|
+
return /* @__PURE__ */ jsx26("div", { className: cls("b316-card", className), style, children: "Plans are unavailable right now." });
|
|
4243
4594
|
}
|
|
4244
4595
|
if (!plans) {
|
|
4245
|
-
return /* @__PURE__ */
|
|
4596
|
+
return /* @__PURE__ */ jsx26("div", { className: cls("b316-card", className), style, children: "Loading plans\u2026" });
|
|
4246
4597
|
}
|
|
4247
4598
|
if (plans.length === 0) {
|
|
4248
|
-
return /* @__PURE__ */
|
|
4599
|
+
return /* @__PURE__ */ jsx26("div", { className: cls("b316-card", className), style, children: "No plans are published yet." });
|
|
4249
4600
|
}
|
|
4250
4601
|
const anyTrial = plans.some((plan) => Boolean(plan.trialDays));
|
|
4251
4602
|
const anyDescription = plans.some((plan) => Boolean(plan.description));
|
|
4252
4603
|
const anyFeatured = plans.some((plan) => plan.key === featuredPlanKey);
|
|
4253
|
-
return /* @__PURE__ */
|
|
4604
|
+
return /* @__PURE__ */ jsxs25("div", { className: cls("b316-plans", className), style, children: [
|
|
4254
4605
|
managedBy ? (
|
|
4255
4606
|
// A client company's plan comes from the firm that runs it. The table
|
|
4256
4607
|
// still shows what is on offer, with the current plan marked, but
|
|
4257
4608
|
// nothing here can be bought: it would grant this account nothing.
|
|
4258
|
-
/* @__PURE__ */
|
|
4609
|
+
/* @__PURE__ */ jsxs25("div", { className: "b316-plans-managed b316-muted", children: [
|
|
4259
4610
|
"Your plan is provided by ",
|
|
4260
4611
|
managedBy.name ?? "the organization that manages your account",
|
|
4261
4612
|
". Ask them to change it."
|
|
4262
4613
|
] })
|
|
4263
|
-
) : lastError ? /* @__PURE__ */
|
|
4614
|
+
) : lastError ? /* @__PURE__ */ jsx26("div", { className: "b316-plans-error", role: "alert", children: lastError }) : scheduled ? /* @__PURE__ */ jsx26("div", { className: "b316-plans-managed b316-muted", role: "status", children: scheduled }) : null,
|
|
4264
4615
|
plans.map((plan) => {
|
|
4265
4616
|
const base = plan.prices.find((price) => price.featureId === null) ?? plan.prices[0];
|
|
4266
4617
|
const isCurrent = current === plan.planVersionId;
|
|
4267
4618
|
const featured = featuredPlanKey === plan.key;
|
|
4268
|
-
return /* @__PURE__ */
|
|
4619
|
+
return /* @__PURE__ */ jsxs25(
|
|
4269
4620
|
"div",
|
|
4270
4621
|
{
|
|
4271
4622
|
className: featured ? "b316-card b316-plan b316-plan-featured" : "b316-card b316-plan",
|
|
4272
4623
|
children: [
|
|
4273
|
-
/* @__PURE__ */
|
|
4274
|
-
anyFeatured ? /* @__PURE__ */
|
|
4275
|
-
/* @__PURE__ */
|
|
4276
|
-
anyDescription ? /* @__PURE__ */
|
|
4624
|
+
/* @__PURE__ */ jsxs25("div", { className: "b316-plan-head", children: [
|
|
4625
|
+
anyFeatured ? /* @__PURE__ */ jsx26("div", { className: featured ? "b316-plan-badge" : "b316-plan-badge-spacer", children: featured ? "Recommended" : "\xA0" }) : null,
|
|
4626
|
+
/* @__PURE__ */ jsx26("div", { className: "b316-plan-name", children: plan.name }),
|
|
4627
|
+
anyDescription ? /* @__PURE__ */ jsx26("div", { className: "b316-plan-desc", children: plan.description ?? "\xA0" }) : null
|
|
4277
4628
|
] }),
|
|
4278
|
-
/* @__PURE__ */
|
|
4279
|
-
/* @__PURE__ */
|
|
4280
|
-
/* @__PURE__ */
|
|
4281
|
-
anyTrial ? /* @__PURE__ */
|
|
4629
|
+
/* @__PURE__ */ jsxs25("div", { className: "b316-plan-pricing", children: [
|
|
4630
|
+
/* @__PURE__ */ jsx26("div", { className: "b316-plan-price", children: formatAmount(base?.amount ?? null, plan.currency) }),
|
|
4631
|
+
/* @__PURE__ */ jsx26("div", { className: "b316-plan-cadence", children: cadence(plan, base?.amount ?? null) }),
|
|
4632
|
+
anyTrial ? /* @__PURE__ */ jsx26("div", { className: "b316-plan-trial", children: describeTrial(plan, plans) ?? "\xA0" }) : null
|
|
4282
4633
|
] }),
|
|
4283
|
-
/* @__PURE__ */
|
|
4284
|
-
/* @__PURE__ */
|
|
4285
|
-
/* @__PURE__ */
|
|
4634
|
+
/* @__PURE__ */ jsx26("ul", { className: "b316-plan-features", children: plan.entitlements.filter((entitlement) => entitlement.enabled).map((entitlement) => /* @__PURE__ */ jsxs25("li", { className: "b316-plan-feature", children: [
|
|
4635
|
+
/* @__PURE__ */ jsx26("span", { children: entitlement.featureName }),
|
|
4636
|
+
/* @__PURE__ */ jsx26("span", { className: "b316-plan-feature-value", children: entitlement.limit === null ? "Unlimited" : (
|
|
4286
4637
|
// A usage price on the feature makes the limit an
|
|
4287
4638
|
// allowance billed past, not a ceiling — the same
|
|
4288
4639
|
// rule `check()` applies (any non-FLAT price).
|
|
@@ -4291,7 +4642,7 @@ function PricingTable({
|
|
|
4291
4642
|
) ? `${entitlement.limit} included` : entitlement.limit
|
|
4292
4643
|
) })
|
|
4293
4644
|
] }, entitlement.featureId)) }),
|
|
4294
|
-
/* @__PURE__ */
|
|
4645
|
+
/* @__PURE__ */ jsx26("div", { className: "b316-plan-action", children: /* @__PURE__ */ jsx26(
|
|
4295
4646
|
"button",
|
|
4296
4647
|
{
|
|
4297
4648
|
type: "button",
|
|
@@ -4313,14 +4664,14 @@ function PricingTable({
|
|
|
4313
4664
|
|
|
4314
4665
|
// src/DataTable.tsx
|
|
4315
4666
|
import { specFor as specFor3 } from "@base316/sdk";
|
|
4316
|
-
import { useState as
|
|
4667
|
+
import { useState as useState28 } from "react";
|
|
4317
4668
|
|
|
4318
4669
|
// src/fields.tsx
|
|
4319
4670
|
import {
|
|
4320
4671
|
formatAddress,
|
|
4321
4672
|
specFor
|
|
4322
4673
|
} from "@base316/sdk";
|
|
4323
|
-
import { jsx as
|
|
4674
|
+
import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4324
4675
|
function formatNumber(value, fraction = 0) {
|
|
4325
4676
|
const number = Number(value);
|
|
4326
4677
|
return Number.isFinite(number) ? new Intl.NumberFormat(void 0, {
|
|
@@ -4342,10 +4693,10 @@ function formatDuration(value) {
|
|
|
4342
4693
|
}
|
|
4343
4694
|
function FieldCell({ value, field, related }) {
|
|
4344
4695
|
if (field.type === "RELATION") {
|
|
4345
|
-
return related?.title ?? (related?.id ? /* @__PURE__ */
|
|
4696
|
+
return related?.title ?? (related?.id ? /* @__PURE__ */ jsx27("code", { className: "b316-muted", children: related.id }) : "\u2014");
|
|
4346
4697
|
}
|
|
4347
4698
|
if (value === null || value === void 0 || value === "") {
|
|
4348
|
-
return /* @__PURE__ */
|
|
4699
|
+
return /* @__PURE__ */ jsx27("span", { className: "b316-muted", children: "\u2014" });
|
|
4349
4700
|
}
|
|
4350
4701
|
switch (field.type) {
|
|
4351
4702
|
case "BOOLEAN":
|
|
@@ -4358,9 +4709,9 @@ function FieldCell({ value, field, related }) {
|
|
|
4358
4709
|
return formatDuration(value);
|
|
4359
4710
|
case "RATING": {
|
|
4360
4711
|
const stars = Math.round(Number(value));
|
|
4361
|
-
return /* @__PURE__ */
|
|
4712
|
+
return /* @__PURE__ */ jsxs26("span", { "aria-label": `${stars} out of 5`, children: [
|
|
4362
4713
|
"\u2605".repeat(stars),
|
|
4363
|
-
/* @__PURE__ */
|
|
4714
|
+
/* @__PURE__ */ jsx27("span", { className: "b316-muted", children: "\u2605".repeat(Math.max(0, 5 - stars)) })
|
|
4364
4715
|
] });
|
|
4365
4716
|
}
|
|
4366
4717
|
case "DATE":
|
|
@@ -4368,15 +4719,15 @@ function FieldCell({ value, field, related }) {
|
|
|
4368
4719
|
case "DATETIME":
|
|
4369
4720
|
return new Date(String(value)).toLocaleString();
|
|
4370
4721
|
case "SELECT":
|
|
4371
|
-
return /* @__PURE__ */
|
|
4722
|
+
return /* @__PURE__ */ jsx27("span", { className: "b316-chip", children: String(value) });
|
|
4372
4723
|
case "MULTISELECT":
|
|
4373
|
-
return /* @__PURE__ */
|
|
4724
|
+
return /* @__PURE__ */ jsx27("span", { className: "b316-chips", children: (Array.isArray(value) ? value : [value]).map((item) => /* @__PURE__ */ jsx27("span", { className: "b316-chip", children: String(item) }, String(item))) });
|
|
4374
4725
|
case "URL":
|
|
4375
|
-
return /* @__PURE__ */
|
|
4726
|
+
return /* @__PURE__ */ jsx27("a", { href: String(value), target: "_blank", rel: "noreferrer noopener", children: String(value) });
|
|
4376
4727
|
case "EMAIL":
|
|
4377
|
-
return /* @__PURE__ */
|
|
4728
|
+
return /* @__PURE__ */ jsx27("a", { href: `mailto:${String(value)}`, children: String(value) });
|
|
4378
4729
|
case "PHONE":
|
|
4379
|
-
return /* @__PURE__ */
|
|
4730
|
+
return /* @__PURE__ */ jsx27("a", { href: `tel:${String(value)}`, children: String(value) });
|
|
4380
4731
|
case "ADDRESS":
|
|
4381
4732
|
return formatAddress(value);
|
|
4382
4733
|
case "ATTACHMENT": {
|
|
@@ -4388,7 +4739,7 @@ function FieldCell({ value, field, related }) {
|
|
|
4388
4739
|
return text.length > 80 ? `${text.slice(0, 80)}\u2026` : text;
|
|
4389
4740
|
}
|
|
4390
4741
|
case "JSON":
|
|
4391
|
-
return /* @__PURE__ */
|
|
4742
|
+
return /* @__PURE__ */ jsx27("code", { className: "b316-muted", children: JSON.stringify(value).slice(0, 60) });
|
|
4392
4743
|
default:
|
|
4393
4744
|
return String(value);
|
|
4394
4745
|
}
|
|
@@ -4409,7 +4760,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4409
4760
|
function control() {
|
|
4410
4761
|
switch (field.type) {
|
|
4411
4762
|
case "LONGTEXT":
|
|
4412
|
-
return /* @__PURE__ */
|
|
4763
|
+
return /* @__PURE__ */ jsx27(
|
|
4413
4764
|
"textarea",
|
|
4414
4765
|
{
|
|
4415
4766
|
...common,
|
|
@@ -4419,7 +4770,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4419
4770
|
}
|
|
4420
4771
|
);
|
|
4421
4772
|
case "BOOLEAN":
|
|
4422
|
-
return /* @__PURE__ */
|
|
4773
|
+
return /* @__PURE__ */ jsx27(
|
|
4423
4774
|
"input",
|
|
4424
4775
|
{
|
|
4425
4776
|
...common,
|
|
@@ -4430,22 +4781,22 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4430
4781
|
}
|
|
4431
4782
|
);
|
|
4432
4783
|
case "SELECT":
|
|
4433
|
-
return /* @__PURE__ */
|
|
4784
|
+
return /* @__PURE__ */ jsxs26(
|
|
4434
4785
|
"select",
|
|
4435
4786
|
{
|
|
4436
4787
|
...common,
|
|
4437
4788
|
value: value === null || value === void 0 ? "" : String(value),
|
|
4438
4789
|
onChange: (event) => onChange(event.target.value === "" ? null : event.target.value),
|
|
4439
4790
|
children: [
|
|
4440
|
-
field.required ? null : /* @__PURE__ */
|
|
4441
|
-
(field.options ?? []).map((option) => /* @__PURE__ */
|
|
4791
|
+
field.required ? null : /* @__PURE__ */ jsx27("option", { value: "", children: "\u2014" }),
|
|
4792
|
+
(field.options ?? []).map((option) => /* @__PURE__ */ jsx27("option", { value: option, children: option }, option))
|
|
4442
4793
|
]
|
|
4443
4794
|
}
|
|
4444
4795
|
);
|
|
4445
4796
|
case "MULTISELECT": {
|
|
4446
4797
|
const selected = new Set(Array.isArray(value) ? value.map(String) : []);
|
|
4447
|
-
return /* @__PURE__ */
|
|
4448
|
-
/* @__PURE__ */
|
|
4798
|
+
return /* @__PURE__ */ jsx27("div", { className: "b316-choices", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxs26("label", { className: "b316-choice", children: [
|
|
4799
|
+
/* @__PURE__ */ jsx27(
|
|
4449
4800
|
"input",
|
|
4450
4801
|
{
|
|
4451
4802
|
type: "checkbox",
|
|
@@ -4468,7 +4819,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4468
4819
|
case "NUMBER":
|
|
4469
4820
|
case "MONEY":
|
|
4470
4821
|
case "PERCENT":
|
|
4471
|
-
return /* @__PURE__ */
|
|
4822
|
+
return /* @__PURE__ */ jsx27(
|
|
4472
4823
|
"input",
|
|
4473
4824
|
{
|
|
4474
4825
|
...common,
|
|
@@ -4479,7 +4830,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4479
4830
|
}
|
|
4480
4831
|
);
|
|
4481
4832
|
case "RATING":
|
|
4482
|
-
return /* @__PURE__ */
|
|
4833
|
+
return /* @__PURE__ */ jsx27(
|
|
4483
4834
|
"input",
|
|
4484
4835
|
{
|
|
4485
4836
|
...common,
|
|
@@ -4493,8 +4844,8 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4493
4844
|
);
|
|
4494
4845
|
case "DURATION": {
|
|
4495
4846
|
const minutes = value === null || value === void 0 ? "" : String(Number(value) / 60);
|
|
4496
|
-
return /* @__PURE__ */
|
|
4497
|
-
/* @__PURE__ */
|
|
4847
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-suffixed", children: [
|
|
4848
|
+
/* @__PURE__ */ jsx27(
|
|
4498
4849
|
"input",
|
|
4499
4850
|
{
|
|
4500
4851
|
...common,
|
|
@@ -4504,11 +4855,11 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4504
4855
|
onChange: (event) => onChange(event.target.value === "" ? null : Number(event.target.value) * 60)
|
|
4505
4856
|
}
|
|
4506
4857
|
),
|
|
4507
|
-
/* @__PURE__ */
|
|
4858
|
+
/* @__PURE__ */ jsx27("span", { className: "b316-muted", children: "minutes" })
|
|
4508
4859
|
] });
|
|
4509
4860
|
}
|
|
4510
4861
|
case "DATE":
|
|
4511
|
-
return /* @__PURE__ */
|
|
4862
|
+
return /* @__PURE__ */ jsx27(
|
|
4512
4863
|
"input",
|
|
4513
4864
|
{
|
|
4514
4865
|
...common,
|
|
@@ -4518,7 +4869,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4518
4869
|
}
|
|
4519
4870
|
);
|
|
4520
4871
|
case "DATETIME":
|
|
4521
|
-
return /* @__PURE__ */
|
|
4872
|
+
return /* @__PURE__ */ jsx27(
|
|
4522
4873
|
"input",
|
|
4523
4874
|
{
|
|
4524
4875
|
...common,
|
|
@@ -4531,7 +4882,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4531
4882
|
);
|
|
4532
4883
|
case "ADDRESS": {
|
|
4533
4884
|
const address = value ?? {};
|
|
4534
|
-
const part = (key, label) => /* @__PURE__ */
|
|
4885
|
+
const part = (key, label) => /* @__PURE__ */ jsx27(
|
|
4535
4886
|
"input",
|
|
4536
4887
|
{
|
|
4537
4888
|
className: "b316-input",
|
|
@@ -4543,7 +4894,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4543
4894
|
},
|
|
4544
4895
|
key
|
|
4545
4896
|
);
|
|
4546
|
-
return /* @__PURE__ */
|
|
4897
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-address", children: [
|
|
4547
4898
|
part("line1", "Address line 1"),
|
|
4548
4899
|
part("line2", "Address line 2"),
|
|
4549
4900
|
part("city", "City"),
|
|
@@ -4553,7 +4904,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4553
4904
|
] });
|
|
4554
4905
|
}
|
|
4555
4906
|
case "EMAIL":
|
|
4556
|
-
return /* @__PURE__ */
|
|
4907
|
+
return /* @__PURE__ */ jsx27(
|
|
4557
4908
|
"input",
|
|
4558
4909
|
{
|
|
4559
4910
|
...common,
|
|
@@ -4563,7 +4914,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4563
4914
|
}
|
|
4564
4915
|
);
|
|
4565
4916
|
case "URL":
|
|
4566
|
-
return /* @__PURE__ */
|
|
4917
|
+
return /* @__PURE__ */ jsx27(
|
|
4567
4918
|
"input",
|
|
4568
4919
|
{
|
|
4569
4920
|
...common,
|
|
@@ -4573,7 +4924,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4573
4924
|
}
|
|
4574
4925
|
);
|
|
4575
4926
|
case "PHONE":
|
|
4576
|
-
return /* @__PURE__ */
|
|
4927
|
+
return /* @__PURE__ */ jsx27(
|
|
4577
4928
|
"input",
|
|
4578
4929
|
{
|
|
4579
4930
|
...common,
|
|
@@ -4583,7 +4934,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4583
4934
|
}
|
|
4584
4935
|
);
|
|
4585
4936
|
default:
|
|
4586
|
-
return /* @__PURE__ */
|
|
4937
|
+
return /* @__PURE__ */ jsx27(
|
|
4587
4938
|
"input",
|
|
4588
4939
|
{
|
|
4589
4940
|
...common,
|
|
@@ -4594,24 +4945,24 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4594
4945
|
);
|
|
4595
4946
|
}
|
|
4596
4947
|
}
|
|
4597
|
-
return /* @__PURE__ */
|
|
4598
|
-
/* @__PURE__ */
|
|
4948
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-field", children: [
|
|
4949
|
+
/* @__PURE__ */ jsxs26("label", { className: "b316-label", htmlFor: id, children: [
|
|
4599
4950
|
field.label,
|
|
4600
|
-
field.required ? /* @__PURE__ */
|
|
4951
|
+
field.required ? /* @__PURE__ */ jsx27("span", { "aria-hidden": "true", children: " *" }) : null
|
|
4601
4952
|
] }),
|
|
4602
4953
|
control(),
|
|
4603
|
-
field.description ? /* @__PURE__ */
|
|
4604
|
-
error ? /* @__PURE__ */
|
|
4954
|
+
field.description ? /* @__PURE__ */ jsx27("div", { className: "b316-hint", children: field.description }) : null,
|
|
4955
|
+
error ? /* @__PURE__ */ jsx27("div", { className: "b316-error", id: described, role: "alert", children: error }) : null
|
|
4605
4956
|
] });
|
|
4606
4957
|
}
|
|
4607
4958
|
|
|
4608
4959
|
// src/RecordForm.tsx
|
|
4609
4960
|
import { specFor as specFor2 } from "@base316/sdk";
|
|
4610
|
-
import { useEffect as
|
|
4961
|
+
import { useEffect as useEffect22, useState as useState27 } from "react";
|
|
4611
4962
|
|
|
4612
4963
|
// src/RelationPicker.tsx
|
|
4613
|
-
import { useEffect as
|
|
4614
|
-
import { Fragment as
|
|
4964
|
+
import { useEffect as useEffect20, useRef as useRef7, useState as useState25 } from "react";
|
|
4965
|
+
import { Fragment as Fragment10, jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4615
4966
|
function RelationPicker({
|
|
4616
4967
|
field,
|
|
4617
4968
|
value,
|
|
@@ -4621,13 +4972,13 @@ function RelationPicker({
|
|
|
4621
4972
|
tenant
|
|
4622
4973
|
}) {
|
|
4623
4974
|
const { client, token } = useBase316();
|
|
4624
|
-
const [query, setQuery] =
|
|
4625
|
-
const [results, setResults] =
|
|
4626
|
-
const [chosenTitle, setChosenTitle] =
|
|
4627
|
-
const [open, setOpen] =
|
|
4975
|
+
const [query, setQuery] = useState25("");
|
|
4976
|
+
const [results, setResults] = useState25([]);
|
|
4977
|
+
const [chosenTitle, setChosenTitle] = useState25(null);
|
|
4978
|
+
const [open, setOpen] = useState25(false);
|
|
4628
4979
|
const id = `b316-field-${field.key}`;
|
|
4629
4980
|
const box = useRef7(null);
|
|
4630
|
-
|
|
4981
|
+
useEffect20(() => {
|
|
4631
4982
|
if (!token || !value || !field.relationTo) {
|
|
4632
4983
|
setChosenTitle(null);
|
|
4633
4984
|
return;
|
|
@@ -4642,7 +4993,7 @@ function RelationPicker({
|
|
|
4642
4993
|
cancelled = true;
|
|
4643
4994
|
};
|
|
4644
4995
|
}, [client, token, value, field.relationTo, tenant]);
|
|
4645
|
-
|
|
4996
|
+
useEffect20(() => {
|
|
4646
4997
|
if (!token || !field.relationTo || !open) {
|
|
4647
4998
|
return;
|
|
4648
4999
|
}
|
|
@@ -4668,7 +5019,7 @@ function RelationPicker({
|
|
|
4668
5019
|
clearTimeout(timer);
|
|
4669
5020
|
};
|
|
4670
5021
|
}, [client, token, field.relationTo, query, open, tenant]);
|
|
4671
|
-
|
|
5022
|
+
useEffect20(() => {
|
|
4672
5023
|
if (!open || typeof document === "undefined") {
|
|
4673
5024
|
return;
|
|
4674
5025
|
}
|
|
@@ -4682,14 +5033,14 @@ function RelationPicker({
|
|
|
4682
5033
|
document.removeEventListener("mousedown", onDocumentClick);
|
|
4683
5034
|
};
|
|
4684
5035
|
}, [open]);
|
|
4685
|
-
return /* @__PURE__ */
|
|
4686
|
-
/* @__PURE__ */
|
|
5036
|
+
return /* @__PURE__ */ jsxs27("div", { className: "b316-field", ref: box, children: [
|
|
5037
|
+
/* @__PURE__ */ jsxs27("label", { className: "b316-label", htmlFor: id, children: [
|
|
4687
5038
|
field.label,
|
|
4688
|
-
field.required ? /* @__PURE__ */
|
|
5039
|
+
field.required ? /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: " *" }) : null
|
|
4689
5040
|
] }),
|
|
4690
|
-
value && !open ? /* @__PURE__ */
|
|
4691
|
-
/* @__PURE__ */
|
|
4692
|
-
disabled ? null : /* @__PURE__ */
|
|
5041
|
+
value && !open ? /* @__PURE__ */ jsxs27("div", { className: "b316-relation-chosen", children: [
|
|
5042
|
+
/* @__PURE__ */ jsx28("span", { children: chosenTitle ?? value }),
|
|
5043
|
+
disabled ? null : /* @__PURE__ */ jsx28(
|
|
4693
5044
|
"button",
|
|
4694
5045
|
{
|
|
4695
5046
|
type: "button",
|
|
@@ -4701,7 +5052,7 @@ function RelationPicker({
|
|
|
4701
5052
|
children: "Change"
|
|
4702
5053
|
}
|
|
4703
5054
|
),
|
|
4704
|
-
disabled || field.required ? null : /* @__PURE__ */
|
|
5055
|
+
disabled || field.required ? null : /* @__PURE__ */ jsx28(
|
|
4705
5056
|
"button",
|
|
4706
5057
|
{
|
|
4707
5058
|
type: "button",
|
|
@@ -4711,8 +5062,8 @@ function RelationPicker({
|
|
|
4711
5062
|
children: "Clear"
|
|
4712
5063
|
}
|
|
4713
5064
|
)
|
|
4714
|
-
] }) : /* @__PURE__ */
|
|
4715
|
-
/* @__PURE__ */
|
|
5065
|
+
] }) : /* @__PURE__ */ jsxs27(Fragment10, { children: [
|
|
5066
|
+
/* @__PURE__ */ jsx28(
|
|
4716
5067
|
"input",
|
|
4717
5068
|
{
|
|
4718
5069
|
id,
|
|
@@ -4733,7 +5084,7 @@ function RelationPicker({
|
|
|
4733
5084
|
}
|
|
4734
5085
|
}
|
|
4735
5086
|
),
|
|
4736
|
-
open ? /* @__PURE__ */
|
|
5087
|
+
open ? /* @__PURE__ */ jsx28("ul", { className: "b316-relation-results", id: `${id}-results`, role: "listbox", children: results.length === 0 ? /* @__PURE__ */ jsx28("li", { className: "b316-muted b316-relation-empty", children: "No matches" }) : results.map((result) => /* @__PURE__ */ jsx28("li", { children: /* @__PURE__ */ jsx28(
|
|
4737
5088
|
"button",
|
|
4738
5089
|
{
|
|
4739
5090
|
type: "button",
|
|
@@ -4749,13 +5100,13 @@ function RelationPicker({
|
|
|
4749
5100
|
}
|
|
4750
5101
|
) }, result.id)) }) : null
|
|
4751
5102
|
] }),
|
|
4752
|
-
field.description ? /* @__PURE__ */
|
|
4753
|
-
error ? /* @__PURE__ */
|
|
5103
|
+
field.description ? /* @__PURE__ */ jsx28("div", { className: "b316-hint", children: field.description }) : null,
|
|
5104
|
+
error ? /* @__PURE__ */ jsx28("div", { className: "b316-error", role: "alert", children: error }) : null
|
|
4754
5105
|
] });
|
|
4755
5106
|
}
|
|
4756
5107
|
|
|
4757
5108
|
// src/useCollection.ts
|
|
4758
|
-
import { useCallback as useCallback9, useEffect as
|
|
5109
|
+
import { useCallback as useCallback9, useEffect as useEffect21, useMemo as useMemo3, useState as useState26 } from "react";
|
|
4759
5110
|
function fieldErrorFrom(cause) {
|
|
4760
5111
|
const param = cause?.param;
|
|
4761
5112
|
const message = cause instanceof Error ? cause.message : "That value was not accepted.";
|
|
@@ -4763,24 +5114,24 @@ function fieldErrorFrom(cause) {
|
|
|
4763
5114
|
}
|
|
4764
5115
|
function useCollection(collection, options = {}) {
|
|
4765
5116
|
const { client, token } = useBase316();
|
|
4766
|
-
const [schema, setSchema] =
|
|
4767
|
-
const [records, setRecords] =
|
|
4768
|
-
const [error, setError] =
|
|
4769
|
-
const [loading, setLoading] =
|
|
4770
|
-
const [total, setTotal] =
|
|
4771
|
-
const [cursor, setCursor] =
|
|
4772
|
-
const [reloadCount, setReloadCount] =
|
|
4773
|
-
const [search, setSearch] =
|
|
4774
|
-
const [filters, setFilters] =
|
|
4775
|
-
const [sort, setSort] =
|
|
5117
|
+
const [schema, setSchema] = useState26(null);
|
|
5118
|
+
const [records, setRecords] = useState26([]);
|
|
5119
|
+
const [error, setError] = useState26(null);
|
|
5120
|
+
const [loading, setLoading] = useState26(true);
|
|
5121
|
+
const [total, setTotal] = useState26(0);
|
|
5122
|
+
const [cursor, setCursor] = useState26(null);
|
|
5123
|
+
const [reloadCount, setReloadCount] = useState26(0);
|
|
5124
|
+
const [search, setSearch] = useState26("");
|
|
5125
|
+
const [filters, setFilters] = useState26([]);
|
|
5126
|
+
const [sort, setSort] = useState26(
|
|
4776
5127
|
options.sort ?? null
|
|
4777
5128
|
);
|
|
4778
|
-
const [fieldErrors, setFieldErrors] =
|
|
4779
|
-
const [saving, setSaving] =
|
|
5129
|
+
const [fieldErrors, setFieldErrors] = useState26({});
|
|
5130
|
+
const [saving, setSaving] = useState26(false);
|
|
4780
5131
|
const { tenant, limit, recordId } = options;
|
|
4781
5132
|
const fixedFilters = JSON.stringify(options.filters ?? []);
|
|
4782
5133
|
const scope = useMemo3(() => tenant ? { tenant } : void 0, [tenant]);
|
|
4783
|
-
|
|
5134
|
+
useEffect21(() => {
|
|
4784
5135
|
if (!token) {
|
|
4785
5136
|
return;
|
|
4786
5137
|
}
|
|
@@ -4799,7 +5150,7 @@ function useCollection(collection, options = {}) {
|
|
|
4799
5150
|
cancelled = true;
|
|
4800
5151
|
};
|
|
4801
5152
|
}, [client, token, collection, scope]);
|
|
4802
|
-
|
|
5153
|
+
useEffect21(() => {
|
|
4803
5154
|
if (!token || !schema) {
|
|
4804
5155
|
return;
|
|
4805
5156
|
}
|
|
@@ -4991,7 +5342,7 @@ function useCollection(collection, options = {}) {
|
|
|
4991
5342
|
}
|
|
4992
5343
|
|
|
4993
5344
|
// src/RecordForm.tsx
|
|
4994
|
-
import { jsx as
|
|
5345
|
+
import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4995
5346
|
function RecordForm({
|
|
4996
5347
|
collection,
|
|
4997
5348
|
recordId,
|
|
@@ -5012,20 +5363,20 @@ function RecordForm({
|
|
|
5012
5363
|
recordId
|
|
5013
5364
|
}
|
|
5014
5365
|
);
|
|
5015
|
-
const [values, setValues] =
|
|
5016
|
-
const [loaded, setLoaded] =
|
|
5366
|
+
const [values, setValues] = useState27(defaults ?? {});
|
|
5367
|
+
const [loaded, setLoaded] = useState27(!recordId);
|
|
5017
5368
|
const existing = recordId ? records.find((record) => record.id === recordId) : void 0;
|
|
5018
|
-
|
|
5369
|
+
useEffect22(() => {
|
|
5019
5370
|
if (existing && !loaded) {
|
|
5020
5371
|
setValues(existing.fields);
|
|
5021
5372
|
setLoaded(true);
|
|
5022
5373
|
}
|
|
5023
5374
|
}, [existing, loaded]);
|
|
5024
5375
|
if (error) {
|
|
5025
|
-
return /* @__PURE__ */
|
|
5376
|
+
return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx29("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5026
5377
|
}
|
|
5027
5378
|
if (!schema || !loaded) {
|
|
5028
|
-
return /* @__PURE__ */
|
|
5379
|
+
return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5029
5380
|
}
|
|
5030
5381
|
const editable = schema.fields.filter((field) => !specFor2(field).computed);
|
|
5031
5382
|
async function submit(event) {
|
|
@@ -5035,11 +5386,11 @@ function RecordForm({
|
|
|
5035
5386
|
onSaved?.(saved.id);
|
|
5036
5387
|
}
|
|
5037
5388
|
}
|
|
5038
|
-
return /* @__PURE__ */
|
|
5039
|
-
/* @__PURE__ */
|
|
5040
|
-
fieldErrors._ ? /* @__PURE__ */
|
|
5389
|
+
return /* @__PURE__ */ jsxs28("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
|
|
5390
|
+
/* @__PURE__ */ jsx29("h3", { className: "b316-form-title", children: recordId ? `Edit ${schema.name.toLowerCase()}` : `New ${schema.name.toLowerCase()}` }),
|
|
5391
|
+
fieldErrors._ ? /* @__PURE__ */ jsx29("div", { className: "b316-error", role: "alert", children: fieldErrors._ }) : null,
|
|
5041
5392
|
editable.map(
|
|
5042
|
-
(field) => field.type === "RELATION" ? /* @__PURE__ */
|
|
5393
|
+
(field) => field.type === "RELATION" ? /* @__PURE__ */ jsx29(
|
|
5043
5394
|
RelationPicker,
|
|
5044
5395
|
{
|
|
5045
5396
|
field,
|
|
@@ -5050,7 +5401,7 @@ function RecordForm({
|
|
|
5050
5401
|
onChange: (next) => setValues((current) => ({ ...current, [field.key]: next }))
|
|
5051
5402
|
},
|
|
5052
5403
|
field.key
|
|
5053
|
-
) : /* @__PURE__ */
|
|
5404
|
+
) : /* @__PURE__ */ jsx29(
|
|
5054
5405
|
FieldInput,
|
|
5055
5406
|
{
|
|
5056
5407
|
field,
|
|
@@ -5062,15 +5413,15 @@ function RecordForm({
|
|
|
5062
5413
|
field.key
|
|
5063
5414
|
)
|
|
5064
5415
|
),
|
|
5065
|
-
/* @__PURE__ */
|
|
5066
|
-
onCancel ? /* @__PURE__ */
|
|
5067
|
-
/* @__PURE__ */
|
|
5416
|
+
/* @__PURE__ */ jsxs28("div", { className: "b316-form-actions", children: [
|
|
5417
|
+
onCancel ? /* @__PURE__ */ jsx29("button", { type: "button", className: "b316-button-quiet", onClick: onCancel, disabled: saving, children: "Cancel" }) : null,
|
|
5418
|
+
/* @__PURE__ */ jsx29("button", { type: "submit", className: "b316-button", disabled: saving, children: saving ? "Saving\u2026" : "Save" })
|
|
5068
5419
|
] })
|
|
5069
5420
|
] });
|
|
5070
5421
|
}
|
|
5071
5422
|
|
|
5072
5423
|
// src/DataTable.tsx
|
|
5073
|
-
import { jsx as
|
|
5424
|
+
import { jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
5074
5425
|
function DataTable({
|
|
5075
5426
|
collection,
|
|
5076
5427
|
columns,
|
|
@@ -5099,13 +5450,13 @@ function DataTable({
|
|
|
5099
5450
|
loadMore,
|
|
5100
5451
|
remove
|
|
5101
5452
|
} = useCollection(collection, options);
|
|
5102
|
-
const [editing, setEditing] =
|
|
5103
|
-
const [removeFailed, setRemoveFailed] =
|
|
5453
|
+
const [editing, setEditing] = useState28(null);
|
|
5454
|
+
const [removeFailed, setRemoveFailed] = useState28(null);
|
|
5104
5455
|
if (error) {
|
|
5105
|
-
return /* @__PURE__ */
|
|
5456
|
+
return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx30("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5106
5457
|
}
|
|
5107
5458
|
if (!schema) {
|
|
5108
|
-
return /* @__PURE__ */
|
|
5459
|
+
return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5109
5460
|
}
|
|
5110
5461
|
const shown = columns ? (
|
|
5111
5462
|
// Ordered by what was asked for, not by the schema: a caller naming
|
|
@@ -5114,10 +5465,10 @@ function DataTable({
|
|
|
5114
5465
|
) : schema.fields;
|
|
5115
5466
|
const searchable = schema.fields.some((field) => specFor3(field).capabilities.searchable);
|
|
5116
5467
|
const writable = canWrite && !readOnly;
|
|
5117
|
-
return /* @__PURE__ */
|
|
5118
|
-
removeFailed ? /* @__PURE__ */
|
|
5119
|
-
/* @__PURE__ */
|
|
5120
|
-
searchable && !hideSearch ? /* @__PURE__ */
|
|
5468
|
+
return /* @__PURE__ */ jsxs29("div", { className: cls("b316-table-wrap", className), style, children: [
|
|
5469
|
+
removeFailed ? /* @__PURE__ */ jsx30("div", { className: "b316-error", role: "alert", children: removeFailed }) : null,
|
|
5470
|
+
/* @__PURE__ */ jsxs29("div", { className: "b316-table-bar", children: [
|
|
5471
|
+
searchable && !hideSearch ? /* @__PURE__ */ jsx30(
|
|
5121
5472
|
"input",
|
|
5122
5473
|
{
|
|
5123
5474
|
type: "search",
|
|
@@ -5127,25 +5478,25 @@ function DataTable({
|
|
|
5127
5478
|
value: search,
|
|
5128
5479
|
onChange: (event) => setSearch(event.target.value)
|
|
5129
5480
|
}
|
|
5130
|
-
) : /* @__PURE__ */
|
|
5131
|
-
/* @__PURE__ */
|
|
5132
|
-
/* @__PURE__ */
|
|
5481
|
+
) : /* @__PURE__ */ jsx30("span", {}),
|
|
5482
|
+
/* @__PURE__ */ jsxs29("div", { className: "b316-table-actions", children: [
|
|
5483
|
+
/* @__PURE__ */ jsxs29("span", { className: "b316-muted", children: [
|
|
5133
5484
|
total,
|
|
5134
5485
|
" ",
|
|
5135
5486
|
total === 1 ? schema.name.toLowerCase() : schema.namePlural.toLowerCase()
|
|
5136
5487
|
] }),
|
|
5137
|
-
writable ? /* @__PURE__ */
|
|
5488
|
+
writable ? /* @__PURE__ */ jsxs29("button", { type: "button", className: "b316-button", onClick: () => setEditing("new"), children: [
|
|
5138
5489
|
"New ",
|
|
5139
5490
|
schema.name.toLowerCase()
|
|
5140
5491
|
] }) : null
|
|
5141
5492
|
] })
|
|
5142
5493
|
] }),
|
|
5143
|
-
/* @__PURE__ */
|
|
5144
|
-
/* @__PURE__ */
|
|
5494
|
+
/* @__PURE__ */ jsx30("div", { className: "b316-table-scroll", children: /* @__PURE__ */ jsxs29("table", { className: "b316-table", children: [
|
|
5495
|
+
/* @__PURE__ */ jsx30("thead", { children: /* @__PURE__ */ jsxs29("tr", { children: [
|
|
5145
5496
|
shown.map((field) => {
|
|
5146
5497
|
const sortable = specFor3(field).capabilities.sortable;
|
|
5147
5498
|
const active = sort?.field === field.key;
|
|
5148
|
-
return /* @__PURE__ */
|
|
5499
|
+
return /* @__PURE__ */ jsx30("th", { scope: "col", "aria-sort": ariaSort(active, sort?.direction), children: sortable ? /* @__PURE__ */ jsxs29(
|
|
5149
5500
|
"button",
|
|
5150
5501
|
{
|
|
5151
5502
|
type: "button",
|
|
@@ -5153,20 +5504,20 @@ function DataTable({
|
|
|
5153
5504
|
onClick: () => toggleSort(field.key),
|
|
5154
5505
|
children: [
|
|
5155
5506
|
field.label,
|
|
5156
|
-
/* @__PURE__ */
|
|
5507
|
+
/* @__PURE__ */ jsx30("span", { "aria-hidden": "true", children: active ? sort?.direction === "desc" ? " \u2193" : " \u2191" : " \u2195" })
|
|
5157
5508
|
]
|
|
5158
5509
|
}
|
|
5159
5510
|
) : field.label }, field.key);
|
|
5160
5511
|
}),
|
|
5161
|
-
writable ? /* @__PURE__ */
|
|
5512
|
+
writable ? /* @__PURE__ */ jsx30("th", { scope: "col", className: "b316-table-rowactions" }) : null
|
|
5162
5513
|
] }) }),
|
|
5163
|
-
/* @__PURE__ */
|
|
5514
|
+
/* @__PURE__ */ jsx30("tbody", { children: records.map((record) => /* @__PURE__ */ jsxs29(
|
|
5164
5515
|
"tr",
|
|
5165
5516
|
{
|
|
5166
5517
|
className: onSelect ? "b316-row-clickable" : void 0,
|
|
5167
5518
|
onClick: onSelect ? () => onSelect(record) : void 0,
|
|
5168
5519
|
children: [
|
|
5169
|
-
shown.map((field) => /* @__PURE__ */
|
|
5520
|
+
shown.map((field) => /* @__PURE__ */ jsx30("td", { children: renderCell?.(record, field) ?? /* @__PURE__ */ jsx30(
|
|
5170
5521
|
FieldCell,
|
|
5171
5522
|
{
|
|
5172
5523
|
value: record.fields[field.key] ?? null,
|
|
@@ -5174,8 +5525,8 @@ function DataTable({
|
|
|
5174
5525
|
related: record.related[field.key]
|
|
5175
5526
|
}
|
|
5176
5527
|
) }, field.key)),
|
|
5177
|
-
writable ? /* @__PURE__ */
|
|
5178
|
-
/* @__PURE__ */
|
|
5528
|
+
writable ? /* @__PURE__ */ jsxs29("td", { className: "b316-table-rowactions", children: [
|
|
5529
|
+
/* @__PURE__ */ jsx30(
|
|
5179
5530
|
"button",
|
|
5180
5531
|
{
|
|
5181
5532
|
type: "button",
|
|
@@ -5187,7 +5538,7 @@ function DataTable({
|
|
|
5187
5538
|
children: "Edit"
|
|
5188
5539
|
}
|
|
5189
5540
|
),
|
|
5190
|
-
/* @__PURE__ */
|
|
5541
|
+
/* @__PURE__ */ jsx30(
|
|
5191
5542
|
ConfirmButton,
|
|
5192
5543
|
{
|
|
5193
5544
|
className: "b316-button-quiet b316-danger",
|
|
@@ -5211,10 +5562,10 @@ function DataTable({
|
|
|
5211
5562
|
record.id
|
|
5212
5563
|
)) })
|
|
5213
5564
|
] }) }),
|
|
5214
|
-
records.length === 0 && !loading ? /* @__PURE__ */
|
|
5215
|
-
loading ? /* @__PURE__ */
|
|
5216
|
-
hasMore ? /* @__PURE__ */
|
|
5217
|
-
editing ? /* @__PURE__ */
|
|
5565
|
+
records.length === 0 && !loading ? /* @__PURE__ */ jsx30("div", { className: "b316-empty", children: emptyState ?? `No ${schema.namePlural.toLowerCase()} yet.` }) : null,
|
|
5566
|
+
loading ? /* @__PURE__ */ jsx30("div", { className: "b316-empty", children: "Loading\u2026" }) : null,
|
|
5567
|
+
hasMore ? /* @__PURE__ */ jsx30("div", { className: "b316-table-more", children: /* @__PURE__ */ jsx30("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: "Load more" }) }) : null,
|
|
5568
|
+
editing ? /* @__PURE__ */ jsx30(
|
|
5218
5569
|
RecordForm,
|
|
5219
5570
|
{
|
|
5220
5571
|
collection,
|
|
@@ -5242,8 +5593,8 @@ import {
|
|
|
5242
5593
|
specFor as specFor4,
|
|
5243
5594
|
titleFieldOf
|
|
5244
5595
|
} from "@base316/sdk";
|
|
5245
|
-
import { useState as
|
|
5246
|
-
import { jsx as
|
|
5596
|
+
import { useState as useState29 } from "react";
|
|
5597
|
+
import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
5247
5598
|
function Kanban({
|
|
5248
5599
|
collection,
|
|
5249
5600
|
groupBy,
|
|
@@ -5260,17 +5611,17 @@ function Kanban({
|
|
|
5260
5611
|
limit: options.limit ?? 100,
|
|
5261
5612
|
...options
|
|
5262
5613
|
});
|
|
5263
|
-
const [dragging, setDragging] =
|
|
5264
|
-
const [over, setOver] =
|
|
5614
|
+
const [dragging, setDragging] = useState29(null);
|
|
5615
|
+
const [over, setOver] = useState29(null);
|
|
5265
5616
|
if (error) {
|
|
5266
|
-
return /* @__PURE__ */
|
|
5617
|
+
return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx31("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5267
5618
|
}
|
|
5268
5619
|
if (!schema) {
|
|
5269
|
-
return /* @__PURE__ */
|
|
5620
|
+
return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5270
5621
|
}
|
|
5271
5622
|
const field = groupBy ? schema.fields.find((candidate) => candidate.key === groupBy) ?? null : defaultGroupFieldOf(schema.fields);
|
|
5272
5623
|
if (!field || !specFor4(field).capabilities.groupable) {
|
|
5273
|
-
return /* @__PURE__ */
|
|
5624
|
+
return /* @__PURE__ */ jsx31("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.` });
|
|
5274
5625
|
}
|
|
5275
5626
|
const columns = columnsFor(field);
|
|
5276
5627
|
const shown = cardFields ? cardFields.map((key) => schema.fields.find((candidate) => candidate.key === key)).filter((candidate) => Boolean(candidate)) : (
|
|
@@ -5287,12 +5638,12 @@ function Kanban({
|
|
|
5287
5638
|
}
|
|
5288
5639
|
await update(record.id, { [field.key]: value });
|
|
5289
5640
|
}
|
|
5290
|
-
return /* @__PURE__ */
|
|
5291
|
-
/* @__PURE__ */
|
|
5641
|
+
return /* @__PURE__ */ jsxs30("div", { className: cls("b316-board-wrap", className), style, children: [
|
|
5642
|
+
/* @__PURE__ */ jsx31("div", { className: "b316-board", role: "list", children: columns.map((column) => {
|
|
5292
5643
|
const inColumn = records.filter(
|
|
5293
5644
|
(record) => String(record.fields[field.key] ?? "") === String(column.value ?? "")
|
|
5294
5645
|
);
|
|
5295
|
-
return /* @__PURE__ */
|
|
5646
|
+
return /* @__PURE__ */ jsxs30(
|
|
5296
5647
|
"section",
|
|
5297
5648
|
{
|
|
5298
5649
|
className: over === String(column.value) ? "b316-board-column b316-board-over" : "b316-board-column",
|
|
@@ -5316,12 +5667,12 @@ function Kanban({
|
|
|
5316
5667
|
setDragging(null);
|
|
5317
5668
|
},
|
|
5318
5669
|
children: [
|
|
5319
|
-
/* @__PURE__ */
|
|
5320
|
-
/* @__PURE__ */
|
|
5321
|
-
/* @__PURE__ */
|
|
5670
|
+
/* @__PURE__ */ jsxs30("header", { className: "b316-board-head", children: [
|
|
5671
|
+
/* @__PURE__ */ jsx31("span", { className: "b316-board-title", children: column.label }),
|
|
5672
|
+
/* @__PURE__ */ jsx31("span", { className: "b316-muted", children: inColumn.length })
|
|
5322
5673
|
] }),
|
|
5323
|
-
/* @__PURE__ */
|
|
5324
|
-
inColumn.map((record) => /* @__PURE__ */
|
|
5674
|
+
/* @__PURE__ */ jsxs30("div", { className: "b316-board-cards", children: [
|
|
5675
|
+
inColumn.map((record) => /* @__PURE__ */ jsxs30(
|
|
5325
5676
|
"article",
|
|
5326
5677
|
{
|
|
5327
5678
|
className: "b316-board-card",
|
|
@@ -5333,10 +5684,10 @@ function Kanban({
|
|
|
5333
5684
|
},
|
|
5334
5685
|
onClick: onSelect ? () => onSelect(record) : void 0,
|
|
5335
5686
|
children: [
|
|
5336
|
-
/* @__PURE__ */
|
|
5337
|
-
shown.map((candidate) => /* @__PURE__ */
|
|
5338
|
-
/* @__PURE__ */
|
|
5339
|
-
/* @__PURE__ */
|
|
5687
|
+
/* @__PURE__ */ jsx31("div", { className: "b316-board-card-title", children: record.title ?? "Untitled" }),
|
|
5688
|
+
shown.map((candidate) => /* @__PURE__ */ jsxs30("div", { className: "b316-board-card-field", children: [
|
|
5689
|
+
/* @__PURE__ */ jsx31("span", { className: "b316-muted", children: candidate.label }),
|
|
5690
|
+
/* @__PURE__ */ jsx31(
|
|
5340
5691
|
FieldCell,
|
|
5341
5692
|
{
|
|
5342
5693
|
value: record.fields[candidate.key] ?? null,
|
|
@@ -5349,9 +5700,9 @@ function Kanban({
|
|
|
5349
5700
|
// Dragging is not reachable by keyboard and is awkward on a
|
|
5350
5701
|
// phone. This is the same action by other means, not a
|
|
5351
5702
|
// lesser fallback.
|
|
5352
|
-
/* @__PURE__ */
|
|
5353
|
-
/* @__PURE__ */
|
|
5354
|
-
/* @__PURE__ */
|
|
5703
|
+
/* @__PURE__ */ jsxs30("label", { className: "b316-board-move", children: [
|
|
5704
|
+
/* @__PURE__ */ jsx31("span", { className: "b316-muted", children: "Move to" }),
|
|
5705
|
+
/* @__PURE__ */ jsx31(
|
|
5355
5706
|
"select",
|
|
5356
5707
|
{
|
|
5357
5708
|
className: "b316-input",
|
|
@@ -5363,7 +5714,7 @@ function Kanban({
|
|
|
5363
5714
|
);
|
|
5364
5715
|
void move(record, chosen?.value ?? null);
|
|
5365
5716
|
},
|
|
5366
|
-
children: columns.map((candidate) => /* @__PURE__ */
|
|
5717
|
+
children: columns.map((candidate) => /* @__PURE__ */ jsx31("option", { value: String(candidate.value), children: candidate.label }, String(candidate.value)))
|
|
5367
5718
|
}
|
|
5368
5719
|
)
|
|
5369
5720
|
] })
|
|
@@ -5372,14 +5723,14 @@ function Kanban({
|
|
|
5372
5723
|
},
|
|
5373
5724
|
record.id
|
|
5374
5725
|
)),
|
|
5375
|
-
inColumn.length === 0 ? /* @__PURE__ */
|
|
5726
|
+
inColumn.length === 0 ? /* @__PURE__ */ jsx31("div", { className: "b316-board-empty", children: emptyState ?? "Nothing here" }) : null
|
|
5376
5727
|
] })
|
|
5377
5728
|
]
|
|
5378
5729
|
},
|
|
5379
5730
|
String(column.value)
|
|
5380
5731
|
);
|
|
5381
5732
|
}) }),
|
|
5382
|
-
hasMore ? /* @__PURE__ */
|
|
5733
|
+
hasMore ? /* @__PURE__ */ jsx31("div", { className: "b316-table-more", children: /* @__PURE__ */ jsxs30("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading, children: [
|
|
5383
5734
|
"Showing ",
|
|
5384
5735
|
records.length,
|
|
5385
5736
|
" of ",
|
|
@@ -5406,7 +5757,7 @@ import {
|
|
|
5406
5757
|
specFor as specFor5
|
|
5407
5758
|
} from "@base316/sdk";
|
|
5408
5759
|
import { useMemo as useMemo4 } from "react";
|
|
5409
|
-
import { jsx as
|
|
5760
|
+
import { jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5410
5761
|
function Chart({
|
|
5411
5762
|
collection,
|
|
5412
5763
|
x,
|
|
@@ -5445,23 +5796,23 @@ function Chart({
|
|
|
5445
5796
|
[records, axis, measure, aggregate, bucket, y]
|
|
5446
5797
|
);
|
|
5447
5798
|
if (error) {
|
|
5448
|
-
return /* @__PURE__ */
|
|
5799
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx32("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5449
5800
|
}
|
|
5450
5801
|
if (!schema || loading) {
|
|
5451
|
-
return /* @__PURE__ */
|
|
5802
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5452
5803
|
}
|
|
5453
5804
|
if (!axis) {
|
|
5454
|
-
return /* @__PURE__ */
|
|
5805
|
+
return /* @__PURE__ */ jsx32("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.` });
|
|
5455
5806
|
}
|
|
5456
5807
|
if (y && !measure) {
|
|
5457
|
-
return /* @__PURE__ */
|
|
5808
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: `"${y}" cannot be ${aggregate === "avg" ? "averaged" : `combined with ${aggregate}`}.` });
|
|
5458
5809
|
}
|
|
5459
5810
|
const peak = Math.max(...buckets.map((entry) => entry.value), 0);
|
|
5460
5811
|
const heading = title ?? `${measure ? `${aggregate} of ${measure.label}` : schema.namePlural} by ${axis.label}`;
|
|
5461
|
-
return /* @__PURE__ */
|
|
5462
|
-
/* @__PURE__ */
|
|
5463
|
-
buckets.length === 0 || peak === 0 ? /* @__PURE__ */
|
|
5464
|
-
/* @__PURE__ */
|
|
5812
|
+
return /* @__PURE__ */ jsxs31("figure", { className: cls("b316-card b316-chart", className), style, children: [
|
|
5813
|
+
/* @__PURE__ */ jsx32("figcaption", { className: "b316-chart-title", children: heading }),
|
|
5814
|
+
buckets.length === 0 || peak === 0 ? /* @__PURE__ */ jsx32("div", { className: "b316-empty", children: "Nothing to chart yet." }) : /* @__PURE__ */ jsx32("div", { className: "b316-chart-plot", style: { height }, children: buckets.map((entry) => /* @__PURE__ */ jsxs31("div", { className: "b316-chart-col", children: [
|
|
5815
|
+
/* @__PURE__ */ jsx32(
|
|
5465
5816
|
"div",
|
|
5466
5817
|
{
|
|
5467
5818
|
className: "b316-chart-bar",
|
|
@@ -5469,18 +5820,18 @@ function Chart({
|
|
|
5469
5820
|
title: `${entry.label}: ${format(entry.value)}`
|
|
5470
5821
|
}
|
|
5471
5822
|
),
|
|
5472
|
-
/* @__PURE__ */
|
|
5823
|
+
/* @__PURE__ */ jsx32("span", { className: "b316-chart-label", children: entry.label })
|
|
5473
5824
|
] }, entry.key)) }),
|
|
5474
|
-
/* @__PURE__ */
|
|
5475
|
-
/* @__PURE__ */
|
|
5476
|
-
/* @__PURE__ */
|
|
5477
|
-
/* @__PURE__ */
|
|
5478
|
-
/* @__PURE__ */
|
|
5479
|
-
/* @__PURE__ */
|
|
5825
|
+
/* @__PURE__ */ jsxs31("details", { className: "b316-chart-data", children: [
|
|
5826
|
+
/* @__PURE__ */ jsx32("summary", { children: "Values" }),
|
|
5827
|
+
/* @__PURE__ */ jsxs31("table", { className: "b316-table", children: [
|
|
5828
|
+
/* @__PURE__ */ jsx32("thead", { children: /* @__PURE__ */ jsxs31("tr", { children: [
|
|
5829
|
+
/* @__PURE__ */ jsx32("th", { scope: "col", children: axis.label }),
|
|
5830
|
+
/* @__PURE__ */ jsx32("th", { scope: "col", children: measure ? measure.label : "Count" })
|
|
5480
5831
|
] }) }),
|
|
5481
|
-
/* @__PURE__ */
|
|
5482
|
-
/* @__PURE__ */
|
|
5483
|
-
/* @__PURE__ */
|
|
5832
|
+
/* @__PURE__ */ jsx32("tbody", { children: buckets.map((entry) => /* @__PURE__ */ jsxs31("tr", { children: [
|
|
5833
|
+
/* @__PURE__ */ jsx32("td", { children: entry.label }),
|
|
5834
|
+
/* @__PURE__ */ jsx32("td", { children: format(entry.value) })
|
|
5484
5835
|
] }, entry.key)) })
|
|
5485
5836
|
] })
|
|
5486
5837
|
] })
|
|
@@ -5539,8 +5890,8 @@ function combine(values, aggregate) {
|
|
|
5539
5890
|
|
|
5540
5891
|
// src/RecordDetail.tsx
|
|
5541
5892
|
import { specFor as specFor6 } from "@base316/sdk";
|
|
5542
|
-
import { useState as
|
|
5543
|
-
import { jsx as
|
|
5893
|
+
import { useState as useState30 } from "react";
|
|
5894
|
+
import { jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5544
5895
|
function RecordDetail({
|
|
5545
5896
|
collection,
|
|
5546
5897
|
recordId,
|
|
@@ -5556,23 +5907,23 @@ function RecordDetail({
|
|
|
5556
5907
|
tenant,
|
|
5557
5908
|
recordId
|
|
5558
5909
|
});
|
|
5559
|
-
const [editing, setEditing] =
|
|
5910
|
+
const [editing, setEditing] = useState30(false);
|
|
5560
5911
|
const record = records.find((candidate) => candidate.id === recordId);
|
|
5561
5912
|
if (error) {
|
|
5562
|
-
return /* @__PURE__ */
|
|
5913
|
+
return /* @__PURE__ */ jsx33("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx33("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5563
5914
|
}
|
|
5564
5915
|
if (!schema || loading) {
|
|
5565
|
-
return /* @__PURE__ */
|
|
5916
|
+
return /* @__PURE__ */ jsx33("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5566
5917
|
}
|
|
5567
5918
|
if (!record) {
|
|
5568
|
-
return /* @__PURE__ */
|
|
5919
|
+
return /* @__PURE__ */ jsxs32("div", { className: cls("b316-card", className), style, children: [
|
|
5569
5920
|
"That ",
|
|
5570
5921
|
schema.name.toLowerCase(),
|
|
5571
5922
|
" is not available."
|
|
5572
5923
|
] });
|
|
5573
5924
|
}
|
|
5574
5925
|
if (editing) {
|
|
5575
|
-
return /* @__PURE__ */
|
|
5926
|
+
return /* @__PURE__ */ jsx33(
|
|
5576
5927
|
RecordForm,
|
|
5577
5928
|
{
|
|
5578
5929
|
collection,
|
|
@@ -5586,12 +5937,12 @@ function RecordDetail({
|
|
|
5586
5937
|
);
|
|
5587
5938
|
}
|
|
5588
5939
|
const writable = canWrite && !readOnly;
|
|
5589
|
-
return /* @__PURE__ */
|
|
5590
|
-
/* @__PURE__ */
|
|
5591
|
-
/* @__PURE__ */
|
|
5592
|
-
/* @__PURE__ */
|
|
5593
|
-
writable ? /* @__PURE__ */
|
|
5594
|
-
writable ? /* @__PURE__ */
|
|
5940
|
+
return /* @__PURE__ */ jsxs32("div", { className: cls("b316-card b316-detail", className), style, children: [
|
|
5941
|
+
/* @__PURE__ */ jsxs32("div", { className: "b316-detail-head", children: [
|
|
5942
|
+
/* @__PURE__ */ jsx33("h3", { className: "b316-detail-title", children: record.title ?? schema.name }),
|
|
5943
|
+
/* @__PURE__ */ jsxs32("div", { className: "b316-detail-actions", children: [
|
|
5944
|
+
writable ? /* @__PURE__ */ jsx33("button", { type: "button", className: "b316-button-quiet", onClick: () => setEditing(true), children: "Edit" }) : null,
|
|
5945
|
+
writable ? /* @__PURE__ */ jsx33(
|
|
5595
5946
|
ConfirmButton,
|
|
5596
5947
|
{
|
|
5597
5948
|
className: "b316-button-quiet b316-danger",
|
|
@@ -5604,15 +5955,15 @@ function RecordDetail({
|
|
|
5604
5955
|
children: "Delete"
|
|
5605
5956
|
}
|
|
5606
5957
|
) : null,
|
|
5607
|
-
onClose ? /* @__PURE__ */
|
|
5958
|
+
onClose ? /* @__PURE__ */ jsx33("button", { type: "button", className: "b316-button-quiet", onClick: onClose, children: "Close" }) : null
|
|
5608
5959
|
] })
|
|
5609
5960
|
] }),
|
|
5610
|
-
/* @__PURE__ */
|
|
5611
|
-
/* @__PURE__ */
|
|
5961
|
+
/* @__PURE__ */ jsx33("dl", { className: "b316-detail-fields", children: schema.fields.map((field) => /* @__PURE__ */ jsxs32("div", { className: "b316-detail-row", children: [
|
|
5962
|
+
/* @__PURE__ */ jsxs32("dt", { className: "b316-label", children: [
|
|
5612
5963
|
field.label,
|
|
5613
|
-
specFor6(field).computed ? /* @__PURE__ */
|
|
5964
|
+
specFor6(field).computed ? /* @__PURE__ */ jsx33("span", { className: "b316-muted", children: " (calculated)" }) : null
|
|
5614
5965
|
] }),
|
|
5615
|
-
/* @__PURE__ */
|
|
5966
|
+
/* @__PURE__ */ jsx33("dd", { children: /* @__PURE__ */ jsx33(
|
|
5616
5967
|
FieldCell,
|
|
5617
5968
|
{
|
|
5618
5969
|
value: record.fields[field.key] ?? null,
|
|
@@ -5626,8 +5977,8 @@ function RecordDetail({
|
|
|
5626
5977
|
}
|
|
5627
5978
|
|
|
5628
5979
|
// src/SubscriptionManager.tsx
|
|
5629
|
-
import { useCallback as useCallback10, useEffect as
|
|
5630
|
-
import { jsx as
|
|
5980
|
+
import { useCallback as useCallback10, useEffect as useEffect23, useState as useState31 } from "react";
|
|
5981
|
+
import { jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5631
5982
|
function statusLabel(status2) {
|
|
5632
5983
|
const words = status2.toLowerCase().split("_");
|
|
5633
5984
|
return words.map((w, i) => i === 0 ? w.charAt(0).toUpperCase() + w.slice(1) : w).join(" ");
|
|
@@ -5667,15 +6018,15 @@ function SubscriptionManager({
|
|
|
5667
6018
|
style
|
|
5668
6019
|
}) {
|
|
5669
6020
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
5670
|
-
const [subscription, setSubscription] =
|
|
5671
|
-
const [loading, setLoading] =
|
|
5672
|
-
const [managedBy, setManagedBy] =
|
|
5673
|
-
const [schedule, setSchedule] =
|
|
5674
|
-
const [busy, setBusy] =
|
|
5675
|
-
const [error, setError] =
|
|
5676
|
-
const [step, setStep] =
|
|
5677
|
-
const [reason, setReason] =
|
|
5678
|
-
const [comment, setComment] =
|
|
6021
|
+
const [subscription, setSubscription] = useState31(null);
|
|
6022
|
+
const [loading, setLoading] = useState31(true);
|
|
6023
|
+
const [managedBy, setManagedBy] = useState31(null);
|
|
6024
|
+
const [schedule, setSchedule] = useState31([]);
|
|
6025
|
+
const [busy, setBusy] = useState31(false);
|
|
6026
|
+
const [error, setError] = useState31(null);
|
|
6027
|
+
const [step, setStep] = useState31({ kind: "idle" });
|
|
6028
|
+
const [reason, setReason] = useState31(null);
|
|
6029
|
+
const [comment, setComment] = useState31("");
|
|
5679
6030
|
const load = useCallback10(async () => {
|
|
5680
6031
|
if (!token) {
|
|
5681
6032
|
setSubscription(null);
|
|
@@ -5694,7 +6045,7 @@ function SubscriptionManager({
|
|
|
5694
6045
|
setLoading(false);
|
|
5695
6046
|
}
|
|
5696
6047
|
}, [client, token]);
|
|
5697
|
-
|
|
6048
|
+
useEffect23(() => {
|
|
5698
6049
|
void load();
|
|
5699
6050
|
}, [load]);
|
|
5700
6051
|
const act = async (change, failure) => {
|
|
@@ -5712,29 +6063,29 @@ function SubscriptionManager({
|
|
|
5712
6063
|
}
|
|
5713
6064
|
};
|
|
5714
6065
|
if (sessionLoading || loading) {
|
|
5715
|
-
return /* @__PURE__ */
|
|
6066
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5716
6067
|
}
|
|
5717
6068
|
if (!token) {
|
|
5718
|
-
return /* @__PURE__ */
|
|
6069
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: "Sign in to manage your subscription." });
|
|
5719
6070
|
}
|
|
5720
6071
|
if (error) {
|
|
5721
|
-
return /* @__PURE__ */
|
|
6072
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx34("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5722
6073
|
}
|
|
5723
6074
|
if (!subscription) {
|
|
5724
|
-
return /* @__PURE__ */
|
|
6075
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: "You are not subscribed to a plan." });
|
|
5725
6076
|
}
|
|
5726
6077
|
const renews = new Date(subscription.currentPeriodEnd).toLocaleDateString();
|
|
5727
6078
|
const next = schedule[0] ?? null;
|
|
5728
6079
|
const nextOn = next?.effectiveAt ? new Date(next.effectiveAt).toLocaleDateString() : renews;
|
|
5729
|
-
return /* @__PURE__ */
|
|
5730
|
-
error ? /* @__PURE__ */
|
|
5731
|
-
/* @__PURE__ */
|
|
5732
|
-
/* @__PURE__ */
|
|
6080
|
+
return /* @__PURE__ */ jsxs33("div", { className: cls("b316-card", className), style, children: [
|
|
6081
|
+
error ? /* @__PURE__ */ jsx34("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6082
|
+
/* @__PURE__ */ jsx34("div", { className: "b316-plan-name", children: subscription.planVersion.plan.name }),
|
|
6083
|
+
/* @__PURE__ */ jsxs33("div", { className: "b316-muted", children: [
|
|
5733
6084
|
statusLabel(subscription.status),
|
|
5734
6085
|
" \xB7 ",
|
|
5735
6086
|
subscription.cancelAtPeriodEnd ? `Ends ${renews}` : `Renews ${renews}`
|
|
5736
6087
|
] }),
|
|
5737
|
-
next && !managedBy ? /* @__PURE__ */
|
|
6088
|
+
next && !managedBy ? /* @__PURE__ */ jsxs33("div", { className: "b316-muted", role: "status", style: { marginTop: 10 }, children: [
|
|
5738
6089
|
"Moves to ",
|
|
5739
6090
|
next.plan.name,
|
|
5740
6091
|
" on ",
|
|
@@ -5742,7 +6093,7 @@ function SubscriptionManager({
|
|
|
5742
6093
|
". You keep ",
|
|
5743
6094
|
subscription.planVersion.plan.name,
|
|
5744
6095
|
" until then.",
|
|
5745
|
-
/* @__PURE__ */
|
|
6096
|
+
/* @__PURE__ */ jsx34("div", { children: /* @__PURE__ */ jsx34(
|
|
5746
6097
|
"button",
|
|
5747
6098
|
{
|
|
5748
6099
|
type: "button",
|
|
@@ -5767,17 +6118,17 @@ function SubscriptionManager({
|
|
|
5767
6118
|
}
|
|
5768
6119
|
) })
|
|
5769
6120
|
] }) : null,
|
|
5770
|
-
managedBy ? /* @__PURE__ */
|
|
6121
|
+
managedBy ? /* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5771
6122
|
"Provided by ",
|
|
5772
6123
|
managedBy.name ?? "the organization that manages your account",
|
|
5773
6124
|
". Ask them to change or cancel it."
|
|
5774
|
-
] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */
|
|
5775
|
-
/* @__PURE__ */
|
|
6125
|
+
] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */ jsxs33("div", { children: [
|
|
6126
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5776
6127
|
"This subscription will not renew. You keep access until ",
|
|
5777
6128
|
renews,
|
|
5778
6129
|
"."
|
|
5779
6130
|
] }),
|
|
5780
|
-
/* @__PURE__ */
|
|
6131
|
+
/* @__PURE__ */ jsx34(
|
|
5781
6132
|
"button",
|
|
5782
6133
|
{
|
|
5783
6134
|
type: "button",
|
|
@@ -5787,14 +6138,14 @@ function SubscriptionManager({
|
|
|
5787
6138
|
children: busy ? "Working\u2026" : "Resume subscription"
|
|
5788
6139
|
}
|
|
5789
6140
|
)
|
|
5790
|
-
] }) : step.kind === "offer" ? /* @__PURE__ */
|
|
5791
|
-
/* @__PURE__ */
|
|
5792
|
-
/* @__PURE__ */
|
|
6141
|
+
] }) : step.kind === "offer" ? /* @__PURE__ */ jsxs33("section", { style: { marginTop: 14 }, "aria-label": "Retention offer", children: [
|
|
6142
|
+
/* @__PURE__ */ jsx34("div", { className: "b316-plan-name", children: step.cancellation.offer.headline ?? "Before you go" }),
|
|
6143
|
+
/* @__PURE__ */ jsx34("p", { className: "b316-muted", children: step.cancellation.offer.message ?? `Stay on ${subscription.planVersion.plan.name} and get ${describeRetentionOffer(
|
|
5793
6144
|
step.cancellation.offer,
|
|
5794
6145
|
step.cancellation.currency
|
|
5795
6146
|
)}.` }),
|
|
5796
|
-
/* @__PURE__ */
|
|
5797
|
-
/* @__PURE__ */
|
|
6147
|
+
/* @__PURE__ */ jsxs33("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
6148
|
+
/* @__PURE__ */ jsx34(
|
|
5798
6149
|
"button",
|
|
5799
6150
|
{
|
|
5800
6151
|
type: "button",
|
|
@@ -5807,7 +6158,7 @@ function SubscriptionManager({
|
|
|
5807
6158
|
children: busy ? "Working\u2026" : "Accept offer and stay"
|
|
5808
6159
|
}
|
|
5809
6160
|
),
|
|
5810
|
-
/* @__PURE__ */
|
|
6161
|
+
/* @__PURE__ */ jsx34(
|
|
5811
6162
|
"button",
|
|
5812
6163
|
{
|
|
5813
6164
|
type: "button",
|
|
@@ -5821,12 +6172,12 @@ function SubscriptionManager({
|
|
|
5821
6172
|
}
|
|
5822
6173
|
)
|
|
5823
6174
|
] }),
|
|
5824
|
-
/* @__PURE__ */
|
|
6175
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5825
6176
|
"If you cancel, you keep access until ",
|
|
5826
6177
|
renews,
|
|
5827
6178
|
"."
|
|
5828
6179
|
] })
|
|
5829
|
-
] }) : step.kind === "survey" ? /* @__PURE__ */
|
|
6180
|
+
] }) : step.kind === "survey" ? /* @__PURE__ */ jsxs33(
|
|
5830
6181
|
"form",
|
|
5831
6182
|
{
|
|
5832
6183
|
style: { marginTop: 14 },
|
|
@@ -5846,15 +6197,15 @@ function SubscriptionManager({
|
|
|
5846
6197
|
}, "Could not cancel. Try again.");
|
|
5847
6198
|
},
|
|
5848
6199
|
children: [
|
|
5849
|
-
/* @__PURE__ */
|
|
6200
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5850
6201
|
"You keep access until ",
|
|
5851
6202
|
renews,
|
|
5852
6203
|
". It will not renew after that."
|
|
5853
6204
|
] }),
|
|
5854
|
-
/* @__PURE__ */
|
|
5855
|
-
/* @__PURE__ */
|
|
5856
|
-
REASONS.map((option) => /* @__PURE__ */
|
|
5857
|
-
/* @__PURE__ */
|
|
6205
|
+
/* @__PURE__ */ jsxs33("fieldset", { className: "b316-fieldset", children: [
|
|
6206
|
+
/* @__PURE__ */ jsx34("legend", { className: "b316-label", children: "Why are you leaving? (optional)" }),
|
|
6207
|
+
REASONS.map((option) => /* @__PURE__ */ jsxs33("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
|
|
6208
|
+
/* @__PURE__ */ jsx34(
|
|
5858
6209
|
"input",
|
|
5859
6210
|
{
|
|
5860
6211
|
type: "radio",
|
|
@@ -5864,12 +6215,12 @@ function SubscriptionManager({
|
|
|
5864
6215
|
onChange: () => setReason(option.value)
|
|
5865
6216
|
}
|
|
5866
6217
|
),
|
|
5867
|
-
/* @__PURE__ */
|
|
6218
|
+
/* @__PURE__ */ jsx34("span", { children: option.label })
|
|
5868
6219
|
] }, option.value))
|
|
5869
6220
|
] }),
|
|
5870
|
-
/* @__PURE__ */
|
|
5871
|
-
/* @__PURE__ */
|
|
5872
|
-
/* @__PURE__ */
|
|
6221
|
+
/* @__PURE__ */ jsxs33("label", { className: "b316-field", children: [
|
|
6222
|
+
/* @__PURE__ */ jsx34("span", { className: "b316-label", children: "Anything else? (optional)" }),
|
|
6223
|
+
/* @__PURE__ */ jsx34(
|
|
5873
6224
|
"textarea",
|
|
5874
6225
|
{
|
|
5875
6226
|
className: "b316-input",
|
|
@@ -5880,9 +6231,9 @@ function SubscriptionManager({
|
|
|
5880
6231
|
}
|
|
5881
6232
|
)
|
|
5882
6233
|
] }),
|
|
5883
|
-
/* @__PURE__ */
|
|
5884
|
-
/* @__PURE__ */
|
|
5885
|
-
/* @__PURE__ */
|
|
6234
|
+
/* @__PURE__ */ jsxs33("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
6235
|
+
/* @__PURE__ */ jsx34("button", { type: "submit", className: "b316-button b316-button-secondary", disabled: busy, children: busy ? "Working\u2026" : "Cancel subscription" }),
|
|
6236
|
+
/* @__PURE__ */ jsxs33(
|
|
5886
6237
|
"button",
|
|
5887
6238
|
{
|
|
5888
6239
|
type: "button",
|
|
@@ -5898,7 +6249,7 @@ function SubscriptionManager({
|
|
|
5898
6249
|
] })
|
|
5899
6250
|
]
|
|
5900
6251
|
}
|
|
5901
|
-
) : /* @__PURE__ */
|
|
6252
|
+
) : /* @__PURE__ */ jsx34("div", { style: { marginTop: 14 }, children: /* @__PURE__ */ jsx34(
|
|
5902
6253
|
"button",
|
|
5903
6254
|
{
|
|
5904
6255
|
type: "button",
|
|
@@ -5916,11 +6267,11 @@ function SubscriptionManager({
|
|
|
5916
6267
|
}
|
|
5917
6268
|
|
|
5918
6269
|
// src/BillingPortal.tsx
|
|
5919
|
-
import { useCallback as useCallback12, useEffect as
|
|
6270
|
+
import { useCallback as useCallback12, useEffect as useEffect27, useState as useState35 } from "react";
|
|
5920
6271
|
|
|
5921
6272
|
// src/CreditBalances.tsx
|
|
5922
|
-
import { useEffect as
|
|
5923
|
-
import { Fragment as
|
|
6273
|
+
import { useEffect as useEffect24, useState as useState32 } from "react";
|
|
6274
|
+
import { Fragment as Fragment11, jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
5924
6275
|
function units(value) {
|
|
5925
6276
|
return value === null ? "Unlimited" : Number(value).toLocaleString("en");
|
|
5926
6277
|
}
|
|
@@ -5955,10 +6306,10 @@ function Feature({
|
|
|
5955
6306
|
}) {
|
|
5956
6307
|
const { client, token } = useBase316();
|
|
5957
6308
|
const setting = feature.autoRecharge;
|
|
5958
|
-
const [busy, setBusy] =
|
|
5959
|
-
const [error, setError] =
|
|
5960
|
-
const [saved, setSaved] =
|
|
5961
|
-
const [pack, setPack] =
|
|
6309
|
+
const [busy, setBusy] = useState32(false);
|
|
6310
|
+
const [error, setError] = useState32(null);
|
|
6311
|
+
const [saved, setSaved] = useState32(null);
|
|
6312
|
+
const [pack, setPack] = useState32(feature.packs[0]?.id ?? "");
|
|
5962
6313
|
const unit = feature.unit ? ` ${feature.unit}` : "";
|
|
5963
6314
|
const warning = status(feature);
|
|
5964
6315
|
const buy = async () => {
|
|
@@ -6012,33 +6363,33 @@ function Feature({
|
|
|
6012
6363
|
setBusy(false);
|
|
6013
6364
|
}
|
|
6014
6365
|
};
|
|
6015
|
-
return /* @__PURE__ */
|
|
6016
|
-
/* @__PURE__ */
|
|
6017
|
-
/* @__PURE__ */
|
|
6018
|
-
/* @__PURE__ */
|
|
6366
|
+
return /* @__PURE__ */ jsxs34("div", { className: "b316-card b316-credit-balance", children: [
|
|
6367
|
+
/* @__PURE__ */ jsx35("div", { className: "b316-label", children: feature.featureName }),
|
|
6368
|
+
/* @__PURE__ */ jsxs34("div", { children: [
|
|
6369
|
+
/* @__PURE__ */ jsx35("strong", { children: units(feature.remaining) }),
|
|
6019
6370
|
unit,
|
|
6020
6371
|
" left"
|
|
6021
6372
|
] }),
|
|
6022
|
-
/* @__PURE__ */
|
|
6373
|
+
/* @__PURE__ */ jsxs34("div", { className: "b316-muted", children: [
|
|
6023
6374
|
feature.allowance === null ? "Unlimited allowance" : `${units(feature.allowanceRemaining)} of ${units(feature.allowance)} included this period`,
|
|
6024
6375
|
" ",
|
|
6025
6376
|
"\xB7 ",
|
|
6026
6377
|
units(feature.purchasedRemaining),
|
|
6027
6378
|
" purchased"
|
|
6028
6379
|
] }),
|
|
6029
|
-
warning && !managed ? /* @__PURE__ */
|
|
6030
|
-
error ? /* @__PURE__ */
|
|
6031
|
-
saved ? /* @__PURE__ */
|
|
6032
|
-
managed || feature.packs.length === 0 ? null : /* @__PURE__ */
|
|
6033
|
-
/* @__PURE__ */
|
|
6034
|
-
/* @__PURE__ */
|
|
6380
|
+
warning && !managed ? /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: warning }) : null,
|
|
6381
|
+
error ? /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6382
|
+
saved ? /* @__PURE__ */ jsx35("div", { className: "b316-notice", role: "status", children: saved }) : null,
|
|
6383
|
+
managed || feature.packs.length === 0 ? null : /* @__PURE__ */ jsxs34(Fragment11, { children: [
|
|
6384
|
+
/* @__PURE__ */ jsxs34("div", { className: "b316-row", style: { marginTop: 12 }, children: [
|
|
6385
|
+
/* @__PURE__ */ jsx35(
|
|
6035
6386
|
"select",
|
|
6036
6387
|
{
|
|
6037
6388
|
className: "b316-input",
|
|
6038
6389
|
"aria-label": "Pack to buy",
|
|
6039
6390
|
value: pack,
|
|
6040
6391
|
onChange: (event) => setPack(event.target.value),
|
|
6041
|
-
children: feature.packs.map((option) => /* @__PURE__ */
|
|
6392
|
+
children: feature.packs.map((option) => /* @__PURE__ */ jsxs34("option", { value: option.id, children: [
|
|
6042
6393
|
option.name,
|
|
6043
6394
|
" \u2014 ",
|
|
6044
6395
|
units(option.units),
|
|
@@ -6047,7 +6398,7 @@ function Feature({
|
|
|
6047
6398
|
] }, option.id))
|
|
6048
6399
|
}
|
|
6049
6400
|
),
|
|
6050
|
-
/* @__PURE__ */
|
|
6401
|
+
/* @__PURE__ */ jsx35(
|
|
6051
6402
|
"button",
|
|
6052
6403
|
{
|
|
6053
6404
|
type: "button",
|
|
@@ -6058,19 +6409,19 @@ function Feature({
|
|
|
6058
6409
|
}
|
|
6059
6410
|
)
|
|
6060
6411
|
] }),
|
|
6061
|
-
/* @__PURE__ */
|
|
6062
|
-
/* @__PURE__ */
|
|
6063
|
-
/* @__PURE__ */
|
|
6412
|
+
/* @__PURE__ */ jsxs34("form", { onSubmit: save, style: { marginTop: 16 }, children: [
|
|
6413
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-checkbox", children: [
|
|
6414
|
+
/* @__PURE__ */ jsx35("input", { type: "checkbox", name: "enabled", defaultChecked: setting?.enabled ?? false }),
|
|
6064
6415
|
" ",
|
|
6065
6416
|
"Buy credits automatically when my balance runs low"
|
|
6066
6417
|
] }),
|
|
6067
|
-
/* @__PURE__ */
|
|
6068
|
-
/* @__PURE__ */
|
|
6418
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6419
|
+
/* @__PURE__ */ jsxs34("span", { className: "b316-label", children: [
|
|
6069
6420
|
"When fewer than this many",
|
|
6070
6421
|
unit,
|
|
6071
6422
|
" are left"
|
|
6072
6423
|
] }),
|
|
6073
|
-
/* @__PURE__ */
|
|
6424
|
+
/* @__PURE__ */ jsx35(
|
|
6074
6425
|
"input",
|
|
6075
6426
|
{
|
|
6076
6427
|
className: "b316-input",
|
|
@@ -6081,21 +6432,21 @@ function Feature({
|
|
|
6081
6432
|
}
|
|
6082
6433
|
)
|
|
6083
6434
|
] }),
|
|
6084
|
-
/* @__PURE__ */
|
|
6085
|
-
/* @__PURE__ */
|
|
6086
|
-
/* @__PURE__ */
|
|
6435
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6436
|
+
/* @__PURE__ */ jsx35("span", { className: "b316-label", children: "Buy" }),
|
|
6437
|
+
/* @__PURE__ */ jsx35(
|
|
6087
6438
|
"select",
|
|
6088
6439
|
{
|
|
6089
6440
|
className: "b316-input",
|
|
6090
6441
|
name: "creditPackId",
|
|
6091
6442
|
defaultValue: setting?.creditPackId ?? feature.packs[0]?.id,
|
|
6092
|
-
children: feature.packs.map((option) => /* @__PURE__ */
|
|
6443
|
+
children: feature.packs.map((option) => /* @__PURE__ */ jsx35("option", { value: option.id, children: option.name }, option.id))
|
|
6093
6444
|
}
|
|
6094
6445
|
)
|
|
6095
6446
|
] }),
|
|
6096
|
-
/* @__PURE__ */
|
|
6097
|
-
/* @__PURE__ */
|
|
6098
|
-
/* @__PURE__ */
|
|
6447
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6448
|
+
/* @__PURE__ */ jsx35("span", { className: "b316-label", children: "At most this many times a month" }),
|
|
6449
|
+
/* @__PURE__ */ jsx35(
|
|
6099
6450
|
"input",
|
|
6100
6451
|
{
|
|
6101
6452
|
className: "b316-input",
|
|
@@ -6105,13 +6456,13 @@ function Feature({
|
|
|
6105
6456
|
}
|
|
6106
6457
|
)
|
|
6107
6458
|
] }),
|
|
6108
|
-
/* @__PURE__ */
|
|
6109
|
-
/* @__PURE__ */
|
|
6459
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6460
|
+
/* @__PURE__ */ jsxs34("span", { className: "b316-label", children: [
|
|
6110
6461
|
"Spending at most (",
|
|
6111
6462
|
setting?.currency ?? feature.packs[0]?.currency ?? "USD",
|
|
6112
6463
|
") a month"
|
|
6113
6464
|
] }),
|
|
6114
|
-
/* @__PURE__ */
|
|
6465
|
+
/* @__PURE__ */ jsx35(
|
|
6115
6466
|
"input",
|
|
6116
6467
|
{
|
|
6117
6468
|
className: "b316-input",
|
|
@@ -6121,16 +6472,16 @@ function Feature({
|
|
|
6121
6472
|
}
|
|
6122
6473
|
)
|
|
6123
6474
|
] }),
|
|
6124
|
-
/* @__PURE__ */
|
|
6475
|
+
/* @__PURE__ */ jsx35("button", { type: "submit", className: "b316-button", disabled: busy, children: "Save auto-recharge" })
|
|
6125
6476
|
] })
|
|
6126
6477
|
] })
|
|
6127
6478
|
] });
|
|
6128
6479
|
}
|
|
6129
6480
|
function CreditBalances({ onChange, className, style }) {
|
|
6130
6481
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6131
|
-
const [state, setState] =
|
|
6132
|
-
const [version, setVersion] =
|
|
6133
|
-
|
|
6482
|
+
const [state, setState] = useState32({ kind: "loading" });
|
|
6483
|
+
const [version, setVersion] = useState32(0);
|
|
6484
|
+
useEffect24(() => {
|
|
6134
6485
|
if (!token) return;
|
|
6135
6486
|
let cancelled = false;
|
|
6136
6487
|
client.billing.credits(token).then((credits2) => {
|
|
@@ -6143,24 +6494,24 @@ function CreditBalances({ onChange, className, style }) {
|
|
|
6143
6494
|
cancelled = true;
|
|
6144
6495
|
};
|
|
6145
6496
|
}, [client, token, version]);
|
|
6146
|
-
const wrap = (content) => /* @__PURE__ */
|
|
6497
|
+
const wrap = (content) => /* @__PURE__ */ jsx35("div", { className: cls("b316-credit-balances", className), style, children: content });
|
|
6147
6498
|
if (sessionLoading || !token || state.kind === "loading") return null;
|
|
6148
6499
|
if (state.kind === "error") {
|
|
6149
6500
|
return wrap(
|
|
6150
|
-
/* @__PURE__ */
|
|
6501
|
+
/* @__PURE__ */ jsx35("div", { className: "b316-card", children: /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: "Could not load your credits." }) })
|
|
6151
6502
|
);
|
|
6152
6503
|
}
|
|
6153
6504
|
const { credits } = state;
|
|
6154
6505
|
if (credits.features.length === 0) return null;
|
|
6155
6506
|
return wrap(
|
|
6156
|
-
/* @__PURE__ */
|
|
6157
|
-
credits.managedBy ? /* @__PURE__ */
|
|
6507
|
+
/* @__PURE__ */ jsxs34(Fragment11, { children: [
|
|
6508
|
+
credits.managedBy ? /* @__PURE__ */ jsxs34("p", { className: "b316-muted", children: [
|
|
6158
6509
|
"Credits for this account come from",
|
|
6159
6510
|
" ",
|
|
6160
6511
|
credits.managedBy.name ?? "the organization that manages it",
|
|
6161
6512
|
", which manages them."
|
|
6162
6513
|
] }) : null,
|
|
6163
|
-
credits.features.map((feature) => /* @__PURE__ */
|
|
6514
|
+
credits.features.map((feature) => /* @__PURE__ */ jsx35(
|
|
6164
6515
|
Feature,
|
|
6165
6516
|
{
|
|
6166
6517
|
feature,
|
|
@@ -6177,19 +6528,19 @@ function CreditBalances({ onChange, className, style }) {
|
|
|
6177
6528
|
}
|
|
6178
6529
|
|
|
6179
6530
|
// src/PaymentMethod.tsx
|
|
6180
|
-
import { useEffect as
|
|
6181
|
-
import { Fragment as
|
|
6531
|
+
import { useEffect as useEffect25, useState as useState33 } from "react";
|
|
6532
|
+
import { Fragment as Fragment12, jsx as jsx36, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
6182
6533
|
function brandName(brand) {
|
|
6183
6534
|
if (!brand) return "Card";
|
|
6184
6535
|
return brand.charAt(0).toUpperCase() + brand.slice(1);
|
|
6185
6536
|
}
|
|
6186
6537
|
function PaymentMethod({ returnUrl, className, style }) {
|
|
6187
6538
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6188
|
-
const [state, setState] =
|
|
6189
|
-
const [busy, setBusy] =
|
|
6190
|
-
const [error, setError] =
|
|
6191
|
-
const [version, setVersion] =
|
|
6192
|
-
|
|
6539
|
+
const [state, setState] = useState33({ kind: "loading" });
|
|
6540
|
+
const [busy, setBusy] = useState33(false);
|
|
6541
|
+
const [error, setError] = useState33(null);
|
|
6542
|
+
const [version, setVersion] = useState33(0);
|
|
6543
|
+
useEffect25(() => {
|
|
6193
6544
|
if (!token) return;
|
|
6194
6545
|
let cancelled = false;
|
|
6195
6546
|
client.billing.paymentMethods(token).then((result) => {
|
|
@@ -6205,7 +6556,7 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6205
6556
|
cancelled = true;
|
|
6206
6557
|
};
|
|
6207
6558
|
}, [client, token, version]);
|
|
6208
|
-
const wrap = (content) => /* @__PURE__ */
|
|
6559
|
+
const wrap = (content) => /* @__PURE__ */ jsx36("div", { className: cls("b316-card b316-payment-method", className), style, children: content });
|
|
6209
6560
|
if (sessionLoading) return wrap("Loading\u2026");
|
|
6210
6561
|
if (!token) return wrap("Sign in to manage your payment method.");
|
|
6211
6562
|
switch (state.kind) {
|
|
@@ -6213,11 +6564,11 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6213
6564
|
return wrap("Loading\u2026");
|
|
6214
6565
|
case "error":
|
|
6215
6566
|
return wrap(
|
|
6216
|
-
/* @__PURE__ */
|
|
6567
|
+
/* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: "Could not load your payment method." })
|
|
6217
6568
|
);
|
|
6218
6569
|
case "managed":
|
|
6219
6570
|
return wrap(
|
|
6220
|
-
/* @__PURE__ */
|
|
6571
|
+
/* @__PURE__ */ jsx36("p", { className: "b316-muted", children: "Your plan is paid for by the organization that manages it." })
|
|
6221
6572
|
);
|
|
6222
6573
|
}
|
|
6223
6574
|
const card = state.cards.find((saved) => saved.isDefault) ?? null;
|
|
@@ -6236,31 +6587,31 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6236
6587
|
}
|
|
6237
6588
|
};
|
|
6238
6589
|
return wrap(
|
|
6239
|
-
/* @__PURE__ */
|
|
6240
|
-
/* @__PURE__ */
|
|
6241
|
-
card ? /* @__PURE__ */
|
|
6242
|
-
/* @__PURE__ */
|
|
6590
|
+
/* @__PURE__ */ jsxs35(Fragment12, { children: [
|
|
6591
|
+
/* @__PURE__ */ jsx36("div", { className: "b316-label", children: "Payment method" }),
|
|
6592
|
+
card ? /* @__PURE__ */ jsxs35("div", { children: [
|
|
6593
|
+
/* @__PURE__ */ jsxs35("div", { children: [
|
|
6243
6594
|
brandName(card.brand),
|
|
6244
6595
|
" ending ",
|
|
6245
6596
|
card.last4 ?? "????"
|
|
6246
6597
|
] }),
|
|
6247
|
-
card.expMonth && card.expYear ? /* @__PURE__ */
|
|
6598
|
+
card.expMonth && card.expYear ? /* @__PURE__ */ jsxs35("div", { className: "b316-muted", children: [
|
|
6248
6599
|
"Expires ",
|
|
6249
6600
|
String(card.expMonth).padStart(2, "0"),
|
|
6250
6601
|
"/",
|
|
6251
6602
|
card.expYear
|
|
6252
6603
|
] }) : null
|
|
6253
|
-
] }) : /* @__PURE__ */
|
|
6254
|
-
others.length > 0 ? /* @__PURE__ */
|
|
6255
|
-
/* @__PURE__ */
|
|
6256
|
-
others.map((saved) => /* @__PURE__ */
|
|
6257
|
-
/* @__PURE__ */
|
|
6604
|
+
] }) : /* @__PURE__ */ jsx36("p", { className: "b316-muted", children: "No card on file." }),
|
|
6605
|
+
others.length > 0 ? /* @__PURE__ */ jsxs35("div", { style: { marginTop: 12 }, children: [
|
|
6606
|
+
/* @__PURE__ */ jsx36("div", { className: "b316-label", children: "Other saved cards" }),
|
|
6607
|
+
others.map((saved) => /* @__PURE__ */ jsxs35("div", { className: "b316-row", style: { marginTop: 6 }, children: [
|
|
6608
|
+
/* @__PURE__ */ jsxs35("span", { children: [
|
|
6258
6609
|
brandName(saved.brand),
|
|
6259
6610
|
" ending ",
|
|
6260
6611
|
saved.last4 ?? "????"
|
|
6261
6612
|
] }),
|
|
6262
|
-
/* @__PURE__ */
|
|
6263
|
-
/* @__PURE__ */
|
|
6613
|
+
/* @__PURE__ */ jsxs35("span", { children: [
|
|
6614
|
+
/* @__PURE__ */ jsx36(
|
|
6264
6615
|
"button",
|
|
6265
6616
|
{
|
|
6266
6617
|
type: "button",
|
|
@@ -6274,7 +6625,7 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6274
6625
|
}
|
|
6275
6626
|
),
|
|
6276
6627
|
" ",
|
|
6277
|
-
/* @__PURE__ */
|
|
6628
|
+
/* @__PURE__ */ jsx36(
|
|
6278
6629
|
"button",
|
|
6279
6630
|
{
|
|
6280
6631
|
type: "button",
|
|
@@ -6290,8 +6641,8 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6290
6641
|
] })
|
|
6291
6642
|
] }, saved.id))
|
|
6292
6643
|
] }) : null,
|
|
6293
|
-
error ? /* @__PURE__ */
|
|
6294
|
-
/* @__PURE__ */
|
|
6644
|
+
error ? /* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6645
|
+
/* @__PURE__ */ jsx36(
|
|
6295
6646
|
"button",
|
|
6296
6647
|
{
|
|
6297
6648
|
type: "button",
|
|
@@ -6320,8 +6671,8 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6320
6671
|
}
|
|
6321
6672
|
|
|
6322
6673
|
// src/PlanChangeReview.tsx
|
|
6323
|
-
import { useCallback as useCallback11, useEffect as
|
|
6324
|
-
import { Fragment as
|
|
6674
|
+
import { useCallback as useCallback11, useEffect as useEffect26, useState as useState34 } from "react";
|
|
6675
|
+
import { Fragment as Fragment13, jsx as jsx37, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
6325
6676
|
function money5(amount, currency) {
|
|
6326
6677
|
if (amount === null) return "\u2014";
|
|
6327
6678
|
const value = Number(amount);
|
|
@@ -6354,12 +6705,12 @@ function PlanChangeReview({
|
|
|
6354
6705
|
style
|
|
6355
6706
|
}) {
|
|
6356
6707
|
const { client, token } = useBase316();
|
|
6357
|
-
const [timing, setTiming] =
|
|
6358
|
-
const [preview, setPreview] =
|
|
6359
|
-
const [error, setError] =
|
|
6360
|
-
const [needsCard, setNeedsCard] =
|
|
6361
|
-
const [busy, setBusy] =
|
|
6362
|
-
|
|
6708
|
+
const [timing, setTiming] = useState34(void 0);
|
|
6709
|
+
const [preview, setPreview] = useState34(null);
|
|
6710
|
+
const [error, setError] = useState34(null);
|
|
6711
|
+
const [needsCard, setNeedsCard] = useState34(false);
|
|
6712
|
+
const [busy, setBusy] = useState34(false);
|
|
6713
|
+
useEffect26(() => {
|
|
6363
6714
|
if (!token) return;
|
|
6364
6715
|
let cancelled = false;
|
|
6365
6716
|
client.billing.previewPlanChange(token, planVersionId, timing).then((result) => {
|
|
@@ -6411,12 +6762,12 @@ function PlanChangeReview({
|
|
|
6411
6762
|
setError("Cards cannot be added here right now.");
|
|
6412
6763
|
}
|
|
6413
6764
|
}, [client, token, onNeedsCard]);
|
|
6414
|
-
const card = (content) => /* @__PURE__ */
|
|
6765
|
+
const card = (content) => /* @__PURE__ */ jsx37("div", { className: cls("b316-card b316-plan-review", className), style, children: content });
|
|
6415
6766
|
if (error && !preview) {
|
|
6416
6767
|
return card(
|
|
6417
|
-
/* @__PURE__ */
|
|
6418
|
-
/* @__PURE__ */
|
|
6419
|
-
onCancel ? /* @__PURE__ */
|
|
6768
|
+
/* @__PURE__ */ jsxs36(Fragment13, { children: [
|
|
6769
|
+
/* @__PURE__ */ jsx37("div", { className: "b316-error", role: "alert", children: error }),
|
|
6770
|
+
onCancel ? /* @__PURE__ */ jsx37("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: "Back" }) : null
|
|
6420
6771
|
] })
|
|
6421
6772
|
);
|
|
6422
6773
|
}
|
|
@@ -6429,26 +6780,26 @@ function PlanChangeReview({
|
|
|
6429
6780
|
const otherReason = preview.timings[other]?.reason ?? null;
|
|
6430
6781
|
const changes = preview.entitlements.filter((change) => change.change !== "UNCHANGED");
|
|
6431
6782
|
return card(
|
|
6432
|
-
/* @__PURE__ */
|
|
6433
|
-
/* @__PURE__ */
|
|
6783
|
+
/* @__PURE__ */ jsxs36(Fragment13, { children: [
|
|
6784
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-plan-name", children: [
|
|
6434
6785
|
"Change to ",
|
|
6435
6786
|
to.planName
|
|
6436
6787
|
] }),
|
|
6437
|
-
/* @__PURE__ */
|
|
6788
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-muted", children: [
|
|
6438
6789
|
"From ",
|
|
6439
6790
|
from.planName
|
|
6440
6791
|
] }),
|
|
6441
|
-
error ? /* @__PURE__ */
|
|
6442
|
-
changes.length === 0 ? /* @__PURE__ */
|
|
6443
|
-
/* @__PURE__ */
|
|
6444
|
-
/* @__PURE__ */
|
|
6445
|
-
/* @__PURE__ */
|
|
6446
|
-
/* @__PURE__ */
|
|
6792
|
+
error ? /* @__PURE__ */ jsx37("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6793
|
+
changes.length === 0 ? /* @__PURE__ */ jsx37("p", { className: "b316-muted", children: "Every feature stays the same." }) : /* @__PURE__ */ jsxs36("table", { className: "b316-review-table", children: [
|
|
6794
|
+
/* @__PURE__ */ jsx37("thead", { children: /* @__PURE__ */ jsxs36("tr", { children: [
|
|
6795
|
+
/* @__PURE__ */ jsx37("th", { children: "Feature" }),
|
|
6796
|
+
/* @__PURE__ */ jsx37("th", { children: from.planName }),
|
|
6797
|
+
/* @__PURE__ */ jsx37("th", { children: to.planName })
|
|
6447
6798
|
] }) }),
|
|
6448
|
-
/* @__PURE__ */
|
|
6449
|
-
/* @__PURE__ */
|
|
6450
|
-
/* @__PURE__ */
|
|
6451
|
-
/* @__PURE__ */
|
|
6799
|
+
/* @__PURE__ */ jsx37("tbody", { children: changes.map((change) => /* @__PURE__ */ jsxs36("tr", { children: [
|
|
6800
|
+
/* @__PURE__ */ jsx37("td", { children: change.featureName }),
|
|
6801
|
+
/* @__PURE__ */ jsx37("td", { children: limitText(change.before, change.type) }),
|
|
6802
|
+
/* @__PURE__ */ jsx37(
|
|
6452
6803
|
"td",
|
|
6453
6804
|
{
|
|
6454
6805
|
className: change.change === "GAINED" || change.change === "INCREASED" ? "b316-review-gain" : "b316-review-loss",
|
|
@@ -6457,40 +6808,40 @@ function PlanChangeReview({
|
|
|
6457
6808
|
)
|
|
6458
6809
|
] }, change.featureId)) })
|
|
6459
6810
|
] }),
|
|
6460
|
-
preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */
|
|
6811
|
+
preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */ jsxs36("p", { children: [
|
|
6461
6812
|
"The change happens now. Your trial carries on until ",
|
|
6462
6813
|
day4(now.trialEndsAt),
|
|
6463
6814
|
", and nothing is charged before then."
|
|
6464
|
-
] }) : /* @__PURE__ */
|
|
6465
|
-
Number(now.credit) > 0 ? /* @__PURE__ */
|
|
6466
|
-
/* @__PURE__ */
|
|
6815
|
+
] }) : /* @__PURE__ */ jsxs36("div", { children: [
|
|
6816
|
+
Number(now.credit) > 0 ? /* @__PURE__ */ jsxs36("div", { className: "b316-row", children: [
|
|
6817
|
+
/* @__PURE__ */ jsxs36("span", { className: "b316-muted", children: [
|
|
6467
6818
|
"Credit for the unused part of ",
|
|
6468
6819
|
from.planName
|
|
6469
6820
|
] }),
|
|
6470
|
-
/* @__PURE__ */
|
|
6821
|
+
/* @__PURE__ */ jsxs36("span", { className: "b316-num", children: [
|
|
6471
6822
|
"\u2212",
|
|
6472
6823
|
money5(now.credit, from.currency)
|
|
6473
6824
|
] })
|
|
6474
6825
|
] }) : null,
|
|
6475
|
-
Number(now.closingUsage) > 0 ? /* @__PURE__ */
|
|
6476
|
-
/* @__PURE__ */
|
|
6477
|
-
/* @__PURE__ */
|
|
6826
|
+
Number(now.closingUsage) > 0 ? /* @__PURE__ */ jsxs36("div", { className: "b316-row", children: [
|
|
6827
|
+
/* @__PURE__ */ jsx37("span", { className: "b316-muted", children: "Usage so far this period" }),
|
|
6828
|
+
/* @__PURE__ */ jsx37("span", { className: "b316-num", children: money5(now.closingUsage, from.currency) })
|
|
6478
6829
|
] }) : null,
|
|
6479
|
-
/* @__PURE__ */
|
|
6480
|
-
/* @__PURE__ */
|
|
6830
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-row", children: [
|
|
6831
|
+
/* @__PURE__ */ jsxs36("span", { className: "b316-muted", children: [
|
|
6481
6832
|
to.planName,
|
|
6482
6833
|
", ",
|
|
6483
6834
|
day4(now.newPeriod.start),
|
|
6484
6835
|
" \u2013 ",
|
|
6485
6836
|
day4(now.newPeriod.end)
|
|
6486
6837
|
] }),
|
|
6487
|
-
/* @__PURE__ */
|
|
6838
|
+
/* @__PURE__ */ jsx37("span", { className: "b316-num", children: money5(now.newPeriodCharge, to.currency) })
|
|
6488
6839
|
] }),
|
|
6489
|
-
now.net !== null ? /* @__PURE__ */
|
|
6490
|
-
/* @__PURE__ */
|
|
6491
|
-
/* @__PURE__ */
|
|
6840
|
+
now.net !== null ? /* @__PURE__ */ jsxs36("div", { className: "b316-row b316-invoice-total", children: [
|
|
6841
|
+
/* @__PURE__ */ jsx37("span", { children: "Due now" }),
|
|
6842
|
+
/* @__PURE__ */ jsx37("span", { className: "b316-num", children: money5(now.net, to.currency) })
|
|
6492
6843
|
] }) : null
|
|
6493
|
-
] }) : /* @__PURE__ */
|
|
6844
|
+
] }) : /* @__PURE__ */ jsxs36("p", { children: [
|
|
6494
6845
|
"You keep ",
|
|
6495
6846
|
from.planName,
|
|
6496
6847
|
" until ",
|
|
@@ -6503,7 +6854,7 @@ function PlanChangeReview({
|
|
|
6503
6854
|
preview.atPeriodEnd.nextInvoice.currency
|
|
6504
6855
|
)}.` : ""
|
|
6505
6856
|
] }),
|
|
6506
|
-
otherOpen ? /* @__PURE__ */
|
|
6857
|
+
otherOpen ? /* @__PURE__ */ jsx37(
|
|
6507
6858
|
"button",
|
|
6508
6859
|
{
|
|
6509
6860
|
type: "button",
|
|
@@ -6514,12 +6865,12 @@ function PlanChangeReview({
|
|
|
6514
6865
|
},
|
|
6515
6866
|
children: other === "NOW" ? "Change now instead" : "Wait until the end of the period instead"
|
|
6516
6867
|
}
|
|
6517
|
-
) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */
|
|
6518
|
-
needsCard ? /* @__PURE__ */
|
|
6868
|
+
) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */ jsx37("p", { className: "b316-muted", children: TIMING_CLOSED[otherReason] }) : null,
|
|
6869
|
+
needsCard ? /* @__PURE__ */ jsxs36("div", { className: "b316-notice", role: "status", children: [
|
|
6519
6870
|
"A card is needed for a change that is charged now.",
|
|
6520
|
-
/* @__PURE__ */
|
|
6521
|
-
] }) : /* @__PURE__ */
|
|
6522
|
-
/* @__PURE__ */
|
|
6871
|
+
/* @__PURE__ */ jsx37("div", { className: "b316-review-actions", children: /* @__PURE__ */ jsx37("button", { type: "button", className: "b316-button", onClick: () => void addCard(), children: "Add a card" }) })
|
|
6872
|
+
] }) : /* @__PURE__ */ jsxs36("div", { className: "b316-review-actions", children: [
|
|
6873
|
+
/* @__PURE__ */ jsx37(
|
|
6523
6874
|
"button",
|
|
6524
6875
|
{
|
|
6525
6876
|
type: "button",
|
|
@@ -6529,7 +6880,7 @@ function PlanChangeReview({
|
|
|
6529
6880
|
children: busy ? "Working\u2026" : preview.timing === "NOW" ? `Change to ${to.planName} now` : `Schedule ${to.planName}`
|
|
6530
6881
|
}
|
|
6531
6882
|
),
|
|
6532
|
-
onCancel ? /* @__PURE__ */
|
|
6883
|
+
onCancel ? /* @__PURE__ */ jsxs36("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: [
|
|
6533
6884
|
"Keep ",
|
|
6534
6885
|
from.planName
|
|
6535
6886
|
] }) : null
|
|
@@ -6539,7 +6890,7 @@ function PlanChangeReview({
|
|
|
6539
6890
|
}
|
|
6540
6891
|
|
|
6541
6892
|
// src/BillingPortal.tsx
|
|
6542
|
-
import { Fragment as
|
|
6893
|
+
import { Fragment as Fragment14, jsx as jsx38, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
6543
6894
|
function BillingPortal({
|
|
6544
6895
|
returnUrl,
|
|
6545
6896
|
featuredPlanKey,
|
|
@@ -6549,12 +6900,12 @@ function BillingPortal({
|
|
|
6549
6900
|
style
|
|
6550
6901
|
}) {
|
|
6551
6902
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6552
|
-
const [overview, setOverview] =
|
|
6553
|
-
const [failed, setFailed] =
|
|
6554
|
-
const [version, setVersion] =
|
|
6555
|
-
const [reviewing, setReviewing] =
|
|
6556
|
-
const [notice, setNotice] =
|
|
6557
|
-
|
|
6903
|
+
const [overview, setOverview] = useState35(null);
|
|
6904
|
+
const [failed, setFailed] = useState35(false);
|
|
6905
|
+
const [version, setVersion] = useState35(0);
|
|
6906
|
+
const [reviewing, setReviewing] = useState35(null);
|
|
6907
|
+
const [notice, setNotice] = useState35(null);
|
|
6908
|
+
useEffect27(() => {
|
|
6558
6909
|
if (!token) return;
|
|
6559
6910
|
let cancelled = false;
|
|
6560
6911
|
client.billing.subscription(token).then((result) => {
|
|
@@ -6577,24 +6928,24 @@ function BillingPortal({
|
|
|
6577
6928
|
setNotice(null);
|
|
6578
6929
|
setVersion((value) => value + 1);
|
|
6579
6930
|
}, []);
|
|
6580
|
-
const shell = (content) => /* @__PURE__ */
|
|
6581
|
-
if (sessionLoading) return shell(/* @__PURE__ */
|
|
6582
|
-
if (!token) return shell(/* @__PURE__ */
|
|
6931
|
+
const shell = (content) => /* @__PURE__ */ jsx38("div", { className: cls("b316-billing-portal", className), style, children: content });
|
|
6932
|
+
if (sessionLoading) return shell(/* @__PURE__ */ jsx38("div", { className: "b316-card", children: "Loading\u2026" }));
|
|
6933
|
+
if (!token) return shell(/* @__PURE__ */ jsx38("div", { className: "b316-card", children: "Sign in to manage your billing." }));
|
|
6583
6934
|
if (failed) {
|
|
6584
6935
|
return shell(
|
|
6585
|
-
/* @__PURE__ */
|
|
6936
|
+
/* @__PURE__ */ jsx38("div", { className: "b316-card", children: /* @__PURE__ */ jsx38("div", { className: "b316-error", role: "alert", children: "Could not load your billing." }) })
|
|
6586
6937
|
);
|
|
6587
6938
|
}
|
|
6588
|
-
if (!overview) return shell(/* @__PURE__ */
|
|
6939
|
+
if (!overview) return shell(/* @__PURE__ */ jsx38("div", { className: "b316-card", children: "Loading\u2026" }));
|
|
6589
6940
|
const { subscription, managedBy, quantityPriced } = overview;
|
|
6590
6941
|
const canChange = Boolean(subscription) && !managedBy;
|
|
6591
6942
|
return shell(
|
|
6592
|
-
/* @__PURE__ */
|
|
6593
|
-
notice ? /* @__PURE__ */
|
|
6594
|
-
/* @__PURE__ */
|
|
6595
|
-
canChange ? /* @__PURE__ */
|
|
6596
|
-
canChange && quantityPriced ? /* @__PURE__ */
|
|
6597
|
-
reviewing ? /* @__PURE__ */
|
|
6943
|
+
/* @__PURE__ */ jsxs37(Fragment14, { children: [
|
|
6944
|
+
notice ? /* @__PURE__ */ jsx38("div", { className: "b316-card b316-notice", role: "status", children: notice }) : null,
|
|
6945
|
+
/* @__PURE__ */ jsx38(SubscriptionManager, { onChange: refresh }, `plan-${version}`),
|
|
6946
|
+
canChange ? /* @__PURE__ */ jsx38(UpcomingInvoice, {}, `next-${version}`) : null,
|
|
6947
|
+
canChange && quantityPriced ? /* @__PURE__ */ jsx38(SeatManager, { unitLabel, onChange: refresh }, `seats-${version}`) : null,
|
|
6948
|
+
reviewing ? /* @__PURE__ */ jsx38(
|
|
6598
6949
|
PlanChangeReview,
|
|
6599
6950
|
{
|
|
6600
6951
|
planVersionId: reviewing,
|
|
@@ -6607,9 +6958,9 @@ function BillingPortal({
|
|
|
6607
6958
|
);
|
|
6608
6959
|
}
|
|
6609
6960
|
}
|
|
6610
|
-
) : /* @__PURE__ */
|
|
6611
|
-
/* @__PURE__ */
|
|
6612
|
-
/* @__PURE__ */
|
|
6961
|
+
) : /* @__PURE__ */ jsxs37("section", { children: [
|
|
6962
|
+
/* @__PURE__ */ jsx38("h2", { className: "b316-billing-portal-section-title", children: subscription ? "Change plan" : "Choose a plan" }),
|
|
6963
|
+
/* @__PURE__ */ jsx38(
|
|
6613
6964
|
PricingTable,
|
|
6614
6965
|
{
|
|
6615
6966
|
featuredPlanKey,
|
|
@@ -6621,17 +6972,17 @@ function BillingPortal({
|
|
|
6621
6972
|
`plans-${version}`
|
|
6622
6973
|
)
|
|
6623
6974
|
] }),
|
|
6624
|
-
/* @__PURE__ */
|
|
6625
|
-
managedBy ? null : /* @__PURE__ */
|
|
6626
|
-
/* @__PURE__ */
|
|
6627
|
-
billingDetails === void 0 ? /* @__PURE__ */
|
|
6975
|
+
/* @__PURE__ */ jsx38(CreditBalances, {}, `credits-${version}`),
|
|
6976
|
+
managedBy ? null : /* @__PURE__ */ jsx38(PaymentMethod, { returnUrl }, `card-${version}`),
|
|
6977
|
+
/* @__PURE__ */ jsx38(Invoices, {}, `invoices-${version}`),
|
|
6978
|
+
billingDetails === void 0 ? /* @__PURE__ */ jsx38(BillingDetailsForm, {}, `details-${version}`) : billingDetails
|
|
6628
6979
|
] })
|
|
6629
6980
|
);
|
|
6630
6981
|
}
|
|
6631
6982
|
|
|
6632
6983
|
// src/ApiKeyManager.tsx
|
|
6633
|
-
import { useCallback as useCallback13, useEffect as
|
|
6634
|
-
import { jsx as
|
|
6984
|
+
import { useCallback as useCallback13, useEffect as useEffect28, useState as useState36 } from "react";
|
|
6985
|
+
import { jsx as jsx39, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
6635
6986
|
function duration(seconds) {
|
|
6636
6987
|
if (seconds % 3600 === 0) {
|
|
6637
6988
|
return `${seconds / 3600}h`;
|
|
@@ -6648,16 +6999,16 @@ function ApiKeyManager({
|
|
|
6648
6999
|
audience
|
|
6649
7000
|
}) {
|
|
6650
7001
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6651
|
-
const [resources, setResources] =
|
|
6652
|
-
const [credentials, setCredentials] =
|
|
6653
|
-
const [loading, setLoading] =
|
|
6654
|
-
const [busy, setBusy] =
|
|
6655
|
-
const [error, setError] =
|
|
6656
|
-
const [creating, setCreating] =
|
|
6657
|
-
const [name, setName] =
|
|
6658
|
-
const [chosen, setChosen] =
|
|
6659
|
-
const [resourceId, setResourceId] =
|
|
6660
|
-
const [issued, setIssued] =
|
|
7002
|
+
const [resources, setResources] = useState36([]);
|
|
7003
|
+
const [credentials, setCredentials] = useState36([]);
|
|
7004
|
+
const [loading, setLoading] = useState36(true);
|
|
7005
|
+
const [busy, setBusy] = useState36(false);
|
|
7006
|
+
const [error, setError] = useState36(null);
|
|
7007
|
+
const [creating, setCreating] = useState36(false);
|
|
7008
|
+
const [name, setName] = useState36("");
|
|
7009
|
+
const [chosen, setChosen] = useState36([]);
|
|
7010
|
+
const [resourceId, setResourceId] = useState36(null);
|
|
7011
|
+
const [issued, setIssued] = useState36(null);
|
|
6661
7012
|
const load = useCallback13(async () => {
|
|
6662
7013
|
if (!token) {
|
|
6663
7014
|
setLoading(false);
|
|
@@ -6679,20 +7030,20 @@ function ApiKeyManager({
|
|
|
6679
7030
|
setLoading(false);
|
|
6680
7031
|
}
|
|
6681
7032
|
}, [client, token, audience]);
|
|
6682
|
-
|
|
7033
|
+
useEffect28(() => {
|
|
6683
7034
|
void load();
|
|
6684
7035
|
}, [load]);
|
|
6685
7036
|
if (sessionLoading || loading) {
|
|
6686
|
-
return /* @__PURE__ */
|
|
7037
|
+
return /* @__PURE__ */ jsx39("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
6687
7038
|
}
|
|
6688
7039
|
if (!token) {
|
|
6689
|
-
return /* @__PURE__ */
|
|
7040
|
+
return /* @__PURE__ */ jsx39("div", { className: cls("b316-card", className), style, children: "Sign in to manage your API keys." });
|
|
6690
7041
|
}
|
|
6691
7042
|
if (error) {
|
|
6692
|
-
return /* @__PURE__ */
|
|
7043
|
+
return /* @__PURE__ */ jsx39("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx39("div", { className: "b316-error", role: "alert", children: error }) });
|
|
6693
7044
|
}
|
|
6694
7045
|
if (resources.length === 0) {
|
|
6695
|
-
return /* @__PURE__ */
|
|
7046
|
+
return /* @__PURE__ */ jsx39("div", { className: cls("b316-card", className), style, children: "There are no APIs available to your account." });
|
|
6696
7047
|
}
|
|
6697
7048
|
const resource = resources.find((item) => item.id === resourceId) ?? resources[0];
|
|
6698
7049
|
const reset = () => {
|
|
@@ -6701,37 +7052,37 @@ function ApiKeyManager({
|
|
|
6701
7052
|
setChosen([]);
|
|
6702
7053
|
setIssued(null);
|
|
6703
7054
|
};
|
|
6704
|
-
return /* @__PURE__ */
|
|
6705
|
-
error ? /* @__PURE__ */
|
|
6706
|
-
resources.length > 1 ? /* @__PURE__ */
|
|
7055
|
+
return /* @__PURE__ */ jsxs38("div", { className: cls("b316-card", className), style, children: [
|
|
7056
|
+
error ? /* @__PURE__ */ jsx39("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
7057
|
+
resources.length > 1 ? /* @__PURE__ */ jsx39(
|
|
6707
7058
|
"select",
|
|
6708
7059
|
{
|
|
6709
7060
|
className: "b316-input",
|
|
6710
7061
|
value: resource.id,
|
|
6711
7062
|
onChange: (event) => setResourceId(event.target.value),
|
|
6712
7063
|
style: { marginBottom: 14 },
|
|
6713
|
-
children: resources.map((item) => /* @__PURE__ */
|
|
7064
|
+
children: resources.map((item) => /* @__PURE__ */ jsx39("option", { value: item.id, children: item.name }, item.id))
|
|
6714
7065
|
}
|
|
6715
|
-
) : /* @__PURE__ */
|
|
6716
|
-
resource.rateLimit ? /* @__PURE__ */
|
|
7066
|
+
) : /* @__PURE__ */ jsx39("div", { className: "b316-plan-name", children: resource.name }),
|
|
7067
|
+
resource.rateLimit ? /* @__PURE__ */ jsxs38("div", { className: "b316-muted", children: [
|
|
6717
7068
|
resource.rateLimit.requestsPerWindow,
|
|
6718
7069
|
" requests per",
|
|
6719
7070
|
" ",
|
|
6720
7071
|
duration(resource.rateLimit.windowSeconds),
|
|
6721
7072
|
resource.rateLimit.burst > resource.rateLimit.requestsPerWindow ? `, bursting to ${resource.rateLimit.burst}` : null
|
|
6722
|
-
] }) : /* @__PURE__ */
|
|
6723
|
-
credentials.length === 0 ? /* @__PURE__ */
|
|
6724
|
-
/* @__PURE__ */
|
|
6725
|
-
/* @__PURE__ */
|
|
6726
|
-
/* @__PURE__ */
|
|
6727
|
-
/* @__PURE__ */
|
|
7073
|
+
] }) : /* @__PURE__ */ jsx39("div", { className: "b316-muted", children: "No rate limit." }),
|
|
7074
|
+
credentials.length === 0 ? /* @__PURE__ */ jsx39("p", { className: "b316-muted", style: { marginTop: 14 }, children: "You have no API keys yet." }) : /* @__PURE__ */ jsx39("ul", { className: "b316-list", style: { marginTop: 14 }, children: credentials.map((credential) => /* @__PURE__ */ jsxs38("li", { className: "b316-list-item", children: [
|
|
7075
|
+
/* @__PURE__ */ jsxs38("div", { children: [
|
|
7076
|
+
/* @__PURE__ */ jsx39("div", { className: "b316-plan-name", children: credential.name }),
|
|
7077
|
+
/* @__PURE__ */ jsxs38("div", { className: "b316-muted", children: [
|
|
7078
|
+
/* @__PURE__ */ jsx39("code", { children: credential.clientId }),
|
|
6728
7079
|
credential.secretLastFour ? ` \xB7 \u2026${credential.secretLastFour}` : null,
|
|
6729
7080
|
credential.disabled ? " \xB7 Disabled" : null
|
|
6730
7081
|
] }),
|
|
6731
|
-
/* @__PURE__ */
|
|
7082
|
+
/* @__PURE__ */ jsx39("div", { className: "b316-muted", children: credential.scopes.join(", ") })
|
|
6732
7083
|
] }),
|
|
6733
|
-
/* @__PURE__ */
|
|
6734
|
-
/* @__PURE__ */
|
|
7084
|
+
/* @__PURE__ */ jsxs38("div", { style: { display: "flex", gap: 8 }, children: [
|
|
7085
|
+
/* @__PURE__ */ jsx39(
|
|
6735
7086
|
"button",
|
|
6736
7087
|
{
|
|
6737
7088
|
type: "button",
|
|
@@ -6760,7 +7111,7 @@ function ApiKeyManager({
|
|
|
6760
7111
|
children: "Rotate"
|
|
6761
7112
|
}
|
|
6762
7113
|
),
|
|
6763
|
-
/* @__PURE__ */
|
|
7114
|
+
/* @__PURE__ */ jsx39(
|
|
6764
7115
|
ConfirmButton,
|
|
6765
7116
|
{
|
|
6766
7117
|
className: "b316-button b316-button-secondary",
|
|
@@ -6784,11 +7135,11 @@ function ApiKeyManager({
|
|
|
6784
7135
|
)
|
|
6785
7136
|
] })
|
|
6786
7137
|
] }, credential.clientId)) }),
|
|
6787
|
-
issued ? /* @__PURE__ */
|
|
6788
|
-
/* @__PURE__ */
|
|
7138
|
+
issued ? /* @__PURE__ */ jsxs38("div", { className: "b316-notice", style: { marginTop: 14 }, children: [
|
|
7139
|
+
/* @__PURE__ */ jsx39("strong", { children: "Copy this now." }),
|
|
6789
7140
|
" It is shown once and cannot be retrieved again.",
|
|
6790
|
-
/* @__PURE__ */
|
|
6791
|
-
/* @__PURE__ */
|
|
7141
|
+
/* @__PURE__ */ jsx39("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx39("code", { style: { wordBreak: "break-all" }, children: issued.secret }) }),
|
|
7142
|
+
/* @__PURE__ */ jsx39(
|
|
6792
7143
|
"button",
|
|
6793
7144
|
{
|
|
6794
7145
|
type: "button",
|
|
@@ -6801,7 +7152,7 @@ function ApiKeyManager({
|
|
|
6801
7152
|
children: "Copy"
|
|
6802
7153
|
}
|
|
6803
7154
|
),
|
|
6804
|
-
/* @__PURE__ */
|
|
7155
|
+
/* @__PURE__ */ jsx39(
|
|
6805
7156
|
"button",
|
|
6806
7157
|
{
|
|
6807
7158
|
type: "button",
|
|
@@ -6812,8 +7163,8 @@ function ApiKeyManager({
|
|
|
6812
7163
|
}
|
|
6813
7164
|
)
|
|
6814
7165
|
] }) : null,
|
|
6815
|
-
creating && !issued ? /* @__PURE__ */
|
|
6816
|
-
/* @__PURE__ */
|
|
7166
|
+
creating && !issued ? /* @__PURE__ */ jsxs38("div", { style: { marginTop: 14 }, children: [
|
|
7167
|
+
/* @__PURE__ */ jsx39(
|
|
6817
7168
|
"input",
|
|
6818
7169
|
{
|
|
6819
7170
|
className: "b316-input",
|
|
@@ -6822,9 +7173,9 @@ function ApiKeyManager({
|
|
|
6822
7173
|
onChange: (event) => setName(event.target.value)
|
|
6823
7174
|
}
|
|
6824
7175
|
),
|
|
6825
|
-
/* @__PURE__ */
|
|
6826
|
-
resource.availableScopes.map((scope) => /* @__PURE__ */
|
|
6827
|
-
/* @__PURE__ */
|
|
7176
|
+
/* @__PURE__ */ jsxs38("div", { style: { marginTop: 10 }, children: [
|
|
7177
|
+
resource.availableScopes.map((scope) => /* @__PURE__ */ jsxs38("label", { className: "b316-checkbox", children: [
|
|
7178
|
+
/* @__PURE__ */ jsx39(
|
|
6828
7179
|
"input",
|
|
6829
7180
|
{
|
|
6830
7181
|
type: "checkbox",
|
|
@@ -6834,19 +7185,19 @@ function ApiKeyManager({
|
|
|
6834
7185
|
)
|
|
6835
7186
|
}
|
|
6836
7187
|
),
|
|
6837
|
-
/* @__PURE__ */
|
|
6838
|
-
scope.description ? /* @__PURE__ */
|
|
7188
|
+
/* @__PURE__ */ jsx39("code", { children: scope.key }),
|
|
7189
|
+
scope.description ? /* @__PURE__ */ jsxs38("span", { className: "b316-muted", children: [
|
|
6839
7190
|
" \u2014 ",
|
|
6840
7191
|
scope.description
|
|
6841
7192
|
] }) : null
|
|
6842
7193
|
] }, scope.key)),
|
|
6843
|
-
resource.lockedScopes.map((scope) => /* @__PURE__ */
|
|
6844
|
-
/* @__PURE__ */
|
|
6845
|
-
/* @__PURE__ */
|
|
6846
|
-
/* @__PURE__ */
|
|
7194
|
+
resource.lockedScopes.map((scope) => /* @__PURE__ */ jsxs38("label", { className: "b316-checkbox b316-muted", children: [
|
|
7195
|
+
/* @__PURE__ */ jsx39("input", { type: "checkbox", disabled: true }),
|
|
7196
|
+
/* @__PURE__ */ jsx39("code", { children: scope.key }),
|
|
7197
|
+
/* @__PURE__ */ jsx39("span", { children: " \u2014 not included in your plan" })
|
|
6847
7198
|
] }, scope.key))
|
|
6848
7199
|
] }),
|
|
6849
|
-
/* @__PURE__ */
|
|
7200
|
+
/* @__PURE__ */ jsx39(
|
|
6850
7201
|
"button",
|
|
6851
7202
|
{
|
|
6852
7203
|
type: "button",
|
|
@@ -6880,7 +7231,7 @@ function ApiKeyManager({
|
|
|
6880
7231
|
children: "Create key"
|
|
6881
7232
|
}
|
|
6882
7233
|
),
|
|
6883
|
-
/* @__PURE__ */
|
|
7234
|
+
/* @__PURE__ */ jsx39(
|
|
6884
7235
|
"button",
|
|
6885
7236
|
{
|
|
6886
7237
|
type: "button",
|
|
@@ -6891,7 +7242,7 @@ function ApiKeyManager({
|
|
|
6891
7242
|
}
|
|
6892
7243
|
)
|
|
6893
7244
|
] }) : null,
|
|
6894
|
-
!creating && !issued ? /* @__PURE__ */
|
|
7245
|
+
!creating && !issued ? /* @__PURE__ */ jsx39(
|
|
6895
7246
|
"button",
|
|
6896
7247
|
{
|
|
6897
7248
|
type: "button",
|
|
@@ -6966,26 +7317,45 @@ var MANIFEST = [
|
|
|
6966
7317
|
{
|
|
6967
7318
|
name: "SignIn",
|
|
6968
7319
|
kind: "component",
|
|
6969
|
-
summary: "
|
|
7320
|
+
summary: "Sign in the ways the environment offers \u2014 password, magic link, passkeys, text message, social providers and SSO, as switched on in the dashboard (`GET /v1/auth/methods`).",
|
|
6970
7321
|
useWhen: "The application renders its own sign-in rather than redirecting to the hosted page.",
|
|
6971
7322
|
requires: [],
|
|
6972
7323
|
props: [
|
|
6973
7324
|
{ name: "onSignedIn", summary: "Called once a session exists.", required: false },
|
|
7325
|
+
{
|
|
7326
|
+
name: "password",
|
|
7327
|
+
summary: "`false` hides the password form. Every method prop can only turn a method off.",
|
|
7328
|
+
required: false
|
|
7329
|
+
},
|
|
6974
7330
|
{
|
|
6975
7331
|
name: "passkeys",
|
|
6976
|
-
summary: "
|
|
7332
|
+
summary: "`false` hides passkeys; otherwise offered where the environment and browser allow.",
|
|
6977
7333
|
required: false
|
|
6978
7334
|
},
|
|
7335
|
+
{ name: "magicLink", summary: "`false` hides the emailed sign-in link.", required: false },
|
|
6979
7336
|
{
|
|
6980
7337
|
name: "magicLinkRedirectUrl",
|
|
6981
|
-
summary: "Where an emailed link lands
|
|
7338
|
+
summary: "Where an emailed link lands; defaults to the page rendering the form, which redeems `?token=`. Must be on the environment's redirect allow-list.",
|
|
7339
|
+
required: false
|
|
7340
|
+
},
|
|
7341
|
+
{ name: "phone", summary: "`false` hides text-message codes.", required: false },
|
|
7342
|
+
{
|
|
7343
|
+
name: "social",
|
|
7344
|
+
summary: "`false` hides the social buttons; a list of slugs keeps only those providers.",
|
|
6982
7345
|
required: false
|
|
6983
7346
|
},
|
|
7347
|
+
{ name: "sso", summary: '`false` hides "Sign in with SSO".', required: false },
|
|
6984
7348
|
{
|
|
6985
|
-
name: "
|
|
6986
|
-
summary: "
|
|
7349
|
+
name: "socialRedirectUrl",
|
|
7350
|
+
summary: "Your server route a social or SSO sign-in returns to with `?code=&state=`: check `state` against the `b316_oauth_state` cookie (`readOAuthState`), then `base316.auth.exchangeCode` with the secret key. On the redirect allow-list. Without it no social or SSO button is shown.",
|
|
6987
7351
|
required: false
|
|
6988
7352
|
},
|
|
7353
|
+
{
|
|
7354
|
+
name: "socialState",
|
|
7355
|
+
summary: "A short value carried through a social or SSO sign-in, returned by `readOAuthState`.",
|
|
7356
|
+
required: false
|
|
7357
|
+
},
|
|
7358
|
+
{ name: "labels", summary: "Wording for the form, for translation.", required: false },
|
|
6989
7359
|
{
|
|
6990
7360
|
name: "secondFactorLabels",
|
|
6991
7361
|
summary: "Wording for the second-factor step (code box, or enrolment when the environment requires a factor and the user has none), for translation. English when omitted.",
|
|
@@ -6995,6 +7365,38 @@ var MANIFEST = [
|
|
|
6995
7365
|
],
|
|
6996
7366
|
seeAlso: ["SignUp", "ForgotPassword", "SecondFactorStep"]
|
|
6997
7367
|
},
|
|
7368
|
+
{
|
|
7369
|
+
name: "SocialSignIn",
|
|
7370
|
+
kind: "component",
|
|
7371
|
+
summary: `The environment's social sign-in buttons alone ("Continue with Google"), for a sign-in or sign-up form you draw yourself.`,
|
|
7372
|
+
useWhen: "Your own form needs the social providers switched on in the dashboard. SignIn and SignUp already include them.",
|
|
7373
|
+
requires: [],
|
|
7374
|
+
props: [
|
|
7375
|
+
{
|
|
7376
|
+
name: "socialRedirectUrl",
|
|
7377
|
+
summary: "Your server route the code lands on with `?code=&state=`; check with `readOAuthState`, redeem with `exchangeCode`. On the redirect allow-list. Without it nothing is drawn.",
|
|
7378
|
+
required: false
|
|
7379
|
+
},
|
|
7380
|
+
{
|
|
7381
|
+
name: "socialState",
|
|
7382
|
+
summary: "A short value carried through, returned by `readOAuthState`.",
|
|
7383
|
+
required: false
|
|
7384
|
+
},
|
|
7385
|
+
{
|
|
7386
|
+
name: "social",
|
|
7387
|
+
summary: "`false` hides every button; a list of slugs keeps only those providers.",
|
|
7388
|
+
required: false
|
|
7389
|
+
},
|
|
7390
|
+
{
|
|
7391
|
+
name: "intent",
|
|
7392
|
+
summary: "`sign-up` hides the buttons when the environment is closed to new accounts.",
|
|
7393
|
+
required: false
|
|
7394
|
+
},
|
|
7395
|
+
{ name: "divider", summary: 'Draw an "or" rule under the buttons.', required: false },
|
|
7396
|
+
{ name: "labels", summary: "`continueWith` and `or`, for translation.", required: false }
|
|
7397
|
+
],
|
|
7398
|
+
seeAlso: ["SignIn", "SignUp"]
|
|
7399
|
+
},
|
|
6998
7400
|
{
|
|
6999
7401
|
name: "SignUp",
|
|
7000
7402
|
kind: "component",
|
|
@@ -7023,6 +7425,21 @@ var MANIFEST = [
|
|
|
7023
7425
|
summary: "Wording for the second-factor step, for translation.",
|
|
7024
7426
|
required: false
|
|
7025
7427
|
},
|
|
7428
|
+
{
|
|
7429
|
+
name: "social",
|
|
7430
|
+
summary: "`false` hides the social buttons; a list of slugs keeps only those providers.",
|
|
7431
|
+
required: false
|
|
7432
|
+
},
|
|
7433
|
+
{
|
|
7434
|
+
name: "socialRedirectUrl",
|
|
7435
|
+
summary: "Where a social sign-up returns with `?code=&state=`, as on SignIn. Without it no social button is shown.",
|
|
7436
|
+
required: false
|
|
7437
|
+
},
|
|
7438
|
+
{
|
|
7439
|
+
name: "socialState",
|
|
7440
|
+
summary: "A short value carried through a social sign-up, returned by `readOAuthState`.",
|
|
7441
|
+
required: false
|
|
7442
|
+
},
|
|
7026
7443
|
...appearance
|
|
7027
7444
|
],
|
|
7028
7445
|
seeAlso: ["SignIn", "VerifyEmail", "SecondFactorStep"]
|
|
@@ -7794,6 +8211,7 @@ export {
|
|
|
7794
8211
|
SecondFactorStep,
|
|
7795
8212
|
SignIn,
|
|
7796
8213
|
SignUp,
|
|
8214
|
+
SocialSignIn,
|
|
7797
8215
|
SubscriptionManager,
|
|
7798
8216
|
TeamMembers,
|
|
7799
8217
|
TwoFactorManager,
|