/** * BrandingProvider — runtime enterprise white-labelling * Version 0.4.2 * * On mount: * 1. Calls supabase.rpc('branding_json_for_tenant') using the user's authed session. * 2. Validates each colour value is a well-formed oklch() string. * 3. Applies each key as a CSS custom property on document.documentElement. * 4. Caches the result in localStorage under BRANDING_STORAGE_KEY for FOUC prevention. * 5. Subscribes to tenant row changes via Supabase Realtime so branding updates * propagate without a page reload (within ~1 second). * * Security / brand policies: * - Only oklch() values are accepted for colour fields — hex/rgb/hsl are rejected. * - --role-error and --role-destructive are NOT overridable by tenants. * Colourblind policy (purple error) is a system-level requirement, not a brand pref. * - brand="braden" short-circuits all Supabase calls — Braden corporate site uses * static CSS tokens, not runtime tenant overrides. * - SEC-002 / SEC-003 (added 0.4.1) — tenant-controlled URL fields * (`logo_url`, `logo_light_url`, `logo_dark_url`, `mark_url`, * `favicon_url`) and `font_stack` are routed through `branding-sanitize` * at the DOM-apply sink. Dangerous schemes (`javascript:`, `data:`, * `vbscript:`, `blob:`, `file:`) are rejected; the URL is parsed and * re-serialised so breakout chars are percent-encoded; the `url()` * token is emitted in the safe quoted form with `"` and `\` escaped; * font values carrying CSS-breakout tokens (`< > ( ) { } ; @ \ /* *\/`) * are rejected and the var is cleared so the default font applies. * - 0.4.2 — `font_stack` now goes through `sanitizeFontFamilyForCss`, not * `sanitizeFontFamily`: a syntactically legitimate bare family name (no * injection attempt) with no matching `@font-face` used to reach * `--font-stack` with nothing to fall back to. Confirmed live on a * consumer app: an inline `--font-body: Geist` (a sibling write, same * class) beat this package's own correctly-chained `vars.css` default * and rendered the page in the browser's serif default. The fix * validates + resolves a known alias to the face this package actually * ships (`Geist` → `"Geist Variable"`, `Geist Mono` → `"Geist Mono * Variable"`) + appends a `system-ui, sans-serif` fallback, so any * family with no shipped face degrades to system sans, never to serif. * * Environment flags: * - VITE_ENABLE_BRANDING_OVERRIDE (default: 'true') — set 'false' as kill switch. * * Usage: * * * {children} * * * * For Braden corporate (skips all RPC/Realtime): * * {children} * */ import type { SupabaseClient } from '@supabase/supabase-js'; import type { ReactNode } from 'react'; export declare const BRANDING_STORAGE_KEY = "bsuite_tenant_branding"; export declare const BRANDING_OVERRIDE_FLAG = "VITE_ENABLE_BRANDING_OVERRIDE"; /** Shape returned by the branding_json_for_tenant RPC */ export interface TenantBranding { /** Primary action colour — MUST be an oklch() string */ primary?: string; /** Accent / secondary colour — MUST be an oklch() string */ accent?: string; /** Full logo URL (SVG or raster) */ logo_url?: string; /** Light-mode full logo URL */ logo_light_url?: string; /** Dark-mode full logo URL */ logo_dark_url?: string; /** Mark / icon logo URL */ mark_url?: string; /** Favicon URL */ favicon_url?: string; /** Display name used for generated logo alt text */ company_name?: string; /** Optional CSS font-family stack string */ font_stack?: string | null; } export interface BrandingContextValue { branding: TenantBranding | null; isLoading: boolean; error: Error | null; refresh: () => Promise; } export declare const BrandingContext: import("react").Context; export type BrandContext = 'bsuite' | 'braden'; export interface BrandingProviderProps { children: ReactNode; /** Authenticated Supabase client from the consuming app */ supabaseClient: SupabaseClient; /** * Brand context. 'braden' short-circuits all Supabase RPC/Realtime calls — * the Braden corporate site uses static CSS tokens only, not runtime overrides. * Default: 'bsuite' */ brand?: BrandContext; /** * If true, apply persisted branding immediately on mount (before RPC resolves) * to prevent FOUC. Default: true. Ignored when brand='braden'. */ applyPersistedOnMount?: boolean; } export declare function BrandingProvider({ children, supabaseClient, brand, applyPersistedOnMount, }: BrandingProviderProps): import("react").JSX.Element; //# sourceMappingURL=BrandingProvider.d.ts.map