@base316/react 0.6.0 → 0.8.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 +69 -0
- package/README.md +3 -3
- package/dist/index.cjs +1595 -998
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1553 -955
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +117 -9
- package/dist/src/CaptchaWidget.d.ts +22 -0
- package/dist/src/CaptchaWidget.d.ts.map +1 -0
- package/dist/src/SecondFactorStep.d.ts +2 -2
- package/dist/src/SignIn.d.ts +79 -18
- package/dist/src/SignIn.d.ts.map +1 -1
- package/dist/src/SignUp.d.ts +27 -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/TeamMembers.d.ts +1 -1
- package/dist/src/TwoFactorManager.d.ts +1 -1
- package/dist/src/appearance.d.ts +4 -4
- package/dist/src/appearance.d.ts.map +1 -1
- package/dist/src/manifest.d.ts +1 -1
- package/dist/src/manifest.d.ts.map +1 -1
- package/dist/src/provider.d.ts +3 -3
- 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/useAddons.d.ts +29 -0
- package/dist/src/useAddons.d.ts.map +1 -0
- package/dist/src/usePaymentLink.d.ts +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -162,7 +162,7 @@ var STYLESHEET = `
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
/* The recommended plan. Lifted rather than merely tinted: on a pricing table
|
|
165
|
-
the eye needs one obvious default, and
|
|
165
|
+
the eye needs one obvious default, and color alone does not survive being
|
|
166
166
|
viewed in greyscale or by someone who cannot distinguish the accent. */
|
|
167
167
|
.b316-plan-featured {
|
|
168
168
|
border-color: var(--b316-color-primary);
|
|
@@ -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; }
|
|
@@ -532,7 +549,7 @@ var STYLESHEET_EXTRA = `
|
|
|
532
549
|
.b316-mfa-uri { font-size: 0.9em; }
|
|
533
550
|
.b316-mfa-code-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
|
|
534
551
|
.b316-mfa-code-list code { user-select: all; }
|
|
535
|
-
/* The
|
|
552
|
+
/* The enrollment choices: whole-width buttons with their explanation inside,
|
|
536
553
|
so the explanation is part of what a screen reader announces. */
|
|
537
554
|
.b316-mfa-methods { display: flex; flex-direction: column; gap: 8px; border: 0; margin: 0; padding: 0; min-width: 0; }
|
|
538
555
|
.b316-mfa-method { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; text-align: left; }
|
|
@@ -663,7 +680,7 @@ function Base316Provider({
|
|
|
663
680
|
const [internalToken, setInternalToken] = useState(null);
|
|
664
681
|
const [session, setSession] = useState(null);
|
|
665
682
|
const [branding, setBranding] = useState(null);
|
|
666
|
-
const [
|
|
683
|
+
const [loading2, setLoading] = useState(true);
|
|
667
684
|
const token = controlled ? controlledToken : internalToken;
|
|
668
685
|
useEffect(() => {
|
|
669
686
|
if (controlled) {
|
|
@@ -725,8 +742,8 @@ function Base316Provider({
|
|
|
725
742
|
setSession(null);
|
|
726
743
|
}, [client, token, setToken]);
|
|
727
744
|
const value = useMemo(
|
|
728
|
-
() => ({ client, branding, token, setToken, session, loading, refresh, signOut }),
|
|
729
|
-
[client, branding, token, setToken, session,
|
|
745
|
+
() => ({ client, branding, token, setToken, session, loading: loading2, refresh, signOut }),
|
|
746
|
+
[client, branding, token, setToken, session, loading2, refresh, signOut]
|
|
730
747
|
);
|
|
731
748
|
return /* @__PURE__ */ jsx(Base316Context.Provider, { value, children: /* @__PURE__ */ jsx(
|
|
732
749
|
"div",
|
|
@@ -735,7 +752,7 @@ function Base316Provider({
|
|
|
735
752
|
style: appearanceToStyle({
|
|
736
753
|
// Whatever was set in the sign-in designer arrives here, so a
|
|
737
754
|
// customer styles their login once on Base316 and the embedded
|
|
738
|
-
// components follow — rather than configuring the same
|
|
755
|
+
// components follow — rather than configuring the same colors
|
|
739
756
|
// twice and watching them drift apart.
|
|
740
757
|
//
|
|
741
758
|
// An explicit `appearance` still wins, because a host that has
|
|
@@ -758,8 +775,8 @@ function useBase316() {
|
|
|
758
775
|
return value;
|
|
759
776
|
}
|
|
760
777
|
function useSession() {
|
|
761
|
-
const { session, loading } = useBase316();
|
|
762
|
-
return { session, loading };
|
|
778
|
+
const { session, loading: loading2 } = useBase316();
|
|
779
|
+
return { session, loading: loading2 };
|
|
763
780
|
}
|
|
764
781
|
|
|
765
782
|
// src/Branding.tsx
|
|
@@ -1607,7 +1624,7 @@ import {
|
|
|
1607
1624
|
isPasskeySupported,
|
|
1608
1625
|
needsSecondFactor
|
|
1609
1626
|
} from "@base316/sdk";
|
|
1610
|
-
import { useEffect as
|
|
1627
|
+
import { useEffect as useEffect8, useRef as useRef2, useState as useState8 } from "react";
|
|
1611
1628
|
|
|
1612
1629
|
// src/SecondFactorStep.tsx
|
|
1613
1630
|
import {
|
|
@@ -1998,33 +2015,233 @@ function SecondFactorStep({
|
|
|
1998
2015
|
return /* @__PURE__ */ jsx7("div", { className: cls("b316-mfa", className), style, children: body });
|
|
1999
2016
|
}
|
|
2000
2017
|
|
|
2018
|
+
// src/sign-in-methods.ts
|
|
2019
|
+
import {
|
|
2020
|
+
OAUTH_STATE_COOKIE,
|
|
2021
|
+
createOAuthState
|
|
2022
|
+
} from "@base316/sdk";
|
|
2023
|
+
import { useEffect as useEffect7, useState as useState7 } from "react";
|
|
2024
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
2025
|
+
function loadSignInMethods(client) {
|
|
2026
|
+
let pending = cache.get(client);
|
|
2027
|
+
if (!pending) {
|
|
2028
|
+
pending = client.auth.methods();
|
|
2029
|
+
cache.set(client, pending);
|
|
2030
|
+
pending.catch(() => cache.delete(client));
|
|
2031
|
+
}
|
|
2032
|
+
return pending;
|
|
2033
|
+
}
|
|
2034
|
+
function useSignInMethods(client) {
|
|
2035
|
+
const [state, setState] = useState7({ status: "loading", methods: null });
|
|
2036
|
+
useEffect7(() => {
|
|
2037
|
+
let cancelled = false;
|
|
2038
|
+
loadSignInMethods(client).then((methods) => {
|
|
2039
|
+
if (!cancelled) setState({ status: "ready", methods });
|
|
2040
|
+
}).catch(() => {
|
|
2041
|
+
if (!cancelled) setState({ status: "unavailable", methods: null });
|
|
2042
|
+
});
|
|
2043
|
+
return () => {
|
|
2044
|
+
cancelled = true;
|
|
2045
|
+
};
|
|
2046
|
+
}, [client]);
|
|
2047
|
+
return state;
|
|
2048
|
+
}
|
|
2049
|
+
function resolveMethods(methods, props, currentPage) {
|
|
2050
|
+
if (!methods) {
|
|
2051
|
+
return {
|
|
2052
|
+
password: props.password !== false,
|
|
2053
|
+
passkeys: props.passkeys !== false,
|
|
2054
|
+
magicLink: props.magicLink !== false ? props.magicLinkRedirectUrl ?? null : null,
|
|
2055
|
+
phone: props.phone === true,
|
|
2056
|
+
social: [],
|
|
2057
|
+
sso: false,
|
|
2058
|
+
signUp: true,
|
|
2059
|
+
hostedUrl: void 0
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2062
|
+
const redirect = props.socialRedirectUrl;
|
|
2063
|
+
const only = Array.isArray(props.social) ? new Set(props.social.map((entry) => entry.toLowerCase())) : null;
|
|
2064
|
+
return {
|
|
2065
|
+
password: methods.password && props.password !== false,
|
|
2066
|
+
passkeys: methods.passkeys && props.passkeys !== false,
|
|
2067
|
+
magicLink: methods.magicLink && props.magicLink !== false ? props.magicLinkRedirectUrl ?? currentPage : null,
|
|
2068
|
+
phone: methods.phone && props.phone !== false,
|
|
2069
|
+
social: redirect && props.social !== false ? methods.social.filter(
|
|
2070
|
+
(option) => !only || only.has(option.slug.toLowerCase()) || only.has(option.provider.toLowerCase())
|
|
2071
|
+
) : [],
|
|
2072
|
+
sso: Boolean(redirect) && methods.sso && props.sso !== false,
|
|
2073
|
+
signUp: methods.signUp,
|
|
2074
|
+
hostedUrl: methods.hostedUrl
|
|
2075
|
+
};
|
|
2076
|
+
}
|
|
2077
|
+
function beginRedirect(build, appState) {
|
|
2078
|
+
const { state, nonce } = createOAuthState(appState);
|
|
2079
|
+
const secure = window.location.protocol === "https:" ? "; Secure" : "";
|
|
2080
|
+
document.cookie = `${OAUTH_STATE_COOKIE}=${nonce}; Path=/; Max-Age=600; SameSite=Lax${secure}`;
|
|
2081
|
+
window.location.assign(build(state));
|
|
2082
|
+
}
|
|
2083
|
+
function currentPageUrl() {
|
|
2084
|
+
if (typeof window === "undefined") {
|
|
2085
|
+
return null;
|
|
2086
|
+
}
|
|
2087
|
+
return `${window.location.origin}${window.location.pathname}`;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
// src/social-icons.ts
|
|
2091
|
+
var PROVIDER_ICON = {
|
|
2092
|
+
GOOGLE: `<svg viewBox="0 0 18 18" aria-hidden="true"><path fill="#4285F4" d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62Z"/><path fill="#34A853" d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18Z"/><path fill="#FBBC05" d="M3.97 10.72a5.4 5.4 0 0 1 0-3.44V4.95H.96a9 9 0 0 0 0 8.1l3.01-2.33Z"/><path fill="#EA4335" d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.58C13.46.9 11.43 0 9 0A9 9 0 0 0 .96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58Z"/></svg>`,
|
|
2093
|
+
FACEBOOK: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M24 12.07C24 5.4 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.05V9.41c0-3.02 1.79-4.69 4.53-4.69 1.31 0 2.68.24 2.68.24v2.96h-1.51c-1.49 0-1.96.93-1.96 1.89v2.26h3.33l-.53 3.49h-2.8V24C19.61 23.1 24 18.1 24 12.07Z"/></svg>`,
|
|
2094
|
+
APPLE: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M17.05 12.54c-.03-2.74 2.24-4.06 2.34-4.12-1.28-1.86-3.26-2.12-3.96-2.15-1.69-.17-3.29 1-4.14 1-.85 0-2.17-.98-3.57-.95-1.83.03-3.53 1.07-4.47 2.71-1.91 3.31-.49 8.2 1.37 10.88.91 1.31 1.99 2.78 3.42 2.73 1.37-.06 1.89-.89 3.55-.89 1.66 0 2.13.89 3.58.86 1.48-.03 2.41-1.34 3.31-2.65 1.04-1.52 1.47-2.99 1.5-3.07-.03-.01-2.88-1.1-2.91-4.37ZM14.3 4.44c.75-.92 1.26-2.19 1.12-3.44-1.08.04-2.4.72-3.18 1.63-.7.81-1.31 2.11-1.15 3.35 1.21.09 2.45-.61 3.21-1.54Z"/></svg>`,
|
|
2095
|
+
MICROSOFT: `<svg viewBox="0 0 23 23" aria-hidden="true"><path fill="#f25022" d="M1 1h10v10H1z"/><path fill="#7fba00" d="M12 1h10v10H12z"/><path fill="#00a4ef" d="M1 12h10v10H1z"/><path fill="#ffb900" d="M12 12h10v10H12z"/></svg>`,
|
|
2096
|
+
GITHUB: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 0-.8.4-1.3.7-1.6-2.7-.3-5.5-1.3-5.5-5.9 0-1.3.5-2.4 1.2-3.2 0-.4-.5-1.6.2-3.2 0 0 1-.3 3.3 1.2a11.5 11.5 0 0 1 6 0C17.4 4.6 18.4 5 18.4 5c.7 1.6.2 2.8.1 3.2.8.8 1.2 1.9 1.2 3.2 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.2v3.3c0 .3.2.7.8.6A12 12 0 0 0 12 .3Z"/></svg>`,
|
|
2097
|
+
GITLAB: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#e24329" d="m12 22.5-3.7-11.3h7.4L12 22.5Z"/><path fill="#fc6d26" d="M12 22.5 8.3 11.2H3.1L12 22.5Z"/><path fill="#fca326" d="M3.1 11.2 2 14.7a.8.8 0 0 0 .3.8l9.7 7-8.9-11.3Z"/><path fill="#e24329" d="M3.1 11.2h5.2L6.1 4.3a.4.4 0 0 0-.8 0l-2.2 6.9Z"/><path fill="#fc6d26" d="M12 22.5l3.7-11.3h5.2L12 22.5Z"/><path fill="#fca326" d="m20.9 11.2 1.1 3.5a.8.8 0 0 1-.3.8l-9.7 7 8.9-11.3Z"/><path fill="#e24329" d="M20.9 11.2h-5.2l2.2-6.9a.4.4 0 0 1 .8 0l2.2 6.9Z"/></svg>`,
|
|
2098
|
+
LINKEDIN: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M20.45 20.45h-3.56v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.41v1.56h.05a3.74 3.74 0 0 1 3.37-1.85c3.6 0 4.27 2.37 4.27 5.46v6.28ZM5.34 7.43a2.07 2.07 0 1 1 0-4.13 2.07 2.07 0 0 1 0 4.13Zm1.78 13.02H3.55V9h3.57v11.45ZM22.22 0H1.77C.79 0 0 .77 0 1.72v20.56C0 23.23.79 24 1.77 24h20.45c.98 0 1.78-.77 1.78-1.72V1.72C24 .77 23.2 0 22.22 0Z"/></svg>`,
|
|
2099
|
+
// The four below are the Simple Icons marks (CC0), https://simpleicons.org.
|
|
2100
|
+
DISCORD: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/></svg>`,
|
|
2101
|
+
TWITTER: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"/></svg>`,
|
|
2102
|
+
TWITCH: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0L1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143l-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714Z"/></svg>`,
|
|
2103
|
+
ROBLOX: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M18.926 23.998 0 18.892 5.075.002 24 5.108ZM15.348 10.09l-5.282-1.453-1.414 5.273 5.282 1.453z"/></svg>`,
|
|
2104
|
+
SLACK: `<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="#e01e5a" d="M5.04 15.17a2.53 2.53 0 1 1-2.52-2.53h2.52v2.53Zm1.27 0a2.53 2.53 0 1 1 5.05 0v6.31a2.53 2.53 0 1 1-5.05 0v-6.31Z"/><path fill="#36c5f0" d="M8.83 5.04a2.53 2.53 0 1 1 2.53-2.52v2.52H8.83Zm0 1.28a2.53 2.53 0 1 1 0 5.05H2.52a2.53 2.53 0 1 1 0-5.05h6.31Z"/><path fill="#2eb67d" d="M18.96 8.83a2.53 2.53 0 1 1 2.52 2.53h-2.52V8.83Zm-1.27 0a2.53 2.53 0 1 1-5.05 0V2.52a2.53 2.53 0 1 1 5.05 0v6.31Z"/><path fill="#ecb22e" d="M15.17 18.96a2.53 2.53 0 1 1-2.53 2.52v-2.52h2.53Zm0-1.27a2.53 2.53 0 1 1 0-5.05h6.31a2.53 2.53 0 1 1 0 5.05h-6.31Z"/></svg>`
|
|
2105
|
+
};
|
|
2106
|
+
|
|
2107
|
+
// src/SocialButtons.tsx
|
|
2108
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2109
|
+
function SocialButtons({
|
|
2110
|
+
options,
|
|
2111
|
+
continueWith,
|
|
2112
|
+
disabled,
|
|
2113
|
+
onChoose
|
|
2114
|
+
}) {
|
|
2115
|
+
if (options.length === 0) {
|
|
2116
|
+
return null;
|
|
2117
|
+
}
|
|
2118
|
+
return /* @__PURE__ */ jsx8("div", { className: "b316-social", children: options.map((option) => {
|
|
2119
|
+
const icon = PROVIDER_ICON[option.provider];
|
|
2120
|
+
const light = /^#f{3}(f{3})?$/i.test(option.buttonColor);
|
|
2121
|
+
return /* @__PURE__ */ jsxs7(
|
|
2122
|
+
"button",
|
|
2123
|
+
{
|
|
2124
|
+
type: "button",
|
|
2125
|
+
className: "b316-social-button",
|
|
2126
|
+
"data-provider": option.slug,
|
|
2127
|
+
disabled,
|
|
2128
|
+
style: {
|
|
2129
|
+
background: option.buttonColor,
|
|
2130
|
+
color: option.buttonTextColor,
|
|
2131
|
+
borderColor: light ? "#747775" : option.buttonColor
|
|
2132
|
+
},
|
|
2133
|
+
onClick: () => onChoose(option),
|
|
2134
|
+
children: [
|
|
2135
|
+
icon ? /* @__PURE__ */ jsx8(
|
|
2136
|
+
"span",
|
|
2137
|
+
{
|
|
2138
|
+
className: "b316-social-icon",
|
|
2139
|
+
"aria-hidden": "true",
|
|
2140
|
+
dangerouslySetInnerHTML: { __html: icon }
|
|
2141
|
+
}
|
|
2142
|
+
) : null,
|
|
2143
|
+
/* @__PURE__ */ jsx8("span", { children: continueWith(option.name, option.provider) })
|
|
2144
|
+
]
|
|
2145
|
+
},
|
|
2146
|
+
option.slug
|
|
2147
|
+
);
|
|
2148
|
+
}) });
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2001
2151
|
// src/SignIn.tsx
|
|
2002
|
-
import { Fragment as Fragment4, jsx as
|
|
2152
|
+
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2153
|
+
var DEFAULT_SIGN_IN_LABELS = {
|
|
2154
|
+
email: "Email",
|
|
2155
|
+
password: "Password",
|
|
2156
|
+
mobileNumber: "Mobile number",
|
|
2157
|
+
code: "Code",
|
|
2158
|
+
tabPassword: "Password",
|
|
2159
|
+
tabMagicLink: "Magic link",
|
|
2160
|
+
tabPhone: "Text message",
|
|
2161
|
+
submit: "Sign in",
|
|
2162
|
+
working: "Working\u2026",
|
|
2163
|
+
emailMeALink: "Email me a link",
|
|
2164
|
+
textMeACode: "Text me a code",
|
|
2165
|
+
includeCountryCode: "Include the country code.",
|
|
2166
|
+
codeSent: (destination) => `We sent a code to ${destination}. It expires in ten minutes.`,
|
|
2167
|
+
useDifferentNumber: "Use a different number",
|
|
2168
|
+
or: "or",
|
|
2169
|
+
passkey: "Sign in with a passkey",
|
|
2170
|
+
continueWith: (name) => `Continue with ${name}`,
|
|
2171
|
+
sso: "Sign in with SSO",
|
|
2172
|
+
ssoEmail: "Work email",
|
|
2173
|
+
ssoContinue: "Continue",
|
|
2174
|
+
back: "Back",
|
|
2175
|
+
checkEmailTitle: "Check your email",
|
|
2176
|
+
checkEmail: (email) => `If an account exists for ${email}, a sign-in link is on its way. It expires shortly and can be used once.`,
|
|
2177
|
+
backToSignIn: "Back to sign in",
|
|
2178
|
+
wrongPassword: "That email and password did not match.",
|
|
2179
|
+
passkeyFailed: "That passkey did not work.",
|
|
2180
|
+
linkInvalid: "That sign-in link is no longer valid. Ask for a new one.",
|
|
2181
|
+
linkFailed: "We could not send that link. Try again.",
|
|
2182
|
+
wrongCode: "That code did not work. Check it, or ask for a new one.",
|
|
2183
|
+
codeFailed: "We could not send a code. Try again.",
|
|
2184
|
+
noMethods: "Signing in is not available right now."
|
|
2185
|
+
};
|
|
2003
2186
|
function SignIn({
|
|
2004
2187
|
onSignedIn,
|
|
2005
|
-
|
|
2188
|
+
password: passwordProp,
|
|
2189
|
+
passkeys: passkeysProp,
|
|
2190
|
+
magicLink: magicLinkProp,
|
|
2006
2191
|
magicLinkRedirectUrl,
|
|
2007
|
-
phone
|
|
2192
|
+
phone: phoneProp,
|
|
2193
|
+
social: socialProp,
|
|
2194
|
+
sso: ssoProp,
|
|
2195
|
+
socialRedirectUrl,
|
|
2196
|
+
socialState,
|
|
2197
|
+
labels: overrides,
|
|
2008
2198
|
secondFactorLabels,
|
|
2009
2199
|
className,
|
|
2010
2200
|
style
|
|
2011
2201
|
}) {
|
|
2202
|
+
const labels = { ...DEFAULT_SIGN_IN_LABELS, ...overrides };
|
|
2012
2203
|
const { client, setToken } = useBase316();
|
|
2013
|
-
const
|
|
2014
|
-
const [
|
|
2015
|
-
const [
|
|
2016
|
-
const [
|
|
2204
|
+
const loaded = useSignInMethods(client);
|
|
2205
|
+
const [currentPage, setCurrentPage] = useState8(null);
|
|
2206
|
+
const [email, setEmail] = useState8("");
|
|
2207
|
+
const [password, setPassword] = useState8("");
|
|
2208
|
+
const [code, setCode] = useState8("");
|
|
2209
|
+
const [pending, setPending] = useState8(null);
|
|
2017
2210
|
const pendingChallenge = pending?.challengeToken ?? null;
|
|
2018
|
-
const [phoneNumber, setPhoneNumber] =
|
|
2019
|
-
const [phoneChallenge, setPhoneChallenge] =
|
|
2211
|
+
const [phoneNumber, setPhoneNumber] = useState8("");
|
|
2212
|
+
const [phoneChallenge, setPhoneChallenge] = useState8(
|
|
2020
2213
|
null
|
|
2021
2214
|
);
|
|
2022
|
-
const [error, setError] =
|
|
2023
|
-
const [busy, setBusy] =
|
|
2024
|
-
const [passkeyReady, setPasskeyReady] =
|
|
2025
|
-
const [
|
|
2026
|
-
const [linkSent, setLinkSent] =
|
|
2215
|
+
const [error, setError] = useState8(null);
|
|
2216
|
+
const [busy, setBusy] = useState8(false);
|
|
2217
|
+
const [passkeyReady, setPasskeyReady] = useState8(false);
|
|
2218
|
+
const [chosenMode, setMode] = useState8(null);
|
|
2219
|
+
const [linkSent, setLinkSent] = useState8(false);
|
|
2027
2220
|
const abortRef = useRef2(null);
|
|
2221
|
+
useEffect8(() => {
|
|
2222
|
+
setCurrentPage(currentPageUrl());
|
|
2223
|
+
}, []);
|
|
2224
|
+
const offered = resolveMethods(
|
|
2225
|
+
loaded.methods,
|
|
2226
|
+
{
|
|
2227
|
+
password: passwordProp,
|
|
2228
|
+
passkeys: passkeysProp,
|
|
2229
|
+
magicLink: magicLinkProp,
|
|
2230
|
+
magicLinkRedirectUrl,
|
|
2231
|
+
phone: phoneProp,
|
|
2232
|
+
social: socialProp,
|
|
2233
|
+
sso: ssoProp,
|
|
2234
|
+
socialRedirectUrl
|
|
2235
|
+
},
|
|
2236
|
+
currentPage
|
|
2237
|
+
);
|
|
2238
|
+
const tabs = [
|
|
2239
|
+
...offered.password ? ["password"] : [],
|
|
2240
|
+
...offered.magicLink ? ["magic"] : [],
|
|
2241
|
+
...offered.phone ? ["phone"] : []
|
|
2242
|
+
];
|
|
2243
|
+
const mode = chosenMode && (chosenMode === "sso" ? offered.sso : tabs.includes(chosenMode)) ? chosenMode : tabs[0] ?? null;
|
|
2244
|
+
const passkeysWanted = loaded.status !== "loading" && offered.passkeys;
|
|
2028
2245
|
const signInWithPasskey = async (conditional, signal) => {
|
|
2029
2246
|
if (!conditional) {
|
|
2030
2247
|
setBusy(true);
|
|
@@ -2042,7 +2259,7 @@ function SignIn({
|
|
|
2042
2259
|
setError(cause.message);
|
|
2043
2260
|
} else if (!conditional) {
|
|
2044
2261
|
console.error("[base316] passkey sign-in failed", cause);
|
|
2045
|
-
setError(
|
|
2262
|
+
setError(labels.passkeyFailed);
|
|
2046
2263
|
}
|
|
2047
2264
|
} finally {
|
|
2048
2265
|
if (!conditional) {
|
|
@@ -2050,8 +2267,9 @@ function SignIn({
|
|
|
2050
2267
|
}
|
|
2051
2268
|
}
|
|
2052
2269
|
};
|
|
2053
|
-
|
|
2054
|
-
if (!
|
|
2270
|
+
useEffect8(() => {
|
|
2271
|
+
if (!passkeysWanted || !isPasskeySupported() || pendingChallenge) {
|
|
2272
|
+
setPasskeyReady(false);
|
|
2055
2273
|
return;
|
|
2056
2274
|
}
|
|
2057
2275
|
setPasskeyReady(true);
|
|
@@ -2065,8 +2283,8 @@ function SignIn({
|
|
|
2065
2283
|
return () => {
|
|
2066
2284
|
controller.abort();
|
|
2067
2285
|
};
|
|
2068
|
-
}, [
|
|
2069
|
-
|
|
2286
|
+
}, [passkeysWanted, pendingChallenge]);
|
|
2287
|
+
useEffect8(() => {
|
|
2070
2288
|
if (typeof window === "undefined") {
|
|
2071
2289
|
return;
|
|
2072
2290
|
}
|
|
@@ -2090,7 +2308,7 @@ function SignIn({
|
|
|
2090
2308
|
onSignedIn?.();
|
|
2091
2309
|
}).catch(() => {
|
|
2092
2310
|
if (!cancelled) {
|
|
2093
|
-
setError(
|
|
2311
|
+
setError(labels.linkInvalid);
|
|
2094
2312
|
}
|
|
2095
2313
|
});
|
|
2096
2314
|
return () => {
|
|
@@ -2098,23 +2316,44 @@ function SignIn({
|
|
|
2098
2316
|
};
|
|
2099
2317
|
}, []);
|
|
2100
2318
|
async function sendLink() {
|
|
2101
|
-
if (!
|
|
2319
|
+
if (!offered.magicLink) {
|
|
2102
2320
|
return;
|
|
2103
2321
|
}
|
|
2104
2322
|
setBusy(true);
|
|
2105
2323
|
setError(null);
|
|
2106
2324
|
try {
|
|
2107
|
-
await client.auth.magicLink.request({ email, redirectUrl:
|
|
2325
|
+
await client.auth.magicLink.request({ email, redirectUrl: offered.magicLink });
|
|
2108
2326
|
setLinkSent(true);
|
|
2109
2327
|
} catch (cause) {
|
|
2110
2328
|
console.error("[base316] magic link request failed", cause);
|
|
2111
|
-
setError(
|
|
2329
|
+
setError(
|
|
2330
|
+
cause instanceof Base316Error2 && cause.code === "INVALID_REQUEST" && cause.message ? cause.message : labels.linkFailed
|
|
2331
|
+
);
|
|
2112
2332
|
} finally {
|
|
2113
2333
|
setBusy(false);
|
|
2114
2334
|
}
|
|
2115
2335
|
}
|
|
2336
|
+
function leaveForSso() {
|
|
2337
|
+
if (!socialRedirectUrl) {
|
|
2338
|
+
return;
|
|
2339
|
+
}
|
|
2340
|
+
setBusy(true);
|
|
2341
|
+
beginRedirect(
|
|
2342
|
+
(state) => client.ssoSignInUrl({
|
|
2343
|
+
email,
|
|
2344
|
+
redirectUri: socialRedirectUrl,
|
|
2345
|
+
state,
|
|
2346
|
+
hostedUrl: offered.hostedUrl
|
|
2347
|
+
}),
|
|
2348
|
+
socialState
|
|
2349
|
+
);
|
|
2350
|
+
}
|
|
2116
2351
|
async function submit(event) {
|
|
2117
2352
|
event.preventDefault();
|
|
2353
|
+
if (mode === "sso") {
|
|
2354
|
+
leaveForSso();
|
|
2355
|
+
return;
|
|
2356
|
+
}
|
|
2118
2357
|
setBusy(true);
|
|
2119
2358
|
setError(null);
|
|
2120
2359
|
try {
|
|
@@ -2151,25 +2390,23 @@ function SignIn({
|
|
|
2151
2390
|
} catch (cause) {
|
|
2152
2391
|
console.error("[base316] sign-in failed", cause);
|
|
2153
2392
|
setError(
|
|
2154
|
-
mode === "phone" ? phoneChallenge ?
|
|
2393
|
+
mode === "phone" ? phoneChallenge ? labels.wrongCode : (
|
|
2155
2394
|
// Why a text could not be sent is worth saying — a number in the
|
|
2156
2395
|
// wrong format, or too many requests — and the server words it
|
|
2157
2396
|
// without saying anything about accounts.
|
|
2158
|
-
cause instanceof Error && cause.message ? cause.message :
|
|
2397
|
+
cause instanceof Error && cause.message ? cause.message : labels.codeFailed
|
|
2159
2398
|
) : (
|
|
2160
2399
|
// An unconfirmed address and a throttle are worth naming; the
|
|
2161
2400
|
// server words both without saying whether an account exists.
|
|
2162
|
-
cause instanceof Base316Error2 && (cause.reason === "EMAIL_NOT_VERIFIED" || cause.code === "RATE_LIMITED") ? cause.message :
|
|
2401
|
+
cause instanceof Base316Error2 && (cause.reason === "EMAIL_NOT_VERIFIED" || cause.code === "RATE_LIMITED") ? cause.message : labels.wrongPassword
|
|
2163
2402
|
)
|
|
2164
2403
|
);
|
|
2165
2404
|
} finally {
|
|
2166
2405
|
setBusy(false);
|
|
2167
2406
|
}
|
|
2168
2407
|
}
|
|
2169
|
-
const magicAvailable = Boolean(magicLinkRedirectUrl) && !pendingChallenge;
|
|
2170
|
-
const tabsShown = (magicAvailable || phone) && !pendingChallenge;
|
|
2171
2408
|
if (pending) {
|
|
2172
|
-
return /* @__PURE__ */
|
|
2409
|
+
return /* @__PURE__ */ jsx9("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx9(
|
|
2173
2410
|
SecondFactorStep,
|
|
2174
2411
|
{
|
|
2175
2412
|
pending,
|
|
@@ -2185,59 +2422,68 @@ function SignIn({
|
|
|
2185
2422
|
) });
|
|
2186
2423
|
}
|
|
2187
2424
|
if (linkSent) {
|
|
2188
|
-
return /* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
/* @__PURE__ */
|
|
2191
|
-
|
|
2192
|
-
email,
|
|
2193
|
-
", a sign-in link is on its way. It expires shortly and can be used once."
|
|
2194
|
-
] }),
|
|
2195
|
-
/* @__PURE__ */ jsx8(
|
|
2425
|
+
return /* @__PURE__ */ jsxs8("div", { className: cls("b316-card", className), style, children: [
|
|
2426
|
+
/* @__PURE__ */ jsx9("div", { style: { fontWeight: 600, marginBottom: 6 }, children: labels.checkEmailTitle }),
|
|
2427
|
+
/* @__PURE__ */ jsx9("div", { className: "b316-muted", children: labels.checkEmail(email) }),
|
|
2428
|
+
/* @__PURE__ */ jsx9(
|
|
2196
2429
|
"button",
|
|
2197
2430
|
{
|
|
2198
2431
|
type: "button",
|
|
2199
2432
|
className: "b316-button b316-button-secondary",
|
|
2200
2433
|
style: { marginTop: 16 },
|
|
2201
2434
|
onClick: () => setLinkSent(false),
|
|
2202
|
-
children:
|
|
2435
|
+
children: labels.backToSignIn
|
|
2203
2436
|
}
|
|
2204
2437
|
)
|
|
2205
2438
|
] });
|
|
2206
2439
|
}
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2440
|
+
const hasForm = mode !== null;
|
|
2441
|
+
const hasButtons = offered.social.length > 0 || passkeyReady || offered.sso && mode !== "sso";
|
|
2442
|
+
if (!hasForm && !hasButtons) {
|
|
2443
|
+
return /* @__PURE__ */ jsx9("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx9("div", { className: "b316-error", role: "alert", children: error ?? labels.noMethods }) });
|
|
2444
|
+
}
|
|
2445
|
+
const tabsShown = tabs.length > 1 && mode !== "sso";
|
|
2446
|
+
return /* @__PURE__ */ jsxs8("form", { onSubmit: submit, className: cls("b316-card", className), style, children: [
|
|
2447
|
+
error ? /* @__PURE__ */ jsx9("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
2448
|
+
offered.social.length > 0 && mode !== "sso" ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
2449
|
+
/* @__PURE__ */ jsx9(
|
|
2450
|
+
SocialButtons,
|
|
2212
2451
|
{
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2452
|
+
options: offered.social,
|
|
2453
|
+
continueWith: labels.continueWith,
|
|
2454
|
+
disabled: busy,
|
|
2455
|
+
onChoose: (option) => {
|
|
2456
|
+
if (!socialRedirectUrl) {
|
|
2457
|
+
return;
|
|
2458
|
+
}
|
|
2459
|
+
setBusy(true);
|
|
2460
|
+
beginRedirect(
|
|
2461
|
+
(state) => client.socialSignInUrl({
|
|
2462
|
+
provider: option.slug,
|
|
2463
|
+
redirectUri: socialRedirectUrl,
|
|
2464
|
+
state,
|
|
2465
|
+
hostedUrl: offered.hostedUrl
|
|
2466
|
+
}),
|
|
2467
|
+
socialState
|
|
2468
|
+
);
|
|
2469
|
+
}
|
|
2217
2470
|
}
|
|
2218
2471
|
),
|
|
2219
|
-
|
|
2220
|
-
"button",
|
|
2221
|
-
{
|
|
2222
|
-
type: "button",
|
|
2223
|
-
className: cls("b316-tab", mode === "magic" ? "b316-tab-on" : void 0),
|
|
2224
|
-
onClick: () => setMode("magic"),
|
|
2225
|
-
children: "Magic link"
|
|
2226
|
-
}
|
|
2227
|
-
) : null,
|
|
2228
|
-
phone ? /* @__PURE__ */ jsx8(
|
|
2229
|
-
"button",
|
|
2230
|
-
{
|
|
2231
|
-
type: "button",
|
|
2232
|
-
className: cls("b316-tab", mode === "phone" ? "b316-tab-on" : void 0),
|
|
2233
|
-
onClick: () => setMode("phone"),
|
|
2234
|
-
children: "Text message"
|
|
2235
|
-
}
|
|
2236
|
-
) : null
|
|
2472
|
+
hasForm ? /* @__PURE__ */ jsx9("div", { className: "b316-divider", children: labels.or }) : null
|
|
2237
2473
|
] }) : null,
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2474
|
+
tabsShown ? /* @__PURE__ */ jsx9("div", { className: "b316-tabs", children: tabs.map((tab) => /* @__PURE__ */ jsx9(
|
|
2475
|
+
"button",
|
|
2476
|
+
{
|
|
2477
|
+
type: "button",
|
|
2478
|
+
className: cls("b316-tab", mode === tab ? "b316-tab-on" : void 0),
|
|
2479
|
+
onClick: () => setMode(tab),
|
|
2480
|
+
children: tab === "password" ? labels.tabPassword : tab === "magic" ? labels.tabMagicLink : labels.tabPhone
|
|
2481
|
+
},
|
|
2482
|
+
tab
|
|
2483
|
+
)) }) : null,
|
|
2484
|
+
mode === "phone" ? phoneChallenge ? /* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2485
|
+
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-phone-code", children: labels.code }),
|
|
2486
|
+
/* @__PURE__ */ jsx9(
|
|
2241
2487
|
"input",
|
|
2242
2488
|
{
|
|
2243
2489
|
id: "b316-phone-code",
|
|
@@ -2249,12 +2495,10 @@ function SignIn({
|
|
|
2249
2495
|
required: true
|
|
2250
2496
|
}
|
|
2251
2497
|
),
|
|
2252
|
-
/* @__PURE__ */
|
|
2253
|
-
|
|
2254
|
-
phoneChallenge.hint,
|
|
2255
|
-
". It expires in ten minutes.",
|
|
2498
|
+
/* @__PURE__ */ jsxs8("span", { className: "b316-muted", children: [
|
|
2499
|
+
labels.codeSent(phoneChallenge.hint),
|
|
2256
2500
|
" ",
|
|
2257
|
-
/* @__PURE__ */
|
|
2501
|
+
/* @__PURE__ */ jsx9(
|
|
2258
2502
|
"button",
|
|
2259
2503
|
{
|
|
2260
2504
|
type: "button",
|
|
@@ -2263,13 +2507,13 @@ function SignIn({
|
|
|
2263
2507
|
setPhoneChallenge(null);
|
|
2264
2508
|
setCode("");
|
|
2265
2509
|
},
|
|
2266
|
-
children:
|
|
2510
|
+
children: labels.useDifferentNumber
|
|
2267
2511
|
}
|
|
2268
2512
|
)
|
|
2269
2513
|
] })
|
|
2270
|
-
] }) : /* @__PURE__ */
|
|
2271
|
-
/* @__PURE__ */
|
|
2272
|
-
/* @__PURE__ */
|
|
2514
|
+
] }) : /* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2515
|
+
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-phone", children: labels.mobileNumber }),
|
|
2516
|
+
/* @__PURE__ */ jsx9(
|
|
2273
2517
|
"input",
|
|
2274
2518
|
{
|
|
2275
2519
|
id: "b316-phone",
|
|
@@ -2282,11 +2526,11 @@ function SignIn({
|
|
|
2282
2526
|
required: true
|
|
2283
2527
|
}
|
|
2284
2528
|
),
|
|
2285
|
-
/* @__PURE__ */
|
|
2286
|
-
] }) : /* @__PURE__ */
|
|
2287
|
-
/* @__PURE__ */
|
|
2288
|
-
/* @__PURE__ */
|
|
2289
|
-
/* @__PURE__ */
|
|
2529
|
+
/* @__PURE__ */ jsx9("span", { className: "b316-muted", children: labels.includeCountryCode })
|
|
2530
|
+
] }) : mode !== null ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
2531
|
+
/* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2532
|
+
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-email", children: mode === "sso" ? labels.ssoEmail : labels.email }),
|
|
2533
|
+
/* @__PURE__ */ jsx9(
|
|
2290
2534
|
"input",
|
|
2291
2535
|
{
|
|
2292
2536
|
id: "b316-email",
|
|
@@ -2294,14 +2538,14 @@ function SignIn({
|
|
|
2294
2538
|
type: "email",
|
|
2295
2539
|
value: email,
|
|
2296
2540
|
onChange: (event) => setEmail(event.target.value),
|
|
2297
|
-
autoComplete: passkeyReady ? "email webauthn" : "email",
|
|
2541
|
+
autoComplete: passkeyReady && mode !== "sso" ? "email webauthn" : "email",
|
|
2298
2542
|
required: true
|
|
2299
2543
|
}
|
|
2300
2544
|
)
|
|
2301
2545
|
] }),
|
|
2302
|
-
mode === "password" ? /* @__PURE__ */
|
|
2303
|
-
/* @__PURE__ */
|
|
2304
|
-
/* @__PURE__ */
|
|
2546
|
+
mode === "password" ? /* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2547
|
+
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-password", children: labels.password }),
|
|
2548
|
+
/* @__PURE__ */ jsx9(
|
|
2305
2549
|
"input",
|
|
2306
2550
|
{
|
|
2307
2551
|
id: "b316-password",
|
|
@@ -2314,34 +2558,165 @@ function SignIn({
|
|
|
2314
2558
|
}
|
|
2315
2559
|
)
|
|
2316
2560
|
] }) : null
|
|
2317
|
-
] }),
|
|
2318
|
-
/* @__PURE__ */
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2561
|
+
] }) : null,
|
|
2562
|
+
mode !== null ? /* @__PURE__ */ jsx9("button", { className: "b316-button", type: "submit", disabled: busy, children: busy ? labels.working : mode === "magic" ? labels.emailMeALink : mode === "phone" && !phoneChallenge ? labels.textMeACode : mode === "sso" ? labels.ssoContinue : labels.submit }) : null,
|
|
2563
|
+
mode === "sso" ? /* @__PURE__ */ jsx9(
|
|
2564
|
+
"button",
|
|
2565
|
+
{
|
|
2566
|
+
type: "button",
|
|
2567
|
+
className: "b316-button b316-button-secondary",
|
|
2568
|
+
style: { marginTop: 10, width: "100%" },
|
|
2569
|
+
disabled: busy,
|
|
2570
|
+
onClick: () => setMode(null),
|
|
2571
|
+
children: labels.back
|
|
2572
|
+
}
|
|
2573
|
+
) : null,
|
|
2574
|
+
(passkeyReady || offered.sso) && mode !== "sso" ? /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
2575
|
+
hasForm ? /* @__PURE__ */ jsx9("div", { className: "b316-divider", children: labels.or }) : null,
|
|
2576
|
+
passkeyReady ? /* @__PURE__ */ jsx9(
|
|
2322
2577
|
"button",
|
|
2323
2578
|
{
|
|
2324
2579
|
type: "button",
|
|
2325
2580
|
className: "b316-button b316-button-secondary",
|
|
2581
|
+
style: { width: "100%" },
|
|
2326
2582
|
disabled: busy,
|
|
2327
2583
|
onClick: () => {
|
|
2328
2584
|
abortRef.current?.abort();
|
|
2329
2585
|
void signInWithPasskey(false);
|
|
2330
2586
|
},
|
|
2331
|
-
children:
|
|
2587
|
+
children: labels.passkey
|
|
2332
2588
|
}
|
|
2333
|
-
)
|
|
2589
|
+
) : null,
|
|
2590
|
+
offered.sso ? /* @__PURE__ */ jsx9(
|
|
2591
|
+
"button",
|
|
2592
|
+
{
|
|
2593
|
+
type: "button",
|
|
2594
|
+
className: "b316-button b316-button-secondary",
|
|
2595
|
+
style: { width: "100%", marginTop: passkeyReady ? 8 : 0 },
|
|
2596
|
+
disabled: busy,
|
|
2597
|
+
onClick: () => {
|
|
2598
|
+
abortRef.current?.abort();
|
|
2599
|
+
setError(null);
|
|
2600
|
+
setMode("sso");
|
|
2601
|
+
},
|
|
2602
|
+
children: labels.sso
|
|
2603
|
+
}
|
|
2604
|
+
) : null
|
|
2334
2605
|
] }) : null
|
|
2335
2606
|
] });
|
|
2336
2607
|
}
|
|
2337
2608
|
|
|
2609
|
+
// src/SocialSignIn.tsx
|
|
2610
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2611
|
+
function SocialSignIn({
|
|
2612
|
+
socialRedirectUrl,
|
|
2613
|
+
socialState,
|
|
2614
|
+
social,
|
|
2615
|
+
intent = "sign-in",
|
|
2616
|
+
divider = false,
|
|
2617
|
+
labels
|
|
2618
|
+
}) {
|
|
2619
|
+
const { client } = useBase316();
|
|
2620
|
+
const loaded = useSignInMethods(client);
|
|
2621
|
+
if (!loaded.methods || intent === "sign-up" && !loaded.methods.signUp) {
|
|
2622
|
+
return null;
|
|
2623
|
+
}
|
|
2624
|
+
const offered = resolveMethods(loaded.methods, { social, socialRedirectUrl }, null);
|
|
2625
|
+
if (!socialRedirectUrl || offered.social.length === 0) {
|
|
2626
|
+
return null;
|
|
2627
|
+
}
|
|
2628
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2629
|
+
/* @__PURE__ */ jsx10(
|
|
2630
|
+
SocialButtons,
|
|
2631
|
+
{
|
|
2632
|
+
options: offered.social,
|
|
2633
|
+
continueWith: labels?.continueWith ?? ((name) => `Continue with ${name}`),
|
|
2634
|
+
onChoose: (option) => beginRedirect(
|
|
2635
|
+
(state) => client.socialSignInUrl({
|
|
2636
|
+
provider: option.slug,
|
|
2637
|
+
redirectUri: socialRedirectUrl,
|
|
2638
|
+
state,
|
|
2639
|
+
hostedUrl: offered.hostedUrl
|
|
2640
|
+
}),
|
|
2641
|
+
socialState
|
|
2642
|
+
)
|
|
2643
|
+
}
|
|
2644
|
+
),
|
|
2645
|
+
divider ? /* @__PURE__ */ jsx10("div", { className: "b316-divider", children: labels?.or ?? "or" }) : null
|
|
2646
|
+
] });
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2338
2649
|
// src/SignUp.tsx
|
|
2339
2650
|
import {
|
|
2340
2651
|
Base316Error as Base316Error3,
|
|
2341
2652
|
needsSecondFactor as needsSecondFactor2
|
|
2342
2653
|
} from "@base316/sdk";
|
|
2343
|
-
import { useEffect as
|
|
2344
|
-
|
|
2654
|
+
import { useEffect as useEffect10, useState as useState9 } from "react";
|
|
2655
|
+
|
|
2656
|
+
// src/CaptchaWidget.tsx
|
|
2657
|
+
import { useEffect as useEffect9, useRef as useRef3 } from "react";
|
|
2658
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
2659
|
+
var SCRIPT_URL = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
|
|
2660
|
+
var loading = null;
|
|
2661
|
+
function loadTurnstile() {
|
|
2662
|
+
if (window.turnstile) {
|
|
2663
|
+
return Promise.resolve(window.turnstile);
|
|
2664
|
+
}
|
|
2665
|
+
loading ??= new Promise((resolve, reject) => {
|
|
2666
|
+
const script = document.createElement("script");
|
|
2667
|
+
script.src = SCRIPT_URL;
|
|
2668
|
+
script.async = true;
|
|
2669
|
+
script.onload = () => {
|
|
2670
|
+
if (window.turnstile) {
|
|
2671
|
+
resolve(window.turnstile);
|
|
2672
|
+
} else {
|
|
2673
|
+
reject(new Error("Turnstile did not start"));
|
|
2674
|
+
}
|
|
2675
|
+
};
|
|
2676
|
+
script.onerror = () => {
|
|
2677
|
+
loading = null;
|
|
2678
|
+
reject(new Error("Turnstile could not be loaded"));
|
|
2679
|
+
};
|
|
2680
|
+
document.head.appendChild(script);
|
|
2681
|
+
});
|
|
2682
|
+
return loading;
|
|
2683
|
+
}
|
|
2684
|
+
function CaptchaWidget({
|
|
2685
|
+
siteKey,
|
|
2686
|
+
onToken
|
|
2687
|
+
}) {
|
|
2688
|
+
const container = useRef3(null);
|
|
2689
|
+
const latest = useRef3(onToken);
|
|
2690
|
+
useEffect9(() => {
|
|
2691
|
+
latest.current = onToken;
|
|
2692
|
+
}, [onToken]);
|
|
2693
|
+
useEffect9(() => {
|
|
2694
|
+
let widgetId = null;
|
|
2695
|
+
let cancelled = false;
|
|
2696
|
+
loadTurnstile().then((turnstile) => {
|
|
2697
|
+
if (cancelled || !container.current) {
|
|
2698
|
+
return;
|
|
2699
|
+
}
|
|
2700
|
+
widgetId = turnstile.render(container.current, {
|
|
2701
|
+
sitekey: siteKey,
|
|
2702
|
+
size: "flexible",
|
|
2703
|
+
callback: (token) => latest.current(token),
|
|
2704
|
+
"expired-callback": () => latest.current(null),
|
|
2705
|
+
"error-callback": () => latest.current(null)
|
|
2706
|
+
});
|
|
2707
|
+
}).catch((cause) => console.error("[base316] CAPTCHA unavailable", cause));
|
|
2708
|
+
return () => {
|
|
2709
|
+
cancelled = true;
|
|
2710
|
+
if (widgetId) {
|
|
2711
|
+
window.turnstile?.remove(widgetId);
|
|
2712
|
+
}
|
|
2713
|
+
};
|
|
2714
|
+
}, [siteKey]);
|
|
2715
|
+
return /* @__PURE__ */ jsx11("div", { ref: container, className: "b316-captcha" });
|
|
2716
|
+
}
|
|
2717
|
+
|
|
2718
|
+
// src/SignUp.tsx
|
|
2719
|
+
import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2345
2720
|
var DEFAULT_SIGN_UP_LABELS = {
|
|
2346
2721
|
name: "Name",
|
|
2347
2722
|
email: "Email",
|
|
@@ -2358,7 +2733,11 @@ var DEFAULT_SIGN_UP_LABELS = {
|
|
|
2358
2733
|
confirmEmail: (email) => `Your account is ready. We sent a confirmation link to ${email} \u2014 open it, then sign in.`,
|
|
2359
2734
|
createdSignInFailed: (reason) => `Your account was created, but we could not sign you in: ${reason}`,
|
|
2360
2735
|
genericError: "We could not create that account. Try again.",
|
|
2361
|
-
joining: (organizationName, roleName) => `You are joining ${organizationName} as ${roleName}. Sign up with the address the invitation was sent to
|
|
2736
|
+
joining: (organizationName, roleName) => `You are joining ${organizationName} as ${roleName}. Sign up with the address the invitation was sent to.`,
|
|
2737
|
+
continueWith: (name) => `Continue with ${name}`,
|
|
2738
|
+
or: "or",
|
|
2739
|
+
closed: "This application is not accepting new accounts right now.",
|
|
2740
|
+
noMethods: "Creating an account is not available here right now."
|
|
2362
2741
|
};
|
|
2363
2742
|
function describeRules(policy, labels) {
|
|
2364
2743
|
const extras = [
|
|
@@ -2377,30 +2756,37 @@ function SignUp({
|
|
|
2377
2756
|
onJoined,
|
|
2378
2757
|
labels: overrides,
|
|
2379
2758
|
secondFactorLabels,
|
|
2759
|
+
social,
|
|
2760
|
+
socialRedirectUrl,
|
|
2761
|
+
socialState,
|
|
2380
2762
|
className,
|
|
2381
2763
|
style
|
|
2382
2764
|
}) {
|
|
2383
2765
|
const labels = { ...DEFAULT_SIGN_UP_LABELS, ...overrides };
|
|
2384
2766
|
const { client, setToken } = useBase316();
|
|
2385
|
-
const
|
|
2386
|
-
const
|
|
2387
|
-
const [
|
|
2388
|
-
const [
|
|
2389
|
-
const [
|
|
2390
|
-
const [
|
|
2391
|
-
const [
|
|
2392
|
-
const [
|
|
2393
|
-
const [
|
|
2394
|
-
const [
|
|
2767
|
+
const methodsState = useSignInMethods(client);
|
|
2768
|
+
const offered = resolveMethods(methodsState.methods, { social, socialRedirectUrl }, null);
|
|
2769
|
+
const [name, setName] = useState9("");
|
|
2770
|
+
const [email, setEmail] = useState9("");
|
|
2771
|
+
const [password, setPassword] = useState9("");
|
|
2772
|
+
const [error, setError] = useState9(null);
|
|
2773
|
+
const [busy, setBusy] = useState9(false);
|
|
2774
|
+
const [policy, setPolicy] = useState9(null);
|
|
2775
|
+
const [pending, setPending] = useState9(null);
|
|
2776
|
+
const [confirmEmail, setConfirmEmail] = useState9(false);
|
|
2777
|
+
const [urlInvitation, setUrlInvitation] = useState9(null);
|
|
2778
|
+
const [loaded, setLoaded] = useState9(null);
|
|
2779
|
+
const [captchaToken, setCaptchaToken] = useState9(null);
|
|
2780
|
+
const [captchaRound, setCaptchaRound] = useState9(0);
|
|
2395
2781
|
const invitation = suppliedInvitation === void 0 ? urlInvitation : suppliedInvitation;
|
|
2396
2782
|
const preview = loaded && loaded.token === invitation ? loaded.preview : null;
|
|
2397
|
-
|
|
2783
|
+
useEffect10(() => {
|
|
2398
2784
|
if (suppliedInvitation !== void 0 || typeof window === "undefined") {
|
|
2399
2785
|
return;
|
|
2400
2786
|
}
|
|
2401
2787
|
setUrlInvitation(new URL(window.location.href).searchParams.get("invitation"));
|
|
2402
2788
|
}, [suppliedInvitation]);
|
|
2403
|
-
|
|
2789
|
+
useEffect10(() => {
|
|
2404
2790
|
if (!invitation) {
|
|
2405
2791
|
return;
|
|
2406
2792
|
}
|
|
@@ -2415,7 +2801,7 @@ function SignUp({
|
|
|
2415
2801
|
cancelled = true;
|
|
2416
2802
|
};
|
|
2417
2803
|
}, [client, invitation]);
|
|
2418
|
-
|
|
2804
|
+
useEffect10(() => {
|
|
2419
2805
|
let cancelled = false;
|
|
2420
2806
|
client.auth.passwordPolicy().then((loaded2) => {
|
|
2421
2807
|
if (!cancelled) {
|
|
@@ -2435,7 +2821,8 @@ function SignUp({
|
|
|
2435
2821
|
email,
|
|
2436
2822
|
password,
|
|
2437
2823
|
name: name || void 0,
|
|
2438
|
-
invitationToken: invitation ?? void 0
|
|
2824
|
+
invitationToken: invitation ?? void 0,
|
|
2825
|
+
captchaToken: captchaToken ?? void 0
|
|
2439
2826
|
});
|
|
2440
2827
|
if (created.invitationAccepted && created.organizationId) {
|
|
2441
2828
|
onJoined?.(created.organizationId);
|
|
@@ -2445,6 +2832,8 @@ function SignUp({
|
|
|
2445
2832
|
setError(
|
|
2446
2833
|
cause instanceof Base316Error3 && (cause.code === "INVALID_REQUEST" || cause.code === "RATE_LIMITED" || cause.code === "CONFLICT") && cause.message ? cause.message : labels.genericError
|
|
2447
2834
|
);
|
|
2835
|
+
setCaptchaToken(null);
|
|
2836
|
+
setCaptchaRound((round) => round + 1);
|
|
2448
2837
|
setBusy(false);
|
|
2449
2838
|
return;
|
|
2450
2839
|
}
|
|
@@ -2473,86 +2862,129 @@ function SignUp({
|
|
|
2473
2862
|
}
|
|
2474
2863
|
}
|
|
2475
2864
|
if (pending) {
|
|
2476
|
-
return /* @__PURE__ */
|
|
2865
|
+
return /* @__PURE__ */ jsx12("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx12(SecondFactorStep, { pending, labels: secondFactorLabels, onSignedIn: onSignedUp }) });
|
|
2477
2866
|
}
|
|
2478
2867
|
if (confirmEmail) {
|
|
2479
|
-
return /* @__PURE__ */
|
|
2480
|
-
/* @__PURE__ */
|
|
2481
|
-
/* @__PURE__ */
|
|
2868
|
+
return /* @__PURE__ */ jsxs10("div", { className: cls("b316-card", className), style, children: [
|
|
2869
|
+
/* @__PURE__ */ jsx12("h3", { className: "b316-form-title", children: labels.confirmEmailTitle }),
|
|
2870
|
+
/* @__PURE__ */ jsx12("output", { className: "b316-muted", children: labels.confirmEmail(email) })
|
|
2482
2871
|
] });
|
|
2483
2872
|
}
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
onChange: (event) => setName(event.target.value),
|
|
2496
|
-
autoComplete: "name"
|
|
2497
|
-
}
|
|
2498
|
-
)
|
|
2499
|
-
] }),
|
|
2500
|
-
/* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2501
|
-
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-signup-email", children: labels.email }),
|
|
2502
|
-
/* @__PURE__ */ jsx9(
|
|
2503
|
-
"input",
|
|
2504
|
-
{
|
|
2505
|
-
id: "b316-signup-email",
|
|
2506
|
-
className: "b316-input",
|
|
2507
|
-
type: "email",
|
|
2508
|
-
value: email,
|
|
2509
|
-
onChange: (event) => setEmail(event.target.value),
|
|
2510
|
-
autoComplete: "email",
|
|
2511
|
-
required: true
|
|
2512
|
-
}
|
|
2513
|
-
)
|
|
2514
|
-
] }),
|
|
2515
|
-
/* @__PURE__ */ jsxs8("div", { className: "b316-field", children: [
|
|
2516
|
-
/* @__PURE__ */ jsx9("label", { className: "b316-label", htmlFor: "b316-signup-password", children: labels.password }),
|
|
2517
|
-
/* @__PURE__ */ jsx9(
|
|
2518
|
-
"input",
|
|
2873
|
+
if (!offered.signUp && !invitation) {
|
|
2874
|
+
return /* @__PURE__ */ jsx12("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx12("output", { className: "b316-muted", children: labels.closed }) });
|
|
2875
|
+
}
|
|
2876
|
+
const socialOptions = invitation ? [] : offered.social;
|
|
2877
|
+
if (!offered.password && socialOptions.length === 0) {
|
|
2878
|
+
return /* @__PURE__ */ jsx12("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx12("output", { className: "b316-muted", children: labels.noMethods }) });
|
|
2879
|
+
}
|
|
2880
|
+
return /* @__PURE__ */ jsxs10("form", { onSubmit: submit, className: cls("b316-card", className), style, children: [
|
|
2881
|
+
socialOptions.length > 0 ? /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
2882
|
+
/* @__PURE__ */ jsx12(
|
|
2883
|
+
SocialButtons,
|
|
2519
2884
|
{
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2885
|
+
options: socialOptions,
|
|
2886
|
+
continueWith: labels.continueWith,
|
|
2887
|
+
disabled: busy,
|
|
2888
|
+
onChoose: (option) => {
|
|
2889
|
+
if (!socialRedirectUrl) {
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2892
|
+
setBusy(true);
|
|
2893
|
+
beginRedirect(
|
|
2894
|
+
(state) => client.socialSignInUrl({
|
|
2895
|
+
provider: option.slug,
|
|
2896
|
+
redirectUri: socialRedirectUrl,
|
|
2897
|
+
state,
|
|
2898
|
+
hostedUrl: offered.hostedUrl
|
|
2899
|
+
}),
|
|
2900
|
+
socialState
|
|
2901
|
+
);
|
|
2902
|
+
}
|
|
2530
2903
|
}
|
|
2531
2904
|
),
|
|
2532
|
-
|
|
2533
|
-
] }),
|
|
2534
|
-
/* @__PURE__ */
|
|
2905
|
+
offered.password ? /* @__PURE__ */ jsx12("div", { className: "b316-divider", children: labels.or }) : null
|
|
2906
|
+
] }) : null,
|
|
2907
|
+
preview ? /* @__PURE__ */ jsx12("p", { className: "b316-muted", children: labels.joining(preview.organizationName, preview.roleName) }) : null,
|
|
2908
|
+
error ? /* @__PURE__ */ jsx12("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
2909
|
+
offered.password || socialOptions.length === 0 ? /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
2910
|
+
/* @__PURE__ */ jsxs10("div", { className: "b316-field", children: [
|
|
2911
|
+
/* @__PURE__ */ jsx12("label", { className: "b316-label", htmlFor: "b316-name", children: labels.name }),
|
|
2912
|
+
/* @__PURE__ */ jsx12(
|
|
2913
|
+
"input",
|
|
2914
|
+
{
|
|
2915
|
+
id: "b316-name",
|
|
2916
|
+
className: "b316-input",
|
|
2917
|
+
value: name,
|
|
2918
|
+
onChange: (event) => setName(event.target.value),
|
|
2919
|
+
autoComplete: "name"
|
|
2920
|
+
}
|
|
2921
|
+
)
|
|
2922
|
+
] }),
|
|
2923
|
+
/* @__PURE__ */ jsxs10("div", { className: "b316-field", children: [
|
|
2924
|
+
/* @__PURE__ */ jsx12("label", { className: "b316-label", htmlFor: "b316-signup-email", children: labels.email }),
|
|
2925
|
+
/* @__PURE__ */ jsx12(
|
|
2926
|
+
"input",
|
|
2927
|
+
{
|
|
2928
|
+
id: "b316-signup-email",
|
|
2929
|
+
className: "b316-input",
|
|
2930
|
+
type: "email",
|
|
2931
|
+
value: email,
|
|
2932
|
+
onChange: (event) => setEmail(event.target.value),
|
|
2933
|
+
autoComplete: "email",
|
|
2934
|
+
required: true
|
|
2935
|
+
}
|
|
2936
|
+
)
|
|
2937
|
+
] }),
|
|
2938
|
+
/* @__PURE__ */ jsxs10("div", { className: "b316-field", children: [
|
|
2939
|
+
/* @__PURE__ */ jsx12("label", { className: "b316-label", htmlFor: "b316-signup-password", children: labels.password }),
|
|
2940
|
+
/* @__PURE__ */ jsx12(
|
|
2941
|
+
"input",
|
|
2942
|
+
{
|
|
2943
|
+
id: "b316-signup-password",
|
|
2944
|
+
className: "b316-input",
|
|
2945
|
+
type: "password",
|
|
2946
|
+
value: password,
|
|
2947
|
+
onChange: (event) => setPassword(event.target.value),
|
|
2948
|
+
autoComplete: "new-password",
|
|
2949
|
+
minLength: policy?.minLength,
|
|
2950
|
+
maxLength: policy?.maxLength,
|
|
2951
|
+
"aria-describedby": policy ? "b316-signup-password-rules" : void 0,
|
|
2952
|
+
required: true
|
|
2953
|
+
}
|
|
2954
|
+
),
|
|
2955
|
+
policy ? /* @__PURE__ */ jsx12("span", { id: "b316-signup-password-rules", className: "b316-muted", children: describeRules(policy, labels) }) : null
|
|
2956
|
+
] }),
|
|
2957
|
+
methodsState.methods?.captcha && !invitation ? /* @__PURE__ */ jsx12(
|
|
2958
|
+
CaptchaWidget,
|
|
2959
|
+
{
|
|
2960
|
+
siteKey: methodsState.methods.captcha.siteKey,
|
|
2961
|
+
onToken: setCaptchaToken
|
|
2962
|
+
},
|
|
2963
|
+
captchaRound
|
|
2964
|
+
) : null,
|
|
2965
|
+
/* @__PURE__ */ jsx12("button", { className: "b316-button", type: "submit", disabled: busy, children: busy ? labels.working : labels.submit })
|
|
2966
|
+
] }) : null
|
|
2535
2967
|
] });
|
|
2536
2968
|
}
|
|
2537
2969
|
|
|
2538
2970
|
// src/UserProfile.tsx
|
|
2539
|
-
import { jsx as
|
|
2971
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2540
2972
|
function UserProfile({ className, style }) {
|
|
2541
|
-
const { session, loading, signOut } = useBase316();
|
|
2542
|
-
if (
|
|
2543
|
-
return /* @__PURE__ */
|
|
2973
|
+
const { session, loading: loading2, signOut } = useBase316();
|
|
2974
|
+
if (loading2) {
|
|
2975
|
+
return /* @__PURE__ */ jsx13("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
2544
2976
|
}
|
|
2545
2977
|
if (!session) {
|
|
2546
|
-
return /* @__PURE__ */
|
|
2978
|
+
return /* @__PURE__ */ jsx13("div", { className: cls("b316-card", className), style, children: "Not signed in." });
|
|
2547
2979
|
}
|
|
2548
2980
|
const user = session.user ?? {};
|
|
2549
|
-
return /* @__PURE__ */
|
|
2550
|
-
/* @__PURE__ */
|
|
2551
|
-
/* @__PURE__ */
|
|
2552
|
-
user.name && user.email ? /* @__PURE__ */
|
|
2553
|
-
user.emailVerified === false ? /* @__PURE__ */
|
|
2981
|
+
return /* @__PURE__ */ jsx13("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsxs11("div", { className: "b316-row", children: [
|
|
2982
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
2983
|
+
/* @__PURE__ */ jsx13("div", { style: { fontWeight: 600 }, children: user.name || user.email || "Signed in" }),
|
|
2984
|
+
user.name && user.email ? /* @__PURE__ */ jsx13("div", { className: "b316-muted", children: user.email }) : null,
|
|
2985
|
+
user.emailVerified === false ? /* @__PURE__ */ jsx13("div", { className: "b316-muted", children: "Email not verified" }) : null
|
|
2554
2986
|
] }),
|
|
2555
|
-
/* @__PURE__ */
|
|
2987
|
+
/* @__PURE__ */ jsx13(
|
|
2556
2988
|
"button",
|
|
2557
2989
|
{
|
|
2558
2990
|
type: "button",
|
|
@@ -2566,11 +2998,11 @@ function UserProfile({ className, style }) {
|
|
|
2566
2998
|
|
|
2567
2999
|
// src/PasskeyManager.tsx
|
|
2568
3000
|
import { isPasskeySupported as isPasskeySupported2 } from "@base316/sdk";
|
|
2569
|
-
import { useCallback as useCallback5, useEffect as
|
|
3001
|
+
import { useCallback as useCallback5, useEffect as useEffect12, useState as useState11 } from "react";
|
|
2570
3002
|
|
|
2571
3003
|
// src/confirm.tsx
|
|
2572
|
-
import { useEffect as
|
|
2573
|
-
import { jsx as
|
|
3004
|
+
import { useEffect as useEffect11, useRef as useRef4, useState as useState10 } from "react";
|
|
3005
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2574
3006
|
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
2575
3007
|
function ConfirmButton({
|
|
2576
3008
|
children,
|
|
@@ -2580,9 +3012,9 @@ function ConfirmButton({
|
|
|
2580
3012
|
disabled,
|
|
2581
3013
|
timeoutMs = DEFAULT_TIMEOUT_MS
|
|
2582
3014
|
}) {
|
|
2583
|
-
const [armed, setArmed] =
|
|
2584
|
-
const confirmRef =
|
|
2585
|
-
|
|
3015
|
+
const [armed, setArmed] = useState10(false);
|
|
3016
|
+
const confirmRef = useRef4(null);
|
|
3017
|
+
useEffect11(() => {
|
|
2586
3018
|
if (!armed) {
|
|
2587
3019
|
return;
|
|
2588
3020
|
}
|
|
@@ -2591,7 +3023,7 @@ function ConfirmButton({
|
|
|
2591
3023
|
return () => clearTimeout(timer);
|
|
2592
3024
|
}, [armed, timeoutMs]);
|
|
2593
3025
|
if (!armed) {
|
|
2594
|
-
return /* @__PURE__ */
|
|
3026
|
+
return /* @__PURE__ */ jsx14(
|
|
2595
3027
|
"button",
|
|
2596
3028
|
{
|
|
2597
3029
|
type: "button",
|
|
@@ -2605,8 +3037,8 @@ function ConfirmButton({
|
|
|
2605
3037
|
return (
|
|
2606
3038
|
// No `role="group"`: both buttons already say what they do, and the
|
|
2607
3039
|
// grouping would only repeat the question a screen reader has just read.
|
|
2608
|
-
/* @__PURE__ */
|
|
2609
|
-
/* @__PURE__ */
|
|
3040
|
+
/* @__PURE__ */ jsxs12("span", { className: "b316-confirm", children: [
|
|
3041
|
+
/* @__PURE__ */ jsx14(
|
|
2610
3042
|
"button",
|
|
2611
3043
|
{
|
|
2612
3044
|
ref: confirmRef,
|
|
@@ -2620,7 +3052,7 @@ function ConfirmButton({
|
|
|
2620
3052
|
children: confirmLabel
|
|
2621
3053
|
}
|
|
2622
3054
|
),
|
|
2623
|
-
/* @__PURE__ */
|
|
3055
|
+
/* @__PURE__ */ jsx14(
|
|
2624
3056
|
"button",
|
|
2625
3057
|
{
|
|
2626
3058
|
type: "button",
|
|
@@ -2634,18 +3066,18 @@ function ConfirmButton({
|
|
|
2634
3066
|
}
|
|
2635
3067
|
|
|
2636
3068
|
// src/PasskeyManager.tsx
|
|
2637
|
-
import { jsx as
|
|
3069
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2638
3070
|
function PasskeyManager({
|
|
2639
3071
|
className,
|
|
2640
3072
|
style,
|
|
2641
3073
|
title = "Passkeys"
|
|
2642
3074
|
}) {
|
|
2643
3075
|
const { client, token, session } = useBase316();
|
|
2644
|
-
const [passkeys, setPasskeys] =
|
|
2645
|
-
const [busy, setBusy] =
|
|
2646
|
-
const [error, setError] =
|
|
2647
|
-
const [name, setName] =
|
|
2648
|
-
const [supported, setSupported] =
|
|
3076
|
+
const [passkeys, setPasskeys] = useState11(null);
|
|
3077
|
+
const [busy, setBusy] = useState11(false);
|
|
3078
|
+
const [error, setError] = useState11(null);
|
|
3079
|
+
const [name, setName] = useState11("");
|
|
3080
|
+
const [supported, setSupported] = useState11(false);
|
|
2649
3081
|
const load = useCallback5(async () => {
|
|
2650
3082
|
if (!token) {
|
|
2651
3083
|
return;
|
|
@@ -2659,7 +3091,7 @@ function PasskeyManager({
|
|
|
2659
3091
|
setPasskeys(null);
|
|
2660
3092
|
}
|
|
2661
3093
|
}, [client, token]);
|
|
2662
|
-
|
|
3094
|
+
useEffect12(() => {
|
|
2663
3095
|
if (!isPasskeySupported2()) {
|
|
2664
3096
|
return;
|
|
2665
3097
|
}
|
|
@@ -2695,18 +3127,18 @@ function PasskeyManager({
|
|
|
2695
3127
|
setError(caught instanceof Error ? caught.message : "That did not work.");
|
|
2696
3128
|
}
|
|
2697
3129
|
};
|
|
2698
|
-
return /* @__PURE__ */
|
|
2699
|
-
/* @__PURE__ */
|
|
2700
|
-
/* @__PURE__ */
|
|
2701
|
-
passkeys === null ? /* @__PURE__ */
|
|
2702
|
-
/* @__PURE__ */
|
|
2703
|
-
/* @__PURE__ */
|
|
2704
|
-
/* @__PURE__ */
|
|
3130
|
+
return /* @__PURE__ */ jsxs13("div", { className: cls("b316-card", className), style, children: [
|
|
3131
|
+
/* @__PURE__ */ jsx15("div", { style: { fontWeight: 600, marginBottom: 4 }, children: title }),
|
|
3132
|
+
/* @__PURE__ */ jsx15("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." }),
|
|
3133
|
+
passkeys === null ? /* @__PURE__ */ jsx15("div", { className: "b316-muted", children: "Loading\u2026" }) : passkeys.length === 0 ? /* @__PURE__ */ jsx15("div", { className: "b316-muted", children: "No passkeys yet." }) : /* @__PURE__ */ jsx15("ul", { style: { listStyle: "none", margin: 0, padding: 0 }, children: passkeys.map((passkey) => /* @__PURE__ */ jsxs13("li", { className: "b316-row", style: { padding: "8px 0" }, children: [
|
|
3134
|
+
/* @__PURE__ */ jsxs13("div", { children: [
|
|
3135
|
+
/* @__PURE__ */ jsx15("div", { children: passkey.name || "Passkey" }),
|
|
3136
|
+
/* @__PURE__ */ jsxs13("div", { className: "b316-muted", children: [
|
|
2705
3137
|
passkey.lastUsedAt ? `Last used ${formatDate(passkey.lastUsedAt)}` : `Added ${formatDate(passkey.createdAt)}`,
|
|
2706
3138
|
passkey.backedUp ? "" : " \xB7 this device only"
|
|
2707
3139
|
] })
|
|
2708
3140
|
] }),
|
|
2709
|
-
/* @__PURE__ */
|
|
3141
|
+
/* @__PURE__ */ jsx15(
|
|
2710
3142
|
ConfirmButton,
|
|
2711
3143
|
{
|
|
2712
3144
|
className: "b316-button b316-button-secondary",
|
|
@@ -2716,9 +3148,9 @@ function PasskeyManager({
|
|
|
2716
3148
|
}
|
|
2717
3149
|
)
|
|
2718
3150
|
] }, passkey.id)) }),
|
|
2719
|
-
error ? /* @__PURE__ */
|
|
2720
|
-
/* @__PURE__ */
|
|
2721
|
-
/* @__PURE__ */
|
|
3151
|
+
error ? /* @__PURE__ */ jsx15("div", { className: "b316-error", role: "alert", style: { marginTop: 12 }, children: error }) : null,
|
|
3152
|
+
/* @__PURE__ */ jsxs13("div", { className: "b316-row", style: { marginTop: 12, gap: 8 }, children: [
|
|
3153
|
+
/* @__PURE__ */ jsx15(
|
|
2722
3154
|
"input",
|
|
2723
3155
|
{
|
|
2724
3156
|
className: "b316-input",
|
|
@@ -2727,7 +3159,7 @@ function PasskeyManager({
|
|
|
2727
3159
|
onChange: (event) => setName(event.target.value)
|
|
2728
3160
|
}
|
|
2729
3161
|
),
|
|
2730
|
-
/* @__PURE__ */
|
|
3162
|
+
/* @__PURE__ */ jsx15("button", { type: "button", className: "b316-button", disabled: busy, onClick: () => void add(), children: busy ? "Waiting\u2026" : "Add a passkey" })
|
|
2731
3163
|
] })
|
|
2732
3164
|
] });
|
|
2733
3165
|
}
|
|
@@ -2737,8 +3169,8 @@ function formatDate(value) {
|
|
|
2737
3169
|
}
|
|
2738
3170
|
|
|
2739
3171
|
// src/ActiveSessions.tsx
|
|
2740
|
-
import { useCallback as useCallback6, useEffect as
|
|
2741
|
-
import { jsx as
|
|
3172
|
+
import { useCallback as useCallback6, useEffect as useEffect13, useState as useState12 } from "react";
|
|
3173
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2742
3174
|
function describeDevice(userAgent) {
|
|
2743
3175
|
if (!userAgent) {
|
|
2744
3176
|
return null;
|
|
@@ -2756,9 +3188,9 @@ function when(value) {
|
|
|
2756
3188
|
}
|
|
2757
3189
|
function ActiveSessions({ onRevoked, className, style }) {
|
|
2758
3190
|
const { client, token } = useBase316();
|
|
2759
|
-
const [sessions, setSessions] =
|
|
2760
|
-
const [error, setError] =
|
|
2761
|
-
const [busy, setBusy] =
|
|
3191
|
+
const [sessions, setSessions] = useState12(null);
|
|
3192
|
+
const [error, setError] = useState12(null);
|
|
3193
|
+
const [busy, setBusy] = useState12(false);
|
|
2762
3194
|
const load = useCallback6(() => {
|
|
2763
3195
|
if (!token) {
|
|
2764
3196
|
return;
|
|
@@ -2770,15 +3202,15 @@ function ActiveSessions({ onRevoked, className, style }) {
|
|
|
2770
3202
|
setError(cause instanceof Error ? cause.message : "Could not load your sessions.");
|
|
2771
3203
|
});
|
|
2772
3204
|
}, [client, token]);
|
|
2773
|
-
|
|
3205
|
+
useEffect13(load, [load]);
|
|
2774
3206
|
if (!token) {
|
|
2775
3207
|
return null;
|
|
2776
3208
|
}
|
|
2777
3209
|
if (error) {
|
|
2778
|
-
return /* @__PURE__ */
|
|
3210
|
+
return /* @__PURE__ */ jsx16("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx16("div", { className: "b316-error", role: "alert", children: error }) });
|
|
2779
3211
|
}
|
|
2780
3212
|
if (!sessions) {
|
|
2781
|
-
return /* @__PURE__ */
|
|
3213
|
+
return /* @__PURE__ */ jsx16("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
2782
3214
|
}
|
|
2783
3215
|
async function revokeOthers() {
|
|
2784
3216
|
setBusy(true);
|
|
@@ -2792,32 +3224,32 @@ function ActiveSessions({ onRevoked, className, style }) {
|
|
|
2792
3224
|
setBusy(false);
|
|
2793
3225
|
}
|
|
2794
3226
|
}
|
|
2795
|
-
return /* @__PURE__ */
|
|
2796
|
-
/* @__PURE__ */
|
|
2797
|
-
/* @__PURE__ */
|
|
2798
|
-
sessions.length > 1 ? /* @__PURE__ */
|
|
3227
|
+
return /* @__PURE__ */ jsxs14("div", { className: cls("b316-card b316-sessions", className), style, children: [
|
|
3228
|
+
/* @__PURE__ */ jsxs14("div", { className: "b316-sessions-head", children: [
|
|
3229
|
+
/* @__PURE__ */ jsx16("h3", { className: "b316-sessions-title", children: "Where you are signed in" }),
|
|
3230
|
+
sessions.length > 1 ? /* @__PURE__ */ jsx16("button", { type: "button", className: "b316-button", disabled: busy, onClick: revokeOthers, children: busy ? "Ending\u2026" : "Sign out other devices" }) : null
|
|
2799
3231
|
] }),
|
|
2800
|
-
/* @__PURE__ */
|
|
2801
|
-
/* @__PURE__ */
|
|
3232
|
+
/* @__PURE__ */ jsx16("ul", { className: "b316-sessions-list", children: sessions.map((session) => /* @__PURE__ */ jsxs14("li", { className: "b316-session", children: [
|
|
3233
|
+
/* @__PURE__ */ jsxs14("div", { className: "b316-session-device", children: [
|
|
2802
3234
|
describeDevice(session.userAgent) ?? "Unknown device",
|
|
2803
3235
|
session.impersonatedBy ? (
|
|
2804
3236
|
// Worth saying loudly: somebody is acting as this account.
|
|
2805
|
-
/* @__PURE__ */
|
|
3237
|
+
/* @__PURE__ */ jsx16("span", { className: "b316-chip", children: " Support access" })
|
|
2806
3238
|
) : null
|
|
2807
3239
|
] }),
|
|
2808
|
-
/* @__PURE__ */
|
|
3240
|
+
/* @__PURE__ */ jsxs14("div", { className: "b316-muted", children: [
|
|
2809
3241
|
session.ipAddress ? `${session.ipAddress} \xB7 ` : "",
|
|
2810
3242
|
"last used ",
|
|
2811
3243
|
when(session.lastSeenAt)
|
|
2812
3244
|
] })
|
|
2813
3245
|
] }, session.id)) }),
|
|
2814
|
-
sessions.length === 0 ? /* @__PURE__ */
|
|
3246
|
+
sessions.length === 0 ? /* @__PURE__ */ jsx16("div", { className: "b316-muted", children: "No active sessions." }) : null
|
|
2815
3247
|
] });
|
|
2816
3248
|
}
|
|
2817
3249
|
|
|
2818
3250
|
// src/DeviceApproval.tsx
|
|
2819
|
-
import { useState as
|
|
2820
|
-
import { jsx as
|
|
3251
|
+
import { useState as useState13 } from "react";
|
|
3252
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2821
3253
|
function DeviceApproval({
|
|
2822
3254
|
userCode = "",
|
|
2823
3255
|
onDecided,
|
|
@@ -2825,11 +3257,11 @@ function DeviceApproval({
|
|
|
2825
3257
|
style
|
|
2826
3258
|
}) {
|
|
2827
3259
|
const { client, token } = useBase316();
|
|
2828
|
-
const [code, setCode] =
|
|
2829
|
-
const [request, setRequest] =
|
|
2830
|
-
const [decided, setDecided] =
|
|
2831
|
-
const [error, setError] =
|
|
2832
|
-
const [busy, setBusy] =
|
|
3260
|
+
const [code, setCode] = useState13(userCode);
|
|
3261
|
+
const [request, setRequest] = useState13(null);
|
|
3262
|
+
const [decided, setDecided] = useState13(null);
|
|
3263
|
+
const [error, setError] = useState13(null);
|
|
3264
|
+
const [busy, setBusy] = useState13(false);
|
|
2833
3265
|
if (!token) {
|
|
2834
3266
|
return null;
|
|
2835
3267
|
}
|
|
@@ -2862,25 +3294,25 @@ function DeviceApproval({
|
|
|
2862
3294
|
}
|
|
2863
3295
|
}
|
|
2864
3296
|
if (decided !== null) {
|
|
2865
|
-
return /* @__PURE__ */
|
|
2866
|
-
/* @__PURE__ */
|
|
2867
|
-
/* @__PURE__ */
|
|
3297
|
+
return /* @__PURE__ */ jsxs15("div", { className: cls("b316-card b316-device", className), style, children: [
|
|
3298
|
+
/* @__PURE__ */ jsx17("h3", { className: "b316-device-title", children: decided ? "You're all set" : "Not approved" }),
|
|
3299
|
+
/* @__PURE__ */ jsx17("p", { className: "b316-muted", children: decided ? "You can close this page and go back to your device." : "Nothing was granted. You can close this page." })
|
|
2868
3300
|
] });
|
|
2869
3301
|
}
|
|
2870
3302
|
if (request) {
|
|
2871
|
-
return /* @__PURE__ */
|
|
2872
|
-
/* @__PURE__ */
|
|
3303
|
+
return /* @__PURE__ */ jsxs15("div", { className: cls("b316-card b316-device", className), style, children: [
|
|
3304
|
+
/* @__PURE__ */ jsxs15("h3", { className: "b316-device-title", children: [
|
|
2873
3305
|
"Sign in to ",
|
|
2874
3306
|
request.clientName
|
|
2875
3307
|
] }),
|
|
2876
|
-
/* @__PURE__ */
|
|
3308
|
+
/* @__PURE__ */ jsxs15("p", { className: "b316-muted", children: [
|
|
2877
3309
|
request.clientName,
|
|
2878
3310
|
" is asking to sign in as you."
|
|
2879
3311
|
] }),
|
|
2880
|
-
request.scopes.length > 0 ? /* @__PURE__ */
|
|
2881
|
-
error ? /* @__PURE__ */
|
|
2882
|
-
/* @__PURE__ */
|
|
2883
|
-
/* @__PURE__ */
|
|
3312
|
+
request.scopes.length > 0 ? /* @__PURE__ */ jsx17("ul", { className: "b316-device-scopes", children: request.scopes.map((scope) => /* @__PURE__ */ jsx17("li", { children: scope }, scope)) }) : null,
|
|
3313
|
+
error ? /* @__PURE__ */ jsx17("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3314
|
+
/* @__PURE__ */ jsxs15("div", { className: "b316-device-actions", children: [
|
|
3315
|
+
/* @__PURE__ */ jsx17(
|
|
2884
3316
|
"button",
|
|
2885
3317
|
{
|
|
2886
3318
|
type: "button",
|
|
@@ -2890,7 +3322,7 @@ function DeviceApproval({
|
|
|
2890
3322
|
children: busy ? "Approving\u2026" : "Approve"
|
|
2891
3323
|
}
|
|
2892
3324
|
),
|
|
2893
|
-
/* @__PURE__ */
|
|
3325
|
+
/* @__PURE__ */ jsx17(
|
|
2894
3326
|
"button",
|
|
2895
3327
|
{
|
|
2896
3328
|
type: "button",
|
|
@@ -2903,11 +3335,11 @@ function DeviceApproval({
|
|
|
2903
3335
|
] })
|
|
2904
3336
|
] });
|
|
2905
3337
|
}
|
|
2906
|
-
return /* @__PURE__ */
|
|
2907
|
-
/* @__PURE__ */
|
|
2908
|
-
/* @__PURE__ */
|
|
2909
|
-
error ? /* @__PURE__ */
|
|
2910
|
-
/* @__PURE__ */
|
|
3338
|
+
return /* @__PURE__ */ jsxs15("form", { className: cls("b316-card b316-device", className), style, onSubmit: lookUp, children: [
|
|
3339
|
+
/* @__PURE__ */ jsx17("h3", { className: "b316-device-title", children: "Connect your device" }),
|
|
3340
|
+
/* @__PURE__ */ jsx17("p", { className: "b316-muted", children: "Enter the code shown on your device." }),
|
|
3341
|
+
error ? /* @__PURE__ */ jsx17("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3342
|
+
/* @__PURE__ */ jsx17(
|
|
2911
3343
|
"input",
|
|
2912
3344
|
{
|
|
2913
3345
|
className: "b316-input",
|
|
@@ -2920,13 +3352,13 @@ function DeviceApproval({
|
|
|
2920
3352
|
"aria-label": "Device code"
|
|
2921
3353
|
}
|
|
2922
3354
|
),
|
|
2923
|
-
/* @__PURE__ */
|
|
3355
|
+
/* @__PURE__ */ jsx17("button", { type: "submit", className: "b316-button", disabled: busy || code.trim().length < 4, children: busy ? "Checking\u2026" : "Continue" })
|
|
2924
3356
|
] });
|
|
2925
3357
|
}
|
|
2926
3358
|
|
|
2927
3359
|
// src/PrivacyControls.tsx
|
|
2928
|
-
import { useState as
|
|
2929
|
-
import { jsx as
|
|
3360
|
+
import { useState as useState14 } from "react";
|
|
3361
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2930
3362
|
function PrivacyControls({
|
|
2931
3363
|
confirmWord = "DELETE",
|
|
2932
3364
|
onErased,
|
|
@@ -2934,10 +3366,10 @@ function PrivacyControls({
|
|
|
2934
3366
|
style
|
|
2935
3367
|
}) {
|
|
2936
3368
|
const { client, token } = useBase316();
|
|
2937
|
-
const [confirming, setConfirming] =
|
|
2938
|
-
const [typed, setTyped] =
|
|
2939
|
-
const [error, setError] =
|
|
2940
|
-
const [busy, setBusy] =
|
|
3369
|
+
const [confirming, setConfirming] = useState14(false);
|
|
3370
|
+
const [typed, setTyped] = useState14("");
|
|
3371
|
+
const [error, setError] = useState14(null);
|
|
3372
|
+
const [busy, setBusy] = useState14(false);
|
|
2941
3373
|
if (!token) {
|
|
2942
3374
|
return null;
|
|
2943
3375
|
}
|
|
@@ -2972,22 +3404,22 @@ function PrivacyControls({
|
|
|
2972
3404
|
setBusy(false);
|
|
2973
3405
|
}
|
|
2974
3406
|
}
|
|
2975
|
-
return /* @__PURE__ */
|
|
2976
|
-
/* @__PURE__ */
|
|
2977
|
-
error ? /* @__PURE__ */
|
|
2978
|
-
/* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
2980
|
-
/* @__PURE__ */
|
|
2981
|
-
/* @__PURE__ */
|
|
3407
|
+
return /* @__PURE__ */ jsxs16("div", { className: cls("b316-card b316-privacy", className), style, children: [
|
|
3408
|
+
/* @__PURE__ */ jsx18("h3", { className: "b316-privacy-title", children: "Your data" }),
|
|
3409
|
+
error ? /* @__PURE__ */ jsx18("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3410
|
+
/* @__PURE__ */ jsxs16("div", { className: "b316-privacy-row", children: [
|
|
3411
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
3412
|
+
/* @__PURE__ */ jsx18("p", { children: "Download a copy" }),
|
|
3413
|
+
/* @__PURE__ */ jsx18("p", { className: "b316-muted", children: "Everything we hold about you, as a file. Passwords and security keys are not included \u2014 they are what protect the account rather than anything you can use." })
|
|
2982
3414
|
] }),
|
|
2983
|
-
/* @__PURE__ */
|
|
3415
|
+
/* @__PURE__ */ jsx18("button", { type: "button", className: "b316-button-quiet", disabled: busy, onClick: download, children: busy ? "Preparing\u2026" : "Download" })
|
|
2984
3416
|
] }),
|
|
2985
|
-
/* @__PURE__ */
|
|
2986
|
-
/* @__PURE__ */
|
|
2987
|
-
/* @__PURE__ */
|
|
2988
|
-
/* @__PURE__ */
|
|
3417
|
+
/* @__PURE__ */ jsxs16("div", { className: "b316-privacy-row", children: [
|
|
3418
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
3419
|
+
/* @__PURE__ */ jsx18("p", { children: "Delete your account" }),
|
|
3420
|
+
/* @__PURE__ */ jsx18("p", { className: "b316-muted", children: "Permanent. Invoices already raised are kept, because the law requires it; everything that identifies you is removed from them." })
|
|
2989
3421
|
] }),
|
|
2990
|
-
confirming ? null : /* @__PURE__ */
|
|
3422
|
+
confirming ? null : /* @__PURE__ */ jsx18(
|
|
2991
3423
|
"button",
|
|
2992
3424
|
{
|
|
2993
3425
|
type: "button",
|
|
@@ -2998,13 +3430,13 @@ function PrivacyControls({
|
|
|
2998
3430
|
}
|
|
2999
3431
|
)
|
|
3000
3432
|
] }),
|
|
3001
|
-
confirming ? /* @__PURE__ */
|
|
3002
|
-
/* @__PURE__ */
|
|
3433
|
+
confirming ? /* @__PURE__ */ jsxs16("div", { className: "b316-privacy-confirm", children: [
|
|
3434
|
+
/* @__PURE__ */ jsxs16("label", { className: "b316-label", htmlFor: "b316-privacy-confirm", children: [
|
|
3003
3435
|
"Type ",
|
|
3004
3436
|
confirmWord,
|
|
3005
3437
|
" to confirm"
|
|
3006
3438
|
] }),
|
|
3007
|
-
/* @__PURE__ */
|
|
3439
|
+
/* @__PURE__ */ jsx18(
|
|
3008
3440
|
"input",
|
|
3009
3441
|
{
|
|
3010
3442
|
id: "b316-privacy-confirm",
|
|
@@ -3014,8 +3446,8 @@ function PrivacyControls({
|
|
|
3014
3446
|
onChange: (event) => setTyped(event.target.value)
|
|
3015
3447
|
}
|
|
3016
3448
|
),
|
|
3017
|
-
/* @__PURE__ */
|
|
3018
|
-
/* @__PURE__ */
|
|
3449
|
+
/* @__PURE__ */ jsxs16("div", { className: "b316-privacy-actions", children: [
|
|
3450
|
+
/* @__PURE__ */ jsx18(
|
|
3019
3451
|
"button",
|
|
3020
3452
|
{
|
|
3021
3453
|
type: "button",
|
|
@@ -3027,7 +3459,7 @@ function PrivacyControls({
|
|
|
3027
3459
|
children: "Cancel"
|
|
3028
3460
|
}
|
|
3029
3461
|
),
|
|
3030
|
-
/* @__PURE__ */
|
|
3462
|
+
/* @__PURE__ */ jsx18(
|
|
3031
3463
|
"button",
|
|
3032
3464
|
{
|
|
3033
3465
|
type: "button",
|
|
@@ -3043,12 +3475,12 @@ function PrivacyControls({
|
|
|
3043
3475
|
}
|
|
3044
3476
|
|
|
3045
3477
|
// src/TwoFactorManager.tsx
|
|
3046
|
-
import { useState as
|
|
3478
|
+
import { useState as useState15 } from "react";
|
|
3047
3479
|
|
|
3048
3480
|
// src/QrCode.tsx
|
|
3049
3481
|
import qrcode from "qrcode-generator";
|
|
3050
3482
|
import { useMemo as useMemo2 } from "react";
|
|
3051
|
-
import { jsx as
|
|
3483
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3052
3484
|
var QUIET_ZONE = 4;
|
|
3053
3485
|
function utf8Binary(value) {
|
|
3054
3486
|
let binary = "";
|
|
@@ -3075,7 +3507,7 @@ function qrPath(value) {
|
|
|
3075
3507
|
function QrCode({ value, label, size = 180, className }) {
|
|
3076
3508
|
const { path, modules } = useMemo2(() => qrPath(value), [value]);
|
|
3077
3509
|
const extent = modules + QUIET_ZONE * 2;
|
|
3078
|
-
return /* @__PURE__ */
|
|
3510
|
+
return /* @__PURE__ */ jsxs17(
|
|
3079
3511
|
"svg",
|
|
3080
3512
|
{
|
|
3081
3513
|
className,
|
|
@@ -3087,15 +3519,15 @@ function QrCode({ value, label, size = 180, className }) {
|
|
|
3087
3519
|
shapeRendering: "crispEdges",
|
|
3088
3520
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3089
3521
|
children: [
|
|
3090
|
-
/* @__PURE__ */
|
|
3091
|
-
/* @__PURE__ */
|
|
3522
|
+
/* @__PURE__ */ jsx19("rect", { width: extent, height: extent, fill: "#ffffff" }),
|
|
3523
|
+
/* @__PURE__ */ jsx19("path", { d: path, fill: "#000000" })
|
|
3092
3524
|
]
|
|
3093
3525
|
}
|
|
3094
3526
|
);
|
|
3095
3527
|
}
|
|
3096
3528
|
|
|
3097
3529
|
// src/TwoFactorManager.tsx
|
|
3098
|
-
import { jsx as
|
|
3530
|
+
import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3099
3531
|
function groupKey(secret) {
|
|
3100
3532
|
return secret.replace(/\s+/g, "").replace(/(.{4})(?=.)/g, "$1 ");
|
|
3101
3533
|
}
|
|
@@ -3108,12 +3540,12 @@ function TwoFactorManager({
|
|
|
3108
3540
|
style
|
|
3109
3541
|
}) {
|
|
3110
3542
|
const { client, token } = useBase316();
|
|
3111
|
-
const [stage, setStage] =
|
|
3112
|
-
const [on, setOn] =
|
|
3113
|
-
const [code, setCode] =
|
|
3114
|
-
const [phone, setPhone] =
|
|
3115
|
-
const [error, setError] =
|
|
3116
|
-
const [busy, setBusy] =
|
|
3543
|
+
const [stage, setStage] = useState15({ name: "idle" });
|
|
3544
|
+
const [on, setOn] = useState15(enabled);
|
|
3545
|
+
const [code, setCode] = useState15("");
|
|
3546
|
+
const [phone, setPhone] = useState15("");
|
|
3547
|
+
const [error, setError] = useState15(null);
|
|
3548
|
+
const [busy, setBusy] = useState15(false);
|
|
3117
3549
|
if (!token) {
|
|
3118
3550
|
return null;
|
|
3119
3551
|
}
|
|
@@ -3191,17 +3623,17 @@ function TwoFactorManager({
|
|
|
3191
3623
|
setBusy(false);
|
|
3192
3624
|
}
|
|
3193
3625
|
}
|
|
3194
|
-
return /* @__PURE__ */
|
|
3195
|
-
/* @__PURE__ */
|
|
3196
|
-
error ? /* @__PURE__ */
|
|
3197
|
-
stage.name === "saved" ? /* @__PURE__ */
|
|
3198
|
-
/* @__PURE__ */
|
|
3199
|
-
/* @__PURE__ */
|
|
3200
|
-
/* @__PURE__ */
|
|
3201
|
-
] }) : stage.name === "smsNumber" ? /* @__PURE__ */
|
|
3202
|
-
/* @__PURE__ */
|
|
3203
|
-
/* @__PURE__ */
|
|
3204
|
-
/* @__PURE__ */
|
|
3626
|
+
return /* @__PURE__ */ jsxs18("div", { className: cls("b316-card b316-mfa", className), style, children: [
|
|
3627
|
+
/* @__PURE__ */ jsx20("h3", { className: "b316-mfa-title", children: "Two-factor authentication" }),
|
|
3628
|
+
error ? /* @__PURE__ */ jsx20("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3629
|
+
stage.name === "saved" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-codes", children: [
|
|
3630
|
+
/* @__PURE__ */ jsx20("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." }),
|
|
3631
|
+
/* @__PURE__ */ jsx20("ul", { className: "b316-mfa-code-list", children: stage.recoveryCodes.map((recovery) => /* @__PURE__ */ jsx20("li", { children: /* @__PURE__ */ jsx20("code", { children: recovery }) }, recovery)) }),
|
|
3632
|
+
/* @__PURE__ */ jsx20("button", { type: "button", className: "b316-button", onClick: () => setStage({ name: "idle" }), children: "I have saved them" })
|
|
3633
|
+
] }) : stage.name === "smsNumber" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-enrol", children: [
|
|
3634
|
+
/* @__PURE__ */ jsx20("p", { children: "We will text a code to this number now, and each time you sign in." }),
|
|
3635
|
+
/* @__PURE__ */ jsx20("label", { className: "b316-label", htmlFor: "b316-mfa-phone", children: "Mobile number" }),
|
|
3636
|
+
/* @__PURE__ */ jsx20(
|
|
3205
3637
|
"input",
|
|
3206
3638
|
{
|
|
3207
3639
|
id: "b316-mfa-phone",
|
|
@@ -3213,8 +3645,8 @@ function TwoFactorManager({
|
|
|
3213
3645
|
onChange: (event) => setPhone(event.target.value)
|
|
3214
3646
|
}
|
|
3215
3647
|
),
|
|
3216
|
-
/* @__PURE__ */
|
|
3217
|
-
/* @__PURE__ */
|
|
3648
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3649
|
+
/* @__PURE__ */ jsx20(
|
|
3218
3650
|
"button",
|
|
3219
3651
|
{
|
|
3220
3652
|
type: "button",
|
|
@@ -3223,16 +3655,16 @@ function TwoFactorManager({
|
|
|
3223
3655
|
children: "Cancel"
|
|
3224
3656
|
}
|
|
3225
3657
|
),
|
|
3226
|
-
/* @__PURE__ */
|
|
3658
|
+
/* @__PURE__ */ jsx20("button", { type: "button", className: "b316-button", disabled: busy, onClick: beginSms, children: busy ? "Sending\u2026" : "Send code" })
|
|
3227
3659
|
] })
|
|
3228
|
-
] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */
|
|
3229
|
-
/* @__PURE__ */
|
|
3660
|
+
] }) : stage.name === "enrollingEmail" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-enrol", children: [
|
|
3661
|
+
/* @__PURE__ */ jsxs18("p", { children: [
|
|
3230
3662
|
"We sent a code to ",
|
|
3231
3663
|
stage.destinationHint,
|
|
3232
3664
|
". Enter it below to turn this on."
|
|
3233
3665
|
] }),
|
|
3234
|
-
/* @__PURE__ */
|
|
3235
|
-
/* @__PURE__ */
|
|
3666
|
+
/* @__PURE__ */ jsx20("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
|
|
3667
|
+
/* @__PURE__ */ jsx20(
|
|
3236
3668
|
"input",
|
|
3237
3669
|
{
|
|
3238
3670
|
id: "b316-mfa-code",
|
|
@@ -3243,8 +3675,8 @@ function TwoFactorManager({
|
|
|
3243
3675
|
onChange: (event) => setCode(event.target.value)
|
|
3244
3676
|
}
|
|
3245
3677
|
),
|
|
3246
|
-
/* @__PURE__ */
|
|
3247
|
-
/* @__PURE__ */
|
|
3678
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3679
|
+
/* @__PURE__ */ jsx20(
|
|
3248
3680
|
"button",
|
|
3249
3681
|
{
|
|
3250
3682
|
type: "button",
|
|
@@ -3253,7 +3685,7 @@ function TwoFactorManager({
|
|
|
3253
3685
|
children: "Cancel"
|
|
3254
3686
|
}
|
|
3255
3687
|
),
|
|
3256
|
-
/* @__PURE__ */
|
|
3688
|
+
/* @__PURE__ */ jsx20(
|
|
3257
3689
|
"button",
|
|
3258
3690
|
{
|
|
3259
3691
|
type: "button",
|
|
@@ -3264,9 +3696,9 @@ function TwoFactorManager({
|
|
|
3264
3696
|
}
|
|
3265
3697
|
)
|
|
3266
3698
|
] })
|
|
3267
|
-
] }) : stage.name === "enrolling" ? /* @__PURE__ */
|
|
3268
|
-
/* @__PURE__ */
|
|
3269
|
-
/* @__PURE__ */
|
|
3699
|
+
] }) : stage.name === "enrolling" ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-enrol", children: [
|
|
3700
|
+
/* @__PURE__ */ jsx20("p", { children: "Scan this with your authenticator app (Google Authenticator, 1Password, Authy\u2026), then enter the six-digit code it shows." }),
|
|
3701
|
+
/* @__PURE__ */ jsx20(
|
|
3270
3702
|
QrCode,
|
|
3271
3703
|
{
|
|
3272
3704
|
className: "b316-mfa-qr",
|
|
@@ -3274,13 +3706,13 @@ function TwoFactorManager({
|
|
|
3274
3706
|
label: "QR code for your authenticator app"
|
|
3275
3707
|
}
|
|
3276
3708
|
),
|
|
3277
|
-
/* @__PURE__ */
|
|
3278
|
-
/* @__PURE__ */
|
|
3279
|
-
/* @__PURE__ */
|
|
3709
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-secret", children: [
|
|
3710
|
+
/* @__PURE__ */ jsx20("span", { className: "b316-label", id: "b316-mfa-manual-key", children: "Can't scan? Enter this key" }),
|
|
3711
|
+
/* @__PURE__ */ jsx20("code", { "aria-labelledby": "b316-mfa-manual-key", children: groupKey(stage.secret) })
|
|
3280
3712
|
] }),
|
|
3281
|
-
/* @__PURE__ */
|
|
3282
|
-
/* @__PURE__ */
|
|
3283
|
-
/* @__PURE__ */
|
|
3713
|
+
/* @__PURE__ */ jsx20("a", { className: "b316-mfa-uri", href: stage.uri, children: "Open in an authenticator app" }),
|
|
3714
|
+
/* @__PURE__ */ jsx20("label", { className: "b316-label", htmlFor: "b316-mfa-code", children: "Code" }),
|
|
3715
|
+
/* @__PURE__ */ jsx20(
|
|
3284
3716
|
"input",
|
|
3285
3717
|
{
|
|
3286
3718
|
id: "b316-mfa-code",
|
|
@@ -3291,8 +3723,8 @@ function TwoFactorManager({
|
|
|
3291
3723
|
onChange: (event) => setCode(event.target.value)
|
|
3292
3724
|
}
|
|
3293
3725
|
),
|
|
3294
|
-
/* @__PURE__ */
|
|
3295
|
-
/* @__PURE__ */
|
|
3726
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3727
|
+
/* @__PURE__ */ jsx20(
|
|
3296
3728
|
"button",
|
|
3297
3729
|
{
|
|
3298
3730
|
type: "button",
|
|
@@ -3301,7 +3733,7 @@ function TwoFactorManager({
|
|
|
3301
3733
|
children: "Cancel"
|
|
3302
3734
|
}
|
|
3303
3735
|
),
|
|
3304
|
-
/* @__PURE__ */
|
|
3736
|
+
/* @__PURE__ */ jsx20(
|
|
3305
3737
|
"button",
|
|
3306
3738
|
{
|
|
3307
3739
|
type: "button",
|
|
@@ -3312,9 +3744,9 @@ function TwoFactorManager({
|
|
|
3312
3744
|
}
|
|
3313
3745
|
)
|
|
3314
3746
|
] })
|
|
3315
|
-
] }) : on ? /* @__PURE__ */
|
|
3316
|
-
/* @__PURE__ */
|
|
3317
|
-
/* @__PURE__ */
|
|
3747
|
+
] }) : on ? /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-on", children: [
|
|
3748
|
+
/* @__PURE__ */ jsx20("p", { className: "b316-muted", children: "On. You will be asked for a code when you sign in." }),
|
|
3749
|
+
/* @__PURE__ */ jsx20(
|
|
3318
3750
|
ConfirmButton,
|
|
3319
3751
|
{
|
|
3320
3752
|
className: "b316-button-quiet b316-danger",
|
|
@@ -3324,11 +3756,11 @@ function TwoFactorManager({
|
|
|
3324
3756
|
children: "Turn off"
|
|
3325
3757
|
}
|
|
3326
3758
|
)
|
|
3327
|
-
] }) : /* @__PURE__ */
|
|
3328
|
-
/* @__PURE__ */
|
|
3329
|
-
/* @__PURE__ */
|
|
3330
|
-
/* @__PURE__ */
|
|
3331
|
-
/* @__PURE__ */
|
|
3759
|
+
] }) : /* @__PURE__ */ jsxs18("div", { className: "b316-mfa-off", children: [
|
|
3760
|
+
/* @__PURE__ */ jsx20("p", { className: "b316-muted", children: "Off. Turning it on means a code as well as your password, every time you sign in." }),
|
|
3761
|
+
/* @__PURE__ */ jsxs18("div", { className: "b316-mfa-actions", children: [
|
|
3762
|
+
/* @__PURE__ */ jsx20("button", { type: "button", className: "b316-button", disabled: busy, onClick: begin, children: busy ? "Starting\u2026" : "Use an authenticator app" }),
|
|
3763
|
+
/* @__PURE__ */ jsx20(
|
|
3332
3764
|
"button",
|
|
3333
3765
|
{
|
|
3334
3766
|
type: "button",
|
|
@@ -3338,7 +3770,7 @@ function TwoFactorManager({
|
|
|
3338
3770
|
children: "Email me a code"
|
|
3339
3771
|
}
|
|
3340
3772
|
),
|
|
3341
|
-
allowSms ? /* @__PURE__ */
|
|
3773
|
+
allowSms ? /* @__PURE__ */ jsx20(
|
|
3342
3774
|
"button",
|
|
3343
3775
|
{
|
|
3344
3776
|
type: "button",
|
|
@@ -3354,14 +3786,14 @@ function TwoFactorManager({
|
|
|
3354
3786
|
}
|
|
3355
3787
|
|
|
3356
3788
|
// src/ForgotPassword.tsx
|
|
3357
|
-
import { useState as
|
|
3358
|
-
import { jsx as
|
|
3789
|
+
import { useState as useState16 } from "react";
|
|
3790
|
+
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3359
3791
|
function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
3360
3792
|
const { client } = useBase316();
|
|
3361
|
-
const [email, setEmail] =
|
|
3362
|
-
const [sent, setSent] =
|
|
3363
|
-
const [busy, setBusy] =
|
|
3364
|
-
const [error, setError] =
|
|
3793
|
+
const [email, setEmail] = useState16("");
|
|
3794
|
+
const [sent, setSent] = useState16(false);
|
|
3795
|
+
const [busy, setBusy] = useState16(false);
|
|
3796
|
+
const [error, setError] = useState16(null);
|
|
3365
3797
|
async function submit(event) {
|
|
3366
3798
|
event.preventDefault();
|
|
3367
3799
|
setBusy(true);
|
|
@@ -3377,22 +3809,22 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
|
3377
3809
|
}
|
|
3378
3810
|
}
|
|
3379
3811
|
if (sent) {
|
|
3380
|
-
return /* @__PURE__ */
|
|
3381
|
-
/* @__PURE__ */
|
|
3382
|
-
/* @__PURE__ */
|
|
3812
|
+
return /* @__PURE__ */ jsxs19("div", { className: cls("b316-card", className), style, children: [
|
|
3813
|
+
/* @__PURE__ */ jsx21("h3", { className: "b316-form-title", children: "Check your email" }),
|
|
3814
|
+
/* @__PURE__ */ jsxs19("p", { className: "b316-muted", children: [
|
|
3383
3815
|
"If there is an account for ",
|
|
3384
3816
|
email.trim(),
|
|
3385
3817
|
", a link to set a new password is on its way."
|
|
3386
3818
|
] }),
|
|
3387
|
-
signInUrl ? /* @__PURE__ */
|
|
3819
|
+
signInUrl ? /* @__PURE__ */ jsx21("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
|
|
3388
3820
|
] });
|
|
3389
3821
|
}
|
|
3390
|
-
return /* @__PURE__ */
|
|
3391
|
-
/* @__PURE__ */
|
|
3392
|
-
error ? /* @__PURE__ */
|
|
3393
|
-
/* @__PURE__ */
|
|
3394
|
-
/* @__PURE__ */
|
|
3395
|
-
/* @__PURE__ */
|
|
3822
|
+
return /* @__PURE__ */ jsxs19("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
|
|
3823
|
+
/* @__PURE__ */ jsx21("h3", { className: "b316-form-title", children: "Reset your password" }),
|
|
3824
|
+
error ? /* @__PURE__ */ jsx21("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3825
|
+
/* @__PURE__ */ jsxs19("div", { className: "b316-field", children: [
|
|
3826
|
+
/* @__PURE__ */ jsx21("label", { className: "b316-label", htmlFor: "b316-forgot-email", children: "Email" }),
|
|
3827
|
+
/* @__PURE__ */ jsx21(
|
|
3396
3828
|
"input",
|
|
3397
3829
|
{
|
|
3398
3830
|
id: "b316-forgot-email",
|
|
@@ -3405,14 +3837,14 @@ function ForgotPassword({ onSent, signInUrl, className, style }) {
|
|
|
3405
3837
|
}
|
|
3406
3838
|
)
|
|
3407
3839
|
] }),
|
|
3408
|
-
/* @__PURE__ */
|
|
3409
|
-
signInUrl ? /* @__PURE__ */
|
|
3840
|
+
/* @__PURE__ */ jsx21("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Send reset link" }),
|
|
3841
|
+
signInUrl ? /* @__PURE__ */ jsx21("a", { className: "b316-button-link", href: signInUrl, children: "Back to sign in" }) : null
|
|
3410
3842
|
] });
|
|
3411
3843
|
}
|
|
3412
3844
|
|
|
3413
3845
|
// src/ResetPassword.tsx
|
|
3414
|
-
import { useEffect as
|
|
3415
|
-
import { jsx as
|
|
3846
|
+
import { useEffect as useEffect14, useState as useState17 } from "react";
|
|
3847
|
+
import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3416
3848
|
function ResetPassword({
|
|
3417
3849
|
token: supplied,
|
|
3418
3850
|
onReset,
|
|
@@ -3421,13 +3853,13 @@ function ResetPassword({
|
|
|
3421
3853
|
style
|
|
3422
3854
|
}) {
|
|
3423
3855
|
const { client } = useBase316();
|
|
3424
|
-
const [token, setToken] =
|
|
3425
|
-
const [password, setPassword] =
|
|
3426
|
-
const [confirmation, setConfirmation] =
|
|
3427
|
-
const [done, setDone] =
|
|
3428
|
-
const [busy, setBusy] =
|
|
3429
|
-
const [error, setError] =
|
|
3430
|
-
|
|
3856
|
+
const [token, setToken] = useState17(supplied ?? null);
|
|
3857
|
+
const [password, setPassword] = useState17("");
|
|
3858
|
+
const [confirmation, setConfirmation] = useState17("");
|
|
3859
|
+
const [done, setDone] = useState17(false);
|
|
3860
|
+
const [busy, setBusy] = useState17(false);
|
|
3861
|
+
const [error, setError] = useState17(null);
|
|
3862
|
+
useEffect14(() => {
|
|
3431
3863
|
if (supplied || typeof window === "undefined") {
|
|
3432
3864
|
return;
|
|
3433
3865
|
}
|
|
@@ -3462,24 +3894,24 @@ function ResetPassword({
|
|
|
3462
3894
|
}
|
|
3463
3895
|
}
|
|
3464
3896
|
if (done) {
|
|
3465
|
-
return /* @__PURE__ */
|
|
3466
|
-
/* @__PURE__ */
|
|
3467
|
-
/* @__PURE__ */
|
|
3468
|
-
signInUrl ? /* @__PURE__ */
|
|
3897
|
+
return /* @__PURE__ */ jsxs20("div", { className: cls("b316-card", className), style, children: [
|
|
3898
|
+
/* @__PURE__ */ jsx22("h3", { className: "b316-form-title", children: "Password changed" }),
|
|
3899
|
+
/* @__PURE__ */ jsx22("p", { className: "b316-muted", children: "You can sign in with your new password." }),
|
|
3900
|
+
signInUrl ? /* @__PURE__ */ jsx22("a", { className: "b316-button-link", href: signInUrl, children: "Sign in" }) : null
|
|
3469
3901
|
] });
|
|
3470
3902
|
}
|
|
3471
3903
|
if (!token) {
|
|
3472
|
-
return /* @__PURE__ */
|
|
3473
|
-
/* @__PURE__ */
|
|
3474
|
-
/* @__PURE__ */
|
|
3904
|
+
return /* @__PURE__ */ jsxs20("div", { className: cls("b316-card", className), style, children: [
|
|
3905
|
+
/* @__PURE__ */ jsx22("h3", { className: "b316-form-title", children: "Nothing to reset" }),
|
|
3906
|
+
/* @__PURE__ */ jsx22("p", { className: "b316-muted", children: "This page needs the link from your email. Request a new one if yours has expired." })
|
|
3475
3907
|
] });
|
|
3476
3908
|
}
|
|
3477
|
-
return /* @__PURE__ */
|
|
3478
|
-
/* @__PURE__ */
|
|
3479
|
-
error ? /* @__PURE__ */
|
|
3480
|
-
/* @__PURE__ */
|
|
3481
|
-
/* @__PURE__ */
|
|
3482
|
-
/* @__PURE__ */
|
|
3909
|
+
return /* @__PURE__ */ jsxs20("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
|
|
3910
|
+
/* @__PURE__ */ jsx22("h3", { className: "b316-form-title", children: "Choose a new password" }),
|
|
3911
|
+
error ? /* @__PURE__ */ jsx22("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
3912
|
+
/* @__PURE__ */ jsxs20("div", { className: "b316-field", children: [
|
|
3913
|
+
/* @__PURE__ */ jsx22("label", { className: "b316-label", htmlFor: "b316-reset-password", children: "New password" }),
|
|
3914
|
+
/* @__PURE__ */ jsx22(
|
|
3483
3915
|
"input",
|
|
3484
3916
|
{
|
|
3485
3917
|
id: "b316-reset-password",
|
|
@@ -3492,9 +3924,9 @@ function ResetPassword({
|
|
|
3492
3924
|
}
|
|
3493
3925
|
)
|
|
3494
3926
|
] }),
|
|
3495
|
-
/* @__PURE__ */
|
|
3496
|
-
/* @__PURE__ */
|
|
3497
|
-
/* @__PURE__ */
|
|
3927
|
+
/* @__PURE__ */ jsxs20("div", { className: "b316-field", children: [
|
|
3928
|
+
/* @__PURE__ */ jsx22("label", { className: "b316-label", htmlFor: "b316-reset-confirm", children: "Repeat it" }),
|
|
3929
|
+
/* @__PURE__ */ jsx22(
|
|
3498
3930
|
"input",
|
|
3499
3931
|
{
|
|
3500
3932
|
id: "b316-reset-confirm",
|
|
@@ -3507,13 +3939,13 @@ function ResetPassword({
|
|
|
3507
3939
|
}
|
|
3508
3940
|
)
|
|
3509
3941
|
] }),
|
|
3510
|
-
/* @__PURE__ */
|
|
3942
|
+
/* @__PURE__ */ jsx22("button", { type: "submit", className: "b316-button", disabled: busy || !password, children: busy ? "Saving\u2026" : "Set password" })
|
|
3511
3943
|
] });
|
|
3512
3944
|
}
|
|
3513
3945
|
|
|
3514
3946
|
// src/VerifyEmail.tsx
|
|
3515
|
-
import { useEffect as
|
|
3516
|
-
import { Fragment as
|
|
3947
|
+
import { useEffect as useEffect15, useRef as useRef5, useState as useState18 } from "react";
|
|
3948
|
+
import { Fragment as Fragment7, jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3517
3949
|
function VerifyEmail({
|
|
3518
3950
|
token: supplied,
|
|
3519
3951
|
onVerified,
|
|
@@ -3522,9 +3954,9 @@ function VerifyEmail({
|
|
|
3522
3954
|
style
|
|
3523
3955
|
}) {
|
|
3524
3956
|
const { client } = useBase316();
|
|
3525
|
-
const [state, setState] =
|
|
3526
|
-
const spent =
|
|
3527
|
-
|
|
3957
|
+
const [state, setState] = useState18("waiting");
|
|
3958
|
+
const spent = useRef5(false);
|
|
3959
|
+
useEffect15(() => {
|
|
3528
3960
|
if (spent.current) {
|
|
3529
3961
|
return;
|
|
3530
3962
|
}
|
|
@@ -3550,22 +3982,22 @@ function VerifyEmail({
|
|
|
3550
3982
|
setState("failed");
|
|
3551
3983
|
});
|
|
3552
3984
|
}, [client, supplied, onVerified]);
|
|
3553
|
-
return /* @__PURE__ */
|
|
3554
|
-
/* @__PURE__ */
|
|
3555
|
-
/* @__PURE__ */
|
|
3556
|
-
continueUrl ? /* @__PURE__ */
|
|
3557
|
-
] }) : state === "failed" ? /* @__PURE__ */
|
|
3558
|
-
/* @__PURE__ */
|
|
3559
|
-
/* @__PURE__ */
|
|
3560
|
-
] }) : state === "missing" ? /* @__PURE__ */
|
|
3561
|
-
/* @__PURE__ */
|
|
3562
|
-
/* @__PURE__ */
|
|
3563
|
-
] }) : /* @__PURE__ */
|
|
3985
|
+
return /* @__PURE__ */ jsx23("div", { className: cls("b316-card", className), style, children: state === "verified" ? /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
3986
|
+
/* @__PURE__ */ jsx23("h3", { className: "b316-form-title", children: "Email confirmed" }),
|
|
3987
|
+
/* @__PURE__ */ jsx23("p", { className: "b316-muted", children: "Thanks \u2014 your address is verified." }),
|
|
3988
|
+
continueUrl ? /* @__PURE__ */ jsx23("a", { className: "b316-button-link", href: continueUrl, children: "Continue" }) : null
|
|
3989
|
+
] }) : state === "failed" ? /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
3990
|
+
/* @__PURE__ */ jsx23("h3", { className: "b316-form-title", children: "That link did not work" }),
|
|
3991
|
+
/* @__PURE__ */ jsx23("p", { className: "b316-muted", children: "It may have expired or already been used. Ask for a new one and try again." })
|
|
3992
|
+
] }) : state === "missing" ? /* @__PURE__ */ jsxs21(Fragment7, { children: [
|
|
3993
|
+
/* @__PURE__ */ jsx23("h3", { className: "b316-form-title", children: "Nothing to confirm" }),
|
|
3994
|
+
/* @__PURE__ */ jsx23("p", { className: "b316-muted", children: "This page needs the link from your email." })
|
|
3995
|
+
] }) : /* @__PURE__ */ jsx23("p", { className: "b316-muted", children: "Confirming your email\u2026" }) });
|
|
3564
3996
|
}
|
|
3565
3997
|
|
|
3566
3998
|
// src/TeamMembers.tsx
|
|
3567
|
-
import { useCallback as useCallback7, useEffect as
|
|
3568
|
-
import { Fragment as
|
|
3999
|
+
import { useCallback as useCallback7, useEffect as useEffect16, useState as useState19 } from "react";
|
|
4000
|
+
import { Fragment as Fragment8, jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
3569
4001
|
function TeamMembers({
|
|
3570
4002
|
organizationId,
|
|
3571
4003
|
onInvited,
|
|
@@ -3575,13 +4007,13 @@ function TeamMembers({
|
|
|
3575
4007
|
style
|
|
3576
4008
|
}) {
|
|
3577
4009
|
const { client, token, session } = useBase316();
|
|
3578
|
-
const [teams, setTeams] =
|
|
3579
|
-
const [members, setMembers] =
|
|
3580
|
-
const [invitations, setInvitations] =
|
|
3581
|
-
const [email, setEmail] =
|
|
3582
|
-
const [busy, setBusy] =
|
|
3583
|
-
const [error, setError] =
|
|
3584
|
-
const [copied, setCopied] =
|
|
4010
|
+
const [teams, setTeams] = useState19(null);
|
|
4011
|
+
const [members, setMembers] = useState19(null);
|
|
4012
|
+
const [invitations, setInvitations] = useState19(null);
|
|
4013
|
+
const [email, setEmail] = useState19("");
|
|
4014
|
+
const [busy, setBusy] = useState19(false);
|
|
4015
|
+
const [error, setError] = useState19(null);
|
|
4016
|
+
const [copied, setCopied] = useState19(null);
|
|
3585
4017
|
const chosen = organizationId ?? (teams?.length === 1 ? teams[0].id : null);
|
|
3586
4018
|
const team = teams?.find((candidate) => candidate.id === chosen) ?? null;
|
|
3587
4019
|
const load = useCallback7(() => {
|
|
@@ -3592,8 +4024,8 @@ function TeamMembers({
|
|
|
3592
4024
|
(cause) => setError(cause instanceof Error ? cause.message : "Could not load your teams.")
|
|
3593
4025
|
);
|
|
3594
4026
|
}, [client, token]);
|
|
3595
|
-
|
|
3596
|
-
|
|
4027
|
+
useEffect16(load, [load]);
|
|
4028
|
+
useEffect16(() => {
|
|
3597
4029
|
if (!token || !chosen) {
|
|
3598
4030
|
return;
|
|
3599
4031
|
}
|
|
@@ -3624,10 +4056,10 @@ function TeamMembers({
|
|
|
3624
4056
|
return null;
|
|
3625
4057
|
}
|
|
3626
4058
|
if (!teams) {
|
|
3627
|
-
return /* @__PURE__ */
|
|
4059
|
+
return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: error ?? "Loading\u2026" });
|
|
3628
4060
|
}
|
|
3629
4061
|
if (!chosen) {
|
|
3630
|
-
return /* @__PURE__ */
|
|
4062
|
+
return /* @__PURE__ */ jsx24("div", { className: cls("b316-card", className), style, children: teams.length === 0 ? "You are not in a team yet." : "You are in more than one team. Name which with the organizationId prop." });
|
|
3631
4063
|
}
|
|
3632
4064
|
const canManage = invitations !== null;
|
|
3633
4065
|
async function invite(event) {
|
|
@@ -3677,30 +4109,30 @@ function TeamMembers({
|
|
|
3677
4109
|
setError(cause instanceof Error ? cause.message : "That invitation could not be withdrawn.");
|
|
3678
4110
|
}
|
|
3679
4111
|
}
|
|
3680
|
-
return /* @__PURE__ */
|
|
3681
|
-
/* @__PURE__ */
|
|
4112
|
+
return /* @__PURE__ */ jsxs22("div", { className: cls("b316-card b316-team", className), style, children: [
|
|
4113
|
+
/* @__PURE__ */ jsx24("h3", { className: "b316-team-title", children: team?.name ?? "Team" }),
|
|
3682
4114
|
team?.inherited ? (
|
|
3683
4115
|
// Not a member of this team, so not in the list below and with nothing
|
|
3684
4116
|
// to leave: access comes from the team that manages it, and ends there.
|
|
3685
|
-
/* @__PURE__ */
|
|
4117
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-muted", children: [
|
|
3686
4118
|
"You have access through",
|
|
3687
4119
|
" ",
|
|
3688
4120
|
teams.find((candidate) => candidate.id === team.via)?.name ?? "the organization that manages this team",
|
|
3689
4121
|
"."
|
|
3690
4122
|
] })
|
|
3691
4123
|
) : null,
|
|
3692
|
-
error ? /* @__PURE__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
3696
|
-
/* @__PURE__ */
|
|
4124
|
+
error ? /* @__PURE__ */ jsx24("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
4125
|
+
/* @__PURE__ */ jsx24("ul", { className: "b316-team-list", children: (members ?? []).map((member) => /* @__PURE__ */ jsxs22("li", { className: "b316-team-member", children: [
|
|
4126
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
4127
|
+
/* @__PURE__ */ jsx24("div", { children: member.user.name ?? member.user.email ?? "Someone" }),
|
|
4128
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-muted", children: [
|
|
3697
4129
|
member.user.email,
|
|
3698
4130
|
member.user.id === session?.userId ? " \xB7 you" : ""
|
|
3699
4131
|
] })
|
|
3700
4132
|
] }),
|
|
3701
|
-
/* @__PURE__ */
|
|
3702
|
-
/* @__PURE__ */
|
|
3703
|
-
canManage || member.user.id === session?.userId ? /* @__PURE__ */
|
|
4133
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-team-member-side", children: [
|
|
4134
|
+
/* @__PURE__ */ jsx24("span", { className: "b316-chip", children: member.role.name }),
|
|
4135
|
+
canManage || member.user.id === session?.userId ? /* @__PURE__ */ jsx24(
|
|
3704
4136
|
ConfirmButton,
|
|
3705
4137
|
{
|
|
3706
4138
|
className: "b316-button-quiet b316-danger",
|
|
@@ -3712,19 +4144,19 @@ function TeamMembers({
|
|
|
3712
4144
|
) : null
|
|
3713
4145
|
] })
|
|
3714
4146
|
] }, member.id)) }),
|
|
3715
|
-
canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */
|
|
3716
|
-
/* @__PURE__ */
|
|
3717
|
-
/* @__PURE__ */
|
|
3718
|
-
/* @__PURE__ */
|
|
3719
|
-
/* @__PURE__ */
|
|
3720
|
-
/* @__PURE__ */
|
|
4147
|
+
canManage && (invitations ?? []).length > 0 ? /* @__PURE__ */ jsxs22(Fragment8, { children: [
|
|
4148
|
+
/* @__PURE__ */ jsx24("h4", { className: "b316-team-subtitle", children: "Invited" }),
|
|
4149
|
+
/* @__PURE__ */ jsx24("ul", { className: "b316-team-list", children: (invitations ?? []).map((invitation) => /* @__PURE__ */ jsxs22("li", { className: "b316-team-member", children: [
|
|
4150
|
+
/* @__PURE__ */ jsxs22("div", { children: [
|
|
4151
|
+
/* @__PURE__ */ jsx24("div", { children: invitation.email }),
|
|
4152
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-muted", children: [
|
|
3721
4153
|
invitation.role.name,
|
|
3722
4154
|
" \xB7 expires",
|
|
3723
4155
|
" ",
|
|
3724
4156
|
new Date(invitation.expiresAt).toLocaleDateString()
|
|
3725
4157
|
] })
|
|
3726
4158
|
] }),
|
|
3727
|
-
/* @__PURE__ */
|
|
4159
|
+
/* @__PURE__ */ jsx24(
|
|
3728
4160
|
"button",
|
|
3729
4161
|
{
|
|
3730
4162
|
type: "button",
|
|
@@ -3735,10 +4167,10 @@ function TeamMembers({
|
|
|
3735
4167
|
)
|
|
3736
4168
|
] }, invitation.id)) })
|
|
3737
4169
|
] }) : null,
|
|
3738
|
-
canManage ? /* @__PURE__ */
|
|
3739
|
-
/* @__PURE__ */
|
|
3740
|
-
/* @__PURE__ */
|
|
3741
|
-
/* @__PURE__ */
|
|
4170
|
+
canManage ? /* @__PURE__ */ jsxs22("form", { className: "b316-team-invite", onSubmit: invite, children: [
|
|
4171
|
+
/* @__PURE__ */ jsx24("label", { className: "b316-label", htmlFor: "b316-invite-email", children: "Invite by email" }),
|
|
4172
|
+
/* @__PURE__ */ jsxs22("div", { className: "b316-team-invite-row", children: [
|
|
4173
|
+
/* @__PURE__ */ jsx24(
|
|
3742
4174
|
"input",
|
|
3743
4175
|
{
|
|
3744
4176
|
id: "b316-invite-email",
|
|
@@ -3750,19 +4182,19 @@ function TeamMembers({
|
|
|
3750
4182
|
onChange: (event) => setEmail(event.target.value)
|
|
3751
4183
|
}
|
|
3752
4184
|
),
|
|
3753
|
-
/* @__PURE__ */
|
|
4185
|
+
/* @__PURE__ */ jsx24("button", { type: "submit", className: "b316-button", disabled: busy || !email, children: busy ? "Sending\u2026" : "Invite" })
|
|
3754
4186
|
] })
|
|
3755
4187
|
] }) : null,
|
|
3756
|
-
copied ? /* @__PURE__ */
|
|
3757
|
-
/* @__PURE__ */
|
|
3758
|
-
/* @__PURE__ */
|
|
4188
|
+
copied ? /* @__PURE__ */ jsxs22("div", { className: "b316-team-link", children: [
|
|
4189
|
+
/* @__PURE__ */ jsx24("div", { className: "b316-muted", children: "Send them this link. It is shown once and cannot be fetched again." }),
|
|
4190
|
+
/* @__PURE__ */ jsx24("code", { children: copied })
|
|
3759
4191
|
] }) : null
|
|
3760
4192
|
] });
|
|
3761
4193
|
}
|
|
3762
4194
|
|
|
3763
4195
|
// src/AcceptInvitation.tsx
|
|
3764
|
-
import { useEffect as
|
|
3765
|
-
import { Fragment as
|
|
4196
|
+
import { useEffect as useEffect17, useState as useState20 } from "react";
|
|
4197
|
+
import { Fragment as Fragment9, jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
3766
4198
|
function signUpUrlWithInvitation(url, token) {
|
|
3767
4199
|
const [beforeHash, ...hash] = url.split("#");
|
|
3768
4200
|
const base = beforeHash ?? "";
|
|
@@ -3781,18 +4213,18 @@ function AcceptInvitation({
|
|
|
3781
4213
|
style
|
|
3782
4214
|
}) {
|
|
3783
4215
|
const { client, token: session, session: user } = useBase316();
|
|
3784
|
-
const [invitationToken, setInvitationToken] =
|
|
3785
|
-
const [preview, setPreview] =
|
|
3786
|
-
const [state, setState] =
|
|
3787
|
-
const [error, setError] =
|
|
3788
|
-
const [busy, setBusy] =
|
|
3789
|
-
|
|
4216
|
+
const [invitationToken, setInvitationToken] = useState20(supplied ?? null);
|
|
4217
|
+
const [preview, setPreview] = useState20(null);
|
|
4218
|
+
const [state, setState] = useState20("loading");
|
|
4219
|
+
const [error, setError] = useState20(null);
|
|
4220
|
+
const [busy, setBusy] = useState20(false);
|
|
4221
|
+
useEffect17(() => {
|
|
3790
4222
|
if (supplied || typeof window === "undefined") {
|
|
3791
4223
|
return;
|
|
3792
4224
|
}
|
|
3793
4225
|
setInvitationToken(new URL(window.location.href).searchParams.get("invitation"));
|
|
3794
4226
|
}, [supplied]);
|
|
3795
|
-
|
|
4227
|
+
useEffect17(() => {
|
|
3796
4228
|
if (!invitationToken) {
|
|
3797
4229
|
setState(supplied === void 0 ? "loading" : "invalid");
|
|
3798
4230
|
return;
|
|
@@ -3829,42 +4261,42 @@ function AcceptInvitation({
|
|
|
3829
4261
|
}
|
|
3830
4262
|
}
|
|
3831
4263
|
if (state === "loading") {
|
|
3832
|
-
return /* @__PURE__ */
|
|
4264
|
+
return /* @__PURE__ */ jsx25("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
3833
4265
|
}
|
|
3834
4266
|
if (state === "invalid") {
|
|
3835
|
-
return /* @__PURE__ */
|
|
3836
|
-
/* @__PURE__ */
|
|
3837
|
-
/* @__PURE__ */
|
|
4267
|
+
return /* @__PURE__ */ jsxs23("div", { className: cls("b316-card", className), style, children: [
|
|
4268
|
+
/* @__PURE__ */ jsx25("h3", { className: "b316-form-title", children: "That invitation is no longer valid" }),
|
|
4269
|
+
/* @__PURE__ */ jsx25("p", { className: "b316-muted", children: "It may have expired, been withdrawn, or already been used. Ask for a new one." })
|
|
3838
4270
|
] });
|
|
3839
4271
|
}
|
|
3840
4272
|
if (state === "accepted") {
|
|
3841
|
-
return /* @__PURE__ */
|
|
4273
|
+
return /* @__PURE__ */ jsx25("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsxs23("h3", { className: "b316-form-title", children: [
|
|
3842
4274
|
"You have joined ",
|
|
3843
4275
|
preview?.organizationName
|
|
3844
4276
|
] }) });
|
|
3845
4277
|
}
|
|
3846
4278
|
const matches = !user || (user.user.email ?? "").toLowerCase() === preview?.email.toLowerCase();
|
|
3847
|
-
return /* @__PURE__ */
|
|
3848
|
-
/* @__PURE__ */
|
|
4279
|
+
return /* @__PURE__ */ jsxs23("div", { className: cls("b316-card b316-invitation", className), style, children: [
|
|
4280
|
+
/* @__PURE__ */ jsxs23("h3", { className: "b316-form-title", children: [
|
|
3849
4281
|
"Join ",
|
|
3850
4282
|
preview?.organizationName
|
|
3851
4283
|
] }),
|
|
3852
|
-
/* @__PURE__ */
|
|
4284
|
+
/* @__PURE__ */ jsxs23("p", { className: "b316-muted", children: [
|
|
3853
4285
|
"Invited as ",
|
|
3854
4286
|
preview?.email,
|
|
3855
4287
|
" \xB7 ",
|
|
3856
4288
|
preview?.roleName
|
|
3857
4289
|
] }),
|
|
3858
|
-
error ? /* @__PURE__ */
|
|
3859
|
-
!session ? /* @__PURE__ */
|
|
3860
|
-
/* @__PURE__ */
|
|
4290
|
+
error ? /* @__PURE__ */ jsx25("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
4291
|
+
!session ? /* @__PURE__ */ jsxs23(Fragment9, { children: [
|
|
4292
|
+
/* @__PURE__ */ jsxs23("p", { children: [
|
|
3861
4293
|
"Sign in as ",
|
|
3862
4294
|
preview?.email,
|
|
3863
4295
|
" to accept."
|
|
3864
4296
|
] }),
|
|
3865
|
-
/* @__PURE__ */
|
|
3866
|
-
signInUrl ? /* @__PURE__ */
|
|
3867
|
-
signUpUrl ? /* @__PURE__ */
|
|
4297
|
+
/* @__PURE__ */ jsxs23("div", { className: "b316-invitation-actions", children: [
|
|
4298
|
+
signInUrl ? /* @__PURE__ */ jsx25("a", { className: "b316-button", href: signInUrl, children: "Sign in" }) : null,
|
|
4299
|
+
signUpUrl ? /* @__PURE__ */ jsx25(
|
|
3868
4300
|
"a",
|
|
3869
4301
|
{
|
|
3870
4302
|
className: "b316-button-link",
|
|
@@ -3877,20 +4309,20 @@ function AcceptInvitation({
|
|
|
3877
4309
|
// Said before they press anything. The server refuses this, but
|
|
3878
4310
|
// finding out after a click reads as a broken invitation rather than
|
|
3879
4311
|
// as being signed in as the wrong person.
|
|
3880
|
-
/* @__PURE__ */
|
|
4312
|
+
/* @__PURE__ */ jsxs23("p", { children: [
|
|
3881
4313
|
"You are signed in as ",
|
|
3882
4314
|
user?.user.email,
|
|
3883
4315
|
". This invitation was sent to ",
|
|
3884
4316
|
preview?.email,
|
|
3885
4317
|
" \u2014 sign in as that address to accept it."
|
|
3886
4318
|
] })
|
|
3887
|
-
) : /* @__PURE__ */
|
|
4319
|
+
) : /* @__PURE__ */ jsx25("button", { type: "button", className: "b316-button", disabled: busy, onClick: accept, children: busy ? "Joining\u2026" : `Join ${preview?.organizationName}` })
|
|
3888
4320
|
] });
|
|
3889
4321
|
}
|
|
3890
4322
|
|
|
3891
4323
|
// src/PayInvoice.tsx
|
|
3892
|
-
import { useEffect as
|
|
3893
|
-
import { jsx as
|
|
4324
|
+
import { useEffect as useEffect18, useRef as useRef6, useState as useState21 } from "react";
|
|
4325
|
+
import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
3894
4326
|
var STRIPE_SRC = "https://js.stripe.com/v3/";
|
|
3895
4327
|
function loadStripeScript() {
|
|
3896
4328
|
if (typeof window === "undefined") {
|
|
@@ -3922,14 +4354,14 @@ function PayInvoice({
|
|
|
3922
4354
|
style
|
|
3923
4355
|
}) {
|
|
3924
4356
|
const { client } = useBase316();
|
|
3925
|
-
const mountRef =
|
|
3926
|
-
const stripeRef =
|
|
3927
|
-
const elementsRef =
|
|
3928
|
-
const [ready, setReady] =
|
|
3929
|
-
const [paying, setPaying] =
|
|
3930
|
-
const [done, setDone] =
|
|
3931
|
-
const [error, setError] =
|
|
3932
|
-
|
|
4357
|
+
const mountRef = useRef6(null);
|
|
4358
|
+
const stripeRef = useRef6(null);
|
|
4359
|
+
const elementsRef = useRef6(null);
|
|
4360
|
+
const [ready, setReady] = useState21(false);
|
|
4361
|
+
const [paying, setPaying] = useState21(false);
|
|
4362
|
+
const [done, setDone] = useState21(false);
|
|
4363
|
+
const [error, setError] = useState21(null);
|
|
4364
|
+
useEffect18(() => {
|
|
3933
4365
|
let cancelled = false;
|
|
3934
4366
|
async function start() {
|
|
3935
4367
|
const base = `${client.baseUrl}/pay/${encodeURIComponent(environmentId)}/${encodeURIComponent(token)}`;
|
|
@@ -3982,17 +4414,17 @@ function PayInvoice({
|
|
|
3982
4414
|
onPaid?.();
|
|
3983
4415
|
};
|
|
3984
4416
|
if (done) {
|
|
3985
|
-
return /* @__PURE__ */
|
|
4417
|
+
return /* @__PURE__ */ jsx26("div", { className: cls("b316-pay", className), style, children: /* @__PURE__ */ jsx26("p", { className: "b316-pay__done", children: "Paid \u2014 thank you." }) });
|
|
3986
4418
|
}
|
|
3987
|
-
return /* @__PURE__ */
|
|
3988
|
-
error ? /* @__PURE__ */
|
|
3989
|
-
/* @__PURE__ */
|
|
3990
|
-
/* @__PURE__ */
|
|
4419
|
+
return /* @__PURE__ */ jsxs24("form", { className: cls("b316-pay", className), style, onSubmit: submit, children: [
|
|
4420
|
+
error ? /* @__PURE__ */ jsx26("p", { className: "b316-pay__error", role: "alert", children: error }) : null,
|
|
4421
|
+
/* @__PURE__ */ jsx26("div", { ref: mountRef, className: "b316-pay__element" }),
|
|
4422
|
+
/* @__PURE__ */ jsx26("button", { className: "b316-pay__submit", type: "submit", disabled: !ready || paying, children: paying ? "Paying\u2026" : "Pay" })
|
|
3991
4423
|
] });
|
|
3992
4424
|
}
|
|
3993
4425
|
|
|
3994
4426
|
// src/usePaymentLink.ts
|
|
3995
|
-
import { useEffect as
|
|
4427
|
+
import { useEffect as useEffect19, useRef as useRef7, useState as useState22 } from "react";
|
|
3996
4428
|
function usePaymentLink({
|
|
3997
4429
|
token,
|
|
3998
4430
|
environmentId,
|
|
@@ -4000,10 +4432,10 @@ function usePaymentLink({
|
|
|
4000
4432
|
onPaid
|
|
4001
4433
|
}) {
|
|
4002
4434
|
const { client } = useBase316();
|
|
4003
|
-
const [status2, setStatus] =
|
|
4004
|
-
const onPaidRef =
|
|
4435
|
+
const [status2, setStatus] = useState22({ state: "loading" });
|
|
4436
|
+
const onPaidRef = useRef7(onPaid);
|
|
4005
4437
|
onPaidRef.current = onPaid;
|
|
4006
|
-
|
|
4438
|
+
useEffect19(() => {
|
|
4007
4439
|
let stopped = false;
|
|
4008
4440
|
let timer;
|
|
4009
4441
|
const statusUrl = `${client.baseUrl}/pay/${encodeURIComponent(environmentId)}/${encodeURIComponent(token)}/status`;
|
|
@@ -4052,23 +4484,23 @@ function usePaymentLink({
|
|
|
4052
4484
|
}
|
|
4053
4485
|
|
|
4054
4486
|
// src/PricingTable.tsx
|
|
4055
|
-
import { useState as
|
|
4487
|
+
import { useState as useState24 } from "react";
|
|
4056
4488
|
|
|
4057
4489
|
// src/usePlans.ts
|
|
4058
|
-
import { useCallback as useCallback8, useEffect as
|
|
4490
|
+
import { useCallback as useCallback8, useEffect as useEffect20, useState as useState23 } from "react";
|
|
4059
4491
|
var CHECKOUT_STATUSES = /* @__PURE__ */ new Set([402, 409]);
|
|
4060
4492
|
function usePlans(options = {}) {
|
|
4061
4493
|
const { client, token } = useBase316();
|
|
4062
|
-
const [plans, setPlans] =
|
|
4063
|
-
const [error, setError] =
|
|
4064
|
-
const [busyPlanVersionId, setBusy] =
|
|
4065
|
-
const [lastError, setLastError] =
|
|
4066
|
-
const [ownPlanVersionId, setOwnPlanVersionId] =
|
|
4067
|
-
const [managedBy, setManagedBy] =
|
|
4068
|
-
const [reloadCount, setReloadCount] =
|
|
4494
|
+
const [plans, setPlans] = useState23(null);
|
|
4495
|
+
const [error, setError] = useState23(false);
|
|
4496
|
+
const [busyPlanVersionId, setBusy] = useState23(null);
|
|
4497
|
+
const [lastError, setLastError] = useState23(null);
|
|
4498
|
+
const [ownPlanVersionId, setOwnPlanVersionId] = useState23(null);
|
|
4499
|
+
const [managedBy, setManagedBy] = useState23(null);
|
|
4500
|
+
const [reloadCount, setReloadCount] = useState23(0);
|
|
4069
4501
|
const supplied = options.currentPlanVersionId;
|
|
4070
4502
|
const discover = supplied === void 0;
|
|
4071
|
-
|
|
4503
|
+
useEffect20(() => {
|
|
4072
4504
|
let cancelled = false;
|
|
4073
4505
|
client.billing.plans().then((result) => {
|
|
4074
4506
|
if (!cancelled) {
|
|
@@ -4084,7 +4516,7 @@ function usePlans(options = {}) {
|
|
|
4084
4516
|
cancelled = true;
|
|
4085
4517
|
};
|
|
4086
4518
|
}, [client, reloadCount]);
|
|
4087
|
-
|
|
4519
|
+
useEffect20(() => {
|
|
4088
4520
|
if (!token) {
|
|
4089
4521
|
return;
|
|
4090
4522
|
}
|
|
@@ -4173,7 +4605,7 @@ function usePlans(options = {}) {
|
|
|
4173
4605
|
}
|
|
4174
4606
|
|
|
4175
4607
|
// src/PricingTable.tsx
|
|
4176
|
-
import { jsx as
|
|
4608
|
+
import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
4177
4609
|
function formatAmount(amount, currency) {
|
|
4178
4610
|
if (amount === null) return "Free";
|
|
4179
4611
|
const value = Number(amount);
|
|
@@ -4222,7 +4654,7 @@ function PricingTable({
|
|
|
4222
4654
|
managedBy,
|
|
4223
4655
|
selectPlan
|
|
4224
4656
|
} = usePlans({ currentPlanVersionId });
|
|
4225
|
-
const [scheduled, setScheduled] =
|
|
4657
|
+
const [scheduled, setScheduled] = useState24(null);
|
|
4226
4658
|
async function choose(plan) {
|
|
4227
4659
|
if (onSelectPlan) {
|
|
4228
4660
|
await onSelectPlan(plan.planVersionId, plan);
|
|
@@ -4239,50 +4671,50 @@ function PricingTable({
|
|
|
4239
4671
|
}
|
|
4240
4672
|
}
|
|
4241
4673
|
if (error) {
|
|
4242
|
-
return /* @__PURE__ */
|
|
4674
|
+
return /* @__PURE__ */ jsx27("div", { className: cls("b316-card", className), style, children: "Plans are unavailable right now." });
|
|
4243
4675
|
}
|
|
4244
4676
|
if (!plans) {
|
|
4245
|
-
return /* @__PURE__ */
|
|
4677
|
+
return /* @__PURE__ */ jsx27("div", { className: cls("b316-card", className), style, children: "Loading plans\u2026" });
|
|
4246
4678
|
}
|
|
4247
4679
|
if (plans.length === 0) {
|
|
4248
|
-
return /* @__PURE__ */
|
|
4680
|
+
return /* @__PURE__ */ jsx27("div", { className: cls("b316-card", className), style, children: "No plans are published yet." });
|
|
4249
4681
|
}
|
|
4250
4682
|
const anyTrial = plans.some((plan) => Boolean(plan.trialDays));
|
|
4251
4683
|
const anyDescription = plans.some((plan) => Boolean(plan.description));
|
|
4252
4684
|
const anyFeatured = plans.some((plan) => plan.key === featuredPlanKey);
|
|
4253
|
-
return /* @__PURE__ */
|
|
4685
|
+
return /* @__PURE__ */ jsxs25("div", { className: cls("b316-plans", className), style, children: [
|
|
4254
4686
|
managedBy ? (
|
|
4255
4687
|
// A client company's plan comes from the firm that runs it. The table
|
|
4256
4688
|
// still shows what is on offer, with the current plan marked, but
|
|
4257
4689
|
// nothing here can be bought: it would grant this account nothing.
|
|
4258
|
-
/* @__PURE__ */
|
|
4690
|
+
/* @__PURE__ */ jsxs25("div", { className: "b316-plans-managed b316-muted", children: [
|
|
4259
4691
|
"Your plan is provided by ",
|
|
4260
4692
|
managedBy.name ?? "the organization that manages your account",
|
|
4261
4693
|
". Ask them to change it."
|
|
4262
4694
|
] })
|
|
4263
|
-
) : lastError ? /* @__PURE__ */
|
|
4695
|
+
) : lastError ? /* @__PURE__ */ jsx27("div", { className: "b316-plans-error", role: "alert", children: lastError }) : scheduled ? /* @__PURE__ */ jsx27("div", { className: "b316-plans-managed b316-muted", role: "status", children: scheduled }) : null,
|
|
4264
4696
|
plans.map((plan) => {
|
|
4265
4697
|
const base = plan.prices.find((price) => price.featureId === null) ?? plan.prices[0];
|
|
4266
4698
|
const isCurrent = current === plan.planVersionId;
|
|
4267
4699
|
const featured = featuredPlanKey === plan.key;
|
|
4268
|
-
return /* @__PURE__ */
|
|
4700
|
+
return /* @__PURE__ */ jsxs25(
|
|
4269
4701
|
"div",
|
|
4270
4702
|
{
|
|
4271
4703
|
className: featured ? "b316-card b316-plan b316-plan-featured" : "b316-card b316-plan",
|
|
4272
4704
|
children: [
|
|
4273
|
-
/* @__PURE__ */
|
|
4274
|
-
anyFeatured ? /* @__PURE__ */
|
|
4275
|
-
/* @__PURE__ */
|
|
4276
|
-
anyDescription ? /* @__PURE__ */
|
|
4705
|
+
/* @__PURE__ */ jsxs25("div", { className: "b316-plan-head", children: [
|
|
4706
|
+
anyFeatured ? /* @__PURE__ */ jsx27("div", { className: featured ? "b316-plan-badge" : "b316-plan-badge-spacer", children: featured ? "Recommended" : "\xA0" }) : null,
|
|
4707
|
+
/* @__PURE__ */ jsx27("div", { className: "b316-plan-name", children: plan.name }),
|
|
4708
|
+
anyDescription ? /* @__PURE__ */ jsx27("div", { className: "b316-plan-desc", children: plan.description ?? "\xA0" }) : null
|
|
4277
4709
|
] }),
|
|
4278
|
-
/* @__PURE__ */
|
|
4279
|
-
/* @__PURE__ */
|
|
4280
|
-
/* @__PURE__ */
|
|
4281
|
-
anyTrial ? /* @__PURE__ */
|
|
4710
|
+
/* @__PURE__ */ jsxs25("div", { className: "b316-plan-pricing", children: [
|
|
4711
|
+
/* @__PURE__ */ jsx27("div", { className: "b316-plan-price", children: formatAmount(base?.amount ?? null, plan.currency) }),
|
|
4712
|
+
/* @__PURE__ */ jsx27("div", { className: "b316-plan-cadence", children: cadence(plan, base?.amount ?? null) }),
|
|
4713
|
+
anyTrial ? /* @__PURE__ */ jsx27("div", { className: "b316-plan-trial", children: describeTrial(plan, plans) ?? "\xA0" }) : null
|
|
4282
4714
|
] }),
|
|
4283
|
-
/* @__PURE__ */
|
|
4284
|
-
/* @__PURE__ */
|
|
4285
|
-
/* @__PURE__ */
|
|
4715
|
+
/* @__PURE__ */ jsx27("ul", { className: "b316-plan-features", children: plan.entitlements.filter((entitlement) => entitlement.enabled).map((entitlement) => /* @__PURE__ */ jsxs25("li", { className: "b316-plan-feature", children: [
|
|
4716
|
+
/* @__PURE__ */ jsx27("span", { children: entitlement.featureName }),
|
|
4717
|
+
/* @__PURE__ */ jsx27("span", { className: "b316-plan-feature-value", children: entitlement.limit === null ? "Unlimited" : (
|
|
4286
4718
|
// A usage price on the feature makes the limit an
|
|
4287
4719
|
// allowance billed past, not a ceiling — the same
|
|
4288
4720
|
// rule `check()` applies (any non-FLAT price).
|
|
@@ -4291,7 +4723,7 @@ function PricingTable({
|
|
|
4291
4723
|
) ? `${entitlement.limit} included` : entitlement.limit
|
|
4292
4724
|
) })
|
|
4293
4725
|
] }, entitlement.featureId)) }),
|
|
4294
|
-
/* @__PURE__ */
|
|
4726
|
+
/* @__PURE__ */ jsx27("div", { className: "b316-plan-action", children: /* @__PURE__ */ jsx27(
|
|
4295
4727
|
"button",
|
|
4296
4728
|
{
|
|
4297
4729
|
type: "button",
|
|
@@ -4311,16 +4743,104 @@ function PricingTable({
|
|
|
4311
4743
|
] });
|
|
4312
4744
|
}
|
|
4313
4745
|
|
|
4746
|
+
// src/useAddons.ts
|
|
4747
|
+
import { useCallback as useCallback9, useEffect as useEffect21, useState as useState25 } from "react";
|
|
4748
|
+
function codeOf(cause) {
|
|
4749
|
+
const reason = cause?.reason;
|
|
4750
|
+
return typeof reason === "string" ? reason : "request_failed";
|
|
4751
|
+
}
|
|
4752
|
+
function useAddons() {
|
|
4753
|
+
const { client, token } = useBase316();
|
|
4754
|
+
const [attached, setAttached] = useState25(null);
|
|
4755
|
+
const [available, setAvailable] = useState25(null);
|
|
4756
|
+
const [loading2, setLoading] = useState25(true);
|
|
4757
|
+
const [lastError, setLastError] = useState25(null);
|
|
4758
|
+
const [busy, setBusy] = useState25(null);
|
|
4759
|
+
const [reloadCount, setReloadCount] = useState25(0);
|
|
4760
|
+
useEffect21(() => {
|
|
4761
|
+
let cancelled = false;
|
|
4762
|
+
if (!token) {
|
|
4763
|
+
return;
|
|
4764
|
+
}
|
|
4765
|
+
client.billing.addonsForSubscription(token).then((result) => {
|
|
4766
|
+
if (!cancelled) {
|
|
4767
|
+
setAttached(result.attached);
|
|
4768
|
+
setAvailable(result.available);
|
|
4769
|
+
setLastError(null);
|
|
4770
|
+
}
|
|
4771
|
+
}).catch((cause) => {
|
|
4772
|
+
if (!cancelled) {
|
|
4773
|
+
setAttached(null);
|
|
4774
|
+
setAvailable(null);
|
|
4775
|
+
setLastError(codeOf(cause));
|
|
4776
|
+
}
|
|
4777
|
+
}).finally(() => {
|
|
4778
|
+
if (!cancelled) {
|
|
4779
|
+
setLoading(false);
|
|
4780
|
+
}
|
|
4781
|
+
});
|
|
4782
|
+
return () => {
|
|
4783
|
+
cancelled = true;
|
|
4784
|
+
};
|
|
4785
|
+
}, [client, token, reloadCount]);
|
|
4786
|
+
const reload = useCallback9(() => {
|
|
4787
|
+
setLoading(true);
|
|
4788
|
+
setReloadCount((count) => count + 1);
|
|
4789
|
+
}, []);
|
|
4790
|
+
const run = useCallback9(
|
|
4791
|
+
async (key, action) => {
|
|
4792
|
+
if (!token) {
|
|
4793
|
+
setLastError("needs_sign_in");
|
|
4794
|
+
return null;
|
|
4795
|
+
}
|
|
4796
|
+
setBusy(key);
|
|
4797
|
+
setLastError(null);
|
|
4798
|
+
try {
|
|
4799
|
+
const outcome = await action(token);
|
|
4800
|
+
reload();
|
|
4801
|
+
return outcome;
|
|
4802
|
+
} catch (cause) {
|
|
4803
|
+
setLastError(codeOf(cause));
|
|
4804
|
+
return null;
|
|
4805
|
+
} finally {
|
|
4806
|
+
setBusy(null);
|
|
4807
|
+
}
|
|
4808
|
+
},
|
|
4809
|
+
[token, reload]
|
|
4810
|
+
);
|
|
4811
|
+
return {
|
|
4812
|
+
attached,
|
|
4813
|
+
available,
|
|
4814
|
+
loading: Boolean(token) && loading2,
|
|
4815
|
+
lastError,
|
|
4816
|
+
busy,
|
|
4817
|
+
signedIn: Boolean(token),
|
|
4818
|
+
attach: (addonId, quantity) => run(
|
|
4819
|
+
addonId,
|
|
4820
|
+
(session) => client.billing.attachAddon(session, {
|
|
4821
|
+
addonId,
|
|
4822
|
+
...quantity === void 0 ? {} : { quantity }
|
|
4823
|
+
})
|
|
4824
|
+
),
|
|
4825
|
+
setQuantity: (attachmentId, quantity) => run(
|
|
4826
|
+
attachmentId,
|
|
4827
|
+
(session) => client.billing.setAddonQuantity(session, attachmentId, quantity)
|
|
4828
|
+
),
|
|
4829
|
+
remove: (attachmentId) => run(attachmentId, (session) => client.billing.removeAddon(session, attachmentId)),
|
|
4830
|
+
reload
|
|
4831
|
+
};
|
|
4832
|
+
}
|
|
4833
|
+
|
|
4314
4834
|
// src/DataTable.tsx
|
|
4315
4835
|
import { specFor as specFor3 } from "@base316/sdk";
|
|
4316
|
-
import { useState as
|
|
4836
|
+
import { useState as useState29 } from "react";
|
|
4317
4837
|
|
|
4318
4838
|
// src/fields.tsx
|
|
4319
4839
|
import {
|
|
4320
4840
|
formatAddress,
|
|
4321
4841
|
specFor
|
|
4322
4842
|
} from "@base316/sdk";
|
|
4323
|
-
import { jsx as
|
|
4843
|
+
import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
4324
4844
|
function formatNumber(value, fraction = 0) {
|
|
4325
4845
|
const number = Number(value);
|
|
4326
4846
|
return Number.isFinite(number) ? new Intl.NumberFormat(void 0, {
|
|
@@ -4342,10 +4862,10 @@ function formatDuration(value) {
|
|
|
4342
4862
|
}
|
|
4343
4863
|
function FieldCell({ value, field, related }) {
|
|
4344
4864
|
if (field.type === "RELATION") {
|
|
4345
|
-
return related?.title ?? (related?.id ? /* @__PURE__ */
|
|
4865
|
+
return related?.title ?? (related?.id ? /* @__PURE__ */ jsx28("code", { className: "b316-muted", children: related.id }) : "\u2014");
|
|
4346
4866
|
}
|
|
4347
4867
|
if (value === null || value === void 0 || value === "") {
|
|
4348
|
-
return /* @__PURE__ */
|
|
4868
|
+
return /* @__PURE__ */ jsx28("span", { className: "b316-muted", children: "\u2014" });
|
|
4349
4869
|
}
|
|
4350
4870
|
switch (field.type) {
|
|
4351
4871
|
case "BOOLEAN":
|
|
@@ -4358,9 +4878,9 @@ function FieldCell({ value, field, related }) {
|
|
|
4358
4878
|
return formatDuration(value);
|
|
4359
4879
|
case "RATING": {
|
|
4360
4880
|
const stars = Math.round(Number(value));
|
|
4361
|
-
return /* @__PURE__ */
|
|
4881
|
+
return /* @__PURE__ */ jsxs26("span", { "aria-label": `${stars} out of 5`, children: [
|
|
4362
4882
|
"\u2605".repeat(stars),
|
|
4363
|
-
/* @__PURE__ */
|
|
4883
|
+
/* @__PURE__ */ jsx28("span", { className: "b316-muted", children: "\u2605".repeat(Math.max(0, 5 - stars)) })
|
|
4364
4884
|
] });
|
|
4365
4885
|
}
|
|
4366
4886
|
case "DATE":
|
|
@@ -4368,15 +4888,15 @@ function FieldCell({ value, field, related }) {
|
|
|
4368
4888
|
case "DATETIME":
|
|
4369
4889
|
return new Date(String(value)).toLocaleString();
|
|
4370
4890
|
case "SELECT":
|
|
4371
|
-
return /* @__PURE__ */
|
|
4891
|
+
return /* @__PURE__ */ jsx28("span", { className: "b316-chip", children: String(value) });
|
|
4372
4892
|
case "MULTISELECT":
|
|
4373
|
-
return /* @__PURE__ */
|
|
4893
|
+
return /* @__PURE__ */ jsx28("span", { className: "b316-chips", children: (Array.isArray(value) ? value : [value]).map((item) => /* @__PURE__ */ jsx28("span", { className: "b316-chip", children: String(item) }, String(item))) });
|
|
4374
4894
|
case "URL":
|
|
4375
|
-
return /* @__PURE__ */
|
|
4895
|
+
return /* @__PURE__ */ jsx28("a", { href: String(value), target: "_blank", rel: "noreferrer noopener", children: String(value) });
|
|
4376
4896
|
case "EMAIL":
|
|
4377
|
-
return /* @__PURE__ */
|
|
4897
|
+
return /* @__PURE__ */ jsx28("a", { href: `mailto:${String(value)}`, children: String(value) });
|
|
4378
4898
|
case "PHONE":
|
|
4379
|
-
return /* @__PURE__ */
|
|
4899
|
+
return /* @__PURE__ */ jsx28("a", { href: `tel:${String(value)}`, children: String(value) });
|
|
4380
4900
|
case "ADDRESS":
|
|
4381
4901
|
return formatAddress(value);
|
|
4382
4902
|
case "ATTACHMENT": {
|
|
@@ -4388,7 +4908,7 @@ function FieldCell({ value, field, related }) {
|
|
|
4388
4908
|
return text.length > 80 ? `${text.slice(0, 80)}\u2026` : text;
|
|
4389
4909
|
}
|
|
4390
4910
|
case "JSON":
|
|
4391
|
-
return /* @__PURE__ */
|
|
4911
|
+
return /* @__PURE__ */ jsx28("code", { className: "b316-muted", children: JSON.stringify(value).slice(0, 60) });
|
|
4392
4912
|
default:
|
|
4393
4913
|
return String(value);
|
|
4394
4914
|
}
|
|
@@ -4409,7 +4929,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4409
4929
|
function control() {
|
|
4410
4930
|
switch (field.type) {
|
|
4411
4931
|
case "LONGTEXT":
|
|
4412
|
-
return /* @__PURE__ */
|
|
4932
|
+
return /* @__PURE__ */ jsx28(
|
|
4413
4933
|
"textarea",
|
|
4414
4934
|
{
|
|
4415
4935
|
...common,
|
|
@@ -4419,7 +4939,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4419
4939
|
}
|
|
4420
4940
|
);
|
|
4421
4941
|
case "BOOLEAN":
|
|
4422
|
-
return /* @__PURE__ */
|
|
4942
|
+
return /* @__PURE__ */ jsx28(
|
|
4423
4943
|
"input",
|
|
4424
4944
|
{
|
|
4425
4945
|
...common,
|
|
@@ -4430,22 +4950,22 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4430
4950
|
}
|
|
4431
4951
|
);
|
|
4432
4952
|
case "SELECT":
|
|
4433
|
-
return /* @__PURE__ */
|
|
4953
|
+
return /* @__PURE__ */ jsxs26(
|
|
4434
4954
|
"select",
|
|
4435
4955
|
{
|
|
4436
4956
|
...common,
|
|
4437
4957
|
value: value === null || value === void 0 ? "" : String(value),
|
|
4438
4958
|
onChange: (event) => onChange(event.target.value === "" ? null : event.target.value),
|
|
4439
4959
|
children: [
|
|
4440
|
-
field.required ? null : /* @__PURE__ */
|
|
4441
|
-
(field.options ?? []).map((option) => /* @__PURE__ */
|
|
4960
|
+
field.required ? null : /* @__PURE__ */ jsx28("option", { value: "", children: "\u2014" }),
|
|
4961
|
+
(field.options ?? []).map((option) => /* @__PURE__ */ jsx28("option", { value: option, children: option }, option))
|
|
4442
4962
|
]
|
|
4443
4963
|
}
|
|
4444
4964
|
);
|
|
4445
4965
|
case "MULTISELECT": {
|
|
4446
4966
|
const selected = new Set(Array.isArray(value) ? value.map(String) : []);
|
|
4447
|
-
return /* @__PURE__ */
|
|
4448
|
-
/* @__PURE__ */
|
|
4967
|
+
return /* @__PURE__ */ jsx28("div", { className: "b316-choices", children: (field.options ?? []).map((option) => /* @__PURE__ */ jsxs26("label", { className: "b316-choice", children: [
|
|
4968
|
+
/* @__PURE__ */ jsx28(
|
|
4449
4969
|
"input",
|
|
4450
4970
|
{
|
|
4451
4971
|
type: "checkbox",
|
|
@@ -4468,7 +4988,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4468
4988
|
case "NUMBER":
|
|
4469
4989
|
case "MONEY":
|
|
4470
4990
|
case "PERCENT":
|
|
4471
|
-
return /* @__PURE__ */
|
|
4991
|
+
return /* @__PURE__ */ jsx28(
|
|
4472
4992
|
"input",
|
|
4473
4993
|
{
|
|
4474
4994
|
...common,
|
|
@@ -4479,7 +4999,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4479
4999
|
}
|
|
4480
5000
|
);
|
|
4481
5001
|
case "RATING":
|
|
4482
|
-
return /* @__PURE__ */
|
|
5002
|
+
return /* @__PURE__ */ jsx28(
|
|
4483
5003
|
"input",
|
|
4484
5004
|
{
|
|
4485
5005
|
...common,
|
|
@@ -4493,8 +5013,8 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4493
5013
|
);
|
|
4494
5014
|
case "DURATION": {
|
|
4495
5015
|
const minutes = value === null || value === void 0 ? "" : String(Number(value) / 60);
|
|
4496
|
-
return /* @__PURE__ */
|
|
4497
|
-
/* @__PURE__ */
|
|
5016
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-suffixed", children: [
|
|
5017
|
+
/* @__PURE__ */ jsx28(
|
|
4498
5018
|
"input",
|
|
4499
5019
|
{
|
|
4500
5020
|
...common,
|
|
@@ -4504,11 +5024,11 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4504
5024
|
onChange: (event) => onChange(event.target.value === "" ? null : Number(event.target.value) * 60)
|
|
4505
5025
|
}
|
|
4506
5026
|
),
|
|
4507
|
-
/* @__PURE__ */
|
|
5027
|
+
/* @__PURE__ */ jsx28("span", { className: "b316-muted", children: "minutes" })
|
|
4508
5028
|
] });
|
|
4509
5029
|
}
|
|
4510
5030
|
case "DATE":
|
|
4511
|
-
return /* @__PURE__ */
|
|
5031
|
+
return /* @__PURE__ */ jsx28(
|
|
4512
5032
|
"input",
|
|
4513
5033
|
{
|
|
4514
5034
|
...common,
|
|
@@ -4518,7 +5038,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4518
5038
|
}
|
|
4519
5039
|
);
|
|
4520
5040
|
case "DATETIME":
|
|
4521
|
-
return /* @__PURE__ */
|
|
5041
|
+
return /* @__PURE__ */ jsx28(
|
|
4522
5042
|
"input",
|
|
4523
5043
|
{
|
|
4524
5044
|
...common,
|
|
@@ -4531,7 +5051,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4531
5051
|
);
|
|
4532
5052
|
case "ADDRESS": {
|
|
4533
5053
|
const address = value ?? {};
|
|
4534
|
-
const part = (key, label) => /* @__PURE__ */
|
|
5054
|
+
const part = (key, label) => /* @__PURE__ */ jsx28(
|
|
4535
5055
|
"input",
|
|
4536
5056
|
{
|
|
4537
5057
|
className: "b316-input",
|
|
@@ -4543,7 +5063,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4543
5063
|
},
|
|
4544
5064
|
key
|
|
4545
5065
|
);
|
|
4546
|
-
return /* @__PURE__ */
|
|
5066
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-address", children: [
|
|
4547
5067
|
part("line1", "Address line 1"),
|
|
4548
5068
|
part("line2", "Address line 2"),
|
|
4549
5069
|
part("city", "City"),
|
|
@@ -4553,7 +5073,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4553
5073
|
] });
|
|
4554
5074
|
}
|
|
4555
5075
|
case "EMAIL":
|
|
4556
|
-
return /* @__PURE__ */
|
|
5076
|
+
return /* @__PURE__ */ jsx28(
|
|
4557
5077
|
"input",
|
|
4558
5078
|
{
|
|
4559
5079
|
...common,
|
|
@@ -4563,7 +5083,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4563
5083
|
}
|
|
4564
5084
|
);
|
|
4565
5085
|
case "URL":
|
|
4566
|
-
return /* @__PURE__ */
|
|
5086
|
+
return /* @__PURE__ */ jsx28(
|
|
4567
5087
|
"input",
|
|
4568
5088
|
{
|
|
4569
5089
|
...common,
|
|
@@ -4573,7 +5093,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4573
5093
|
}
|
|
4574
5094
|
);
|
|
4575
5095
|
case "PHONE":
|
|
4576
|
-
return /* @__PURE__ */
|
|
5096
|
+
return /* @__PURE__ */ jsx28(
|
|
4577
5097
|
"input",
|
|
4578
5098
|
{
|
|
4579
5099
|
...common,
|
|
@@ -4583,7 +5103,7 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4583
5103
|
}
|
|
4584
5104
|
);
|
|
4585
5105
|
default:
|
|
4586
|
-
return /* @__PURE__ */
|
|
5106
|
+
return /* @__PURE__ */ jsx28(
|
|
4587
5107
|
"input",
|
|
4588
5108
|
{
|
|
4589
5109
|
...common,
|
|
@@ -4594,24 +5114,24 @@ function FieldInput({ value, field, onChange, error, disabled }) {
|
|
|
4594
5114
|
);
|
|
4595
5115
|
}
|
|
4596
5116
|
}
|
|
4597
|
-
return /* @__PURE__ */
|
|
4598
|
-
/* @__PURE__ */
|
|
5117
|
+
return /* @__PURE__ */ jsxs26("div", { className: "b316-field", children: [
|
|
5118
|
+
/* @__PURE__ */ jsxs26("label", { className: "b316-label", htmlFor: id, children: [
|
|
4599
5119
|
field.label,
|
|
4600
|
-
field.required ? /* @__PURE__ */
|
|
5120
|
+
field.required ? /* @__PURE__ */ jsx28("span", { "aria-hidden": "true", children: " *" }) : null
|
|
4601
5121
|
] }),
|
|
4602
5122
|
control(),
|
|
4603
|
-
field.description ? /* @__PURE__ */
|
|
4604
|
-
error ? /* @__PURE__ */
|
|
5123
|
+
field.description ? /* @__PURE__ */ jsx28("div", { className: "b316-hint", children: field.description }) : null,
|
|
5124
|
+
error ? /* @__PURE__ */ jsx28("div", { className: "b316-error", id: described, role: "alert", children: error }) : null
|
|
4605
5125
|
] });
|
|
4606
5126
|
}
|
|
4607
5127
|
|
|
4608
5128
|
// src/RecordForm.tsx
|
|
4609
5129
|
import { specFor as specFor2 } from "@base316/sdk";
|
|
4610
|
-
import { useEffect as
|
|
5130
|
+
import { useEffect as useEffect24, useState as useState28 } from "react";
|
|
4611
5131
|
|
|
4612
5132
|
// src/RelationPicker.tsx
|
|
4613
|
-
import { useEffect as
|
|
4614
|
-
import { Fragment as
|
|
5133
|
+
import { useEffect as useEffect22, useRef as useRef8, useState as useState26 } from "react";
|
|
5134
|
+
import { Fragment as Fragment10, jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
4615
5135
|
function RelationPicker({
|
|
4616
5136
|
field,
|
|
4617
5137
|
value,
|
|
@@ -4621,13 +5141,13 @@ function RelationPicker({
|
|
|
4621
5141
|
tenant
|
|
4622
5142
|
}) {
|
|
4623
5143
|
const { client, token } = useBase316();
|
|
4624
|
-
const [query, setQuery] =
|
|
4625
|
-
const [results, setResults] =
|
|
4626
|
-
const [chosenTitle, setChosenTitle] =
|
|
4627
|
-
const [open, setOpen] =
|
|
5144
|
+
const [query, setQuery] = useState26("");
|
|
5145
|
+
const [results, setResults] = useState26([]);
|
|
5146
|
+
const [chosenTitle, setChosenTitle] = useState26(null);
|
|
5147
|
+
const [open, setOpen] = useState26(false);
|
|
4628
5148
|
const id = `b316-field-${field.key}`;
|
|
4629
|
-
const box =
|
|
4630
|
-
|
|
5149
|
+
const box = useRef8(null);
|
|
5150
|
+
useEffect22(() => {
|
|
4631
5151
|
if (!token || !value || !field.relationTo) {
|
|
4632
5152
|
setChosenTitle(null);
|
|
4633
5153
|
return;
|
|
@@ -4642,7 +5162,7 @@ function RelationPicker({
|
|
|
4642
5162
|
cancelled = true;
|
|
4643
5163
|
};
|
|
4644
5164
|
}, [client, token, value, field.relationTo, tenant]);
|
|
4645
|
-
|
|
5165
|
+
useEffect22(() => {
|
|
4646
5166
|
if (!token || !field.relationTo || !open) {
|
|
4647
5167
|
return;
|
|
4648
5168
|
}
|
|
@@ -4668,7 +5188,7 @@ function RelationPicker({
|
|
|
4668
5188
|
clearTimeout(timer);
|
|
4669
5189
|
};
|
|
4670
5190
|
}, [client, token, field.relationTo, query, open, tenant]);
|
|
4671
|
-
|
|
5191
|
+
useEffect22(() => {
|
|
4672
5192
|
if (!open || typeof document === "undefined") {
|
|
4673
5193
|
return;
|
|
4674
5194
|
}
|
|
@@ -4682,14 +5202,14 @@ function RelationPicker({
|
|
|
4682
5202
|
document.removeEventListener("mousedown", onDocumentClick);
|
|
4683
5203
|
};
|
|
4684
5204
|
}, [open]);
|
|
4685
|
-
return /* @__PURE__ */
|
|
4686
|
-
/* @__PURE__ */
|
|
5205
|
+
return /* @__PURE__ */ jsxs27("div", { className: "b316-field", ref: box, children: [
|
|
5206
|
+
/* @__PURE__ */ jsxs27("label", { className: "b316-label", htmlFor: id, children: [
|
|
4687
5207
|
field.label,
|
|
4688
|
-
field.required ? /* @__PURE__ */
|
|
5208
|
+
field.required ? /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", children: " *" }) : null
|
|
4689
5209
|
] }),
|
|
4690
|
-
value && !open ? /* @__PURE__ */
|
|
4691
|
-
/* @__PURE__ */
|
|
4692
|
-
disabled ? null : /* @__PURE__ */
|
|
5210
|
+
value && !open ? /* @__PURE__ */ jsxs27("div", { className: "b316-relation-chosen", children: [
|
|
5211
|
+
/* @__PURE__ */ jsx29("span", { children: chosenTitle ?? value }),
|
|
5212
|
+
disabled ? null : /* @__PURE__ */ jsx29(
|
|
4693
5213
|
"button",
|
|
4694
5214
|
{
|
|
4695
5215
|
type: "button",
|
|
@@ -4701,7 +5221,7 @@ function RelationPicker({
|
|
|
4701
5221
|
children: "Change"
|
|
4702
5222
|
}
|
|
4703
5223
|
),
|
|
4704
|
-
disabled || field.required ? null : /* @__PURE__ */
|
|
5224
|
+
disabled || field.required ? null : /* @__PURE__ */ jsx29(
|
|
4705
5225
|
"button",
|
|
4706
5226
|
{
|
|
4707
5227
|
type: "button",
|
|
@@ -4711,8 +5231,8 @@ function RelationPicker({
|
|
|
4711
5231
|
children: "Clear"
|
|
4712
5232
|
}
|
|
4713
5233
|
)
|
|
4714
|
-
] }) : /* @__PURE__ */
|
|
4715
|
-
/* @__PURE__ */
|
|
5234
|
+
] }) : /* @__PURE__ */ jsxs27(Fragment10, { children: [
|
|
5235
|
+
/* @__PURE__ */ jsx29(
|
|
4716
5236
|
"input",
|
|
4717
5237
|
{
|
|
4718
5238
|
id,
|
|
@@ -4733,7 +5253,7 @@ function RelationPicker({
|
|
|
4733
5253
|
}
|
|
4734
5254
|
}
|
|
4735
5255
|
),
|
|
4736
|
-
open ? /* @__PURE__ */
|
|
5256
|
+
open ? /* @__PURE__ */ jsx29("ul", { className: "b316-relation-results", id: `${id}-results`, role: "listbox", children: results.length === 0 ? /* @__PURE__ */ jsx29("li", { className: "b316-muted b316-relation-empty", children: "No matches" }) : results.map((result) => /* @__PURE__ */ jsx29("li", { children: /* @__PURE__ */ jsx29(
|
|
4737
5257
|
"button",
|
|
4738
5258
|
{
|
|
4739
5259
|
type: "button",
|
|
@@ -4749,13 +5269,13 @@ function RelationPicker({
|
|
|
4749
5269
|
}
|
|
4750
5270
|
) }, result.id)) }) : null
|
|
4751
5271
|
] }),
|
|
4752
|
-
field.description ? /* @__PURE__ */
|
|
4753
|
-
error ? /* @__PURE__ */
|
|
5272
|
+
field.description ? /* @__PURE__ */ jsx29("div", { className: "b316-hint", children: field.description }) : null,
|
|
5273
|
+
error ? /* @__PURE__ */ jsx29("div", { className: "b316-error", role: "alert", children: error }) : null
|
|
4754
5274
|
] });
|
|
4755
5275
|
}
|
|
4756
5276
|
|
|
4757
5277
|
// src/useCollection.ts
|
|
4758
|
-
import { useCallback as
|
|
5278
|
+
import { useCallback as useCallback10, useEffect as useEffect23, useMemo as useMemo3, useState as useState27 } from "react";
|
|
4759
5279
|
function fieldErrorFrom(cause) {
|
|
4760
5280
|
const param = cause?.param;
|
|
4761
5281
|
const message = cause instanceof Error ? cause.message : "That value was not accepted.";
|
|
@@ -4763,24 +5283,24 @@ function fieldErrorFrom(cause) {
|
|
|
4763
5283
|
}
|
|
4764
5284
|
function useCollection(collection, options = {}) {
|
|
4765
5285
|
const { client, token } = useBase316();
|
|
4766
|
-
const [schema, setSchema] =
|
|
4767
|
-
const [records, setRecords] =
|
|
4768
|
-
const [error, setError] =
|
|
4769
|
-
const [
|
|
4770
|
-
const [total, setTotal] =
|
|
4771
|
-
const [cursor, setCursor] =
|
|
4772
|
-
const [reloadCount, setReloadCount] =
|
|
4773
|
-
const [search, setSearch] =
|
|
4774
|
-
const [filters, setFilters] =
|
|
4775
|
-
const [sort, setSort] =
|
|
5286
|
+
const [schema, setSchema] = useState27(null);
|
|
5287
|
+
const [records, setRecords] = useState27([]);
|
|
5288
|
+
const [error, setError] = useState27(null);
|
|
5289
|
+
const [loading2, setLoading] = useState27(true);
|
|
5290
|
+
const [total, setTotal] = useState27(0);
|
|
5291
|
+
const [cursor, setCursor] = useState27(null);
|
|
5292
|
+
const [reloadCount, setReloadCount] = useState27(0);
|
|
5293
|
+
const [search, setSearch] = useState27("");
|
|
5294
|
+
const [filters, setFilters] = useState27([]);
|
|
5295
|
+
const [sort, setSort] = useState27(
|
|
4776
5296
|
options.sort ?? null
|
|
4777
5297
|
);
|
|
4778
|
-
const [fieldErrors, setFieldErrors] =
|
|
4779
|
-
const [saving, setSaving] =
|
|
5298
|
+
const [fieldErrors, setFieldErrors] = useState27({});
|
|
5299
|
+
const [saving, setSaving] = useState27(false);
|
|
4780
5300
|
const { tenant, limit, recordId } = options;
|
|
4781
5301
|
const fixedFilters = JSON.stringify(options.filters ?? []);
|
|
4782
5302
|
const scope = useMemo3(() => tenant ? { tenant } : void 0, [tenant]);
|
|
4783
|
-
|
|
5303
|
+
useEffect23(() => {
|
|
4784
5304
|
if (!token) {
|
|
4785
5305
|
return;
|
|
4786
5306
|
}
|
|
@@ -4799,7 +5319,7 @@ function useCollection(collection, options = {}) {
|
|
|
4799
5319
|
cancelled = true;
|
|
4800
5320
|
};
|
|
4801
5321
|
}, [client, token, collection, scope]);
|
|
4802
|
-
|
|
5322
|
+
useEffect23(() => {
|
|
4803
5323
|
if (!token || !schema) {
|
|
4804
5324
|
return;
|
|
4805
5325
|
}
|
|
@@ -4869,10 +5389,10 @@ function useCollection(collection, options = {}) {
|
|
|
4869
5389
|
scope,
|
|
4870
5390
|
reloadCount
|
|
4871
5391
|
]);
|
|
4872
|
-
const reload =
|
|
5392
|
+
const reload = useCallback10(() => {
|
|
4873
5393
|
setReloadCount((count) => count + 1);
|
|
4874
5394
|
}, []);
|
|
4875
|
-
const loadMore =
|
|
5395
|
+
const loadMore = useCallback10(() => {
|
|
4876
5396
|
if (!token || !cursor) {
|
|
4877
5397
|
return;
|
|
4878
5398
|
}
|
|
@@ -4896,7 +5416,7 @@ function useCollection(collection, options = {}) {
|
|
|
4896
5416
|
setLoading(false);
|
|
4897
5417
|
});
|
|
4898
5418
|
}, [client, token, collection, cursor, fixedFilters, filters, search, sort, limit, scope]);
|
|
4899
|
-
const toggleSort =
|
|
5419
|
+
const toggleSort = useCallback10((field) => {
|
|
4900
5420
|
setSort((current) => {
|
|
4901
5421
|
if (current?.field !== field) {
|
|
4902
5422
|
return { field, direction: "asc" };
|
|
@@ -4904,7 +5424,7 @@ function useCollection(collection, options = {}) {
|
|
|
4904
5424
|
return current.direction === "asc" ? { field, direction: "desc" } : null;
|
|
4905
5425
|
});
|
|
4906
5426
|
}, []);
|
|
4907
|
-
const create =
|
|
5427
|
+
const create = useCallback10(
|
|
4908
5428
|
async (fields) => {
|
|
4909
5429
|
if (!token) {
|
|
4910
5430
|
return null;
|
|
@@ -4924,7 +5444,7 @@ function useCollection(collection, options = {}) {
|
|
|
4924
5444
|
},
|
|
4925
5445
|
[client, token, collection, scope, reload]
|
|
4926
5446
|
);
|
|
4927
|
-
const update =
|
|
5447
|
+
const update = useCallback10(
|
|
4928
5448
|
async (id, fields) => {
|
|
4929
5449
|
if (!token) {
|
|
4930
5450
|
return null;
|
|
@@ -4946,7 +5466,7 @@ function useCollection(collection, options = {}) {
|
|
|
4946
5466
|
},
|
|
4947
5467
|
[client, token, collection, scope]
|
|
4948
5468
|
);
|
|
4949
|
-
const remove =
|
|
5469
|
+
const remove = useCallback10(
|
|
4950
5470
|
async (id) => {
|
|
4951
5471
|
if (!token) {
|
|
4952
5472
|
return false;
|
|
@@ -4969,7 +5489,7 @@ function useCollection(collection, options = {}) {
|
|
|
4969
5489
|
return {
|
|
4970
5490
|
schema,
|
|
4971
5491
|
records,
|
|
4972
|
-
loading,
|
|
5492
|
+
loading: loading2,
|
|
4973
5493
|
error,
|
|
4974
5494
|
total,
|
|
4975
5495
|
hasMore: cursor !== null,
|
|
@@ -4991,7 +5511,7 @@ function useCollection(collection, options = {}) {
|
|
|
4991
5511
|
}
|
|
4992
5512
|
|
|
4993
5513
|
// src/RecordForm.tsx
|
|
4994
|
-
import { jsx as
|
|
5514
|
+
import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
4995
5515
|
function RecordForm({
|
|
4996
5516
|
collection,
|
|
4997
5517
|
recordId,
|
|
@@ -5012,20 +5532,20 @@ function RecordForm({
|
|
|
5012
5532
|
recordId
|
|
5013
5533
|
}
|
|
5014
5534
|
);
|
|
5015
|
-
const [values, setValues] =
|
|
5016
|
-
const [loaded, setLoaded] =
|
|
5535
|
+
const [values, setValues] = useState28(defaults ?? {});
|
|
5536
|
+
const [loaded, setLoaded] = useState28(!recordId);
|
|
5017
5537
|
const existing = recordId ? records.find((record) => record.id === recordId) : void 0;
|
|
5018
|
-
|
|
5538
|
+
useEffect24(() => {
|
|
5019
5539
|
if (existing && !loaded) {
|
|
5020
5540
|
setValues(existing.fields);
|
|
5021
5541
|
setLoaded(true);
|
|
5022
5542
|
}
|
|
5023
5543
|
}, [existing, loaded]);
|
|
5024
5544
|
if (error) {
|
|
5025
|
-
return /* @__PURE__ */
|
|
5545
|
+
return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx30("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5026
5546
|
}
|
|
5027
5547
|
if (!schema || !loaded) {
|
|
5028
|
-
return /* @__PURE__ */
|
|
5548
|
+
return /* @__PURE__ */ jsx30("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5029
5549
|
}
|
|
5030
5550
|
const editable = schema.fields.filter((field) => !specFor2(field).computed);
|
|
5031
5551
|
async function submit(event) {
|
|
@@ -5035,11 +5555,11 @@ function RecordForm({
|
|
|
5035
5555
|
onSaved?.(saved.id);
|
|
5036
5556
|
}
|
|
5037
5557
|
}
|
|
5038
|
-
return /* @__PURE__ */
|
|
5039
|
-
/* @__PURE__ */
|
|
5040
|
-
fieldErrors._ ? /* @__PURE__ */
|
|
5558
|
+
return /* @__PURE__ */ jsxs28("form", { className: cls("b316-card b316-form", className), style, onSubmit: submit, children: [
|
|
5559
|
+
/* @__PURE__ */ jsx30("h3", { className: "b316-form-title", children: recordId ? `Edit ${schema.name.toLowerCase()}` : `New ${schema.name.toLowerCase()}` }),
|
|
5560
|
+
fieldErrors._ ? /* @__PURE__ */ jsx30("div", { className: "b316-error", role: "alert", children: fieldErrors._ }) : null,
|
|
5041
5561
|
editable.map(
|
|
5042
|
-
(field) => field.type === "RELATION" ? /* @__PURE__ */
|
|
5562
|
+
(field) => field.type === "RELATION" ? /* @__PURE__ */ jsx30(
|
|
5043
5563
|
RelationPicker,
|
|
5044
5564
|
{
|
|
5045
5565
|
field,
|
|
@@ -5050,7 +5570,7 @@ function RecordForm({
|
|
|
5050
5570
|
onChange: (next) => setValues((current) => ({ ...current, [field.key]: next }))
|
|
5051
5571
|
},
|
|
5052
5572
|
field.key
|
|
5053
|
-
) : /* @__PURE__ */
|
|
5573
|
+
) : /* @__PURE__ */ jsx30(
|
|
5054
5574
|
FieldInput,
|
|
5055
5575
|
{
|
|
5056
5576
|
field,
|
|
@@ -5062,15 +5582,15 @@ function RecordForm({
|
|
|
5062
5582
|
field.key
|
|
5063
5583
|
)
|
|
5064
5584
|
),
|
|
5065
|
-
/* @__PURE__ */
|
|
5066
|
-
onCancel ? /* @__PURE__ */
|
|
5067
|
-
/* @__PURE__ */
|
|
5585
|
+
/* @__PURE__ */ jsxs28("div", { className: "b316-form-actions", children: [
|
|
5586
|
+
onCancel ? /* @__PURE__ */ jsx30("button", { type: "button", className: "b316-button-quiet", onClick: onCancel, disabled: saving, children: "Cancel" }) : null,
|
|
5587
|
+
/* @__PURE__ */ jsx30("button", { type: "submit", className: "b316-button", disabled: saving, children: saving ? "Saving\u2026" : "Save" })
|
|
5068
5588
|
] })
|
|
5069
5589
|
] });
|
|
5070
5590
|
}
|
|
5071
5591
|
|
|
5072
5592
|
// src/DataTable.tsx
|
|
5073
|
-
import { jsx as
|
|
5593
|
+
import { jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
5074
5594
|
function DataTable({
|
|
5075
5595
|
collection,
|
|
5076
5596
|
columns,
|
|
@@ -5087,7 +5607,7 @@ function DataTable({
|
|
|
5087
5607
|
const {
|
|
5088
5608
|
schema,
|
|
5089
5609
|
records,
|
|
5090
|
-
loading,
|
|
5610
|
+
loading: loading2,
|
|
5091
5611
|
error,
|
|
5092
5612
|
total,
|
|
5093
5613
|
hasMore,
|
|
@@ -5099,13 +5619,13 @@ function DataTable({
|
|
|
5099
5619
|
loadMore,
|
|
5100
5620
|
remove
|
|
5101
5621
|
} = useCollection(collection, options);
|
|
5102
|
-
const [editing, setEditing] =
|
|
5103
|
-
const [removeFailed, setRemoveFailed] =
|
|
5622
|
+
const [editing, setEditing] = useState29(null);
|
|
5623
|
+
const [removeFailed, setRemoveFailed] = useState29(null);
|
|
5104
5624
|
if (error) {
|
|
5105
|
-
return /* @__PURE__ */
|
|
5625
|
+
return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx31("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5106
5626
|
}
|
|
5107
5627
|
if (!schema) {
|
|
5108
|
-
return /* @__PURE__ */
|
|
5628
|
+
return /* @__PURE__ */ jsx31("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5109
5629
|
}
|
|
5110
5630
|
const shown = columns ? (
|
|
5111
5631
|
// Ordered by what was asked for, not by the schema: a caller naming
|
|
@@ -5114,10 +5634,10 @@ function DataTable({
|
|
|
5114
5634
|
) : schema.fields;
|
|
5115
5635
|
const searchable = schema.fields.some((field) => specFor3(field).capabilities.searchable);
|
|
5116
5636
|
const writable = canWrite && !readOnly;
|
|
5117
|
-
return /* @__PURE__ */
|
|
5118
|
-
removeFailed ? /* @__PURE__ */
|
|
5119
|
-
/* @__PURE__ */
|
|
5120
|
-
searchable && !hideSearch ? /* @__PURE__ */
|
|
5637
|
+
return /* @__PURE__ */ jsxs29("div", { className: cls("b316-table-wrap", className), style, children: [
|
|
5638
|
+
removeFailed ? /* @__PURE__ */ jsx31("div", { className: "b316-error", role: "alert", children: removeFailed }) : null,
|
|
5639
|
+
/* @__PURE__ */ jsxs29("div", { className: "b316-table-bar", children: [
|
|
5640
|
+
searchable && !hideSearch ? /* @__PURE__ */ jsx31(
|
|
5121
5641
|
"input",
|
|
5122
5642
|
{
|
|
5123
5643
|
type: "search",
|
|
@@ -5127,25 +5647,25 @@ function DataTable({
|
|
|
5127
5647
|
value: search,
|
|
5128
5648
|
onChange: (event) => setSearch(event.target.value)
|
|
5129
5649
|
}
|
|
5130
|
-
) : /* @__PURE__ */
|
|
5131
|
-
/* @__PURE__ */
|
|
5132
|
-
/* @__PURE__ */
|
|
5650
|
+
) : /* @__PURE__ */ jsx31("span", {}),
|
|
5651
|
+
/* @__PURE__ */ jsxs29("div", { className: "b316-table-actions", children: [
|
|
5652
|
+
/* @__PURE__ */ jsxs29("span", { className: "b316-muted", children: [
|
|
5133
5653
|
total,
|
|
5134
5654
|
" ",
|
|
5135
5655
|
total === 1 ? schema.name.toLowerCase() : schema.namePlural.toLowerCase()
|
|
5136
5656
|
] }),
|
|
5137
|
-
writable ? /* @__PURE__ */
|
|
5657
|
+
writable ? /* @__PURE__ */ jsxs29("button", { type: "button", className: "b316-button", onClick: () => setEditing("new"), children: [
|
|
5138
5658
|
"New ",
|
|
5139
5659
|
schema.name.toLowerCase()
|
|
5140
5660
|
] }) : null
|
|
5141
5661
|
] })
|
|
5142
5662
|
] }),
|
|
5143
|
-
/* @__PURE__ */
|
|
5144
|
-
/* @__PURE__ */
|
|
5663
|
+
/* @__PURE__ */ jsx31("div", { className: "b316-table-scroll", children: /* @__PURE__ */ jsxs29("table", { className: "b316-table", children: [
|
|
5664
|
+
/* @__PURE__ */ jsx31("thead", { children: /* @__PURE__ */ jsxs29("tr", { children: [
|
|
5145
5665
|
shown.map((field) => {
|
|
5146
5666
|
const sortable = specFor3(field).capabilities.sortable;
|
|
5147
5667
|
const active = sort?.field === field.key;
|
|
5148
|
-
return /* @__PURE__ */
|
|
5668
|
+
return /* @__PURE__ */ jsx31("th", { scope: "col", "aria-sort": ariaSort(active, sort?.direction), children: sortable ? /* @__PURE__ */ jsxs29(
|
|
5149
5669
|
"button",
|
|
5150
5670
|
{
|
|
5151
5671
|
type: "button",
|
|
@@ -5153,20 +5673,20 @@ function DataTable({
|
|
|
5153
5673
|
onClick: () => toggleSort(field.key),
|
|
5154
5674
|
children: [
|
|
5155
5675
|
field.label,
|
|
5156
|
-
/* @__PURE__ */
|
|
5676
|
+
/* @__PURE__ */ jsx31("span", { "aria-hidden": "true", children: active ? sort?.direction === "desc" ? " \u2193" : " \u2191" : " \u2195" })
|
|
5157
5677
|
]
|
|
5158
5678
|
}
|
|
5159
5679
|
) : field.label }, field.key);
|
|
5160
5680
|
}),
|
|
5161
|
-
writable ? /* @__PURE__ */
|
|
5681
|
+
writable ? /* @__PURE__ */ jsx31("th", { scope: "col", className: "b316-table-rowactions" }) : null
|
|
5162
5682
|
] }) }),
|
|
5163
|
-
/* @__PURE__ */
|
|
5683
|
+
/* @__PURE__ */ jsx31("tbody", { children: records.map((record) => /* @__PURE__ */ jsxs29(
|
|
5164
5684
|
"tr",
|
|
5165
5685
|
{
|
|
5166
5686
|
className: onSelect ? "b316-row-clickable" : void 0,
|
|
5167
5687
|
onClick: onSelect ? () => onSelect(record) : void 0,
|
|
5168
5688
|
children: [
|
|
5169
|
-
shown.map((field) => /* @__PURE__ */
|
|
5689
|
+
shown.map((field) => /* @__PURE__ */ jsx31("td", { children: renderCell?.(record, field) ?? /* @__PURE__ */ jsx31(
|
|
5170
5690
|
FieldCell,
|
|
5171
5691
|
{
|
|
5172
5692
|
value: record.fields[field.key] ?? null,
|
|
@@ -5174,8 +5694,8 @@ function DataTable({
|
|
|
5174
5694
|
related: record.related[field.key]
|
|
5175
5695
|
}
|
|
5176
5696
|
) }, field.key)),
|
|
5177
|
-
writable ? /* @__PURE__ */
|
|
5178
|
-
/* @__PURE__ */
|
|
5697
|
+
writable ? /* @__PURE__ */ jsxs29("td", { className: "b316-table-rowactions", children: [
|
|
5698
|
+
/* @__PURE__ */ jsx31(
|
|
5179
5699
|
"button",
|
|
5180
5700
|
{
|
|
5181
5701
|
type: "button",
|
|
@@ -5187,7 +5707,7 @@ function DataTable({
|
|
|
5187
5707
|
children: "Edit"
|
|
5188
5708
|
}
|
|
5189
5709
|
),
|
|
5190
|
-
/* @__PURE__ */
|
|
5710
|
+
/* @__PURE__ */ jsx31(
|
|
5191
5711
|
ConfirmButton,
|
|
5192
5712
|
{
|
|
5193
5713
|
className: "b316-button-quiet b316-danger",
|
|
@@ -5211,10 +5731,10 @@ function DataTable({
|
|
|
5211
5731
|
record.id
|
|
5212
5732
|
)) })
|
|
5213
5733
|
] }) }),
|
|
5214
|
-
records.length === 0 && !
|
|
5215
|
-
|
|
5216
|
-
hasMore ? /* @__PURE__ */
|
|
5217
|
-
editing ? /* @__PURE__ */
|
|
5734
|
+
records.length === 0 && !loading2 ? /* @__PURE__ */ jsx31("div", { className: "b316-empty", children: emptyState ?? `No ${schema.namePlural.toLowerCase()} yet.` }) : null,
|
|
5735
|
+
loading2 ? /* @__PURE__ */ jsx31("div", { className: "b316-empty", children: "Loading\u2026" }) : null,
|
|
5736
|
+
hasMore ? /* @__PURE__ */ jsx31("div", { className: "b316-table-more", children: /* @__PURE__ */ jsx31("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading2, children: "Load more" }) }) : null,
|
|
5737
|
+
editing ? /* @__PURE__ */ jsx31(
|
|
5218
5738
|
RecordForm,
|
|
5219
5739
|
{
|
|
5220
5740
|
collection,
|
|
@@ -5242,8 +5762,8 @@ import {
|
|
|
5242
5762
|
specFor as specFor4,
|
|
5243
5763
|
titleFieldOf
|
|
5244
5764
|
} from "@base316/sdk";
|
|
5245
|
-
import { useState as
|
|
5246
|
-
import { jsx as
|
|
5765
|
+
import { useState as useState30 } from "react";
|
|
5766
|
+
import { jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
5247
5767
|
function Kanban({
|
|
5248
5768
|
collection,
|
|
5249
5769
|
groupBy,
|
|
@@ -5254,23 +5774,23 @@ function Kanban({
|
|
|
5254
5774
|
style,
|
|
5255
5775
|
...options
|
|
5256
5776
|
}) {
|
|
5257
|
-
const { schema, records, loading, error, canWrite, update, total, hasMore, loadMore } = useCollection(collection, {
|
|
5777
|
+
const { schema, records, loading: loading2, error, canWrite, update, total, hasMore, loadMore } = useCollection(collection, {
|
|
5258
5778
|
// A board shows everything at once by its nature — a column holding the
|
|
5259
5779
|
// first twenty-five of two hundred is misleading rather than partial.
|
|
5260
5780
|
limit: options.limit ?? 100,
|
|
5261
5781
|
...options
|
|
5262
5782
|
});
|
|
5263
|
-
const [dragging, setDragging] =
|
|
5264
|
-
const [over, setOver] =
|
|
5783
|
+
const [dragging, setDragging] = useState30(null);
|
|
5784
|
+
const [over, setOver] = useState30(null);
|
|
5265
5785
|
if (error) {
|
|
5266
|
-
return /* @__PURE__ */
|
|
5786
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx32("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5267
5787
|
}
|
|
5268
5788
|
if (!schema) {
|
|
5269
|
-
return /* @__PURE__ */
|
|
5789
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5270
5790
|
}
|
|
5271
5791
|
const field = groupBy ? schema.fields.find((candidate) => candidate.key === groupBy) ?? null : defaultGroupFieldOf(schema.fields);
|
|
5272
5792
|
if (!field || !specFor4(field).capabilities.groupable) {
|
|
5273
|
-
return /* @__PURE__ */
|
|
5793
|
+
return /* @__PURE__ */ jsx32("div", { className: cls("b316-card", className), style, children: groupBy ? `"${groupBy}" cannot make columns. A board groups by a choice, a yes/no or a date.` : `${schema.namePlural} have no field to group by. Add a choice field \u2014 a status or a stage \u2014 and this board will use it.` });
|
|
5274
5794
|
}
|
|
5275
5795
|
const columns = columnsFor(field);
|
|
5276
5796
|
const shown = cardFields ? cardFields.map((key) => schema.fields.find((candidate) => candidate.key === key)).filter((candidate) => Boolean(candidate)) : (
|
|
@@ -5287,12 +5807,12 @@ function Kanban({
|
|
|
5287
5807
|
}
|
|
5288
5808
|
await update(record.id, { [field.key]: value });
|
|
5289
5809
|
}
|
|
5290
|
-
return /* @__PURE__ */
|
|
5291
|
-
/* @__PURE__ */
|
|
5810
|
+
return /* @__PURE__ */ jsxs30("div", { className: cls("b316-board-wrap", className), style, children: [
|
|
5811
|
+
/* @__PURE__ */ jsx32("div", { className: "b316-board", role: "list", children: columns.map((column) => {
|
|
5292
5812
|
const inColumn = records.filter(
|
|
5293
5813
|
(record) => String(record.fields[field.key] ?? "") === String(column.value ?? "")
|
|
5294
5814
|
);
|
|
5295
|
-
return /* @__PURE__ */
|
|
5815
|
+
return /* @__PURE__ */ jsxs30(
|
|
5296
5816
|
"section",
|
|
5297
5817
|
{
|
|
5298
5818
|
className: over === String(column.value) ? "b316-board-column b316-board-over" : "b316-board-column",
|
|
@@ -5316,12 +5836,12 @@ function Kanban({
|
|
|
5316
5836
|
setDragging(null);
|
|
5317
5837
|
},
|
|
5318
5838
|
children: [
|
|
5319
|
-
/* @__PURE__ */
|
|
5320
|
-
/* @__PURE__ */
|
|
5321
|
-
/* @__PURE__ */
|
|
5839
|
+
/* @__PURE__ */ jsxs30("header", { className: "b316-board-head", children: [
|
|
5840
|
+
/* @__PURE__ */ jsx32("span", { className: "b316-board-title", children: column.label }),
|
|
5841
|
+
/* @__PURE__ */ jsx32("span", { className: "b316-muted", children: inColumn.length })
|
|
5322
5842
|
] }),
|
|
5323
|
-
/* @__PURE__ */
|
|
5324
|
-
inColumn.map((record) => /* @__PURE__ */
|
|
5843
|
+
/* @__PURE__ */ jsxs30("div", { className: "b316-board-cards", children: [
|
|
5844
|
+
inColumn.map((record) => /* @__PURE__ */ jsxs30(
|
|
5325
5845
|
"article",
|
|
5326
5846
|
{
|
|
5327
5847
|
className: "b316-board-card",
|
|
@@ -5333,10 +5853,10 @@ function Kanban({
|
|
|
5333
5853
|
},
|
|
5334
5854
|
onClick: onSelect ? () => onSelect(record) : void 0,
|
|
5335
5855
|
children: [
|
|
5336
|
-
/* @__PURE__ */
|
|
5337
|
-
shown.map((candidate) => /* @__PURE__ */
|
|
5338
|
-
/* @__PURE__ */
|
|
5339
|
-
/* @__PURE__ */
|
|
5856
|
+
/* @__PURE__ */ jsx32("div", { className: "b316-board-card-title", children: record.title ?? "Untitled" }),
|
|
5857
|
+
shown.map((candidate) => /* @__PURE__ */ jsxs30("div", { className: "b316-board-card-field", children: [
|
|
5858
|
+
/* @__PURE__ */ jsx32("span", { className: "b316-muted", children: candidate.label }),
|
|
5859
|
+
/* @__PURE__ */ jsx32(
|
|
5340
5860
|
FieldCell,
|
|
5341
5861
|
{
|
|
5342
5862
|
value: record.fields[candidate.key] ?? null,
|
|
@@ -5349,9 +5869,9 @@ function Kanban({
|
|
|
5349
5869
|
// Dragging is not reachable by keyboard and is awkward on a
|
|
5350
5870
|
// phone. This is the same action by other means, not a
|
|
5351
5871
|
// lesser fallback.
|
|
5352
|
-
/* @__PURE__ */
|
|
5353
|
-
/* @__PURE__ */
|
|
5354
|
-
/* @__PURE__ */
|
|
5872
|
+
/* @__PURE__ */ jsxs30("label", { className: "b316-board-move", children: [
|
|
5873
|
+
/* @__PURE__ */ jsx32("span", { className: "b316-muted", children: "Move to" }),
|
|
5874
|
+
/* @__PURE__ */ jsx32(
|
|
5355
5875
|
"select",
|
|
5356
5876
|
{
|
|
5357
5877
|
className: "b316-input",
|
|
@@ -5363,7 +5883,7 @@ function Kanban({
|
|
|
5363
5883
|
);
|
|
5364
5884
|
void move(record, chosen?.value ?? null);
|
|
5365
5885
|
},
|
|
5366
|
-
children: columns.map((candidate) => /* @__PURE__ */
|
|
5886
|
+
children: columns.map((candidate) => /* @__PURE__ */ jsx32("option", { value: String(candidate.value), children: candidate.label }, String(candidate.value)))
|
|
5367
5887
|
}
|
|
5368
5888
|
)
|
|
5369
5889
|
] })
|
|
@@ -5372,14 +5892,14 @@ function Kanban({
|
|
|
5372
5892
|
},
|
|
5373
5893
|
record.id
|
|
5374
5894
|
)),
|
|
5375
|
-
inColumn.length === 0 ? /* @__PURE__ */
|
|
5895
|
+
inColumn.length === 0 ? /* @__PURE__ */ jsx32("div", { className: "b316-board-empty", children: emptyState ?? "Nothing here" }) : null
|
|
5376
5896
|
] })
|
|
5377
5897
|
]
|
|
5378
5898
|
},
|
|
5379
5899
|
String(column.value)
|
|
5380
5900
|
);
|
|
5381
5901
|
}) }),
|
|
5382
|
-
hasMore ? /* @__PURE__ */
|
|
5902
|
+
hasMore ? /* @__PURE__ */ jsx32("div", { className: "b316-table-more", children: /* @__PURE__ */ jsxs30("button", { type: "button", className: "b316-button-quiet", onClick: loadMore, disabled: loading2, children: [
|
|
5383
5903
|
"Showing ",
|
|
5384
5904
|
records.length,
|
|
5385
5905
|
" of ",
|
|
@@ -5406,7 +5926,7 @@ import {
|
|
|
5406
5926
|
specFor as specFor5
|
|
5407
5927
|
} from "@base316/sdk";
|
|
5408
5928
|
import { useMemo as useMemo4 } from "react";
|
|
5409
|
-
import { jsx as
|
|
5929
|
+
import { jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5410
5930
|
function Chart({
|
|
5411
5931
|
collection,
|
|
5412
5932
|
x,
|
|
@@ -5419,7 +5939,7 @@ function Chart({
|
|
|
5419
5939
|
style,
|
|
5420
5940
|
...options
|
|
5421
5941
|
}) {
|
|
5422
|
-
const { schema, records, error, loading } = useCollection(collection, {
|
|
5942
|
+
const { schema, records, error, loading: loading2 } = useCollection(collection, {
|
|
5423
5943
|
// A chart of one page is a chart of an arbitrary subset, which is worse
|
|
5424
5944
|
// than no chart: it looks like an answer.
|
|
5425
5945
|
limit: options.limit ?? 200,
|
|
@@ -5445,23 +5965,23 @@ function Chart({
|
|
|
5445
5965
|
[records, axis, measure, aggregate, bucket, y]
|
|
5446
5966
|
);
|
|
5447
5967
|
if (error) {
|
|
5448
|
-
return /* @__PURE__ */
|
|
5968
|
+
return /* @__PURE__ */ jsx33("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx33("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5449
5969
|
}
|
|
5450
|
-
if (!schema ||
|
|
5451
|
-
return /* @__PURE__ */
|
|
5970
|
+
if (!schema || loading2) {
|
|
5971
|
+
return /* @__PURE__ */ jsx33("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5452
5972
|
}
|
|
5453
5973
|
if (!axis) {
|
|
5454
|
-
return /* @__PURE__ */
|
|
5974
|
+
return /* @__PURE__ */ jsx33("div", { className: cls("b316-card", className), style, children: x ? `"${x}" is not a date, so it cannot be a time axis.` : `${schema.namePlural} have no date field to chart against. Add one and this chart will use it.` });
|
|
5455
5975
|
}
|
|
5456
5976
|
if (y && !measure) {
|
|
5457
|
-
return /* @__PURE__ */
|
|
5977
|
+
return /* @__PURE__ */ jsx33("div", { className: cls("b316-card", className), style, children: `"${y}" cannot be ${aggregate === "avg" ? "averaged" : `combined with ${aggregate}`}.` });
|
|
5458
5978
|
}
|
|
5459
5979
|
const peak = Math.max(...buckets.map((entry) => entry.value), 0);
|
|
5460
5980
|
const heading = title ?? `${measure ? `${aggregate} of ${measure.label}` : schema.namePlural} by ${axis.label}`;
|
|
5461
|
-
return /* @__PURE__ */
|
|
5462
|
-
/* @__PURE__ */
|
|
5463
|
-
buckets.length === 0 || peak === 0 ? /* @__PURE__ */
|
|
5464
|
-
/* @__PURE__ */
|
|
5981
|
+
return /* @__PURE__ */ jsxs31("figure", { className: cls("b316-card b316-chart", className), style, children: [
|
|
5982
|
+
/* @__PURE__ */ jsx33("figcaption", { className: "b316-chart-title", children: heading }),
|
|
5983
|
+
buckets.length === 0 || peak === 0 ? /* @__PURE__ */ jsx33("div", { className: "b316-empty", children: "Nothing to chart yet." }) : /* @__PURE__ */ jsx33("div", { className: "b316-chart-plot", style: { height }, children: buckets.map((entry) => /* @__PURE__ */ jsxs31("div", { className: "b316-chart-col", children: [
|
|
5984
|
+
/* @__PURE__ */ jsx33(
|
|
5465
5985
|
"div",
|
|
5466
5986
|
{
|
|
5467
5987
|
className: "b316-chart-bar",
|
|
@@ -5469,18 +5989,18 @@ function Chart({
|
|
|
5469
5989
|
title: `${entry.label}: ${format(entry.value)}`
|
|
5470
5990
|
}
|
|
5471
5991
|
),
|
|
5472
|
-
/* @__PURE__ */
|
|
5992
|
+
/* @__PURE__ */ jsx33("span", { className: "b316-chart-label", children: entry.label })
|
|
5473
5993
|
] }, entry.key)) }),
|
|
5474
|
-
/* @__PURE__ */
|
|
5475
|
-
/* @__PURE__ */
|
|
5476
|
-
/* @__PURE__ */
|
|
5477
|
-
/* @__PURE__ */
|
|
5478
|
-
/* @__PURE__ */
|
|
5479
|
-
/* @__PURE__ */
|
|
5994
|
+
/* @__PURE__ */ jsxs31("details", { className: "b316-chart-data", children: [
|
|
5995
|
+
/* @__PURE__ */ jsx33("summary", { children: "Values" }),
|
|
5996
|
+
/* @__PURE__ */ jsxs31("table", { className: "b316-table", children: [
|
|
5997
|
+
/* @__PURE__ */ jsx33("thead", { children: /* @__PURE__ */ jsxs31("tr", { children: [
|
|
5998
|
+
/* @__PURE__ */ jsx33("th", { scope: "col", children: axis.label }),
|
|
5999
|
+
/* @__PURE__ */ jsx33("th", { scope: "col", children: measure ? measure.label : "Count" })
|
|
5480
6000
|
] }) }),
|
|
5481
|
-
/* @__PURE__ */
|
|
5482
|
-
/* @__PURE__ */
|
|
5483
|
-
/* @__PURE__ */
|
|
6001
|
+
/* @__PURE__ */ jsx33("tbody", { children: buckets.map((entry) => /* @__PURE__ */ jsxs31("tr", { children: [
|
|
6002
|
+
/* @__PURE__ */ jsx33("td", { children: entry.label }),
|
|
6003
|
+
/* @__PURE__ */ jsx33("td", { children: format(entry.value) })
|
|
5484
6004
|
] }, entry.key)) })
|
|
5485
6005
|
] })
|
|
5486
6006
|
] })
|
|
@@ -5539,8 +6059,8 @@ function combine(values, aggregate) {
|
|
|
5539
6059
|
|
|
5540
6060
|
// src/RecordDetail.tsx
|
|
5541
6061
|
import { specFor as specFor6 } from "@base316/sdk";
|
|
5542
|
-
import { useState as
|
|
5543
|
-
import { jsx as
|
|
6062
|
+
import { useState as useState31 } from "react";
|
|
6063
|
+
import { jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
5544
6064
|
function RecordDetail({
|
|
5545
6065
|
collection,
|
|
5546
6066
|
recordId,
|
|
@@ -5552,27 +6072,27 @@ function RecordDetail({
|
|
|
5552
6072
|
className,
|
|
5553
6073
|
style
|
|
5554
6074
|
}) {
|
|
5555
|
-
const { schema, records, canWrite, remove, loading, error } = useCollection(collection, {
|
|
6075
|
+
const { schema, records, canWrite, remove, loading: loading2, error } = useCollection(collection, {
|
|
5556
6076
|
tenant,
|
|
5557
6077
|
recordId
|
|
5558
6078
|
});
|
|
5559
|
-
const [editing, setEditing] =
|
|
6079
|
+
const [editing, setEditing] = useState31(false);
|
|
5560
6080
|
const record = records.find((candidate) => candidate.id === recordId);
|
|
5561
6081
|
if (error) {
|
|
5562
|
-
return /* @__PURE__ */
|
|
6082
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx34("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5563
6083
|
}
|
|
5564
|
-
if (!schema ||
|
|
5565
|
-
return /* @__PURE__ */
|
|
6084
|
+
if (!schema || loading2) {
|
|
6085
|
+
return /* @__PURE__ */ jsx34("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5566
6086
|
}
|
|
5567
6087
|
if (!record) {
|
|
5568
|
-
return /* @__PURE__ */
|
|
6088
|
+
return /* @__PURE__ */ jsxs32("div", { className: cls("b316-card", className), style, children: [
|
|
5569
6089
|
"That ",
|
|
5570
6090
|
schema.name.toLowerCase(),
|
|
5571
6091
|
" is not available."
|
|
5572
6092
|
] });
|
|
5573
6093
|
}
|
|
5574
6094
|
if (editing) {
|
|
5575
|
-
return /* @__PURE__ */
|
|
6095
|
+
return /* @__PURE__ */ jsx34(
|
|
5576
6096
|
RecordForm,
|
|
5577
6097
|
{
|
|
5578
6098
|
collection,
|
|
@@ -5586,12 +6106,12 @@ function RecordDetail({
|
|
|
5586
6106
|
);
|
|
5587
6107
|
}
|
|
5588
6108
|
const writable = canWrite && !readOnly;
|
|
5589
|
-
return /* @__PURE__ */
|
|
5590
|
-
/* @__PURE__ */
|
|
5591
|
-
/* @__PURE__ */
|
|
5592
|
-
/* @__PURE__ */
|
|
5593
|
-
writable ? /* @__PURE__ */
|
|
5594
|
-
writable ? /* @__PURE__ */
|
|
6109
|
+
return /* @__PURE__ */ jsxs32("div", { className: cls("b316-card b316-detail", className), style, children: [
|
|
6110
|
+
/* @__PURE__ */ jsxs32("div", { className: "b316-detail-head", children: [
|
|
6111
|
+
/* @__PURE__ */ jsx34("h3", { className: "b316-detail-title", children: record.title ?? schema.name }),
|
|
6112
|
+
/* @__PURE__ */ jsxs32("div", { className: "b316-detail-actions", children: [
|
|
6113
|
+
writable ? /* @__PURE__ */ jsx34("button", { type: "button", className: "b316-button-quiet", onClick: () => setEditing(true), children: "Edit" }) : null,
|
|
6114
|
+
writable ? /* @__PURE__ */ jsx34(
|
|
5595
6115
|
ConfirmButton,
|
|
5596
6116
|
{
|
|
5597
6117
|
className: "b316-button-quiet b316-danger",
|
|
@@ -5604,15 +6124,15 @@ function RecordDetail({
|
|
|
5604
6124
|
children: "Delete"
|
|
5605
6125
|
}
|
|
5606
6126
|
) : null,
|
|
5607
|
-
onClose ? /* @__PURE__ */
|
|
6127
|
+
onClose ? /* @__PURE__ */ jsx34("button", { type: "button", className: "b316-button-quiet", onClick: onClose, children: "Close" }) : null
|
|
5608
6128
|
] })
|
|
5609
6129
|
] }),
|
|
5610
|
-
/* @__PURE__ */
|
|
5611
|
-
/* @__PURE__ */
|
|
6130
|
+
/* @__PURE__ */ jsx34("dl", { className: "b316-detail-fields", children: schema.fields.map((field) => /* @__PURE__ */ jsxs32("div", { className: "b316-detail-row", children: [
|
|
6131
|
+
/* @__PURE__ */ jsxs32("dt", { className: "b316-label", children: [
|
|
5612
6132
|
field.label,
|
|
5613
|
-
specFor6(field).computed ? /* @__PURE__ */
|
|
6133
|
+
specFor6(field).computed ? /* @__PURE__ */ jsx34("span", { className: "b316-muted", children: " (calculated)" }) : null
|
|
5614
6134
|
] }),
|
|
5615
|
-
/* @__PURE__ */
|
|
6135
|
+
/* @__PURE__ */ jsx34("dd", { children: /* @__PURE__ */ jsx34(
|
|
5616
6136
|
FieldCell,
|
|
5617
6137
|
{
|
|
5618
6138
|
value: record.fields[field.key] ?? null,
|
|
@@ -5626,8 +6146,8 @@ function RecordDetail({
|
|
|
5626
6146
|
}
|
|
5627
6147
|
|
|
5628
6148
|
// src/SubscriptionManager.tsx
|
|
5629
|
-
import { useCallback as
|
|
5630
|
-
import { jsx as
|
|
6149
|
+
import { useCallback as useCallback11, useEffect as useEffect25, useState as useState32 } from "react";
|
|
6150
|
+
import { jsx as jsx35, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5631
6151
|
function statusLabel(status2) {
|
|
5632
6152
|
const words = status2.toLowerCase().split("_");
|
|
5633
6153
|
return words.map((w, i) => i === 0 ? w.charAt(0).toUpperCase() + w.slice(1) : w).join(" ");
|
|
@@ -5667,16 +6187,16 @@ function SubscriptionManager({
|
|
|
5667
6187
|
style
|
|
5668
6188
|
}) {
|
|
5669
6189
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
5670
|
-
const [subscription, setSubscription] =
|
|
5671
|
-
const [
|
|
5672
|
-
const [managedBy, setManagedBy] =
|
|
5673
|
-
const [schedule, setSchedule] =
|
|
5674
|
-
const [busy, setBusy] =
|
|
5675
|
-
const [error, setError] =
|
|
5676
|
-
const [step, setStep] =
|
|
5677
|
-
const [reason, setReason] =
|
|
5678
|
-
const [comment, setComment] =
|
|
5679
|
-
const load =
|
|
6190
|
+
const [subscription, setSubscription] = useState32(null);
|
|
6191
|
+
const [loading2, setLoading] = useState32(true);
|
|
6192
|
+
const [managedBy, setManagedBy] = useState32(null);
|
|
6193
|
+
const [schedule, setSchedule] = useState32([]);
|
|
6194
|
+
const [busy, setBusy] = useState32(false);
|
|
6195
|
+
const [error, setError] = useState32(null);
|
|
6196
|
+
const [step, setStep] = useState32({ kind: "idle" });
|
|
6197
|
+
const [reason, setReason] = useState32(null);
|
|
6198
|
+
const [comment, setComment] = useState32("");
|
|
6199
|
+
const load = useCallback11(async () => {
|
|
5680
6200
|
if (!token) {
|
|
5681
6201
|
setSubscription(null);
|
|
5682
6202
|
setLoading(false);
|
|
@@ -5694,7 +6214,7 @@ function SubscriptionManager({
|
|
|
5694
6214
|
setLoading(false);
|
|
5695
6215
|
}
|
|
5696
6216
|
}, [client, token]);
|
|
5697
|
-
|
|
6217
|
+
useEffect25(() => {
|
|
5698
6218
|
void load();
|
|
5699
6219
|
}, [load]);
|
|
5700
6220
|
const act = async (change, failure) => {
|
|
@@ -5711,30 +6231,30 @@ function SubscriptionManager({
|
|
|
5711
6231
|
setBusy(false);
|
|
5712
6232
|
}
|
|
5713
6233
|
};
|
|
5714
|
-
if (sessionLoading ||
|
|
5715
|
-
return /* @__PURE__ */
|
|
6234
|
+
if (sessionLoading || loading2) {
|
|
6235
|
+
return /* @__PURE__ */ jsx35("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
5716
6236
|
}
|
|
5717
6237
|
if (!token) {
|
|
5718
|
-
return /* @__PURE__ */
|
|
6238
|
+
return /* @__PURE__ */ jsx35("div", { className: cls("b316-card", className), style, children: "Sign in to manage your subscription." });
|
|
5719
6239
|
}
|
|
5720
6240
|
if (error) {
|
|
5721
|
-
return /* @__PURE__ */
|
|
6241
|
+
return /* @__PURE__ */ jsx35("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: error }) });
|
|
5722
6242
|
}
|
|
5723
6243
|
if (!subscription) {
|
|
5724
|
-
return /* @__PURE__ */
|
|
6244
|
+
return /* @__PURE__ */ jsx35("div", { className: cls("b316-card", className), style, children: "You are not subscribed to a plan." });
|
|
5725
6245
|
}
|
|
5726
6246
|
const renews = new Date(subscription.currentPeriodEnd).toLocaleDateString();
|
|
5727
6247
|
const next = schedule[0] ?? null;
|
|
5728
6248
|
const nextOn = next?.effectiveAt ? new Date(next.effectiveAt).toLocaleDateString() : renews;
|
|
5729
|
-
return /* @__PURE__ */
|
|
5730
|
-
error ? /* @__PURE__ */
|
|
5731
|
-
/* @__PURE__ */
|
|
5732
|
-
/* @__PURE__ */
|
|
6249
|
+
return /* @__PURE__ */ jsxs33("div", { className: cls("b316-card", className), style, children: [
|
|
6250
|
+
error ? /* @__PURE__ */ jsx35("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6251
|
+
/* @__PURE__ */ jsx35("div", { className: "b316-plan-name", children: subscription.planVersion.plan.name }),
|
|
6252
|
+
/* @__PURE__ */ jsxs33("div", { className: "b316-muted", children: [
|
|
5733
6253
|
statusLabel(subscription.status),
|
|
5734
6254
|
" \xB7 ",
|
|
5735
6255
|
subscription.cancelAtPeriodEnd ? `Ends ${renews}` : `Renews ${renews}`
|
|
5736
6256
|
] }),
|
|
5737
|
-
next && !managedBy ? /* @__PURE__ */
|
|
6257
|
+
next && !managedBy ? /* @__PURE__ */ jsxs33("div", { className: "b316-muted", role: "status", style: { marginTop: 10 }, children: [
|
|
5738
6258
|
"Moves to ",
|
|
5739
6259
|
next.plan.name,
|
|
5740
6260
|
" on ",
|
|
@@ -5742,7 +6262,7 @@ function SubscriptionManager({
|
|
|
5742
6262
|
". You keep ",
|
|
5743
6263
|
subscription.planVersion.plan.name,
|
|
5744
6264
|
" until then.",
|
|
5745
|
-
/* @__PURE__ */
|
|
6265
|
+
/* @__PURE__ */ jsx35("div", { children: /* @__PURE__ */ jsx35(
|
|
5746
6266
|
"button",
|
|
5747
6267
|
{
|
|
5748
6268
|
type: "button",
|
|
@@ -5767,17 +6287,17 @@ function SubscriptionManager({
|
|
|
5767
6287
|
}
|
|
5768
6288
|
) })
|
|
5769
6289
|
] }) : null,
|
|
5770
|
-
managedBy ? /* @__PURE__ */
|
|
6290
|
+
managedBy ? /* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5771
6291
|
"Provided by ",
|
|
5772
6292
|
managedBy.name ?? "the organization that manages your account",
|
|
5773
6293
|
". Ask them to change or cancel it."
|
|
5774
|
-
] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */
|
|
5775
|
-
/* @__PURE__ */
|
|
6294
|
+
] }) : subscription.cancelAtPeriodEnd ? /* @__PURE__ */ jsxs33("div", { children: [
|
|
6295
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5776
6296
|
"This subscription will not renew. You keep access until ",
|
|
5777
6297
|
renews,
|
|
5778
6298
|
"."
|
|
5779
6299
|
] }),
|
|
5780
|
-
/* @__PURE__ */
|
|
6300
|
+
/* @__PURE__ */ jsx35(
|
|
5781
6301
|
"button",
|
|
5782
6302
|
{
|
|
5783
6303
|
type: "button",
|
|
@@ -5787,14 +6307,14 @@ function SubscriptionManager({
|
|
|
5787
6307
|
children: busy ? "Working\u2026" : "Resume subscription"
|
|
5788
6308
|
}
|
|
5789
6309
|
)
|
|
5790
|
-
] }) : step.kind === "offer" ? /* @__PURE__ */
|
|
5791
|
-
/* @__PURE__ */
|
|
5792
|
-
/* @__PURE__ */
|
|
6310
|
+
] }) : step.kind === "offer" ? /* @__PURE__ */ jsxs33("section", { style: { marginTop: 14 }, "aria-label": "Retention offer", children: [
|
|
6311
|
+
/* @__PURE__ */ jsx35("div", { className: "b316-plan-name", children: step.cancellation.offer.headline ?? "Before you go" }),
|
|
6312
|
+
/* @__PURE__ */ jsx35("p", { className: "b316-muted", children: step.cancellation.offer.message ?? `Stay on ${subscription.planVersion.plan.name} and get ${describeRetentionOffer(
|
|
5793
6313
|
step.cancellation.offer,
|
|
5794
6314
|
step.cancellation.currency
|
|
5795
6315
|
)}.` }),
|
|
5796
|
-
/* @__PURE__ */
|
|
5797
|
-
/* @__PURE__ */
|
|
6316
|
+
/* @__PURE__ */ jsxs33("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
6317
|
+
/* @__PURE__ */ jsx35(
|
|
5798
6318
|
"button",
|
|
5799
6319
|
{
|
|
5800
6320
|
type: "button",
|
|
@@ -5807,7 +6327,7 @@ function SubscriptionManager({
|
|
|
5807
6327
|
children: busy ? "Working\u2026" : "Accept offer and stay"
|
|
5808
6328
|
}
|
|
5809
6329
|
),
|
|
5810
|
-
/* @__PURE__ */
|
|
6330
|
+
/* @__PURE__ */ jsx35(
|
|
5811
6331
|
"button",
|
|
5812
6332
|
{
|
|
5813
6333
|
type: "button",
|
|
@@ -5821,12 +6341,12 @@ function SubscriptionManager({
|
|
|
5821
6341
|
}
|
|
5822
6342
|
)
|
|
5823
6343
|
] }),
|
|
5824
|
-
/* @__PURE__ */
|
|
6344
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5825
6345
|
"If you cancel, you keep access until ",
|
|
5826
6346
|
renews,
|
|
5827
6347
|
"."
|
|
5828
6348
|
] })
|
|
5829
|
-
] }) : step.kind === "survey" ? /* @__PURE__ */
|
|
6349
|
+
] }) : step.kind === "survey" ? /* @__PURE__ */ jsxs33(
|
|
5830
6350
|
"form",
|
|
5831
6351
|
{
|
|
5832
6352
|
style: { marginTop: 14 },
|
|
@@ -5846,15 +6366,15 @@ function SubscriptionManager({
|
|
|
5846
6366
|
}, "Could not cancel. Try again.");
|
|
5847
6367
|
},
|
|
5848
6368
|
children: [
|
|
5849
|
-
/* @__PURE__ */
|
|
6369
|
+
/* @__PURE__ */ jsxs33("p", { className: "b316-muted", children: [
|
|
5850
6370
|
"You keep access until ",
|
|
5851
6371
|
renews,
|
|
5852
6372
|
". It will not renew after that."
|
|
5853
6373
|
] }),
|
|
5854
|
-
/* @__PURE__ */
|
|
5855
|
-
/* @__PURE__ */
|
|
5856
|
-
REASONS.map((option) => /* @__PURE__ */
|
|
5857
|
-
/* @__PURE__ */
|
|
6374
|
+
/* @__PURE__ */ jsxs33("fieldset", { className: "b316-fieldset", children: [
|
|
6375
|
+
/* @__PURE__ */ jsx35("legend", { className: "b316-label", children: "Why are you leaving? (optional)" }),
|
|
6376
|
+
REASONS.map((option) => /* @__PURE__ */ jsxs33("label", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
|
|
6377
|
+
/* @__PURE__ */ jsx35(
|
|
5858
6378
|
"input",
|
|
5859
6379
|
{
|
|
5860
6380
|
type: "radio",
|
|
@@ -5864,12 +6384,12 @@ function SubscriptionManager({
|
|
|
5864
6384
|
onChange: () => setReason(option.value)
|
|
5865
6385
|
}
|
|
5866
6386
|
),
|
|
5867
|
-
/* @__PURE__ */
|
|
6387
|
+
/* @__PURE__ */ jsx35("span", { children: option.label })
|
|
5868
6388
|
] }, option.value))
|
|
5869
6389
|
] }),
|
|
5870
|
-
/* @__PURE__ */
|
|
5871
|
-
/* @__PURE__ */
|
|
5872
|
-
/* @__PURE__ */
|
|
6390
|
+
/* @__PURE__ */ jsxs33("label", { className: "b316-field", children: [
|
|
6391
|
+
/* @__PURE__ */ jsx35("span", { className: "b316-label", children: "Anything else? (optional)" }),
|
|
6392
|
+
/* @__PURE__ */ jsx35(
|
|
5873
6393
|
"textarea",
|
|
5874
6394
|
{
|
|
5875
6395
|
className: "b316-input",
|
|
@@ -5880,9 +6400,9 @@ function SubscriptionManager({
|
|
|
5880
6400
|
}
|
|
5881
6401
|
)
|
|
5882
6402
|
] }),
|
|
5883
|
-
/* @__PURE__ */
|
|
5884
|
-
/* @__PURE__ */
|
|
5885
|
-
/* @__PURE__ */
|
|
6403
|
+
/* @__PURE__ */ jsxs33("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
6404
|
+
/* @__PURE__ */ jsx35("button", { type: "submit", className: "b316-button b316-button-secondary", disabled: busy, children: busy ? "Working\u2026" : "Cancel subscription" }),
|
|
6405
|
+
/* @__PURE__ */ jsxs33(
|
|
5886
6406
|
"button",
|
|
5887
6407
|
{
|
|
5888
6408
|
type: "button",
|
|
@@ -5898,7 +6418,7 @@ function SubscriptionManager({
|
|
|
5898
6418
|
] })
|
|
5899
6419
|
]
|
|
5900
6420
|
}
|
|
5901
|
-
) : /* @__PURE__ */
|
|
6421
|
+
) : /* @__PURE__ */ jsx35("div", { style: { marginTop: 14 }, children: /* @__PURE__ */ jsx35(
|
|
5902
6422
|
"button",
|
|
5903
6423
|
{
|
|
5904
6424
|
type: "button",
|
|
@@ -5916,11 +6436,11 @@ function SubscriptionManager({
|
|
|
5916
6436
|
}
|
|
5917
6437
|
|
|
5918
6438
|
// src/BillingPortal.tsx
|
|
5919
|
-
import { useCallback as
|
|
6439
|
+
import { useCallback as useCallback13, useEffect as useEffect29, useState as useState36 } from "react";
|
|
5920
6440
|
|
|
5921
6441
|
// src/CreditBalances.tsx
|
|
5922
|
-
import { useEffect as
|
|
5923
|
-
import { Fragment as
|
|
6442
|
+
import { useEffect as useEffect26, useState as useState33 } from "react";
|
|
6443
|
+
import { Fragment as Fragment11, jsx as jsx36, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
5924
6444
|
function units(value) {
|
|
5925
6445
|
return value === null ? "Unlimited" : Number(value).toLocaleString("en");
|
|
5926
6446
|
}
|
|
@@ -5955,10 +6475,10 @@ function Feature({
|
|
|
5955
6475
|
}) {
|
|
5956
6476
|
const { client, token } = useBase316();
|
|
5957
6477
|
const setting = feature.autoRecharge;
|
|
5958
|
-
const [busy, setBusy] =
|
|
5959
|
-
const [error, setError] =
|
|
5960
|
-
const [saved, setSaved] =
|
|
5961
|
-
const [pack, setPack] =
|
|
6478
|
+
const [busy, setBusy] = useState33(false);
|
|
6479
|
+
const [error, setError] = useState33(null);
|
|
6480
|
+
const [saved, setSaved] = useState33(null);
|
|
6481
|
+
const [pack, setPack] = useState33(feature.packs[0]?.id ?? "");
|
|
5962
6482
|
const unit = feature.unit ? ` ${feature.unit}` : "";
|
|
5963
6483
|
const warning = status(feature);
|
|
5964
6484
|
const buy = async () => {
|
|
@@ -6012,33 +6532,33 @@ function Feature({
|
|
|
6012
6532
|
setBusy(false);
|
|
6013
6533
|
}
|
|
6014
6534
|
};
|
|
6015
|
-
return /* @__PURE__ */
|
|
6016
|
-
/* @__PURE__ */
|
|
6017
|
-
/* @__PURE__ */
|
|
6018
|
-
/* @__PURE__ */
|
|
6535
|
+
return /* @__PURE__ */ jsxs34("div", { className: "b316-card b316-credit-balance", children: [
|
|
6536
|
+
/* @__PURE__ */ jsx36("div", { className: "b316-label", children: feature.featureName }),
|
|
6537
|
+
/* @__PURE__ */ jsxs34("div", { children: [
|
|
6538
|
+
/* @__PURE__ */ jsx36("strong", { children: units(feature.remaining) }),
|
|
6019
6539
|
unit,
|
|
6020
6540
|
" left"
|
|
6021
6541
|
] }),
|
|
6022
|
-
/* @__PURE__ */
|
|
6542
|
+
/* @__PURE__ */ jsxs34("div", { className: "b316-muted", children: [
|
|
6023
6543
|
feature.allowance === null ? "Unlimited allowance" : `${units(feature.allowanceRemaining)} of ${units(feature.allowance)} included this period`,
|
|
6024
6544
|
" ",
|
|
6025
6545
|
"\xB7 ",
|
|
6026
6546
|
units(feature.purchasedRemaining),
|
|
6027
6547
|
" purchased"
|
|
6028
6548
|
] }),
|
|
6029
|
-
warning && !managed ? /* @__PURE__ */
|
|
6030
|
-
error ? /* @__PURE__ */
|
|
6031
|
-
saved ? /* @__PURE__ */
|
|
6032
|
-
managed || feature.packs.length === 0 ? null : /* @__PURE__ */
|
|
6033
|
-
/* @__PURE__ */
|
|
6034
|
-
/* @__PURE__ */
|
|
6549
|
+
warning && !managed ? /* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: warning }) : null,
|
|
6550
|
+
error ? /* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6551
|
+
saved ? /* @__PURE__ */ jsx36("div", { className: "b316-notice", role: "status", children: saved }) : null,
|
|
6552
|
+
managed || feature.packs.length === 0 ? null : /* @__PURE__ */ jsxs34(Fragment11, { children: [
|
|
6553
|
+
/* @__PURE__ */ jsxs34("div", { className: "b316-row", style: { marginTop: 12 }, children: [
|
|
6554
|
+
/* @__PURE__ */ jsx36(
|
|
6035
6555
|
"select",
|
|
6036
6556
|
{
|
|
6037
6557
|
className: "b316-input",
|
|
6038
6558
|
"aria-label": "Pack to buy",
|
|
6039
6559
|
value: pack,
|
|
6040
6560
|
onChange: (event) => setPack(event.target.value),
|
|
6041
|
-
children: feature.packs.map((option) => /* @__PURE__ */
|
|
6561
|
+
children: feature.packs.map((option) => /* @__PURE__ */ jsxs34("option", { value: option.id, children: [
|
|
6042
6562
|
option.name,
|
|
6043
6563
|
" \u2014 ",
|
|
6044
6564
|
units(option.units),
|
|
@@ -6047,7 +6567,7 @@ function Feature({
|
|
|
6047
6567
|
] }, option.id))
|
|
6048
6568
|
}
|
|
6049
6569
|
),
|
|
6050
|
-
/* @__PURE__ */
|
|
6570
|
+
/* @__PURE__ */ jsx36(
|
|
6051
6571
|
"button",
|
|
6052
6572
|
{
|
|
6053
6573
|
type: "button",
|
|
@@ -6058,19 +6578,19 @@ function Feature({
|
|
|
6058
6578
|
}
|
|
6059
6579
|
)
|
|
6060
6580
|
] }),
|
|
6061
|
-
/* @__PURE__ */
|
|
6062
|
-
/* @__PURE__ */
|
|
6063
|
-
/* @__PURE__ */
|
|
6581
|
+
/* @__PURE__ */ jsxs34("form", { onSubmit: save, style: { marginTop: 16 }, children: [
|
|
6582
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-checkbox", children: [
|
|
6583
|
+
/* @__PURE__ */ jsx36("input", { type: "checkbox", name: "enabled", defaultChecked: setting?.enabled ?? false }),
|
|
6064
6584
|
" ",
|
|
6065
6585
|
"Buy credits automatically when my balance runs low"
|
|
6066
6586
|
] }),
|
|
6067
|
-
/* @__PURE__ */
|
|
6068
|
-
/* @__PURE__ */
|
|
6587
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6588
|
+
/* @__PURE__ */ jsxs34("span", { className: "b316-label", children: [
|
|
6069
6589
|
"When fewer than this many",
|
|
6070
6590
|
unit,
|
|
6071
6591
|
" are left"
|
|
6072
6592
|
] }),
|
|
6073
|
-
/* @__PURE__ */
|
|
6593
|
+
/* @__PURE__ */ jsx36(
|
|
6074
6594
|
"input",
|
|
6075
6595
|
{
|
|
6076
6596
|
className: "b316-input",
|
|
@@ -6081,21 +6601,21 @@ function Feature({
|
|
|
6081
6601
|
}
|
|
6082
6602
|
)
|
|
6083
6603
|
] }),
|
|
6084
|
-
/* @__PURE__ */
|
|
6085
|
-
/* @__PURE__ */
|
|
6086
|
-
/* @__PURE__ */
|
|
6604
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6605
|
+
/* @__PURE__ */ jsx36("span", { className: "b316-label", children: "Buy" }),
|
|
6606
|
+
/* @__PURE__ */ jsx36(
|
|
6087
6607
|
"select",
|
|
6088
6608
|
{
|
|
6089
6609
|
className: "b316-input",
|
|
6090
6610
|
name: "creditPackId",
|
|
6091
6611
|
defaultValue: setting?.creditPackId ?? feature.packs[0]?.id,
|
|
6092
|
-
children: feature.packs.map((option) => /* @__PURE__ */
|
|
6612
|
+
children: feature.packs.map((option) => /* @__PURE__ */ jsx36("option", { value: option.id, children: option.name }, option.id))
|
|
6093
6613
|
}
|
|
6094
6614
|
)
|
|
6095
6615
|
] }),
|
|
6096
|
-
/* @__PURE__ */
|
|
6097
|
-
/* @__PURE__ */
|
|
6098
|
-
/* @__PURE__ */
|
|
6616
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6617
|
+
/* @__PURE__ */ jsx36("span", { className: "b316-label", children: "At most this many times a month" }),
|
|
6618
|
+
/* @__PURE__ */ jsx36(
|
|
6099
6619
|
"input",
|
|
6100
6620
|
{
|
|
6101
6621
|
className: "b316-input",
|
|
@@ -6105,13 +6625,13 @@ function Feature({
|
|
|
6105
6625
|
}
|
|
6106
6626
|
)
|
|
6107
6627
|
] }),
|
|
6108
|
-
/* @__PURE__ */
|
|
6109
|
-
/* @__PURE__ */
|
|
6628
|
+
/* @__PURE__ */ jsxs34("label", { className: "b316-field", children: [
|
|
6629
|
+
/* @__PURE__ */ jsxs34("span", { className: "b316-label", children: [
|
|
6110
6630
|
"Spending at most (",
|
|
6111
6631
|
setting?.currency ?? feature.packs[0]?.currency ?? "USD",
|
|
6112
6632
|
") a month"
|
|
6113
6633
|
] }),
|
|
6114
|
-
/* @__PURE__ */
|
|
6634
|
+
/* @__PURE__ */ jsx36(
|
|
6115
6635
|
"input",
|
|
6116
6636
|
{
|
|
6117
6637
|
className: "b316-input",
|
|
@@ -6121,16 +6641,16 @@ function Feature({
|
|
|
6121
6641
|
}
|
|
6122
6642
|
)
|
|
6123
6643
|
] }),
|
|
6124
|
-
/* @__PURE__ */
|
|
6644
|
+
/* @__PURE__ */ jsx36("button", { type: "submit", className: "b316-button", disabled: busy, children: "Save auto-recharge" })
|
|
6125
6645
|
] })
|
|
6126
6646
|
] })
|
|
6127
6647
|
] });
|
|
6128
6648
|
}
|
|
6129
6649
|
function CreditBalances({ onChange, className, style }) {
|
|
6130
6650
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6131
|
-
const [state, setState] =
|
|
6132
|
-
const [version, setVersion] =
|
|
6133
|
-
|
|
6651
|
+
const [state, setState] = useState33({ kind: "loading" });
|
|
6652
|
+
const [version, setVersion] = useState33(0);
|
|
6653
|
+
useEffect26(() => {
|
|
6134
6654
|
if (!token) return;
|
|
6135
6655
|
let cancelled = false;
|
|
6136
6656
|
client.billing.credits(token).then((credits2) => {
|
|
@@ -6143,24 +6663,24 @@ function CreditBalances({ onChange, className, style }) {
|
|
|
6143
6663
|
cancelled = true;
|
|
6144
6664
|
};
|
|
6145
6665
|
}, [client, token, version]);
|
|
6146
|
-
const wrap = (content) => /* @__PURE__ */
|
|
6666
|
+
const wrap = (content) => /* @__PURE__ */ jsx36("div", { className: cls("b316-credit-balances", className), style, children: content });
|
|
6147
6667
|
if (sessionLoading || !token || state.kind === "loading") return null;
|
|
6148
6668
|
if (state.kind === "error") {
|
|
6149
6669
|
return wrap(
|
|
6150
|
-
/* @__PURE__ */
|
|
6670
|
+
/* @__PURE__ */ jsx36("div", { className: "b316-card", children: /* @__PURE__ */ jsx36("div", { className: "b316-error", role: "alert", children: "Could not load your credits." }) })
|
|
6151
6671
|
);
|
|
6152
6672
|
}
|
|
6153
6673
|
const { credits } = state;
|
|
6154
6674
|
if (credits.features.length === 0) return null;
|
|
6155
6675
|
return wrap(
|
|
6156
|
-
/* @__PURE__ */
|
|
6157
|
-
credits.managedBy ? /* @__PURE__ */
|
|
6676
|
+
/* @__PURE__ */ jsxs34(Fragment11, { children: [
|
|
6677
|
+
credits.managedBy ? /* @__PURE__ */ jsxs34("p", { className: "b316-muted", children: [
|
|
6158
6678
|
"Credits for this account come from",
|
|
6159
6679
|
" ",
|
|
6160
6680
|
credits.managedBy.name ?? "the organization that manages it",
|
|
6161
6681
|
", which manages them."
|
|
6162
6682
|
] }) : null,
|
|
6163
|
-
credits.features.map((feature) => /* @__PURE__ */
|
|
6683
|
+
credits.features.map((feature) => /* @__PURE__ */ jsx36(
|
|
6164
6684
|
Feature,
|
|
6165
6685
|
{
|
|
6166
6686
|
feature,
|
|
@@ -6177,19 +6697,19 @@ function CreditBalances({ onChange, className, style }) {
|
|
|
6177
6697
|
}
|
|
6178
6698
|
|
|
6179
6699
|
// src/PaymentMethod.tsx
|
|
6180
|
-
import { useEffect as
|
|
6181
|
-
import { Fragment as
|
|
6700
|
+
import { useEffect as useEffect27, useState as useState34 } from "react";
|
|
6701
|
+
import { Fragment as Fragment12, jsx as jsx37, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
6182
6702
|
function brandName(brand) {
|
|
6183
6703
|
if (!brand) return "Card";
|
|
6184
6704
|
return brand.charAt(0).toUpperCase() + brand.slice(1);
|
|
6185
6705
|
}
|
|
6186
6706
|
function PaymentMethod({ returnUrl, className, style }) {
|
|
6187
6707
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6188
|
-
const [state, setState] =
|
|
6189
|
-
const [busy, setBusy] =
|
|
6190
|
-
const [error, setError] =
|
|
6191
|
-
const [version, setVersion] =
|
|
6192
|
-
|
|
6708
|
+
const [state, setState] = useState34({ kind: "loading" });
|
|
6709
|
+
const [busy, setBusy] = useState34(false);
|
|
6710
|
+
const [error, setError] = useState34(null);
|
|
6711
|
+
const [version, setVersion] = useState34(0);
|
|
6712
|
+
useEffect27(() => {
|
|
6193
6713
|
if (!token) return;
|
|
6194
6714
|
let cancelled = false;
|
|
6195
6715
|
client.billing.paymentMethods(token).then((result) => {
|
|
@@ -6205,7 +6725,7 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6205
6725
|
cancelled = true;
|
|
6206
6726
|
};
|
|
6207
6727
|
}, [client, token, version]);
|
|
6208
|
-
const wrap = (content) => /* @__PURE__ */
|
|
6728
|
+
const wrap = (content) => /* @__PURE__ */ jsx37("div", { className: cls("b316-card b316-payment-method", className), style, children: content });
|
|
6209
6729
|
if (sessionLoading) return wrap("Loading\u2026");
|
|
6210
6730
|
if (!token) return wrap("Sign in to manage your payment method.");
|
|
6211
6731
|
switch (state.kind) {
|
|
@@ -6213,11 +6733,11 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6213
6733
|
return wrap("Loading\u2026");
|
|
6214
6734
|
case "error":
|
|
6215
6735
|
return wrap(
|
|
6216
|
-
/* @__PURE__ */
|
|
6736
|
+
/* @__PURE__ */ jsx37("div", { className: "b316-error", role: "alert", children: "Could not load your payment method." })
|
|
6217
6737
|
);
|
|
6218
6738
|
case "managed":
|
|
6219
6739
|
return wrap(
|
|
6220
|
-
/* @__PURE__ */
|
|
6740
|
+
/* @__PURE__ */ jsx37("p", { className: "b316-muted", children: "Your plan is paid for by the organization that manages it." })
|
|
6221
6741
|
);
|
|
6222
6742
|
}
|
|
6223
6743
|
const card = state.cards.find((saved) => saved.isDefault) ?? null;
|
|
@@ -6236,31 +6756,31 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6236
6756
|
}
|
|
6237
6757
|
};
|
|
6238
6758
|
return wrap(
|
|
6239
|
-
/* @__PURE__ */
|
|
6240
|
-
/* @__PURE__ */
|
|
6241
|
-
card ? /* @__PURE__ */
|
|
6242
|
-
/* @__PURE__ */
|
|
6759
|
+
/* @__PURE__ */ jsxs35(Fragment12, { children: [
|
|
6760
|
+
/* @__PURE__ */ jsx37("div", { className: "b316-label", children: "Payment method" }),
|
|
6761
|
+
card ? /* @__PURE__ */ jsxs35("div", { children: [
|
|
6762
|
+
/* @__PURE__ */ jsxs35("div", { children: [
|
|
6243
6763
|
brandName(card.brand),
|
|
6244
6764
|
" ending ",
|
|
6245
6765
|
card.last4 ?? "????"
|
|
6246
6766
|
] }),
|
|
6247
|
-
card.expMonth && card.expYear ? /* @__PURE__ */
|
|
6767
|
+
card.expMonth && card.expYear ? /* @__PURE__ */ jsxs35("div", { className: "b316-muted", children: [
|
|
6248
6768
|
"Expires ",
|
|
6249
6769
|
String(card.expMonth).padStart(2, "0"),
|
|
6250
6770
|
"/",
|
|
6251
6771
|
card.expYear
|
|
6252
6772
|
] }) : null
|
|
6253
|
-
] }) : /* @__PURE__ */
|
|
6254
|
-
others.length > 0 ? /* @__PURE__ */
|
|
6255
|
-
/* @__PURE__ */
|
|
6256
|
-
others.map((saved) => /* @__PURE__ */
|
|
6257
|
-
/* @__PURE__ */
|
|
6773
|
+
] }) : /* @__PURE__ */ jsx37("p", { className: "b316-muted", children: "No card on file." }),
|
|
6774
|
+
others.length > 0 ? /* @__PURE__ */ jsxs35("div", { style: { marginTop: 12 }, children: [
|
|
6775
|
+
/* @__PURE__ */ jsx37("div", { className: "b316-label", children: "Other saved cards" }),
|
|
6776
|
+
others.map((saved) => /* @__PURE__ */ jsxs35("div", { className: "b316-row", style: { marginTop: 6 }, children: [
|
|
6777
|
+
/* @__PURE__ */ jsxs35("span", { children: [
|
|
6258
6778
|
brandName(saved.brand),
|
|
6259
6779
|
" ending ",
|
|
6260
6780
|
saved.last4 ?? "????"
|
|
6261
6781
|
] }),
|
|
6262
|
-
/* @__PURE__ */
|
|
6263
|
-
/* @__PURE__ */
|
|
6782
|
+
/* @__PURE__ */ jsxs35("span", { children: [
|
|
6783
|
+
/* @__PURE__ */ jsx37(
|
|
6264
6784
|
"button",
|
|
6265
6785
|
{
|
|
6266
6786
|
type: "button",
|
|
@@ -6274,7 +6794,7 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6274
6794
|
}
|
|
6275
6795
|
),
|
|
6276
6796
|
" ",
|
|
6277
|
-
/* @__PURE__ */
|
|
6797
|
+
/* @__PURE__ */ jsx37(
|
|
6278
6798
|
"button",
|
|
6279
6799
|
{
|
|
6280
6800
|
type: "button",
|
|
@@ -6290,8 +6810,8 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6290
6810
|
] })
|
|
6291
6811
|
] }, saved.id))
|
|
6292
6812
|
] }) : null,
|
|
6293
|
-
error ? /* @__PURE__ */
|
|
6294
|
-
/* @__PURE__ */
|
|
6813
|
+
error ? /* @__PURE__ */ jsx37("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6814
|
+
/* @__PURE__ */ jsx37(
|
|
6295
6815
|
"button",
|
|
6296
6816
|
{
|
|
6297
6817
|
type: "button",
|
|
@@ -6320,8 +6840,8 @@ function PaymentMethod({ returnUrl, className, style }) {
|
|
|
6320
6840
|
}
|
|
6321
6841
|
|
|
6322
6842
|
// src/PlanChangeReview.tsx
|
|
6323
|
-
import { useCallback as
|
|
6324
|
-
import { Fragment as
|
|
6843
|
+
import { useCallback as useCallback12, useEffect as useEffect28, useState as useState35 } from "react";
|
|
6844
|
+
import { Fragment as Fragment13, jsx as jsx38, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
6325
6845
|
function money5(amount, currency) {
|
|
6326
6846
|
if (amount === null) return "\u2014";
|
|
6327
6847
|
const value = Number(amount);
|
|
@@ -6354,12 +6874,12 @@ function PlanChangeReview({
|
|
|
6354
6874
|
style
|
|
6355
6875
|
}) {
|
|
6356
6876
|
const { client, token } = useBase316();
|
|
6357
|
-
const [timing, setTiming] =
|
|
6358
|
-
const [preview, setPreview] =
|
|
6359
|
-
const [error, setError] =
|
|
6360
|
-
const [needsCard, setNeedsCard] =
|
|
6361
|
-
const [busy, setBusy] =
|
|
6362
|
-
|
|
6877
|
+
const [timing, setTiming] = useState35(void 0);
|
|
6878
|
+
const [preview, setPreview] = useState35(null);
|
|
6879
|
+
const [error, setError] = useState35(null);
|
|
6880
|
+
const [needsCard, setNeedsCard] = useState35(false);
|
|
6881
|
+
const [busy, setBusy] = useState35(false);
|
|
6882
|
+
useEffect28(() => {
|
|
6363
6883
|
if (!token) return;
|
|
6364
6884
|
let cancelled = false;
|
|
6365
6885
|
client.billing.previewPlanChange(token, planVersionId, timing).then((result) => {
|
|
@@ -6376,7 +6896,7 @@ function PlanChangeReview({
|
|
|
6376
6896
|
cancelled = true;
|
|
6377
6897
|
};
|
|
6378
6898
|
}, [client, token, planVersionId, timing]);
|
|
6379
|
-
const confirm =
|
|
6899
|
+
const confirm = useCallback12(async () => {
|
|
6380
6900
|
if (!token || !preview) return;
|
|
6381
6901
|
setBusy(true);
|
|
6382
6902
|
setError(null);
|
|
@@ -6397,7 +6917,7 @@ function PlanChangeReview({
|
|
|
6397
6917
|
setBusy(false);
|
|
6398
6918
|
}
|
|
6399
6919
|
}, [client, token, preview, planVersionId, onDone]);
|
|
6400
|
-
const addCard =
|
|
6920
|
+
const addCard = useCallback12(async () => {
|
|
6401
6921
|
if (onNeedsCard) {
|
|
6402
6922
|
onNeedsCard();
|
|
6403
6923
|
return;
|
|
@@ -6411,12 +6931,12 @@ function PlanChangeReview({
|
|
|
6411
6931
|
setError("Cards cannot be added here right now.");
|
|
6412
6932
|
}
|
|
6413
6933
|
}, [client, token, onNeedsCard]);
|
|
6414
|
-
const card = (content) => /* @__PURE__ */
|
|
6934
|
+
const card = (content) => /* @__PURE__ */ jsx38("div", { className: cls("b316-card b316-plan-review", className), style, children: content });
|
|
6415
6935
|
if (error && !preview) {
|
|
6416
6936
|
return card(
|
|
6417
|
-
/* @__PURE__ */
|
|
6418
|
-
/* @__PURE__ */
|
|
6419
|
-
onCancel ? /* @__PURE__ */
|
|
6937
|
+
/* @__PURE__ */ jsxs36(Fragment13, { children: [
|
|
6938
|
+
/* @__PURE__ */ jsx38("div", { className: "b316-error", role: "alert", children: error }),
|
|
6939
|
+
onCancel ? /* @__PURE__ */ jsx38("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: "Back" }) : null
|
|
6420
6940
|
] })
|
|
6421
6941
|
);
|
|
6422
6942
|
}
|
|
@@ -6429,26 +6949,26 @@ function PlanChangeReview({
|
|
|
6429
6949
|
const otherReason = preview.timings[other]?.reason ?? null;
|
|
6430
6950
|
const changes = preview.entitlements.filter((change) => change.change !== "UNCHANGED");
|
|
6431
6951
|
return card(
|
|
6432
|
-
/* @__PURE__ */
|
|
6433
|
-
/* @__PURE__ */
|
|
6952
|
+
/* @__PURE__ */ jsxs36(Fragment13, { children: [
|
|
6953
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-plan-name", children: [
|
|
6434
6954
|
"Change to ",
|
|
6435
6955
|
to.planName
|
|
6436
6956
|
] }),
|
|
6437
|
-
/* @__PURE__ */
|
|
6957
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-muted", children: [
|
|
6438
6958
|
"From ",
|
|
6439
6959
|
from.planName
|
|
6440
6960
|
] }),
|
|
6441
|
-
error ? /* @__PURE__ */
|
|
6442
|
-
changes.length === 0 ? /* @__PURE__ */
|
|
6443
|
-
/* @__PURE__ */
|
|
6444
|
-
/* @__PURE__ */
|
|
6445
|
-
/* @__PURE__ */
|
|
6446
|
-
/* @__PURE__ */
|
|
6961
|
+
error ? /* @__PURE__ */ jsx38("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
6962
|
+
changes.length === 0 ? /* @__PURE__ */ jsx38("p", { className: "b316-muted", children: "Every feature stays the same." }) : /* @__PURE__ */ jsxs36("table", { className: "b316-review-table", children: [
|
|
6963
|
+
/* @__PURE__ */ jsx38("thead", { children: /* @__PURE__ */ jsxs36("tr", { children: [
|
|
6964
|
+
/* @__PURE__ */ jsx38("th", { children: "Feature" }),
|
|
6965
|
+
/* @__PURE__ */ jsx38("th", { children: from.planName }),
|
|
6966
|
+
/* @__PURE__ */ jsx38("th", { children: to.planName })
|
|
6447
6967
|
] }) }),
|
|
6448
|
-
/* @__PURE__ */
|
|
6449
|
-
/* @__PURE__ */
|
|
6450
|
-
/* @__PURE__ */
|
|
6451
|
-
/* @__PURE__ */
|
|
6968
|
+
/* @__PURE__ */ jsx38("tbody", { children: changes.map((change) => /* @__PURE__ */ jsxs36("tr", { children: [
|
|
6969
|
+
/* @__PURE__ */ jsx38("td", { children: change.featureName }),
|
|
6970
|
+
/* @__PURE__ */ jsx38("td", { children: limitText(change.before, change.type) }),
|
|
6971
|
+
/* @__PURE__ */ jsx38(
|
|
6452
6972
|
"td",
|
|
6453
6973
|
{
|
|
6454
6974
|
className: change.change === "GAINED" || change.change === "INCREASED" ? "b316-review-gain" : "b316-review-loss",
|
|
@@ -6457,40 +6977,40 @@ function PlanChangeReview({
|
|
|
6457
6977
|
)
|
|
6458
6978
|
] }, change.featureId)) })
|
|
6459
6979
|
] }),
|
|
6460
|
-
preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */
|
|
6980
|
+
preview.timing === "NOW" ? now.trialing ? /* @__PURE__ */ jsxs36("p", { children: [
|
|
6461
6981
|
"The change happens now. Your trial carries on until ",
|
|
6462
6982
|
day4(now.trialEndsAt),
|
|
6463
6983
|
", and nothing is charged before then."
|
|
6464
|
-
] }) : /* @__PURE__ */
|
|
6465
|
-
Number(now.credit) > 0 ? /* @__PURE__ */
|
|
6466
|
-
/* @__PURE__ */
|
|
6984
|
+
] }) : /* @__PURE__ */ jsxs36("div", { children: [
|
|
6985
|
+
Number(now.credit) > 0 ? /* @__PURE__ */ jsxs36("div", { className: "b316-row", children: [
|
|
6986
|
+
/* @__PURE__ */ jsxs36("span", { className: "b316-muted", children: [
|
|
6467
6987
|
"Credit for the unused part of ",
|
|
6468
6988
|
from.planName
|
|
6469
6989
|
] }),
|
|
6470
|
-
/* @__PURE__ */
|
|
6990
|
+
/* @__PURE__ */ jsxs36("span", { className: "b316-num", children: [
|
|
6471
6991
|
"\u2212",
|
|
6472
6992
|
money5(now.credit, from.currency)
|
|
6473
6993
|
] })
|
|
6474
6994
|
] }) : null,
|
|
6475
|
-
Number(now.closingUsage) > 0 ? /* @__PURE__ */
|
|
6476
|
-
/* @__PURE__ */
|
|
6477
|
-
/* @__PURE__ */
|
|
6995
|
+
Number(now.closingUsage) > 0 ? /* @__PURE__ */ jsxs36("div", { className: "b316-row", children: [
|
|
6996
|
+
/* @__PURE__ */ jsx38("span", { className: "b316-muted", children: "Usage so far this period" }),
|
|
6997
|
+
/* @__PURE__ */ jsx38("span", { className: "b316-num", children: money5(now.closingUsage, from.currency) })
|
|
6478
6998
|
] }) : null,
|
|
6479
|
-
/* @__PURE__ */
|
|
6480
|
-
/* @__PURE__ */
|
|
6999
|
+
/* @__PURE__ */ jsxs36("div", { className: "b316-row", children: [
|
|
7000
|
+
/* @__PURE__ */ jsxs36("span", { className: "b316-muted", children: [
|
|
6481
7001
|
to.planName,
|
|
6482
7002
|
", ",
|
|
6483
7003
|
day4(now.newPeriod.start),
|
|
6484
7004
|
" \u2013 ",
|
|
6485
7005
|
day4(now.newPeriod.end)
|
|
6486
7006
|
] }),
|
|
6487
|
-
/* @__PURE__ */
|
|
7007
|
+
/* @__PURE__ */ jsx38("span", { className: "b316-num", children: money5(now.newPeriodCharge, to.currency) })
|
|
6488
7008
|
] }),
|
|
6489
|
-
now.net !== null ? /* @__PURE__ */
|
|
6490
|
-
/* @__PURE__ */
|
|
6491
|
-
/* @__PURE__ */
|
|
7009
|
+
now.net !== null ? /* @__PURE__ */ jsxs36("div", { className: "b316-row b316-invoice-total", children: [
|
|
7010
|
+
/* @__PURE__ */ jsx38("span", { children: "Due now" }),
|
|
7011
|
+
/* @__PURE__ */ jsx38("span", { className: "b316-num", children: money5(now.net, to.currency) })
|
|
6492
7012
|
] }) : null
|
|
6493
|
-
] }) : /* @__PURE__ */
|
|
7013
|
+
] }) : /* @__PURE__ */ jsxs36("p", { children: [
|
|
6494
7014
|
"You keep ",
|
|
6495
7015
|
from.planName,
|
|
6496
7016
|
" until ",
|
|
@@ -6503,7 +7023,7 @@ function PlanChangeReview({
|
|
|
6503
7023
|
preview.atPeriodEnd.nextInvoice.currency
|
|
6504
7024
|
)}.` : ""
|
|
6505
7025
|
] }),
|
|
6506
|
-
otherOpen ? /* @__PURE__ */
|
|
7026
|
+
otherOpen ? /* @__PURE__ */ jsx38(
|
|
6507
7027
|
"button",
|
|
6508
7028
|
{
|
|
6509
7029
|
type: "button",
|
|
@@ -6514,12 +7034,12 @@ function PlanChangeReview({
|
|
|
6514
7034
|
},
|
|
6515
7035
|
children: other === "NOW" ? "Change now instead" : "Wait until the end of the period instead"
|
|
6516
7036
|
}
|
|
6517
|
-
) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */
|
|
6518
|
-
needsCard ? /* @__PURE__ */
|
|
7037
|
+
) : otherReason && TIMING_CLOSED[otherReason] ? /* @__PURE__ */ jsx38("p", { className: "b316-muted", children: TIMING_CLOSED[otherReason] }) : null,
|
|
7038
|
+
needsCard ? /* @__PURE__ */ jsxs36("div", { className: "b316-notice", role: "status", children: [
|
|
6519
7039
|
"A card is needed for a change that is charged now.",
|
|
6520
|
-
/* @__PURE__ */
|
|
6521
|
-
] }) : /* @__PURE__ */
|
|
6522
|
-
/* @__PURE__ */
|
|
7040
|
+
/* @__PURE__ */ jsx38("div", { className: "b316-review-actions", children: /* @__PURE__ */ jsx38("button", { type: "button", className: "b316-button", onClick: () => void addCard(), children: "Add a card" }) })
|
|
7041
|
+
] }) : /* @__PURE__ */ jsxs36("div", { className: "b316-review-actions", children: [
|
|
7042
|
+
/* @__PURE__ */ jsx38(
|
|
6523
7043
|
"button",
|
|
6524
7044
|
{
|
|
6525
7045
|
type: "button",
|
|
@@ -6529,7 +7049,7 @@ function PlanChangeReview({
|
|
|
6529
7049
|
children: busy ? "Working\u2026" : preview.timing === "NOW" ? `Change to ${to.planName} now` : `Schedule ${to.planName}`
|
|
6530
7050
|
}
|
|
6531
7051
|
),
|
|
6532
|
-
onCancel ? /* @__PURE__ */
|
|
7052
|
+
onCancel ? /* @__PURE__ */ jsxs36("button", { type: "button", className: "b316-button b316-button-secondary", onClick: onCancel, children: [
|
|
6533
7053
|
"Keep ",
|
|
6534
7054
|
from.planName
|
|
6535
7055
|
] }) : null
|
|
@@ -6539,7 +7059,7 @@ function PlanChangeReview({
|
|
|
6539
7059
|
}
|
|
6540
7060
|
|
|
6541
7061
|
// src/BillingPortal.tsx
|
|
6542
|
-
import { Fragment as
|
|
7062
|
+
import { Fragment as Fragment14, jsx as jsx39, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
6543
7063
|
function BillingPortal({
|
|
6544
7064
|
returnUrl,
|
|
6545
7065
|
featuredPlanKey,
|
|
@@ -6549,12 +7069,12 @@ function BillingPortal({
|
|
|
6549
7069
|
style
|
|
6550
7070
|
}) {
|
|
6551
7071
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6552
|
-
const [overview, setOverview] =
|
|
6553
|
-
const [failed, setFailed] =
|
|
6554
|
-
const [version, setVersion] =
|
|
6555
|
-
const [reviewing, setReviewing] =
|
|
6556
|
-
const [notice, setNotice] =
|
|
6557
|
-
|
|
7072
|
+
const [overview, setOverview] = useState36(null);
|
|
7073
|
+
const [failed, setFailed] = useState36(false);
|
|
7074
|
+
const [version, setVersion] = useState36(0);
|
|
7075
|
+
const [reviewing, setReviewing] = useState36(null);
|
|
7076
|
+
const [notice, setNotice] = useState36(null);
|
|
7077
|
+
useEffect29(() => {
|
|
6558
7078
|
if (!token) return;
|
|
6559
7079
|
let cancelled = false;
|
|
6560
7080
|
client.billing.subscription(token).then((result) => {
|
|
@@ -6573,28 +7093,28 @@ function BillingPortal({
|
|
|
6573
7093
|
cancelled = true;
|
|
6574
7094
|
};
|
|
6575
7095
|
}, [client, token, version]);
|
|
6576
|
-
const refresh =
|
|
7096
|
+
const refresh = useCallback13(() => {
|
|
6577
7097
|
setNotice(null);
|
|
6578
7098
|
setVersion((value) => value + 1);
|
|
6579
7099
|
}, []);
|
|
6580
|
-
const shell = (content) => /* @__PURE__ */
|
|
6581
|
-
if (sessionLoading) return shell(/* @__PURE__ */
|
|
6582
|
-
if (!token) return shell(/* @__PURE__ */
|
|
7100
|
+
const shell = (content) => /* @__PURE__ */ jsx39("div", { className: cls("b316-billing-portal", className), style, children: content });
|
|
7101
|
+
if (sessionLoading) return shell(/* @__PURE__ */ jsx39("div", { className: "b316-card", children: "Loading\u2026" }));
|
|
7102
|
+
if (!token) return shell(/* @__PURE__ */ jsx39("div", { className: "b316-card", children: "Sign in to manage your billing." }));
|
|
6583
7103
|
if (failed) {
|
|
6584
7104
|
return shell(
|
|
6585
|
-
/* @__PURE__ */
|
|
7105
|
+
/* @__PURE__ */ jsx39("div", { className: "b316-card", children: /* @__PURE__ */ jsx39("div", { className: "b316-error", role: "alert", children: "Could not load your billing." }) })
|
|
6586
7106
|
);
|
|
6587
7107
|
}
|
|
6588
|
-
if (!overview) return shell(/* @__PURE__ */
|
|
7108
|
+
if (!overview) return shell(/* @__PURE__ */ jsx39("div", { className: "b316-card", children: "Loading\u2026" }));
|
|
6589
7109
|
const { subscription, managedBy, quantityPriced } = overview;
|
|
6590
7110
|
const canChange = Boolean(subscription) && !managedBy;
|
|
6591
7111
|
return shell(
|
|
6592
|
-
/* @__PURE__ */
|
|
6593
|
-
notice ? /* @__PURE__ */
|
|
6594
|
-
/* @__PURE__ */
|
|
6595
|
-
canChange ? /* @__PURE__ */
|
|
6596
|
-
canChange && quantityPriced ? /* @__PURE__ */
|
|
6597
|
-
reviewing ? /* @__PURE__ */
|
|
7112
|
+
/* @__PURE__ */ jsxs37(Fragment14, { children: [
|
|
7113
|
+
notice ? /* @__PURE__ */ jsx39("div", { className: "b316-card b316-notice", role: "status", children: notice }) : null,
|
|
7114
|
+
/* @__PURE__ */ jsx39(SubscriptionManager, { onChange: refresh }, `plan-${version}`),
|
|
7115
|
+
canChange ? /* @__PURE__ */ jsx39(UpcomingInvoice, {}, `next-${version}`) : null,
|
|
7116
|
+
canChange && quantityPriced ? /* @__PURE__ */ jsx39(SeatManager, { unitLabel, onChange: refresh }, `seats-${version}`) : null,
|
|
7117
|
+
reviewing ? /* @__PURE__ */ jsx39(
|
|
6598
7118
|
PlanChangeReview,
|
|
6599
7119
|
{
|
|
6600
7120
|
planVersionId: reviewing,
|
|
@@ -6607,9 +7127,9 @@ function BillingPortal({
|
|
|
6607
7127
|
);
|
|
6608
7128
|
}
|
|
6609
7129
|
}
|
|
6610
|
-
) : /* @__PURE__ */
|
|
6611
|
-
/* @__PURE__ */
|
|
6612
|
-
/* @__PURE__ */
|
|
7130
|
+
) : /* @__PURE__ */ jsxs37("section", { children: [
|
|
7131
|
+
/* @__PURE__ */ jsx39("h2", { className: "b316-billing-portal-section-title", children: subscription ? "Change plan" : "Choose a plan" }),
|
|
7132
|
+
/* @__PURE__ */ jsx39(
|
|
6613
7133
|
PricingTable,
|
|
6614
7134
|
{
|
|
6615
7135
|
featuredPlanKey,
|
|
@@ -6621,17 +7141,17 @@ function BillingPortal({
|
|
|
6621
7141
|
`plans-${version}`
|
|
6622
7142
|
)
|
|
6623
7143
|
] }),
|
|
6624
|
-
/* @__PURE__ */
|
|
6625
|
-
managedBy ? null : /* @__PURE__ */
|
|
6626
|
-
/* @__PURE__ */
|
|
6627
|
-
billingDetails === void 0 ? /* @__PURE__ */
|
|
7144
|
+
/* @__PURE__ */ jsx39(CreditBalances, {}, `credits-${version}`),
|
|
7145
|
+
managedBy ? null : /* @__PURE__ */ jsx39(PaymentMethod, { returnUrl }, `card-${version}`),
|
|
7146
|
+
/* @__PURE__ */ jsx39(Invoices, {}, `invoices-${version}`),
|
|
7147
|
+
billingDetails === void 0 ? /* @__PURE__ */ jsx39(BillingDetailsForm, {}, `details-${version}`) : billingDetails
|
|
6628
7148
|
] })
|
|
6629
7149
|
);
|
|
6630
7150
|
}
|
|
6631
7151
|
|
|
6632
7152
|
// src/ApiKeyManager.tsx
|
|
6633
|
-
import { useCallback as
|
|
6634
|
-
import { jsx as
|
|
7153
|
+
import { useCallback as useCallback14, useEffect as useEffect30, useState as useState37 } from "react";
|
|
7154
|
+
import { jsx as jsx40, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
6635
7155
|
function duration(seconds) {
|
|
6636
7156
|
if (seconds % 3600 === 0) {
|
|
6637
7157
|
return `${seconds / 3600}h`;
|
|
@@ -6648,17 +7168,17 @@ function ApiKeyManager({
|
|
|
6648
7168
|
audience
|
|
6649
7169
|
}) {
|
|
6650
7170
|
const { client, token, loading: sessionLoading } = useBase316();
|
|
6651
|
-
const [resources, setResources] =
|
|
6652
|
-
const [credentials, setCredentials] =
|
|
6653
|
-
const [
|
|
6654
|
-
const [busy, setBusy] =
|
|
6655
|
-
const [error, setError] =
|
|
6656
|
-
const [creating, setCreating] =
|
|
6657
|
-
const [name, setName] =
|
|
6658
|
-
const [chosen, setChosen] =
|
|
6659
|
-
const [resourceId, setResourceId] =
|
|
6660
|
-
const [issued, setIssued] =
|
|
6661
|
-
const load =
|
|
7171
|
+
const [resources, setResources] = useState37([]);
|
|
7172
|
+
const [credentials, setCredentials] = useState37([]);
|
|
7173
|
+
const [loading2, setLoading] = useState37(true);
|
|
7174
|
+
const [busy, setBusy] = useState37(false);
|
|
7175
|
+
const [error, setError] = useState37(null);
|
|
7176
|
+
const [creating, setCreating] = useState37(false);
|
|
7177
|
+
const [name, setName] = useState37("");
|
|
7178
|
+
const [chosen, setChosen] = useState37([]);
|
|
7179
|
+
const [resourceId, setResourceId] = useState37(null);
|
|
7180
|
+
const [issued, setIssued] = useState37(null);
|
|
7181
|
+
const load = useCallback14(async () => {
|
|
6662
7182
|
if (!token) {
|
|
6663
7183
|
setLoading(false);
|
|
6664
7184
|
return;
|
|
@@ -6679,20 +7199,20 @@ function ApiKeyManager({
|
|
|
6679
7199
|
setLoading(false);
|
|
6680
7200
|
}
|
|
6681
7201
|
}, [client, token, audience]);
|
|
6682
|
-
|
|
7202
|
+
useEffect30(() => {
|
|
6683
7203
|
void load();
|
|
6684
7204
|
}, [load]);
|
|
6685
|
-
if (sessionLoading ||
|
|
6686
|
-
return /* @__PURE__ */
|
|
7205
|
+
if (sessionLoading || loading2) {
|
|
7206
|
+
return /* @__PURE__ */ jsx40("div", { className: cls("b316-card", className), style, children: "Loading\u2026" });
|
|
6687
7207
|
}
|
|
6688
7208
|
if (!token) {
|
|
6689
|
-
return /* @__PURE__ */
|
|
7209
|
+
return /* @__PURE__ */ jsx40("div", { className: cls("b316-card", className), style, children: "Sign in to manage your API keys." });
|
|
6690
7210
|
}
|
|
6691
7211
|
if (error) {
|
|
6692
|
-
return /* @__PURE__ */
|
|
7212
|
+
return /* @__PURE__ */ jsx40("div", { className: cls("b316-card", className), style, children: /* @__PURE__ */ jsx40("div", { className: "b316-error", role: "alert", children: error }) });
|
|
6693
7213
|
}
|
|
6694
7214
|
if (resources.length === 0) {
|
|
6695
|
-
return /* @__PURE__ */
|
|
7215
|
+
return /* @__PURE__ */ jsx40("div", { className: cls("b316-card", className), style, children: "There are no APIs available to your account." });
|
|
6696
7216
|
}
|
|
6697
7217
|
const resource = resources.find((item) => item.id === resourceId) ?? resources[0];
|
|
6698
7218
|
const reset = () => {
|
|
@@ -6701,37 +7221,37 @@ function ApiKeyManager({
|
|
|
6701
7221
|
setChosen([]);
|
|
6702
7222
|
setIssued(null);
|
|
6703
7223
|
};
|
|
6704
|
-
return /* @__PURE__ */
|
|
6705
|
-
error ? /* @__PURE__ */
|
|
6706
|
-
resources.length > 1 ? /* @__PURE__ */
|
|
7224
|
+
return /* @__PURE__ */ jsxs38("div", { className: cls("b316-card", className), style, children: [
|
|
7225
|
+
error ? /* @__PURE__ */ jsx40("div", { className: "b316-error", role: "alert", children: error }) : null,
|
|
7226
|
+
resources.length > 1 ? /* @__PURE__ */ jsx40(
|
|
6707
7227
|
"select",
|
|
6708
7228
|
{
|
|
6709
7229
|
className: "b316-input",
|
|
6710
7230
|
value: resource.id,
|
|
6711
7231
|
onChange: (event) => setResourceId(event.target.value),
|
|
6712
7232
|
style: { marginBottom: 14 },
|
|
6713
|
-
children: resources.map((item) => /* @__PURE__ */
|
|
7233
|
+
children: resources.map((item) => /* @__PURE__ */ jsx40("option", { value: item.id, children: item.name }, item.id))
|
|
6714
7234
|
}
|
|
6715
|
-
) : /* @__PURE__ */
|
|
6716
|
-
resource.rateLimit ? /* @__PURE__ */
|
|
7235
|
+
) : /* @__PURE__ */ jsx40("div", { className: "b316-plan-name", children: resource.name }),
|
|
7236
|
+
resource.rateLimit ? /* @__PURE__ */ jsxs38("div", { className: "b316-muted", children: [
|
|
6717
7237
|
resource.rateLimit.requestsPerWindow,
|
|
6718
7238
|
" requests per",
|
|
6719
7239
|
" ",
|
|
6720
7240
|
duration(resource.rateLimit.windowSeconds),
|
|
6721
7241
|
resource.rateLimit.burst > resource.rateLimit.requestsPerWindow ? `, bursting to ${resource.rateLimit.burst}` : null
|
|
6722
|
-
] }) : /* @__PURE__ */
|
|
6723
|
-
credentials.length === 0 ? /* @__PURE__ */
|
|
6724
|
-
/* @__PURE__ */
|
|
6725
|
-
/* @__PURE__ */
|
|
6726
|
-
/* @__PURE__ */
|
|
6727
|
-
/* @__PURE__ */
|
|
7242
|
+
] }) : /* @__PURE__ */ jsx40("div", { className: "b316-muted", children: "No rate limit." }),
|
|
7243
|
+
credentials.length === 0 ? /* @__PURE__ */ jsx40("p", { className: "b316-muted", style: { marginTop: 14 }, children: "You have no API keys yet." }) : /* @__PURE__ */ jsx40("ul", { className: "b316-list", style: { marginTop: 14 }, children: credentials.map((credential) => /* @__PURE__ */ jsxs38("li", { className: "b316-list-item", children: [
|
|
7244
|
+
/* @__PURE__ */ jsxs38("div", { children: [
|
|
7245
|
+
/* @__PURE__ */ jsx40("div", { className: "b316-plan-name", children: credential.name }),
|
|
7246
|
+
/* @__PURE__ */ jsxs38("div", { className: "b316-muted", children: [
|
|
7247
|
+
/* @__PURE__ */ jsx40("code", { children: credential.clientId }),
|
|
6728
7248
|
credential.secretLastFour ? ` \xB7 \u2026${credential.secretLastFour}` : null,
|
|
6729
7249
|
credential.disabled ? " \xB7 Disabled" : null
|
|
6730
7250
|
] }),
|
|
6731
|
-
/* @__PURE__ */
|
|
7251
|
+
/* @__PURE__ */ jsx40("div", { className: "b316-muted", children: credential.scopes.join(", ") })
|
|
6732
7252
|
] }),
|
|
6733
|
-
/* @__PURE__ */
|
|
6734
|
-
/* @__PURE__ */
|
|
7253
|
+
/* @__PURE__ */ jsxs38("div", { style: { display: "flex", gap: 8 }, children: [
|
|
7254
|
+
/* @__PURE__ */ jsx40(
|
|
6735
7255
|
"button",
|
|
6736
7256
|
{
|
|
6737
7257
|
type: "button",
|
|
@@ -6760,7 +7280,7 @@ function ApiKeyManager({
|
|
|
6760
7280
|
children: "Rotate"
|
|
6761
7281
|
}
|
|
6762
7282
|
),
|
|
6763
|
-
/* @__PURE__ */
|
|
7283
|
+
/* @__PURE__ */ jsx40(
|
|
6764
7284
|
ConfirmButton,
|
|
6765
7285
|
{
|
|
6766
7286
|
className: "b316-button b316-button-secondary",
|
|
@@ -6784,11 +7304,11 @@ function ApiKeyManager({
|
|
|
6784
7304
|
)
|
|
6785
7305
|
] })
|
|
6786
7306
|
] }, credential.clientId)) }),
|
|
6787
|
-
issued ? /* @__PURE__ */
|
|
6788
|
-
/* @__PURE__ */
|
|
7307
|
+
issued ? /* @__PURE__ */ jsxs38("div", { className: "b316-notice", style: { marginTop: 14 }, children: [
|
|
7308
|
+
/* @__PURE__ */ jsx40("strong", { children: "Copy this now." }),
|
|
6789
7309
|
" It is shown once and cannot be retrieved again.",
|
|
6790
|
-
/* @__PURE__ */
|
|
6791
|
-
/* @__PURE__ */
|
|
7310
|
+
/* @__PURE__ */ jsx40("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx40("code", { style: { wordBreak: "break-all" }, children: issued.secret }) }),
|
|
7311
|
+
/* @__PURE__ */ jsx40(
|
|
6792
7312
|
"button",
|
|
6793
7313
|
{
|
|
6794
7314
|
type: "button",
|
|
@@ -6801,7 +7321,7 @@ function ApiKeyManager({
|
|
|
6801
7321
|
children: "Copy"
|
|
6802
7322
|
}
|
|
6803
7323
|
),
|
|
6804
|
-
/* @__PURE__ */
|
|
7324
|
+
/* @__PURE__ */ jsx40(
|
|
6805
7325
|
"button",
|
|
6806
7326
|
{
|
|
6807
7327
|
type: "button",
|
|
@@ -6812,8 +7332,8 @@ function ApiKeyManager({
|
|
|
6812
7332
|
}
|
|
6813
7333
|
)
|
|
6814
7334
|
] }) : null,
|
|
6815
|
-
creating && !issued ? /* @__PURE__ */
|
|
6816
|
-
/* @__PURE__ */
|
|
7335
|
+
creating && !issued ? /* @__PURE__ */ jsxs38("div", { style: { marginTop: 14 }, children: [
|
|
7336
|
+
/* @__PURE__ */ jsx40(
|
|
6817
7337
|
"input",
|
|
6818
7338
|
{
|
|
6819
7339
|
className: "b316-input",
|
|
@@ -6822,9 +7342,9 @@ function ApiKeyManager({
|
|
|
6822
7342
|
onChange: (event) => setName(event.target.value)
|
|
6823
7343
|
}
|
|
6824
7344
|
),
|
|
6825
|
-
/* @__PURE__ */
|
|
6826
|
-
resource.availableScopes.map((scope) => /* @__PURE__ */
|
|
6827
|
-
/* @__PURE__ */
|
|
7345
|
+
/* @__PURE__ */ jsxs38("div", { style: { marginTop: 10 }, children: [
|
|
7346
|
+
resource.availableScopes.map((scope) => /* @__PURE__ */ jsxs38("label", { className: "b316-checkbox", children: [
|
|
7347
|
+
/* @__PURE__ */ jsx40(
|
|
6828
7348
|
"input",
|
|
6829
7349
|
{
|
|
6830
7350
|
type: "checkbox",
|
|
@@ -6834,19 +7354,19 @@ function ApiKeyManager({
|
|
|
6834
7354
|
)
|
|
6835
7355
|
}
|
|
6836
7356
|
),
|
|
6837
|
-
/* @__PURE__ */
|
|
6838
|
-
scope.description ? /* @__PURE__ */
|
|
7357
|
+
/* @__PURE__ */ jsx40("code", { children: scope.key }),
|
|
7358
|
+
scope.description ? /* @__PURE__ */ jsxs38("span", { className: "b316-muted", children: [
|
|
6839
7359
|
" \u2014 ",
|
|
6840
7360
|
scope.description
|
|
6841
7361
|
] }) : null
|
|
6842
7362
|
] }, scope.key)),
|
|
6843
|
-
resource.lockedScopes.map((scope) => /* @__PURE__ */
|
|
6844
|
-
/* @__PURE__ */
|
|
6845
|
-
/* @__PURE__ */
|
|
6846
|
-
/* @__PURE__ */
|
|
7363
|
+
resource.lockedScopes.map((scope) => /* @__PURE__ */ jsxs38("label", { className: "b316-checkbox b316-muted", children: [
|
|
7364
|
+
/* @__PURE__ */ jsx40("input", { type: "checkbox", disabled: true }),
|
|
7365
|
+
/* @__PURE__ */ jsx40("code", { children: scope.key }),
|
|
7366
|
+
/* @__PURE__ */ jsx40("span", { children: " \u2014 not included in your plan" })
|
|
6847
7367
|
] }, scope.key))
|
|
6848
7368
|
] }),
|
|
6849
|
-
/* @__PURE__ */
|
|
7369
|
+
/* @__PURE__ */ jsx40(
|
|
6850
7370
|
"button",
|
|
6851
7371
|
{
|
|
6852
7372
|
type: "button",
|
|
@@ -6880,7 +7400,7 @@ function ApiKeyManager({
|
|
|
6880
7400
|
children: "Create key"
|
|
6881
7401
|
}
|
|
6882
7402
|
),
|
|
6883
|
-
/* @__PURE__ */
|
|
7403
|
+
/* @__PURE__ */ jsx40(
|
|
6884
7404
|
"button",
|
|
6885
7405
|
{
|
|
6886
7406
|
type: "button",
|
|
@@ -6891,7 +7411,7 @@ function ApiKeyManager({
|
|
|
6891
7411
|
}
|
|
6892
7412
|
)
|
|
6893
7413
|
] }) : null,
|
|
6894
|
-
!creating && !issued ? /* @__PURE__ */
|
|
7414
|
+
!creating && !issued ? /* @__PURE__ */ jsx40(
|
|
6895
7415
|
"button",
|
|
6896
7416
|
{
|
|
6897
7417
|
type: "button",
|
|
@@ -6933,12 +7453,12 @@ var MANIFEST = [
|
|
|
6933
7453
|
},
|
|
6934
7454
|
{
|
|
6935
7455
|
name: "appearance",
|
|
6936
|
-
summary: "
|
|
7456
|
+
summary: "Colors, radius and font as tokens. Restyles everything at once.",
|
|
6937
7457
|
required: false
|
|
6938
7458
|
},
|
|
6939
7459
|
{
|
|
6940
7460
|
name: "tenant",
|
|
6941
|
-
summary: "White-label everything inside for one tenant \u2014 `{ organizationId }` or `{ organizationExternalId }`. A firm's name, logo and
|
|
7461
|
+
summary: "White-label everything inside for one tenant \u2014 `{ organizationId }` or `{ organizationExternalId }`. A firm's name, logo and colors on the screens it runs its clients on; its own branding, then its parent's, then the environment's. Change it when the user switches team.",
|
|
6942
7462
|
required: false
|
|
6943
7463
|
},
|
|
6944
7464
|
...appearance
|
|
@@ -6966,35 +7486,86 @@ var MANIFEST = [
|
|
|
6966
7486
|
{
|
|
6967
7487
|
name: "SignIn",
|
|
6968
7488
|
kind: "component",
|
|
6969
|
-
summary: "
|
|
7489
|
+
summary: "Sign in the ways the environment offers \u2014 password, magic link, passkeys, text message, social providers and SSO, as switched on in the dashboard (`GET /v1/auth/methods`).",
|
|
6970
7490
|
useWhen: "The application renders its own sign-in rather than redirecting to the hosted page.",
|
|
6971
7491
|
requires: [],
|
|
6972
7492
|
props: [
|
|
6973
7493
|
{ name: "onSignedIn", summary: "Called once a session exists.", required: false },
|
|
7494
|
+
{
|
|
7495
|
+
name: "password",
|
|
7496
|
+
summary: "`false` hides the password form. Every method prop can only turn a method off.",
|
|
7497
|
+
required: false
|
|
7498
|
+
},
|
|
6974
7499
|
{
|
|
6975
7500
|
name: "passkeys",
|
|
6976
|
-
summary: "
|
|
7501
|
+
summary: "`false` hides passkeys; otherwise offered where the environment and browser allow.",
|
|
6977
7502
|
required: false
|
|
6978
7503
|
},
|
|
7504
|
+
{ name: "magicLink", summary: "`false` hides the emailed sign-in link.", required: false },
|
|
6979
7505
|
{
|
|
6980
7506
|
name: "magicLinkRedirectUrl",
|
|
6981
|
-
summary: "Where an emailed link lands
|
|
7507
|
+
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.",
|
|
6982
7508
|
required: false
|
|
6983
7509
|
},
|
|
7510
|
+
{ name: "phone", summary: "`false` hides text-message codes.", required: false },
|
|
6984
7511
|
{
|
|
6985
|
-
name: "
|
|
6986
|
-
summary: "
|
|
7512
|
+
name: "social",
|
|
7513
|
+
summary: "`false` hides the social buttons; a list of slugs keeps only those providers.",
|
|
6987
7514
|
required: false
|
|
6988
7515
|
},
|
|
7516
|
+
{ name: "sso", summary: '`false` hides "Sign in with SSO".', required: false },
|
|
7517
|
+
{
|
|
7518
|
+
name: "socialRedirectUrl",
|
|
7519
|
+
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.",
|
|
7520
|
+
required: false
|
|
7521
|
+
},
|
|
7522
|
+
{
|
|
7523
|
+
name: "socialState",
|
|
7524
|
+
summary: "A short value carried through a social or SSO sign-in, returned by `readOAuthState`.",
|
|
7525
|
+
required: false
|
|
7526
|
+
},
|
|
7527
|
+
{ name: "labels", summary: "Wording for the form, for translation.", required: false },
|
|
6989
7528
|
{
|
|
6990
7529
|
name: "secondFactorLabels",
|
|
6991
|
-
summary: "Wording for the second-factor step (code box, or
|
|
7530
|
+
summary: "Wording for the second-factor step (code box, or enrollment when the environment requires a factor and the user has none), for translation. English when omitted.",
|
|
6992
7531
|
required: false
|
|
6993
7532
|
},
|
|
6994
7533
|
...appearance
|
|
6995
7534
|
],
|
|
6996
7535
|
seeAlso: ["SignUp", "ForgotPassword", "SecondFactorStep"]
|
|
6997
7536
|
},
|
|
7537
|
+
{
|
|
7538
|
+
name: "SocialSignIn",
|
|
7539
|
+
kind: "component",
|
|
7540
|
+
summary: `The environment's social sign-in buttons alone ("Continue with Google"), for a sign-in or sign-up form you draw yourself.`,
|
|
7541
|
+
useWhen: "Your own form needs the social providers switched on in the dashboard. SignIn and SignUp already include them.",
|
|
7542
|
+
requires: [],
|
|
7543
|
+
props: [
|
|
7544
|
+
{
|
|
7545
|
+
name: "socialRedirectUrl",
|
|
7546
|
+
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.",
|
|
7547
|
+
required: false
|
|
7548
|
+
},
|
|
7549
|
+
{
|
|
7550
|
+
name: "socialState",
|
|
7551
|
+
summary: "A short value carried through, returned by `readOAuthState`.",
|
|
7552
|
+
required: false
|
|
7553
|
+
},
|
|
7554
|
+
{
|
|
7555
|
+
name: "social",
|
|
7556
|
+
summary: "`false` hides every button; a list of slugs keeps only those providers.",
|
|
7557
|
+
required: false
|
|
7558
|
+
},
|
|
7559
|
+
{
|
|
7560
|
+
name: "intent",
|
|
7561
|
+
summary: "`sign-up` hides the buttons when the environment is closed to new accounts.",
|
|
7562
|
+
required: false
|
|
7563
|
+
},
|
|
7564
|
+
{ name: "divider", summary: 'Draw an "or" rule under the buttons.', required: false },
|
|
7565
|
+
{ name: "labels", summary: "`continueWith` and `or`, for translation.", required: false }
|
|
7566
|
+
],
|
|
7567
|
+
seeAlso: ["SignIn", "SignUp"]
|
|
7568
|
+
},
|
|
6998
7569
|
{
|
|
6999
7570
|
name: "SignUp",
|
|
7000
7571
|
kind: "component",
|
|
@@ -7023,6 +7594,21 @@ var MANIFEST = [
|
|
|
7023
7594
|
summary: "Wording for the second-factor step, for translation.",
|
|
7024
7595
|
required: false
|
|
7025
7596
|
},
|
|
7597
|
+
{
|
|
7598
|
+
name: "social",
|
|
7599
|
+
summary: "`false` hides the social buttons; a list of slugs keeps only those providers.",
|
|
7600
|
+
required: false
|
|
7601
|
+
},
|
|
7602
|
+
{
|
|
7603
|
+
name: "socialRedirectUrl",
|
|
7604
|
+
summary: "Where a social sign-up returns with `?code=&state=`, as on SignIn. Without it no social button is shown.",
|
|
7605
|
+
required: false
|
|
7606
|
+
},
|
|
7607
|
+
{
|
|
7608
|
+
name: "socialState",
|
|
7609
|
+
summary: "A short value carried through a social sign-up, returned by `readOAuthState`.",
|
|
7610
|
+
required: false
|
|
7611
|
+
},
|
|
7026
7612
|
...appearance
|
|
7027
7613
|
],
|
|
7028
7614
|
seeAlso: ["SignIn", "VerifyEmail", "SecondFactorStep"]
|
|
@@ -7316,10 +7902,20 @@ var MANIFEST = [
|
|
|
7316
7902
|
props: [],
|
|
7317
7903
|
seeAlso: ["PricingTable"]
|
|
7318
7904
|
},
|
|
7905
|
+
{
|
|
7906
|
+
name: "useAddons",
|
|
7907
|
+
kind: "hook",
|
|
7908
|
+
summary: "The signed-in user's addons and the ones on sale for their plan, with buy, resize and remove \u2014 settled by the API (more now and charged for the rest of the period, fewer at the period end). No markup.",
|
|
7909
|
+
useWhen: "You sell extras on top of a plan (more apps, seats, storage) as self-serve addons.",
|
|
7910
|
+
requires: ["session"],
|
|
7911
|
+
props: [],
|
|
7912
|
+
whenUnmet: "Loads nothing without a session; `lastError` carries the API's code.",
|
|
7913
|
+
seeAlso: ["usePlans", "SubscriptionManager"]
|
|
7914
|
+
},
|
|
7319
7915
|
{
|
|
7320
7916
|
name: "SubscriptionManager",
|
|
7321
7917
|
kind: "component",
|
|
7322
|
-
summary: "The current plan, its renewal date, a scheduled plan change with its undo,
|
|
7918
|
+
summary: "The current plan, its renewal date, a scheduled plan change with its undo, canceling at the period end \u2014 asking why, and showing the environment's retention offer when it makes one \u2014 and resuming a canceled one.",
|
|
7323
7919
|
useWhen: "A billing settings page.",
|
|
7324
7920
|
requires: ["session"],
|
|
7325
7921
|
props: [
|
|
@@ -7600,7 +8196,7 @@ var MANIFEST = [
|
|
|
7600
8196
|
{
|
|
7601
8197
|
name: "Chart",
|
|
7602
8198
|
kind: "component",
|
|
7603
|
-
summary: "Records over time, counted or
|
|
8199
|
+
summary: "Records over time, counted or totaled.",
|
|
7604
8200
|
useWhen: "The question is how many or how much, by day, week or month.",
|
|
7605
8201
|
requires: ["session", "collection"],
|
|
7606
8202
|
bindsToCollection: true,
|
|
@@ -7794,6 +8390,7 @@ export {
|
|
|
7794
8390
|
SecondFactorStep,
|
|
7795
8391
|
SignIn,
|
|
7796
8392
|
SignUp,
|
|
8393
|
+
SocialSignIn,
|
|
7797
8394
|
SubscriptionManager,
|
|
7798
8395
|
TeamMembers,
|
|
7799
8396
|
TwoFactorManager,
|
|
@@ -7802,6 +8399,7 @@ export {
|
|
|
7802
8399
|
VerifyEmail,
|
|
7803
8400
|
componentsRequiring,
|
|
7804
8401
|
describeComponent,
|
|
8402
|
+
useAddons,
|
|
7805
8403
|
useBase316,
|
|
7806
8404
|
useCollection,
|
|
7807
8405
|
usePaymentLink,
|