@base316/react 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider.tsx","../src/appearance.ts","../src/Branding.tsx","../src/Invoices.tsx","../src/SignIn.tsx","../src/SignUp.tsx","../src/UserProfile.tsx","../src/PasskeyManager.tsx","../src/PricingTable.tsx","../src/SubscriptionManager.tsx"],"sourcesContent":["\"use client\";\n\nimport { Base316Browser } from \"@base316/sdk\";\nimport type { Branding as BrandingInfo, ResolvedSession } from \"@base316/sdk\";\nimport {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseState,\n\ttype ReactNode,\n} from \"react\";\n\nimport {\n\tappearanceToStyle,\n\tSTYLESHEET,\n\tSTYLESHEET_EXTRA,\n\tSTYLE_ELEMENT_ID,\n\ttype Base316Appearance,\n} from \"./appearance\";\n\n/**\n * Shared state for the Base316 components.\n *\n * Holds one browser client and the end user's session. The session token is the\n * credential these components send alongside the publishable key: the key says\n * which environment, the token says who, and billing answers need both.\n *\n * The token is kept in `localStorage` by default because that is what a\n * single-page app needs to survive a refresh. An application that would rather\n * hold it in an httpOnly cookie can pass `token` and `onTokenChange` and own\n * the storage itself — which is the better choice if the app has a server.\n */\n\ninterface Base316ContextValue {\n\tclient: Base316Browser;\n\t/** The environment's logo, name and colours. Null until it loads. */\n\tbranding: BrandingInfo | null;\n\ttoken: string | null;\n\tsetToken: (token: string | null) => void;\n\tsession: ResolvedSession | null;\n\tloading: boolean;\n\trefresh: () => Promise<void>;\n\tsignOut: () => Promise<void>;\n}\n\nconst Base316Context = createContext<Base316ContextValue | null>(null);\n\nconst STORAGE_KEY = \"base316.session\";\n\nfunction readStoredToken(): string | null {\n\ttry {\n\t\treturn window.localStorage.getItem(STORAGE_KEY);\n\t} catch {\n\t\t// Private browsing and blocked site data both throw here. A signed-out\n\t\t// render is correct in that case, not a crash.\n\t\treturn null;\n\t}\n}\n\nfunction writeStoredToken(token: string | null): void {\n\ttry {\n\t\tif (token === null) {\n\t\t\twindow.localStorage.removeItem(STORAGE_KEY);\n\t\t} else {\n\t\t\twindow.localStorage.setItem(STORAGE_KEY, token);\n\t\t}\n\t} catch {\n\t\t// Nothing to do: the session simply will not survive a refresh.\n\t}\n}\n\nexport function Base316Provider({\n\tpublishableKey,\n\tbaseUrl,\n\ttoken: controlledToken,\n\tonTokenChange,\n\tappearance,\n\tclassName,\n\tchildren,\n}: {\n\tpublishableKey: string;\n\tbaseUrl?: string;\n\t/** Supply this to own session storage yourself. */\n\ttoken?: string | null;\n\tonTokenChange?: (token: string | null) => void;\n\t/** Colours, radius and font, as tokens. See `Base316Appearance`. */\n\tappearance?: Base316Appearance;\n\t/** Your own classes on the wrapper — a Tailwind scope, for instance. */\n\tclassName?: string;\n\tchildren: ReactNode;\n}) {\n\tconst client = useMemo(\n\t\t() => new Base316Browser({ publishableKey, baseUrl }),\n\t\t[publishableKey, baseUrl],\n\t);\n\n\t// Injected once per document rather than imported. The package ships as\n\t// source, and a bare `import \"./styles.css\"` would force every consumer to\n\t// have a CSS loader configured before anything would render at all.\n\tuseEffect(() => {\n\t\tif (document.getElementById(STYLE_ELEMENT_ID)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst element = document.createElement(\"style\");\n\t\telement.id = STYLE_ELEMENT_ID;\n\t\telement.textContent = STYLESHEET + STYLESHEET_EXTRA;\n\t\tdocument.head.appendChild(element);\n\t}, []);\n\n\tconst controlled = controlledToken !== undefined;\n\tconst [internalToken, setInternalToken] = useState<string | null>(null);\n\tconst [session, setSession] = useState<ResolvedSession | null>(null);\n\tconst [branding, setBranding] = useState<BrandingInfo | null>(null);\n\tconst [loading, setLoading] = useState(true);\n\n\tconst token = controlled ? controlledToken : internalToken;\n\n\t// Read storage after mount rather than in the initial state, so a server\n\t// render and the first client render agree and React does not warn.\n\tuseEffect(() => {\n\t\tif (controlled) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetInternalToken(readStoredToken());\n\t}, [controlled]);\n\n\t// Branding needs only the publishable key, so it loads independently of the\n\t// session and is available on a signed-out page too.\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\n\t\tclient.billing\n\t\t\t.branding()\n\t\t\t.then((result) => {\n\t\t\t\tif (!cancelled) setBranding(result);\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\t// A page without branding is still usable: the components that show\n\t\t\t\t// it render nothing rather than blocking everything else.\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [client]);\n\n\tconst setToken = useCallback(\n\t\t(next: string | null) => {\n\t\t\tif (controlled) {\n\t\t\t\tonTokenChange?.(next);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twriteStoredToken(next);\n\t\t\tsetInternalToken(next);\n\t\t\tonTokenChange?.(next);\n\t\t},\n\t\t[controlled, onTokenChange],\n\t);\n\n\tconst refresh = useCallback(async () => {\n\t\tif (!token) {\n\t\t\tsetSession(null);\n\t\t\tsetLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tsetSession(await client.auth.session(token));\n\t\t} catch {\n\t\t\t// An expired or revoked token is indistinguishable from a bad one and\n\t\t\t// both mean the same thing here: this browser is signed out.\n\t\t\tsetSession(null);\n\t\t\tsetToken(null);\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t}, [client, token, setToken]);\n\n\tuseEffect(() => {\n\t\tsetLoading(true);\n\t\tvoid refresh();\n\t}, [refresh]);\n\n\tconst signOut = useCallback(async () => {\n\t\tif (token) {\n\t\t\tawait client.auth.signOut(token).catch(() => {\n\t\t\t\t// The local session is cleared regardless: a failed revoke must not\n\t\t\t\t// leave someone apparently still signed in.\n\t\t\t});\n\t\t}\n\n\t\tsetToken(null);\n\t\tsetSession(null);\n\t}, [client, token, setToken]);\n\n\tconst value = useMemo(\n\t\t() => ({ client, branding, token, setToken, session, loading, refresh, signOut }),\n\t\t[client, branding, token, setToken, session, loading, refresh, signOut],\n\t);\n\n\treturn (\n\t\t<Base316Context.Provider value={value}>\n\t\t\t<div\n\t\t\t\tclassName={className ? `b316-root ${className}` : \"b316-root\"}\n\t\t\t\tstyle={appearanceToStyle({\n\t\t\t\t\t// Whatever was set in the sign-in designer arrives here, so a\n\t\t\t\t\t// customer styles their login once on Base316 and the embedded\n\t\t\t\t\t// components follow — rather than configuring the same colours\n\t\t\t\t\t// twice and watching them drift apart.\n\t\t\t\t\t//\n\t\t\t\t\t// An explicit `appearance` still wins, because a host that has\n\t\t\t\t\t// gone to the trouble of passing tokens means them.\n\t\t\t\t\t...(branding\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tcolorPrimary: branding.primaryColor,\n\t\t\t\t\t\t\t\tcolorBackground: branding.backgroundColor,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...appearance,\n\t\t\t\t})}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</Base316Context.Provider>\n\t);\n}\n\nexport function useBase316(): Base316ContextValue {\n\tconst value = useContext(Base316Context);\n\n\tif (!value) {\n\t\tthrow new Error(\"Base316 components must be rendered inside <Base316Provider>.\");\n\t}\n\n\treturn value;\n}\n\n/** The signed-in user, or null. `loading` distinguishes \"no one\" from \"not yet\". */\nexport function useSession(): { session: ResolvedSession | null; loading: boolean } {\n\tconst { session, loading } = useBase316();\n\treturn { session, loading };\n}\n","import type { CSSProperties } from \"react\";\n\n/**\n * How these components are styled, and why it works this way.\n *\n * They drop into an application whose CSS we cannot see. Three approaches were\n * possible and only one of them is actually controllable by the host:\n *\n * - Inline styles are self-contained but *unoverridable* — they beat any\n * stylesheet short of `!important`, so a customer cannot restyle anything.\n * - A shipped stylesheet fights the host's cascade unpredictably.\n * - CSS custom properties, with every value read through a variable, let the\n * host restyle without either side guessing at specificity.\n *\n * So: one small stylesheet, injected once, with every colour, radius and font\n * behind a `--b316-*` variable. A customer can restyle in three ways, from\n * least to most invasive:\n *\n * 1. `appearance` on the provider — tokens, no CSS to write.\n * 2. Their own CSS targeting the `b316-*` class names.\n * 3. `className` on any component, to hand it their own utility classes.\n *\n * Nothing here inherits the host's design automatically. That is deliberate:\n * silently absorbing whatever `body { font }` and `button { }` rules exist\n * produces components that look broken in ways neither side can predict.\n */\n\nexport interface Base316Appearance {\n\t/** Buttons, links, focus rings. */\n\tcolorPrimary?: string;\n\t/** Text on primary-coloured surfaces. */\n\tcolorPrimaryText?: string;\n\tcolorText?: string;\n\tcolorMuted?: string;\n\tcolorBackground?: string;\n\tcolorBorder?: string;\n\tcolorDanger?: string;\n\tcolorDangerBackground?: string;\n\tcolorSuccess?: string;\n\tborderRadius?: string;\n\tfontFamily?: string;\n\tfontSize?: string;\n\tspacing?: string;\n}\n\nconst VARIABLES: Record<keyof Base316Appearance, string> = {\n\tcolorPrimary: \"--b316-color-primary\",\n\tcolorPrimaryText: \"--b316-color-primary-text\",\n\tcolorText: \"--b316-color-text\",\n\tcolorMuted: \"--b316-color-muted\",\n\tcolorBackground: \"--b316-color-background\",\n\tcolorBorder: \"--b316-color-border\",\n\tcolorDanger: \"--b316-color-danger\",\n\tcolorDangerBackground: \"--b316-color-danger-bg\",\n\tcolorSuccess: \"--b316-color-success\",\n\tborderRadius: \"--b316-radius\",\n\tfontFamily: \"--b316-font\",\n\tfontSize: \"--b316-font-size\",\n\tspacing: \"--b316-spacing\",\n};\n\n/** Turn the token object into inline custom properties for the root element. */\nexport function appearanceToStyle(appearance?: Base316Appearance): CSSProperties {\n\tif (!appearance) {\n\t\treturn {};\n\t}\n\n\tconst style: Record<string, string> = {};\n\n\tfor (const [key, variable] of Object.entries(VARIABLES)) {\n\t\tconst value = appearance[key as keyof Base316Appearance];\n\n\t\tif (value !== undefined) {\n\t\t\tstyle[variable] = value;\n\t\t}\n\t}\n\n\treturn style as CSSProperties;\n}\n\nexport const STYLE_ELEMENT_ID = \"base316-components\";\n\n/**\n * The stylesheet, injected once per document.\n *\n * Defaults live on `.b316-root` rather than `:root` so an application that\n * never sets a token still gets a coherent look, and one that sets tokens on a\n * parent still wins through normal inheritance.\n */\nexport const STYLESHEET = `\n.b316-root {\n --b316-color-primary: #111827;\n --b316-color-primary-text: #ffffff;\n --b316-color-text: #111827;\n --b316-color-muted: #6b7280;\n --b316-color-background: #ffffff;\n --b316-color-border: #e5e7eb;\n --b316-color-danger: #991b1b;\n --b316-color-danger-bg: #fef2f2;\n --b316-color-success: #166534;\n --b316-radius: 12px;\n --b316-font: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n --b316-font-size: 15px;\n --b316-spacing: 12px;\n\n font-family: var(--b316-font);\n font-size: var(--b316-font-size);\n line-height: 1.5;\n color: var(--b316-color-text);\n}\n\n.b316-card {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n padding: calc(var(--b316-spacing) * 1.6);\n background: var(--b316-color-background);\n}\n\n.b316-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--b316-spacing); }\n.b316-label { font-size: 0.87em; color: var(--b316-color-muted); }\n\n.b316-input {\n padding: 9px 11px;\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) / 1.6);\n font: inherit;\n color: inherit;\n background: var(--b316-color-background);\n}\n.b316-input:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n\n.b316-button {\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.b316-button:hover:not([disabled]) { filter: brightness(1.12); }\n.b316-button:active:not([disabled]) { transform: translateY(1px); }\n.b316-button:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n.b316-button[disabled] { opacity: .55; cursor: not-allowed; }\n\n.b316-button-secondary {\n width: auto;\n transition: background-color .12s ease;\n background: var(--b316-color-background);\n color: var(--b316-color-text);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n}\n\n.b316-button-link {\n width: auto;\n background: none;\n border: 0;\n padding: 0;\n color: var(--b316-color-primary);\n font: inherit;\n cursor: pointer;\n text-decoration: underline;\n}\n\n.b316-error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-muted { color: var(--b316-color-muted); font-size: 0.87em; }\n.b316-success { color: var(--b316-color-success); }\n\n.b316-plans {\n display: grid;\n gap: calc(var(--b316-spacing) * 1.3);\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n align-items: stretch;\n}\n\n.b316-plan {\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n}\n\n/* The recommended plan. Lifted rather than merely tinted: on a pricing table\n the eye needs one obvious default, and colour alone does not survive being\n viewed in greyscale or by someone who cannot distinguish the accent. */\n.b316-plan-featured {\n border-color: var(--b316-color-primary);\n box-shadow: 0 0 0 1px var(--b316-color-primary);\n}\n\n.b316-plan-badge {\n display: inline-block;\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n border-radius: 999px;\n padding: 2px 9px;\n font-size: 0.75em;\n font-weight: 600;\n letter-spacing: .02em;\n margin-bottom: 8px;\n}\n\n/* Occupies the badge's height without drawing anything, so a featured card\n does not push its own price and features out of line with the others. */\n.b316-plan-badge-spacer {\n display: inline-block;\n padding: 2px 9px;\n font-size: 0.75em;\n margin-bottom: 8px;\n visibility: hidden;\n}\n\n.b316-plan-head { padding: calc(var(--b316-spacing) * 1.6); padding-bottom: 0; }\n.b316-plan-name { font-weight: 600; font-size: 1.06em; }\n.b316-plan-desc { color: var(--b316-color-muted); font-size: 0.87em; margin-top: 2px; }\n\n.b316-plan-pricing { padding: 0 calc(var(--b316-spacing) * 1.6) calc(var(--b316-spacing) * 1.4); }\n\n.b316-plan-price {\n font-size: 2.1em;\n font-weight: 640;\n letter-spacing: -.02em;\n margin-top: calc(var(--b316-spacing) * 0.7);\n /* Lining figures of even width, so prices do not shimmer between cards. */\n font-variant-numeric: tabular-nums lining-nums;\n}\n\n.b316-plan-cadence { color: var(--b316-color-muted); font-size: 0.87em; min-height: 1.35em; }\n.b316-plan-trial { color: var(--b316-color-success); font-size: 0.87em; min-height: 1.35em; }\n\n.b316-plan-features {\n list-style: none;\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n margin: 0;\n flex: 1;\n border-top: 1px solid var(--b316-color-border);\n}\n.b316-plan-feature {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding: 5px 0;\n font-size: 0.94em;\n}\n.b316-plan-feature-value { color: var(--b316-color-muted); font-variant-numeric: tabular-nums; }\n\n.b316-plan-action {\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n border-top: 1px solid var(--b316-color-border);\n}\n\n/* The plan already held. A faded primary button reads as broken rather than\n as \"you are here\", so this is a flat, quiet, genuinely inert surface. */\n.b316-button-current,\n.b316-button-current[disabled] {\n background: transparent;\n color: var(--b316-color-muted);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n opacity: 1;\n cursor: default;\n}\n\n.b316-row { display: flex; justify-content: space-between; gap: 16px; align-items: center; }\n`;\n\n/** Join the component's own class with any the host passed in. */\nexport function cls(base: string, extra?: string): string {\n\treturn extra ? `${base} ${extra}` : base;\n}\n\n/**\n * Branding and invoice styles.\n *\n * Appended as a second block so the print rules stay next to the invoice they\n * apply to, rather than being buried in the middle of the component styles.\n */\nexport const STYLESHEET_EXTRA = `\n.b316-branding { display: flex; flex-direction: column; gap: 4px; }\n.b316-branding-logo { max-height: 40px; width: auto; align-self: flex-start; }\n.b316-branding-name { font-size: 1.5em; font-weight: 650; letter-spacing: -.01em; }\n.b316-branding-tagline { color: var(--b316-color-muted); }\n\n.b316-invoice-table { width: 100%; border-collapse: collapse; font-size: 0.94em; }\n.b316-invoice-table th {\n text-align: left;\n font-weight: 500;\n color: var(--b316-color-muted);\n font-size: 0.85em;\n padding: 0 0 6px;\n border-bottom: 1px solid var(--b316-color-border);\n}\n.b316-invoice-table td { padding: 9px 0; border-bottom: 1px solid var(--b316-color-border); }\n/* Columns need breathing room or the amount runs straight into the action —\n \"$49.00View\" — which is what happens when only the row has padding. */\n.b316-invoice-table th + th,\n.b316-invoice-table td + td { padding-left: 16px; }\n.b316-invoice-table td:last-child,\n.b316-invoice-table th:last-child { text-align: right; width: 1%; white-space: nowrap; }\n.b316-invoice-table tr:last-child td { border-bottom: 0; }\n.b316-num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.b316-invoice-view {\n margin-top: calc(var(--b316-spacing) * 1.4);\n border-top: 1px solid var(--b316-color-border);\n padding-top: calc(var(--b316-spacing) * 1.4);\n}\n.b316-invoice-actions { display: flex; gap: 8px; justify-content: flex-end; margin-bottom: var(--b316-spacing); }\n.b316-invoice-doc { display: flex; flex-direction: column; gap: calc(var(--b316-spacing) * 1.4); }\n.b316-invoice-meta { display: grid; grid-template-columns: 1fr 1fr; gap: var(--b316-spacing); }\n.b316-invoice-totals { display: flex; flex-direction: column; gap: 6px; margin-left: auto; min-width: 240px; }\n.b316-invoice-total { font-weight: 650; border-top: 1px solid var(--b316-color-border); padding-top: 6px; }\n\n/* Printing emits the invoice alone. Without this the browser would paginate the\n whole application around it, which is not something anyone wants to file. */\n@media print {\n body * { visibility: hidden; }\n .b316-invoice-doc, .b316-invoice-doc * { visibility: visible; }\n .b316-invoice-doc {\n position: absolute;\n inset: 0 auto auto 0;\n width: 100%;\n padding: 24px;\n }\n .b316-invoice-actions { display: none; }\n}\n`;\n","\"use client\";\n\nimport type { CSSProperties } from \"react\";\n\nimport { cls } from \"./appearance\";\nimport { useBase316 } from \"./provider\";\n\n/**\n * The customer's logo, name and tagline, as configured in the dashboard.\n *\n * `brandDisplay` decides which of the logo and the name is shown, so an\n * application's own header matches the Base316-hosted sign-in page without the\n * customer setting their brand up twice. `LOGO` still renders the name as the\n * image's alt text, because a logo that fails to load must not leave the page\n * anonymous.\n */\nexport function Branding({\n\tshowTagline = true,\n\tclassName,\n\tstyle,\n}: {\n\tshowTagline?: boolean;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}) {\n\tconst { branding } = useBase316();\n\n\tif (!branding) {\n\t\treturn null;\n\t}\n\n\tconst showLogo = branding.logoUrl && branding.brandDisplay !== \"NAME\";\n\tconst showName = branding.brandDisplay !== \"LOGO\" || !branding.logoUrl;\n\n\treturn (\n\t\t<div className={cls(\"b316-branding\", className)} style={style}>\n\t\t\t{showLogo ? (\n\t\t\t\t<img className=\"b316-branding-logo\" src={branding.logoUrl!} alt={branding.brandName} />\n\t\t\t) : null}\n\t\t\t{showName ? <div className=\"b316-branding-name\">{branding.brandName}</div> : null}\n\t\t\t{showTagline && branding.tagline ? (\n\t\t\t\t<div className=\"b316-branding-tagline\">{branding.tagline}</div>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","\"use client\";\n\nimport type { InvoiceDetail, InvoiceSummary } from \"@base316/sdk\";\nimport { useCallback, useEffect, useState, type CSSProperties } from \"react\";\n\nimport { cls } from \"./appearance\";\nimport { useBase316 } from \"./provider\";\n\nfunction money(amount: string, currency: string): string {\n\tconst value = Number(amount);\n\n\tif (!Number.isFinite(value)) {\n\t\treturn `${amount} ${currency}`;\n\t}\n\n\ttry {\n\t\treturn new Intl.NumberFormat(undefined, { style: \"currency\", currency }).format(value);\n\t} catch {\n\t\treturn `${value} ${currency}`;\n\t}\n}\n\nfunction day(value: string | null): string {\n\treturn value ? new Date(value).toLocaleDateString() : \"—\";\n}\n\n/**\n * The signed-in user's invoices, and a way to keep one.\n *\n * Downloading is done by printing a rendered invoice rather than by fetching a\n * PDF: there is no PDF renderer on the server, and adding one is a real\n * dependency decision rather than something to slip in here. Print-to-PDF is\n * built into every browser, produces a selectable-text document, and needs\n * nothing installed — so the button opens the invoice and prints it.\n *\n * Drafts never appear. They are the rating engine's working state and can still\n * change, so showing one as a bill would be wrong.\n */\nexport function Invoices({ className, style }: { className?: string; style?: CSSProperties }) {\n\tconst { client, token, loading: sessionLoading } = useBase316();\n\tconst [invoices, setInvoices] = useState<InvoiceSummary[] | null>(null);\n\tconst [open, setOpen] = useState<InvoiceDetail | null>(null);\n\tconst [error, setError] = useState<string | null>(null);\n\n\tuseEffect(() => {\n\t\tif (!token) {\n\t\t\tsetInvoices([]);\n\t\t\treturn;\n\t\t}\n\n\t\tlet cancelled = false;\n\n\t\tclient.billing\n\t\t\t.invoices(token)\n\t\t\t.then((result) => {\n\t\t\t\tif (!cancelled) setInvoices(result.data);\n\t\t\t})\n\t\t\t.catch((cause) => {\n\t\t\t\tconsole.error(\"[base316] could not load invoices\", cause);\n\t\t\t\tif (!cancelled) setError(\"Could not load your invoices.\");\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [client, token]);\n\n\tconst view = useCallback(\n\t\tasync (id: string) => {\n\t\t\tif (!token) return;\n\n\t\t\ttry {\n\t\t\t\tsetOpen(await client.billing.invoice(token, id));\n\t\t\t} catch (cause) {\n\t\t\t\tconsole.error(\"[base316] could not load the invoice\", cause);\n\t\t\t\tsetError(\"Could not open that invoice.\");\n\t\t\t}\n\t\t},\n\t\t[client, token],\n\t);\n\n\tif (sessionLoading || invoices === null) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tLoading…\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!token) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tSign in to see your invoices.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (invoices.length === 0) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tNo invoices yet.\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className={cls(\"b316-card b316-invoices\", className)} style={style}>\n\t\t\t{error ? <div className=\"b316-error\">{error}</div> : null}\n\n\t\t\t<table className=\"b316-invoice-table\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>Invoice</th>\n\t\t\t\t\t\t<th>Period</th>\n\t\t\t\t\t\t<th>Status</th>\n\t\t\t\t\t\t<th className=\"b316-num\">Total</th>\n\t\t\t\t\t\t<th />\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t{invoices.map((invoice) => (\n\t\t\t\t\t\t<tr key={invoice.id}>\n\t\t\t\t\t\t\t<td>{invoice.number}</td>\n\t\t\t\t\t\t\t<td className=\"b316-muted\">\n\t\t\t\t\t\t\t\t{day(invoice.periodStart)} – {day(invoice.periodEnd)}\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t<td className=\"b316-muted\">{invoice.status.toLowerCase()}</td>\n\t\t\t\t\t\t\t<td className=\"b316-num\">{money(invoice.total, invoice.currency)}</td>\n\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"b316-button b316-button-link\"\n\t\t\t\t\t\t\t\t\tonClick={() => void view(invoice.id)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tView\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t))}\n\t\t\t\t</tbody>\n\t\t\t</table>\n\n\t\t\t{open ? <InvoiceView invoice={open} onClose={() => setOpen(null)} /> : null}\n\t\t</div>\n\t);\n}\n\n/**\n * One invoice, laid out to be printed.\n *\n * `b316-print-only` and the print stylesheet mean the browser's print dialog\n * emits just this document rather than the whole application around it.\n */\nfunction InvoiceView({ invoice, onClose }: { invoice: InvoiceDetail; onClose: () => void }) {\n\treturn (\n\t\t<div className=\"b316-invoice-view\">\n\t\t\t<div className=\"b316-invoice-actions\">\n\t\t\t\t<button type=\"button\" className=\"b316-button b316-button-secondary\" onClick={onClose}>\n\t\t\t\t\tClose\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"b316-button b316-button-secondary\"\n\t\t\t\t\tonClick={() => window.print()}\n\t\t\t\t>\n\t\t\t\t\tDownload PDF\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div className=\"b316-invoice-doc\">\n\t\t\t\t<div className=\"b316-row\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"b316-plan-name\">{invoice.issuer.brandName}</div>\n\t\t\t\t\t\t{invoice.issuer.supportEmail ? (\n\t\t\t\t\t\t\t<div className=\"b316-muted\">{invoice.issuer.supportEmail}</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div style={{ textAlign: \"right\" }}>\n\t\t\t\t\t\t<div className=\"b316-plan-name\">{invoice.number}</div>\n\t\t\t\t\t\t<div className=\"b316-muted\">{invoice.status.toLowerCase()}</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"b316-invoice-meta\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"b316-label\">Billed to</div>\n\t\t\t\t\t\t<div>{invoice.customer.name ?? invoice.customer.email ?? \"—\"}</div>\n\t\t\t\t\t\t{invoice.customer.name && invoice.customer.email ? (\n\t\t\t\t\t\t\t<div className=\"b316-muted\">{invoice.customer.email}</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div className=\"b316-label\">Period</div>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t{day(invoice.periodStart)} – {day(invoice.periodEnd)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"b316-muted\">Issued {day(invoice.issuedAt)}</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t<table className=\"b316-invoice-table\">\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>Description</th>\n\t\t\t\t\t\t\t<th className=\"b316-num\">Qty</th>\n\t\t\t\t\t\t\t<th className=\"b316-num\">Unit</th>\n\t\t\t\t\t\t\t<th className=\"b316-num\">Amount</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{invoice.lineItems.map((line) => (\n\t\t\t\t\t\t\t<tr key={line.id}>\n\t\t\t\t\t\t\t\t<td>{line.description}</td>\n\t\t\t\t\t\t\t\t<td className=\"b316-num b316-muted\">\n\t\t\t\t\t\t\t\t\t{/* Billable, not consumed: the difference is the included\n\t\t\t\t\t\t\t\t\t allowance, and charging it would be wrong. */}\n\t\t\t\t\t\t\t\t\t{line.billable}\n\t\t\t\t\t\t\t\t\t{line.unit ? ` ${line.unit}` : \"\"}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td className=\"b316-num b316-muted\">\n\t\t\t\t\t\t\t\t\t{line.unitAmount === null ? \"—\" : money(line.unitAmount, invoice.currency)}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td className=\"b316-num\">{money(line.amount, invoice.currency)}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\n\t\t\t\t<div className=\"b316-invoice-totals\">\n\t\t\t\t\t<div className=\"b316-row\">\n\t\t\t\t\t\t<span className=\"b316-muted\">Subtotal</span>\n\t\t\t\t\t\t<span className=\"b316-num\">{money(invoice.subtotal, invoice.currency)}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{Number(invoice.discountTotal) > 0 ? (\n\t\t\t\t\t\t<div className=\"b316-row\">\n\t\t\t\t\t\t\t<span className=\"b316-muted\">Discount</span>\n\t\t\t\t\t\t\t<span className=\"b316-num\">−{money(invoice.discountTotal, invoice.currency)}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{Number(invoice.taxTotal) > 0 ? (\n\t\t\t\t\t\t<div className=\"b316-row\">\n\t\t\t\t\t\t\t<span className=\"b316-muted\">Tax</span>\n\t\t\t\t\t\t\t<span className=\"b316-num\">{money(invoice.taxTotal, invoice.currency)}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<div className=\"b316-row b316-invoice-total\">\n\t\t\t\t\t\t<span>Total</span>\n\t\t\t\t\t\t<span className=\"b316-num\">{money(invoice.total, invoice.currency)}</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{Number(invoice.amountPaid) > 0 ? (\n\t\t\t\t\t\t<div className=\"b316-row\">\n\t\t\t\t\t\t\t<span className=\"b316-muted\">Paid</span>\n\t\t\t\t\t\t\t<span className=\"b316-num\">{money(invoice.amountPaid, invoice.currency)}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","\"use client\";\n\nimport {\n\tisPasskeyAutofillAvailable,\n\tisPasskeySupported,\n\tneedsSecondFactor,\n} from \"@base316/sdk\";\nimport { useEffect, useRef, useState, type CSSProperties, type FormEvent } from \"react\";\n\nimport { cls } from \"./appearance\";\nimport { useBase316 } from \"./provider\";\n\n/**\n * Email and password sign-in.\n *\n * Handles the MFA branch, because an account with a second factor gets a\n * challenge instead of a session, and a form that ignores that case appears to\n * fail for exactly the users who most need it to work.\n */\nexport function SignIn({\n\tonSignedIn,\n\tpasskeys = true,\n\tclassName,\n\tstyle,\n}: {\n\tonSignedIn?: () => void;\n\t/** Offer passkeys alongside the password. On by default where supported. */\n\tpasskeys?: boolean;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}) {\n\tconst { client, setToken } = useBase316();\n\tconst [email, setEmail] = useState(\"\");\n\tconst [password, setPassword] = useState(\"\");\n\tconst [code, setCode] = useState(\"\");\n\tconst [pendingUserId, setPendingUserId] = useState<string | null>(null);\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\n\t// Whether to draw a passkey button at all. Resolved in an effect rather than\n\t// during render: it asks the browser, and it is false on the server.\n\tconst [passkeyReady, setPasskeyReady] = useState(false);\n\tconst abortRef = useRef<AbortController | null>(null);\n\n\tconst signInWithPasskey = async (conditional: boolean, signal?: AbortSignal) => {\n\t\tif (!conditional) {\n\t\t\tsetBusy(true);\n\t\t\tsetError(null);\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await client.auth.passkeys.signIn({ conditional, signal });\n\n\t\t\tsetToken(result.token);\n\t\t\tonSignedIn?.();\n\t\t} catch (cause) {\n\t\t\t// Cancelling is an answer, not an error — and a conditional ceremony\n\t\t\t// aborts every time the component unmounts, which must stay silent.\n\t\t\tif (cause instanceof DOMException && (cause.name === \"NotAllowedError\" || cause.name === \"AbortError\")) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!conditional) {\n\t\t\t\tconsole.error(\"[base316] passkey sign-in failed\", cause);\n\t\t\t\tsetError(\"That passkey did not work.\");\n\t\t\t}\n\t\t} finally {\n\t\t\tif (!conditional) {\n\t\t\t\tsetBusy(false);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Offer the passkey in the browser's own autofill list.\n\t *\n\t * This is what makes a passkey better than a password rather than merely\n\t * different: the credential appears in the email field's suggestions and one\n\t * tap signs in. The promise stays pending until somebody picks one, so it is\n\t * aborted on unmount.\n\t */\n\tuseEffect(() => {\n\t\tif (!passkeys || !isPasskeySupported() || pendingUserId) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetPasskeyReady(true);\n\n\t\tconst controller = new AbortController();\n\t\tabortRef.current = controller;\n\n\t\tvoid isPasskeyAutofillAvailable().then((available) => {\n\t\t\tif (available && !controller.signal.aborted) {\n\t\t\t\tvoid signInWithPasskey(true, controller.signal);\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tcontroller.abort();\n\t\t};\n\t\t// Re-running this on every render would start a new ceremony each time,\n\t\t// so it deliberately depends only on what decides whether to run at all.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [passkeys, pendingUserId]);\n\n\tasync function submit(event: FormEvent) {\n\t\tevent.preventDefault();\n\t\tsetBusy(true);\n\t\tsetError(null);\n\n\t\ttry {\n\t\t\tif (pendingUserId) {\n\t\t\t\tconst verified = await client.auth.verifyMfa({ userId: pendingUserId, code });\n\t\t\t\tsetToken(verified.token);\n\t\t\t\tonSignedIn?.();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst result = await client.auth.signIn({ email, password });\n\n\t\t\t// `needsSecondFactor` is the SDK's narrowing helper; the response itself\n\t\t\t// carries `mfaRequired`. Testing for a field of the helper's name never\n\t\t\t// matched, so a second-factor account fell through to \"wrong password\".\n\t\t\tif (needsSecondFactor(result)) {\n\t\t\t\tsetPendingUserId(result.userId);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetToken(result.token);\n\t\t\tonSignedIn?.();\n\t\t} catch (cause) {\n\t\t\tconsole.error(\"[base316] sign-in failed\", cause);\n\t\t\tsetError(\n\t\t\t\tpendingUserId ? \"That code was not accepted.\" : \"That email and password did not match.\",\n\t\t\t);\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t}\n\n\treturn (\n\t\t<form onSubmit={submit} className={cls(\"b316-card\", className)} style={style}>\n\t\t\t{error ? <div className=\"b316-error\">{error}</div> : null}\n\n\t\t\t{pendingUserId ? (\n\t\t\t\t<div className=\"b316-field\">\n\t\t\t\t\t<label className=\"b316-label\" htmlFor=\"b316-code\">\n\t\t\t\t\t\tAuthentication code\n\t\t\t\t\t</label>\n\t\t\t\t\t<input\n\t\t\t\t\t\tid=\"b316-code\"\n\t\t\t\t\t\tclassName=\"b316-input\"\n\t\t\t\t\t\tvalue={code}\n\t\t\t\t\t\tonChange={(event) => setCode(event.target.value)}\n\t\t\t\t\t\tautoComplete=\"one-time-code\"\n\t\t\t\t\t\tinputMode=\"numeric\"\n\t\t\t\t\t\trequired\n\t\t\t\t\t/>\n\t\t\t\t\t<span className=\"b316-muted\">\n\t\t\t\t\t\tFrom your authenticator app, or one of your recovery codes.\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"b316-field\">\n\t\t\t\t\t\t<label className=\"b316-label\" htmlFor=\"b316-email\">\n\t\t\t\t\t\t\tEmail\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid=\"b316-email\"\n\t\t\t\t\t\t\tclassName=\"b316-input\"\n\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\tvalue={email}\n\t\t\t\t\t\t\tonChange={(event) => setEmail(event.target.value)}\n\t\t\t\t\t\t\tautoComplete={passkeyReady ? \"email webauthn\" : \"email\"}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"b316-field\">\n\t\t\t\t\t\t<label className=\"b316-label\" htmlFor=\"b316-password\">\n\t\t\t\t\t\t\tPassword\n\t\t\t\t\t\t</label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tid=\"b316-password\"\n\t\t\t\t\t\t\tclassName=\"b316-input\"\n\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\tvalue={password}\n\t\t\t\t\t\t\tonChange={(event) => setPassword(event.target.value)}\n\t\t\t\t\t\t\tautoComplete=\"current-password\"\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t<button className=\"b316-button\" type=\"submit\" disabled={busy}>\n\t\t\t\t{busy ? \"Working…\" : pendingUserId ? \"Verify\" : \"Sign in\"}\n\t\t\t</button>\n\n\t\t\t{passkeyReady && !pendingUserId ? (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"b316-muted\" style={{ textAlign: \"center\", margin: \"10px 0\" }}>\n\t\t\t\t\t\tor\n\t\t\t\t\t</div>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"b316-button b316-button-secondary\"\n\t\t\t\t\t\tdisabled={busy}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t// The conditional ceremony holds the only credential request\n\t\t\t\t\t\t\t// the browser allows at a time; it has to go before a\n\t\t\t\t\t\t\t// deliberate one can start.\n\t\t\t\t\t\t\tabortRef.current?.abort();\n\t\t\t\t\t\t\tvoid signInWithPasskey(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tSign in with a passkey\n\t\t\t\t\t</button>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</form>\n\t);\n}\n","\"use client\";\n\nimport { useState, type CSSProperties, type FormEvent } from \"react\";\n\nimport { cls } from \"./appearance\";\nimport { useBase316 } from \"./provider\";\n\n/**\n * Create an account.\n *\n * Signing up provisions the billing identity too, so the user this returns can\n * be put on a plan immediately — there is no second step to link them to a\n * customer record.\n *\n * Sign-up does not itself produce a session, since the account still has to\n * verify its email. The form signs in straight afterwards so the common case\n * does not make people type their password twice.\n */\nexport function SignUp({\n\tonSignedUp,\n\tclassName,\n\tstyle,\n}: {\n\tonSignedUp?: () => void;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}) {\n\tconst { client, setToken } = useBase316();\n\tconst [name, setName] = useState(\"\");\n\tconst [email, setEmail] = useState(\"\");\n\tconst [password, setPassword] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\n\tasync function submit(event: FormEvent) {\n\t\tevent.preventDefault();\n\t\tsetBusy(true);\n\t\tsetError(null);\n\n\t\ttry {\n\t\t\tawait client.auth.signUp({ email, password, name: name || undefined });\n\n\t\t\tconst signedIn = await client.auth.signIn({ email, password });\n\n\t\t\tif (\"token\" in signedIn && signedIn.token) {\n\t\t\t\tsetToken(signedIn.token);\n\t\t\t}\n\n\t\t\tonSignedUp?.();\n\t\t} catch (cause) {\n\t\t\t// The friendly message is what the person sees; the cause goes to the\n\t\t\t// console so a developer integrating this is not left guessing.\n\t\t\tconsole.error(\"[base316] sign-up failed\", cause);\n\t\t\tsetError(\"We could not create that account. The email may already be registered.\");\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t}\n\n\treturn (\n\t\t<form onSubmit={submit} className={cls(\"b316-card\", className)} style={style}>\n\t\t\t{error ? <div className=\"b316-error\">{error}</div> : null}\n\n\t\t\t<div className=\"b316-field\">\n\t\t\t\t<label className=\"b316-label\" htmlFor=\"b316-name\">\n\t\t\t\t\tName\n\t\t\t\t</label>\n\t\t\t\t<input\n\t\t\t\t\tid=\"b316-name\"\n\t\t\t\t\tclassName=\"b316-input\"\n\t\t\t\t\tvalue={name}\n\t\t\t\t\tonChange={(event) => setName(event.target.value)}\n\t\t\t\t\tautoComplete=\"name\"\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div className=\"b316-field\">\n\t\t\t\t<label className=\"b316-label\" htmlFor=\"b316-signup-email\">\n\t\t\t\t\tEmail\n\t\t\t\t</label>\n\t\t\t\t<input\n\t\t\t\t\tid=\"b316-signup-email\"\n\t\t\t\t\tclassName=\"b316-input\"\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tvalue={email}\n\t\t\t\t\tonChange={(event) => setEmail(event.target.value)}\n\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\trequired\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t<div className=\"b316-field\">\n\t\t\t\t<label className=\"b316-label\" htmlFor=\"b316-signup-password\">\n\t\t\t\t\tPassword\n\t\t\t\t</label>\n\t\t\t\t<input\n\t\t\t\t\tid=\"b316-signup-password\"\n\t\t\t\t\tclassName=\"b316-input\"\n\t\t\t\t\ttype=\"password\"\n\t\t\t\t\tvalue={password}\n\t\t\t\t\tonChange={(event) => setPassword(event.target.value)}\n\t\t\t\t\tautoComplete=\"new-password\"\n\t\t\t\t\tminLength={8}\n\t\t\t\t\trequired\n\t\t\t\t/>\n\t\t\t\t<span className=\"b316-muted\">At least 8 characters.</span>\n\t\t\t</div>\n\n\t\t\t<button className=\"b316-button\" type=\"submit\" disabled={busy}>\n\t\t\t\t{busy ? \"Creating…\" : \"Create account\"}\n\t\t\t</button>\n\t\t</form>\n\t);\n}\n","\"use client\";\n\nimport type { CSSProperties } from \"react\";\n\nimport { cls } from \"./appearance\";\nimport { useBase316 } from \"./provider\";\n\n/**\n * Who is signed in, and a way out.\n *\n * Reads the session the provider already resolved rather than fetching again,\n * so a page with several of these components makes one round trip, not several.\n */\nexport function UserProfile({ className, style }: { className?: string; style?: CSSProperties }) {\n\tconst { session, loading, signOut } = useBase316();\n\n\tif (loading) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tLoading…\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!session) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tNot signed in.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst user = (session.user ?? {}) as {\n\t\tname?: string;\n\t\temail?: string;\n\t\temailVerified?: boolean;\n\t};\n\n\treturn (\n\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t<div className=\"b316-row\">\n\t\t\t\t<div>\n\t\t\t\t\t<div style={{ fontWeight: 600 }}>{user.name || user.email || \"Signed in\"}</div>\n\t\t\t\t\t{user.name && user.email ? <div className=\"b316-muted\">{user.email}</div> : null}\n\t\t\t\t\t{user.emailVerified === false ? (\n\t\t\t\t\t\t<div className=\"b316-muted\">Email not verified</div>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"b316-button b316-button-secondary\"\n\t\t\t\t\tonClick={() => void signOut()}\n\t\t\t\t>\n\t\t\t\t\tSign out\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","\"use client\";\n\nimport { isPasskeySupported, type PasskeySummary } from \"@base316/sdk\";\nimport { useCallback, useEffect, useState, type CSSProperties } from \"react\";\n\nimport { cls } from \"./appearance\";\nimport { useBase316 } from \"./provider\";\n\n/**\n * The signed-in user's passkeys, and a way to add one.\n *\n * Belongs on an account screen next to \"change password\". A passkey is bound to\n * the origin it was created on, so one registered here works on this site and\n * not on the hosted sign-in page — which is why this component exists at all\n * rather than sending people somewhere else to manage them.\n */\nexport function PasskeyManager({\n\tclassName,\n\tstyle,\n\ttitle = \"Passkeys\",\n}: {\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\ttitle?: string;\n}) {\n\tconst { client, token, session } = useBase316();\n\n\tconst [passkeys, setPasskeys] = useState<PasskeySummary[] | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [name, setName] = useState(\"\");\n\n\t/**\n\t * Whether this browser can do WebAuthn at all.\n\t *\n\t * Asked in an effect rather than during render. It is false on a server and\n\t * usually true in the browser, so deciding during render renders one thing on\n\t * the server and another on the client — which React reports as a hydration\n\t * error rather than as the section quietly appearing.\n\t */\n\tconst [supported, setSupported] = useState(false);\n\n\tconst load = useCallback(async () => {\n\t\tif (!token) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await client.auth.passkeys.list(token);\n\t\t\tsetPasskeys(result.data);\n\t\t} catch {\n\t\t\t// An account screen that cannot list passkeys should still render the\n\t\t\t// rest of itself. The add button reports its own failure if pressed.\n\t\t\tsetPasskeys([]);\n\t\t}\n\t}, [client, token]);\n\n\tuseEffect(() => {\n\t\tif (!isPasskeySupported()) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetSupported(true);\n\t\tvoid load();\n\t}, [load]);\n\n\t// An \"add a passkey\" button in a browser that cannot make one is worse than\n\t// no section at all.\n\tif (!session || !token || !supported) {\n\t\treturn null;\n\t}\n\n\tconst add = async () => {\n\t\tsetBusy(true);\n\t\tsetError(null);\n\n\t\ttry {\n\t\t\tawait client.auth.passkeys.register(token, { name: name.trim() || undefined });\n\t\t\tsetName(\"\");\n\t\t\tawait load();\n\t\t} catch (caught) {\n\t\t\t// A cancelled ceremony is not a failure worth shouting about: the\n\t\t\t// person closed the dialog, which is an answer.\n\t\t\tif (caught instanceof DOMException && caught.name === \"NotAllowedError\") {\n\t\t\t\tsetError(null);\n\t\t\t} else {\n\t\t\t\tsetError(caught instanceof Error ? caught.message : \"That did not work.\");\n\t\t\t}\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\tconst remove = async (id: string) => {\n\t\tsetError(null);\n\n\t\ttry {\n\t\t\tawait client.auth.passkeys.remove(token, id);\n\t\t\tawait load();\n\t\t} catch (caught) {\n\t\t\tsetError(caught instanceof Error ? caught.message : \"That did not work.\");\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t<div style={{ fontWeight: 600, marginBottom: 4 }}>{title}</div>\n\t\t\t<div className=\"b316-muted\" style={{ marginBottom: 12 }}>\n\t\t\t\tSign in with your fingerprint, face or a security key — nothing to type and nothing to\n\t\t\t\tremember.\n\t\t\t</div>\n\n\t\t\t{passkeys === null ? (\n\t\t\t\t<div className=\"b316-muted\">Loading…</div>\n\t\t\t) : passkeys.length === 0 ? (\n\t\t\t\t<div className=\"b316-muted\">No passkeys yet.</div>\n\t\t\t) : (\n\t\t\t\t<ul style={{ listStyle: \"none\", margin: 0, padding: 0 }}>\n\t\t\t\t\t{passkeys.map((passkey) => (\n\t\t\t\t\t\t<li key={passkey.id} className=\"b316-row\" style={{ padding: \"8px 0\" }}>\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<div>{passkey.name || \"Passkey\"}</div>\n\t\t\t\t\t\t\t\t<div className=\"b316-muted\">\n\t\t\t\t\t\t\t\t\t{passkey.lastUsedAt\n\t\t\t\t\t\t\t\t\t\t? `Last used ${formatDate(passkey.lastUsedAt)}`\n\t\t\t\t\t\t\t\t\t\t: `Added ${formatDate(passkey.createdAt)}`}\n\t\t\t\t\t\t\t\t\t{/* A passkey that is not backed up lives on one device, and\n\t\t\t\t\t\t\t\t\t losing that device loses the passkey. Worth saying. */}\n\t\t\t\t\t\t\t\t\t{passkey.backedUp ? \"\" : \" · this device only\"}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"b316-button b316-button-secondary\"\n\t\t\t\t\t\t\t\tonClick={() => void remove(passkey.id)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tRemove\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\n\t\t\t{error ? (\n\t\t\t\t<div className=\"b316-error\" style={{ marginTop: 12 }}>\n\t\t\t\t\t{error}\n\t\t\t\t</div>\n\t\t\t) : null}\n\n\t\t\t<div className=\"b316-row\" style={{ marginTop: 12, gap: 8 }}>\n\t\t\t\t<input\n\t\t\t\t\tclassName=\"b316-input\"\n\t\t\t\t\tplaceholder=\"Name this passkey (optional)\"\n\t\t\t\t\tvalue={name}\n\t\t\t\t\tonChange={(event) => setName(event.target.value)}\n\t\t\t\t/>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"b316-button\"\n\t\t\t\t\tdisabled={busy}\n\t\t\t\t\tonClick={() => void add()}\n\t\t\t\t>\n\t\t\t\t\t{busy ? \"Waiting…\" : \"Add a passkey\"}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction formatDate(value: string): string {\n\tconst date = new Date(value);\n\n\treturn Number.isNaN(date.getTime()) ? \"\" : date.toLocaleDateString();\n}\n","\"use client\";\n\nimport type { PublicPlan } from \"@base316/sdk\";\nimport { useEffect, useState, type CSSProperties } from \"react\";\n\nimport { cls } from \"./appearance\";\nimport { useBase316 } from \"./provider\";\n\nfunction formatAmount(amount: string | null, currency: string): string {\n\tif (amount === null) return \"Free\";\n\n\tconst value = Number(amount);\n\tif (!Number.isFinite(value)) return \"Free\";\n\n\ttry {\n\t\treturn new Intl.NumberFormat(undefined, { style: \"currency\", currency }).format(value);\n\t} catch {\n\t\t// An unknown currency code should not blank the price.\n\t\treturn `${value} ${currency}`;\n\t}\n}\n\nfunction cadence(plan: PublicPlan, amount: string | null): string {\n\tif (amount === null) {\n\t\treturn \"\\u00a0\";\n\t}\n\n\tconst unit = plan.interval.toLowerCase();\n\treturn plan.intervalCount === 1 ? `per ${unit}` : `every ${plan.intervalCount} ${unit}s`;\n}\n\n/**\n * The plans, as an end user picks between them.\n *\n * `onSelectPlan` is required and takes the plan version id, because this\n * component deliberately cannot start a checkout itself. Minting a checkout\n * session needs a secret key, and the plan has to be named by a server — a\n * browser that could choose its own plan would pick the cheapest one. So the\n * host application posts to its own backend, which calls\n * `POST /v1/checkout/sessions` and redirects to the URL it returns.\n */\nexport function PricingTable({\n\tonSelectPlan,\n\tcurrentPlanVersionId,\n\tfeaturedPlanKey,\n\tclassName,\n\tstyle,\n}: {\n\tonSelectPlan: (planVersionId: string, plan: PublicPlan) => void | Promise<void>;\n\t/** Marks the plan the viewer is already on. */\n\tcurrentPlanVersionId?: string | null;\n\t/** The plan to present as the default choice, by its key. */\n\tfeaturedPlanKey?: string;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}) {\n\tconst { client } = useBase316();\n\tconst [plans, setPlans] = useState<PublicPlan[] | null>(null);\n\tconst [error, setError] = useState(false);\n\tconst [busy, setBusy] = useState<string | null>(null);\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\n\t\tclient.billing\n\t\t\t.plans()\n\t\t\t.then((result) => {\n\t\t\t\tif (!cancelled) setPlans(result.data);\n\t\t\t})\n\t\t\t.catch((cause) => {\n\t\t\t\tconsole.error(\"[base316] could not load plans\", cause);\n\t\t\t\tif (!cancelled) setError(true);\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [client]);\n\n\tif (error) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tPlans are unavailable right now.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!plans) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tLoading plans…\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (plans.length === 0) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tNo plans are published yet.\n\t\t\t</div>\n\t\t);\n\t}\n\n\t// Whether a slot is rendered is a property of the table, not of one plan:\n\t// reserving space on every card is what keeps the rows aligned.\n\tconst anyTrial = plans.some((plan) => Boolean(plan.trialDays));\n\tconst anyDescription = plans.some((plan) => Boolean(plan.description));\n\tconst anyFeatured = plans.some((plan) => plan.key === featuredPlanKey);\n\n\treturn (\n\t\t<div className={cls(\"b316-plans\", className)} style={style}>\n\t\t\t{plans.map((plan) => {\n\t\t\t\tconst base = plan.prices.find((price) => price.featureId === null) ?? plan.prices[0];\n\t\t\t\tconst current = currentPlanVersionId === plan.planVersionId;\n\t\t\t\tconst featured = featuredPlanKey === plan.key;\n\n\t\t\t\treturn (\n\t\t\t\t\t<div\n\t\t\t\t\t\tkey={plan.id}\n\t\t\t\t\t\tclassName={featured ? \"b316-card b316-plan b316-plan-featured\" : \"b316-card b316-plan\"}\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"b316-plan-head\">\n\t\t\t\t\t\t\t{anyFeatured ? (\n\t\t\t\t\t\t\t\t<div className={featured ? \"b316-plan-badge\" : \"b316-plan-badge-spacer\"}>\n\t\t\t\t\t\t\t\t\t{featured ? \"Recommended\" : \"\\u00a0\"}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t<div className=\"b316-plan-name\">{plan.name}</div>\n\t\t\t\t\t\t\t{anyDescription ? (\n\t\t\t\t\t\t\t\t<div className=\"b316-plan-desc\">{plan.description ?? \"\\u00a0\"}</div>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div className=\"b316-plan-pricing\">\n\t\t\t\t\t\t\t<div className=\"b316-plan-price\">\n\t\t\t\t\t\t\t\t{formatAmount(base?.amount ?? null, plan.currency)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{/* Rendered even when empty so every card's feature list starts\n\t\t\t\t\t\t\t at the same height — otherwise a free plan pulls its rows up\n\t\t\t\t\t\t\t and nothing lines up across the table. */}\n\t\t\t\t\t\t\t<div className=\"b316-plan-cadence\">{cadence(plan, base?.amount ?? null)}</div>\n\t\t\t\t\t\t\t{anyTrial ? (\n\t\t\t\t\t\t\t\t<div className=\"b316-plan-trial\">\n\t\t\t\t\t\t\t\t\t{plan.trialDays ? `${plan.trialDays}-day free trial` : \"\\u00a0\"}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<ul className=\"b316-plan-features\">\n\t\t\t\t\t\t\t{plan.entitlements\n\t\t\t\t\t\t\t\t.filter((entitlement) => entitlement.enabled)\n\t\t\t\t\t\t\t\t.map((entitlement) => (\n\t\t\t\t\t\t\t\t\t<li key={entitlement.featureId} className=\"b316-plan-feature\">\n\t\t\t\t\t\t\t\t\t\t<span>{entitlement.featureName}</span>\n\t\t\t\t\t\t\t\t\t\t<span className=\"b316-plan-feature-value\">\n\t\t\t\t\t\t\t\t\t\t\t{entitlement.limit === null ? \"Unlimited\" : entitlement.limit}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\n\t\t\t\t\t\t<div className=\"b316-plan-action\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName={current ? \"b316-button b316-button-current\" : \"b316-button\"}\n\t\t\t\t\t\t\t\tdisabled={current || busy !== null}\n\t\t\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\t\t\tsetBusy(plan.planVersionId);\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait onSelectPlan(plan.planVersionId, plan);\n\t\t\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\t\t\tsetBusy(null);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{current ? \"Current plan\" : busy === plan.planVersionId ? \"Working…\" : \"Choose\"}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t})}\n\t\t</div>\n\t);\n}\n","\"use client\";\n\nimport type { BillingSubscription } from \"@base316/sdk\";\nimport { useCallback, useEffect, useState, type CSSProperties } from \"react\";\n\nimport { cls } from \"./appearance\";\nimport { useBase316 } from \"./provider\";\n\nfunction statusLabel(status: string): string {\n\tconst words = status.toLowerCase().split(\"_\");\n\treturn words.map((w, i) => (i === 0 ? w.charAt(0).toUpperCase() + w.slice(1) : w)).join(\" \");\n}\n\n/**\n * The signed-in user's own subscription.\n *\n * Reads through the session, never a customer id from props: the account is\n * whoever the session says it is, so one user cannot be pointed at another's\n * billing by changing a prop.\n */\nexport function SubscriptionManager({\n\tclassName,\n\tstyle,\n}: {\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}) {\n\tconst { client, token, loading: sessionLoading } = useBase316();\n\tconst [subscription, setSubscription] = useState<BillingSubscription | null>(null);\n\tconst [loading, setLoading] = useState(true);\n\tconst [busy, setBusy] = useState(false);\n\tconst [error, setError] = useState<string | null>(null);\n\n\tconst load = useCallback(async () => {\n\t\tif (!token) {\n\t\t\tsetSubscription(null);\n\t\t\tsetLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst result = await client.billing.subscription(token);\n\t\t\tsetSubscription(result.subscription);\n\t\t} catch (cause) {\n\t\t\tconsole.error(\"[base316] could not load the subscription\", cause);\n\t\t\tsetError(\"Could not load your subscription.\");\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t}, [client, token]);\n\n\tuseEffect(() => {\n\t\tvoid load();\n\t}, [load]);\n\n\tif (sessionLoading || loading) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tLoading…\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!token) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tSign in to manage your subscription.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tif (!subscription) {\n\t\treturn (\n\t\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t\tYou are not subscribed to a plan.\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst renews = new Date(subscription.currentPeriodEnd).toLocaleDateString();\n\n\treturn (\n\t\t<div className={cls(\"b316-card\", className)} style={style}>\n\t\t\t{error ? <div className=\"b316-error\">{error}</div> : null}\n\n\t\t\t<div className=\"b316-plan-name\">{subscription.planVersion.plan.name}</div>\n\t\t\t<div className=\"b316-muted\">\n\t\t\t\t{/* PAST_DUE reads as \"Past due\", not \"past_due\". */}\n\t\t\t\t{statusLabel(subscription.status)}\n\t\t\t\t{\" · \"}\n\t\t\t\t{subscription.cancelAtPeriodEnd ? `Ends ${renews}` : `Renews ${renews}`}\n\t\t\t</div>\n\n\t\t\t{subscription.cancelAtPeriodEnd ? (\n\t\t\t\t<p className=\"b316-muted\">\n\t\t\t\t\tThis subscription will not renew. You keep access until {renews}.\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"b316-button b316-button-secondary\"\n\t\t\t\t\tstyle={{ marginTop: 14 }}\n\t\t\t\t\tdisabled={busy}\n\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\tsetBusy(true);\n\t\t\t\t\t\tsetError(null);\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Cancels at period end: the user paid for the period they\n\t\t\t\t\t\t\t// are in, and ending it now would forfeit it.\n\t\t\t\t\t\t\tawait client.billing.cancel(token);\n\t\t\t\t\t\t\tawait load();\n\t\t\t\t\t\t} catch (cause) {\n\t\t\t\t\t\t\tconsole.error(\"[base316] cancel failed\", cause);\n\t\t\t\t\t\t\tsetError(\"Could not cancel. Try again.\");\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tsetBusy(false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{busy ? \"Working…\" : \"Cancel subscription\"}\n\t\t\t\t</button>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n"],"mappings":"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","names":["jsx","useCallback","useEffect","useState","jsx","jsxs","useState","useEffect","useCallback","useEffect","useState","jsx","jsxs","useState","useEffect","useState","jsx","jsxs","useState","jsx","jsxs","isPasskeySupported","useCallback","useEffect","useState","jsx","jsxs","useState","useCallback","useEffect","isPasskeySupported","useEffect","useState","jsx","jsxs","useState","useEffect","useCallback","useEffect","useState","jsx","jsxs","useState","useCallback","useEffect"]}
@@ -0,0 +1,16 @@
1
+ import type { CSSProperties } from "react";
2
+ /**
3
+ * The customer's logo, name and tagline, as configured in the dashboard.
4
+ *
5
+ * `brandDisplay` decides which of the logo and the name is shown, so an
6
+ * application's own header matches the Base316-hosted sign-in page without the
7
+ * customer setting their brand up twice. `LOGO` still renders the name as the
8
+ * image's alt text, because a logo that fails to load must not leave the page
9
+ * anonymous.
10
+ */
11
+ export declare function Branding({ showTagline, className, style, }: {
12
+ showTagline?: boolean;
13
+ className?: string;
14
+ style?: CSSProperties;
15
+ }): import("react").JSX.Element | null;
16
+ //# sourceMappingURL=Branding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Branding.d.ts","sourceRoot":"","sources":["../../src/Branding.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAK3C;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,EACxB,WAAkB,EAClB,SAAS,EACT,KAAK,GACL,EAAE;IACF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,sCAqBA"}
@@ -0,0 +1,18 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * The signed-in user's invoices, and a way to keep one.
4
+ *
5
+ * Downloading is done by printing a rendered invoice rather than by fetching a
6
+ * PDF: there is no PDF renderer on the server, and adding one is a real
7
+ * dependency decision rather than something to slip in here. Print-to-PDF is
8
+ * built into every browser, produces a selectable-text document, and needs
9
+ * nothing installed — so the button opens the invoice and prints it.
10
+ *
11
+ * Drafts never appear. They are the rating engine's working state and can still
12
+ * change, so showing one as a bill would be wrong.
13
+ */
14
+ export declare function Invoices({ className, style }: {
15
+ className?: string;
16
+ style?: CSSProperties;
17
+ }): import("react").JSX.Element;
18
+ //# sourceMappingURL=Invoices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Invoices.d.ts","sourceRoot":"","sources":["../../src/Invoices.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAuB7E;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,+BA2G3F"}
@@ -0,0 +1,15 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * The signed-in user's passkeys, and a way to add one.
4
+ *
5
+ * Belongs on an account screen next to "change password". A passkey is bound to
6
+ * the origin it was created on, so one registered here works on this site and
7
+ * not on the hosted sign-in page — which is why this component exists at all
8
+ * rather than sending people somewhere else to manage them.
9
+ */
10
+ export declare function PasskeyManager({ className, style, title, }: {
11
+ className?: string;
12
+ style?: CSSProperties;
13
+ title?: string;
14
+ }): import("react").JSX.Element | null;
15
+ //# sourceMappingURL=PasskeyManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasskeyManager.d.ts","sourceRoot":"","sources":["../../src/PasskeyManager.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAK7E;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAC9B,SAAS,EACT,KAAK,EACL,KAAkB,GAClB,EAAE;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf,sCA+IA"}
@@ -0,0 +1,22 @@
1
+ import type { PublicPlan } from "@base316/sdk";
2
+ import { type CSSProperties } from "react";
3
+ /**
4
+ * The plans, as an end user picks between them.
5
+ *
6
+ * `onSelectPlan` is required and takes the plan version id, because this
7
+ * component deliberately cannot start a checkout itself. Minting a checkout
8
+ * session needs a secret key, and the plan has to be named by a server — a
9
+ * browser that could choose its own plan would pick the cheapest one. So the
10
+ * host application posts to its own backend, which calls
11
+ * `POST /v1/checkout/sessions` and redirects to the URL it returns.
12
+ */
13
+ export declare function PricingTable({ onSelectPlan, currentPlanVersionId, featuredPlanKey, className, style, }: {
14
+ onSelectPlan: (planVersionId: string, plan: PublicPlan) => void | Promise<void>;
15
+ /** Marks the plan the viewer is already on. */
16
+ currentPlanVersionId?: string | null;
17
+ /** The plan to present as the default choice, by its key. */
18
+ featuredPlanKey?: string;
19
+ className?: string;
20
+ style?: CSSProperties;
21
+ }): import("react").JSX.Element;
22
+ //# sourceMappingURL=PricingTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PricingTable.d.ts","sourceRoot":"","sources":["../../src/PricingTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AA4BhE;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,EAC5B,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,SAAS,EACT,KAAK,GACL,EAAE;IACF,YAAY,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,+CAA+C;IAC/C,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAgIA"}
@@ -0,0 +1,16 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * Email and password sign-in.
4
+ *
5
+ * Handles the MFA branch, because an account with a second factor gets a
6
+ * challenge instead of a session, and a form that ignores that case appears to
7
+ * fail for exactly the users who most need it to work.
8
+ */
9
+ export declare function SignIn({ onSignedIn, passkeys, className, style, }: {
10
+ onSignedIn?: () => void;
11
+ /** Offer passkeys alongside the password. On by default where supported. */
12
+ passkeys?: boolean;
13
+ className?: string;
14
+ style?: CSSProperties;
15
+ }): import("react").JSX.Element;
16
+ //# sourceMappingURL=SignIn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignIn.d.ts","sourceRoot":"","sources":["../../src/SignIn.tsx"],"names":[],"mappings":"AAOA,OAAO,EAA+B,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAKxF;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,EACtB,UAAU,EACV,QAAe,EACf,SAAS,EACT,KAAK,GACL,EAAE;IACF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAgMA"}
@@ -0,0 +1,18 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * Create an account.
4
+ *
5
+ * Signing up provisions the billing identity too, so the user this returns can
6
+ * be put on a plan immediately — there is no second step to link them to a
7
+ * customer record.
8
+ *
9
+ * Sign-up does not itself produce a session, since the account still has to
10
+ * verify its email. The form signs in straight afterwards so the common case
11
+ * does not make people type their password twice.
12
+ */
13
+ export declare function SignUp({ onSignedUp, className, style, }: {
14
+ onSignedUp?: () => void;
15
+ className?: string;
16
+ style?: CSSProperties;
17
+ }): import("react").JSX.Element;
18
+ //# sourceMappingURL=SignUp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignUp.d.ts","sourceRoot":"","sources":["../../src/SignUp.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,aAAa,EAAkB,MAAM,OAAO,CAAC;AAKrE;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,EACtB,UAAU,EACV,SAAS,EACT,KAAK,GACL,EAAE;IACF,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAqFA"}
@@ -0,0 +1,13 @@
1
+ import { type CSSProperties } from "react";
2
+ /**
3
+ * The signed-in user's own subscription.
4
+ *
5
+ * Reads through the session, never a customer id from props: the account is
6
+ * whoever the session says it is, so one user cannot be pointed at another's
7
+ * billing by changing a prop.
8
+ */
9
+ export declare function SubscriptionManager({ className, style, }: {
10
+ className?: string;
11
+ style?: CSSProperties;
12
+ }): import("react").JSX.Element;
13
+ //# sourceMappingURL=SubscriptionManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriptionManager.d.ts","sourceRoot":"","sources":["../../src/SubscriptionManager.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAU7E;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,SAAS,EACT,KAAK,GACL,EAAE;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACtB,+BAmGA"}
@@ -0,0 +1,12 @@
1
+ import type { CSSProperties } from "react";
2
+ /**
3
+ * Who is signed in, and a way out.
4
+ *
5
+ * Reads the session the provider already resolved rather than fetching again,
6
+ * so a page with several of these components makes one round trip, not several.
7
+ */
8
+ export declare function UserProfile({ className, style }: {
9
+ className?: string;
10
+ style?: CSSProperties;
11
+ }): import("react").JSX.Element;
12
+ //# sourceMappingURL=UserProfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserProfile.d.ts","sourceRoot":"","sources":["../../src/UserProfile.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAK3C;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,+BA6C9F"}
@@ -0,0 +1,63 @@
1
+ import type { CSSProperties } from "react";
2
+ /**
3
+ * How these components are styled, and why it works this way.
4
+ *
5
+ * They drop into an application whose CSS we cannot see. Three approaches were
6
+ * possible and only one of them is actually controllable by the host:
7
+ *
8
+ * - Inline styles are self-contained but *unoverridable* — they beat any
9
+ * stylesheet short of `!important`, so a customer cannot restyle anything.
10
+ * - A shipped stylesheet fights the host's cascade unpredictably.
11
+ * - CSS custom properties, with every value read through a variable, let the
12
+ * host restyle without either side guessing at specificity.
13
+ *
14
+ * So: one small stylesheet, injected once, with every colour, radius and font
15
+ * behind a `--b316-*` variable. A customer can restyle in three ways, from
16
+ * least to most invasive:
17
+ *
18
+ * 1. `appearance` on the provider — tokens, no CSS to write.
19
+ * 2. Their own CSS targeting the `b316-*` class names.
20
+ * 3. `className` on any component, to hand it their own utility classes.
21
+ *
22
+ * Nothing here inherits the host's design automatically. That is deliberate:
23
+ * silently absorbing whatever `body { font }` and `button { }` rules exist
24
+ * produces components that look broken in ways neither side can predict.
25
+ */
26
+ export interface Base316Appearance {
27
+ /** Buttons, links, focus rings. */
28
+ colorPrimary?: string;
29
+ /** Text on primary-coloured surfaces. */
30
+ colorPrimaryText?: string;
31
+ colorText?: string;
32
+ colorMuted?: string;
33
+ colorBackground?: string;
34
+ colorBorder?: string;
35
+ colorDanger?: string;
36
+ colorDangerBackground?: string;
37
+ colorSuccess?: string;
38
+ borderRadius?: string;
39
+ fontFamily?: string;
40
+ fontSize?: string;
41
+ spacing?: string;
42
+ }
43
+ /** Turn the token object into inline custom properties for the root element. */
44
+ export declare function appearanceToStyle(appearance?: Base316Appearance): CSSProperties;
45
+ export declare const STYLE_ELEMENT_ID = "base316-components";
46
+ /**
47
+ * The stylesheet, injected once per document.
48
+ *
49
+ * Defaults live on `.b316-root` rather than `:root` so an application that
50
+ * never sets a token still gets a coherent look, and one that sets tokens on a
51
+ * parent still wins through normal inheritance.
52
+ */
53
+ export declare const STYLESHEET = "\n.b316-root {\n --b316-color-primary: #111827;\n --b316-color-primary-text: #ffffff;\n --b316-color-text: #111827;\n --b316-color-muted: #6b7280;\n --b316-color-background: #ffffff;\n --b316-color-border: #e5e7eb;\n --b316-color-danger: #991b1b;\n --b316-color-danger-bg: #fef2f2;\n --b316-color-success: #166534;\n --b316-radius: 12px;\n --b316-font: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n --b316-font-size: 15px;\n --b316-spacing: 12px;\n\n font-family: var(--b316-font);\n font-size: var(--b316-font-size);\n line-height: 1.5;\n color: var(--b316-color-text);\n}\n\n.b316-card {\n border: 1px solid var(--b316-color-border);\n border-radius: var(--b316-radius);\n padding: calc(var(--b316-spacing) * 1.6);\n background: var(--b316-color-background);\n}\n\n.b316-field { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--b316-spacing); }\n.b316-label { font-size: 0.87em; color: var(--b316-color-muted); }\n\n.b316-input {\n padding: 9px 11px;\n border: 1px solid var(--b316-color-border);\n border-radius: calc(var(--b316-radius) / 1.6);\n font: inherit;\n color: inherit;\n background: var(--b316-color-background);\n}\n.b316-input:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 1px; }\n\n.b316-button {\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-radius: calc(var(--b316-radius) / 1.6);\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n}\n.b316-button:hover:not([disabled]) { filter: brightness(1.12); }\n.b316-button:active:not([disabled]) { transform: translateY(1px); }\n.b316-button:focus-visible { outline: 2px solid var(--b316-color-primary); outline-offset: 2px; }\n.b316-button[disabled] { opacity: .55; cursor: not-allowed; }\n\n.b316-button-secondary {\n width: auto;\n transition: background-color .12s ease;\n background: var(--b316-color-background);\n color: var(--b316-color-text);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n}\n\n.b316-button-link {\n width: auto;\n background: none;\n border: 0;\n padding: 0;\n color: var(--b316-color-primary);\n font: inherit;\n cursor: pointer;\n text-decoration: underline;\n}\n\n.b316-error {\n background: var(--b316-color-danger-bg);\n color: var(--b316-color-danger);\n padding: 8px 10px;\n border-radius: calc(var(--b316-radius) / 2);\n font-size: 0.9em;\n margin-bottom: var(--b316-spacing);\n}\n\n.b316-muted { color: var(--b316-color-muted); font-size: 0.87em; }\n.b316-success { color: var(--b316-color-success); }\n\n.b316-plans {\n display: grid;\n gap: calc(var(--b316-spacing) * 1.3);\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n align-items: stretch;\n}\n\n.b316-plan {\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n}\n\n/* The recommended plan. Lifted rather than merely tinted: on a pricing table\n the eye needs one obvious default, and colour alone does not survive being\n viewed in greyscale or by someone who cannot distinguish the accent. */\n.b316-plan-featured {\n border-color: var(--b316-color-primary);\n box-shadow: 0 0 0 1px var(--b316-color-primary);\n}\n\n.b316-plan-badge {\n display: inline-block;\n background: var(--b316-color-primary);\n color: var(--b316-color-primary-text);\n border-radius: 999px;\n padding: 2px 9px;\n font-size: 0.75em;\n font-weight: 600;\n letter-spacing: .02em;\n margin-bottom: 8px;\n}\n\n/* Occupies the badge's height without drawing anything, so a featured card\n does not push its own price and features out of line with the others. */\n.b316-plan-badge-spacer {\n display: inline-block;\n padding: 2px 9px;\n font-size: 0.75em;\n margin-bottom: 8px;\n visibility: hidden;\n}\n\n.b316-plan-head { padding: calc(var(--b316-spacing) * 1.6); padding-bottom: 0; }\n.b316-plan-name { font-weight: 600; font-size: 1.06em; }\n.b316-plan-desc { color: var(--b316-color-muted); font-size: 0.87em; margin-top: 2px; }\n\n.b316-plan-pricing { padding: 0 calc(var(--b316-spacing) * 1.6) calc(var(--b316-spacing) * 1.4); }\n\n.b316-plan-price {\n font-size: 2.1em;\n font-weight: 640;\n letter-spacing: -.02em;\n margin-top: calc(var(--b316-spacing) * 0.7);\n /* Lining figures of even width, so prices do not shimmer between cards. */\n font-variant-numeric: tabular-nums lining-nums;\n}\n\n.b316-plan-cadence { color: var(--b316-color-muted); font-size: 0.87em; min-height: 1.35em; }\n.b316-plan-trial { color: var(--b316-color-success); font-size: 0.87em; min-height: 1.35em; }\n\n.b316-plan-features {\n list-style: none;\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n margin: 0;\n flex: 1;\n border-top: 1px solid var(--b316-color-border);\n}\n.b316-plan-feature {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n padding: 5px 0;\n font-size: 0.94em;\n}\n.b316-plan-feature-value { color: var(--b316-color-muted); font-variant-numeric: tabular-nums; }\n\n.b316-plan-action {\n padding: calc(var(--b316-spacing) * 1.2) calc(var(--b316-spacing) * 1.6);\n border-top: 1px solid var(--b316-color-border);\n}\n\n/* The plan already held. A faded primary button reads as broken rather than\n as \"you are here\", so this is a flat, quiet, genuinely inert surface. */\n.b316-button-current,\n.b316-button-current[disabled] {\n background: transparent;\n color: var(--b316-color-muted);\n border: 1px solid var(--b316-color-border);\n font-weight: 500;\n opacity: 1;\n cursor: default;\n}\n\n.b316-row { display: flex; justify-content: space-between; gap: 16px; align-items: center; }\n";
54
+ /** Join the component's own class with any the host passed in. */
55
+ export declare function cls(base: string, extra?: string): string;
56
+ /**
57
+ * Branding and invoice styles.
58
+ *
59
+ * Appended as a second block so the print rules stay next to the invoice they
60
+ * apply to, rather than being buried in the middle of the component styles.
61
+ */
62
+ export declare const STYLESHEET_EXTRA = "\n.b316-branding { display: flex; flex-direction: column; gap: 4px; }\n.b316-branding-logo { max-height: 40px; width: auto; align-self: flex-start; }\n.b316-branding-name { font-size: 1.5em; font-weight: 650; letter-spacing: -.01em; }\n.b316-branding-tagline { color: var(--b316-color-muted); }\n\n.b316-invoice-table { width: 100%; border-collapse: collapse; font-size: 0.94em; }\n.b316-invoice-table th {\n text-align: left;\n font-weight: 500;\n color: var(--b316-color-muted);\n font-size: 0.85em;\n padding: 0 0 6px;\n border-bottom: 1px solid var(--b316-color-border);\n}\n.b316-invoice-table td { padding: 9px 0; border-bottom: 1px solid var(--b316-color-border); }\n/* Columns need breathing room or the amount runs straight into the action \u2014\n \"$49.00View\" \u2014 which is what happens when only the row has padding. */\n.b316-invoice-table th + th,\n.b316-invoice-table td + td { padding-left: 16px; }\n.b316-invoice-table td:last-child,\n.b316-invoice-table th:last-child { text-align: right; width: 1%; white-space: nowrap; }\n.b316-invoice-table tr:last-child td { border-bottom: 0; }\n.b316-num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.b316-invoice-view {\n margin-top: calc(var(--b316-spacing) * 1.4);\n border-top: 1px solid var(--b316-color-border);\n padding-top: calc(var(--b316-spacing) * 1.4);\n}\n.b316-invoice-actions { display: flex; gap: 8px; justify-content: flex-end; margin-bottom: var(--b316-spacing); }\n.b316-invoice-doc { display: flex; flex-direction: column; gap: calc(var(--b316-spacing) * 1.4); }\n.b316-invoice-meta { display: grid; grid-template-columns: 1fr 1fr; gap: var(--b316-spacing); }\n.b316-invoice-totals { display: flex; flex-direction: column; gap: 6px; margin-left: auto; min-width: 240px; }\n.b316-invoice-total { font-weight: 650; border-top: 1px solid var(--b316-color-border); padding-top: 6px; }\n\n/* Printing emits the invoice alone. Without this the browser would paginate the\n whole application around it, which is not something anyone wants to file. */\n@media print {\n body * { visibility: hidden; }\n .b316-invoice-doc, .b316-invoice-doc * { visibility: visible; }\n .b316-invoice-doc {\n position: absolute;\n inset: 0 auto auto 0;\n width: 100%;\n padding: 24px;\n }\n .b316-invoice-actions { display: none; }\n}\n";
63
+ //# sourceMappingURL=appearance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appearance.d.ts","sourceRoot":"","sources":["../../src/appearance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,WAAW,iBAAiB;IACjC,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAkBD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,iBAAiB,GAAG,aAAa,CAgB/E;AAED,eAAO,MAAM,gBAAgB,uBAAuB,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,6lLA0LtB,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,wyEAiD5B,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { Base316Browser } from "@base316/sdk";
2
+ import type { Branding as BrandingInfo, ResolvedSession } from "@base316/sdk";
3
+ import { type ReactNode } from "react";
4
+ import { type Base316Appearance } from "./appearance";
5
+ /**
6
+ * Shared state for the Base316 components.
7
+ *
8
+ * Holds one browser client and the end user's session. The session token is the
9
+ * credential these components send alongside the publishable key: the key says
10
+ * which environment, the token says who, and billing answers need both.
11
+ *
12
+ * The token is kept in `localStorage` by default because that is what a
13
+ * single-page app needs to survive a refresh. An application that would rather
14
+ * hold it in an httpOnly cookie can pass `token` and `onTokenChange` and own
15
+ * the storage itself — which is the better choice if the app has a server.
16
+ */
17
+ interface Base316ContextValue {
18
+ client: Base316Browser;
19
+ /** The environment's logo, name and colours. Null until it loads. */
20
+ branding: BrandingInfo | null;
21
+ token: string | null;
22
+ setToken: (token: string | null) => void;
23
+ session: ResolvedSession | null;
24
+ loading: boolean;
25
+ refresh: () => Promise<void>;
26
+ signOut: () => Promise<void>;
27
+ }
28
+ export declare function Base316Provider({ publishableKey, baseUrl, token: controlledToken, onTokenChange, appearance, className, children, }: {
29
+ publishableKey: string;
30
+ baseUrl?: string;
31
+ /** Supply this to own session storage yourself. */
32
+ token?: string | null;
33
+ onTokenChange?: (token: string | null) => void;
34
+ /** Colours, radius and font, as tokens. See `Base316Appearance`. */
35
+ appearance?: Base316Appearance;
36
+ /** Your own classes on the wrapper — a Tailwind scope, for instance. */
37
+ className?: string;
38
+ children: ReactNode;
39
+ }): import("react").JSX.Element;
40
+ export declare function useBase316(): Base316ContextValue;
41
+ /** The signed-in user, or null. `loading` distinguishes "no one" from "not yet". */
42
+ export declare function useSession(): {
43
+ session: ResolvedSession | null;
44
+ loading: boolean;
45
+ };
46
+ export {};
47
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAON,KAAK,SAAS,EACd,MAAM,OAAO,CAAC;AAEf,OAAO,EAKN,KAAK,iBAAiB,EACtB,MAAM,cAAc,CAAC;AAEtB;;;;;;;;;;;GAWG;AAEH,UAAU,mBAAmB;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,qEAAqE;IACrE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AA4BD,wBAAgB,eAAe,CAAC,EAC/B,cAAc,EACd,OAAO,EACP,KAAK,EAAE,eAAe,EACtB,aAAa,EACb,UAAU,EACV,SAAS,EACT,QAAQ,GACR,EAAE;IACF,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,oEAAoE;IACpE,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACpB,+BA0IA;AAED,wBAAgB,UAAU,IAAI,mBAAmB,CAQhD;AAED,oFAAoF;AACpF,wBAAgB,UAAU,IAAI;IAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAGlF"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@base316/react",
3
+ "version": "0.1.0",
4
+ "description": "Drop-in React components for Base316 authentication and billing.",
5
+ "sideEffects": false,
6
+ "main": "./dist/index.cjs",
7
+ "types": "./dist/index.d.ts",
8
+ "dependencies": {
9
+ "@base316/sdk": "0.1.0"
10
+ },
11
+ "devDependencies": {
12
+ "@types/react": "19.2.18",
13
+ "react": "19.2.8",
14
+ "tsup": "^8.5.0",
15
+ "typescript": "7.0.2",
16
+ "vitest": "^5.0.0",
17
+ "@repo/tsconfig": "0.0.0"
18
+ },
19
+ "peerDependencies": {
20
+ "react": ">=18"
21
+ },
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/ThinkfleetAI/base316.git",
26
+ "directory": "packages/react"
27
+ },
28
+ "homepage": "https://base316.com",
29
+ "bugs": "https://github.com/ThinkfleetAI/base316/issues",
30
+ "module": "./dist/index.js",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "import": "./dist/index.js",
35
+ "require": "./dist/index.cjs"
36
+ }
37
+ },
38
+ "files": [
39
+ "LICENSE",
40
+ "README.md",
41
+ "dist"
42
+ ],
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "scripts": {
47
+ "build": "tsup && tsc -p tsconfig.build.json",
48
+ "clean": "git clean -xdf .cache .turbo dist node_modules",
49
+ "test": "vitest run --passWithNoTests",
50
+ "type-check": "tsc --noEmit"
51
+ }
52
+ }