@base316/react 0.5.2 → 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 +49 -0
- package/dist/index.cjs +1392 -975
- 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 +1333 -914
- 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/provider.d.ts +9 -1
- package/dist/src/provider.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/dist/src/test/harness.d.ts +2 -1
- package/dist/src/test/harness.d.ts.map +1 -1
- 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; }
|
|
@@ -642,12 +659,13 @@ function Base316Provider({
|
|
|
642
659
|
onTokenChange,
|
|
643
660
|
appearance: appearance2,
|
|
644
661
|
tenant,
|
|
662
|
+
organizationId,
|
|
645
663
|
className,
|
|
646
664
|
children
|
|
647
665
|
}) {
|
|
648
666
|
const client = useMemo(
|
|
649
|
-
() => new Base316Browser({ publishableKey, baseUrl }),
|
|
650
|
-
[publishableKey, baseUrl]
|
|
667
|
+
() => new Base316Browser({ publishableKey, baseUrl, organizationId: organizationId ?? void 0 }),
|
|
668
|
+
[publishableKey, baseUrl, organizationId]
|
|
651
669
|
);
|
|
652
670
|
useEffect(() => {
|
|
653
671
|
if (document.getElementById(STYLE_ELEMENT_ID)) {
|
|
@@ -1606,7 +1624,7 @@ import {
|
|
|
1606
1624
|
isPasskeySupported,
|
|
1607
1625
|
needsSecondFactor
|
|
1608
1626
|
} from "@base316/sdk";
|
|
1609
|
-
import { useEffect as
|
|
1627
|
+
import { useEffect as useEffect8, useRef as useRef2, useState as useState8 } from "react";
|
|
1610
1628
|
|
|
1611
1629
|
// src/SecondFactorStep.tsx
|
|
1612
1630
|
import {
|
|
@@ -1997,33 +2015,233 @@ function SecondFactorStep({
|
|
|
1997
2015
|
return /* @__PURE__ */ jsx7("div", { className: cls("b316-mfa", className), style, children: body });
|
|
1998
2016
|
}
|
|
1999
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
|
+
|
|
2000
2151
|
// src/SignIn.tsx
|
|
2001
|
-
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
|
+
};
|
|
2002
2186
|
function SignIn({
|
|
2003
2187
|
onSignedIn,
|
|
2004
|
-
|
|
2188
|
+
password: passwordProp,
|
|
2189
|
+
passkeys: passkeysProp,
|
|
2190
|
+
magicLink: magicLinkProp,
|
|
2005
2191
|
magicLinkRedirectUrl,
|
|
2006
|
-
phone
|
|
2192
|
+
phone: phoneProp,
|
|
2193
|
+
social: socialProp,
|
|
2194
|
+
sso: ssoProp,
|
|
2195
|
+
socialRedirectUrl,
|
|
2196
|
+
socialState,
|
|
2197
|
+
labels: overrides,
|
|
2007
2198
|
secondFactorLabels,
|
|
2008
2199
|
className,
|
|
2009
2200
|
style
|
|
2010
2201
|
}) {
|
|
2202
|
+
const labels = { ...DEFAULT_SIGN_IN_LABELS, ...overrides };
|
|
2011
2203
|
const { client, setToken } = useBase316();
|
|
2012
|
-
const
|
|
2013
|
-
const [
|
|
2014
|
-
const [
|
|
2015
|
-
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);
|
|
2016
2210
|
const pendingChallenge = pending?.challengeToken ?? null;
|
|
2017
|
-
const [phoneNumber, setPhoneNumber] =
|
|
2018
|
-
const [phoneChallenge, setPhoneChallenge] =
|
|
2211
|
+
const [phoneNumber, setPhoneNumber] = useState8("");
|
|
2212
|
+
const [phoneChallenge, setPhoneChallenge] = useState8(
|
|
2019
2213
|
null
|
|
2020
2214
|
);
|
|
2021
|
-
const [error, setError] =
|
|
2022
|
-
const [busy, setBusy] =
|
|
2023
|
-
const [passkeyReady, setPasskeyReady] =
|
|
2024
|
-
const [
|
|
2025
|
-
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);
|
|
2026
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;
|
|
2027
2245
|
const signInWithPasskey = async (conditional, signal) => {
|
|
2028
2246
|
if (!conditional) {
|
|
2029
2247
|
setBusy(true);
|
|
@@ -2041,7 +2259,7 @@ function SignIn({
|
|
|
2041
2259
|
setError(cause.message);
|
|
2042
2260
|
} else if (!conditional) {
|
|
2043
2261
|
console.error("[base316] passkey sign-in failed", cause);
|
|
2044
|
-
setError(
|
|
2262
|
+
setError(labels.passkeyFailed);
|
|
2045
2263
|
}
|
|
2046
2264
|
} finally {
|
|
2047
2265
|
if (!conditional) {
|
|
@@ -2049,8 +2267,9 @@ function SignIn({
|
|
|
2049
2267
|
}
|
|
2050
2268
|
}
|
|
2051
2269
|
};
|
|
2052
|
-
|
|
2053
|
-
if (!
|
|
2270
|
+
useEffect8(() => {
|
|
2271
|
+
if (!passkeysWanted || !isPasskeySupported() || pendingChallenge) {
|
|
2272
|
+
setPasskeyReady(false);
|
|
2054
2273
|
return;
|
|
2055
2274
|
}
|
|
2056
2275
|
setPasskeyReady(true);
|
|
@@ -2064,8 +2283,8 @@ function SignIn({
|
|
|
2064
2283
|
return () => {
|
|
2065
2284
|
controller.abort();
|
|
2066
2285
|
};
|
|
2067
|
-
}, [
|
|
2068
|
-
|
|
2286
|
+
}, [passkeysWanted, pendingChallenge]);
|
|
2287
|
+
useEffect8(() => {
|
|
2069
2288
|
if (typeof window === "undefined") {
|
|
2070
2289
|
return;
|
|
2071
2290
|
}
|
|
@@ -2089,7 +2308,7 @@ function SignIn({
|
|
|
2089
2308
|
onSignedIn?.();
|
|
2090
2309
|
}).catch(() => {
|
|
2091
2310
|
if (!cancelled) {
|
|
2092
|
-
setError(
|
|
2311
|
+
setError(labels.linkInvalid);
|
|
2093
2312
|
}
|
|
2094
2313
|
});
|
|
2095
2314
|
return () => {
|
|
@@ -2097,23 +2316,44 @@ function SignIn({
|
|
|
2097
2316
|
};
|
|
2098
2317
|
}, []);
|
|
2099
2318
|
async function sendLink() {
|
|
2100
|
-
if (!
|
|
2319
|
+
if (!offered.magicLink) {
|
|
2101
2320
|
return;
|
|
2102
2321
|
}
|
|
2103
2322
|
setBusy(true);
|
|
2104
2323
|
setError(null);
|
|
2105
2324
|
try {
|
|
2106
|
-
await client.auth.magicLink.request({ email, redirectUrl:
|
|
2325
|
+
await client.auth.magicLink.request({ email, redirectUrl: offered.magicLink });
|
|
2107
2326
|
setLinkSent(true);
|
|
2108
2327
|
} catch (cause) {
|
|
2109
2328
|
console.error("[base316] magic link request failed", cause);
|
|
2110
|
-
setError(
|
|
2329
|
+
setError(
|
|
2330
|
+
cause instanceof Base316Error2 && cause.code === "INVALID_REQUEST" && cause.message ? cause.message : labels.linkFailed
|
|
2331
|
+
);
|
|
2111
2332
|
} finally {
|
|
2112
2333
|
setBusy(false);
|
|
2113
2334
|
}
|
|
2114
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
|
+
}
|
|
2115
2351
|
async function submit(event) {
|
|
2116
2352
|
event.preventDefault();
|
|
2353
|
+
if (mode === "sso") {
|
|
2354
|
+
leaveForSso();
|
|
2355
|
+
return;
|
|
2356
|
+
}
|
|
2117
2357
|
setBusy(true);
|
|
2118
2358
|
setError(null);
|
|
2119
2359
|
try {
|
|
@@ -2150,25 +2390,23 @@ function SignIn({
|
|
|
2150
2390
|
} catch (cause) {
|
|
2151
2391
|
console.error("[base316] sign-in failed", cause);
|
|
2152
2392
|
setError(
|
|
2153
|
-
mode === "phone" ? phoneChallenge ?
|
|
2393
|
+
mode === "phone" ? phoneChallenge ? labels.wrongCode : (
|
|
2154
2394
|
// Why a text could not be sent is worth saying — a number in the
|
|
2155
2395
|
// wrong format, or too many requests — and the server words it
|
|
2156
2396
|
// without saying anything about accounts.
|
|
2157
|
-
cause instanceof Error && cause.message ? cause.message :
|
|
2397
|
+
cause instanceof Error && cause.message ? cause.message : labels.codeFailed
|
|
2158
2398
|
) : (
|
|
2159
2399
|
// An unconfirmed address and a throttle are worth naming; the
|
|
2160
2400
|
// server words both without saying whether an account exists.
|
|
2161
|
-
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
|
|
2162
2402
|
)
|
|
2163
2403
|
);
|
|
2164
2404
|
} finally {
|
|
2165
2405
|
setBusy(false);
|
|
2166
2406
|
}
|
|
2167
2407
|
}
|
|
2168
|
-
const magicAvailable = Boolean(magicLinkRedirectUrl) && !pendingChallenge;
|
|
2169
|
-
const tabsShown = (magicAvailable || phone) && !pendingChallenge;
|
|
2170
2408
|
if (pending) {
|
|
2171
|
-
return /* @__PURE__ */
|
|
2409
|
+
return /* @__PURE__ */ jsx9("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx9(
|
|
2172
2410
|
SecondFactorStep,
|
|
2173
2411
|
{
|
|
2174
2412
|
pending,
|
|
@@ -2184,59 +2422,68 @@ function SignIn({
|
|
|
2184
2422
|
) });
|
|
2185
2423
|
}
|
|
2186
2424
|
if (linkSent) {
|
|
2187
|
-
return /* @__PURE__ */
|
|
2188
|
-
/* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
|
|
2191
|
-
email,
|
|
2192
|
-
", a sign-in link is on its way. It expires shortly and can be used once."
|
|
2193
|
-
] }),
|
|
2194
|
-
/* @__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(
|
|
2195
2429
|
"button",
|
|
2196
2430
|
{
|
|
2197
2431
|
type: "button",
|
|
2198
2432
|
className: "b316-button b316-button-secondary",
|
|
2199
2433
|
style: { marginTop: 16 },
|
|
2200
2434
|
onClick: () => setLinkSent(false),
|
|
2201
|
-
children:
|
|
2435
|
+
children: labels.backToSignIn
|
|
2202
2436
|
}
|
|
2203
2437
|
)
|
|
2204
2438
|
] });
|
|
2205
2439
|
}
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
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,
|
|
2211
2451
|
{
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
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
|
+
}
|
|
2216
2470
|
}
|
|
2217
2471
|
),
|
|
2218
|
-
|
|
2219
|
-
"button",
|
|
2220
|
-
{
|
|
2221
|
-
type: "button",
|
|
2222
|
-
className: cls("b316-tab", mode === "magic" ? "b316-tab-on" : void 0),
|
|
2223
|
-
onClick: () => setMode("magic"),
|
|
2224
|
-
children: "Magic link"
|
|
2225
|
-
}
|
|
2226
|
-
) : null,
|
|
2227
|
-
phone ? /* @__PURE__ */ jsx8(
|
|
2228
|
-
"button",
|
|
2229
|
-
{
|
|
2230
|
-
type: "button",
|
|
2231
|
-
className: cls("b316-tab", mode === "phone" ? "b316-tab-on" : void 0),
|
|
2232
|
-
onClick: () => setMode("phone"),
|
|
2233
|
-
children: "Text message"
|
|
2234
|
-
}
|
|
2235
|
-
) : null
|
|
2472
|
+
hasForm ? /* @__PURE__ */ jsx9("div", { className: "b316-divider", children: labels.or }) : null
|
|
2236
2473
|
] }) : null,
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
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(
|
|
2240
2487
|
"input",
|
|
2241
2488
|
{
|
|
2242
2489
|
id: "b316-phone-code",
|
|
@@ -2248,12 +2495,10 @@ function SignIn({
|
|
|
2248
2495
|
required: true
|
|
2249
2496
|
}
|
|
2250
2497
|
),
|
|
2251
|
-
/* @__PURE__ */
|
|
2252
|
-
|
|
2253
|
-
phoneChallenge.hint,
|
|
2254
|
-
". It expires in ten minutes.",
|
|
2498
|
+
/* @__PURE__ */ jsxs8("span", { className: "b316-muted", children: [
|
|
2499
|
+
labels.codeSent(phoneChallenge.hint),
|
|
2255
2500
|
" ",
|
|
2256
|
-
/* @__PURE__ */
|
|
2501
|
+
/* @__PURE__ */ jsx9(
|
|
2257
2502
|
"button",
|
|
2258
2503
|
{
|
|
2259
2504
|
type: "button",
|
|
@@ -2262,13 +2507,13 @@ function SignIn({
|
|
|
2262
2507
|
setPhoneChallenge(null);
|
|
2263
2508
|
setCode("");
|
|
2264
2509
|
},
|
|
2265
|
-
children:
|
|
2510
|
+
children: labels.useDifferentNumber
|
|
2266
2511
|
}
|
|
2267
2512
|
)
|
|
2268
2513
|
] })
|
|
2269
|
-
] }) : /* @__PURE__ */
|
|
2270
|
-
/* @__PURE__ */
|
|
2271
|
-
/* @__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(
|
|
2272
2517
|
"input",
|
|
2273
2518
|
{
|
|
2274
2519
|
id: "b316-phone",
|
|
@@ -2281,11 +2526,11 @@ function SignIn({
|
|
|
2281
2526
|
required: true
|
|
2282
2527
|
}
|
|
2283
2528
|
),
|
|
2284
|
-
/* @__PURE__ */
|
|
2285
|
-
] }) : /* @__PURE__ */
|
|
2286
|
-
/* @__PURE__ */
|
|
2287
|
-
/* @__PURE__ */
|
|
2288
|
-
/* @__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(
|
|
2289
2534
|
"input",
|
|
2290
2535
|
{
|
|
2291
2536
|
id: "b316-email",
|
|
@@ -2293,14 +2538,14 @@ function SignIn({
|
|
|
2293
2538
|
type: "email",
|
|
2294
2539
|
value: email,
|
|
2295
2540
|
onChange: (event) => setEmail(event.target.value),
|
|
2296
|
-
autoComplete: passkeyReady ? "email webauthn" : "email",
|
|
2541
|
+
autoComplete: passkeyReady && mode !== "sso" ? "email webauthn" : "email",
|
|
2297
2542
|
required: true
|
|
2298
2543
|
}
|
|
2299
2544
|
)
|
|
2300
2545
|
] }),
|
|
2301
|
-
mode === "password" ? /* @__PURE__ */
|
|
2302
|
-
/* @__PURE__ */
|
|
2303
|
-
/* @__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(
|
|
2304
2549
|
"input",
|
|
2305
2550
|
{
|
|
2306
2551
|
id: "b316-password",
|
|
@@ -2313,34 +2558,101 @@ function SignIn({
|
|
|
2313
2558
|
}
|
|
2314
2559
|
)
|
|
2315
2560
|
] }) : null
|
|
2316
|
-
] }),
|
|
2317
|
-
/* @__PURE__ */
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
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(
|
|
2321
2577
|
"button",
|
|
2322
2578
|
{
|
|
2323
2579
|
type: "button",
|
|
2324
2580
|
className: "b316-button b316-button-secondary",
|
|
2581
|
+
style: { width: "100%" },
|
|
2325
2582
|
disabled: busy,
|
|
2326
2583
|
onClick: () => {
|
|
2327
2584
|
abortRef.current?.abort();
|
|
2328
2585
|
void signInWithPasskey(false);
|
|
2329
2586
|
},
|
|
2330
|
-
children:
|
|
2587
|
+
children: labels.passkey
|
|
2331
2588
|
}
|
|
2332
|
-
)
|
|
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
|
|
2333
2605
|
] }) : null
|
|
2334
2606
|
] });
|
|
2335
2607
|
}
|
|
2336
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
|
+
|
|
2337
2649
|
// src/SignUp.tsx
|
|
2338
2650
|
import {
|
|
2339
2651
|
Base316Error as Base316Error3,
|
|
2340
2652
|
needsSecondFactor as needsSecondFactor2
|
|
2341
2653
|
} from "@base316/sdk";
|
|
2342
|
-
import { useEffect as
|
|
2343
|
-
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";
|
|
2344
2656
|
var DEFAULT_SIGN_UP_LABELS = {
|
|
2345
2657
|
name: "Name",
|
|
2346
2658
|
email: "Email",
|
|
@@ -2357,7 +2669,10 @@ var DEFAULT_SIGN_UP_LABELS = {
|
|
|
2357
2669
|
confirmEmail: (email) => `Your account is ready. We sent a confirmation link to ${email} \u2014 open it, then sign in.`,
|
|
2358
2670
|
createdSignInFailed: (reason) => `Your account was created, but we could not sign you in: ${reason}`,
|
|
2359
2671
|
genericError: "We could not create that account. Try again.",
|
|
2360
|
-
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."
|
|
2361
2676
|
};
|
|
2362
2677
|
function describeRules(policy, labels) {
|
|
2363
2678
|
const extras = [
|
|
@@ -2376,30 +2691,35 @@ function SignUp({
|
|
|
2376
2691
|
onJoined,
|
|
2377
2692
|
labels: overrides,
|
|
2378
2693
|
secondFactorLabels,
|
|
2694
|
+
social,
|
|
2695
|
+
socialRedirectUrl,
|
|
2696
|
+
socialState,
|
|
2379
2697
|
className,
|
|
2380
2698
|
style
|
|
2381
2699
|
}) {
|
|
2382
2700
|
const labels = { ...DEFAULT_SIGN_UP_LABELS, ...overrides };
|
|
2383
2701
|
const { client, setToken } = useBase316();
|
|
2384
|
-
const
|
|
2385
|
-
const
|
|
2386
|
-
const [
|
|
2387
|
-
const [
|
|
2388
|
-
const [
|
|
2389
|
-
const [
|
|
2390
|
-
const [
|
|
2391
|
-
const [
|
|
2392
|
-
const [
|
|
2393
|
-
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);
|
|
2394
2714
|
const invitation = suppliedInvitation === void 0 ? urlInvitation : suppliedInvitation;
|
|
2395
2715
|
const preview = loaded && loaded.token === invitation ? loaded.preview : null;
|
|
2396
|
-
|
|
2716
|
+
useEffect9(() => {
|
|
2397
2717
|
if (suppliedInvitation !== void 0 || typeof window === "undefined") {
|
|
2398
2718
|
return;
|
|
2399
2719
|
}
|
|
2400
2720
|
setUrlInvitation(new URL(window.location.href).searchParams.get("invitation"));
|
|
2401
2721
|
}, [suppliedInvitation]);
|
|
2402
|
-
|
|
2722
|
+
useEffect9(() => {
|
|
2403
2723
|
if (!invitation) {
|
|
2404
2724
|
return;
|
|
2405
2725
|
}
|
|
@@ -2414,7 +2734,7 @@ function SignUp({
|
|
|
2414
2734
|
cancelled = true;
|
|
2415
2735
|
};
|
|
2416
2736
|
}, [client, invitation]);
|
|
2417
|
-
|
|
2737
|
+
useEffect9(() => {
|
|
2418
2738
|
let cancelled = false;
|
|
2419
2739
|
client.auth.passwordPolicy().then((loaded2) => {
|
|
2420
2740
|
if (!cancelled) {
|
|
@@ -2472,86 +2792,118 @@ function SignUp({
|
|
|
2472
2792
|
}
|
|
2473
2793
|
}
|
|
2474
2794
|
if (pending) {
|
|
2475
|
-
return /* @__PURE__ */
|
|
2795
|
+
return /* @__PURE__ */ jsx11("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx11(SecondFactorStep, { pending, labels: secondFactorLabels, onSignedIn: onSignedUp }) });
|
|
2476
2796
|
}
|
|
2477
2797
|
if (confirmEmail) {
|
|
2478
|
-
return /* @__PURE__ */
|
|
2479
|
-
/* @__PURE__ */
|
|
2480
|
-
/* @__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) })
|
|
2481
2801
|
] });
|
|
2482
2802
|
}
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
id: "b316-name",
|
|
2492
|
-
className: "b316-input",
|
|
2493
|
-
value: name,
|
|
2494
|
-
onChange: (event) => setName(event.target.value),
|
|
2495
|
-
autoComplete: "name"
|
|
2496
|
-
}
|
|
2497
|
-
)
|
|
2498
|
-
] }),
|
|
2499
|
-
/* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2500
|
-
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-signup-email", children: labels.email }),
|
|
2501
|
-
/* @__PURE__ */ jsx9(
|
|
2502
|
-
"input",
|
|
2503
|
-
{
|
|
2504
|
-
id: "b316-signup-email",
|
|
2505
|
-
className: "b316-input",
|
|
2506
|
-
type: "email",
|
|
2507
|
-
value: email,
|
|
2508
|
-
onChange: (event) => setEmail(event.target.value),
|
|
2509
|
-
autoComplete: "email",
|
|
2510
|
-
required: true
|
|
2511
|
-
}
|
|
2512
|
-
)
|
|
2513
|
-
] }),
|
|
2514
|
-
/* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2515
|
-
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-signup-password", children: labels.password }),
|
|
2516
|
-
/* @__PURE__ */ jsx9(
|
|
2517
|
-
"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,
|
|
2518
2811
|
{
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
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
|
+
}
|
|
2529
2830
|
}
|
|
2530
2831
|
),
|
|
2531
|
-
|
|
2532
|
-
] }),
|
|
2533
|
-
/* @__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
|
|
2534
2886
|
] });
|
|
2535
2887
|
}
|
|
2536
2888
|
|
|
2537
2889
|
// src/UserProfile.tsx
|
|
2538
|
-
import { jsx as
|
|
2890
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2539
2891
|
function UserProfile({ className, style }) {
|
|
2540
2892
|
const { session, loading, signOut } = useBase316();
|
|
2541
2893
|
if (loading) {
|
|
2542
|
-
return /* @__PURE__ */
|
|
2894
|
+
return /* @__PURE__ */ jsx12("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
2543
2895
|
}
|
|
2544
2896
|
if (!session) {
|
|
2545
|
-
return /* @__PURE__ */
|
|
2897
|
+
return /* @__PURE__ */ jsx12("div", { className: cls("b316-card", className), style, children: "Not signed in." });
|
|
2546
2898
|
}
|
|
2547
2899
|
const user = session.user ?? {};
|
|
2548
|
-
return /* @__PURE__ */
|
|
2549
|
-
/* @__PURE__ */
|
|
2550
|
-
/* @__PURE__ */
|
|
2551
|
-
user.name && user.email ? /* @__PURE__ */
|
|
2552
|
-
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
|
|
2553
2905
|
] }),
|
|
2554
|
-
/* @__PURE__ */
|
|
2906
|
+
/* @__PURE__ */ jsx12(
|
|
2555
2907
|
"button",
|
|
2556
2908
|
{
|
|
2557
2909
|
type: "button",
|
|
@@ -2565,11 +2917,11 @@ function UserProfile({ className, style }) {
|
|
|
2565
2917
|
|
|
2566
2918
|
// src/PasskeyManager.tsx
|
|
2567
2919
|
import { isPasskeySupported as isPasskeySupported2 } from "@base316/sdk";
|
|
2568
|
-
import { useCallback as useCallback5, useEffect as
|
|
2920
|
+
import { useCallback as useCallback5, useEffect as useEffect11, useState as useState11 } from "react";
|
|
2569
2921
|
|
|
2570
2922
|
// src/confirm.tsx
|
|
2571
|
-
import { useEffect as
|
|
2572
|
-
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";
|
|
2573
2925
|
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
2574
2926
|
function ConfirmButton({
|
|
2575
2927
|
children,
|
|
@@ -2579,9 +2931,9 @@ function ConfirmButton({
|
|
|
2579
2931
|
disabled,
|
|
2580
2932
|
timeoutMs = DEFAULT_TIMEOUT_MS
|
|
2581
2933
|
}) {
|
|
2582
|
-
const [armed, setArmed] =
|
|
2934
|
+
const [armed, setArmed] = useState10(false);
|
|
2583
2935
|
const confirmRef = useRef3(null);
|
|
2584
|
-
|
|
2936
|
+
useEffect10(() => {
|
|
2585
2937
|
if (!armed) {
|
|
2586
2938
|
return;
|
|
2587
2939
|
}
|
|
@@ -2590,7 +2942,7 @@ function ConfirmButton({
|
|
|
2590
2942
|
return () => clearTimeout(timer);
|
|
2591
2943
|
}, [armed, timeoutMs]);
|
|
2592
2944
|
if (!armed) {
|
|
2593
|
-
return /* @__PURE__ */
|
|
2945
|
+
return /* @__PURE__ */ jsx13(
|
|
2594
2946
|
"button",
|
|
2595
2947
|
{
|
|
2596
2948
|
type: "button",
|
|
@@ -2604,8 +2956,8 @@ function ConfirmButton({
|
|
|
2604
2956
|
return (
|
|
2605
2957
|
// No `role="group"`: both buttons already say what they do, and the
|
|
2606
2958
|
// grouping would only repeat the question a screen reader has just read.
|
|
2607
|
-
/* @__PURE__ */
|
|
2608
|
-
/* @__PURE__ */
|
|
2959
|
+
/* @__PURE__ */ jsxs12("span", { className: "b316-confirm", children: [
|
|
2960
|
+
/* @__PURE__ */ jsx13(
|
|
2609
2961
|
"button",
|
|
2610
2962
|
{
|
|
2611
2963
|
ref: confirmRef,
|
|
@@ -2619,7 +2971,7 @@ function ConfirmButton({
|
|
|
2619
2971
|
children: confirmLabel
|
|
2620
2972
|
}
|
|
2621
2973
|
),
|
|
2622
|
-
/* @__PURE__ */
|
|
2974
|
+
/* @__PURE__ */ jsx13(
|
|
2623
2975
|
"button",
|
|
2624
2976
|
{
|
|
2625
2977
|
type: "button",
|
|
@@ -2633,18 +2985,18 @@ function ConfirmButton({
|
|
|
2633
2985
|
}
|
|
2634
2986
|
|
|
2635
2987
|
// src/PasskeyManager.tsx
|
|
2636
|
-
import { jsx as
|
|
2988
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2637
2989
|
function PasskeyManager({
|
|
2638
2990
|
className,
|
|
2639
2991
|
style,
|
|
2640
2992
|
title = "Passkeys"
|
|
2641
2993
|
}) {
|
|
2642
2994
|
const { client, token, session } = useBase316();
|
|
2643
|
-
const [passkeys, setPasskeys] =
|
|
2644
|
-
const [busy, setBusy] =
|
|
2645
|
-
const [error, setError] =
|
|
2646
|
-
const [name, setName] =
|
|
2647
|
-
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);
|
|
2648
3000
|
const load = useCallback5(async () => {
|
|
2649
3001
|
if (!token) {
|
|
2650
3002
|
return;
|
|
@@ -2658,7 +3010,7 @@ function PasskeyManager({
|
|
|
2658
3010
|
setPasskeys(null);
|
|
2659
3011
|
}
|
|
2660
3012
|
}, [client, token]);
|
|
2661
|
-
|
|
3013
|
+
useEffect11(() => {
|
|
2662
3014
|
if (!isPasskeySupported2()) {
|
|
2663
3015
|
return;
|
|
2664
3016
|
}
|
|
@@ -2694,18 +3046,18 @@ function PasskeyManager({
|
|
|
2694
3046
|
setError(caught instanceof Error ? caught.message : "That did not work.");
|
|
2695
3047
|
}
|
|
2696
3048
|
};
|
|
2697
|
-
return /* @__PURE__ */
|
|
2698
|
-
/* @__PURE__ */
|
|
2699
|
-
/* @__PURE__ */
|
|
2700
|
-
passkeys === null ? /* @__PURE__ */
|
|
2701
|
-
/* @__PURE__ */
|
|
2702
|
-
/* @__PURE__ */
|
|
2703
|
-
/* @__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: [
|
|
2704
3056
|
passkey.lastUsedAt ? `Last used ${formatDate(passkey.lastUsedAt)}` : `Added ${formatDate(passkey.createdAt)}`,
|
|
2705
3057
|
passkey.backedUp ? "" : " \xB7 this device only"
|
|
2706
3058
|
] })
|
|
2707
3059
|
] }),
|
|
2708
|
-
/* @__PURE__ */
|
|
3060
|
+
/* @__PURE__ */ jsx14(
|
|
2709
3061
|
ConfirmButton,
|
|
2710
3062
|
{
|
|
2711
3063
|
className: "b316-button b316-button-secondary",
|
|
@@ -2715,9 +3067,9 @@ function PasskeyManager({
|
|
|
2715
3067
|
}
|
|
2716
3068
|
)
|
|
2717
3069
|
] }, passkey.id)) }),
|
|
2718
|
-
error ? /* @__PURE__ */
|
|
2719
|
-
/* @__PURE__ */
|
|
2720
|
-
/* @__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(
|
|
2721
3073
|
"input",
|
|
2722
3074
|
{
|
|
2723
3075
|
className: "b316-input",
|
|
@@ -2726,7 +3078,7 @@ function PasskeyManager({
|
|
|
2726
3078
|
onChange: (event) => setName(event.target.value)
|
|
2727
3079
|
}
|
|
2728
3080
|
),
|
|
2729
|
-
/* @__PURE__ */
|
|
3081
|
+
/* @__PURE__ */ jsx14("button", { type: "button", className: "b316-button", disabled: busy, onClick: () => void add(), children: busy ? "Waiting\u2026" : "Add a passkey" })
|
|
2730
3082
|
] })
|
|
2731
3083
|
] });
|
|
2732
3084
|
}
|
|
@@ -2736,8 +3088,8 @@ function formatDate(value) {
|
|
|
2736
3088
|
}
|
|
2737
3089
|
|
|
2738
3090
|
// src/ActiveSessions.tsx
|
|
2739
|
-
import { useCallback as useCallback6, useEffect as
|
|
2740
|
-
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";
|
|
2741
3093
|
function describeDevice(userAgent) {
|
|
2742
3094
|
if (!userAgent) {
|
|
2743
3095
|
return null;
|
|
@@ -2755,9 +3107,9 @@ function when(value) {
|
|
|
2755
3107
|
}
|
|
2756
3108
|
function ActiveSessions({ onRevoked, className, style }) {
|
|
2757
3109
|
const { client, token } = useBase316();
|
|
2758
|
-
const [sessions, setSessions] =
|
|
2759
|
-
const [error, setError] =
|
|
2760
|
-
const [busy, setBusy] =
|
|
3110
|
+
const [sessions, setSessions] = useState12(null);
|
|
3111
|
+
const [error, setError] = useState12(null);
|
|
3112
|
+
const [busy, setBusy] = useState12(false);
|
|
2761
3113
|
const load = useCallback6(() => {
|
|
2762
3114
|
if (!token) {
|
|
2763
3115
|
return;
|
|
@@ -2769,15 +3121,15 @@ function ActiveSessions({ onRevoked, className, style }) {
|
|
|
2769
3121
|
setError(cause instanceof Error ? cause.message : "Could not load your sessions.");
|
|
2770
3122
|
});
|
|
2771
3123
|
}, [client, token]);
|
|
2772
|
-
|
|
3124
|
+
useEffect12(load, [load]);
|
|
2773
3125
|
if (!token) {
|
|
2774
3126
|
return null;
|
|
2775
3127
|
}
|
|
2776
3128
|
if (error) {
|
|
2777
|
-
return /* @__PURE__ */
|
|
3129
|
+
return /* @__PURE__ */ jsx15("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx15("div", { className: "b316-error", role: "alert", children: error }) });
|
|
2778
3130
|
}
|
|
2779
3131
|
if (!sessions) {
|
|
2780
|
-
return /* @__PURE__ */
|
|
3132
|
+
return /* @__PURE__ */ jsx15("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
2781
3133
|
}
|
|
2782
3134
|
async function revokeOthers() {
|
|
2783
3135
|
setBusy(true);
|
|
@@ -2791,32 +3143,32 @@ function ActiveSessions({ onRevoked, className, style }) {
|
|
|
2791
3143
|
setBusy(false);
|
|
2792
3144
|
}
|
|
2793
3145
|
}
|
|
2794
|
-
return /* @__PURE__ */
|
|
2795
|
-
/* @__PURE__ */
|
|
2796
|
-
/* @__PURE__ */
|
|
2797
|
-
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
|
|
2798
3150
|
] }),
|
|
2799
|
-
/* @__PURE__ */
|
|
2800
|
-
/* @__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: [
|
|
2801
3153
|
describeDevice(session.userAgent) ?? "Unknown device",
|
|
2802
3154
|
session.impersonatedBy ? (
|
|
2803
3155
|
// Worth saying loudly: somebody is acting as this account.
|
|
2804
|
-
/* @__PURE__ */
|
|
3156
|
+
/* @__PURE__ */ jsx15("span", { className: "b316-chip", children: " Support access" })
|
|
2805
3157
|
) : null
|
|
2806
3158
|
] }),
|
|
2807
|
-
/* @__PURE__ */
|
|
3159
|
+
/* @__PURE__ */ jsxs14("div", { className: "b316-muted", children: [
|
|
2808
3160
|
session.ipAddress ? `${session.ipAddress} \xB7 ` : "",
|
|
2809
3161
|
"last used ",
|
|
2810
3162
|
when(session.lastSeenAt)
|
|
2811
3163
|
] })
|
|
2812
3164
|
] }, session.id)) }),
|
|
2813
|
-
sessions.length === 0 ? /* @__PURE__ */
|
|
3165
|
+
sessions.length === 0 ? /* @__PURE__ */ jsx15("div", { className: "b316-muted", children: "No active sessions." }) : null
|
|
2814
3166
|
] });
|
|
2815
3167
|
}
|
|
2816
3168
|
|
|
2817
3169
|
// src/DeviceApproval.tsx
|
|
2818
|
-
import { useState as
|
|
2819
|
-
import { jsx as
|
|
3170
|
+
import { useState as useState13 } from "react";
|
|
3171
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2820
3172
|
function DeviceApproval({
|
|
2821
3173
|
userCode = "",
|
|
2822
3174
|
onDecided,
|
|
@@ -2824,11 +3176,11 @@ function DeviceApproval({
|
|
|
2824
3176
|
style
|
|
2825
3177
|
}) {
|
|
2826
3178
|
const { client, token } = useBase316();
|
|
2827
|
-
const [code, setCode] =
|
|
2828
|
-
const [request, setRequest] =
|
|
2829
|
-
const [decided, setDecided] =
|
|
2830
|
-
const [error, setError] =
|
|
2831
|
-
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);
|
|
2832
3184
|
if (!token) {
|
|
2833
3185
|
return null;
|
|
2834
3186
|
}
|
|
@@ -2861,25 +3213,25 @@ function DeviceApproval({
|
|
|
2861
3213
|
}
|
|
2862
3214
|
}
|
|
2863
3215
|
if (decided !== null) {
|
|
2864
|
-
return /* @__PURE__ */
|
|
2865
|
-
/* @__PURE__ */
|
|
2866
|
-
/* @__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." })
|
|
2867
3219
|
] });
|
|
2868
3220
|
}
|
|
2869
3221
|
if (request) {
|
|
2870
|
-
return /* @__PURE__ */
|
|
2871
|
-
/* @__PURE__ */
|
|
3222
|
+
return /* @__PURE__ */ jsxs15("div", { className: cls("b316-card b316-device", className), style, children: [
|
|
3223
|
+
/* @__PURE__ */ jsxs15("h3", { className: "b316-device-title", children: [
|
|
2872
3224
|
"Sign in to ",
|
|
2873
3225
|
request.clientName
|
|
2874
3226
|
] }),
|
|
2875
|
-
/* @__PURE__ */
|
|
3227
|
+
/* @__PURE__ */ jsxs15("p", { className: "b316-muted", children: [
|
|
2876
3228
|
request.clientName,
|
|
2877
3229
|
" is asking to sign in as you."
|
|
2878
3230
|
] }),
|
|
2879
|
-
request.scopes.length > 0 ? /* @__PURE__ */
|
|
2880
|
-
error ? /* @__PURE__ */
|
|
2881
|
-
/* @__PURE__ */
|
|
2882
|
-
/* @__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(
|
|
2883
3235
|
"button",
|
|
2884
3236
|
{
|
|
2885
3237
|
type: "button",
|
|
@@ -2889,7 +3241,7 @@ function DeviceApproval({
|
|
|
2889
3241
|
children: busy ? "Approving\u2026" : "Approve"
|
|
2890
3242
|
}
|
|
2891
3243
|
),
|
|
2892
|
-
/* @__PURE__ */
|
|
3244
|
+
/* @__PURE__ */ jsx16(
|
|
2893
3245
|
"button",
|
|
2894
3246
|
{
|
|
2895
3247
|
type: "button",
|
|
@@ -2902,11 +3254,11 @@ function DeviceApproval({
|
|
|
2902
3254
|
] })
|
|
2903
3255
|
] });
|
|
2904
3256
|
}
|
|
2905
|
-
return /* @__PURE__ */
|
|
2906
|
-
/* @__PURE__ */
|
|
2907
|
-
/* @__PURE__ */
|
|
2908
|
-
error ? /* @__PURE__ */
|
|
2909
|
-
/* @__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(
|
|
2910
3262
|
"input",
|
|
2911
3263
|
{
|
|
2912
3264
|
className: "b316-input",
|
|
@@ -2919,13 +3271,13 @@ function DeviceApproval({
|
|
|
2919
3271
|
"aria-label": "Device code"
|
|
2920
3272
|
}
|
|
2921
3273
|
),
|
|
2922
|
-
/* @__PURE__ */
|
|
3274
|
+
/* @__PURE__ */ jsx16("button", { type: "submit", className: "b316-button", disabled: busy || code.trim().length < 4, children: busy ? "Checking\u2026" : "Continue" })
|
|
2923
3275
|
] });
|
|
2924
3276
|
}
|
|
2925
3277
|
|
|
2926
3278
|
// src/PrivacyControls.tsx
|
|
2927
|
-
import { useState as
|
|
2928
|
-
import { jsx as
|
|
3279
|
+
import { useState as useState14 } from "react";
|
|
3280
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2929
3281
|
function PrivacyControls({
|
|
2930
3282
|
confirmWord = "DELETE",
|
|
2931
3283
|
onErased,
|
|
@@ -2933,10 +3285,10 @@ function PrivacyControls({
|
|
|
2933
3285
|
style
|
|
2934
3286
|
}) {
|
|
2935
3287
|
const { client, token } = useBase316();
|
|
2936
|
-
const [confirming, setConfirming] =
|
|
2937
|
-
const [typed, setTyped] =
|
|
2938
|
-
const [error, setError] =
|
|
2939
|
-
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);
|
|
2940
3292
|
if (!token) {
|
|
2941
3293
|
return null;
|
|
2942
3294
|
}
|
|
@@ -2971,22 +3323,22 @@ function PrivacyControls({
|
|
|
2971
3323
|
setBusy(false);
|
|
2972
3324
|
}
|
|
2973
3325
|
}
|
|
2974
|
-
return /* @__PURE__ */
|
|
2975
|
-
/* @__PURE__ */
|
|
2976
|
-
error ? /* @__PURE__ */
|
|
2977
|
-
/* @__PURE__ */
|
|
2978
|
-
/* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
2980
|
-
/* @__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." })
|
|
2981
3333
|
] }),
|
|
2982
|
-
/* @__PURE__ */
|
|
3334
|
+
/* @__PURE__ */ jsx17("button", { type: "button", className: "b316-button-quiet", disabled: busy, onClick: download, children: busy ? "Preparing\u2026" : "Download" })
|
|
2983
3335
|
] }),
|
|
2984
|
-
/* @__PURE__ */
|
|
2985
|
-
/* @__PURE__ */
|
|
2986
|
-
/* @__PURE__ */
|
|
2987
|
-
/* @__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." })
|
|
2988
3340
|
] }),
|
|
2989
|
-
confirming ? null : /* @__PURE__ */
|
|
3341
|
+
confirming ? null : /* @__PURE__ */ jsx17(
|
|
2990
3342
|
"button",
|
|
2991
3343
|
{
|
|
2992
3344
|
type: "button",
|
|
@@ -2997,13 +3349,13 @@ function PrivacyControls({
|
|
|
2997
3349
|
}
|
|
2998
3350
|
)
|
|
2999
3351
|
] }),
|
|
3000
|
-
confirming ? /* @__PURE__ */
|
|
3001
|
-
/* @__PURE__ */
|
|
3352
|
+
confirming ? /* @__PURE__ */ jsxs16("div", { className: "b316-privacy-confirm", children: [
|
|
3353
|
+
/* @__PURE__ */ jsxs16("label", { className: "b316-label", htmlFor: "b316-privacy-confirm", children: [
|
|
3002
3354
|
"Type ",
|
|
3003
3355
|
confirmWord,
|
|
3004
3356
|
" to confirm"
|
|
3005
3357
|
] }),
|
|
3006
|
-
/* @__PURE__ */
|
|
3358
|
+
/* @__PURE__ */ jsx17(
|
|
3007
3359
|
"input",
|
|
3008
3360
|
{
|
|
3009
3361
|
id: "b316-privacy-confirm",
|
|
@@ -3013,8 +3365,8 @@ function PrivacyControls({
|
|
|
3013
3365
|
onChange: (event) => setTyped(event.target.value)
|
|
3014
3366
|
}
|
|
3015
3367
|
),
|
|
3016
|
-
/* @__PURE__ */
|
|
3017
|
-
/* @__PURE__ */
|
|
3368
|
+
/* @__PURE__ */ jsxs16("div", { className: "b316-privacy-actions", children: [
|
|
3369
|
+
/* @__PURE__ */ jsx17(
|
|
3018
3370
|
"button",
|
|
3019
3371
|
{
|
|
3020
3372
|
type: "button",
|
|
@@ -3026,7 +3378,7 @@ function PrivacyControls({
|
|
|
3026
3378
|
children: "Cancel"
|
|
3027
3379
|
}
|
|
3028
3380
|
),
|
|
3029
|
-
/* @__PURE__ */
|
|
3381
|
+
/* @__PURE__ */ jsx17(
|
|
3030
3382
|
"button",
|
|
3031
3383
|
{
|
|
3032
3384
|
type: "button",
|
|
@@ -3042,12 +3394,12 @@ function PrivacyControls({
|
|
|
3042
3394
|
}
|
|
3043
3395
|
|
|
3044
3396
|
// src/TwoFactorManager.tsx
|
|
3045
|
-
import { useState as
|
|
3397
|
+
import { useState as useState15 } from "react";
|
|
3046
3398
|
|
|
3047
3399
|
// src/QrCode.tsx
|
|
3048
3400
|
import qrcode from "qrcode-generator";
|
|
3049
3401
|
import { useMemo as useMemo2 } from "react";
|
|
3050
|
-
import { jsx as
|
|
3402
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3051
3403
|
var QUIET_ZONE = 4;
|
|
3052
3404
|
function utf8Binary(value) {
|
|
3053
3405
|
let binary = "";
|
|
@@ -3074,7 +3426,7 @@ function qrPath(value) {
|
|
|
3074
3426
|
function QrCode({ value, label, size = 180, className }) {
|
|
3075
3427
|
const { path, modules } = useMemo2(() => qrPath(value), [value]);
|
|
3076
3428
|
const extent = modules + QUIET_ZONE * 2;
|
|
3077
|
-
return /* @__PURE__ */
|
|
3429
|
+
return /* @__PURE__ */ jsxs17(
|
|
3078
3430
|
"svg",
|
|
3079
3431
|
{
|
|
3080
3432
|
className,
|
|
@@ -3086,15 +3438,15 @@ function QrCode({ value, label, size = 180, className }) {
|
|
|
3086
3438
|
shapeRendering: "crispEdges",
|
|
3087
3439
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3088
3440
|
children: [
|
|
3089
|
-
/* @__PURE__ */
|
|
3090
|
-
/* @__PURE__ */
|
|
3441
|
+
/* @__PURE__ */ jsx18("rect", { width: extent, height: extent, fill: "#ffffff" }),
|
|
3442
|
+
/* @__PURE__ */ jsx18("path", { d: path, fill: "#000000" })
|
|
3091
3443
|
]
|
|
3092
3444
|
}
|
|
3093
3445
|
);
|
|
3094
3446
|
}
|
|
3095
3447
|
|
|
3096
3448
|
// src/TwoFactorManager.tsx
|
|
3097
|
-
import { jsx as
|
|
3449
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3098
3450
|
function groupKey(secret) {
|
|
3099
3451
|
return secret.replace(/\s+/g, "").replace(/(.{4})(?=.)/g, "$1 ");
|
|
3100
3452
|
}
|
|
@@ -3107,12 +3459,12 @@ function TwoFactorManager({
|
|
|
3107
3459
|
style
|
|
3108
3460
|
}) {
|
|
3109
3461
|
const { client, token } = useBase316();
|
|
3110
|
-
const [stage, setStage] =
|
|
3111
|
-
const [on, setOn] =
|
|
3112
|
-
const [code, setCode] =
|
|
3113
|
-
const [phone, setPhone] =
|
|
3114
|
-
const [error, setError] =
|
|
3115
|
-
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);
|
|
3116
3468
|
if (!token) {
|
|
3117
3469
|
return null;
|
|
3118
3470
|
}
|
|
@@ -3190,17 +3542,17 @@ function TwoFactorManager({
|
|
|
3190
3542
|
setBusy(false);
|
|
3191
3543
|
}
|
|
3192
3544
|
}
|
|
3193
|
-
return /* @__PURE__ */
|
|
3194
|
-
/* @__PURE__ */
|
|
3195
|
-
error ? /* @__PURE__ */
|
|
3196
|
-
stage.name === "saved" ? /* @__PURE__ */
|
|
3197
|
-
/* @__PURE__ */
|
|
3198
|
-
/* @__PURE__ */
|
|
3199
|
-
/* @__PURE__ */
|
|
3200
|
-
] }) : stage.name === "smsNumber" ? /* @__PURE__ */
|
|
3201
|
-
/* @__PURE__ */
|
|
3202
|
-
/* @__PURE__ */
|
|
3203
|
-
/* @__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(
|
|
3204
3556
|
"input",
|
|
3205
3557
|
{
|
|
3206
3558
|
id: "b316-mfa-phone",
|
|
@@ -3212,8 +3564,8 @@ function TwoFactorManager({
|
|
|
3212
3564
|
onChange: (event) => setPhone(event.target.value)
|
|
3213
3565
|
}
|
|
3214
3566
|
),
|
|
3215
|
-
/* @__PURE__ */
|
|
3216
|
-
/* @__PURE__ */
|
|
3567
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3568
|
+
/* @__PURE__ */ jsx19(
|
|
3217
3569
|
"button",
|
|
3218
3570
|
{
|
|
3219
3571
|
type: "button",
|
|
@@ -3222,16 +3574,16 @@ function TwoFactorManager({
|
|
|
3222
3574
|
children: "Cancel"
|
|
3223
3575
|
}
|
|
3224
3576
|
),
|
|
3225
|
-
/* @__PURE__ */
|
|
3577
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "b316-button", disabled: busy, onClick: beginSms, children: busy ? "Sending\u2026" : "Send code" })
|
|
3226
3578
|
] })
|
|
3227
|
-
] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */
|
|
3228
|
-
/* @__PURE__ */
|
|
3579
|
+
] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-enrol", children: [
|
|
3580
|
+
/* @__PURE__ */ jsxs18("p", { children: [
|
|
3229
3581
|
"We sent a code to ",
|
|
3230
3582
|
stage.destinationHint,
|
|
3231
3583
|
". Enter it below to turn this on."
|
|
3232
3584
|
] }),
|
|
3233
|
-
/* @__PURE__ */
|
|
3234
|
-
/* @__PURE__ */
|
|
3585
|
+
/* @__PURE__ */ jsx19("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
|
|
3586
|
+
/* @__PURE__ */ jsx19(
|
|
3235
3587
|
"input",
|
|
3236
3588
|
{
|
|
3237
3589
|
id: "b316-mfa-code",
|
|
@@ -3242,8 +3594,8 @@ function TwoFactorManager({
|
|
|
3242
3594
|
onChange: (event) => setCode(event.target.value)
|
|
3243
3595
|
}
|
|
3244
3596
|
),
|
|
3245
|
-
/* @__PURE__ */
|
|
3246
|
-
/* @__PURE__ */
|
|
3597
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3598
|
+
/* @__PURE__ */ jsx19(
|
|
3247
3599
|
"button",
|
|
3248
3600
|
{
|
|
3249
3601
|
type: "button",
|
|
@@ -3252,7 +3604,7 @@ function TwoFactorManager({
|
|
|
3252
3604
|
children: "Cancel"
|
|
3253
3605
|
}
|
|
3254
3606
|
),
|
|
3255
|
-
/* @__PURE__ */
|
|
3607
|
+
/* @__PURE__ */ jsx19(
|
|
3256
3608
|
"button",
|
|
3257
3609
|
{
|
|
3258
3610
|
type: "button",
|
|
@@ -3263,9 +3615,9 @@ function TwoFactorManager({
|
|
|
3263
3615
|
}
|
|
3264
3616
|
)
|
|
3265
3617
|
] })
|
|
3266
|
-
] }) : stage.name === "enrolling" ? /* @__PURE__ */
|
|
3267
|
-
/* @__PURE__ */
|
|
3268
|
-
/* @__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(
|
|
3269
3621
|
QrCode,
|
|
3270
3622
|
{
|
|
3271
3623
|
className: "b316-mfa-qr",
|
|
@@ -3273,13 +3625,13 @@ function TwoFactorManager({
|
|
|
3273
3625
|
label: "QR code for your authenticator app"
|
|
3274
3626
|
}
|
|
3275
3627
|
),
|
|
3276
|
-
/* @__PURE__ */
|
|
3277
|
-
/* @__PURE__ */
|
|
3278
|
-
/* @__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) })
|
|
3279
3631
|
] }),
|
|
3280
|
-
/* @__PURE__ */
|
|
3281
|
-
/* @__PURE__ */
|
|
3282
|
-
/* @__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(
|
|
3283
3635
|
"input",
|
|
3284
3636
|
{
|
|
3285
3637
|
id: "b316-mfa-code",
|
|
@@ -3290,8 +3642,8 @@ function TwoFactorManager({
|
|
|
3290
3642
|
onChange: (event) => setCode(event.target.value)
|
|
3291
3643
|
}
|
|
3292
3644
|
),
|
|
3293
|
-
/* @__PURE__ */
|
|
3294
|
-
/* @__PURE__ */
|
|
3645
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3646
|
+
/* @__PURE__ */ jsx19(
|
|
3295
3647
|
"button",
|
|
3296
3648
|
{
|
|
3297
3649
|
type: "button",
|
|
@@ -3300,7 +3652,7 @@ function TwoFactorManager({
|
|
|
3300
3652
|
children: "Cancel"
|
|
3301
3653
|
}
|
|
3302
3654
|
),
|
|
3303
|
-
/* @__PURE__ */
|
|
3655
|
+
/* @__PURE__ */ jsx19(
|
|
3304
3656
|
"button",
|
|
3305
3657
|
{
|
|
3306
3658
|
type: "button",
|
|
@@ -3311,9 +3663,9 @@ function TwoFactorManager({
|
|
|
3311
3663
|
}
|
|
3312
3664
|
)
|
|
3313
3665
|
] })
|
|
3314
|
-
] }) : on ? /* @__PURE__ */
|
|
3315
|
-
/* @__PURE__ */
|
|
3316
|
-
/* @__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(
|
|
3317
3669
|
ConfirmButton,
|
|
3318
3670
|
{
|
|
3319
3671
|
className: "b316-button-quiet b316-danger",
|
|
@@ -3323,11 +3675,11 @@ function TwoFactorManager({
|
|
|
3323
3675
|
children: "Turn off"
|
|
3324
3676
|
}
|
|
3325
3677
|
)
|
|
3326
|
-
] }) : /* @__PURE__ */
|
|
3327
|
-
/* @__PURE__ */
|
|
3328
|
-
/* @__PURE__ */
|
|
3329
|
-
/* @__PURE__ */
|
|
3330
|
-
/* @__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(
|
|
3331
3683
|
"button",
|
|
3332
3684
|
{
|
|
3333
3685
|
type: "button",
|
|
@@ -3337,7 +3689,7 @@ function TwoFactorManager({
|
|
|
3337
3689
|
children: "Email me a code"
|
|
3338
3690
|
}
|
|
3339
3691
|
),
|
|
3340
|
-
allowSms ? /* @__PURE__ */
|
|
3692
|
+
allowSms ? /* @__PURE__ */ jsx19(
|
|
3341
3693
|
"button",
|
|
3342
3694
|
{
|
|
3343
3695
|
type: "button",
|
|
@@ -3353,14 +3705,14 @@ function TwoFactorManager({
|
|
|
3353
3705
|
}
|
|
3354
3706
|
|
|
3355
3707
|
// src/ForgotPassword.tsx
|
|
3356
|
-
import { useState as
|
|
3357
|
-
import { jsx as
|
|
3708
|
+
import { useState as useState16 } from "react";
|
|
3709
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3358
3710
|
function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
3359
3711
|
const { client } = useBase316();
|
|
3360
|
-
const [email, setEmail] =
|
|
3361
|
-
const [sent, setSent] =
|
|
3362
|
-
const [busy, setBusy] =
|
|
3363
|
-
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);
|
|
3364
3716
|
async function submit(event) {
|
|
3365
3717
|
event.preventDefault();
|
|
3366
3718
|
setBusy(true);
|
|
@@ -3376,22 +3728,22 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
|
3376
3728
|
}
|
|
3377
3729
|
}
|
|
3378
3730
|
if (sent) {
|
|
3379
|
-
return /* @__PURE__ */
|
|
3380
|
-
/* @__PURE__ */
|
|
3381
|
-
/* @__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: [
|
|
3382
3734
|
"If there is an account for ",
|
|
3383
3735
|
email.trim(),
|
|
3384
3736
|
", a link to set a new password is on its way."
|
|
3385
3737
|
] }),
|
|
3386
|
-
signInUrl ? /* @__PURE__ */
|
|
3738
|
+
signInUrl ? /* @__PURE__ */ jsx20("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
|
|
3387
3739
|
] });
|
|
3388
3740
|
}
|
|
3389
|
-
return /* @__PURE__ */
|
|
3390
|
-
/* @__PURE__ */
|
|
3391
|
-
error ? /* @__PURE__ */
|
|
3392
|
-
/* @__PURE__ */
|
|
3393
|
-
/* @__PURE__ */
|
|
3394
|
-
/* @__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(
|
|
3395
3747
|
"input",
|
|
3396
3748
|
{
|
|
3397
3749
|
id: "b316-forgot-email",
|
|
@@ -3404,14 +3756,14 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
|
3404
3756
|
}
|
|
3405
3757
|
)
|
|
3406
3758
|
] }),
|
|
3407
|
-
/* @__PURE__ */
|
|
3408
|
-
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
|
|
3409
3761
|
] });
|
|
3410
3762
|
}
|
|
3411
3763
|
|
|
3412
3764
|
// src/ResetPassword.tsx
|
|
3413
|
-
import { useEffect as
|
|
3414
|
-
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";
|
|
3415
3767
|
function ResetPassword({
|
|
3416
3768
|
token: supplied,
|
|
3417
3769
|
onReset,
|
|
@@ -3420,13 +3772,13 @@ function ResetPassword({
|
|
|
3420
3772
|
style
|
|
3421
3773
|
}) {
|
|
3422
3774
|
const { client } = useBase316();
|
|
3423
|
-
const [token, setToken] =
|
|
3424
|
-
const [password, setPassword] =
|
|
3425
|
-
const [confirmation, setConfirmation] =
|
|
3426
|
-
const [done, setDone] =
|
|
3427
|
-
const [busy, setBusy] =
|
|
3428
|
-
const [error, setError] =
|
|
3429
|
-
|
|
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(() => {
|
|
3430
3782
|
if (supplied || typeof window === "undefined") {
|
|
3431
3783
|
return;
|
|
3432
3784
|
}
|
|
@@ -3461,24 +3813,24 @@ function ResetPassword({
|
|
|
3461
3813
|
}
|
|
3462
3814
|
}
|
|
3463
3815
|
if (done) {
|
|
3464
|
-
return /* @__PURE__ */
|
|
3465
|
-
/* @__PURE__ */
|
|
3466
|
-
/* @__PURE__ */
|
|
3467
|
-
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
|
|
3468
3820
|
] });
|
|
3469
3821
|
}
|
|
3470
3822
|
if (!token) {
|
|
3471
|
-
return /* @__PURE__ */
|
|
3472
|
-
/* @__PURE__ */
|
|
3473
|
-
/* @__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." })
|
|
3474
3826
|
] });
|
|
3475
3827
|
}
|
|
3476
|
-
return /* @__PURE__ */
|
|
3477
|
-
/* @__PURE__ */
|
|
3478
|
-
error ? /* @__PURE__ */
|
|
3479
|
-
/* @__PURE__ */
|
|
3480
|
-
/* @__PURE__ */
|
|
3481
|
-
/* @__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(
|
|
3482
3834
|
"input",
|
|
3483
3835
|
{
|
|
3484
3836
|
id: "b316-reset-password",
|
|
@@ -3491,9 +3843,9 @@ function ResetPassword({
|
|
|
3491
3843
|
}
|
|
3492
3844
|
)
|
|
3493
3845
|
] }),
|
|
3494
|
-
/* @__PURE__ */
|
|
3495
|
-
/* @__PURE__ */
|
|
3496
|
-
/* @__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(
|
|
3497
3849
|
"input",
|
|
3498
3850
|
{
|
|
3499
3851
|
id: "b316-reset-confirm",
|
|
@@ -3506,13 +3858,13 @@ function ResetPassword({
|
|
|
3506
3858
|
}
|
|
3507
3859
|
)
|
|
3508
3860
|
] }),
|
|
3509
|
-
/* @__PURE__ */
|
|
3861
|
+
/* @__PURE__ */ jsx21("button", { type: "submit", className: "b316-button", disabled: busy || !password, children: busy ? "Saving\u2026" : "Set password" })
|
|
3510
3862
|
] });
|
|
3511
3863
|
}
|
|
3512
3864
|
|
|
3513
3865
|
// src/VerifyEmail.tsx
|
|
3514
|
-
import { useEffect as
|
|
3515
|
-
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";
|
|
3516
3868
|
function VerifyEmail({
|
|
3517
3869
|
token: supplied,
|
|
3518
3870
|
onVerified,
|
|
@@ -3521,9 +3873,9 @@ function VerifyEmail({
|
|
|
3521
3873
|
style
|
|
3522
3874
|
}) {
|
|
3523
3875
|
const { client } = useBase316();
|
|
3524
|
-
const [state, setState] =
|
|
3876
|
+
const [state, setState] = useState18("waiting");
|
|
3525
3877
|
const spent = useRef4(false);
|
|
3526
|
-
|
|
3878
|
+
useEffect14(() => {
|
|
3527
3879
|
if (spent.current) {
|
|
3528
3880
|
return;
|
|
3529
3881
|
}
|
|
@@ -3549,22 +3901,22 @@ function VerifyEmail({
|
|
|
3549
3901
|
setState("failed");
|
|
3550
3902
|
});
|
|
3551
3903
|
}, [client, supplied, onVerified]);
|
|
3552
|
-
return /* @__PURE__ */
|
|
3553
|
-
/* @__PURE__ */
|
|
3554
|
-
/* @__PURE__ */
|
|
3555
|
-
continueUrl ? /* @__PURE__ */
|
|
3556
|
-
] }) : state === "failed" ? /* @__PURE__ */
|
|
3557
|
-
/* @__PURE__ */
|
|
3558
|
-
/* @__PURE__ */
|
|
3559
|
-
] }) : state === "missing" ? /* @__PURE__ */
|
|
3560
|
-
/* @__PURE__ */
|
|
3561
|
-
/* @__PURE__ */
|
|
3562
|
-
] }) : /* @__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" }) });
|
|
3563
3915
|
}
|
|
3564
3916
|
|
|
3565
3917
|
// src/TeamMembers.tsx
|
|
3566
|
-
import { useCallback as useCallback7, useEffect as
|
|
3567
|
-
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";
|
|
3568
3920
|
function TeamMembers({
|
|
3569
3921
|
organizationId,
|
|
3570
3922
|
onInvited,
|
|
@@ -3574,13 +3926,13 @@ function TeamMembers({
|
|
|
3574
3926
|
style
|
|
3575
3927
|
}) {
|
|
3576
3928
|
const { client, token, session } = useBase316();
|
|
3577
|
-
const [teams, setTeams] =
|
|
3578
|
-
const [members, setMembers] =
|
|
3579
|
-
const [invitations, setInvitations] =
|
|
3580
|
-
const [email, setEmail] =
|
|
3581
|
-
const [busy, setBusy] =
|
|
3582
|
-
const [error, setError] =
|
|
3583
|
-
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);
|
|
3584
3936
|
const chosen = organizationId ?? (teams?.length === 1 ? teams[0].id : null);
|
|
3585
3937
|
const team = teams?.find((candidate) => candidate.id === chosen) ?? null;
|
|
3586
3938
|
const load = useCallback7(() => {
|
|
@@ -3591,8 +3943,8 @@ function TeamMembers({
|
|
|
3591
3943
|
(cause) => setError(cause instanceof Error ? cause.message : "Could not load your teams.")
|
|
3592
3944
|
);
|
|
3593
3945
|
}, [client, token]);
|
|
3594
|
-
|
|
3595
|
-
|
|
3946
|
+
useEffect15(load, [load]);
|
|
3947
|
+
useEffect15(() => {
|
|
3596
3948
|
if (!token || !chosen) {
|
|
3597
3949
|
return;
|
|
3598
3950
|
}
|
|
@@ -3623,10 +3975,10 @@ function TeamMembers({
|
|
|
3623
3975
|
return null;
|
|
3624
3976
|
}
|
|
3625
3977
|
if (!teams) {
|
|
3626
|
-
return /* @__PURE__ */
|
|
3978
|
+
return /* @__PURE__ */ jsx23("div", { className: cls("b316-card", className), style, children: error ?? "Loading\u2026" });
|
|
3627
3979
|
}
|
|
3628
3980
|
if (!chosen) {
|
|
3629
|
-
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." });
|
|
3630
3982
|
}
|
|
3631
3983
|
const canManage = invitations !== null;
|
|
3632
3984
|
async function invite(event) {
|
|
@@ -3676,30 +4028,30 @@ function TeamMembers({
|
|
|
3676
4028
|
setError(cause instanceof Error ? cause.message : "That invitation could not be withdrawn.");
|
|
3677
4029
|
}
|
|
3678
4030
|
}
|
|
3679
|
-
return /* @__PURE__ */
|
|
3680
|
-
/* @__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" }),
|
|
3681
4033
|
team?.inherited ? (
|
|
3682
4034
|
// Not a member of this team, so not in the list below and with nothing
|
|
3683
4035
|
// to leave: access comes from the team that manages it, and ends there.
|
|
3684
|
-
/* @__PURE__ */
|
|
4036
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-muted", children: [
|
|
3685
4037
|
"You have access through",
|
|
3686
4038
|
" ",
|
|
3687
4039
|
teams.find((candidate) => candidate.id === team.via)?.name ?? "the organization that manages this team",
|
|
3688
4040
|
"."
|
|
3689
4041
|
] })
|
|
3690
4042
|
) : null,
|
|
3691
|
-
error ? /* @__PURE__ */
|
|
3692
|
-
/* @__PURE__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
/* @__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: [
|
|
3696
4048
|
member.user.email,
|
|
3697
4049
|
member.user.id === session?.userId ? " \xB7 you" : ""
|
|
3698
4050
|
] })
|
|
3699
4051
|
] }),
|
|
3700
|
-
/* @__PURE__ */
|
|
3701
|
-
/* @__PURE__ */
|
|
3702
|
-
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(
|
|
3703
4055
|
ConfirmButton,
|
|
3704
4056
|
{
|
|
3705
4057
|
className: "b316-button-quiet b316-danger",
|
|
@@ -3711,19 +4063,19 @@ function TeamMembers({
|
|
|
3711
4063
|
) : null
|
|
3712
4064
|
] })
|
|
3713
4065
|
] }, member.id)) }),
|
|
3714
|
-
canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */
|
|
3715
|
-
/* @__PURE__ */
|
|
3716
|
-
/* @__PURE__ */
|
|
3717
|
-
/* @__PURE__ */
|
|
3718
|
-
/* @__PURE__ */
|
|
3719
|
-
/* @__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: [
|
|
3720
4072
|
invitation.role.name,
|
|
3721
4073
|
" \xB7 expires",
|
|
3722
4074
|
" ",
|
|
3723
4075
|
new Date(invitation.expiresAt).toLocaleDateString()
|
|
3724
4076
|
] })
|
|
3725
4077
|
] }),
|
|
3726
|
-
/* @__PURE__ */
|
|
4078
|
+
/* @__PURE__ */ jsx23(
|
|
3727
4079
|
"button",
|
|
3728
4080
|
{
|
|
3729
4081
|
type: "button",
|
|
@@ -3734,10 +4086,10 @@ function TeamMembers({
|
|
|
3734
4086
|
)
|
|
3735
4087
|
] }, invitation.id)) })
|
|
3736
4088
|
] }) : null,
|
|
3737
|
-
canManage ? /* @__PURE__ */
|
|
3738
|
-
/* @__PURE__ */
|
|
3739
|
-
/* @__PURE__ */
|
|
3740
|
-
/* @__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(
|
|
3741
4093
|
"input",
|
|
3742
4094
|
{
|
|
3743
4095
|
id: "b316-invite-email",
|
|
@@ -3749,19 +4101,19 @@ function TeamMembers({
|
|
|
3749
4101
|
onChange: (event) => setEmail(event.target.value)
|
|
3750
4102
|
}
|
|
3751
4103
|
),
|
|
3752
|
-
/* @__PURE__ */
|
|
4104
|
+
/* @__PURE__ */ jsx23("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Invite" })
|
|
3753
4105
|
] })
|
|
3754
4106
|
] }) : null,
|
|
3755
|
-
copied ? /* @__PURE__ */
|
|
3756
|
-
/* @__PURE__ */
|
|
3757
|
-
/* @__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 })
|
|
3758
4110
|
] }) : null
|
|
3759
4111
|
] });
|
|
3760
4112
|
}
|
|
3761
4113
|
|
|
3762
4114
|
// src/AcceptInvitation.tsx
|
|
3763
|
-
import { useEffect as
|
|
3764
|
-
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";
|
|
3765
4117
|
function signUpUrlWithInvitation(url, token) {
|
|
3766
4118
|
const [beforeHash, ...hash] = url.split("#");
|
|
3767
4119
|
const base = beforeHash ?? "";
|
|
@@ -3780,18 +4132,18 @@ function AcceptInvitation({
|
|
|
3780
4132
|
style
|
|
3781
4133
|
}) {
|
|
3782
4134
|
const { client, token: session, session: user } = useBase316();
|
|
3783
|
-
const [invitationToken, setInvitationToken] =
|
|
3784
|
-
const [preview, setPreview] =
|
|
3785
|
-
const [state, setState] =
|
|
3786
|
-
const [error, setError] =
|
|
3787
|
-
const [busy, setBusy] =
|
|
3788
|
-
|
|
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(() => {
|
|
3789
4141
|
if (supplied || typeof window === "undefined") {
|
|
3790
4142
|
return;
|
|
3791
4143
|
}
|
|
3792
4144
|
setInvitationToken(new URL(window.location.href).searchParams.get("invitation"));
|
|
3793
4145
|
}, [supplied]);
|
|
3794
|
-
|
|
4146
|
+
useEffect16(() => {
|
|
3795
4147
|
if (!invitationToken) {
|
|
3796
4148
|
setState(supplied === void 0 ? "loading" : "invalid");
|
|
3797
4149
|
return;
|
|
@@ -3828,42 +4180,42 @@ function AcceptInvitation({
|
|
|
3828
4180
|
}
|
|
3829
4181
|
}
|
|
3830
4182
|
if (state === "loading") {
|
|
3831
|
-
return /* @__PURE__ */
|
|
4183
|
+
return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
3832
4184
|
}
|
|
3833
4185
|
if (state === "invalid") {
|
|
3834
|
-
return /* @__PURE__ */
|
|
3835
|
-
/* @__PURE__ */
|
|
3836
|
-
/* @__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." })
|
|
3837
4189
|
] });
|
|
3838
4190
|
}
|
|
3839
4191
|
if (state === "accepted") {
|
|
3840
|
-
return /* @__PURE__ */
|
|
4192
|
+
return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsxs23("h3", { className: "b316-form-title", children: [
|
|
3841
4193
|
"You have joined ",
|
|
3842
4194
|
preview?.organizationName
|
|
3843
4195
|
] }) });
|
|
3844
4196
|
}
|
|
3845
4197
|
const matches = !user || (user.user.email ?? "").toLowerCase() === preview?.email.toLowerCase();
|
|
3846
|
-
return /* @__PURE__ */
|
|
3847
|
-
/* @__PURE__ */
|
|
4198
|
+
return /* @__PURE__ */ jsxs23("div", { className: cls("b316-card b316-invitation", className), style, children: [
|
|
4199
|
+
/* @__PURE__ */ jsxs23("h3", { className: "b316-form-title", children: [
|
|
3848
4200
|
"Join ",
|
|
3849
4201
|
preview?.organizationName
|
|
3850
4202
|
] }),
|
|
3851
|
-
/* @__PURE__ */
|
|
4203
|
+
/* @__PURE__ */ jsxs23("p", { className: "b316-muted", children: [
|
|
3852
4204
|
"Invited as ",
|
|
3853
4205
|
preview?.email,
|
|
3854
4206
|
" \xB7 ",
|
|
3855
4207
|
preview?.roleName
|
|
3856
4208
|
] }),
|
|
3857
|
-
error ? /* @__PURE__ */
|
|
3858
|
-
!session ? /* @__PURE__ */
|
|
3859
|
-
/* @__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: [
|
|
3860
4212
|
"Sign in as ",
|
|
3861
4213
|
preview?.email,
|
|
3862
4214
|
" to accept."
|
|
3863
4215
|
] }),
|
|
3864
|
-
/* @__PURE__ */
|
|
3865
|
-
signInUrl ? /* @__PURE__ */
|
|
3866
|
-
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(
|
|
3867
4219
|
"a",
|
|
3868
4220
|
{
|
|
3869
4221
|
className: "b316-button-link",
|
|
@@ -3876,20 +4228,20 @@ function AcceptInvitation({
|
|
|
3876
4228
|
// Said before they press anything. The server refuses this, but
|
|
3877
4229
|
// finding out after a click reads as a broken invitation rather than
|
|
3878
4230
|
// as being signed in as the wrong person.
|
|
3879
|
-
/* @__PURE__ */
|
|
4231
|
+
/* @__PURE__ */ jsxs23("p", { children: [
|
|
3880
4232
|
"You are signed in as ",
|
|
3881
4233
|
user?.user.email,
|
|
3882
4234
|
". This invitation was sent to ",
|
|
3883
4235
|
preview?.email,
|
|
3884
4236
|
" \u2014 sign in as that address to accept it."
|
|
3885
4237
|
] })
|
|
3886
|
-
) : /* @__PURE__ */
|
|
4238
|
+
) : /* @__PURE__ */ jsx24("button", { type: "button", className: "b316-button", disabled: busy, onClick: accept, children: busy ? "Joining\u2026" : `Join ${preview?.organizationName}` })
|
|
3887
4239
|
] });
|
|
3888
4240
|
}
|
|
3889
4241
|
|
|
3890
4242
|
// src/PayInvoice.tsx
|
|
3891
|
-
import { useEffect as
|
|
3892
|
-
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";
|
|
3893
4245
|
var STRIPE_SRC = "https://js.stripe.com/v3/";
|
|
3894
4246
|
function loadStripeScript() {
|
|
3895
4247
|
if (typeof window === "undefined") {
|
|
@@ -3924,11 +4276,11 @@ function PayInvoice({
|
|
|
3924
4276
|
const mountRef = useRef5(null);
|
|
3925
4277
|
const stripeRef = useRef5(null);
|
|
3926
4278
|
const elementsRef = useRef5(null);
|
|
3927
|
-
const [ready, setReady] =
|
|
3928
|
-
const [paying, setPaying] =
|
|
3929
|
-
const [done, setDone] =
|
|
3930
|
-
const [error, setError] =
|
|
3931
|
-
|
|
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(() => {
|
|
3932
4284
|
let cancelled = false;
|
|
3933
4285
|
async function start() {
|
|
3934
4286
|
const base = `${client.baseUrl}/pay/${encodeURIComponent(environmentId)}/${encodeURIComponent(token)}`;
|
|
@@ -3981,17 +4333,17 @@ function PayInvoice({
|
|
|
3981
4333
|
onPaid?.();
|
|
3982
4334
|
};
|
|
3983
4335
|
if (done) {
|
|
3984
|
-
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." }) });
|
|
3985
4337
|
}
|
|
3986
|
-
return /* @__PURE__ */
|
|
3987
|
-
error ? /* @__PURE__ */
|
|
3988
|
-
/* @__PURE__ */
|
|
3989
|
-
/* @__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" })
|
|
3990
4342
|
] });
|
|
3991
4343
|
}
|
|
3992
4344
|
|
|
3993
4345
|
// src/usePaymentLink.ts
|
|
3994
|
-
import { useEffect as
|
|
4346
|
+
import { useEffect as useEffect18, useRef as useRef6, useState as useState22 } from "react";
|
|
3995
4347
|
function usePaymentLink({
|
|
3996
4348
|
token,
|
|
3997
4349
|
environmentId,
|
|
@@ -3999,10 +4351,10 @@ function usePaymentLink({
|
|
|
3999
4351
|
onPaid
|
|
4000
4352
|
}) {
|
|
4001
4353
|
const { client } = useBase316();
|
|
4002
|
-
const [status2, setStatus] =
|
|
4354
|
+
const [status2, setStatus] = useState22({ state: "loading" });
|
|
4003
4355
|
const onPaidRef = useRef6(onPaid);
|
|
4004
4356
|
onPaidRef.current = onPaid;
|
|
4005
|
-
|
|
4357
|
+
useEffect18(() => {
|
|
4006
4358
|
let stopped = false;
|
|
4007
4359
|
let timer;
|
|
4008
4360
|
const statusUrl = `${client.baseUrl}/pay/${encodeURIComponent(environmentId)}/${encodeURIComponent(token)}/status`;
|
|
@@ -4051,23 +4403,23 @@ function usePaymentLink({
|
|
|
4051
4403
|
}
|
|
4052
4404
|
|
|
4053
4405
|
// src/PricingTable.tsx
|
|
4054
|
-
import { useState as
|
|
4406
|
+
import { useState as useState24 } from "react";
|
|
4055
4407
|
|
|
4056
4408
|
// src/usePlans.ts
|
|
4057
|
-
import { useCallback as useCallback8, useEffect as
|
|
4409
|
+
import { useCallback as useCallback8, useEffect as useEffect19, useState as useState23 } from "react";
|
|
4058
4410
|
var CHECKOUT_STATUSES = /* @__PURE__ */ new Set([402, 409]);
|
|
4059
4411
|
function usePlans(options = {}) {
|
|
4060
4412
|
const { client, token } = useBase316();
|
|
4061
|
-
const [plans, setPlans] =
|
|
4062
|
-
const [error, setError] =
|
|
4063
|
-
const [busyPlanVersionId, setBusy] =
|
|
4064
|
-
const [lastError, setLastError] =
|
|
4065
|
-
const [ownPlanVersionId, setOwnPlanVersionId] =
|
|
4066
|
-
const [managedBy, setManagedBy] =
|
|
4067
|
-
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);
|
|
4068
4420
|
const supplied = options.currentPlanVersionId;
|
|
4069
4421
|
const discover = supplied === void 0;
|
|
4070
|
-
|
|
4422
|
+
useEffect19(() => {
|
|
4071
4423
|
let cancelled = false;
|
|
4072
4424
|
client.billing.plans().then((result) => {
|
|
4073
4425
|
if (!cancelled) {
|
|
@@ -4083,7 +4435,7 @@ function usePlans(options = {}) {
|
|
|
4083
4435
|
cancelled = true;
|
|
4084
4436
|
};
|
|
4085
4437
|
}, [client, reloadCount]);
|
|
4086
|
-
|
|
4438
|
+
useEffect19(() => {
|
|
4087
4439
|
if (!token) {
|
|
4088
4440
|
return;
|
|
4089
4441
|
}
|
|
@@ -4172,7 +4524,7 @@ function usePlans(options = {}) {
|
|
|
4172
4524
|
}
|
|
4173
4525
|
|
|
4174
4526
|
// src/PricingTable.tsx
|
|
4175
|
-
import { jsx as
|
|
4527
|
+
import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
4176
4528
|
function formatAmount(amount, currency) {
|
|
4177
4529
|
if (amount === null) return "Free";
|
|
4178
4530
|
const value = Number(amount);
|
|
@@ -4221,7 +4573,7 @@ function PricingTable({
|
|
|
4221
4573
|
managedBy,
|
|
4222
4574
|
selectPlan
|
|
4223
4575
|
} = usePlans({ currentPlanVersionId });
|
|
4224
|
-
const [scheduled, setScheduled] =
|
|
4576
|
+
const [scheduled, setScheduled] = useState24(null);
|
|
4225
4577
|
async function choose(plan) {
|
|
4226
4578
|
if (onSelectPlan) {
|
|
4227
4579
|
await onSelectPlan(plan.planVersionId, plan);
|
|
@@ -4238,50 +4590,50 @@ function PricingTable({
|
|
|
4238
4590
|
}
|
|
4239
4591
|
}
|
|
4240
4592
|
if (error) {
|
|
4241
|
-
return /* @__PURE__ */
|
|
4593
|
+
return /* @__PURE__ */ jsx26("div", { className: cls("b316-card", className), style, children: "Plans are unavailable right now." });
|
|
4242
4594
|
}
|
|
4243
4595
|
if (!plans) {
|
|
4244
|
-
return /* @__PURE__ */
|
|
4596
|
+
return /* @__PURE__ */ jsx26("div", { className: cls("b316-card", className), style, children: "Loading plans\u2026" });
|
|
4245
4597
|
}
|
|
4246
4598
|
if (plans.length === 0) {
|
|
4247
|
-
return /* @__PURE__ */
|
|
4599
|
+
return /* @__PURE__ */ jsx26("div", { className: cls("b316-card", className), style, children: "No plans are published yet." });
|
|
4248
4600
|
}
|
|
4249
4601
|
const anyTrial = plans.some((plan) => Boolean(plan.trialDays));
|
|
4250
4602
|
const anyDescription = plans.some((plan) => Boolean(plan.description));
|
|
4251
4603
|
const anyFeatured = plans.some((plan) => plan.key === featuredPlanKey);
|
|
4252
|
-
return /* @__PURE__ */
|
|
4604
|
+
return /* @__PURE__ */ jsxs25("div", { className: cls("b316-plans", className), style, children: [
|
|
4253
4605
|
managedBy ? (
|
|
4254
4606
|
// A client company's plan comes from the firm that runs it. The table
|
|
4255
4607
|
// still shows what is on offer, with the current plan marked, but
|
|
4256
4608
|
// nothing here can be bought: it would grant this account nothing.
|
|
4257
|
-
/* @__PURE__ */
|
|
4609
|
+
/* @__PURE__ */ jsxs25("div", { className: "b316-plans-managed b316-muted", children: [
|
|
4258
4610
|
"Your plan is provided by ",
|
|
4259
4611
|
managedBy.name ?? "the organization that manages your account",
|
|
4260
4612
|
". Ask them to change it."
|
|
4261
4613
|
] })
|
|
4262
|
-
) : 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,
|
|
4263
4615
|
plans.map((plan) => {
|
|
4264
4616
|
const base = plan.prices.find((price) => price.featureId === null) ?? plan.prices[0];
|
|
4265
4617
|
const isCurrent = current === plan.planVersionId;
|
|
4266
4618
|
const featured = featuredPlanKey === plan.key;
|
|
4267
|
-
return /* @__PURE__ */
|
|
4619
|
+
return /* @__PURE__ */ jsxs25(
|
|
4268
4620
|
"div",
|
|
4269
4621
|
{
|
|
4270
4622
|
className: featured ? "b316-card b316-plan b316-plan-featured" : "b316-card b316-plan",
|
|
4271
4623
|
children: [
|
|
4272
|
-
/* @__PURE__ */
|
|
4273
|
-
anyFeatured ? /* @__PURE__ */
|
|
4274
|
-
/* @__PURE__ */
|
|
4275
|
-
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
|
|
4276
4628
|
] }),
|
|
4277
|
-
/* @__PURE__ */
|
|
4278
|
-
/* @__PURE__ */
|
|
4279
|
-
/* @__PURE__ */
|
|
4280
|
-
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
|
|
4281
4633
|
] }),
|
|
4282
|
-
/* @__PURE__ */
|
|
4283
|
-
/* @__PURE__ */
|
|
4284
|
-
/* @__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" : (
|
|
4285
4637
|
// A usage price on the feature makes the limit an
|
|
4286
4638
|
// allowance billed past, not a ceiling — the same
|
|
4287
4639
|
// rule `check()` applies (any non-FLAT price).
|
|
@@ -4290,7 +4642,7 @@ function PricingTable({
|
|
|
4290
4642
|
) ? `${entitlement.limit} included` : entitlement.limit
|
|
4291
4643
|
) })
|
|
4292
4644
|
] }, entitlement.featureId)) }),
|
|
4293
|
-
/* @__PURE__ */
|
|
4645
|
+
/* @__PURE__ */ jsx26("div", { className: "b316-plan-action", children: /* @__PURE__ */ jsx26(
|
|
4294
4646
|
"button",
|
|
4295
4647
|
{
|
|
4296
4648
|
type: "button",
|
|
@@ -4312,14 +4664,14 @@ function PricingTable({
|
|
|
4312
4664
|
|
|
4313
4665
|
// src/DataTable.tsx
|
|
4314
4666
|
import { specFor as specFor3 } from "@base316/sdk";
|
|
4315
|
-
import { useState as
|
|
4667
|
+
import { useState as useState28 } from "react";
|
|
4316
4668
|
|
|
4317
4669
|
// src/fields.tsx
|
|
4318
4670
|
import {
|
|
4319
4671
|
formatAddress,
|
|
4320
4672
|
specFor
|
|
4321
4673
|
} from "@base316/sdk";
|
|
4322
|
-
import { jsx as
|
|
4674
|
+
import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4323
4675
|
function formatNumber(value, fraction = 0) {
|
|
4324
4676
|
const number = Number(value);
|
|
4325
4677
|
return Number.isFinite(number) ? new Intl.NumberFormat(void 0, {
|
|
@@ -4341,10 +4693,10 @@ function formatDuration(value) {
|
|
|
4341
4693
|
}
|
|
4342
4694
|
function FieldCell({ value, field, related }) {
|
|
4343
4695
|
if (field.type === "RELATION") {
|
|
4344
|
-
return related?.title ?? (related?.id ? /* @__PURE__ */
|
|
4696
|
+
return related?.title ?? (related?.id ? /* @__PURE__ */ jsx27("code", { className: "b316-muted", children: related.id }) : "\u2014");
|
|
4345
4697
|
}
|
|
4346
4698
|
if (value === null || value === void 0 || value === "") {
|
|
4347
|
-
return /* @__PURE__ */
|
|
4699
|
+
return /* @__PURE__ */ jsx27("span", { className: "b316-muted", children: "\u2014" });
|
|
4348
4700
|
}
|
|
4349
4701
|
switch (field.type) {
|
|
4350
4702
|
case "BOOLEAN":
|
|
@@ -4357,9 +4709,9 @@ function FieldCell({ value, field, related }) {
|
|
|
4357
4709
|
return formatDuration(value);
|
|
4358
4710
|
case "RATING": {
|
|
4359
4711
|
const stars = Math.round(Number(value));
|
|
4360
|
-
return /* @__PURE__ */
|
|
4712
|
+
return /* @__PURE__ */ jsxs26("span", { "aria-label": `${stars} out of 5`, children: [
|
|
4361
4713
|
"\u2605".repeat(stars),
|
|
4362
|
-
/* @__PURE__ */
|
|
4714
|
+
/* @__PURE__ */ jsx27("span", { className: "b316-muted", children: "\u2605".repeat(Math.max(0, 5 - stars)) })
|
|
4363
4715
|
] });
|
|
4364
4716
|
}
|
|
4365
4717
|
case "DATE":
|
|
@@ -4367,15 +4719,15 @@ function FieldCell({ value, field, related }) {
|
|
|
4367
4719
|
case "DATETIME":
|
|
4368
4720
|
return new Date(String(value)).toLocaleString();
|
|
4369
4721
|
case "SELECT":
|
|
4370
|
-
return /* @__PURE__ */
|
|
4722
|
+
return /* @__PURE__ */ jsx27("span", { className: "b316-chip", children: String(value) });
|
|
4371
4723
|
case "MULTISELECT":
|
|
4372
|
-
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))) });
|
|
4373
4725
|
case "URL":
|
|
4374
|
-
return /* @__PURE__ */
|
|
4726
|
+
return /* @__PURE__ */ jsx27("a", { href: String(value), target: "_blank", rel: "noreferrer noopener", children: String(value) });
|
|
4375
4727
|
case "EMAIL":
|
|
4376
|
-
return /* @__PURE__ */
|
|
4728
|
+
return /* @__PURE__ */ jsx27("a", { href: `mailto:${String(value)}`, children: String(value) });
|
|
4377
4729
|
case "PHONE":
|
|
4378
|
-
return /* @__PURE__ */
|
|
4730
|
+
return /* @__PURE__ */ jsx27("a", { href: `tel:${String(value)}`, children: String(value) });
|
|
4379
4731
|
case "ADDRESS":
|
|
4380
4732
|
return formatAddress(value);
|
|
4381
4733
|
case "ATTACHMENT": {
|
|
@@ -4387,7 +4739,7 @@ function FieldCell({ value, field, related }) {
|
|
|
4387
4739
|
return text.length > 80 ? `${text.slice(0, 80)}\u2026` : text;
|
|
4388
4740
|
}
|
|
4389
4741
|
case "JSON":
|
|
4390
|
-
return /* @__PURE__ */
|
|
4742
|
+
return /* @__PURE__ */ jsx27("code", { className: "b316-muted", children: JSON.stringify(value).slice(0, 60) });
|
|
4391
4743
|
default:
|
|
4392
4744
|
return String(value);
|
|
4393
4745
|
}
|
|
@@ -4408,7 +4760,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4408
4760
|
function control() {
|
|
4409
4761
|
switch (field.type) {
|
|
4410
4762
|
case "LONGTEXT":
|
|
4411
|
-
return /* @__PURE__ */
|
|
4763
|
+
return /* @__PURE__ */ jsx27(
|
|
4412
4764
|
"textarea",
|
|
4413
4765
|
{
|
|
4414
4766
|
...common,
|
|
@@ -4418,7 +4770,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4418
4770
|
}
|
|
4419
4771
|
);
|
|
4420
4772
|
case "BOOLEAN":
|
|
4421
|
-
return /* @__PURE__ */
|
|
4773
|
+
return /* @__PURE__ */ jsx27(
|
|
4422
4774
|
"input",
|
|
4423
4775
|
{
|
|
4424
4776
|
...common,
|
|
@@ -4429,22 +4781,22 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4429
4781
|
}
|
|
4430
4782
|
);
|
|
4431
4783
|
case "SELECT":
|
|
4432
|
-
return /* @__PURE__ */
|
|
4784
|
+
return /* @__PURE__ */ jsxs26(
|
|
4433
4785
|
"select",
|
|
4434
4786
|
{
|
|
4435
4787
|
...common,
|
|
4436
4788
|
value: value === null || value === void 0 ? "" : String(value),
|
|
4437
4789
|
onChange: (event) => onChange(event.target.value === "" ? null : event.target.value),
|
|
4438
4790
|
children: [
|
|
4439
|
-
field.required ? null : /* @__PURE__ */
|
|
4440
|
-
(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))
|
|
4441
4793
|
]
|
|
4442
4794
|
}
|
|
4443
4795
|
);
|
|
4444
4796
|
case "MULTISELECT": {
|
|
4445
4797
|
const selected = new Set(Array.isArray(value) ? value.map(String) : []);
|
|
4446
|
-
return /* @__PURE__ */
|
|
4447
|
-
/* @__PURE__ */
|
|
4798
|
+
return /* @__PURE__ */ jsx27("div", { className: "b316-choices", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxs26("label", { className: "b316-choice", children: [
|
|
4799
|
+
/* @__PURE__ */ jsx27(
|
|
4448
4800
|
"input",
|
|
4449
4801
|
{
|
|
4450
4802
|
type: "checkbox",
|
|
@@ -4467,7 +4819,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4467
4819
|
case "NUMBER":
|
|
4468
4820
|
case "MONEY":
|
|
4469
4821
|
case "PERCENT":
|
|
4470
|
-
return /* @__PURE__ */
|
|
4822
|
+
return /* @__PURE__ */ jsx27(
|
|
4471
4823
|
"input",
|
|
4472
4824
|
{
|
|
4473
4825
|
...common,
|
|
@@ -4478,7 +4830,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4478
4830
|
}
|
|
4479
4831
|
);
|
|
4480
4832
|
case "RATING":
|
|
4481
|
-
return /* @__PURE__ */
|
|
4833
|
+
return /* @__PURE__ */ jsx27(
|
|
4482
4834
|
"input",
|
|
4483
4835
|
{
|
|
4484
4836
|
...common,
|
|
@@ -4492,8 +4844,8 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4492
4844
|
);
|
|
4493
4845
|
case "DURATION": {
|
|
4494
4846
|
const minutes = value === null || value === void 0 ? "" : String(Number(value) / 60);
|
|
4495
|
-
return /* @__PURE__ */
|
|
4496
|
-
/* @__PURE__ */
|
|
4847
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-suffixed", children: [
|
|
4848
|
+
/* @__PURE__ */ jsx27(
|
|
4497
4849
|
"input",
|
|
4498
4850
|
{
|
|
4499
4851
|
...common,
|
|
@@ -4503,11 +4855,11 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4503
4855
|
onChange: (event) => onChange(event.target.value === "" ? null : Number(event.target.value) * 60)
|
|
4504
4856
|
}
|
|
4505
4857
|
),
|
|
4506
|
-
/* @__PURE__ */
|
|
4858
|
+
/* @__PURE__ */ jsx27("span", { className: "b316-muted", children: "minutes" })
|
|
4507
4859
|
] });
|
|
4508
4860
|
}
|
|
4509
4861
|
case "DATE":
|
|
4510
|
-
return /* @__PURE__ */
|
|
4862
|
+
return /* @__PURE__ */ jsx27(
|
|
4511
4863
|
"input",
|
|
4512
4864
|
{
|
|
4513
4865
|
...common,
|
|
@@ -4517,7 +4869,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4517
4869
|
}
|
|
4518
4870
|
);
|
|
4519
4871
|
case "DATETIME":
|
|
4520
|
-
return /* @__PURE__ */
|
|
4872
|
+
return /* @__PURE__ */ jsx27(
|
|
4521
4873
|
"input",
|
|
4522
4874
|
{
|
|
4523
4875
|
...common,
|
|
@@ -4530,7 +4882,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4530
4882
|
);
|
|
4531
4883
|
case "ADDRESS": {
|
|
4532
4884
|
const address = value ?? {};
|
|
4533
|
-
const part = (key, label) => /* @__PURE__ */
|
|
4885
|
+
const part = (key, label) => /* @__PURE__ */ jsx27(
|
|
4534
4886
|
"input",
|
|
4535
4887
|
{
|
|
4536
4888
|
className: "b316-input",
|
|
@@ -4542,7 +4894,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4542
4894
|
},
|
|
4543
4895
|
key
|
|
4544
4896
|
);
|
|
4545
|
-
return /* @__PURE__ */
|
|
4897
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-address", children: [
|
|
4546
4898
|
part("line1", "Address line 1"),
|
|
4547
4899
|
part("line2", "Address line 2"),
|
|
4548
4900
|
part("city", "City"),
|
|
@@ -4552,7 +4904,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4552
4904
|
] });
|
|
4553
4905
|
}
|
|
4554
4906
|
case "EMAIL":
|
|
4555
|
-
return /* @__PURE__ */
|
|
4907
|
+
return /* @__PURE__ */ jsx27(
|
|
4556
4908
|
"input",
|
|
4557
4909
|
{
|
|
4558
4910
|
...common,
|
|
@@ -4562,7 +4914,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4562
4914
|
}
|
|
4563
4915
|
);
|
|
4564
4916
|
case "URL":
|
|
4565
|
-
return /* @__PURE__ */
|
|
4917
|
+
return /* @__PURE__ */ jsx27(
|
|
4566
4918
|
"input",
|
|
4567
4919
|
{
|
|
4568
4920
|
...common,
|
|
@@ -4572,7 +4924,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4572
4924
|
}
|
|
4573
4925
|
);
|
|
4574
4926
|
case "PHONE":
|
|
4575
|
-
return /* @__PURE__ */
|
|
4927
|
+
return /* @__PURE__ */ jsx27(
|
|
4576
4928
|
"input",
|
|
4577
4929
|
{
|
|
4578
4930
|
...common,
|
|
@@ -4582,7 +4934,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4582
4934
|
}
|
|
4583
4935
|
);
|
|
4584
4936
|
default:
|
|
4585
|
-
return /* @__PURE__ */
|
|
4937
|
+
return /* @__PURE__ */ jsx27(
|
|
4586
4938
|
"input",
|
|
4587
4939
|
{
|
|
4588
4940
|
...common,
|
|
@@ -4593,24 +4945,24 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4593
4945
|
);
|
|
4594
4946
|
}
|
|
4595
4947
|
}
|
|
4596
|
-
return /* @__PURE__ */
|
|
4597
|
-
/* @__PURE__ */
|
|
4948
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-field", children: [
|
|
4949
|
+
/* @__PURE__ */ jsxs26("label", { className: "b316-label", htmlFor: id, children: [
|
|
4598
4950
|
field.label,
|
|
4599
|
-
field.required ? /* @__PURE__ */
|
|
4951
|
+
field.required ? /* @__PURE__ */ jsx27("span", { "aria-hidden": "true", children: " *" }) : null
|
|
4600
4952
|
] }),
|
|
4601
4953
|
control(),
|
|
4602
|
-
field.description ? /* @__PURE__ */
|
|
4603
|
-
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
|
|
4604
4956
|
] });
|
|
4605
4957
|
}
|
|
4606
4958
|
|
|
4607
4959
|
// src/RecordForm.tsx
|
|
4608
4960
|
import { specFor as specFor2 } from "@base316/sdk";
|
|
4609
|
-
import { useEffect as
|
|
4961
|
+
import { useEffect as useEffect22, useState as useState27 } from "react";
|
|
4610
4962
|
|
|
4611
4963
|
// src/RelationPicker.tsx
|
|
4612
|
-
import { useEffect as
|
|
4613
|
-
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";
|
|
4614
4966
|
function RelationPicker({
|
|
4615
4967
|
field,
|
|
4616
4968
|
value,
|
|
@@ -4620,13 +4972,13 @@ function RelationPicker({
|
|
|
4620
4972
|
tenant
|
|
4621
4973
|
}) {
|
|
4622
4974
|
const { client, token } = useBase316();
|
|
4623
|
-
const [query, setQuery] =
|
|
4624
|
-
const [results, setResults] =
|
|
4625
|
-
const [chosenTitle, setChosenTitle] =
|
|
4626
|
-
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);
|
|
4627
4979
|
const id = `b316-field-${field.key}`;
|
|
4628
4980
|
const box = useRef7(null);
|
|
4629
|
-
|
|
4981
|
+
useEffect20(() => {
|
|
4630
4982
|
if (!token || !value || !field.relationTo) {
|
|
4631
4983
|
setChosenTitle(null);
|
|
4632
4984
|
return;
|
|
@@ -4641,7 +4993,7 @@ function RelationPicker({
|
|
|
4641
4993
|
cancelled = true;
|
|
4642
4994
|
};
|
|
4643
4995
|
}, [client, token, value, field.relationTo, tenant]);
|
|
4644
|
-
|
|
4996
|
+
useEffect20(() => {
|
|
4645
4997
|
if (!token || !field.relationTo || !open) {
|
|
4646
4998
|
return;
|
|
4647
4999
|
}
|
|
@@ -4667,7 +5019,7 @@ function RelationPicker({
|
|
|
4667
5019
|
clearTimeout(timer);
|
|
4668
5020
|
};
|
|
4669
5021
|
}, [client, token, field.relationTo, query, open, tenant]);
|
|
4670
|
-
|
|
5022
|
+
useEffect20(() => {
|
|
4671
5023
|
if (!open || typeof document === "undefined") {
|
|
4672
5024
|
return;
|
|
4673
5025
|
}
|
|
@@ -4681,14 +5033,14 @@ function RelationPicker({
|
|
|
4681
5033
|
document.removeEventListener("mousedown", onDocumentClick);
|
|
4682
5034
|
};
|
|
4683
5035
|
}, [open]);
|
|
4684
|
-
return /* @__PURE__ */
|
|
4685
|
-
/* @__PURE__ */
|
|
5036
|
+
return /* @__PURE__ */ jsxs27("div", { className: "b316-field", ref: box, children: [
|
|
5037
|
+
/* @__PURE__ */ jsxs27("label", { className: "b316-label", htmlFor: id, children: [
|
|
4686
5038
|
field.label,
|
|
4687
|
-
field.required ? /* @__PURE__ */
|
|
5039
|
+
field.required ? /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: " *" }) : null
|
|
4688
5040
|
] }),
|
|
4689
|
-
value && !open ? /* @__PURE__ */
|
|
4690
|
-
/* @__PURE__ */
|
|
4691
|
-
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(
|
|
4692
5044
|
"button",
|
|
4693
5045
|
{
|
|
4694
5046
|
type: "button",
|
|
@@ -4700,7 +5052,7 @@ function RelationPicker({
|
|
|
4700
5052
|
children: "Change"
|
|
4701
5053
|
}
|
|
4702
5054
|
),
|
|
4703
|
-
disabled || field.required ? null : /* @__PURE__ */
|
|
5055
|
+
disabled || field.required ? null : /* @__PURE__ */ jsx28(
|
|
4704
5056
|
"button",
|
|
4705
5057
|
{
|
|
4706
5058
|
type: "button",
|
|
@@ -4710,8 +5062,8 @@ function RelationPicker({
|
|
|
4710
5062
|
children: "Clear"
|
|
4711
5063
|
}
|
|
4712
5064
|
)
|
|
4713
|
-
] }) : /* @__PURE__ */
|
|
4714
|
-
/* @__PURE__ */
|
|
5065
|
+
] }) : /* @__PURE__ */ jsxs27(Fragment10, { children: [
|
|
5066
|
+
/* @__PURE__ */ jsx28(
|
|
4715
5067
|
"input",
|
|
4716
5068
|
{
|
|
4717
5069
|
id,
|
|
@@ -4732,7 +5084,7 @@ function RelationPicker({
|
|
|
4732
5084
|
}
|
|
4733
5085
|
}
|
|
4734
5086
|
),
|
|
4735
|
-
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(
|
|
4736
5088
|
"button",
|
|
4737
5089
|
{
|
|
4738
5090
|
type: "button",
|
|
@@ -4748,13 +5100,13 @@ function RelationPicker({
|
|
|
4748
5100
|
}
|
|
4749
5101
|
) }, result.id)) }) : null
|
|
4750
5102
|
] }),
|
|
4751
|
-
field.description ? /* @__PURE__ */
|
|
4752
|
-
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
|
|
4753
5105
|
] });
|
|
4754
5106
|
}
|
|
4755
5107
|
|
|
4756
5108
|
// src/useCollection.ts
|
|
4757
|
-
import { useCallback as useCallback9, useEffect as
|
|
5109
|
+
import { useCallback as useCallback9, useEffect as useEffect21, useMemo as useMemo3, useState as useState26 } from "react";
|
|
4758
5110
|
function fieldErrorFrom(cause) {
|
|
4759
5111
|
const param = cause?.param;
|
|
4760
5112
|
const message = cause instanceof Error ? cause.message : "That value was not accepted.";
|
|
@@ -4762,24 +5114,24 @@ function fieldErrorFrom(cause) {
|
|
|
4762
5114
|
}
|
|
4763
5115
|
function useCollection(collection, options = {}) {
|
|
4764
5116
|
const { client, token } = useBase316();
|
|
4765
|
-
const [schema, setSchema] =
|
|
4766
|
-
const [records, setRecords] =
|
|
4767
|
-
const [error, setError] =
|
|
4768
|
-
const [loading, setLoading] =
|
|
4769
|
-
const [total, setTotal] =
|
|
4770
|
-
const [cursor, setCursor] =
|
|
4771
|
-
const [reloadCount, setReloadCount] =
|
|
4772
|
-
const [search, setSearch] =
|
|
4773
|
-
const [filters, setFilters] =
|
|
4774
|
-
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(
|
|
4775
5127
|
options.sort ?? null
|
|
4776
5128
|
);
|
|
4777
|
-
const [fieldErrors, setFieldErrors] =
|
|
4778
|
-
const [saving, setSaving] =
|
|
5129
|
+
const [fieldErrors, setFieldErrors] = useState26({});
|
|
5130
|
+
const [saving, setSaving] = useState26(false);
|
|
4779
5131
|
const { tenant, limit, recordId } = options;
|
|
4780
5132
|
const fixedFilters = JSON.stringify(options.filters ?? []);
|
|
4781
5133
|
const scope = useMemo3(() => tenant ? { tenant } : void 0, [tenant]);
|
|
4782
|
-
|
|
5134
|
+
useEffect21(() => {
|
|
4783
5135
|
if (!token) {
|
|
4784
5136
|
return;
|
|
4785
5137
|
}
|
|
@@ -4798,7 +5150,7 @@ function useCollection(collection, options = {}) {
|
|
|
4798
5150
|
cancelled = true;
|
|
4799
5151
|
};
|
|
4800
5152
|
}, [client, token, collection, scope]);
|
|
4801
|
-
|
|
5153
|
+
useEffect21(() => {
|
|
4802
5154
|
if (!token || !schema) {
|
|
4803
5155
|
return;
|
|
4804
5156
|
}
|
|
@@ -4990,7 +5342,7 @@ function useCollection(collection, options = {}) {
|
|
|
4990
5342
|
}
|
|
4991
5343
|
|
|
4992
5344
|
// src/RecordForm.tsx
|
|
4993
|
-
import { jsx as
|
|
5345
|
+
import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4994
5346
|
function RecordForm({
|
|
4995
5347
|
collection,
|
|
4996
5348
|
recordId,
|
|
@@ -5011,20 +5363,20 @@ function RecordForm({
|
|
|
5011
5363
|
recordId
|
|
5012
5364
|
}
|
|
5013
5365
|
);
|
|
5014
|
-
const [values, setValues] =
|
|
5015
|
-
const [loaded, setLoaded] =
|
|
5366
|
+
const [values, setValues] = useState27(defaults ?? {});
|
|
5367
|
+
const [loaded, setLoaded] = useState27(!recordId);
|
|
5016
5368
|
const existing = recordId ? records.find((record) => record.id === recordId) : void 0;
|
|
5017
|
-
|
|
5369
|
+
useEffect22(() => {
|
|
5018
5370
|
if (existing && !loaded) {
|
|
5019
5371
|
setValues(existing.fields);
|
|
5020
5372
|
setLoaded(true);
|
|
5021
5373
|
}
|
|
5022
5374
|
}, [existing, loaded]);
|
|
5023
5375
|
if (error) {
|
|
5024
|
-
return /* @__PURE__ */
|
|
5376
|
+
return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx29("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5025
5377
|
}
|
|
5026
5378
|
if (!schema || !loaded) {
|
|
5027
|
-
return /* @__PURE__ */
|
|
5379
|
+
return /* @__PURE__ */ jsx29("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5028
5380
|
}
|
|
5029
5381
|
const editable = schema.fields.filter((field) => !specFor2(field).computed);
|
|
5030
5382
|
async function submit(event) {
|
|
@@ -5034,11 +5386,11 @@ function RecordForm({
|
|
|
5034
5386
|
onSaved?.(saved.id);
|
|
5035
5387
|
}
|
|
5036
5388
|
}
|
|
5037
|
-
return /* @__PURE__ */
|
|
5038
|
-
/* @__PURE__ */
|
|
5039
|
-
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,
|
|
5040
5392
|
editable.map(
|
|
5041
|
-
(field) => field.type === "RELATION" ? /* @__PURE__ */
|
|
5393
|
+
(field) => field.type === "RELATION" ? /* @__PURE__ */ jsx29(
|
|
5042
5394
|
RelationPicker,
|
|
5043
5395
|
{
|
|
5044
5396
|
field,
|
|
@@ -5049,7 +5401,7 @@ function RecordForm({
|
|
|
5049
5401
|
onChange: (next) => setValues((current) => ({ ...current, [field.key]: next }))
|
|
5050
5402
|
},
|
|
5051
5403
|
field.key
|
|
5052
|
-
) : /* @__PURE__ */
|
|
5404
|
+
) : /* @__PURE__ */ jsx29(
|
|
5053
5405
|
FieldInput,
|
|
5054
5406
|
{
|
|
5055
5407
|
field,
|
|
@@ -5061,15 +5413,15 @@ function RecordForm({
|
|
|
5061
5413
|
field.key
|
|
5062
5414
|
)
|
|
5063
5415
|
),
|
|
5064
|
-
/* @__PURE__ */
|
|
5065
|
-
onCancel ? /* @__PURE__ */
|
|
5066
|
-
/* @__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" })
|
|
5067
5419
|
] })
|
|
5068
5420
|
] });
|
|
5069
5421
|
}
|
|
5070
5422
|
|
|
5071
5423
|
// src/DataTable.tsx
|
|
5072
|
-
import { jsx as
|
|
5424
|
+
import { jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
5073
5425
|
function DataTable({
|
|
5074
5426
|
collection,
|
|
5075
5427
|
columns,
|
|
@@ -5098,13 +5450,13 @@ function DataTable({
|
|
|
5098
5450
|
loadMore,
|
|
5099
5451
|
remove
|
|
5100
5452
|
} = useCollection(collection, options);
|
|
5101
|
-
const [editing, setEditing] =
|
|
5102
|
-
const [removeFailed, setRemoveFailed] =
|
|
5453
|
+
const [editing, setEditing] = useState28(null);
|
|
5454
|
+
const [removeFailed, setRemoveFailed] = useState28(null);
|
|
5103
5455
|
if (error) {
|
|
5104
|
-
return /* @__PURE__ */
|
|
5456
|
+
return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx30("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5105
5457
|
}
|
|
5106
5458
|
if (!schema) {
|
|
5107
|
-
return /* @__PURE__ */
|
|
5459
|
+
return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5108
5460
|
}
|
|
5109
5461
|
const shown = columns ? (
|
|
5110
5462
|
// Ordered by what was asked for, not by the schema: a caller naming
|
|
@@ -5113,10 +5465,10 @@ function DataTable({
|
|
|
5113
5465
|
) : schema.fields;
|
|
5114
5466
|
const searchable = schema.fields.some((field) => specFor3(field).capabilities.searchable);
|
|
5115
5467
|
const writable = canWrite && !readOnly;
|
|
5116
|
-
return /* @__PURE__ */
|
|
5117
|
-
removeFailed ? /* @__PURE__ */
|
|
5118
|
-
/* @__PURE__ */
|
|
5119
|
-
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(
|
|
5120
5472
|
"input",
|
|
5121
5473
|
{
|
|
5122
5474
|
type: "search",
|
|
@@ -5126,25 +5478,25 @@ function DataTable({
|
|
|
5126
5478
|
value: search,
|
|
5127
5479
|
onChange: (event) => setSearch(event.target.value)
|
|
5128
5480
|
}
|
|
5129
|
-
) : /* @__PURE__ */
|
|
5130
|
-
/* @__PURE__ */
|
|
5131
|
-
/* @__PURE__ */
|
|
5481
|
+
) : /* @__PURE__ */ jsx30("span", {}),
|
|
5482
|
+
/* @__PURE__ */ jsxs29("div", { className: "b316-table-actions", children: [
|
|
5483
|
+
/* @__PURE__ */ jsxs29("span", { className: "b316-muted", children: [
|
|
5132
5484
|
total,
|
|
5133
5485
|
" ",
|
|
5134
5486
|
total === 1 ? schema.name.toLowerCase() : schema.namePlural.toLowerCase()
|
|
5135
5487
|
] }),
|
|
5136
|
-
writable ? /* @__PURE__ */
|
|
5488
|
+
writable ? /* @__PURE__ */ jsxs29("button", { type: "button", className: "b316-button", onClick: () => setEditing("new"), children: [
|
|
5137
5489
|
"New ",
|
|
5138
5490
|
schema.name.toLowerCase()
|
|
5139
5491
|
] }) : null
|
|
5140
5492
|
] })
|
|
5141
5493
|
] }),
|
|
5142
|
-
/* @__PURE__ */
|
|
5143
|
-
/* @__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: [
|
|
5144
5496
|
shown.map((field) => {
|
|
5145
5497
|
const sortable = specFor3(field).capabilities.sortable;
|
|
5146
5498
|
const active = sort?.field === field.key;
|
|
5147
|
-
return /* @__PURE__ */
|
|
5499
|
+
return /* @__PURE__ */ jsx30("th", { scope: "col", "aria-sort": ariaSort(active, sort?.direction), children: sortable ? /* @__PURE__ */ jsxs29(
|
|
5148
5500
|
"button",
|
|
5149
5501
|
{
|
|
5150
5502
|
type: "button",
|
|
@@ -5152,20 +5504,20 @@ function DataTable({
|
|
|
5152
5504
|
onClick: () => toggleSort(field.key),
|
|
5153
5505
|
children: [
|
|
5154
5506
|
field.label,
|
|
5155
|
-
/* @__PURE__ */
|
|
5507
|
+
/* @__PURE__ */ jsx30("span", { "aria-hidden": "true", children: active ? sort?.direction === "desc" ? " \u2193" : " \u2191" : " \u2195" })
|
|
5156
5508
|
]
|
|
5157
5509
|
}
|
|
5158
5510
|
) : field.label }, field.key);
|
|
5159
5511
|
}),
|
|
5160
|
-
writable ? /* @__PURE__ */
|
|
5512
|
+
writable ? /* @__PURE__ */ jsx30("th", { scope: "col", className: "b316-table-rowactions" }) : null
|
|
5161
5513
|
] }) }),
|
|
5162
|
-
/* @__PURE__ */
|
|
5514
|
+
/* @__PURE__ */ jsx30("tbody", { children: records.map((record) => /* @__PURE__ */ jsxs29(
|
|
5163
5515
|
"tr",
|
|
5164
5516
|
{
|
|
5165
5517
|
className: onSelect ? "b316-row-clickable" : void 0,
|
|
5166
5518
|
onClick: onSelect ? () => onSelect(record) : void 0,
|
|
5167
5519
|
children: [
|
|
5168
|
-
shown.map((field) => /* @__PURE__ */
|
|
5520
|
+
shown.map((field) => /* @__PURE__ */ jsx30("td", { children: renderCell?.(record, field) ?? /* @__PURE__ */ jsx30(
|
|
5169
5521
|
FieldCell,
|
|
5170
5522
|
{
|
|
5171
5523
|
value: record.fields[field.key] ?? null,
|
|
@@ -5173,8 +5525,8 @@ function DataTable({
|
|
|
5173
5525
|
related: record.related[field.key]
|
|
5174
5526
|
}
|
|
5175
5527
|
) }, field.key)),
|
|
5176
|
-
writable ? /* @__PURE__ */
|
|
5177
|
-
/* @__PURE__ */
|
|
5528
|
+
writable ? /* @__PURE__ */ jsxs29("td", { className: "b316-table-rowactions", children: [
|
|
5529
|
+
/* @__PURE__ */ jsx30(
|
|
5178
5530
|
"button",
|
|
5179
5531
|
{
|
|
5180
5532
|
type: "button",
|
|
@@ -5186,7 +5538,7 @@ function DataTable({
|
|
|
5186
5538
|
children: "Edit"
|
|
5187
5539
|
}
|
|
5188
5540
|
),
|
|
5189
|
-
/* @__PURE__ */
|
|
5541
|
+
/* @__PURE__ */ jsx30(
|
|
5190
5542
|
ConfirmButton,
|
|
5191
5543
|
{
|
|
5192
5544
|
className: "b316-button-quiet b316-danger",
|
|
@@ -5210,10 +5562,10 @@ function DataTable({
|
|
|
5210
5562
|
record.id
|
|
5211
5563
|
)) })
|
|
5212
5564
|
] }) }),
|
|
5213
|
-
records.length === 0 && !loading ? /* @__PURE__ */
|
|
5214
|
-
loading ? /* @__PURE__ */
|
|
5215
|
-
hasMore ? /* @__PURE__ */
|
|
5216
|
-
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(
|
|
5217
5569
|
RecordForm,
|
|
5218
5570
|
{
|
|
5219
5571
|
collection,
|
|
@@ -5241,8 +5593,8 @@ import {
|
|
|
5241
5593
|
specFor as specFor4,
|
|
5242
5594
|
titleFieldOf
|
|
5243
5595
|
} from "@base316/sdk";
|
|
5244
|
-
import { useState as
|
|
5245
|
-
import { jsx as
|
|
5596
|
+
import { useState as useState29 } from "react";
|
|
5597
|
+
import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
5246
5598
|
function Kanban({
|
|
5247
5599
|
collection,
|
|
5248
5600
|
groupBy,
|
|
@@ -5259,17 +5611,17 @@ function Kanban({
|
|
|
5259
5611
|
limit: options.limit ?? 100,
|
|
5260
5612
|
...options
|
|
5261
5613
|
});
|
|
5262
|
-
const [dragging, setDragging] =
|
|
5263
|
-
const [over, setOver] =
|
|
5614
|
+
const [dragging, setDragging] = useState29(null);
|
|
5615
|
+
const [over, setOver] = useState29(null);
|
|
5264
5616
|
if (error) {
|
|
5265
|
-
return /* @__PURE__ */
|
|
5617
|
+
return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx31("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5266
5618
|
}
|
|
5267
5619
|
if (!schema) {
|
|
5268
|
-
return /* @__PURE__ */
|
|
5620
|
+
return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5269
5621
|
}
|
|
5270
5622
|
const field = groupBy ? schema.fields.find((candidate) => candidate.key === groupBy) ?? null : defaultGroupFieldOf(schema.fields);
|
|
5271
5623
|
if (!field || !specFor4(field).capabilities.groupable) {
|
|
5272
|
-
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.` });
|
|
5273
5625
|
}
|
|
5274
5626
|
const columns = columnsFor(field);
|
|
5275
5627
|
const shown = cardFields ? cardFields.map((key) => schema.fields.find((candidate) => candidate.key === key)).filter((candidate) => Boolean(candidate)) : (
|
|
@@ -5286,12 +5638,12 @@ function Kanban({
|
|
|
5286
5638
|
}
|
|
5287
5639
|
await update(record.id, { [field.key]: value });
|
|
5288
5640
|
}
|
|
5289
|
-
return /* @__PURE__ */
|
|
5290
|
-
/* @__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) => {
|
|
5291
5643
|
const inColumn = records.filter(
|
|
5292
5644
|
(record) => String(record.fields[field.key] ?? "") === String(column.value ?? "")
|
|
5293
5645
|
);
|
|
5294
|
-
return /* @__PURE__ */
|
|
5646
|
+
return /* @__PURE__ */ jsxs30(
|
|
5295
5647
|
"section",
|
|
5296
5648
|
{
|
|
5297
5649
|
className: over === String(column.value) ? "b316-board-column b316-board-over" : "b316-board-column",
|
|
@@ -5315,12 +5667,12 @@ function Kanban({
|
|
|
5315
5667
|
setDragging(null);
|
|
5316
5668
|
},
|
|
5317
5669
|
children: [
|
|
5318
|
-
/* @__PURE__ */
|
|
5319
|
-
/* @__PURE__ */
|
|
5320
|
-
/* @__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 })
|
|
5321
5673
|
] }),
|
|
5322
|
-
/* @__PURE__ */
|
|
5323
|
-
inColumn.map((record) => /* @__PURE__ */
|
|
5674
|
+
/* @__PURE__ */ jsxs30("div", { className: "b316-board-cards", children: [
|
|
5675
|
+
inColumn.map((record) => /* @__PURE__ */ jsxs30(
|
|
5324
5676
|
"article",
|
|
5325
5677
|
{
|
|
5326
5678
|
className: "b316-board-card",
|
|
@@ -5332,10 +5684,10 @@ function Kanban({
|
|
|
5332
5684
|
},
|
|
5333
5685
|
onClick: onSelect ? () => onSelect(record) : void 0,
|
|
5334
5686
|
children: [
|
|
5335
|
-
/* @__PURE__ */
|
|
5336
|
-
shown.map((candidate) => /* @__PURE__ */
|
|
5337
|
-
/* @__PURE__ */
|
|
5338
|
-
/* @__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(
|
|
5339
5691
|
FieldCell,
|
|
5340
5692
|
{
|
|
5341
5693
|
value: record.fields[candidate.key] ?? null,
|
|
@@ -5348,9 +5700,9 @@ function Kanban({
|
|
|
5348
5700
|
// Dragging is not reachable by keyboard and is awkward on a
|
|
5349
5701
|
// phone. This is the same action by other means, not a
|
|
5350
5702
|
// lesser fallback.
|
|
5351
|
-
/* @__PURE__ */
|
|
5352
|
-
/* @__PURE__ */
|
|
5353
|
-
/* @__PURE__ */
|
|
5703
|
+
/* @__PURE__ */ jsxs30("label", { className: "b316-board-move", children: [
|
|
5704
|
+
/* @__PURE__ */ jsx31("span", { className: "b316-muted", children: "Move to" }),
|
|
5705
|
+
/* @__PURE__ */ jsx31(
|
|
5354
5706
|
"select",
|
|
5355
5707
|
{
|
|
5356
5708
|
className: "b316-input",
|
|
@@ -5362,7 +5714,7 @@ function Kanban({
|
|
|
5362
5714
|
);
|
|
5363
5715
|
void move(record, chosen?.value ?? null);
|
|
5364
5716
|
},
|
|
5365
|
-
children: columns.map((candidate) => /* @__PURE__ */
|
|
5717
|
+
children: columns.map((candidate) => /* @__PURE__ */ jsx31("option", { value: String(candidate.value), children: candidate.label }, String(candidate.value)))
|
|
5366
5718
|
}
|
|
5367
5719
|
)
|
|
5368
5720
|
] })
|
|
@@ -5371,14 +5723,14 @@ function Kanban({
|
|
|
5371
5723
|
},
|
|
5372
5724
|
record.id
|
|
5373
5725
|
)),
|
|
5374
|
-
inColumn.length === 0 ? /* @__PURE__ */
|
|
5726
|
+
inColumn.length === 0 ? /* @__PURE__ */ jsx31("div", { className: "b316-board-empty", children: emptyState ?? "Nothing here" }) : null
|
|
5375
5727
|
] })
|
|
5376
5728
|
]
|
|
5377
5729
|
},
|
|
5378
5730
|
String(column.value)
|
|
5379
5731
|
);
|
|
5380
5732
|
}) }),
|
|
5381
|
-
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: [
|
|
5382
5734
|
"Showing ",
|
|
5383
5735
|
records.length,
|
|
5384
5736
|
" of ",
|
|
@@ -5405,7 +5757,7 @@ import {
|
|
|
5405
5757
|
specFor as specFor5
|
|
5406
5758
|
} from "@base316/sdk";
|
|
5407
5759
|
import { useMemo as useMemo4 } from "react";
|
|
5408
|
-
import { jsx as
|
|
5760
|
+
import { jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5409
5761
|
function Chart({
|
|
5410
5762
|
collection,
|
|
5411
5763
|
x,
|
|
@@ -5444,23 +5796,23 @@ function Chart({
|
|
|
5444
5796
|
[records, axis, measure, aggregate, bucket, y]
|
|
5445
5797
|
);
|
|
5446
5798
|
if (error) {
|
|
5447
|
-
return /* @__PURE__ */
|
|
5799
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx32("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5448
5800
|
}
|
|
5449
5801
|
if (!schema || loading) {
|
|
5450
|
-
return /* @__PURE__ */
|
|
5802
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5451
5803
|
}
|
|
5452
5804
|
if (!axis) {
|
|
5453
|
-
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.` });
|
|
5454
5806
|
}
|
|
5455
5807
|
if (y && !measure) {
|
|
5456
|
-
return /* @__PURE__ */
|
|
5808
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: `"${y}" cannot be ${aggregate === "avg" ? "averaged" : `combined with ${aggregate}`}.` });
|
|
5457
5809
|
}
|
|
5458
5810
|
const peak = Math.max(...buckets.map((entry) => entry.value), 0);
|
|
5459
5811
|
const heading = title ?? `${measure ? `${aggregate} of ${measure.label}` : schema.namePlural} by ${axis.label}`;
|
|
5460
|
-
return /* @__PURE__ */
|
|
5461
|
-
/* @__PURE__ */
|
|
5462
|
-
buckets.length === 0 || peak === 0 ? /* @__PURE__ */
|
|
5463
|
-
/* @__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(
|
|
5464
5816
|
"div",
|
|
5465
5817
|
{
|
|
5466
5818
|
className: "b316-chart-bar",
|
|
@@ -5468,18 +5820,18 @@ function Chart({
|
|
|
5468
5820
|
title: `${entry.label}: ${format(entry.value)}`
|
|
5469
5821
|
}
|
|
5470
5822
|
),
|
|
5471
|
-
/* @__PURE__ */
|
|
5823
|
+
/* @__PURE__ */ jsx32("span", { className: "b316-chart-label", children: entry.label })
|
|
5472
5824
|
] }, entry.key)) }),
|
|
5473
|
-
/* @__PURE__ */
|
|
5474
|
-
/* @__PURE__ */
|
|
5475
|
-
/* @__PURE__ */
|
|
5476
|
-
/* @__PURE__ */
|
|
5477
|
-
/* @__PURE__ */
|
|
5478
|
-
/* @__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" })
|
|
5479
5831
|
] }) }),
|
|
5480
|
-
/* @__PURE__ */
|
|
5481
|
-
/* @__PURE__ */
|
|
5482
|
-
/* @__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) })
|
|
5483
5835
|
] }, entry.key)) })
|
|
5484
5836
|
] })
|
|
5485
5837
|
] })
|
|
@@ -5538,8 +5890,8 @@ function combine(values, aggregate) {
|
|
|
5538
5890
|
|
|
5539
5891
|
// src/RecordDetail.tsx
|
|
5540
5892
|
import { specFor as specFor6 } from "@base316/sdk";
|
|
5541
|
-
import { useState as
|
|
5542
|
-
import { jsx as
|
|
5893
|
+
import { useState as useState30 } from "react";
|
|
5894
|
+
import { jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5543
5895
|
function RecordDetail({
|
|
5544
5896
|
collection,
|
|
5545
5897
|
recordId,
|
|
@@ -5555,23 +5907,23 @@ function RecordDetail({
|
|
|
5555
5907
|
tenant,
|
|
5556
5908
|
recordId
|
|
5557
5909
|
});
|
|
5558
|
-
const [editing, setEditing] =
|
|
5910
|
+
const [editing, setEditing] = useState30(false);
|
|
5559
5911
|
const record = records.find((candidate) => candidate.id === recordId);
|
|
5560
5912
|
if (error) {
|
|
5561
|
-
return /* @__PURE__ */
|
|
5913
|
+
return /* @__PURE__ */ jsx33("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx33("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5562
5914
|
}
|
|
5563
5915
|
if (!schema || loading) {
|
|
5564
|
-
return /* @__PURE__ */
|
|
5916
|
+
return /* @__PURE__ */ jsx33("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5565
5917
|
}
|
|
5566
5918
|
if (!record) {
|
|
5567
|
-
return /* @__PURE__ */
|
|
5919
|
+
return /* @__PURE__ */ jsxs32("div", { className: cls("b316-card", className), style, children: [
|
|
5568
5920
|
"That ",
|
|
5569
5921
|
schema.name.toLowerCase(),
|
|
5570
5922
|
" is not available."
|
|
5571
5923
|
] });
|
|
5572
5924
|
}
|
|
5573
5925
|
if (editing) {
|
|
5574
|
-
return /* @__PURE__ */
|
|
5926
|
+
return /* @__PURE__ */ jsx33(
|
|
5575
5927
|
RecordForm,
|
|
5576
5928
|
{
|
|
5577
5929
|
collection,
|
|
@@ -5585,12 +5937,12 @@ function RecordDetail({
|
|
|
5585
5937
|
);
|
|
5586
5938
|
}
|
|
5587
5939
|
const writable = canWrite && !readOnly;
|
|
5588
|
-
return /* @__PURE__ */
|
|
5589
|
-
/* @__PURE__ */
|
|
5590
|
-
/* @__PURE__ */
|
|
5591
|
-
/* @__PURE__ */
|
|
5592
|
-
writable ? /* @__PURE__ */
|
|
5593
|
-
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(
|
|
5594
5946
|
ConfirmButton,
|
|
5595
5947
|
{
|
|
5596
5948
|
className: "b316-button-quiet b316-danger",
|
|
@@ -5603,15 +5955,15 @@ function RecordDetail({
|
|
|
5603
5955
|
children: "Delete"
|
|
5604
5956
|
}
|
|
5605
5957
|
) : null,
|
|
5606
|
-
onClose ? /* @__PURE__ */
|
|
5958
|
+
onClose ? /* @__PURE__ */ jsx33("button", { type: "button", className: "b316-button-quiet", onClick: onClose, children: "Close" }) : null
|
|
5607
5959
|
] })
|
|
5608
5960
|
] }),
|
|
5609
|
-
/* @__PURE__ */
|
|
5610
|
-
/* @__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: [
|
|
5611
5963
|
field.label,
|
|
5612
|
-
specFor6(field).computed ? /* @__PURE__ */
|
|
5964
|
+
specFor6(field).computed ? /* @__PURE__ */ jsx33("span", { className: "b316-muted", children: " (calculated)" }) : null
|
|
5613
5965
|
] }),
|
|
5614
|
-
/* @__PURE__ */
|
|
5966
|
+
/* @__PURE__ */ jsx33("dd", { children: /* @__PURE__ */ jsx33(
|
|
5615
5967
|
FieldCell,
|
|
5616
5968
|
{
|
|
5617
5969
|
value: record.fields[field.key] ?? null,
|
|
@@ -5625,8 +5977,8 @@ function RecordDetail({
|
|
|
5625
5977
|
}
|
|
5626
5978
|
|
|
5627
5979
|
// src/SubscriptionManager.tsx
|
|
5628
|
-
import { useCallback as useCallback10, useEffect as
|
|
5629
|
-
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";
|
|
5630
5982
|
function statusLabel(status2) {
|
|
5631
5983
|
const words = status2.toLowerCase().split("_");
|
|
5632
5984
|
return words.map((w, i) => i === 0 ? w.charAt(0).toUpperCase() + w.slice(1) : w).join(" ");
|
|
@@ -5666,15 +6018,15 @@ function SubscriptionManager({
|
|
|
5666
6018
|
style
|
|
5667
6019
|
}) {
|
|
5668
6020
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
5669
|
-
const [subscription, setSubscription] =
|
|
5670
|
-
const [loading, setLoading] =
|
|
5671
|
-
const [managedBy, setManagedBy] =
|
|
5672
|
-
const [schedule, setSchedule] =
|
|
5673
|
-
const [busy, setBusy] =
|
|
5674
|
-
const [error, setError] =
|
|
5675
|
-
const [step, setStep] =
|
|
5676
|
-
const [reason, setReason] =
|
|
5677
|
-
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("");
|
|
5678
6030
|
const load = useCallback10(async () => {
|
|
5679
6031
|
if (!token) {
|
|
5680
6032
|
setSubscription(null);
|
|
@@ -5693,7 +6045,7 @@ function SubscriptionManager({
|
|
|
5693
6045
|
setLoading(false);
|
|
5694
6046
|
}
|
|
5695
6047
|
}, [client, token]);
|
|
5696
|
-
|
|
6048
|
+
useEffect23(() => {
|
|
5697
6049
|
void load();
|
|
5698
6050
|
}, [load]);
|
|
5699
6051
|
const act = async (change, failure) => {
|
|
@@ -5711,29 +6063,29 @@ function SubscriptionManager({
|
|
|
5711
6063
|
}
|
|
5712
6064
|
};
|
|
5713
6065
|
if (sessionLoading || loading) {
|
|
5714
|
-
return /* @__PURE__ */
|
|
6066
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5715
6067
|
}
|
|
5716
6068
|
if (!token) {
|
|
5717
|
-
return /* @__PURE__ */
|
|
6069
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: "Sign in to manage your subscription." });
|
|
5718
6070
|
}
|
|
5719
6071
|
if (error) {
|
|
5720
|
-
return /* @__PURE__ */
|
|
6072
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx34("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5721
6073
|
}
|
|
5722
6074
|
if (!subscription) {
|
|
5723
|
-
return /* @__PURE__ */
|
|
6075
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: "You are not subscribed to a plan." });
|
|
5724
6076
|
}
|
|
5725
6077
|
const renews = new Date(subscription.currentPeriodEnd).toLocaleDateString();
|
|
5726
6078
|
const next = schedule[0] ?? null;
|
|
5727
6079
|
const nextOn = next?.effectiveAt ? new Date(next.effectiveAt).toLocaleDateString() : renews;
|
|
5728
|
-
return /* @__PURE__ */
|
|
5729
|
-
error ? /* @__PURE__ */
|
|
5730
|
-
/* @__PURE__ */
|
|
5731
|
-
/* @__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: [
|
|
5732
6084
|
statusLabel(subscription.status),
|
|
5733
6085
|
" \xB7 ",
|
|
5734
6086
|
subscription.cancelAtPeriodEnd ? `Ends ${renews}` : `Renews ${renews}`
|
|
5735
6087
|
] }),
|
|
5736
|
-
next && !managedBy ? /* @__PURE__ */
|
|
6088
|
+
next && !managedBy ? /* @__PURE__ */ jsxs33("div", { className: "b316-muted", role: "status", style: { marginTop: 10 }, children: [
|
|
5737
6089
|
"Moves to ",
|
|
5738
6090
|
next.plan.name,
|
|
5739
6091
|
" on ",
|
|
@@ -5741,7 +6093,7 @@ function SubscriptionManager({
|
|
|
5741
6093
|
". You keep ",
|
|
5742
6094
|
subscription.planVersion.plan.name,
|
|
5743
6095
|
" until then.",
|
|
5744
|
-
/* @__PURE__ */
|
|
6096
|
+
/* @__PURE__ */ jsx34("div", { children: /* @__PURE__ */ jsx34(
|
|
5745
6097
|
"button",
|
|
5746
6098
|
{
|
|
5747
6099
|
type: "button",
|
|
@@ -5766,17 +6118,17 @@ function SubscriptionManager({
|
|
|
5766
6118
|
}
|
|
5767
6119
|
) })
|
|
5768
6120
|
] }) : null,
|
|
5769
|
-
managedBy ? /* @__PURE__ */
|
|
6121
|
+
managedBy ? /* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5770
6122
|
"Provided by ",
|
|
5771
6123
|
managedBy.name ?? "the organization that manages your account",
|
|
5772
6124
|
". Ask them to change or cancel it."
|
|
5773
|
-
] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */
|
|
5774
|
-
/* @__PURE__ */
|
|
6125
|
+
] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */ jsxs33("div", { children: [
|
|
6126
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5775
6127
|
"This subscription will not renew. You keep access until ",
|
|
5776
6128
|
renews,
|
|
5777
6129
|
"."
|
|
5778
6130
|
] }),
|
|
5779
|
-
/* @__PURE__ */
|
|
6131
|
+
/* @__PURE__ */ jsx34(
|
|
5780
6132
|
"button",
|
|
5781
6133
|
{
|
|
5782
6134
|
type: "button",
|
|
@@ -5786,14 +6138,14 @@ function SubscriptionManager({
|
|
|
5786
6138
|
children: busy ? "Working\u2026" : "Resume subscription"
|
|
5787
6139
|
}
|
|
5788
6140
|
)
|
|
5789
|
-
] }) : step.kind === "offer" ? /* @__PURE__ */
|
|
5790
|
-
/* @__PURE__ */
|
|
5791
|
-
/* @__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(
|
|
5792
6144
|
step.cancellation.offer,
|
|
5793
6145
|
step.cancellation.currency
|
|
5794
6146
|
)}.` }),
|
|
5795
|
-
/* @__PURE__ */
|
|
5796
|
-
/* @__PURE__ */
|
|
6147
|
+
/* @__PURE__ */ jsxs33("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
6148
|
+
/* @__PURE__ */ jsx34(
|
|
5797
6149
|
"button",
|
|
5798
6150
|
{
|
|
5799
6151
|
type: "button",
|
|
@@ -5806,7 +6158,7 @@ function SubscriptionManager({
|
|
|
5806
6158
|
children: busy ? "Working\u2026" : "Accept offer and stay"
|
|
5807
6159
|
}
|
|
5808
6160
|
),
|
|
5809
|
-
/* @__PURE__ */
|
|
6161
|
+
/* @__PURE__ */ jsx34(
|
|
5810
6162
|
"button",
|
|
5811
6163
|
{
|
|
5812
6164
|
type: "button",
|
|
@@ -5820,12 +6172,12 @@ function SubscriptionManager({
|
|
|
5820
6172
|
}
|
|
5821
6173
|
)
|
|
5822
6174
|
] }),
|
|
5823
|
-
/* @__PURE__ */
|
|
6175
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5824
6176
|
"If you cancel, you keep access until ",
|
|
5825
6177
|
renews,
|
|
5826
6178
|
"."
|
|
5827
6179
|
] })
|
|
5828
|
-
] }) : step.kind === "survey" ? /* @__PURE__ */
|
|
6180
|
+
] }) : step.kind === "survey" ? /* @__PURE__ */ jsxs33(
|
|
5829
6181
|
"form",
|
|
5830
6182
|
{
|
|
5831
6183
|
style: { marginTop: 14 },
|
|
@@ -5845,15 +6197,15 @@ function SubscriptionManager({
|
|
|
5845
6197
|
}, "Could not cancel. Try again.");
|
|
5846
6198
|
},
|
|
5847
6199
|
children: [
|
|
5848
|
-
/* @__PURE__ */
|
|
6200
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5849
6201
|
"You keep access until ",
|
|
5850
6202
|
renews,
|
|
5851
6203
|
". It will not renew after that."
|
|
5852
6204
|
] }),
|
|
5853
|
-
/* @__PURE__ */
|
|
5854
|
-
/* @__PURE__ */
|
|
5855
|
-
REASONS.map((option) => /* @__PURE__ */
|
|
5856
|
-
/* @__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(
|
|
5857
6209
|
"input",
|
|
5858
6210
|
{
|
|
5859
6211
|
type: "radio",
|
|
@@ -5863,12 +6215,12 @@ function SubscriptionManager({
|
|
|
5863
6215
|
onChange: () => setReason(option.value)
|
|
5864
6216
|
}
|
|
5865
6217
|
),
|
|
5866
|
-
/* @__PURE__ */
|
|
6218
|
+
/* @__PURE__ */ jsx34("span", { children: option.label })
|
|
5867
6219
|
] }, option.value))
|
|
5868
6220
|
] }),
|
|
5869
|
-
/* @__PURE__ */
|
|
5870
|
-
/* @__PURE__ */
|
|
5871
|
-
/* @__PURE__ */
|
|
6221
|
+
/* @__PURE__ */ jsxs33("label", { className: "b316-field", children: [
|
|
6222
|
+
/* @__PURE__ */ jsx34("span", { className: "b316-label", children: "Anything else? (optional)" }),
|
|
6223
|
+
/* @__PURE__ */ jsx34(
|
|
5872
6224
|
"textarea",
|
|
5873
6225
|
{
|
|
5874
6226
|
className: "b316-input",
|
|
@@ -5879,9 +6231,9 @@ function SubscriptionManager({
|
|
|
5879
6231
|
}
|
|
5880
6232
|
)
|
|
5881
6233
|
] }),
|
|
5882
|
-
/* @__PURE__ */
|
|
5883
|
-
/* @__PURE__ */
|
|
5884
|
-
/* @__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(
|
|
5885
6237
|
"button",
|
|
5886
6238
|
{
|
|
5887
6239
|
type: "button",
|
|
@@ -5897,7 +6249,7 @@ function SubscriptionManager({
|
|
|
5897
6249
|
] })
|
|
5898
6250
|
]
|
|
5899
6251
|
}
|
|
5900
|
-
) : /* @__PURE__ */
|
|
6252
|
+
) : /* @__PURE__ */ jsx34("div", { style: { marginTop: 14 }, children: /* @__PURE__ */ jsx34(
|
|
5901
6253
|
"button",
|
|
5902
6254
|
{
|
|
5903
6255
|
type: "button",
|
|
@@ -5915,11 +6267,11 @@ function SubscriptionManager({
|
|
|
5915
6267
|
}
|
|
5916
6268
|
|
|
5917
6269
|
// src/BillingPortal.tsx
|
|
5918
|
-
import { useCallback as useCallback12, useEffect as
|
|
6270
|
+
import { useCallback as useCallback12, useEffect as useEffect27, useState as useState35 } from "react";
|
|
5919
6271
|
|
|
5920
6272
|
// src/CreditBalances.tsx
|
|
5921
|
-
import { useEffect as
|
|
5922
|
-
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";
|
|
5923
6275
|
function units(value) {
|
|
5924
6276
|
return value === null ? "Unlimited" : Number(value).toLocaleString("en");
|
|
5925
6277
|
}
|
|
@@ -5954,10 +6306,10 @@ function Feature({
|
|
|
5954
6306
|
}) {
|
|
5955
6307
|
const { client, token } = useBase316();
|
|
5956
6308
|
const setting = feature.autoRecharge;
|
|
5957
|
-
const [busy, setBusy] =
|
|
5958
|
-
const [error, setError] =
|
|
5959
|
-
const [saved, setSaved] =
|
|
5960
|
-
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 ?? "");
|
|
5961
6313
|
const unit = feature.unit ? ` ${feature.unit}` : "";
|
|
5962
6314
|
const warning = status(feature);
|
|
5963
6315
|
const buy = async () => {
|
|
@@ -6011,33 +6363,33 @@ function Feature({
|
|
|
6011
6363
|
setBusy(false);
|
|
6012
6364
|
}
|
|
6013
6365
|
};
|
|
6014
|
-
return /* @__PURE__ */
|
|
6015
|
-
/* @__PURE__ */
|
|
6016
|
-
/* @__PURE__ */
|
|
6017
|
-
/* @__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) }),
|
|
6018
6370
|
unit,
|
|
6019
6371
|
" left"
|
|
6020
6372
|
] }),
|
|
6021
|
-
/* @__PURE__ */
|
|
6373
|
+
/* @__PURE__ */ jsxs34("div", { className: "b316-muted", children: [
|
|
6022
6374
|
feature.allowance === null ? "Unlimited allowance" : `${units(feature.allowanceRemaining)} of ${units(feature.allowance)} included this period`,
|
|
6023
6375
|
" ",
|
|
6024
6376
|
"\xB7 ",
|
|
6025
6377
|
units(feature.purchasedRemaining),
|
|
6026
6378
|
" purchased"
|
|
6027
6379
|
] }),
|
|
6028
|
-
warning && !managed ? /* @__PURE__ */
|
|
6029
|
-
error ? /* @__PURE__ */
|
|
6030
|
-
saved ? /* @__PURE__ */
|
|
6031
|
-
managed || feature.packs.length === 0 ? null : /* @__PURE__ */
|
|
6032
|
-
/* @__PURE__ */
|
|
6033
|
-
/* @__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(
|
|
6034
6386
|
"select",
|
|
6035
6387
|
{
|
|
6036
6388
|
className: "b316-input",
|
|
6037
6389
|
"aria-label": "Pack to buy",
|
|
6038
6390
|
value: pack,
|
|
6039
6391
|
onChange: (event) => setPack(event.target.value),
|
|
6040
|
-
children: feature.packs.map((option) => /* @__PURE__ */
|
|
6392
|
+
children: feature.packs.map((option) => /* @__PURE__ */ jsxs34("option", { value: option.id, children: [
|
|
6041
6393
|
option.name,
|
|
6042
6394
|
" \u2014 ",
|
|
6043
6395
|
units(option.units),
|
|
@@ -6046,7 +6398,7 @@ function Feature({
|
|
|
6046
6398
|
] }, option.id))
|
|
6047
6399
|
}
|
|
6048
6400
|
),
|
|
6049
|
-
/* @__PURE__ */
|
|
6401
|
+
/* @__PURE__ */ jsx35(
|
|
6050
6402
|
"button",
|
|
6051
6403
|
{
|
|
6052
6404
|
type: "button",
|
|
@@ -6057,19 +6409,19 @@ function Feature({
|
|
|
6057
6409
|
}
|
|
6058
6410
|
)
|
|
6059
6411
|
] }),
|
|
6060
|
-
/* @__PURE__ */
|
|
6061
|
-
/* @__PURE__ */
|
|
6062
|
-
/* @__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 }),
|
|
6063
6415
|
" ",
|
|
6064
6416
|
"Buy credits automatically when my balance runs low"
|
|
6065
6417
|
] }),
|
|
6066
|
-
/* @__PURE__ */
|
|
6067
|
-
/* @__PURE__ */
|
|
6418
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6419
|
+
/* @__PURE__ */ jsxs34("span", { className: "b316-label", children: [
|
|
6068
6420
|
"When fewer than this many",
|
|
6069
6421
|
unit,
|
|
6070
6422
|
" are left"
|
|
6071
6423
|
] }),
|
|
6072
|
-
/* @__PURE__ */
|
|
6424
|
+
/* @__PURE__ */ jsx35(
|
|
6073
6425
|
"input",
|
|
6074
6426
|
{
|
|
6075
6427
|
className: "b316-input",
|
|
@@ -6080,21 +6432,21 @@ function Feature({
|
|
|
6080
6432
|
}
|
|
6081
6433
|
)
|
|
6082
6434
|
] }),
|
|
6083
|
-
/* @__PURE__ */
|
|
6084
|
-
/* @__PURE__ */
|
|
6085
|
-
/* @__PURE__ */
|
|
6435
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6436
|
+
/* @__PURE__ */ jsx35("span", { className: "b316-label", children: "Buy" }),
|
|
6437
|
+
/* @__PURE__ */ jsx35(
|
|
6086
6438
|
"select",
|
|
6087
6439
|
{
|
|
6088
6440
|
className: "b316-input",
|
|
6089
6441
|
name: "creditPackId",
|
|
6090
6442
|
defaultValue: setting?.creditPackId ?? feature.packs[0]?.id,
|
|
6091
|
-
children: feature.packs.map((option) => /* @__PURE__ */
|
|
6443
|
+
children: feature.packs.map((option) => /* @__PURE__ */ jsx35("option", { value: option.id, children: option.name }, option.id))
|
|
6092
6444
|
}
|
|
6093
6445
|
)
|
|
6094
6446
|
] }),
|
|
6095
|
-
/* @__PURE__ */
|
|
6096
|
-
/* @__PURE__ */
|
|
6097
|
-
/* @__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(
|
|
6098
6450
|
"input",
|
|
6099
6451
|
{
|
|
6100
6452
|
className: "b316-input",
|
|
@@ -6104,13 +6456,13 @@ function Feature({
|
|
|
6104
6456
|
}
|
|
6105
6457
|
)
|
|
6106
6458
|
] }),
|
|
6107
|
-
/* @__PURE__ */
|
|
6108
|
-
/* @__PURE__ */
|
|
6459
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6460
|
+
/* @__PURE__ */ jsxs34("span", { className: "b316-label", children: [
|
|
6109
6461
|
"Spending at most (",
|
|
6110
6462
|
setting?.currency ?? feature.packs[0]?.currency ?? "USD",
|
|
6111
6463
|
") a month"
|
|
6112
6464
|
] }),
|
|
6113
|
-
/* @__PURE__ */
|
|
6465
|
+
/* @__PURE__ */ jsx35(
|
|
6114
6466
|
"input",
|
|
6115
6467
|
{
|
|
6116
6468
|
className: "b316-input",
|
|
@@ -6120,16 +6472,16 @@ function Feature({
|
|
|
6120
6472
|
}
|
|
6121
6473
|
)
|
|
6122
6474
|
] }),
|
|
6123
|
-
/* @__PURE__ */
|
|
6475
|
+
/* @__PURE__ */ jsx35("button", { type: "submit", className: "b316-button", disabled: busy, children: "Save auto-recharge" })
|
|
6124
6476
|
] })
|
|
6125
6477
|
] })
|
|
6126
6478
|
] });
|
|
6127
6479
|
}
|
|
6128
6480
|
function CreditBalances({ onChange, className, style }) {
|
|
6129
6481
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6130
|
-
const [state, setState] =
|
|
6131
|
-
const [version, setVersion] =
|
|
6132
|
-
|
|
6482
|
+
const [state, setState] = useState32({ kind: "loading" });
|
|
6483
|
+
const [version, setVersion] = useState32(0);
|
|
6484
|
+
useEffect24(() => {
|
|
6133
6485
|
if (!token) return;
|
|
6134
6486
|
let cancelled = false;
|
|
6135
6487
|
client.billing.credits(token).then((credits2) => {
|
|
@@ -6142,24 +6494,24 @@ function CreditBalances({ onChange, className, style }) {
|
|
|
6142
6494
|
cancelled = true;
|
|
6143
6495
|
};
|
|
6144
6496
|
}, [client, token, version]);
|
|
6145
|
-
const wrap = (content) => /* @__PURE__ */
|
|
6497
|
+
const wrap = (content) => /* @__PURE__ */ jsx35("div", { className: cls("b316-credit-balances", className), style, children: content });
|
|
6146
6498
|
if (sessionLoading || !token || state.kind === "loading") return null;
|
|
6147
6499
|
if (state.kind === "error") {
|
|
6148
6500
|
return wrap(
|
|
6149
|
-
/* @__PURE__ */
|
|
6501
|
+
/* @__PURE__ */ jsx35("div", { className: "b316-card", children: /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: "Could not load your credits." }) })
|
|
6150
6502
|
);
|
|
6151
6503
|
}
|
|
6152
6504
|
const { credits } = state;
|
|
6153
6505
|
if (credits.features.length === 0) return null;
|
|
6154
6506
|
return wrap(
|
|
6155
|
-
/* @__PURE__ */
|
|
6156
|
-
credits.managedBy ? /* @__PURE__ */
|
|
6507
|
+
/* @__PURE__ */ jsxs34(Fragment11, { children: [
|
|
6508
|
+
credits.managedBy ? /* @__PURE__ */ jsxs34("p", { className: "b316-muted", children: [
|
|
6157
6509
|
"Credits for this account come from",
|
|
6158
6510
|
" ",
|
|
6159
6511
|
credits.managedBy.name ?? "the organization that manages it",
|
|
6160
6512
|
", which manages them."
|
|
6161
6513
|
] }) : null,
|
|
6162
|
-
credits.features.map((feature) => /* @__PURE__ */
|
|
6514
|
+
credits.features.map((feature) => /* @__PURE__ */ jsx35(
|
|
6163
6515
|
Feature,
|
|
6164
6516
|
{
|
|
6165
6517
|
feature,
|
|
@@ -6176,19 +6528,19 @@ function CreditBalances({ onChange, className, style }) {
|
|
|
6176
6528
|
}
|
|
6177
6529
|
|
|
6178
6530
|
// src/PaymentMethod.tsx
|
|
6179
|
-
import { useEffect as
|
|
6180
|
-
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";
|
|
6181
6533
|
function brandName(brand) {
|
|
6182
6534
|
if (!brand) return "Card";
|
|
6183
6535
|
return brand.charAt(0).toUpperCase() + brand.slice(1);
|
|
6184
6536
|
}
|
|
6185
6537
|
function PaymentMethod({ returnUrl, className, style }) {
|
|
6186
6538
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6187
|
-
const [state, setState] =
|
|
6188
|
-
const [busy, setBusy] =
|
|
6189
|
-
const [error, setError] =
|
|
6190
|
-
const [version, setVersion] =
|
|
6191
|
-
|
|
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(() => {
|
|
6192
6544
|
if (!token) return;
|
|
6193
6545
|
let cancelled = false;
|
|
6194
6546
|
client.billing.paymentMethods(token).then((result) => {
|
|
@@ -6204,7 +6556,7 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6204
6556
|
cancelled = true;
|
|
6205
6557
|
};
|
|
6206
6558
|
}, [client, token, version]);
|
|
6207
|
-
const wrap = (content) => /* @__PURE__ */
|
|
6559
|
+
const wrap = (content) => /* @__PURE__ */ jsx36("div", { className: cls("b316-card b316-payment-method", className), style, children: content });
|
|
6208
6560
|
if (sessionLoading) return wrap("Loading\u2026");
|
|
6209
6561
|
if (!token) return wrap("Sign in to manage your payment method.");
|
|
6210
6562
|
switch (state.kind) {
|
|
@@ -6212,11 +6564,11 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6212
6564
|
return wrap("Loading\u2026");
|
|
6213
6565
|
case "error":
|
|
6214
6566
|
return wrap(
|
|
6215
|
-
/* @__PURE__ */
|
|
6567
|
+
/* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: "Could not load your payment method." })
|
|
6216
6568
|
);
|
|
6217
6569
|
case "managed":
|
|
6218
6570
|
return wrap(
|
|
6219
|
-
/* @__PURE__ */
|
|
6571
|
+
/* @__PURE__ */ jsx36("p", { className: "b316-muted", children: "Your plan is paid for by the organization that manages it." })
|
|
6220
6572
|
);
|
|
6221
6573
|
}
|
|
6222
6574
|
const card = state.cards.find((saved) => saved.isDefault) ?? null;
|
|
@@ -6235,31 +6587,31 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6235
6587
|
}
|
|
6236
6588
|
};
|
|
6237
6589
|
return wrap(
|
|
6238
|
-
/* @__PURE__ */
|
|
6239
|
-
/* @__PURE__ */
|
|
6240
|
-
card ? /* @__PURE__ */
|
|
6241
|
-
/* @__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: [
|
|
6242
6594
|
brandName(card.brand),
|
|
6243
6595
|
" ending ",
|
|
6244
6596
|
card.last4 ?? "????"
|
|
6245
6597
|
] }),
|
|
6246
|
-
card.expMonth && card.expYear ? /* @__PURE__ */
|
|
6598
|
+
card.expMonth && card.expYear ? /* @__PURE__ */ jsxs35("div", { className: "b316-muted", children: [
|
|
6247
6599
|
"Expires ",
|
|
6248
6600
|
String(card.expMonth).padStart(2, "0"),
|
|
6249
6601
|
"/",
|
|
6250
6602
|
card.expYear
|
|
6251
6603
|
] }) : null
|
|
6252
|
-
] }) : /* @__PURE__ */
|
|
6253
|
-
others.length > 0 ? /* @__PURE__ */
|
|
6254
|
-
/* @__PURE__ */
|
|
6255
|
-
others.map((saved) => /* @__PURE__ */
|
|
6256
|
-
/* @__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: [
|
|
6257
6609
|
brandName(saved.brand),
|
|
6258
6610
|
" ending ",
|
|
6259
6611
|
saved.last4 ?? "????"
|
|
6260
6612
|
] }),
|
|
6261
|
-
/* @__PURE__ */
|
|
6262
|
-
/* @__PURE__ */
|
|
6613
|
+
/* @__PURE__ */ jsxs35("span", { children: [
|
|
6614
|
+
/* @__PURE__ */ jsx36(
|
|
6263
6615
|
"button",
|
|
6264
6616
|
{
|
|
6265
6617
|
type: "button",
|
|
@@ -6273,7 +6625,7 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6273
6625
|
}
|
|
6274
6626
|
),
|
|
6275
6627
|
" ",
|
|
6276
|
-
/* @__PURE__ */
|
|
6628
|
+
/* @__PURE__ */ jsx36(
|
|
6277
6629
|
"button",
|
|
6278
6630
|
{
|
|
6279
6631
|
type: "button",
|
|
@@ -6289,8 +6641,8 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6289
6641
|
] })
|
|
6290
6642
|
] }, saved.id))
|
|
6291
6643
|
] }) : null,
|
|
6292
|
-
error ? /* @__PURE__ */
|
|
6293
|
-
/* @__PURE__ */
|
|
6644
|
+
error ? /* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6645
|
+
/* @__PURE__ */ jsx36(
|
|
6294
6646
|
"button",
|
|
6295
6647
|
{
|
|
6296
6648
|
type: "button",
|
|
@@ -6319,8 +6671,8 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6319
6671
|
}
|
|
6320
6672
|
|
|
6321
6673
|
// src/PlanChangeReview.tsx
|
|
6322
|
-
import { useCallback as useCallback11, useEffect as
|
|
6323
|
-
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";
|
|
6324
6676
|
function money5(amount, currency) {
|
|
6325
6677
|
if (amount === null) return "\u2014";
|
|
6326
6678
|
const value = Number(amount);
|
|
@@ -6353,12 +6705,12 @@ function PlanChangeReview({
|
|
|
6353
6705
|
style
|
|
6354
6706
|
}) {
|
|
6355
6707
|
const { client, token } = useBase316();
|
|
6356
|
-
const [timing, setTiming] =
|
|
6357
|
-
const [preview, setPreview] =
|
|
6358
|
-
const [error, setError] =
|
|
6359
|
-
const [needsCard, setNeedsCard] =
|
|
6360
|
-
const [busy, setBusy] =
|
|
6361
|
-
|
|
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(() => {
|
|
6362
6714
|
if (!token) return;
|
|
6363
6715
|
let cancelled = false;
|
|
6364
6716
|
client.billing.previewPlanChange(token, planVersionId, timing).then((result) => {
|
|
@@ -6410,12 +6762,12 @@ function PlanChangeReview({
|
|
|
6410
6762
|
setError("Cards cannot be added here right now.");
|
|
6411
6763
|
}
|
|
6412
6764
|
}, [client, token, onNeedsCard]);
|
|
6413
|
-
const card = (content) => /* @__PURE__ */
|
|
6765
|
+
const card = (content) => /* @__PURE__ */ jsx37("div", { className: cls("b316-card b316-plan-review", className), style, children: content });
|
|
6414
6766
|
if (error && !preview) {
|
|
6415
6767
|
return card(
|
|
6416
|
-
/* @__PURE__ */
|
|
6417
|
-
/* @__PURE__ */
|
|
6418
|
-
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
|
|
6419
6771
|
] })
|
|
6420
6772
|
);
|
|
6421
6773
|
}
|
|
@@ -6428,26 +6780,26 @@ function PlanChangeReview({
|
|
|
6428
6780
|
const otherReason = preview.timings[other]?.reason ?? null;
|
|
6429
6781
|
const changes = preview.entitlements.filter((change) => change.change !== "UNCHANGED");
|
|
6430
6782
|
return card(
|
|
6431
|
-
/* @__PURE__ */
|
|
6432
|
-
/* @__PURE__ */
|
|
6783
|
+
/* @__PURE__ */ jsxs36(Fragment13, { children: [
|
|
6784
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-plan-name", children: [
|
|
6433
6785
|
"Change to ",
|
|
6434
6786
|
to.planName
|
|
6435
6787
|
] }),
|
|
6436
|
-
/* @__PURE__ */
|
|
6788
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-muted", children: [
|
|
6437
6789
|
"From ",
|
|
6438
6790
|
from.planName
|
|
6439
6791
|
] }),
|
|
6440
|
-
error ? /* @__PURE__ */
|
|
6441
|
-
changes.length === 0 ? /* @__PURE__ */
|
|
6442
|
-
/* @__PURE__ */
|
|
6443
|
-
/* @__PURE__ */
|
|
6444
|
-
/* @__PURE__ */
|
|
6445
|
-
/* @__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 })
|
|
6446
6798
|
] }) }),
|
|
6447
|
-
/* @__PURE__ */
|
|
6448
|
-
/* @__PURE__ */
|
|
6449
|
-
/* @__PURE__ */
|
|
6450
|
-
/* @__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(
|
|
6451
6803
|
"td",
|
|
6452
6804
|
{
|
|
6453
6805
|
className: change.change === "GAINED" || change.change === "INCREASED" ? "b316-review-gain" : "b316-review-loss",
|
|
@@ -6456,40 +6808,40 @@ function PlanChangeReview({
|
|
|
6456
6808
|
)
|
|
6457
6809
|
] }, change.featureId)) })
|
|
6458
6810
|
] }),
|
|
6459
|
-
preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */
|
|
6811
|
+
preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */ jsxs36("p", { children: [
|
|
6460
6812
|
"The change happens now. Your trial carries on until ",
|
|
6461
6813
|
day4(now.trialEndsAt),
|
|
6462
6814
|
", and nothing is charged before then."
|
|
6463
|
-
] }) : /* @__PURE__ */
|
|
6464
|
-
Number(now.credit) > 0 ? /* @__PURE__ */
|
|
6465
|
-
/* @__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: [
|
|
6466
6818
|
"Credit for the unused part of ",
|
|
6467
6819
|
from.planName
|
|
6468
6820
|
] }),
|
|
6469
|
-
/* @__PURE__ */
|
|
6821
|
+
/* @__PURE__ */ jsxs36("span", { className: "b316-num", children: [
|
|
6470
6822
|
"\u2212",
|
|
6471
6823
|
money5(now.credit, from.currency)
|
|
6472
6824
|
] })
|
|
6473
6825
|
] }) : null,
|
|
6474
|
-
Number(now.closingUsage) > 0 ? /* @__PURE__ */
|
|
6475
|
-
/* @__PURE__ */
|
|
6476
|
-
/* @__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) })
|
|
6477
6829
|
] }) : null,
|
|
6478
|
-
/* @__PURE__ */
|
|
6479
|
-
/* @__PURE__ */
|
|
6830
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-row", children: [
|
|
6831
|
+
/* @__PURE__ */ jsxs36("span", { className: "b316-muted", children: [
|
|
6480
6832
|
to.planName,
|
|
6481
6833
|
", ",
|
|
6482
6834
|
day4(now.newPeriod.start),
|
|
6483
6835
|
" \u2013 ",
|
|
6484
6836
|
day4(now.newPeriod.end)
|
|
6485
6837
|
] }),
|
|
6486
|
-
/* @__PURE__ */
|
|
6838
|
+
/* @__PURE__ */ jsx37("span", { className: "b316-num", children: money5(now.newPeriodCharge, to.currency) })
|
|
6487
6839
|
] }),
|
|
6488
|
-
now.net !== null ? /* @__PURE__ */
|
|
6489
|
-
/* @__PURE__ */
|
|
6490
|
-
/* @__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) })
|
|
6491
6843
|
] }) : null
|
|
6492
|
-
] }) : /* @__PURE__ */
|
|
6844
|
+
] }) : /* @__PURE__ */ jsxs36("p", { children: [
|
|
6493
6845
|
"You keep ",
|
|
6494
6846
|
from.planName,
|
|
6495
6847
|
" until ",
|
|
@@ -6502,7 +6854,7 @@ function PlanChangeReview({
|
|
|
6502
6854
|
preview.atPeriodEnd.nextInvoice.currency
|
|
6503
6855
|
)}.` : ""
|
|
6504
6856
|
] }),
|
|
6505
|
-
otherOpen ? /* @__PURE__ */
|
|
6857
|
+
otherOpen ? /* @__PURE__ */ jsx37(
|
|
6506
6858
|
"button",
|
|
6507
6859
|
{
|
|
6508
6860
|
type: "button",
|
|
@@ -6513,12 +6865,12 @@ function PlanChangeReview({
|
|
|
6513
6865
|
},
|
|
6514
6866
|
children: other === "NOW" ? "Change now instead" : "Wait until the end of the period instead"
|
|
6515
6867
|
}
|
|
6516
|
-
) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */
|
|
6517
|
-
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: [
|
|
6518
6870
|
"A card is needed for a change that is charged now.",
|
|
6519
|
-
/* @__PURE__ */
|
|
6520
|
-
] }) : /* @__PURE__ */
|
|
6521
|
-
/* @__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(
|
|
6522
6874
|
"button",
|
|
6523
6875
|
{
|
|
6524
6876
|
type: "button",
|
|
@@ -6528,7 +6880,7 @@ function PlanChangeReview({
|
|
|
6528
6880
|
children: busy ? "Working\u2026" : preview.timing === "NOW" ? `Change to ${to.planName} now` : `Schedule ${to.planName}`
|
|
6529
6881
|
}
|
|
6530
6882
|
),
|
|
6531
|
-
onCancel ? /* @__PURE__ */
|
|
6883
|
+
onCancel ? /* @__PURE__ */ jsxs36("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: [
|
|
6532
6884
|
"Keep ",
|
|
6533
6885
|
from.planName
|
|
6534
6886
|
] }) : null
|
|
@@ -6538,7 +6890,7 @@ function PlanChangeReview({
|
|
|
6538
6890
|
}
|
|
6539
6891
|
|
|
6540
6892
|
// src/BillingPortal.tsx
|
|
6541
|
-
import { Fragment as
|
|
6893
|
+
import { Fragment as Fragment14, jsx as jsx38, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
6542
6894
|
function BillingPortal({
|
|
6543
6895
|
returnUrl,
|
|
6544
6896
|
featuredPlanKey,
|
|
@@ -6548,12 +6900,12 @@ function BillingPortal({
|
|
|
6548
6900
|
style
|
|
6549
6901
|
}) {
|
|
6550
6902
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6551
|
-
const [overview, setOverview] =
|
|
6552
|
-
const [failed, setFailed] =
|
|
6553
|
-
const [version, setVersion] =
|
|
6554
|
-
const [reviewing, setReviewing] =
|
|
6555
|
-
const [notice, setNotice] =
|
|
6556
|
-
|
|
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(() => {
|
|
6557
6909
|
if (!token) return;
|
|
6558
6910
|
let cancelled = false;
|
|
6559
6911
|
client.billing.subscription(token).then((result) => {
|
|
@@ -6576,24 +6928,24 @@ function BillingPortal({
|
|
|
6576
6928
|
setNotice(null);
|
|
6577
6929
|
setVersion((value) => value + 1);
|
|
6578
6930
|
}, []);
|
|
6579
|
-
const shell = (content) => /* @__PURE__ */
|
|
6580
|
-
if (sessionLoading) return shell(/* @__PURE__ */
|
|
6581
|
-
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." }));
|
|
6582
6934
|
if (failed) {
|
|
6583
6935
|
return shell(
|
|
6584
|
-
/* @__PURE__ */
|
|
6936
|
+
/* @__PURE__ */ jsx38("div", { className: "b316-card", children: /* @__PURE__ */ jsx38("div", { className: "b316-error", role: "alert", children: "Could not load your billing." }) })
|
|
6585
6937
|
);
|
|
6586
6938
|
}
|
|
6587
|
-
if (!overview) return shell(/* @__PURE__ */
|
|
6939
|
+
if (!overview) return shell(/* @__PURE__ */ jsx38("div", { className: "b316-card", children: "Loading\u2026" }));
|
|
6588
6940
|
const { subscription, managedBy, quantityPriced } = overview;
|
|
6589
6941
|
const canChange = Boolean(subscription) && !managedBy;
|
|
6590
6942
|
return shell(
|
|
6591
|
-
/* @__PURE__ */
|
|
6592
|
-
notice ? /* @__PURE__ */
|
|
6593
|
-
/* @__PURE__ */
|
|
6594
|
-
canChange ? /* @__PURE__ */
|
|
6595
|
-
canChange && quantityPriced ? /* @__PURE__ */
|
|
6596
|
-
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(
|
|
6597
6949
|
PlanChangeReview,
|
|
6598
6950
|
{
|
|
6599
6951
|
planVersionId: reviewing,
|
|
@@ -6606,9 +6958,9 @@ function BillingPortal({
|
|
|
6606
6958
|
);
|
|
6607
6959
|
}
|
|
6608
6960
|
}
|
|
6609
|
-
) : /* @__PURE__ */
|
|
6610
|
-
/* @__PURE__ */
|
|
6611
|
-
/* @__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(
|
|
6612
6964
|
PricingTable,
|
|
6613
6965
|
{
|
|
6614
6966
|
featuredPlanKey,
|
|
@@ -6620,17 +6972,17 @@ function BillingPortal({
|
|
|
6620
6972
|
`plans-${version}`
|
|
6621
6973
|
)
|
|
6622
6974
|
] }),
|
|
6623
|
-
/* @__PURE__ */
|
|
6624
|
-
managedBy ? null : /* @__PURE__ */
|
|
6625
|
-
/* @__PURE__ */
|
|
6626
|
-
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
|
|
6627
6979
|
] })
|
|
6628
6980
|
);
|
|
6629
6981
|
}
|
|
6630
6982
|
|
|
6631
6983
|
// src/ApiKeyManager.tsx
|
|
6632
|
-
import { useCallback as useCallback13, useEffect as
|
|
6633
|
-
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";
|
|
6634
6986
|
function duration(seconds) {
|
|
6635
6987
|
if (seconds % 3600 === 0) {
|
|
6636
6988
|
return `${seconds / 3600}h`;
|
|
@@ -6647,16 +6999,16 @@ function ApiKeyManager({
|
|
|
6647
6999
|
audience
|
|
6648
7000
|
}) {
|
|
6649
7001
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6650
|
-
const [resources, setResources] =
|
|
6651
|
-
const [credentials, setCredentials] =
|
|
6652
|
-
const [loading, setLoading] =
|
|
6653
|
-
const [busy, setBusy] =
|
|
6654
|
-
const [error, setError] =
|
|
6655
|
-
const [creating, setCreating] =
|
|
6656
|
-
const [name, setName] =
|
|
6657
|
-
const [chosen, setChosen] =
|
|
6658
|
-
const [resourceId, setResourceId] =
|
|
6659
|
-
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);
|
|
6660
7012
|
const load = useCallback13(async () => {
|
|
6661
7013
|
if (!token) {
|
|
6662
7014
|
setLoading(false);
|
|
@@ -6678,20 +7030,20 @@ function ApiKeyManager({
|
|
|
6678
7030
|
setLoading(false);
|
|
6679
7031
|
}
|
|
6680
7032
|
}, [client, token, audience]);
|
|
6681
|
-
|
|
7033
|
+
useEffect28(() => {
|
|
6682
7034
|
void load();
|
|
6683
7035
|
}, [load]);
|
|
6684
7036
|
if (sessionLoading || loading) {
|
|
6685
|
-
return /* @__PURE__ */
|
|
7037
|
+
return /* @__PURE__ */ jsx39("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
6686
7038
|
}
|
|
6687
7039
|
if (!token) {
|
|
6688
|
-
return /* @__PURE__ */
|
|
7040
|
+
return /* @__PURE__ */ jsx39("div", { className: cls("b316-card", className), style, children: "Sign in to manage your API keys." });
|
|
6689
7041
|
}
|
|
6690
7042
|
if (error) {
|
|
6691
|
-
return /* @__PURE__ */
|
|
7043
|
+
return /* @__PURE__ */ jsx39("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx39("div", { className: "b316-error", role: "alert", children: error }) });
|
|
6692
7044
|
}
|
|
6693
7045
|
if (resources.length === 0) {
|
|
6694
|
-
return /* @__PURE__ */
|
|
7046
|
+
return /* @__PURE__ */ jsx39("div", { className: cls("b316-card", className), style, children: "There are no APIs available to your account." });
|
|
6695
7047
|
}
|
|
6696
7048
|
const resource = resources.find((item) => item.id === resourceId) ?? resources[0];
|
|
6697
7049
|
const reset = () => {
|
|
@@ -6700,37 +7052,37 @@ function ApiKeyManager({
|
|
|
6700
7052
|
setChosen([]);
|
|
6701
7053
|
setIssued(null);
|
|
6702
7054
|
};
|
|
6703
|
-
return /* @__PURE__ */
|
|
6704
|
-
error ? /* @__PURE__ */
|
|
6705
|
-
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(
|
|
6706
7058
|
"select",
|
|
6707
7059
|
{
|
|
6708
7060
|
className: "b316-input",
|
|
6709
7061
|
value: resource.id,
|
|
6710
7062
|
onChange: (event) => setResourceId(event.target.value),
|
|
6711
7063
|
style: { marginBottom: 14 },
|
|
6712
|
-
children: resources.map((item) => /* @__PURE__ */
|
|
7064
|
+
children: resources.map((item) => /* @__PURE__ */ jsx39("option", { value: item.id, children: item.name }, item.id))
|
|
6713
7065
|
}
|
|
6714
|
-
) : /* @__PURE__ */
|
|
6715
|
-
resource.rateLimit ? /* @__PURE__ */
|
|
7066
|
+
) : /* @__PURE__ */ jsx39("div", { className: "b316-plan-name", children: resource.name }),
|
|
7067
|
+
resource.rateLimit ? /* @__PURE__ */ jsxs38("div", { className: "b316-muted", children: [
|
|
6716
7068
|
resource.rateLimit.requestsPerWindow,
|
|
6717
7069
|
" requests per",
|
|
6718
7070
|
" ",
|
|
6719
7071
|
duration(resource.rateLimit.windowSeconds),
|
|
6720
7072
|
resource.rateLimit.burst > resource.rateLimit.requestsPerWindow ? `, bursting to ${resource.rateLimit.burst}` : null
|
|
6721
|
-
] }) : /* @__PURE__ */
|
|
6722
|
-
credentials.length === 0 ? /* @__PURE__ */
|
|
6723
|
-
/* @__PURE__ */
|
|
6724
|
-
/* @__PURE__ */
|
|
6725
|
-
/* @__PURE__ */
|
|
6726
|
-
/* @__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 }),
|
|
6727
7079
|
credential.secretLastFour ? ` \xB7 \u2026${credential.secretLastFour}` : null,
|
|
6728
7080
|
credential.disabled ? " \xB7 Disabled" : null
|
|
6729
7081
|
] }),
|
|
6730
|
-
/* @__PURE__ */
|
|
7082
|
+
/* @__PURE__ */ jsx39("div", { className: "b316-muted", children: credential.scopes.join(", ") })
|
|
6731
7083
|
] }),
|
|
6732
|
-
/* @__PURE__ */
|
|
6733
|
-
/* @__PURE__ */
|
|
7084
|
+
/* @__PURE__ */ jsxs38("div", { style: { display: "flex", gap: 8 }, children: [
|
|
7085
|
+
/* @__PURE__ */ jsx39(
|
|
6734
7086
|
"button",
|
|
6735
7087
|
{
|
|
6736
7088
|
type: "button",
|
|
@@ -6759,7 +7111,7 @@ function ApiKeyManager({
|
|
|
6759
7111
|
children: "Rotate"
|
|
6760
7112
|
}
|
|
6761
7113
|
),
|
|
6762
|
-
/* @__PURE__ */
|
|
7114
|
+
/* @__PURE__ */ jsx39(
|
|
6763
7115
|
ConfirmButton,
|
|
6764
7116
|
{
|
|
6765
7117
|
className: "b316-button b316-button-secondary",
|
|
@@ -6783,11 +7135,11 @@ function ApiKeyManager({
|
|
|
6783
7135
|
)
|
|
6784
7136
|
] })
|
|
6785
7137
|
] }, credential.clientId)) }),
|
|
6786
|
-
issued ? /* @__PURE__ */
|
|
6787
|
-
/* @__PURE__ */
|
|
7138
|
+
issued ? /* @__PURE__ */ jsxs38("div", { className: "b316-notice", style: { marginTop: 14 }, children: [
|
|
7139
|
+
/* @__PURE__ */ jsx39("strong", { children: "Copy this now." }),
|
|
6788
7140
|
" It is shown once and cannot be retrieved again.",
|
|
6789
|
-
/* @__PURE__ */
|
|
6790
|
-
/* @__PURE__ */
|
|
7141
|
+
/* @__PURE__ */ jsx39("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx39("code", { style: { wordBreak: "break-all" }, children: issued.secret }) }),
|
|
7142
|
+
/* @__PURE__ */ jsx39(
|
|
6791
7143
|
"button",
|
|
6792
7144
|
{
|
|
6793
7145
|
type: "button",
|
|
@@ -6800,7 +7152,7 @@ function ApiKeyManager({
|
|
|
6800
7152
|
children: "Copy"
|
|
6801
7153
|
}
|
|
6802
7154
|
),
|
|
6803
|
-
/* @__PURE__ */
|
|
7155
|
+
/* @__PURE__ */ jsx39(
|
|
6804
7156
|
"button",
|
|
6805
7157
|
{
|
|
6806
7158
|
type: "button",
|
|
@@ -6811,8 +7163,8 @@ function ApiKeyManager({
|
|
|
6811
7163
|
}
|
|
6812
7164
|
)
|
|
6813
7165
|
] }) : null,
|
|
6814
|
-
creating && !issued ? /* @__PURE__ */
|
|
6815
|
-
/* @__PURE__ */
|
|
7166
|
+
creating && !issued ? /* @__PURE__ */ jsxs38("div", { style: { marginTop: 14 }, children: [
|
|
7167
|
+
/* @__PURE__ */ jsx39(
|
|
6816
7168
|
"input",
|
|
6817
7169
|
{
|
|
6818
7170
|
className: "b316-input",
|
|
@@ -6821,9 +7173,9 @@ function ApiKeyManager({
|
|
|
6821
7173
|
onChange: (event) => setName(event.target.value)
|
|
6822
7174
|
}
|
|
6823
7175
|
),
|
|
6824
|
-
/* @__PURE__ */
|
|
6825
|
-
resource.availableScopes.map((scope) => /* @__PURE__ */
|
|
6826
|
-
/* @__PURE__ */
|
|
7176
|
+
/* @__PURE__ */ jsxs38("div", { style: { marginTop: 10 }, children: [
|
|
7177
|
+
resource.availableScopes.map((scope) => /* @__PURE__ */ jsxs38("label", { className: "b316-checkbox", children: [
|
|
7178
|
+
/* @__PURE__ */ jsx39(
|
|
6827
7179
|
"input",
|
|
6828
7180
|
{
|
|
6829
7181
|
type: "checkbox",
|
|
@@ -6833,19 +7185,19 @@ function ApiKeyManager({
|
|
|
6833
7185
|
)
|
|
6834
7186
|
}
|
|
6835
7187
|
),
|
|
6836
|
-
/* @__PURE__ */
|
|
6837
|
-
scope.description ? /* @__PURE__ */
|
|
7188
|
+
/* @__PURE__ */ jsx39("code", { children: scope.key }),
|
|
7189
|
+
scope.description ? /* @__PURE__ */ jsxs38("span", { className: "b316-muted", children: [
|
|
6838
7190
|
" \u2014 ",
|
|
6839
7191
|
scope.description
|
|
6840
7192
|
] }) : null
|
|
6841
7193
|
] }, scope.key)),
|
|
6842
|
-
resource.lockedScopes.map((scope) => /* @__PURE__ */
|
|
6843
|
-
/* @__PURE__ */
|
|
6844
|
-
/* @__PURE__ */
|
|
6845
|
-
/* @__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" })
|
|
6846
7198
|
] }, scope.key))
|
|
6847
7199
|
] }),
|
|
6848
|
-
/* @__PURE__ */
|
|
7200
|
+
/* @__PURE__ */ jsx39(
|
|
6849
7201
|
"button",
|
|
6850
7202
|
{
|
|
6851
7203
|
type: "button",
|
|
@@ -6879,7 +7231,7 @@ function ApiKeyManager({
|
|
|
6879
7231
|
children: "Create key"
|
|
6880
7232
|
}
|
|
6881
7233
|
),
|
|
6882
|
-
/* @__PURE__ */
|
|
7234
|
+
/* @__PURE__ */ jsx39(
|
|
6883
7235
|
"button",
|
|
6884
7236
|
{
|
|
6885
7237
|
type: "button",
|
|
@@ -6890,7 +7242,7 @@ function ApiKeyManager({
|
|
|
6890
7242
|
}
|
|
6891
7243
|
)
|
|
6892
7244
|
] }) : null,
|
|
6893
|
-
!creating && !issued ? /* @__PURE__ */
|
|
7245
|
+
!creating && !issued ? /* @__PURE__ */ jsx39(
|
|
6894
7246
|
"button",
|
|
6895
7247
|
{
|
|
6896
7248
|
type: "button",
|
|
@@ -6965,26 +7317,45 @@ var MANIFEST = [
|
|
|
6965
7317
|
{
|
|
6966
7318
|
name: "SignIn",
|
|
6967
7319
|
kind: "component",
|
|
6968
|
-
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`).",
|
|
6969
7321
|
useWhen: "The application renders its own sign-in rather than redirecting to the hosted page.",
|
|
6970
7322
|
requires: [],
|
|
6971
7323
|
props: [
|
|
6972
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
|
+
},
|
|
6973
7330
|
{
|
|
6974
7331
|
name: "passkeys",
|
|
6975
|
-
summary: "
|
|
7332
|
+
summary: "`false` hides passkeys; otherwise offered where the environment and browser allow.",
|
|
6976
7333
|
required: false
|
|
6977
7334
|
},
|
|
7335
|
+
{ name: "magicLink", summary: "`false` hides the emailed sign-in link.", required: false },
|
|
6978
7336
|
{
|
|
6979
7337
|
name: "magicLinkRedirectUrl",
|
|
6980
|
-
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.",
|
|
6981
7345
|
required: false
|
|
6982
7346
|
},
|
|
7347
|
+
{ name: "sso", summary: '`false` hides "Sign in with SSO".', required: false },
|
|
6983
7348
|
{
|
|
6984
|
-
name: "
|
|
6985
|
-
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.",
|
|
6986
7351
|
required: false
|
|
6987
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 },
|
|
6988
7359
|
{
|
|
6989
7360
|
name: "secondFactorLabels",
|
|
6990
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.",
|
|
@@ -6994,6 +7365,38 @@ var MANIFEST = [
|
|
|
6994
7365
|
],
|
|
6995
7366
|
seeAlso: ["SignUp", "ForgotPassword", "SecondFactorStep"]
|
|
6996
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
|
+
},
|
|
6997
7400
|
{
|
|
6998
7401
|
name: "SignUp",
|
|
6999
7402
|
kind: "component",
|
|
@@ -7022,6 +7425,21 @@ var MANIFEST = [
|
|
|
7022
7425
|
summary: "Wording for the second-factor step, for translation.",
|
|
7023
7426
|
required: false
|
|
7024
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
|
+
},
|
|
7025
7443
|
...appearance
|
|
7026
7444
|
],
|
|
7027
7445
|
seeAlso: ["SignIn", "VerifyEmail", "SecondFactorStep"]
|
|
@@ -7793,6 +8211,7 @@ export {
|
|
|
7793
8211
|
SecondFactorStep,
|
|
7794
8212
|
SignIn,
|
|
7795
8213
|
SignUp,
|
|
8214
|
+
SocialSignIn,
|
|
7796
8215
|
SubscriptionManager,
|
|
7797
8216
|
TeamMembers,
|
|
7798
8217
|
TwoFactorManager,
|