@sorb/leaf 0.3.0 → 0.4.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/TokenProvider.jsx", "../src/context.js", "../src/sanitize.js", "../src/apply.js", "../src/modeStylesheet.js", "../node_modules/@sorb/core/src/index.js", "../src/targets/reactBootstrap.js", "../src/previewGuard.js", "../src/previewVocab.js", "../src/bridgeAuth.js", "../src/connection.js", "../src/sse.js", "../src/previewMode.js", "../src/modeAction.js", "../src/core.js", "../src/legacyMap.js", "../src/legacyDom.js", "../src/PreviewBanner.jsx", "../src/hooks.js", "../src/ThemeToggle.jsx", "../src/verify.js", "../src/darkModeConventions.js"],
4
- "sourcesContent": ["import React, { useCallback, useEffect, useMemo, useRef } from 'react'\nimport { TokenContext } from './context'\nimport { sorbInit, warnedDeprecations } from './core'\nimport { applyLegacyMap, clearLegacyMap } from './legacyDom'\n\n// Re-exported for back-compat \u2014 `warnedDeprecations` isn't part of the\n// public `@sorb/leaf` surface (not in `src/index.js`) but lived on this\n// module before the P0 leaf-core extraction moved the dedupe `Set` itself\n// into `./core.js`. Kept here so any existing deep import\n// (`sorb-leaf/src/TokenProvider`) still resolves the same object identity.\nexport { warnedDeprecations }\n\n// matchMedia only exists in browsers \u2014 same node:test-safety concern\n// `./core.js` guards against; used here only to seed the FIRST render's\n// `resolvedScheme` (a read, no DOM mutation) so it's correct before the\n// mount effect below has run, matching the pre-extraction component.\nconst matchMediaFn = typeof matchMedia !== 'undefined' ? matchMedia : null\nconst DARK_MEDIA_QUERY = '(prefers-color-scheme: dark)'\n\n/**\n * `SorbProvider` \u2014 the React shell over `sorbInit` (`./core.js`, the\n * framework-free injector; component-compat-roadmap P0). ALL runtime logic\n * (connection resolution, committed/preview loading, mode-aware injection,\n * SSE/poll, dark-mode state) now lives in `sorbInit`; this component's only\n * job is to bridge that instance's pub-sub store into React state and\n * expose the same `TokenContext` shape as before \u2014 non-breaking, byte-\n * identical behavior to the pre-extraction implementation. `sorbInit` is\n * created in the mount `useEffect` (not during render) so timing \u2014 and\n * StrictMode double-invoke safety \u2014 matches the original implementation,\n * which did all its DOM work in a mount-only effect too.\n *\n * The optional `legacyMap` (Legacy-React adapter, roadmap \u00A76) is an ADDITIVE,\n * non-destructive DOM overlay layered on top of the shell \u2014 it never touches\n * `sorbInit`. When present, after tokens apply it remaps any element whose\n * hardcoded literal matches a row's `raw` to `var(--<cssVar>, <raw>)`, and\n * restores the originals on unmount.\n *\n * @param {{\n * config: import('./types').SorbConfig,\n * legacyMap?: import('./types').LegacyMapRow[],\n * children: React.ReactNode,\n * }} props\n */\nexport const SorbProvider = ({ config, legacyMap, children }) => {\n const instanceRef = useRef(null)\n const legacyHandleRef = useRef(null)\n const [state, setState] = React.useState(() => ({\n tokens: config.tokens,\n isPreview: false,\n previewId: null,\n previewMismatch: false,\n mode: 'auto',\n resolvedScheme: matchMediaFn ? (matchMediaFn(DARK_MEDIA_QUERY).matches ? 'dark' : 'light') : 'light',\n }))\n\n // legacyMap prop wins over config.legacyMap; either enables the shim.\n const resolvedLegacyMap = legacyMap ?? config.legacyMap ?? null\n\n useEffect(() => {\n const instance = sorbInit(config)\n instanceRef.current = instance\n setState(instance.getState())\n const unsubscribe = instance.subscribe(setState)\n return () => {\n unsubscribe()\n instance.destroy()\n instanceRef.current = null\n }\n // Intentionally empty \u2014 only runs on mount, mirroring the original\n // component's contract (a changed `config` prop identity does not\n // reinitialize the connection).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // \u2500\u2500\u2500 legacy-map shim (roadmap \u00A76) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Additive overlay on top of the sorbInit shell: after tokens are applied\n // (and on every token change, so previews remap too), walk the DOM and remap\n // any hardcoded literal that matches a legacyMap row to `var(--cssVar, raw)`.\n // Restore on cleanup so removing the provider \u2014 or unmounting \u2014 returns the\n // original inline values.\n useEffect(() => {\n if (!resolvedLegacyMap || resolvedLegacyMap.length === 0) return undefined\n if (typeof document === 'undefined') return undefined\n // restore any prior overrides before re-applying against the new tokens\n if (legacyHandleRef.current) clearLegacyMap(legacyHandleRef.current)\n legacyHandleRef.current = applyLegacyMap(document.body, resolvedLegacyMap)\n return () => {\n if (legacyHandleRef.current) {\n clearLegacyMap(legacyHandleRef.current)\n legacyHandleRef.current = null\n }\n }\n }, [resolvedLegacyMap, state.tokens])\n\n const setMode = useCallback((next) => {\n if (instanceRef.current) instanceRef.current.setMode(next)\n }, [])\n const clearPreview = useCallback(() => {\n if (instanceRef.current) instanceRef.current.clearPreview()\n }, [])\n\n const value = useMemo(\n () => ({\n tokens: state.tokens,\n isPreview: state.isPreview,\n previewId: state.previewId,\n previewMismatch: state.previewMismatch,\n clearPreview,\n mode: state.mode,\n setMode,\n resolvedScheme: state.resolvedScheme,\n }),\n [state, clearPreview, setMode],\n )\n\n return <TokenContext.Provider value={value}>{children}</TokenContext.Provider>\n}\n", "import { createContext, useContext } from 'react'\n\n/** @type {import('react').Context<import('./types').TokenContextValue | null>} */\nexport const TokenContext = createContext(null)\n\n/** @returns {import('./types').TokenContextValue} */\nexport const useTokenContext = () => {\n const ctx = useContext(TokenContext)\n if (!ctx) {\n throw new Error('Sorb hooks must be used inside <SorbProvider>')\n }\n return ctx\n}\n", "/**\n * CSS token-value sanitizer \u2014 the C1 injection-boundary guard.\n *\n * Token values flow Figma \u2192 bridge \u2192 `applyTokens` \u2192 `setProperty`. Those values\n * are UNTRUSTED INPUT crossing a trust boundary. This is a pure string function\n * (no DOM) so it is fully node:test-able and reusable. Phase 2 will hoist it to\n * `@sorb/core`; do NOT add a DOM dependency here.\n *\n * Strategy: deny-by-default on the dangerous classes, then allowlist CSS\n * functions. A *valid* hostile value (a real `url(...)`) passes `setProperty`\n * unharmed, so we cannot rely on the browser \u2014 we reject it here.\n */\n\n/**\n * The only CSS functions we permit inside a token value. Anything else \u2014\n * `url(`, `image(`, `image-set(`, `-webkit-image-set(`, `cross-fade(`,\n * `expression(`, `paint(`, `element(`, `attr(`, \u2026 \u2014 is rejected.\n * @type {Set<string>}\n */\nconst ALLOWED_FUNCTIONS = new Set([\n 'rgb',\n 'rgba',\n 'hsl',\n 'hsla',\n 'hwb',\n 'lab',\n 'lch',\n 'oklab',\n 'oklch',\n 'color',\n 'calc',\n 'min',\n 'max',\n 'clamp',\n 'var',\n 'env',\n])\n\n// Matches an identifier immediately followed by '(' \u2014 i.e. a CSS function call.\n// Identifiers may start with one or two leading hyphens (vendor prefixes like\n// `-webkit-image-set`). The lookahead keeps the '(' out of the captured name.\nconst FUNCTION_CALL = /([a-zA-Z_-][\\w-]*)\\s*\\(/g\n\n// ASCII control chars (incl. NUL, newlines, tabs) \u2014 never legitimate in a\n// token value and a classic way to smuggle past naive filters.\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHARS = /[\\x00-\\x1f]/\n\n// CSS-context-break characters that let a value escape the custom-property\n// declaration: `;` ends the declaration, `{` / `}` open/close a block.\nconst CONTEXT_BREAK = /[{};]/\n\n/**\n * Validate an untrusted CSS token value before it is injected via\n * `setProperty`. Pure \u2014 does not touch the DOM.\n *\n * Rules (deny-by-default):\n * - non-string / empty input is rejected.\n * - reject ASCII control chars `\\x00-\\x1f`.\n * - reject the context-break chars `{` `}` `;`.\n * - reject (case-insensitive, whitespace-tolerant) `@import`, `javascript:`,\n * and the markup-break `</`.\n * - extract every `identifier(` and reject if ANY is not in the allowlist\n * (this is what stops `url(`, `image-set(`, `expression(`, `paint(`, \u2026).\n *\n * @param {unknown} value\n * @returns {{ ok: boolean, value: string, reason?: string }}\n */\nexport const sanitizeCssValue = (value) => {\n if (typeof value !== 'string') {\n return { ok: false, value: '', reason: 'not-a-string' }\n }\n\n const raw = value\n if (raw.length === 0) {\n return { ok: false, value: '', reason: 'empty' }\n }\n\n if (CONTROL_CHARS.test(raw)) {\n return { ok: false, value: raw, reason: 'control-char' }\n }\n\n if (CONTEXT_BREAK.test(raw)) {\n return { ok: false, value: raw, reason: 'context-break-char' }\n }\n\n // Case-insensitive, whitespace-tolerant dangerous tokens. We strip ASCII\n // whitespace before substring-matching so `@ import`, `java script:`,\n // `< /script` style evasions are still caught.\n const lower = raw.toLowerCase()\n const collapsed = lower.replace(/\\s+/g, '')\n if (collapsed.includes('@import')) {\n return { ok: false, value: raw, reason: 'at-import' }\n }\n if (collapsed.includes('javascript:')) {\n return { ok: false, value: raw, reason: 'javascript-scheme' }\n }\n if (collapsed.includes('</')) {\n return { ok: false, value: raw, reason: 'markup-break' }\n }\n\n // Allowlist every function call in the value.\n FUNCTION_CALL.lastIndex = 0\n let match\n while ((match = FUNCTION_CALL.exec(raw)) !== null) {\n const name = match[1].toLowerCase()\n if (!ALLOWED_FUNCTIONS.has(name)) {\n return { ok: false, value: raw, reason: `disallowed-function:${name}` }\n }\n }\n\n return { ok: true, value: raw }\n}\n", "import { sanitizeCssValue } from './sanitize.js'\n\n/**\n * Dev-only warning that never throws in a browser (no `process` global there).\n * Silent in production so a hostile token can't spam a shipped app's console.\n *\n * @param {string} key\n * @param {string} [reason]\n * @returns {void}\n */\nconst warnRejected = (key, reason) => {\n try {\n if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(\n `[sorb] skipped token \"--${key}\": value failed CSS sanitization` +\n (reason ? ` (${reason})` : ''),\n )\n }\n } catch (e) {\n // never let logging break token application\n void e\n }\n}\n\n/**\n * Writes all token values as CSS custom properties on :root.\n * Applies globally \u2014 affects the entire app.\n *\n * Each value is validated by {@link sanitizeCssValue} at this injection\n * boundary (concern C1). A value that fails sanitization is SKIPPED (fail\n * safe) \u2014 it is never written \u2014 and the remaining tokens still apply.\n *\n * @param {import('./types').TokenSet} tokens\n * @returns {void}\n */\nexport const applyTokens = (tokens) => {\n const root = document.documentElement\n Object.entries(tokens).forEach(([key, value]) => {\n const result = sanitizeCssValue(String(value))\n if (!result.ok) {\n warnRejected(key, result.reason)\n return\n }\n root.style.setProperty(`--${key}`, result.value)\n })\n}\n\n/**\n * Removes token CSS custom properties from :root.\n * Called when clearing a preview to restore the committed set.\n *\n * @param {import('./types').TokenSet} tokens\n * @returns {void}\n */\nexport const clearTokenOverrides = (tokens) => {\n const root = document.documentElement\n Object.keys(tokens).forEach((key) => {\n root.style.removeProperty(`--${key}`)\n })\n}\n\n/** The id of the `<style>` tag {@link injectModeStylesheet} upserts. */\nexport const MODE_STYLESHEET_ID = 'sorb-tokens'\n\n/**\n * Upserts a `<style id=\"sorb-tokens\">` tag in `<head>` carrying mode-aware\n * CSS (real-dark-mode spec D3) \u2014 the injection path used when a theme has\n * both a light and a dark value-set (see `buildModeStylesheet`,\n * `./modeStylesheet.js`).\n *\n * DELIBERATELY SEPARATE from `applyTokens`/`clearTokenOverrides` (inline\n * `style.setProperty`, above): those two stay untouched and are still what\n * `TokenProvider` calls for a light-only theme, so a single-mode app's\n * output is byte-identical to today (back-compat gate, spec \u00A73 D3). This\n * function is only reached when a theme actually has a dark mode \u2014 a\n * `<style>` tag is required (not inline styles) because only a stylesheet\n * can carry a `@media (prefers-color-scheme: dark)` block and\n * attribute-selector rules; inline styles on `documentElement` can express\n * neither.\n *\n * The `css` argument is expected to already be sanitized (`buildModeStylesheet`\n * runs every value through `sanitizeCssValue` before it reaches here) \u2014 this\n * function does no further validation, it only manages the tag's lifecycle.\n *\n * @param {string} css CSS text, e.g. from `buildModeStylesheet(...)`.\n * @returns {void}\n */\nexport const injectModeStylesheet = (css) => {\n let tag = document.getElementById(MODE_STYLESHEET_ID)\n if (!tag) {\n tag = document.createElement('style')\n tag.id = MODE_STYLESHEET_ID\n document.head.appendChild(tag)\n }\n tag.textContent = css\n}\n\n/**\n * Removes the `<style id=\"sorb-tokens\">` tag injected by\n * {@link injectModeStylesheet}, if present. Counterpart to\n * `clearTokenOverrides` for the mode-aware (dual-mode) path.\n *\n * @returns {void}\n */\nexport const clearModeStylesheet = () => {\n const tag = document.getElementById(MODE_STYLESHEET_ID)\n if (tag && tag.parentNode) tag.parentNode.removeChild(tag)\n}\n", "import { sanitizeCssValue } from './sanitize.js'\n\n/**\n * Builds the mode-aware CSS text carrying both a light and (optionally) a\n * dark value-set for the same token ids \u2014 real-dark-mode spec D2/D3.\n *\n * Pure \u2014 no DOM. Returns a CSS string meant to be upserted into a\n * `<style id=\"sorb-tokens\">` tag by {@link injectModeStylesheet} (`apply.js`).\n *\n * Contract (must stay byte-shape-stable \u2014 the demo/cloud emit agents match\n * this exact shape):\n *\n * ```css\n * :root { --a: 1; color-scheme: light; }\n * @media (prefers-color-scheme: dark) {\n * :root:not([data-bs-theme=\"light\"]) { --a: 2; color-scheme: dark; }\n * }\n * [data-bs-theme=\"dark\"] { --a: 2; color-scheme: dark; }\n * [data-bs-theme=\"light\"] { --a: 1; color-scheme: light; }\n * ```\n *\n * The `:not(<lightSelector>)` clause in the `@media` block is what lets a\n * manual \"light\" override beat the OS `prefers-color-scheme: dark` setting \u2014\n * without it, an explicit light choice would still get overridden by an OS\n * dark preference.\n *\n * Single-mode fallback (no `darkVars` / no `darkMode`): emits ONLY a flat\n * `:root { <light decls> }` block \u2014 no `color-scheme`, no media query, no\n * attribute rules \u2014 so a light-only theme's CSS is unchanged from today's\n * flat emit (back-compat gate, spec \u00A73 D3).\n *\n * @param {import('./types').TokenSet} lightVars\n * Light-mode token map. Keys may be bare (`'primary'`) or already\n * `--`-prefixed (`'--primary'`) \u2014 normalized here.\n * @param {import('./types').TokenSet | null | undefined} darkVars\n * Dark-mode token map, same key shape. `null`/`undefined`/`{}` \u21D2 single-mode.\n * @param {import('@sorb/core').DarkModeConvention | null | undefined} darkMode\n * The active TargetAdapter's dark-mode convention (e.g.\n * `reactBootstrapTarget.darkMode`). Undefined \u21D2 single-mode.\n * @returns {string} CSS text, ready to inject verbatim.\n */\nexport const buildModeStylesheet = (lightVars, darkVars, darkMode) => {\n const lightDecls = normalizeDecls(lightVars)\n const hasDark = !!darkMode && !!darkVars && Object.keys(darkVars).length > 0\n\n if (!hasDark) {\n return `:root {\\n${indent(lightDecls)}\\n}\\n`\n }\n\n const darkDecls = normalizeDecls(darkVars)\n const darkSelector = darkMode.darkSelector\n const lightSelector = darkMode.lightSelector\n\n const mediaScopeSelector = lightSelector ? `:root:not(${lightSelector})` : ':root'\n\n const lines = []\n lines.push(':root {')\n lines.push(indent([...lightDecls, 'color-scheme: light;']))\n lines.push('}')\n lines.push('@media (prefers-color-scheme: dark) {')\n lines.push(` ${mediaScopeSelector} {`)\n lines.push(indent([...darkDecls, 'color-scheme: dark;'], 2))\n lines.push(' }')\n lines.push('}')\n lines.push(`${darkSelector} {`)\n lines.push(indent([...darkDecls, 'color-scheme: dark;']))\n lines.push('}')\n if (lightSelector) {\n lines.push(`${lightSelector} {`)\n lines.push(indent([...lightDecls, 'color-scheme: light;']))\n lines.push('}')\n }\n return `${lines.join('\\n')}\\n`\n}\n\n/**\n * Normalizes a TokenSet into `--key: value;` declaration lines, normalizing\n * bare keys to `--`-prefixed and skipping any value that fails\n * {@link sanitizeCssValue} (fail-safe \u2014 same C1 boundary `applyTokens` uses;\n * this text goes straight into a `<style>` tag so it's an even more\n * sensitive boundary than `setProperty`).\n *\n * @param {import('./types').TokenSet | null | undefined} vars\n * @returns {string[]}\n */\nconst normalizeDecls = (vars) => {\n if (!vars) return []\n return Object.entries(vars).reduce((acc, [key, value]) => {\n const result = sanitizeCssValue(String(value))\n if (!result.ok) return acc\n const cssVar = key.startsWith('--') ? key : `--${key}`\n acc.push(`${cssVar}: ${result.value};`)\n return acc\n }, [])\n}\n\n/**\n * @param {string[]} lines\n * @param {number} [level]\n * @returns {string}\n */\nconst indent = (lines, level = 1) => {\n const pad = ' '.repeat(level)\n return lines.map((l) => `${pad}${l}`).join('\\n')\n}\n", "// @sorb/core \u2014 the shared Sorb contract.\n//\n// One published home for the shapes that cross repo boundaries: the resolved\n// bindable token map (Style Dictionary's `sorb/resolved-map` output) and the\n// capture schemas (LayerNode tree, story index). Consolidated here so the\n// contract can't drift across sorb-seed, sorb-juice, and sorb-leaf once the\n// monorepo is split (sorb-rename-migration \u00A73.2).\n//\n// JS-only, JSDoc typedefs \u2014 per the hard rules, no TypeScript. The only runtime\n// export is the canonical tier ordering, which the capture annotator and the\n// plugin both rank against.\n\n/**\n * Token tiers, most-specific first. Binding precedence: component beats\n * semantic beats primitive.\n * @type {readonly ['component', 'semantic', 'primitive']}\n */\nexport const TIERS = Object.freeze(['component', 'semantic', 'primitive'])\n\n/**\n * Tier \u2192 rank (0 = most specific). Lower wins when several tokens share a value.\n * @type {Readonly<Record<Tier, number>>}\n */\nexport const TIER_RANK = Object.freeze({ component: 0, semantic: 1, primitive: 2 })\n\n// \u2500\u2500\u2500 Shared typedefs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * @typedef {'primitive' | 'semantic' | 'component'} Tier\n * Which layer of the 3-tier DTCG taxonomy a token belongs to.\n */\n\n/**\n * @typedef {'color' | 'dimension' | 'fontFamily' | 'fontWeight' | 'number' | 'string'} TokenType\n * DTCG `$type` of the resolved token (extend as the taxonomy grows).\n */\n\n/**\n * A flat map of token name \u2192 value.\n * @typedef {Object.<string, string | number>} TokenSet\n */\n\n/**\n * One entry of the resolved bindable token map \u2014 the single contract produced by\n * Style Dictionary (`sorb/resolved-map`) and consumed by the bridge, the capture\n * annotator, and the plugin. This is THE shape that must not drift.\n * @typedef {Object} ResolvedToken\n * @property {string} id Dotted token id, e.g. `button.primary.bg.default`.\n * @property {string} cssVar The emitted CSS custom property, e.g. `--button-primary-bg-default`.\n * @property {string | number} value Fully resolved value (no `var()` chains).\n * @property {Tier} tier Taxonomy tier (drives binding precedence via TIER_RANK).\n * @property {TokenType} type DTCG `$type`.\n */\n\n/**\n * The resolved map as served/written: `.sorb/resolved.json`.\n * @typedef {ResolvedToken[]} ResolvedMap\n */\n\n/**\n * A captured CSS value plus the raw string it came from.\n * @typedef {Object} RawValue\n * @property {string} raw The raw CSS string captured from the DOM (e.g. `rgb(15,101,239)`).\n */\n\n/**\n * A node in a captured layer tree (Storybook story \u2192 Figma-insertable geometry).\n * Produced by capture, annotated in place by the seed annotator, materialized by\n * the plugin.\n * @typedef {Object} LayerNode\n * @property {string} type Figma-ish node type, e.g. `FRAME`, `TEXT`.\n * @property {RawValue[]} [fills] Fill paints (index 0 is the primary fill).\n * @property {RawValue[]} [strokes] Stroke paints.\n * @property {number} [cornerRadius] Corner radius in px.\n * @property {{ color?: RawValue }[]} [effects] Effects (shadows, etc.).\n * @property {LayerNode[]} [children] Child nodes.\n * @property {SorbAnnotation} [sorb] Token bindings attached by the annotator.\n */\n\n/**\n * Token bindings the seed annotator stamps onto a matched LayerNode.\n * @typedef {Object} SorbAnnotation\n * @property {Object.<string, string>} tokens\n * role (`fill`/`stroke`/`cornerRadius`/`effectN`) \u2192 bound token id.\n * @property {Object.<string, string[]>} candidates\n * role \u2192 all token ids whose value matched (the plugin offers these as a switch).\n */\n\n/**\n * One story's entry in the capture index (`.sorb/index.json`).\n * @typedef {Object} StoryEntry\n * @property {string} artifact Relative path to the captured artifact (`*.sorb.json`).\n */\n\n/**\n * The capture index written to `.sorb/index.json`.\n * @typedef {Object} StoryIndex\n * @property {Object.<string, StoryEntry>} stories storyId \u2192 entry.\n */\n\n/**\n * Identifies a component variant by its dot-path prefix.\n * e.g. \"button.tertiary\" covers all tokens whose id starts with \"button.tertiary.\"\n * @typedef {Object} VariantSpec\n * @property {string} componentId Top-level component key, e.g. \"button\".\n * @property {string} variantId Full dot-path of the variant, e.g. \"button.tertiary\".\n * @property {string} [fromVariant] Dot-path of the source variant to clone from (addVariant only).\n * @property {string} [replacedBy] Dot-path that replaces this variant (deprecateVariant only).\n */\n\n/**\n * The result of a lifecycle action \u2014 what changed.\n * @typedef {Object} VariantChangeset\n * @property {'add'|'deprecate'} action\n * @property {string} variantId The variant that was added or deprecated.\n * @property {string[]} tokenIds All token ids affected (added or deprecated).\n * @property {string} newVersion The component set's new $version after the change.\n */\n\n// \u2500\u2500\u2500 Connector contract (v1: additive) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Three pluggable axes \u2014 SOURCE (where tokens + geometry come IN), CODE-SOURCE\n// (where the running app / codebase lives), and TARGET (how tokens bind into the\n// app) \u2014 plus a runtime registry that dispatches by `id`. Core only defines the\n// contract + registry + default ids; the default implementations are registered\n// by sorb-seed / sorb-juice / sorb-leaf in later phases. See\n// spec/sorb/connectors-architecture.md. `config` everywhere below is the app's\n// `sorb.config.json`-shaped object.\n\n/**\n * A design unit to capture \u2014 one addressable thing a SourceConnector can turn\n * into geometry (today's Storybook \"story entry\" is one). Opaque-ish: only `id`\n * is guaranteed; connectors carry whatever extra metadata they need.\n * @typedef {Object} DesignUnit\n * @property {string} id Stable unit id (e.g. a Storybook story id).\n * @property {string} [name] Human-readable label.\n */\n\n/**\n * SOURCE axis \u2014 where design tokens + geometry come IN. A real source pulls BOTH\n * tokens and geometry from the tool (founder decision 2026-08-28).\n * @typedef {Object} SourceConnector\n * @property {string} id Registry key (default `'storybook-dom'`).\n * @property {(config: Object) => Promise<DesignUnit[]>} listUnits\n * Discover the design units to capture.\n * @property {(unit: DesignUnit, config: Object) => Promise<LayerNode>} captureGeometry\n * Capture one unit as a raw (un-annotated) LayerNode tree.\n * @property {(config: Object) => Promise<TokenSet>} readTokens\n * Read the DTCG token set for this source.\n */\n\n/**\n * CODE-SOURCE axis \u2014 where the running app / codebase lives.\n * @typedef {Object} CodeSourceConnector\n * @property {string} id Registry key (default `'local'`).\n * @property {(config: Object) => Promise<string|null>} resolveAppUrl\n * Resolve the running app's URL (today = `appUrl` / `localhost:5173`).\n * @property {(config: Object) => string} resolveProjectRoot\n * Resolve the project root dir (today = `process.cwd()`).\n * @property {(config: Object) => Promise<void>} [provision]\n * Optional: clone/build a repo \u2192 hosted preview (future code sources).\n */\n\n/**\n * TARGET axis \u2014 how tokens bind into the running app (the component-compat seam).\n * @typedef {Object} TargetAdapter\n * @property {string} id Registry key (default `'react-bootstrap'`).\n * @property {string} emitFormat A Style-Dictionary format id (e.g. `SORB_TOKENSET`).\n * @property {string[]} expectPrefixes Vocab-guard namespace(s), e.g. `['bs-']`.\n * @property {(tokens: TokenSet, config: Object) => void} [inject]\n * Optional: bind tokens into non-React hosts (the `sorbInit` seam).\n * @property {DarkModeConvention} [darkMode]\n * Optional: this target's dark-mode convention (real-dark-mode spec D1).\n * Undefined \u21D2 single-mode (no dark) \u2014 the target has no notion of a dark\n * variant and mode-aware emit/inject should fall back to flat `:root` output.\n */\n\n/**\n * How a TargetAdapter's host framework expresses light/dark mode. v1 only\n * ships `'attribute'` (Bootstrap 5.3's `[data-bs-theme]`); `'class'`\n * (Tailwind's `.dark`) and `'media'` (OS-only, no manual override) are named\n * here for forward-compat but not yet implemented by any shipped adapter \u2014\n * see real-dark-mode-implementation spec \u00A73 \"Deferred to phase 2\".\n * @typedef {Object} DarkModeConvention\n * @property {'attribute'|'class'|'media'} strategy\n * How the manual override is expressed. `'attribute'` sets/reads a DOM\n * attribute (e.g. `data-bs-theme`); `'class'` toggles a class on\n * `documentElement`; `'media'` means OS-only, no manual override.\n * @property {string} [attribute]\n * The attribute name for `strategy: 'attribute'` (e.g. `'data-bs-theme'`).\n * @property {string} darkSelector\n * The CSS selector matching the dark-mode override (e.g.\n * `'[data-bs-theme=\"dark\"]'`).\n * @property {string} [lightSelector]\n * The CSS selector matching an explicit light-mode override (e.g.\n * `'[data-bs-theme=\"light\"]'`) \u2014 lets a manual \"light\" choice beat an OS\n * `prefers-color-scheme: dark` setting.\n */\n\n/** Default SOURCE connector id (registered by sorb-seed). @type {string} */\nexport const DEFAULT_SOURCE_ID = 'storybook-dom'\n\n/** Default CODE-SOURCE connector id (registered by sorb-juice). @type {string} */\nexport const DEFAULT_CODE_SOURCE_ID = 'local'\n\n/** Default TARGET adapter id (registered by sorb-leaf). @type {string} */\nexport const DEFAULT_TARGET_ID = 'react-bootstrap'\n\n/**\n * The runtime connector registry \u2014 id \u2192 impl per axis. The Maps are mutable by\n * design so consumer packages register their defaults into them; the container\n * itself is frozen so the axis set can't drift.\n * @typedef {Object} ConnectorRegistry\n * @property {Map<string, SourceConnector>} source\n * @property {Map<string, CodeSourceConnector>} codeSource\n * @property {Map<string, TargetAdapter>} target\n * @type {ConnectorRegistry}\n */\nexport const connectors = Object.freeze({\n source: new Map(),\n codeSource: new Map(),\n target: new Map(),\n})\n\n/**\n * Register a SOURCE connector by its `id`.\n * @param {SourceConnector} conn\n * @returns {SourceConnector} the registered connector.\n */\nexport function registerSource(conn) {\n connectors.source.set(conn.id, conn)\n return conn\n}\n\n/**\n * Register a CODE-SOURCE connector by its `id`.\n * @param {CodeSourceConnector} conn\n * @returns {CodeSourceConnector} the registered connector.\n */\nexport function registerCodeSource(conn) {\n connectors.codeSource.set(conn.id, conn)\n return conn\n}\n\n/**\n * Register a TARGET adapter by its `id`.\n * @param {TargetAdapter} adapter\n * @returns {TargetAdapter} the registered adapter.\n */\nexport function registerTarget(adapter) {\n connectors.target.set(adapter.id, adapter)\n return adapter\n}\n\n/**\n * Look up a registered SOURCE connector; throws on unknown id.\n * @param {string} id\n * @returns {SourceConnector}\n */\nexport function getSource(id) {\n const conn = connectors.source.get(id)\n if (!conn) throw new Error(`Unknown source connector: ${JSON.stringify(id)}`)\n return conn\n}\n\n/**\n * Look up a registered CODE-SOURCE connector; throws on unknown id.\n * @param {string} id\n * @returns {CodeSourceConnector}\n */\nexport function getCodeSource(id) {\n const conn = connectors.codeSource.get(id)\n if (!conn) throw new Error(`Unknown codeSource connector: ${JSON.stringify(id)}`)\n return conn\n}\n\n/**\n * Look up a registered TARGET adapter; throws on unknown id.\n * @param {string} id\n * @returns {TargetAdapter}\n */\nexport function getTarget(id) {\n const adapter = connectors.target.get(id)\n if (!adapter) throw new Error(`Unknown target adapter: ${JSON.stringify(id)}`)\n return adapter\n}\n\n/**\n * Resolve the three connector ids from a config, falling back to the defaults\n * when a key is absent (back-compat = today's behavior).\n * @param {{ source?: string, codeSource?: string, target?: string }} [config]\n * @returns {{ source: string, codeSource: string, target: string }}\n */\nexport function resolveConnectorIds(config = {}) {\n return {\n source: config.source || DEFAULT_SOURCE_ID,\n codeSource: config.codeSource || DEFAULT_CODE_SOURCE_ID,\n target: config.target || DEFAULT_TARGET_ID,\n }\n}\n\nexport {}\n", "/**\n * The `react-bootstrap` TargetAdapter \u2014 Sorb's DEFAULT target (connectors\n * architecture spec \u00A73.3/\u00A74 C3): \"how tokens bind into the running app\" for\n * today's React + Bootstrap-styled component set.\n *\n * v1 scope (spec \u00A74 C3): DEFINE + REGISTER the adapter against the\n * `@sorb/core` connector contract. This is a descriptive re-cast of today's\n * already-shipped behavior \u2014 it does NOT reroute the live vocab guard or the\n * Provider's token-apply path to the registry. `SorbProvider` keeps reading\n * `config.preview.expectPrefixes` directly (see `TokenProvider.jsx`) and\n * `applyTokens` (`apply.js`) stays the pure-JS inject; both are unchanged by\n * this file. `inject` is intentionally left undefined here \u2014 React hosts\n * bind tokens via the Provider/`applyTokens`, not via an adapter-level\n * `inject` call; that seam is for non-React hosts and belongs to the\n * Component Compat Roadmap's `@sorb/leaf-core`/`@sorb/emit` extraction\n * (out of scope for this phase).\n */\nimport * as core from '@sorb/core'\n\n// The Style-Dictionary format id that emits this target's token set, from the\n// named-format registry (`sorb-demo/sd/sorb-format.js:30`):\n// export const SORB_TOKENSET = 'sorb/tokenset-esm'\n// Inlined as a string (not imported) so `@sorb/leaf` doesn't take a build-time\n// dependency on `sorb-demo`'s Style Dictionary config \u2014 the format id is a\n// stable, documented string contract, not a JS binding.\nconst SORB_TOKENSET_FORMAT_ID = 'sorb/tokenset-esm'\n\n/**\n * @type {import('@sorb/core').TargetAdapter}\n */\nexport const reactBootstrapTarget = {\n id: 'react-bootstrap',\n emitFormat: SORB_TOKENSET_FORMAT_ID,\n // The Bootstrap-styled vocab namespace (matches `sorb-demo/src/sorbConfig.js`'s\n // `preview.expectPrefixes: ['bs-']`).\n expectPrefixes: ['bs-'],\n // Left undefined on purpose \u2014 see file header.\n inject: undefined,\n // Bootstrap 5.3's native dark-mode convention (real-dark-mode spec D1): a\n // `data-bs-theme` attribute on any ancestor (Bootstrap recommends\n // `<html>`) selects the mode; absent \u21D2 OS `prefers-color-scheme` governs.\n darkMode: {\n strategy: 'attribute',\n attribute: 'data-bs-theme',\n darkSelector: '[data-bs-theme=\"dark\"]',\n lightSelector: '[data-bs-theme=\"light\"]',\n },\n}\n\n// Register into the @sorb/core registry WHEN this build's core supports it. The\n// published @sorb/core on npm can lag the connector contract (polyrepo publish\n// order); a namespace import + feature-detect keeps the esbuild build + runtime\n// working against an older published core (no \"no matching export\" / crash).\nif (typeof core.registerTarget === 'function') {\n core.registerTarget(reactBootstrapTarget)\n}\n\nexport default reactBootstrapTarget\n", "/**\n * Preview-origin guard \u2014 the C3 production foot-gun guard.\n *\n * Preview defaults OFF. Even when a team opts in, the SDK must only talk to a\n * TRUSTED bridge origin: a stray `?preview=` on a production link must not be\n * able to point the running app at an untrusted bridge. This pure helper makes\n * that decision; the provider wires it in. No DOM, fully node:test-able.\n */\n\nconst DEFAULT_ORIGIN = 'http://localhost:7777'\n\n/**\n * Is `origin` a localhost / loopback origin (any port)? `http`/`https`,\n * `localhost`, `127.0.0.1`, and IPv6 `[::1]` all count.\n *\n * @param {string} origin\n * @returns {boolean}\n */\nconst isLocalhostOrigin = (origin) => {\n let url\n try {\n url = new URL(origin)\n } catch (e) {\n void e\n return false\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return false\n const host = url.hostname.toLowerCase()\n return host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '[::1]'\n}\n\n/**\n * Normalise to a bare `protocol//host:port` origin for exact comparison\n * against a consumer-supplied allowlist (trailing slashes / paths ignored).\n *\n * @param {string} value\n * @returns {string|null}\n */\nconst toOrigin = (value) => {\n try {\n return new URL(value).origin\n } catch (e) {\n void e\n return null\n }\n}\n\n/**\n * Decide whether the preview path may run, and against which origin.\n *\n * Allowed only when BOTH:\n * 1. `config.preview?.enabled === true` (strict \u2014 not just truthy), and\n * 2. the resolved origin is on the allowlist: localhost/127.0.0.1/[::1]\n * (any port) by default, plus any exact origins the consumer lists in\n * `config.preview.allowedOrigins`.\n *\n * Anything else (disabled, missing config, non-allowlisted origin, malformed\n * origin) \u2192 not allowed; the caller falls back to committed tokens.\n *\n * @param {import('./types').SorbConfig} [config]\n * @returns {{ allowed: boolean, origin: string|null, reason?: string }}\n */\nexport const shouldLoadPreview = (config) => {\n const preview = config && config.preview\n if (!preview || preview.enabled !== true) {\n return { allowed: false, origin: null, reason: 'preview-disabled' }\n }\n\n const origin = preview.origin ?? DEFAULT_ORIGIN\n const normalized = toOrigin(origin)\n if (!normalized) {\n return { allowed: false, origin: null, reason: 'malformed-origin' }\n }\n\n if (isLocalhostOrigin(origin)) {\n return { allowed: true, origin }\n }\n\n const extra = Array.isArray(preview.allowedOrigins) ? preview.allowedOrigins : []\n const allowed = extra.some((entry) => toOrigin(entry) === normalized)\n if (allowed) {\n return { allowed: true, origin }\n }\n\n return { allowed: false, origin, reason: 'origin-not-allowlisted' }\n}\n", "/**\n * Vocabulary / contract guard (GFP RC1 Part 4 \u00B7 backlog B4).\n *\n * The failure mode this catches: a preview whose token keys don't intersect the\n * custom-property namespace the app actually consumes (e.g. an app that renders\n * from `--bs-*` fed a `--color-*` preview). `applyTokens` faithfully writes the\n * preview's vars onto `<html>`, the \"preview active\" banner lights \u2014 but nothing\n * on screen moves. A silent no-op is the worst founder-demo failure mode.\n *\n * This guard makes that condition LOUD instead of silent. It is fully opt-in:\n * off unless the consumer sets `config.preview.expectPrefixes` to a non-empty\n * array of key prefixes it expects (e.g. `['bs-']`). No DOM, fully node:test-able.\n */\n\n/**\n * How many of `tokens`' keys start with ANY of `prefixes`.\n *\n * @param {import('./types').TokenSet} tokens\n * @param {string[]} prefixes\n * @returns {number}\n */\nexport const countMatchingPrefixes = (tokens, prefixes) => {\n const list = Array.isArray(prefixes) ? prefixes : []\n return Object.keys(tokens || {}).filter((key) => list.some((p) => key.startsWith(p))).length\n}\n\n/**\n * Decide whether a freshly-applied preview mismatches the app's expected token\n * vocabulary, and `console.warn` an actionable message when it does.\n *\n * Guard is OFF (returns false, never warns) unless `expectPrefixes` is a\n * non-empty array \u2014 so the default is zero behaviour change. When ON: a preview\n * that applied at least one token but matched ZERO expected prefixes is a\n * mismatch (warn + return true). An empty/failed preview (0 applied tokens) is\n * NOT treated as a mismatch \u2014 that is a separate condition the provider already\n * handles by falling back to committed tokens.\n *\n * @param {object} args\n * @param {import('./types').TokenSet} args.tokens Applied preview token set.\n * @param {string[]} [args.expectPrefixes] Key prefixes the app expects.\n * @param {string|null} [args.previewId] Preview id, for the message.\n * @returns {boolean} true when a vocabulary mismatch was detected.\n */\nexport const checkPreviewVocabulary = ({ tokens, expectPrefixes, previewId }) => {\n if (!Array.isArray(expectPrefixes) || expectPrefixes.length === 0) return false\n\n const appliedCount = Object.keys(tokens || {}).length\n if (appliedCount === 0) return false // empty/failed preview \u2014 not a vocab mismatch\n\n const matched = countMatchingPrefixes(tokens, expectPrefixes)\n if (matched > 0) return false\n\n try {\n // Intentionally NOT gated on NODE_ENV: the guard is opt-in, and a\n // demo-blocking silent no-op is exactly what a shipped consumer wants to see.\n // eslint-disable-next-line no-console\n console.warn(\n `[Sorb] preview ${previewId ? `\"${previewId}\" ` : ''}applied ${appliedCount} tokens ` +\n `but none match expected prefixes ${JSON.stringify(expectPrefixes)} \u2014 the app may not ` +\n `visibly re-skin (token-vocabulary mismatch).`,\n )\n } catch (e) {\n // never let logging break token application\n void e\n }\n return true\n}\n", "// bridgeAuth.js \u2014 hosted-bridge Authorization header (Plugin-UX U4).\n//\n// Sorb's hosted bridge (https://bridge.sorbcloud.com) requires\n// `Authorization: Bearer <key>` on every route except /health. The key is a\n// read-only publishable `sorb_pk_\u2026` (safe to ship in a distributable; 403s on\n// writes). Local `sorb dev` runs with NO auth, so when no key is configured we\n// send NO header and the localhost path is byte-for-byte unchanged.\n//\n// One place builds the header so both fetch sites (TokenProvider preview poll +\n// verify.js) stay consistent. Pure + node:test-able; no DOM, no fetch.\n\n/**\n * Build the request headers for a hosted-bridge call, merging in the bearer\n * `Authorization` header only when a non-empty key is configured.\n *\n * @param {string} [key] The configured bearer key (`config.preview.key`), if any.\n * @param {Record<string,string>} [base] Base headers to extend (e.g. Content-Type).\n * @returns {Record<string,string>}\n */\nexport const bridgeHeaders = (key, base) => {\n const headers = base ? { ...base } : {}\n if (typeof key === 'string' && key.trim() !== '') {\n headers.Authorization = `Bearer ${key.trim()}`\n }\n return headers\n}\n", "// connection.js \u2014 org-key connection resolution (Phase E1, hosted-bridge-modes).\n//\n// Load-bearing principle (spec/sorb/hosted-bridge-modes-exploration-plan.md \u00A71,\n// experiments/sorb-bridge-modes/contracts/config-migration.md \"Resolution chain\n// per client / sorb-leaf\"): the running app identifies itself via a single\n// org/publishable key \u2014 like an analytics SDK key \u2014 and everything else\n// (bridge mode/url, token source, preview persistence) resolves from the org\n// server-side. Explicit `config.preview.origin` (today's file-mode / Mode C\n// path) always wins and is untouched; org-key resolution is purely additive.\n//\n// TODO(E1 cloud contract \u2014 reconcile when the sorb-cloud agent lands the real\n// endpoint): assumed shape \u2014\n//\n// GET <cloudBase>/api/orgs/resolve?key=<publishableKey>\n// \u2192 200 {\n// bridgeMode: 'A' | 'B' | 'C',\n// bridgeUrl: string, // e.g. \"https://bridge.sorbcloud.com\"\n// orgId?: string, // needed to build the SSE subscribe URL\n// tokenSource?: string,\n// previewPersistence?: boolean,\n// transport?: 'sse' | 'poll', // defaults to 'sse' when bridgeMode === 'A'\n// }\n// \u2192 non-2xx (unknown/revoked key, network error) \u2192 resolution returns `null`;\n// the caller falls back to today's \"server not running\" behavior (loads\n// committed tokens, never throws).\n\n/** @type {string} */\nexport const DEFAULT_CLOUD_BASE = 'https://api.sorbcloud.com'\n\n/**\n * Read the org/publishable key off a SorbConfig, accepting either field name.\n * @param {import('./types').SorbConfig} [config]\n * @returns {string|null}\n */\nexport const getOrgKey = (config) => {\n if (!config) return null\n const key = config.orgKey || config.publishableKey\n return typeof key === 'string' && key.trim() !== '' ? key.trim() : null\n}\n\n/**\n * Should we attempt org-key resolution at all? Only when an org key is\n * present AND the consumer has not already pinned an explicit\n * `config.preview.origin` \u2014 an explicit origin is today's file-mode / Mode C\n * path and always takes precedence (config-migration.md's resolution chain,\n * step 1).\n *\n * @param {import('./types').SorbConfig} [config]\n * @returns {boolean}\n */\nexport const shouldResolveOrgConnection = (config) => {\n const key = getOrgKey(config)\n if (!key) return false\n const explicitOrigin = config && config.preview && config.preview.origin\n return !(typeof explicitOrigin === 'string' && explicitOrigin.trim() !== '')\n}\n\n/**\n * Fetch the effective connection config for an org/publishable key.\n * Never throws \u2014 network errors, non-2xx responses, and malformed payloads\n * all resolve to `null` so callers can fall back safely.\n *\n * @param {string} orgKey\n * @param {{ cloudBase?: string, fetchImpl?: typeof fetch }} [opts]\n * @returns {Promise<import('./types').ResolvedConnection|null>}\n */\nexport const resolveOrgConnection = async (orgKey, opts) => {\n const { cloudBase = DEFAULT_CLOUD_BASE, fetchImpl } = opts || {}\n const doFetch = fetchImpl || (typeof fetch !== 'undefined' ? fetch : null)\n if (!doFetch || typeof orgKey !== 'string' || orgKey.trim() === '') return null\n\n try {\n const base = cloudBase.replace(/\\/$/, '')\n const url = `${base}/api/orgs/resolve?key=${encodeURIComponent(orgKey.trim())}`\n const res = await doFetch(url)\n if (!res || !res.ok) return null\n const data = await res.json()\n if (!data || typeof data !== 'object') return null\n if (typeof data.bridgeUrl !== 'string' || data.bridgeUrl.trim() === '') return null\n\n const bridgeMode = typeof data.bridgeMode === 'string' ? data.bridgeMode : 'C'\n return {\n bridgeMode,\n bridgeUrl: data.bridgeUrl,\n orgId: typeof data.orgId === 'string' ? data.orgId : null,\n tokenSource: typeof data.tokenSource === 'string' ? data.tokenSource : null,\n // sorb-cloud's /api/orgs/resolve returns this as a boolean (entitlement\n // flag), not an object \u2014 see cloud src/lib/orgResolve.ts.\n previewPersistence:\n typeof data.previewPersistence === 'boolean' ? data.previewPersistence : null,\n transport: data.transport === 'poll' || data.transport === 'sse' ? data.transport : bridgeMode === 'A' ? 'sse' : 'poll',\n }\n } catch (e) {\n void e\n return null\n }\n}\n\n/**\n * Merge a resolved org connection into an effective `preview` config, without\n * mutating the inputs. When `resolved` is falsy this is the identity function\n * on `config.preview` \u2014 the byte-for-byte back-compat path.\n *\n * @param {import('./types').SorbConfig} config\n * @param {import('./types').ResolvedConnection|null} resolved\n * @returns {import('./types').PreviewConfig}\n */\nexport const buildEffectivePreviewConfig = (config, resolved) => {\n const base = (config && config.preview) || {}\n if (!resolved) return base\n const orgKey = getOrgKey(config)\n return {\n ...base,\n enabled: true,\n origin: resolved.bridgeUrl,\n allowedOrigins: [...(Array.isArray(base.allowedOrigins) ? base.allowedOrigins : []), resolved.bridgeUrl],\n key: base.key || orgKey || undefined,\n }\n}\n\n/**\n * Build the effective SorbConfig used for the rest of the provider's logic:\n * `config` untouched, except `preview` merged with the resolved connection\n * (if any). Pure, so it's trivially testable independent of React/fetch.\n *\n * @param {import('./types').SorbConfig} config\n * @param {import('./types').ResolvedConnection|null} resolved\n * @returns {import('./types').SorbConfig}\n */\nexport const buildEffectiveConfig = (config, resolved) => {\n if (!resolved) return config\n return { ...config, preview: buildEffectivePreviewConfig(config, resolved) }\n}\n", "// sse.js \u2014 hosted-relay preview subscription (Phase E1, hosted-bridge-modes).\n//\n// When the resolved connection is a hosted relay (Mode A), SorbProvider\n// subscribes to preview updates via Server-Sent Events instead of the poll\n// loop kept for Mode C / non-SSE bridges. Pure URL-building + frame-parsing\n// live here so they're node:test-able without a real EventSource/DOM; the\n// thin `createPreviewSubscription` wiring is exercised with a fake\n// EventSource constructor in tests.\n//\n// TODO(juice SSE contract \u2014 reconcile when the sorb-juice agent lands the\n// real endpoint): assumed shape \u2014\n//\n// new EventSource(`${bridgeUrl}/orgs/${orgId}/preview/${previewId}/subscribe`)\n// (auth: EventSource can't set custom headers, so the bearer key is passed\n// as a `?key=` query param until an EventSource polyfill with header\n// support is adopted \u2014 flagged for reconciliation, not decided here)\n//\n// `message` event, `evt.data` = JSON:\n// { type: 'snapshot' | 'update', tokens: TokenSet } \u2014 apply tokens\n// { type: 'ping' } \u2014 keepalive, ignored\n//\n// Relay-spike precedent (experiments/sorb-bridge-modes/relay-spike/NOTES.md):\n// \"initial snapshot on subscribe + periodic ping\" is exactly this shape.\n\n/**\n * Build the subscribe URL for a hosted-relay preview.\n * @param {string} bridgeUrl\n * @param {string} orgId\n * @param {string} previewId\n * @param {string} [key] Bearer key, sent as `?key=` (see TODO above).\n * @returns {string}\n */\nexport const buildSubscribeUrl = (bridgeUrl, orgId, previewId, key) => {\n const base = String(bridgeUrl).replace(/\\/$/, '')\n const path = `${base}/orgs/${encodeURIComponent(orgId)}/preview/${encodeURIComponent(previewId)}/subscribe`\n if (typeof key === 'string' && key.trim() !== '') {\n return `${path}?key=${encodeURIComponent(key.trim())}`\n }\n return path\n}\n\n/**\n * Parse one SSE frame's `data` payload. Returns `null` for anything that\n * isn't a recognised, well-formed frame \u2014 callers should simply ignore it\n * (never throw on an unexpected/future frame shape).\n *\n * @param {string} raw\n * @returns {{ type: 'snapshot'|'update', tokens: import('./types').TokenSet } | { type: 'delete', tokens: null } | { type: 'ping' } | null}\n */\nexport const parsePreviewFrame = (raw) => {\n let frame\n try {\n frame = JSON.parse(raw)\n } catch (e) {\n void e\n return null\n }\n if (!frame || typeof frame !== 'object') return null\n if (frame.type === 'ping') return { type: 'ping' }\n // juice emits a delete frame (tokens:null) when a preview is removed/expires\n // server-side \u2014 the subscriber should revert to committed tokens.\n if (frame.type === 'delete') return { type: 'delete', tokens: null }\n if ((frame.type === 'snapshot' || frame.type === 'update') && frame.tokens && typeof frame.tokens === 'object') {\n return { type: frame.type, tokens: frame.tokens }\n }\n return null\n}\n\n/**\n * Open an SSE subscription and wire parsed token frames to `onTokens`.\n * Returns an unsubscribe function, or `null` if no usable EventSource\n * constructor was provided (caller should fall back to polling).\n *\n * @param {{\n * EventSourceImpl?: typeof EventSource,\n * url: string,\n * onTokens: (tokens: import('./types').TokenSet) => void,\n * onDelete?: () => void,\n * onError?: (evt: unknown) => void,\n * }} opts\n * @returns {(() => void) | null}\n */\nexport const createPreviewSubscription = ({ EventSourceImpl, url, onTokens, onDelete, onError }) => {\n if (typeof EventSourceImpl !== 'function') return null\n\n const es = new EventSourceImpl(url)\n\n es.onmessage = (evt) => {\n const parsed = parsePreviewFrame(evt && evt.data)\n if (!parsed || parsed.type === 'ping') return\n if (parsed.type === 'delete') {\n if (onDelete) onDelete()\n return\n }\n onTokens(parsed.tokens)\n }\n\n const handleError = (evt) => {\n if (onError) onError(evt)\n }\n if (typeof es.addEventListener === 'function') {\n es.addEventListener('error', handleError)\n } else {\n es.onerror = handleError\n }\n\n return () => {\n try {\n es.close()\n } catch (e) {\n void e\n }\n }\n}\n", "/**\n * Pure (no-DOM) preview-body classification \u2014 real-dark-mode phase 2 (spec\n * P2). The bridge's `/preview/:id` fetch response AND the SSE `onTokens`\n * push carry the SAME body shape, which is EITHER:\n *\n * - legacy flat map: `{ \"--token\": \"value\", ... }`\n * - mode-aware wrapper: `{ tokens: {...light}, darkTokens\uFF1F: {...dark},\n * darkMode\uFF1F: DarkModeConvention }`\n *\n * Kept separate from `TokenProvider.jsx` (which owns the DOM side-effects \u2014\n * `injectModeStylesheet`/`applyTokens`) so the detection + resolution logic\n * is unit-testable without a DOM stub.\n */\n\n/**\n * @param {unknown} body\n * @returns {boolean} true when `body` uses the mode-aware wrapper shape.\n */\nexport const isModeAwarePreviewBody = (body) =>\n !!body && typeof body === 'object' && !Array.isArray(body) && 'tokens' in body\n\n/**\n * @typedef {{ kind: 'flat', tokens: import('./types').TokenSet }} FlatPreviewResolution\n * @typedef {{\n * kind: 'mode-aware',\n * lightTokens: import('./types').TokenSet,\n * darkTokens: import('./types').TokenSet,\n * darkMode: import('@sorb/core').DarkModeConvention,\n * }} ModeAwarePreviewResolution\n */\n\n/**\n * Resolves a raw preview body into either a flat-apply instruction or a\n * mode-aware-inject instruction. Never touches the DOM.\n *\n * - Legacy flat body \u21D2 `{ kind: 'flat', tokens: body }` (byte-identical\n * back-compat path \u2014 the caller must still call the exact same\n * `applyTokens` it always has).\n * - Mode-aware body with NO `darkTokens` (absent/empty) \u21D2 still `'flat'`,\n * using `body.tokens` as the flat map (spec: \"treat body.tokens as the\n * flat map\").\n * - Mode-aware body WITH a non-empty `darkTokens` \u21D2 `'mode-aware'`, with\n * `darkMode` resolved from `body.darkMode`, falling back to\n * `fallbackDarkMode` (the active target's convention) when the bridge\n * didn't send one.\n *\n * @param {unknown} body\n * @param {import('@sorb/core').DarkModeConvention | undefined} fallbackDarkMode\n * @returns {FlatPreviewResolution | ModeAwarePreviewResolution}\n */\nexport const resolvePreviewBody = (body, fallbackDarkMode) => {\n if (!isModeAwarePreviewBody(body)) {\n return { kind: 'flat', tokens: /** @type {import('./types').TokenSet} */ (body) }\n }\n const wrapper = /** @type {{ tokens: import('./types').TokenSet, darkTokens?: import('./types').TokenSet, darkMode?: import('@sorb/core').DarkModeConvention }} */ (\n body\n )\n const darkTokens = wrapper.darkTokens\n if (darkTokens && Object.keys(darkTokens).length > 0) {\n return {\n kind: 'mode-aware',\n lightTokens: wrapper.tokens,\n darkTokens,\n darkMode: wrapper.darkMode ?? fallbackDarkMode,\n }\n }\n return { kind: 'flat', tokens: wrapper.tokens }\n}\n", "/**\n * Pure (no-DOM) resolution of what `setMode` (`TokenProvider.jsx`) should do\n * to the document for a given `darkMode` convention + requested mode \u2014 P2a\n * multi-framework `setMode` support. Kept separate from `TokenProvider.jsx`\n * (which owns the actual DOM writes) so the strategy dispatch is\n * unit-testable without a DOM stub or a React render harness.\n */\n\n/**\n * Derives the class name a `strategy: 'class'` convention's `darkSelector`\n * names (e.g. `'.dark'` \u2192 `'dark'`). Falls back to `'dark'` if the selector\n * isn't a bare single-class selector (defensive; every shipped convention\n * names one).\n * @param {import('@sorb/core').DarkModeConvention | undefined} darkModeConvention\n * @returns {string}\n */\nexport const darkClassName = (darkModeConvention) => {\n const selector = String(darkModeConvention?.darkSelector || '').trim()\n const match = /^\\.([a-zA-Z0-9_-]+)$/.exec(selector)\n return match ? match[1] : 'dark'\n}\n\n/**\n * @typedef {{ type: 'none' }} NoneAction\n * @typedef {{ type: 'attr-set', attribute: string, value: 'light'|'dark' }} AttrSetAction\n * @typedef {{ type: 'attr-remove', attribute: string }} AttrRemoveAction\n * @typedef {{ type: 'class-add', className: string }} ClassAddAction\n * @typedef {{ type: 'class-remove', className: string }} ClassRemoveAction\n */\n\n/**\n * Resolves the DOM action `setMode(next)` should perform for the given\n * convention, without touching the DOM.\n *\n * - `strategy: 'media'` \u21D2 `{ type: 'none' }` \u2014 pure OS, no manual override.\n * - `strategy: 'class'` \u21D2 `next === 'dark'` adds the class; `'light'` AND\n * `'auto'` both remove it (no separate \"light\" class in e.g. Tailwind's\n * convention).\n * - `strategy: 'attribute'` (default, incl. undefined convention) \u21D2\n * `next === 'auto'` removes the attribute (media governs); `'light'`/\n * `'dark'` set it.\n *\n * @param {import('@sorb/core').DarkModeConvention | undefined} darkModeConvention\n * @param {'auto'|'light'|'dark'} next\n * @returns {NoneAction | AttrSetAction | AttrRemoveAction | ClassAddAction | ClassRemoveAction}\n */\nexport const resolveModeAction = (darkModeConvention, next) => {\n const strategy = darkModeConvention?.strategy || 'attribute'\n\n if (strategy === 'media') {\n return { type: 'none' }\n }\n\n if (strategy === 'class') {\n const className = darkClassName(darkModeConvention)\n return next === 'dark' ? { type: 'class-add', className } : { type: 'class-remove', className }\n }\n\n const attribute = darkModeConvention?.attribute || 'data-bs-theme'\n return next === 'auto' ? { type: 'attr-remove', attribute } : { type: 'attr-set', attribute, value: next }\n}\n", "// @sorb/leaf-core \u2014 the framework-free injector (component-compat-roadmap P0).\n//\n// Everything `SorbProvider` (`TokenProvider.jsx`) does at runtime, minus\n// React: resolve the bridge connection, load committed/preview tokens, apply\n// them via the mode-aware `<style>` injector or the legacy inline\n// `applyTokens` path, and expose `setMode`/mode state through a tiny\n// pub-sub store. `sorbInit(config)` is the ONE entry a non-React host needs.\n//\n// This module is pure JS with no React import \u2014 that's the whole point (the\n// P0 acceptance test: a plain-HTML page can drive it with zero React in the\n// bundle). `TokenProvider.jsx` is now a thin wrapper that subscribes to the\n// instance this returns instead of re-implementing the logic below.\nimport { applyTokens, clearTokenOverrides, injectModeStylesheet, clearModeStylesheet } from './apply.js'\nimport { buildModeStylesheet } from './modeStylesheet.js'\nimport { reactBootstrapTarget } from './targets/reactBootstrap.js'\nimport { shouldLoadPreview } from './previewGuard.js'\nimport { checkPreviewVocabulary } from './previewVocab.js'\nimport { bridgeHeaders } from './bridgeAuth.js'\nimport { shouldResolveOrgConnection, getOrgKey, resolveOrgConnection, buildEffectiveConfig } from './connection.js'\nimport { buildSubscribeUrl, createPreviewSubscription } from './sse.js'\nimport { resolvePreviewBody } from './previewMode.js'\nimport { resolveModeAction } from './modeAction.js'\n\n// EventSource/matchMedia only exist in browsers (and some polyfilled envs) \u2014\n// never reference the bare global at module scope so this file stays\n// node:test-safe (identical guard to the one TokenProvider.jsx used).\nconst EventSourceCtor = typeof EventSource !== 'undefined' ? EventSource : null\nconst matchMediaFn = typeof matchMedia !== 'undefined' ? matchMedia : null\nconst DARK_MEDIA_QUERY = '(prefers-color-scheme: dark)'\n\n/**\n * Dev-only warning that never throws outside a Node-like env.\n * @param {string} msg\n * @returns {void}\n */\nconst devWarn = (msg) => {\n try {\n if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(`[sorb] ${msg}`)\n }\n } catch (e) {\n void e\n }\n}\n\n// Tracks which deprecated token ids have already been warned this session.\n// Single module-level set \u2014 shared by every `sorbInit` call (and, via\n// TokenProvider.jsx's re-export, every `SorbProvider` too) so a page mixing\n// both entry points still only warns once per token id.\nexport const warnedDeprecations = new Set()\n\nfunction warnDeprecated(resolved) {\n if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') return\n for (let i = 0; i < resolved.length; i++) {\n const token = resolved[i]\n if (!token.deprecated) continue\n if (warnedDeprecations.has(token.id)) continue\n warnedDeprecations.add(token.id)\n const replacedBy =\n token.replacedBy ||\n (token.$extensions && token.$extensions.sorb && token.$extensions.sorb.replacedBy) ||\n null\n if (replacedBy) {\n console.warn('[@sorb/leaf] Deprecated token: ' + token.id + ' \u2014 use ' + replacedBy + ' instead')\n } else {\n console.warn('[@sorb/leaf] Deprecated token: ' + token.id + ' is deprecated')\n }\n }\n}\n\n/**\n * @typedef {{\n * tokens: import('./types').TokenSet,\n * isPreview: boolean,\n * previewId: string|null,\n * previewMismatch: boolean,\n * mode: 'auto'|'light'|'dark',\n * resolvedScheme: 'light'|'dark',\n * }} SorbState\n *\n * @typedef {{\n * getState: () => SorbState,\n * subscribe: (listener: (state: SorbState) => void) => (() => void),\n * setMode: (next: 'auto'|'light'|'dark') => void,\n * clearPreview: () => void,\n * destroy: () => void,\n * }} SorbInstance\n */\n\n/**\n * Framework-free Sorb entry point. Resolves the connection, loads\n * committed/preview tokens onto `document.documentElement`, and returns a\n * small store (`getState`/`subscribe`) plus `setMode`/`clearPreview`. No\n * React, no JSX \u2014 safe to call from a plain `<script type=\"module\">`.\n *\n * Byte-identical DOM behavior to `SorbProvider`: same guard/vocab/mode-aware\n * injection logic, just driven by a manual pub-sub store instead of React\n * state.\n *\n * @param {import('./types').SorbConfig} config\n * @returns {SorbInstance}\n */\nexport function sorbInit(config) {\n let activeTokens = config.tokens\n let isPreview = false\n let previewId = null\n let previewMismatch = false\n let pollId = null\n let cancelled = false\n let unsubscribeSSE = null\n\n const hasDarkMode = !!(config.darkTokens && Object.keys(config.darkTokens).length > 0)\n const darkModeConvention = config.darkModeConvention || reactBootstrapTarget.darkMode\n\n let mode = 'auto'\n let systemScheme = matchMediaFn ? (matchMediaFn(DARK_MEDIA_QUERY).matches ? 'dark' : 'light') : 'light'\n\n const listeners = new Set()\n const getState = () => ({\n tokens: activeTokens,\n isPreview,\n previewId,\n previewMismatch,\n mode,\n resolvedScheme: mode === 'auto' ? systemScheme : mode,\n })\n const notify = () => {\n const state = getState()\n listeners.forEach((listener) => listener(state))\n }\n const subscribe = (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n }\n\n let mql = null\n const onSchemeChange = (e) => {\n systemScheme = e.matches ? 'dark' : 'light'\n notify()\n }\n if (matchMediaFn) {\n mql = matchMediaFn(DARK_MEDIA_QUERY)\n if (typeof mql.addEventListener === 'function') mql.addEventListener('change', onSchemeChange)\n else if (typeof mql.addListener === 'function') mql.addListener(onSchemeChange)\n }\n\n // Tracks the token map currently written as INLINE `--x` custom properties\n // (flat path) so switching TO the mode-aware `<style>` path can clear\n // those stale inline overrides first \u2014 same reasoning as TokenProvider.jsx.\n let inlineTokens = null\n\n const applyFlat = (tokens) => {\n clearModeStylesheet()\n applyTokens(tokens)\n inlineTokens = tokens\n }\n\n const applyModeAware = (lightTokens, darkTokens, convention) => {\n if (inlineTokens) {\n clearTokenOverrides(inlineTokens)\n inlineTokens = null\n }\n injectModeStylesheet(buildModeStylesheet(lightTokens, darkTokens, convention))\n }\n\n const loadCommitted = () => {\n if (hasDarkMode) {\n applyModeAware(config.tokens, config.darkTokens, darkModeConvention)\n } else {\n applyFlat(config.tokens)\n }\n activeTokens = config.tokens\n isPreview = false\n previewId = null\n previewMismatch = false\n notify()\n }\n\n const applyPreviewTokens = (body, id, effectiveConfig) => {\n const resolved = resolvePreviewBody(body, darkModeConvention)\n let flatTokens\n if (resolved.kind === 'mode-aware') {\n applyModeAware(resolved.lightTokens, resolved.darkTokens, resolved.darkMode)\n flatTokens = resolved.lightTokens\n } else {\n applyFlat(resolved.tokens)\n flatTokens = resolved.tokens\n }\n activeTokens = flatTokens\n isPreview = true\n previewId = id\n previewMismatch = checkPreviewVocabulary({\n tokens: flatTokens,\n expectPrefixes: effectiveConfig.preview?.expectPrefixes,\n previewId: id,\n })\n notify()\n }\n\n const loadPreview = async (id, effectiveConfig) => {\n const cfg = effectiveConfig || config\n const guard = shouldLoadPreview(cfg)\n if (!guard.allowed) {\n loadCommitted()\n return false\n }\n const origin = guard.origin\n try {\n const res = await fetch(`${origin}/preview/${id}`, {\n headers: bridgeHeaders(cfg.preview?.key),\n })\n if (!res.ok) throw new Error('preview not found')\n const tokens = await res.json()\n applyPreviewTokens(tokens, id, cfg)\n return true\n } catch (e) {\n // local server not running, preview expired, or network error \u2014\n // fall back silently, never break the page.\n void e\n loadCommitted()\n return false\n }\n }\n\n const clearPreview = () => {\n if (pollId) {\n clearInterval(pollId)\n pollId = null\n }\n if (typeof location !== 'undefined' && typeof history !== 'undefined') {\n const params = new URLSearchParams(location.search)\n params.delete('preview')\n const qs = params.toString()\n history.replaceState(null, '', qs ? `?${qs}` : location.pathname)\n }\n loadCommitted()\n }\n\n const setMode = (next) => {\n mode = next\n if (typeof document !== 'undefined') {\n const action = resolveModeAction(darkModeConvention, next)\n switch (action.type) {\n case 'attr-set':\n document.documentElement.setAttribute(action.attribute, action.value)\n break\n case 'attr-remove':\n document.documentElement.removeAttribute(action.attribute)\n break\n case 'class-add':\n document.documentElement.classList.add(action.className)\n break\n case 'class-remove':\n document.documentElement.classList.remove(action.className)\n break\n case 'none':\n default:\n break\n }\n }\n notify()\n }\n\n const destroy = () => {\n cancelled = true\n if (pollId) clearInterval(pollId)\n if (unsubscribeSSE) unsubscribeSSE()\n if (mql) {\n if (typeof mql.removeEventListener === 'function') mql.removeEventListener('change', onSchemeChange)\n else if (typeof mql.removeListener === 'function') mql.removeListener(onSchemeChange)\n }\n listeners.clear()\n }\n\n const init = async () => {\n if (config.resolved && config.resolved.length) warnDeprecated(config.resolved)\n\n let effectiveConfig = config\n let resolvedConnection = null\n if (shouldResolveOrgConnection(config)) {\n resolvedConnection = await resolveOrgConnection(getOrgKey(config), {\n cloudBase: config.cloudBase,\n })\n if (cancelled) return\n effectiveConfig = buildEffectiveConfig(config, resolvedConnection)\n }\n\n const guard = shouldLoadPreview(effectiveConfig)\n const id = typeof location !== 'undefined' ? new URLSearchParams(location.search).get('preview') : null\n\n if (!guard.allowed || !id) {\n if (id && !guard.allowed) {\n devWarn(\n `ignoring ?preview= \u2014 preview not permitted (${guard.reason ?? 'blocked'}); ` +\n 'loading committed tokens',\n )\n }\n loadCommitted()\n return\n }\n\n const ok = await loadPreview(id, effectiveConfig)\n if (!ok || cancelled) return\n\n const useSSE =\n resolvedConnection &&\n resolvedConnection.transport === 'sse' &&\n resolvedConnection.orgId &&\n EventSourceCtor\n\n if (useSSE) {\n const url = buildSubscribeUrl(\n resolvedConnection.bridgeUrl,\n resolvedConnection.orgId,\n id,\n effectiveConfig.preview?.key,\n )\n unsubscribeSSE = createPreviewSubscription({\n EventSourceImpl: EventSourceCtor,\n url,\n onTokens: (tokens) => applyPreviewTokens(tokens, id, effectiveConfig),\n onDelete: () => loadCommitted(),\n onError: () => devWarn('SSE preview subscription error \u2014 preview may be stale'),\n })\n }\n\n if (!unsubscribeSSE) {\n const interval = effectiveConfig.preview?.pollInterval ?? 1500\n pollId = setInterval(() => loadPreview(id, effectiveConfig), interval)\n }\n }\n\n init()\n\n return { getState, subscribe, setMode, clearPreview, destroy }\n}\n", "// Runtime shim for the Legacy-React adapter (roadmap \u00A76, Phase 2).\n//\n// A hardcoded literal in a legacy app (e.g. `background: #0F65EF`) does NOT\n// reference a CSS custom property, so `applyTokens` alone can never re-theme it.\n// This shim closes that gap NON-DESTRUCTIVELY: at render it finds elements whose\n// computed style for a mapped property equals a `raw` value in the legacyMap and\n// overrides that element's *inline* style to `var(--<cssVar>, <raw>)`.\n//\n// - non-destructive : no source edit; only inline style is set at runtime.\n// - reversible : `clearLegacyMap(handle)` restores the original inline value.\n// - live-re-themeable: the `var(--cssVar, raw)` re-resolves whenever the token\n// flips (via `applyTokens`), with `raw` as the fallback.\n//\n// The decision logic lives in the pure `computeLegacyOverride` so it can be\n// unit-tested without a real browser; the DOM walker is a thin wrapper.\n\n/**\n * Map a CSS property name (camelCase from JS style objects, or kebab-case from\n * computed style) to a canonical kebab-case form for comparison.\n * @param {string} prop\n * @returns {string}\n */\nexport const normalizeProp = (prop) => {\n if (typeof prop !== 'string') return ''\n return prop\n .trim()\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/_/g, '-')\n .toLowerCase()\n}\n\n/**\n * Canonicalize a color literal to its `rgb(r, g, b)` / `rgba(r, g, b, a)` form.\n * This is the key to matching an authored hex `raw` (`#0F65EF`) against the\n * *computed* value \u2014 browsers (and jsdom) always report computed colors as\n * `rgb()`/`rgba()`, never hex. Handles #rgb / #rrggbb / #rrggbbaa and existing\n * rgb()/rgba() (whitespace-collapsed). Returns null if it isn't a color literal.\n * @param {string} v lowercased, whitespace-collapsed value\n * @returns {string|null}\n */\nconst canonicalizeColor = (v) => {\n // #rgb, #rrggbb, #rrggbbaa (and #rgba)\n const hex = v.match(/^#([0-9a-f]{3,8})$/)\n if (hex) {\n let h = hex[1]\n if (h.length === 3 || h.length === 4) {\n h = h.split('').map((c) => c + c).join('')\n }\n if (h.length !== 6 && h.length !== 8) return null\n const r = parseInt(h.slice(0, 2), 16)\n const g = parseInt(h.slice(2, 4), 16)\n const b = parseInt(h.slice(4, 6), 16)\n if (h.length === 8) {\n const a = parseInt(h.slice(6, 8), 16) / 255\n // round alpha to 3 dp, strip trailing zeros, to match rgba() printing\n const as = String(Math.round(a * 1000) / 1000)\n return `rgba(${r}, ${g}, ${b}, ${as})`\n }\n return `rgb(${r}, ${g}, ${b})`\n }\n // existing rgb()/rgba() \u2192 normalize spacing/commas\n const fn = v.match(/^(rgba?)\\(([^)]*)\\)$/)\n if (fn) {\n const parts = fn[2].split(',').map((p) => p.trim()).filter((p) => p !== '')\n if (parts.length === 3) return `rgb(${parts[0]}, ${parts[1]}, ${parts[2]})`\n if (parts.length === 4) return `rgba(${parts[0]}, ${parts[1]}, ${parts[2]}, ${parts[3]})`\n }\n return null\n}\n\n/**\n * Normalize a style *value* so an authored literal (`\"#0F65EF\"`, `\"4\"`, `\"4px\"`)\n * compares equal to its computed-style form. Trims, lowercases, collapses\n * whitespace, canonicalizes colors to `rgb()/rgba()` (so hex `raw` matches the\n * computed `rgb()`), and treats a bare unitless number as its `px` form (covers\n * `borderRadius: 4` \u2192 `\"4px\"`).\n * @param {string|number} value\n * @returns {string}\n */\nexport const normalizeValue = (value) => {\n if (value == null) return ''\n let v = String(value).trim().toLowerCase()\n if (v === '') return ''\n\n // collapse internal whitespace (e.g. \"rgb( 15 , 101 , 239 )\")\n v = v.replace(/\\s+/g, ' ')\n\n // colors \u2192 canonical rgb()/rgba() so hex and rgb compare equal\n const color = canonicalizeColor(v)\n if (color) return color\n\n // bare unitless number \u2192 px (React style numbers, `borderRadius: 4`)\n if (/^-?\\d*\\.?\\d+$/.test(v)) v = `${v}px`\n\n return v\n}\n\n/**\n * @typedef {import('./types').LegacyMapRow} LegacyMapRow\n */\n\n/**\n * Index a legacyMap into a `prop \u2192 [{ normValue, cssVar, raw }]` lookup so the\n * decision function is O(1)-per-prop instead of scanning the whole array.\n * @param {LegacyMapRow[]} legacyMap\n * @returns {Map<string, Array<{ normValue: string, cssVar: string, raw: string }>>}\n */\nexport const indexLegacyMap = (legacyMap) => {\n /** @type {Map<string, Array<{ normValue: string, cssVar: string, raw: string }>>} */\n const idx = new Map()\n if (!Array.isArray(legacyMap)) return idx\n for (const row of legacyMap) {\n if (!row || row.cssVar == null || row.raw == null || row.prop == null) continue\n const p = normalizeProp(row.prop)\n const entry = {\n normValue: normalizeValue(row.raw),\n cssVar: String(row.cssVar).replace(/^--/, ''),\n raw: String(row.raw),\n }\n const list = idx.get(p)\n if (list) list.push(entry)\n else idx.set(p, [entry])\n }\n return idx\n}\n\n/**\n * PURE decision logic. Given a property, the element's *computed* value for that\n * property, and the legacyMap (array or pre-built index), return the override\n * string `var(--<cssVar>, <raw>)` when the value matches a mapped `raw`, else\n * null. This is the unit-tested core of the shim.\n *\n * @param {string} prop CSS property (camelCase or kebab-case)\n * @param {string|number} computedValue the element's computed value for `prop`\n * @param {LegacyMapRow[]|Map<string, any[]>} legacyMap rows, or an index from `indexLegacyMap`\n * @returns {string|null}\n */\nexport const computeLegacyOverride = (prop, computedValue, legacyMap) => {\n const idx = legacyMap instanceof Map ? legacyMap : indexLegacyMap(legacyMap)\n const list = idx.get(normalizeProp(prop))\n if (!list || list.length === 0) return null\n const target = normalizeValue(computedValue)\n if (target === '') return null\n for (const entry of list) {\n if (entry.normValue === target) {\n return `var(--${entry.cssVar}, ${entry.raw})`\n }\n }\n return null\n}\n\nexport {}\n", "// DOM-applying wrapper for the legacy-map shim. Thin by design: all matching\n// decisions defer to `computeLegacyOverride` (pure, in legacyMap.js); this file\n// only walks the tree, reads computed style, and writes/restores inline styles.\n\nimport { computeLegacyOverride, indexLegacyMap, normalizeProp } from './legacyMap.js'\n\n/**\n * @typedef {import('./types').LegacyMapRow} LegacyMapRow\n * @typedef {import('./types').LegacyMapHandle} LegacyMapHandle\n */\n\n/**\n * Walk `root` (and its descendants), and for every element whose computed value\n * for a mapped property equals a `raw` in the legacyMap, override that element's\n * INLINE style for that property to `var(--<cssVar>, <raw>)`. Returns a handle\n * that `clearLegacyMap` uses to restore the original inline values.\n *\n * Non-destructive: only inline `element.style[prop]` is touched, and the prior\n * inline value (often empty) is captured so it can be restored exactly.\n *\n * @param {Element|Document|null} [root=document.body] subtree to remap\n * @param {LegacyMapRow[]} legacyMap the report's `auto` rows\n * @returns {LegacyMapHandle}\n */\nexport const applyLegacyMap = (root, legacyMap) => {\n /** @type {Array<{ el: HTMLElement, prop: string, prev: string }>} */\n const restores = []\n const handle = { restores }\n\n if (typeof document === 'undefined') return handle\n const start = root ?? document.body\n if (!start || !Array.isArray(legacyMap) || legacyMap.length === 0) return handle\n\n const idx = indexLegacyMap(legacyMap)\n if (idx.size === 0) return handle\n\n // Properties we care about, kebab-cased \u2014 used both to read computed style and\n // to write inline style (kebab works with CSSStyleDeclaration.setProperty).\n const props = Array.from(idx.keys())\n\n const getView = () => {\n const doc = start.ownerDocument || (start.nodeType === 9 ? start : document)\n return (doc.defaultView || (typeof window !== 'undefined' ? window : null))\n }\n const view = getView()\n if (!view || typeof view.getComputedStyle !== 'function') return handle\n\n /** @param {Element} el */\n const visit = (el) => {\n if (!el || el.nodeType !== 1) return\n const cs = view.getComputedStyle(el)\n for (const prop of props) {\n const computed = cs.getPropertyValue(prop)\n const override = computeLegacyOverride(prop, computed, idx)\n if (override == null) continue\n // capture prior inline value (kebab-safe) so restore is exact\n const prev = el.style.getPropertyValue(prop)\n restores.push({ el: /** @type {HTMLElement} */ (el), prop, prev })\n el.style.setProperty(prop, override)\n }\n }\n\n // include `start` itself if it's an element, plus all descendant elements\n if (start.nodeType === 1) visit(/** @type {Element} */ (start))\n const all = start.querySelectorAll ? start.querySelectorAll('*') : []\n for (const el of all) visit(el)\n\n return handle\n}\n\n/**\n * Restore every inline style override recorded by `applyLegacyMap`, returning\n * each element to its original (usually empty) inline value.\n * @param {LegacyMapHandle|null} handle\n * @returns {void}\n */\nexport const clearLegacyMap = (handle) => {\n if (!handle || !Array.isArray(handle.restores)) return\n for (const { el, prop, prev } of handle.restores) {\n if (!el || !el.style) continue\n if (prev === '' || prev == null) el.style.removeProperty(prop)\n else el.style.setProperty(prop, prev)\n }\n handle.restores = []\n}\n\nexport { normalizeProp }\n", "import React from 'react'\nimport { usePreviewState } from './hooks'\n\n/**\n * Drop-in banner that appears at the bottom of the screen when a\n * Sorb preview is active. Includes an \"Exit preview\" button.\n *\n * Only renders when preview.enabled is true AND a preview is loaded.\n * Safe to include unconditionally \u2014 renders nothing in production.\n *\n * @example\n * // In your app root, after <SorbProvider>\n * <PreviewBanner />\n */\nexport const PreviewBanner = () => {\n const { isPreview, previewId, previewMismatch, clearPreview } = usePreviewState()\n if (!isPreview) return null\n\n // B4: on a vocabulary mismatch the preview is active but likely re-skins\n // nothing \u2014 warn the viewer instead of showing a normal \"live\" banner. The\n // warning colours are token-bindable (`--sorb-preview-warning-*`) with amber\n // fallbacks so a consumer can theme them (e.g. to its own --bs-warning).\n const background = previewMismatch\n ? 'var(--sorb-preview-warning-bg, #B54708)'\n : '#3B5BDB'\n const accent = previewMismatch\n ? 'var(--sorb-preview-warning-accent, #F59E0B)'\n : 'transparent'\n\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n style={{\n position: 'fixed',\n bottom: 0,\n left: 0,\n right: 0,\n background,\n borderTop: `3px solid ${accent}`,\n color: '#fff',\n padding: '10px 20px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '12px',\n fontSize: '13px',\n lineHeight: '1.4',\n zIndex: 99999,\n fontFamily:\n 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n boxShadow: '0 -2px 12px rgba(0,0,0,0.15)',\n }}\n >\n <span>\n <strong style={{ fontWeight: 600 }}>\n {previewMismatch ? 'Sorb preview active \u2014 may not re-skin' : 'Sorb preview active'}\n </strong>\n {previewId && (\n <code\n style={{\n marginLeft: '8px',\n opacity: 0.75,\n fontSize: '11px',\n background: 'rgba(255,255,255,0.15)',\n padding: '2px 6px',\n borderRadius: '4px',\n }}\n >\n {previewId}\n </code>\n )}\n <span style={{ marginLeft: '8px', opacity: 0.75, fontSize: '12px' }}>\n {previewMismatch\n ? 'No matching tokens for this app \u2014 colours may be unchanged'\n : 'Token changes from Figma are live'}\n </span>\n </span>\n <button\n onClick={clearPreview}\n style={{\n flexShrink: 0,\n background: 'rgba(255,255,255,0.2)',\n border: '1px solid rgba(255,255,255,0.3)',\n color: '#fff',\n padding: '5px 14px',\n borderRadius: '6px',\n cursor: 'pointer',\n fontSize: '12px',\n fontWeight: 500,\n transition: 'background 0.15s',\n }}\n onMouseEnter={(e) =>\n (e.target.style.background = 'rgba(255,255,255,0.3)')\n }\n onMouseLeave={(e) =>\n (e.target.style.background = 'rgba(255,255,255,0.2)')\n }\n >\n Exit preview\n </button>\n </div>\n )\n}\n", "import { useTokenContext } from './context'\n\n/**\n * Returns the full active token set (committed or preview).\n * @returns {import('./types').TokenSet}\n */\nexport const useTokens = () => {\n return useTokenContext().tokens\n}\n\n/**\n * Returns a single token value by key.\n *\n * @param {string} key\n * @returns {string}\n * @example\n * const primary = useToken('color-primary') // \u2192 '#3B5BDB'\n */\nexport const useToken = (key) => {\n const tokens = useTokenContext().tokens\n const value = tokens[key]\n if (value === undefined && process.env.NODE_ENV === 'development') {\n console.warn(`[Sorb] Token not found: \"${key}\"`)\n }\n return String(value ?? '')\n}\n\n/**\n * Returns whether a preview token set is currently active.\n * Useful for showing a preview indicator in your app.\n * @returns {boolean}\n */\nexport const useIsPreview = () => {\n return useTokenContext().isPreview\n}\n\n/**\n * Returns full preview state \u2014 useful for building a preview banner.\n *\n * `previewMismatch` is true when a preview loaded but its tokens don't match the\n * app's `preview.expectPrefixes` (vocabulary mismatch \u2014 see B4); use it to render\n * a warning state. Always false unless the guard is opted into.\n *\n * @example\n * const { isPreview, previewId, previewMismatch, clearPreview } = usePreviewState()\n */\nexport const usePreviewState = () => {\n const { isPreview, previewId, previewMismatch, clearPreview } = useTokenContext()\n return { isPreview, previewId, previewMismatch, clearPreview }\n}\n\n/**\n * Real-dark-mode (spec D3): the manual mode selection + the live-resolved\n * scheme actually in effect.\n *\n * `mode` is meaningful for every app; `setMode('light'|'dark')` always\n * works. It only visibly changes anything once the consumer's `SorbConfig`\n * carries a `darkTokens` set (otherwise there's no dark stylesheet for the\n * attribute toggle to select).\n *\n * @returns {{ mode: 'auto'|'light'|'dark', setMode: (mode: 'auto'|'light'|'dark') => void, resolvedScheme: 'light'|'dark' }}\n * @example\n * const { mode, setMode, resolvedScheme } = useTheme()\n */\nexport const useTheme = () => {\n const { mode, setMode, resolvedScheme } = useTokenContext()\n return { mode, setMode, resolvedScheme }\n}\n", "import React from 'react'\nimport { useTheme } from './hooks'\n\nconst OPTIONS = [\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n { value: 'auto', label: 'Auto' },\n]\n\n/**\n * Drop-in Light / Dark / Auto mode toggle (real-dark-mode spec D3).\n *\n * Purely a thin `useTheme()` view \u2014 three buttons that call `setMode`, with\n * the active one highlighted. Renders unconditionally (safe even in a\n * single-mode app, where `setMode` still works but has nothing to visibly\n * toggle since there's no injected dark stylesheet).\n *\n * Unstyled beyond minimal inline layout \u2014 bring your own CSS/className to\n * match your app, same philosophy as `PreviewBanner`.\n *\n * @param {{ className?: string }} [props]\n * @example\n * // In your app root, alongside <PreviewBanner>\n * <ThemeToggle />\n */\nexport const ThemeToggle = ({ className } = {}) => {\n const { mode, setMode } = useTheme()\n\n return (\n <div\n role=\"radiogroup\"\n aria-label=\"Color mode\"\n className={className}\n style={{\n display: 'inline-flex',\n gap: '4px',\n fontFamily:\n 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n fontSize: '13px',\n }}\n >\n {OPTIONS.map(({ value, label }) => {\n const active = mode === value\n return (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n onClick={() => setMode(value)}\n style={{\n padding: '4px 10px',\n borderRadius: '6px',\n border: '1px solid rgba(0,0,0,0.15)',\n background: active ? 'var(--sorb-theme-toggle-active-bg, #3B5BDB)' : 'transparent',\n color: active ? '#fff' : 'inherit',\n cursor: 'pointer',\n fontWeight: active ? 600 : 400,\n }}\n >\n {label}\n </button>\n )\n })}\n </div>\n )\n}\n", "// verify.js \u2014 RUNNING-APP token verification (e2e-fix W2).\n//\n// Reports the values the running app ACTUALLY resolved for a set of tokens (read\n// off `:root` \u2014 where SorbProvider's applyTokens wrote the committed/preview\n// values) to the bridge's `POST /verify/app`, which diffs them against the\n// committed resolved map. This is what makes \"verify-before-merge in your running\n// app\" true in code: it asserts the live DOM resolves to the bound token values,\n// not Figma-side geometry.\n//\n// SSR-safe: no DOM \u2192 returns a clear `{ ok:false, reason:'no-dom' }` rather than\n// throwing (safe to call from a server-rendered component's effect). `fetch` is\n// injectable for tests.\n\nimport { bridgeHeaders } from './bridgeAuth.js'\n\n/** Normalize a token name to a `--cssVar`. */\nconst toCssVar = (name) => {\n const s = String(name).trim()\n return s.startsWith('--') ? s : `--${s}`\n}\n\n/**\n * Read each token's resolved value off `:root` and ask the bridge whether the\n * running app matches the committed resolved map.\n *\n * Precondition: call from inside a mounted `<SorbProvider>` \u2014 it applies the\n * resolved token literals onto `:root`. Without it, custom props read back as\n * `var(...)` refs (outputReferences css) and the result is `{ ok:false,\n * reason:'provider-not-applied' }` rather than a misleading mismatch.\n *\n * @param {string[]} tokens Token names or `--cssVar`s to check (e.g. `'button-primary-bg-default'`).\n * @param {{ origin?: string, key?: string, fetch?: typeof globalThis.fetch }} [opts]\n * `key` is the hosted-bridge bearer key (`config.preview.key`). Omit for the\n * no-auth localhost bridge \u2014 no `Authorization` header is then sent.\n * @returns {Promise<{ok:boolean, reason?:string, checked?:number, matched?:number, mismatches?:Array<{cssVar:string,expected:any,got:any}>, unknown?:string[], error?:string}>}\n */\nexport const verifyResolved = async (tokens, { origin = 'http://localhost:7777', key, fetch: fetchImpl } = {}) => {\n if (typeof document === 'undefined' || !document.documentElement) {\n return { ok: false, reason: 'no-dom' }\n }\n if (!Array.isArray(tokens) || tokens.length === 0) {\n return { ok: false, reason: 'no-tokens' }\n }\n const cs = getComputedStyle(document.documentElement)\n /** @type {Record<string,string>} */\n const values = {}\n for (const t of tokens) {\n const cssVar = toCssVar(t)\n values[cssVar] = cs.getPropertyValue(cssVar).trim()\n }\n // Precondition: SorbProvider must have applied the resolved literals onto :root.\n // `variables.css` is built with outputReferences, so an un-applied custom prop\n // reads back as a `var(--\u2026)` reference, not a value \u2014 verifying that is\n // meaningless. Detect it and say so plainly instead of reporting false mismatches.\n const unapplied = Object.entries(values)\n .filter(([, v]) => v.startsWith('var('))\n .map(([k]) => k)\n if (unapplied.length) return { ok: false, reason: 'provider-not-applied', unapplied }\n const f = fetchImpl || (typeof fetch !== 'undefined' ? fetch : globalThis.fetch)\n if (typeof f !== 'function') return { ok: false, reason: 'no-fetch' }\n const base = String(origin).replace(/\\/+$/, '')\n try {\n const res = await f(`${base}/verify/app`, {\n method: 'POST',\n // Hosted bridge needs the bearer key; localhost (no key) sends no header.\n headers: bridgeHeaders(key, { 'Content-Type': 'application/json' }),\n body: JSON.stringify({ values }),\n })\n if (!res.ok) {\n let detail = ''\n try {\n const b = await res.json()\n detail = b && b.error ? b.error : ''\n } catch (e) {\n void e\n }\n return { ok: false, reason: 'bridge-error', error: `${res.status}${detail ? ` \u2014 ${detail}` : ''}` }\n }\n return await res.json()\n } catch (e) {\n // Bridge not running / network error \u2014 never throw into the app.\n return { ok: false, reason: 'bridge-unreachable', error: e && e.message }\n }\n}\n", "/**\n * Reference `darkMode` conventions (real-dark-mode spec P2a) for\n * TargetAdapters beyond `react-bootstrap`. The connectors roadmap builds the\n * full adapters (Tailwind, a generic `data-theme` host, \u2026) later \u2014 this file\n * only defines the *convention* shape so `buildModeStylesheet`\n * (`modeStylesheet.js`) and `SorbProvider`'s `setMode` (`TokenProvider.jsx`)\n * already know how to drive them once those adapters land and pass one of\n * these (or an equivalent) as `config.darkModeConvention` /\n * `TargetAdapter.darkMode`.\n *\n * Not wired into the `@sorb/core` connector registry \u2014 these are plain data,\n * exported for adapters to import/spread, not registered TargetAdapters\n * themselves (this repo owns react-bootstrap's registration only).\n */\n\n/**\n * Tailwind's `darkMode: 'class'` convention \u2014 a `.dark` class toggled on\n * `documentElement` (typically `<html>`). Tailwind has no canonical \"light\"\n * class (light is just the absence of `.dark`), so `lightSelector` is\n * omitted: a manual \"light\" choice cannot out-rank an OS dark preference\n * under this convention (see `modeAction.js`'s `resolveModeAction`) \u2014 a\n * known limitation of class-only theming without a light marker.\n *\n * @type {import('@sorb/core').DarkModeConvention}\n */\nexport const tailwindDarkMode = {\n strategy: 'class',\n darkSelector: '.dark',\n}\n\n/**\n * A generic `[data-theme=\"...\"]` attribute convention \u2014 the same shape as\n * `react-bootstrap`'s `data-bs-theme` but under the more common\n * `data-theme` attribute name, for hosts that don't use Bootstrap's specific\n * convention.\n *\n * @type {import('@sorb/core').DarkModeConvention}\n */\nexport const dataThemeDarkMode = {\n strategy: 'attribute',\n attribute: 'data-theme',\n darkSelector: '[data-theme=\"dark\"]',\n lightSelector: '[data-theme=\"light\"]',\n}\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/TokenProvider.jsx", "../src/context.js", "../src/sanitize.js", "../src/apply.js", "../src/modeStylesheet.js", "../node_modules/@sorb/core/src/index.js", "../src/targets/reactBootstrap.js", "../src/previewGuard.js", "../src/previewVocab.js", "../src/bridgeAuth.js", "../src/connection.js", "../src/sse.js", "../src/previewMode.js", "../src/modeAction.js", "../src/core.js", "../src/legacyMap.js", "../src/legacyDom.js", "../src/PreviewBanner.jsx", "../src/hooks.js", "../src/ThemeToggle.jsx", "../src/verify.js", "../src/darkModeConventions.js", "../src/targets/mantine.js", "../src/targets/tailwindV4.js", "../src/targets/shadcn.js", "../src/targets/primevue.js", "../src/targets/mui.js", "../src/targets/angularMaterial.js"],
4
+ "sourcesContent": ["import React, { useCallback, useEffect, useMemo, useRef } from 'react'\nimport { TokenContext } from './context'\nimport { sorbInit, warnedDeprecations } from './core'\nimport { applyLegacyMap, clearLegacyMap } from './legacyDom'\n\n// Re-exported for back-compat \u2014 `warnedDeprecations` isn't part of the\n// public `@sorb/leaf` surface (not in `src/index.js`) but lived on this\n// module before the P0 leaf-core extraction moved the dedupe `Set` itself\n// into `./core.js`. Kept here so any existing deep import\n// (`sorb-leaf/src/TokenProvider`) still resolves the same object identity.\nexport { warnedDeprecations }\n\n// matchMedia only exists in browsers \u2014 same node:test-safety concern\n// `./core.js` guards against; used here only to seed the FIRST render's\n// `resolvedScheme` (a read, no DOM mutation) so it's correct before the\n// mount effect below has run, matching the pre-extraction component.\nconst matchMediaFn = typeof matchMedia !== 'undefined' ? matchMedia : null\nconst DARK_MEDIA_QUERY = '(prefers-color-scheme: dark)'\n\n/**\n * `SorbProvider` \u2014 the React shell over `sorbInit` (`./core.js`, the\n * framework-free injector; component-compat-roadmap P0). ALL runtime logic\n * (connection resolution, committed/preview loading, mode-aware injection,\n * SSE/poll, dark-mode state) now lives in `sorbInit`; this component's only\n * job is to bridge that instance's pub-sub store into React state and\n * expose the same `TokenContext` shape as before \u2014 non-breaking, byte-\n * identical behavior to the pre-extraction implementation. `sorbInit` is\n * created in the mount `useEffect` (not during render) so timing \u2014 and\n * StrictMode double-invoke safety \u2014 matches the original implementation,\n * which did all its DOM work in a mount-only effect too.\n *\n * The optional `legacyMap` (Legacy-React adapter, roadmap \u00A76) is an ADDITIVE,\n * non-destructive DOM overlay layered on top of the shell \u2014 it never touches\n * `sorbInit`. When present, after tokens apply it remaps any element whose\n * hardcoded literal matches a row's `raw` to `var(--<cssVar>, <raw>)`, and\n * restores the originals on unmount.\n *\n * @param {{\n * config: import('./types').SorbConfig,\n * legacyMap?: import('./types').LegacyMapRow[],\n * children: React.ReactNode,\n * }} props\n */\nexport const SorbProvider = ({ config, legacyMap, children }) => {\n const instanceRef = useRef(null)\n const legacyHandleRef = useRef(null)\n const [state, setState] = React.useState(() => ({\n tokens: config.tokens,\n isPreview: false,\n previewId: null,\n previewMismatch: false,\n mode: 'auto',\n resolvedScheme: matchMediaFn ? (matchMediaFn(DARK_MEDIA_QUERY).matches ? 'dark' : 'light') : 'light',\n }))\n\n // legacyMap prop wins over config.legacyMap; either enables the shim.\n const resolvedLegacyMap = legacyMap ?? config.legacyMap ?? null\n\n useEffect(() => {\n const instance = sorbInit(config)\n instanceRef.current = instance\n setState(instance.getState())\n const unsubscribe = instance.subscribe(setState)\n return () => {\n unsubscribe()\n instance.destroy()\n instanceRef.current = null\n }\n // Intentionally empty \u2014 only runs on mount, mirroring the original\n // component's contract (a changed `config` prop identity does not\n // reinitialize the connection).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // \u2500\u2500\u2500 legacy-map shim (roadmap \u00A76) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Additive overlay on top of the sorbInit shell: after tokens are applied\n // (and on every token change, so previews remap too), walk the DOM and remap\n // any hardcoded literal that matches a legacyMap row to `var(--cssVar, raw)`.\n // Restore on cleanup so removing the provider \u2014 or unmounting \u2014 returns the\n // original inline values.\n useEffect(() => {\n if (!resolvedLegacyMap || resolvedLegacyMap.length === 0) return undefined\n if (typeof document === 'undefined') return undefined\n // restore any prior overrides before re-applying against the new tokens\n if (legacyHandleRef.current) clearLegacyMap(legacyHandleRef.current)\n legacyHandleRef.current = applyLegacyMap(document.body, resolvedLegacyMap)\n return () => {\n if (legacyHandleRef.current) {\n clearLegacyMap(legacyHandleRef.current)\n legacyHandleRef.current = null\n }\n }\n }, [resolvedLegacyMap, state.tokens])\n\n const setMode = useCallback((next) => {\n if (instanceRef.current) instanceRef.current.setMode(next)\n }, [])\n const clearPreview = useCallback(() => {\n if (instanceRef.current) instanceRef.current.clearPreview()\n }, [])\n\n const value = useMemo(\n () => ({\n tokens: state.tokens,\n isPreview: state.isPreview,\n previewId: state.previewId,\n previewMismatch: state.previewMismatch,\n clearPreview,\n mode: state.mode,\n setMode,\n resolvedScheme: state.resolvedScheme,\n }),\n [state, clearPreview, setMode],\n )\n\n return <TokenContext.Provider value={value}>{children}</TokenContext.Provider>\n}\n", "import { createContext, useContext } from 'react'\n\n/** @type {import('react').Context<import('./types').TokenContextValue | null>} */\nexport const TokenContext = createContext(null)\n\n/** @returns {import('./types').TokenContextValue} */\nexport const useTokenContext = () => {\n const ctx = useContext(TokenContext)\n if (!ctx) {\n throw new Error('Sorb hooks must be used inside <SorbProvider>')\n }\n return ctx\n}\n", "/**\n * CSS token-value sanitizer \u2014 the C1 injection-boundary guard.\n *\n * Token values flow Figma \u2192 bridge \u2192 `applyTokens` \u2192 `setProperty`. Those values\n * are UNTRUSTED INPUT crossing a trust boundary. This is a pure string function\n * (no DOM) so it is fully node:test-able and reusable. Phase 2 will hoist it to\n * `@sorb/core`; do NOT add a DOM dependency here.\n *\n * Strategy: deny-by-default on the dangerous classes, then allowlist CSS\n * functions. A *valid* hostile value (a real `url(...)`) passes `setProperty`\n * unharmed, so we cannot rely on the browser \u2014 we reject it here.\n */\n\n/**\n * The only CSS functions we permit inside a token value. Anything else \u2014\n * `url(`, `image(`, `image-set(`, `-webkit-image-set(`, `cross-fade(`,\n * `expression(`, `paint(`, `element(`, `attr(`, \u2026 \u2014 is rejected.\n * @type {Set<string>}\n */\nconst ALLOWED_FUNCTIONS = new Set([\n 'rgb',\n 'rgba',\n 'hsl',\n 'hsla',\n 'hwb',\n 'lab',\n 'lch',\n 'oklab',\n 'oklch',\n 'color',\n 'calc',\n 'min',\n 'max',\n 'clamp',\n 'var',\n 'env',\n])\n\n// Matches an identifier immediately followed by '(' \u2014 i.e. a CSS function call.\n// Identifiers may start with one or two leading hyphens (vendor prefixes like\n// `-webkit-image-set`). The lookahead keeps the '(' out of the captured name.\nconst FUNCTION_CALL = /([a-zA-Z_-][\\w-]*)\\s*\\(/g\n\n// ASCII control chars (incl. NUL, newlines, tabs) \u2014 never legitimate in a\n// token value and a classic way to smuggle past naive filters.\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHARS = /[\\x00-\\x1f]/\n\n// CSS-context-break characters that let a value escape the custom-property\n// declaration: `;` ends the declaration, `{` / `}` open/close a block.\nconst CONTEXT_BREAK = /[{};]/\n\n/**\n * Validate an untrusted CSS token value before it is injected via\n * `setProperty`. Pure \u2014 does not touch the DOM.\n *\n * Rules (deny-by-default):\n * - non-string / empty input is rejected.\n * - reject ASCII control chars `\\x00-\\x1f`.\n * - reject the context-break chars `{` `}` `;`.\n * - reject (case-insensitive, whitespace-tolerant) `@import`, `javascript:`,\n * and the markup-break `</`.\n * - extract every `identifier(` and reject if ANY is not in the allowlist\n * (this is what stops `url(`, `image-set(`, `expression(`, `paint(`, \u2026).\n *\n * @param {unknown} value\n * @returns {{ ok: boolean, value: string, reason?: string }}\n */\nexport const sanitizeCssValue = (value) => {\n if (typeof value !== 'string') {\n return { ok: false, value: '', reason: 'not-a-string' }\n }\n\n const raw = value\n if (raw.length === 0) {\n return { ok: false, value: '', reason: 'empty' }\n }\n\n if (CONTROL_CHARS.test(raw)) {\n return { ok: false, value: raw, reason: 'control-char' }\n }\n\n if (CONTEXT_BREAK.test(raw)) {\n return { ok: false, value: raw, reason: 'context-break-char' }\n }\n\n // Case-insensitive, whitespace-tolerant dangerous tokens. We strip ASCII\n // whitespace before substring-matching so `@ import`, `java script:`,\n // `< /script` style evasions are still caught.\n const lower = raw.toLowerCase()\n const collapsed = lower.replace(/\\s+/g, '')\n if (collapsed.includes('@import')) {\n return { ok: false, value: raw, reason: 'at-import' }\n }\n if (collapsed.includes('javascript:')) {\n return { ok: false, value: raw, reason: 'javascript-scheme' }\n }\n if (collapsed.includes('</')) {\n return { ok: false, value: raw, reason: 'markup-break' }\n }\n\n // Allowlist every function call in the value.\n FUNCTION_CALL.lastIndex = 0\n let match\n while ((match = FUNCTION_CALL.exec(raw)) !== null) {\n const name = match[1].toLowerCase()\n if (!ALLOWED_FUNCTIONS.has(name)) {\n return { ok: false, value: raw, reason: `disallowed-function:${name}` }\n }\n }\n\n return { ok: true, value: raw }\n}\n", "import { sanitizeCssValue } from './sanitize.js'\n\n/**\n * Dev-only warning that never throws in a browser (no `process` global there).\n * Silent in production so a hostile token can't spam a shipped app's console.\n *\n * @param {string} key\n * @param {string} [reason]\n * @returns {void}\n */\nconst warnRejected = (key, reason) => {\n try {\n if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(\n `[sorb] skipped token \"--${key}\": value failed CSS sanitization` +\n (reason ? ` (${reason})` : ''),\n )\n }\n } catch (e) {\n // never let logging break token application\n void e\n }\n}\n\n/**\n * Writes all token values as CSS custom properties on :root.\n * Applies globally \u2014 affects the entire app.\n *\n * Each value is validated by {@link sanitizeCssValue} at this injection\n * boundary (concern C1). A value that fails sanitization is SKIPPED (fail\n * safe) \u2014 it is never written \u2014 and the remaining tokens still apply.\n *\n * @param {import('./types').TokenSet} tokens\n * @returns {void}\n */\nexport const applyTokens = (tokens) => {\n const root = document.documentElement\n Object.entries(tokens).forEach(([key, value]) => {\n const result = sanitizeCssValue(String(value))\n if (!result.ok) {\n warnRejected(key, result.reason)\n return\n }\n root.style.setProperty(`--${key}`, result.value)\n })\n}\n\n/**\n * Removes token CSS custom properties from :root.\n * Called when clearing a preview to restore the committed set.\n *\n * @param {import('./types').TokenSet} tokens\n * @returns {void}\n */\nexport const clearTokenOverrides = (tokens) => {\n const root = document.documentElement\n Object.keys(tokens).forEach((key) => {\n root.style.removeProperty(`--${key}`)\n })\n}\n\n/** The id of the `<style>` tag {@link injectModeStylesheet} upserts. */\nexport const MODE_STYLESHEET_ID = 'sorb-tokens'\n\n/**\n * Upserts a `<style id=\"sorb-tokens\">` tag in `<head>` carrying mode-aware\n * CSS (real-dark-mode spec D3) \u2014 the injection path used when a theme has\n * both a light and a dark value-set (see `buildModeStylesheet`,\n * `./modeStylesheet.js`).\n *\n * DELIBERATELY SEPARATE from `applyTokens`/`clearTokenOverrides` (inline\n * `style.setProperty`, above): those two stay untouched and are still what\n * `TokenProvider` calls for a light-only theme, so a single-mode app's\n * output is byte-identical to today (back-compat gate, spec \u00A73 D3). This\n * function is only reached when a theme actually has a dark mode \u2014 a\n * `<style>` tag is required (not inline styles) because only a stylesheet\n * can carry a `@media (prefers-color-scheme: dark)` block and\n * attribute-selector rules; inline styles on `documentElement` can express\n * neither.\n *\n * The `css` argument is expected to already be sanitized (`buildModeStylesheet`\n * runs every value through `sanitizeCssValue` before it reaches here) \u2014 this\n * function does no further validation, it only manages the tag's lifecycle.\n *\n * @param {string} css CSS text, e.g. from `buildModeStylesheet(...)`.\n * @returns {void}\n */\nexport const injectModeStylesheet = (css) => {\n let tag = document.getElementById(MODE_STYLESHEET_ID)\n if (!tag) {\n tag = document.createElement('style')\n tag.id = MODE_STYLESHEET_ID\n document.head.appendChild(tag)\n }\n tag.textContent = css\n}\n\n/**\n * Removes the `<style id=\"sorb-tokens\">` tag injected by\n * {@link injectModeStylesheet}, if present. Counterpart to\n * `clearTokenOverrides` for the mode-aware (dual-mode) path.\n *\n * @returns {void}\n */\nexport const clearModeStylesheet = () => {\n const tag = document.getElementById(MODE_STYLESHEET_ID)\n if (tag && tag.parentNode) tag.parentNode.removeChild(tag)\n}\n", "import { sanitizeCssValue } from './sanitize.js'\n\n/**\n * Builds the mode-aware CSS text carrying both a light and (optionally) a\n * dark value-set for the same token ids \u2014 real-dark-mode spec D2/D3.\n *\n * Pure \u2014 no DOM. Returns a CSS string meant to be upserted into a\n * `<style id=\"sorb-tokens\">` tag by {@link injectModeStylesheet} (`apply.js`).\n *\n * Contract (must stay byte-shape-stable \u2014 the demo/cloud emit agents match\n * this exact shape):\n *\n * ```css\n * :root { --a: 1; color-scheme: light; }\n * @media (prefers-color-scheme: dark) {\n * :root:not([data-bs-theme=\"light\"]) { --a: 2; color-scheme: dark; }\n * }\n * [data-bs-theme=\"dark\"] { --a: 2; color-scheme: dark; }\n * [data-bs-theme=\"light\"] { --a: 1; color-scheme: light; }\n * ```\n *\n * The `:not(<lightSelector>)` clause in the `@media` block is what lets a\n * manual \"light\" override beat the OS `prefers-color-scheme: dark` setting \u2014\n * without it, an explicit light choice would still get overridden by an OS\n * dark preference.\n *\n * Single-mode fallback (no `darkVars` / no `darkMode`): emits ONLY a flat\n * `:root { <light decls> }` block \u2014 no `color-scheme`, no media query, no\n * attribute rules \u2014 so a light-only theme's CSS is unchanged from today's\n * flat emit (back-compat gate, spec \u00A73 D3).\n *\n * @param {import('./types').TokenSet} lightVars\n * Light-mode token map. Keys may be bare (`'primary'`) or already\n * `--`-prefixed (`'--primary'`) \u2014 normalized here.\n * @param {import('./types').TokenSet | null | undefined} darkVars\n * Dark-mode token map, same key shape. `null`/`undefined`/`{}` \u21D2 single-mode.\n * @param {import('@sorb/core').DarkModeConvention | null | undefined} darkMode\n * The active TargetAdapter's dark-mode convention (e.g.\n * `reactBootstrapTarget.darkMode`). Undefined \u21D2 single-mode.\n * @returns {string} CSS text, ready to inject verbatim.\n */\nexport const buildModeStylesheet = (lightVars, darkVars, darkMode) => {\n const lightDecls = normalizeDecls(lightVars)\n const hasDark = !!darkMode && !!darkVars && Object.keys(darkVars).length > 0\n\n if (!hasDark) {\n return `:root {\\n${indent(lightDecls)}\\n}\\n`\n }\n\n const darkDecls = normalizeDecls(darkVars)\n const darkSelector = darkMode.darkSelector\n const lightSelector = darkMode.lightSelector\n\n const mediaScopeSelector = lightSelector ? `:root:not(${lightSelector})` : ':root'\n\n const lines = []\n lines.push(':root {')\n lines.push(indent([...lightDecls, 'color-scheme: light;']))\n lines.push('}')\n lines.push('@media (prefers-color-scheme: dark) {')\n lines.push(` ${mediaScopeSelector} {`)\n lines.push(indent([...darkDecls, 'color-scheme: dark;'], 2))\n lines.push(' }')\n lines.push('}')\n lines.push(`${darkSelector} {`)\n lines.push(indent([...darkDecls, 'color-scheme: dark;']))\n lines.push('}')\n if (lightSelector) {\n lines.push(`${lightSelector} {`)\n lines.push(indent([...lightDecls, 'color-scheme: light;']))\n lines.push('}')\n }\n return `${lines.join('\\n')}\\n`\n}\n\n/**\n * Normalizes a TokenSet into `--key: value;` declaration lines, normalizing\n * bare keys to `--`-prefixed and skipping any value that fails\n * {@link sanitizeCssValue} (fail-safe \u2014 same C1 boundary `applyTokens` uses;\n * this text goes straight into a `<style>` tag so it's an even more\n * sensitive boundary than `setProperty`).\n *\n * @param {import('./types').TokenSet | null | undefined} vars\n * @returns {string[]}\n */\nconst normalizeDecls = (vars) => {\n if (!vars) return []\n return Object.entries(vars).reduce((acc, [key, value]) => {\n const result = sanitizeCssValue(String(value))\n if (!result.ok) return acc\n const cssVar = key.startsWith('--') ? key : `--${key}`\n acc.push(`${cssVar}: ${result.value};`)\n return acc\n }, [])\n}\n\n/**\n * @param {string[]} lines\n * @param {number} [level]\n * @returns {string}\n */\nconst indent = (lines, level = 1) => {\n const pad = ' '.repeat(level)\n return lines.map((l) => `${pad}${l}`).join('\\n')\n}\n", "// @sorb/core \u2014 the shared Sorb contract.\n//\n// One published home for the shapes that cross repo boundaries: the resolved\n// bindable token map (Style Dictionary's `sorb/resolved-map` output) and the\n// capture schemas (LayerNode tree, story index). Consolidated here so the\n// contract can't drift across sorb-seed, sorb-juice, and sorb-leaf once the\n// monorepo is split (sorb-rename-migration \u00A73.2).\n//\n// JS-only, JSDoc typedefs \u2014 per the hard rules, no TypeScript. The only runtime\n// export is the canonical tier ordering, which the capture annotator and the\n// plugin both rank against.\n\n/**\n * Token tiers, most-specific first. Binding precedence: component beats\n * semantic beats primitive.\n * @type {readonly ['component', 'semantic', 'primitive']}\n */\nexport const TIERS = Object.freeze(['component', 'semantic', 'primitive'])\n\n/**\n * Tier \u2192 rank (0 = most specific). Lower wins when several tokens share a value.\n * @type {Readonly<Record<Tier, number>>}\n */\nexport const TIER_RANK = Object.freeze({ component: 0, semantic: 1, primitive: 2 })\n\n// \u2500\u2500\u2500 Shared typedefs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * @typedef {'primitive' | 'semantic' | 'component'} Tier\n * Which layer of the 3-tier DTCG taxonomy a token belongs to.\n */\n\n/**\n * @typedef {'color' | 'dimension' | 'fontFamily' | 'fontWeight' | 'number' | 'string'} TokenType\n * DTCG `$type` of the resolved token (extend as the taxonomy grows).\n */\n\n/**\n * A flat map of token name \u2192 value.\n * @typedef {Object.<string, string | number>} TokenSet\n */\n\n/**\n * One entry of the resolved bindable token map \u2014 the single contract produced by\n * Style Dictionary (`sorb/resolved-map`) and consumed by the bridge, the capture\n * annotator, and the plugin. This is THE shape that must not drift.\n * @typedef {Object} ResolvedToken\n * @property {string} id Dotted token id, e.g. `button.primary.bg.default`.\n * @property {string} cssVar The emitted CSS custom property, e.g. `--button-primary-bg-default`.\n * @property {string | number} value Fully resolved value (no `var()` chains).\n * @property {Tier} tier Taxonomy tier (drives binding precedence via TIER_RANK).\n * @property {TokenType} type DTCG `$type`.\n */\n\n/**\n * The resolved map as served/written: `.sorb/resolved.json`.\n * @typedef {ResolvedToken[]} ResolvedMap\n */\n\n/**\n * A captured CSS value plus the raw string it came from.\n * @typedef {Object} RawValue\n * @property {string} raw The raw CSS string captured from the DOM (e.g. `rgb(15,101,239)`).\n */\n\n/**\n * A node in a captured layer tree (Storybook story \u2192 Figma-insertable geometry).\n * Produced by capture, annotated in place by the seed annotator, materialized by\n * the plugin.\n * @typedef {Object} LayerNode\n * @property {string} type Figma-ish node type, e.g. `FRAME`, `TEXT`.\n * @property {RawValue[]} [fills] Fill paints (index 0 is the primary fill).\n * @property {RawValue[]} [strokes] Stroke paints.\n * @property {number} [cornerRadius] Corner radius in px.\n * @property {{ color?: RawValue }[]} [effects] Effects (shadows, etc.).\n * @property {LayerNode[]} [children] Child nodes.\n * @property {SorbAnnotation} [sorb] Token bindings attached by the annotator.\n */\n\n/**\n * Token bindings the seed annotator stamps onto a matched LayerNode.\n * @typedef {Object} SorbAnnotation\n * @property {Object.<string, string>} tokens\n * role (`fill`/`stroke`/`cornerRadius`/`effectN`) \u2192 bound token id.\n * @property {Object.<string, string[]>} candidates\n * role \u2192 all token ids whose value matched (the plugin offers these as a switch).\n */\n\n/**\n * One story's entry in the capture index (`.sorb/index.json`).\n * @typedef {Object} StoryEntry\n * @property {string} artifact Relative path to the captured artifact (`*.sorb.json`).\n */\n\n/**\n * The capture index written to `.sorb/index.json`.\n * @typedef {Object} StoryIndex\n * @property {Object.<string, StoryEntry>} stories storyId \u2192 entry.\n */\n\n/**\n * Identifies a component variant by its dot-path prefix.\n * e.g. \"button.tertiary\" covers all tokens whose id starts with \"button.tertiary.\"\n * @typedef {Object} VariantSpec\n * @property {string} componentId Top-level component key, e.g. \"button\".\n * @property {string} variantId Full dot-path of the variant, e.g. \"button.tertiary\".\n * @property {string} [fromVariant] Dot-path of the source variant to clone from (addVariant only).\n * @property {string} [replacedBy] Dot-path that replaces this variant (deprecateVariant only).\n */\n\n/**\n * The result of a lifecycle action \u2014 what changed.\n * @typedef {Object} VariantChangeset\n * @property {'add'|'deprecate'} action\n * @property {string} variantId The variant that was added or deprecated.\n * @property {string[]} tokenIds All token ids affected (added or deprecated).\n * @property {string} newVersion The component set's new $version after the change.\n */\n\n// \u2500\u2500\u2500 Connector contract (v1: additive) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Three pluggable axes \u2014 SOURCE (where tokens + geometry come IN), CODE-SOURCE\n// (where the running app / codebase lives), and TARGET (how tokens bind into the\n// app) \u2014 plus a runtime registry that dispatches by `id`. Core only defines the\n// contract + registry + default ids; the default implementations are registered\n// by sorb-seed / sorb-juice / sorb-leaf in later phases. See\n// spec/sorb/connectors-architecture.md. `config` everywhere below is the app's\n// `sorb.config.json`-shaped object.\n\n/**\n * A design unit to capture \u2014 one addressable thing a SourceConnector can turn\n * into geometry (today's Storybook \"story entry\" is one). Opaque-ish: only `id`\n * is guaranteed; connectors carry whatever extra metadata they need.\n * @typedef {Object} DesignUnit\n * @property {string} id Stable unit id (e.g. a Storybook story id).\n * @property {string} [name] Human-readable label.\n */\n\n/**\n * SOURCE axis \u2014 where design tokens + geometry come IN. A real source pulls BOTH\n * tokens and geometry from the tool (founder decision 2026-08-28).\n * @typedef {Object} SourceConnector\n * @property {string} id Registry key (default `'storybook-dom'`).\n * @property {(config: Object) => Promise<DesignUnit[]>} listUnits\n * Discover the design units to capture.\n * @property {(unit: DesignUnit, config: Object) => Promise<LayerNode>} captureGeometry\n * Capture one unit as a raw (un-annotated) LayerNode tree.\n * @property {(config: Object) => Promise<TokenSet>} readTokens\n * Read the DTCG token set for this source.\n */\n\n/**\n * CODE-SOURCE axis \u2014 where the running app / codebase lives.\n * @typedef {Object} CodeSourceConnector\n * @property {string} id Registry key (default `'local'`).\n * @property {(config: Object) => Promise<string|null>} resolveAppUrl\n * Resolve the running app's URL (today = `appUrl` / `localhost:5173`).\n * @property {(config: Object) => string} resolveProjectRoot\n * Resolve the project root dir (today = `process.cwd()`).\n * @property {(config: Object) => Promise<void>} [provision]\n * Optional: clone/build a repo \u2192 hosted preview (future code sources).\n */\n\n/**\n * TARGET axis \u2014 how tokens bind into the running app (the component-compat seam).\n * @typedef {Object} TargetAdapter\n * @property {string} id Registry key (default `'react-bootstrap'`).\n * @property {string} emitFormat A Style-Dictionary format id (e.g. `SORB_TOKENSET`).\n * @property {string[]} expectPrefixes Vocab-guard namespace(s), e.g. `['bs-']`.\n * @property {(tokens: TokenSet, config: Object) => void} [inject]\n * Optional: bind tokens into non-React hosts (the `sorbInit` seam).\n * @property {DarkModeConvention} [darkMode]\n * Optional: this target's dark-mode convention (real-dark-mode spec D1).\n * Undefined \u21D2 single-mode (no dark) \u2014 the target has no notion of a dark\n * variant and mode-aware emit/inject should fall back to flat `:root` output.\n */\n\n/**\n * How a TargetAdapter's host framework expresses light/dark mode. v1 only\n * ships `'attribute'` (Bootstrap 5.3's `[data-bs-theme]`); `'class'`\n * (Tailwind's `.dark`) and `'media'` (OS-only, no manual override) are named\n * here for forward-compat but not yet implemented by any shipped adapter \u2014\n * see real-dark-mode-implementation spec \u00A73 \"Deferred to phase 2\".\n * @typedef {Object} DarkModeConvention\n * @property {'attribute'|'class'|'media'} strategy\n * How the manual override is expressed. `'attribute'` sets/reads a DOM\n * attribute (e.g. `data-bs-theme`); `'class'` toggles a class on\n * `documentElement`; `'media'` means OS-only, no manual override.\n * @property {string} [attribute]\n * The attribute name for `strategy: 'attribute'` (e.g. `'data-bs-theme'`).\n * @property {string} darkSelector\n * The CSS selector matching the dark-mode override (e.g.\n * `'[data-bs-theme=\"dark\"]'`).\n * @property {string} [lightSelector]\n * The CSS selector matching an explicit light-mode override (e.g.\n * `'[data-bs-theme=\"light\"]'`) \u2014 lets a manual \"light\" choice beat an OS\n * `prefers-color-scheme: dark` setting.\n */\n\n/**\n * SEMANTIC-ROLE CONTRACT (framework-targets-productization, T0).\n *\n * The canonical set of role ids a token kit MUST expose for the framework\n * TargetAdapter emit formats (`sorb/mantine-vars`, `sorb/mui-vars`,\n * `sorb/mat-sys-vars`, `sorb/shadcn-theme`, `sorb/primevue-preset`) to emit\n * correctly. Each format maps its framework's own vars (`--mantine-*`, `--mui-*`,\n * `--mat-sys-*`, shadcn vars, PrimeVue preset roots) ONTO these role ids.\n *\n * These are DTCG dot-path ids (\u2192 CSS var `--<kebab>` \u2192 preview-payload key\n * `<kebab>`). The Janes Jeans kit (`@metatoy/janes-jeans`) is the reference\n * implementation. A kit using different names supplies `options.roleMap`\n * (role-id \u2192 its-own-token-id) to a format rather than forking it.\n *\n * SEMVER: adding a role id here is a MINOR bump; renaming or removing one is a\n * MAJOR bump for @sorb/core AND @sorb/seed \u2014 every format consumer depends on\n * this set. Scope = the UNION of the target maps' role columns, not a kit's full\n * token tree; anything beyond this list is kit-private.\n *\n * @typedef {Object} SemanticRoles\n * @property {string[]} color surface/ink/brand/accent/danger/success/border/focus roles.\n * @property {string[]} radius control/card/pill.\n * @property {string[]} shadow raised/overlay.\n * @property {string[]} typography display/heading/body/caption \u00D7 fontSize/Weight/lineHeight.\n */\n\n/**\n * The canonical role-id list (T0 reference = the JJ kit's semantic tier).\n * @type {Readonly<{color: string[], radius: string[], shadow: string[], typography: string[]}>}\n */\nexport const DEFAULT_ROLE_IDS = Object.freeze({\n color: Object.freeze([\n 'color.surface', 'color.surface-raised', 'color.surface-sunken',\n 'color.ink', 'color.ink-muted', 'color.ink-on-brand',\n 'color.brand', 'color.brand-hover', 'color.brand-contrast',\n 'color.accent', 'color.accent-hover', 'color.accent-contrast',\n 'color.danger', 'color.danger-hover', 'color.success', 'color.success-hover',\n 'color.focus-ring', 'color.border', 'color.border-subtle', 'color.border-strong',\n ]),\n radius: Object.freeze(['radius.control', 'radius.card', 'radius.pill']),\n shadow: Object.freeze(['shadow.raised', 'shadow.overlay']),\n typography: Object.freeze([\n 'typography.display.fontSize', 'typography.display.fontWeight', 'typography.display.lineHeight',\n 'typography.heading.fontSize', 'typography.heading.fontWeight', 'typography.heading.lineHeight',\n 'typography.body.fontSize', 'typography.body.fontWeight', 'typography.body.lineHeight',\n 'typography.caption.fontSize', 'typography.caption.fontWeight', 'typography.caption.lineHeight',\n ]),\n})\n\n/**\n * Flat list of every canonical role id (all tiers), for iteration/validation.\n * @type {readonly string[]}\n */\nexport const ALL_ROLE_IDS = Object.freeze([\n ...DEFAULT_ROLE_IDS.color, ...DEFAULT_ROLE_IDS.radius,\n ...DEFAULT_ROLE_IDS.shadow, ...DEFAULT_ROLE_IDS.typography,\n])\n\n/**\n * Resolve a role id to the kit's actual token id via an optional override map.\n * A format calls `resolveRole('color.brand', options.roleMap)` \u2192 the kit's token\n * id (identity when the kit uses canonical ids, i.e. the JJ reference).\n * @param {string} roleId A canonical role id from {@link ALL_ROLE_IDS}.\n * @param {Record<string,string>} [roleMap] role-id \u2192 kit-token-id overrides.\n * @returns {string} the kit token id to reference (`var(--<kebab>)`).\n */\nexport function resolveRole(roleId, roleMap) {\n return (roleMap && roleMap[roleId]) || roleId\n}\n\n/** Default SOURCE connector id (registered by sorb-seed). @type {string} */\nexport const DEFAULT_SOURCE_ID = 'storybook-dom'\n\n/** Default CODE-SOURCE connector id (registered by sorb-juice). @type {string} */\nexport const DEFAULT_CODE_SOURCE_ID = 'local'\n\n/** Default TARGET adapter id (registered by sorb-leaf). @type {string} */\nexport const DEFAULT_TARGET_ID = 'react-bootstrap'\n\n/**\n * The runtime connector registry \u2014 id \u2192 impl per axis. The Maps are mutable by\n * design so consumer packages register their defaults into them; the container\n * itself is frozen so the axis set can't drift.\n * @typedef {Object} ConnectorRegistry\n * @property {Map<string, SourceConnector>} source\n * @property {Map<string, CodeSourceConnector>} codeSource\n * @property {Map<string, TargetAdapter>} target\n * @type {ConnectorRegistry}\n */\nexport const connectors = Object.freeze({\n source: new Map(),\n codeSource: new Map(),\n target: new Map(),\n})\n\n/**\n * Register a SOURCE connector by its `id`.\n * @param {SourceConnector} conn\n * @returns {SourceConnector} the registered connector.\n */\nexport function registerSource(conn) {\n connectors.source.set(conn.id, conn)\n return conn\n}\n\n/**\n * Register a CODE-SOURCE connector by its `id`.\n * @param {CodeSourceConnector} conn\n * @returns {CodeSourceConnector} the registered connector.\n */\nexport function registerCodeSource(conn) {\n connectors.codeSource.set(conn.id, conn)\n return conn\n}\n\n/**\n * Register a TARGET adapter by its `id`. Minimal shape validation (T0b) \u2014 with\n * seven+ adapters registering into one Map, a typo'd `id` or missing\n * `emitFormat` would fail silently at query time; catch it at register time.\n * Throws on a malformed adapter; `console.warn`s (does not throw) on a\n * duplicate-id overwrite so a legitimate re-register in tests/HMR still works.\n * @param {TargetAdapter} adapter\n * @returns {TargetAdapter} the registered adapter.\n */\nexport function registerTarget(adapter) {\n if (!adapter || typeof adapter.id !== 'string' || !adapter.id) {\n throw new Error('registerTarget: adapter.id must be a non-empty string')\n }\n if (typeof adapter.emitFormat !== 'string' || !adapter.emitFormat) {\n throw new Error(`registerTarget(${JSON.stringify(adapter.id)}): emitFormat must be a non-empty string`)\n }\n if (!Array.isArray(adapter.expectPrefixes)) {\n throw new Error(`registerTarget(${JSON.stringify(adapter.id)}): expectPrefixes must be an array`)\n }\n if (connectors.target.has(adapter.id)) {\n // eslint-disable-next-line no-console\n console.warn(`registerTarget: overwriting existing target adapter ${JSON.stringify(adapter.id)}`)\n }\n connectors.target.set(adapter.id, adapter)\n return adapter\n}\n\n/**\n * Look up a registered SOURCE connector; throws on unknown id.\n * @param {string} id\n * @returns {SourceConnector}\n */\nexport function getSource(id) {\n const conn = connectors.source.get(id)\n if (!conn) throw new Error(`Unknown source connector: ${JSON.stringify(id)}`)\n return conn\n}\n\n/**\n * Look up a registered CODE-SOURCE connector; throws on unknown id.\n * @param {string} id\n * @returns {CodeSourceConnector}\n */\nexport function getCodeSource(id) {\n const conn = connectors.codeSource.get(id)\n if (!conn) throw new Error(`Unknown codeSource connector: ${JSON.stringify(id)}`)\n return conn\n}\n\n/**\n * Look up a registered TARGET adapter; throws on unknown id.\n * @param {string} id\n * @returns {TargetAdapter}\n */\nexport function getTarget(id) {\n const adapter = connectors.target.get(id)\n if (!adapter) throw new Error(`Unknown target adapter: ${JSON.stringify(id)}`)\n return adapter\n}\n\n/**\n * Resolve the three connector ids from a config, falling back to the defaults\n * when a key is absent (back-compat = today's behavior).\n * @param {{ source?: string, codeSource?: string, target?: string }} [config]\n * @returns {{ source: string, codeSource: string, target: string }}\n */\nexport function resolveConnectorIds(config = {}) {\n return {\n source: config.source || DEFAULT_SOURCE_ID,\n codeSource: config.codeSource || DEFAULT_CODE_SOURCE_ID,\n target: config.target || DEFAULT_TARGET_ID,\n }\n}\n\nexport {}\n", "/**\n * The `react-bootstrap` TargetAdapter \u2014 Sorb's DEFAULT target (connectors\n * architecture spec \u00A73.3/\u00A74 C3): \"how tokens bind into the running app\" for\n * today's React + Bootstrap-styled component set.\n *\n * v1 scope (spec \u00A74 C3): DEFINE + REGISTER the adapter against the\n * `@sorb/core` connector contract. This is a descriptive re-cast of today's\n * already-shipped behavior \u2014 it does NOT reroute the live vocab guard or the\n * Provider's token-apply path to the registry. `SorbProvider` keeps reading\n * `config.preview.expectPrefixes` directly (see `TokenProvider.jsx`) and\n * `applyTokens` (`apply.js`) stays the pure-JS inject; both are unchanged by\n * this file. `inject` is intentionally left undefined here \u2014 React hosts\n * bind tokens via the Provider/`applyTokens`, not via an adapter-level\n * `inject` call; that seam is for non-React hosts and belongs to the\n * Component Compat Roadmap's `@sorb/leaf-core`/`@sorb/emit` extraction\n * (out of scope for this phase).\n */\nimport * as core from '@sorb/core'\n\n// The Style-Dictionary format id that emits this target's token set, from the\n// named-format registry (`sorb-demo/sd/sorb-format.js:30`):\n// export const SORB_TOKENSET = 'sorb/tokenset-esm'\n// Inlined as a string (not imported) so `@sorb/leaf` doesn't take a build-time\n// dependency on `sorb-demo`'s Style Dictionary config \u2014 the format id is a\n// stable, documented string contract, not a JS binding.\nconst SORB_TOKENSET_FORMAT_ID = 'sorb/tokenset-esm'\n\n/**\n * @type {import('@sorb/core').TargetAdapter}\n */\nexport const reactBootstrapTarget = {\n id: 'react-bootstrap',\n emitFormat: SORB_TOKENSET_FORMAT_ID,\n // The Bootstrap-styled vocab namespace (matches `sorb-demo/src/sorbConfig.js`'s\n // `preview.expectPrefixes: ['bs-']`).\n expectPrefixes: ['bs-'],\n // Left undefined on purpose \u2014 see file header.\n inject: undefined,\n // Bootstrap 5.3's native dark-mode convention (real-dark-mode spec D1): a\n // `data-bs-theme` attribute on any ancestor (Bootstrap recommends\n // `<html>`) selects the mode; absent \u21D2 OS `prefers-color-scheme` governs.\n darkMode: {\n strategy: 'attribute',\n attribute: 'data-bs-theme',\n darkSelector: '[data-bs-theme=\"dark\"]',\n lightSelector: '[data-bs-theme=\"light\"]',\n },\n}\n\n// Register into the @sorb/core registry WHEN this build's core supports it. The\n// published @sorb/core on npm can lag the connector contract (polyrepo publish\n// order); a namespace import + feature-detect keeps the esbuild build + runtime\n// working against an older published core (no \"no matching export\" / crash).\nif (typeof core.registerTarget === 'function') {\n core.registerTarget(reactBootstrapTarget)\n}\n\nexport default reactBootstrapTarget\n", "/**\n * Preview-origin guard \u2014 the C3 production foot-gun guard.\n *\n * Preview defaults OFF. Even when a team opts in, the SDK must only talk to a\n * TRUSTED bridge origin: a stray `?preview=` on a production link must not be\n * able to point the running app at an untrusted bridge. This pure helper makes\n * that decision; the provider wires it in. No DOM, fully node:test-able.\n */\n\nconst DEFAULT_ORIGIN = 'http://localhost:7777'\n\n/**\n * Is `origin` a localhost / loopback origin (any port)? `http`/`https`,\n * `localhost`, `127.0.0.1`, and IPv6 `[::1]` all count.\n *\n * @param {string} origin\n * @returns {boolean}\n */\nconst isLocalhostOrigin = (origin) => {\n let url\n try {\n url = new URL(origin)\n } catch (e) {\n void e\n return false\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return false\n const host = url.hostname.toLowerCase()\n return host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '[::1]'\n}\n\n/**\n * Normalise to a bare `protocol//host:port` origin for exact comparison\n * against a consumer-supplied allowlist (trailing slashes / paths ignored).\n *\n * @param {string} value\n * @returns {string|null}\n */\nconst toOrigin = (value) => {\n try {\n return new URL(value).origin\n } catch (e) {\n void e\n return null\n }\n}\n\n/**\n * Decide whether the preview path may run, and against which origin.\n *\n * Allowed only when BOTH:\n * 1. `config.preview?.enabled === true` (strict \u2014 not just truthy), and\n * 2. the resolved origin is on the allowlist: localhost/127.0.0.1/[::1]\n * (any port) by default, plus any exact origins the consumer lists in\n * `config.preview.allowedOrigins`.\n *\n * Anything else (disabled, missing config, non-allowlisted origin, malformed\n * origin) \u2192 not allowed; the caller falls back to committed tokens.\n *\n * @param {import('./types').SorbConfig} [config]\n * @returns {{ allowed: boolean, origin: string|null, reason?: string }}\n */\nexport const shouldLoadPreview = (config) => {\n const preview = config && config.preview\n if (!preview || preview.enabled !== true) {\n return { allowed: false, origin: null, reason: 'preview-disabled' }\n }\n\n const origin = preview.origin ?? DEFAULT_ORIGIN\n const normalized = toOrigin(origin)\n if (!normalized) {\n return { allowed: false, origin: null, reason: 'malformed-origin' }\n }\n\n if (isLocalhostOrigin(origin)) {\n return { allowed: true, origin }\n }\n\n const extra = Array.isArray(preview.allowedOrigins) ? preview.allowedOrigins : []\n const allowed = extra.some((entry) => toOrigin(entry) === normalized)\n if (allowed) {\n return { allowed: true, origin }\n }\n\n return { allowed: false, origin, reason: 'origin-not-allowlisted' }\n}\n", "/**\n * Vocabulary / contract guard (GFP RC1 Part 4 \u00B7 backlog B4).\n *\n * The failure mode this catches: a preview whose token keys don't intersect the\n * custom-property namespace the app actually consumes (e.g. an app that renders\n * from `--bs-*` fed a `--color-*` preview). `applyTokens` faithfully writes the\n * preview's vars onto `<html>`, the \"preview active\" banner lights \u2014 but nothing\n * on screen moves. A silent no-op is the worst founder-demo failure mode.\n *\n * This guard makes that condition LOUD instead of silent. It is fully opt-in:\n * off unless the consumer sets `config.preview.expectPrefixes` to a non-empty\n * array of key prefixes it expects (e.g. `['bs-']`). No DOM, fully node:test-able.\n */\n\n/**\n * How many of `tokens`' keys start with ANY of `prefixes`.\n *\n * @param {import('./types').TokenSet} tokens\n * @param {string[]} prefixes\n * @returns {number}\n */\nexport const countMatchingPrefixes = (tokens, prefixes) => {\n const list = Array.isArray(prefixes) ? prefixes : []\n return Object.keys(tokens || {}).filter((key) => list.some((p) => key.startsWith(p))).length\n}\n\n/**\n * Decide whether a freshly-applied preview mismatches the app's expected token\n * vocabulary, and `console.warn` an actionable message when it does.\n *\n * Guard is OFF (returns false, never warns) unless `expectPrefixes` is a\n * non-empty array \u2014 so the default is zero behaviour change. When ON: a preview\n * that applied at least one token but matched ZERO expected prefixes is a\n * mismatch (warn + return true). An empty/failed preview (0 applied tokens) is\n * NOT treated as a mismatch \u2014 that is a separate condition the provider already\n * handles by falling back to committed tokens.\n *\n * @param {object} args\n * @param {import('./types').TokenSet} args.tokens Applied preview token set.\n * @param {string[]} [args.expectPrefixes] Key prefixes the app expects.\n * @param {string|null} [args.previewId] Preview id, for the message.\n * @returns {boolean} true when a vocabulary mismatch was detected.\n */\nexport const checkPreviewVocabulary = ({ tokens, expectPrefixes, previewId }) => {\n if (!Array.isArray(expectPrefixes) || expectPrefixes.length === 0) return false\n\n const appliedCount = Object.keys(tokens || {}).length\n if (appliedCount === 0) return false // empty/failed preview \u2014 not a vocab mismatch\n\n const matched = countMatchingPrefixes(tokens, expectPrefixes)\n if (matched > 0) return false\n\n try {\n // Intentionally NOT gated on NODE_ENV: the guard is opt-in, and a\n // demo-blocking silent no-op is exactly what a shipped consumer wants to see.\n // eslint-disable-next-line no-console\n console.warn(\n `[Sorb] preview ${previewId ? `\"${previewId}\" ` : ''}applied ${appliedCount} tokens ` +\n `but none match expected prefixes ${JSON.stringify(expectPrefixes)} \u2014 the app may not ` +\n `visibly re-skin (token-vocabulary mismatch).`,\n )\n } catch (e) {\n // never let logging break token application\n void e\n }\n return true\n}\n", "// bridgeAuth.js \u2014 hosted-bridge Authorization header (Plugin-UX U4).\n//\n// Sorb's hosted bridge (https://bridge.sorbcloud.com) requires\n// `Authorization: Bearer <key>` on every route except /health. The key is a\n// read-only publishable `sorb_pk_\u2026` (safe to ship in a distributable; 403s on\n// writes). Local `sorb dev` runs with NO auth, so when no key is configured we\n// send NO header and the localhost path is byte-for-byte unchanged.\n//\n// One place builds the header so both fetch sites (TokenProvider preview poll +\n// verify.js) stay consistent. Pure + node:test-able; no DOM, no fetch.\n\n/**\n * Build the request headers for a hosted-bridge call, merging in the bearer\n * `Authorization` header only when a non-empty key is configured.\n *\n * @param {string} [key] The configured bearer key (`config.preview.key`), if any.\n * @param {Record<string,string>} [base] Base headers to extend (e.g. Content-Type).\n * @returns {Record<string,string>}\n */\nexport const bridgeHeaders = (key, base) => {\n const headers = base ? { ...base } : {}\n if (typeof key === 'string' && key.trim() !== '') {\n headers.Authorization = `Bearer ${key.trim()}`\n }\n return headers\n}\n", "// connection.js \u2014 org-key connection resolution (Phase E1, hosted-bridge-modes).\n//\n// Load-bearing principle (spec/sorb/hosted-bridge-modes-exploration-plan.md \u00A71,\n// experiments/sorb-bridge-modes/contracts/config-migration.md \"Resolution chain\n// per client / sorb-leaf\"): the running app identifies itself via a single\n// org/publishable key \u2014 like an analytics SDK key \u2014 and everything else\n// (bridge mode/url, token source, preview persistence) resolves from the org\n// server-side. Explicit `config.preview.origin` (today's file-mode / Mode C\n// path) always wins and is untouched; org-key resolution is purely additive.\n//\n// TODO(E1 cloud contract \u2014 reconcile when the sorb-cloud agent lands the real\n// endpoint): assumed shape \u2014\n//\n// GET <cloudBase>/api/orgs/resolve?key=<publishableKey>\n// \u2192 200 {\n// bridgeMode: 'A' | 'B' | 'C',\n// bridgeUrl: string, // e.g. \"https://bridge.sorbcloud.com\"\n// orgId?: string, // needed to build the SSE subscribe URL\n// tokenSource?: string,\n// previewPersistence?: boolean,\n// transport?: 'sse' | 'poll', // defaults to 'sse' when bridgeMode === 'A'\n// }\n// \u2192 non-2xx (unknown/revoked key, network error) \u2192 resolution returns `null`;\n// the caller falls back to today's \"server not running\" behavior (loads\n// committed tokens, never throws).\n\n/** @type {string} */\nexport const DEFAULT_CLOUD_BASE = 'https://api.sorbcloud.com'\n\n/**\n * Read the org/publishable key off a SorbConfig, accepting either field name.\n * @param {import('./types').SorbConfig} [config]\n * @returns {string|null}\n */\nexport const getOrgKey = (config) => {\n if (!config) return null\n const key = config.orgKey || config.publishableKey\n return typeof key === 'string' && key.trim() !== '' ? key.trim() : null\n}\n\n/**\n * Should we attempt org-key resolution at all? Only when an org key is\n * present AND the consumer has not already pinned an explicit\n * `config.preview.origin` \u2014 an explicit origin is today's file-mode / Mode C\n * path and always takes precedence (config-migration.md's resolution chain,\n * step 1).\n *\n * @param {import('./types').SorbConfig} [config]\n * @returns {boolean}\n */\nexport const shouldResolveOrgConnection = (config) => {\n const key = getOrgKey(config)\n if (!key) return false\n const explicitOrigin = config && config.preview && config.preview.origin\n return !(typeof explicitOrigin === 'string' && explicitOrigin.trim() !== '')\n}\n\n/**\n * Fetch the effective connection config for an org/publishable key.\n * Never throws \u2014 network errors, non-2xx responses, and malformed payloads\n * all resolve to `null` so callers can fall back safely.\n *\n * @param {string} orgKey\n * @param {{ cloudBase?: string, fetchImpl?: typeof fetch }} [opts]\n * @returns {Promise<import('./types').ResolvedConnection|null>}\n */\nexport const resolveOrgConnection = async (orgKey, opts) => {\n const { cloudBase = DEFAULT_CLOUD_BASE, fetchImpl } = opts || {}\n const doFetch = fetchImpl || (typeof fetch !== 'undefined' ? fetch : null)\n if (!doFetch || typeof orgKey !== 'string' || orgKey.trim() === '') return null\n\n try {\n const base = cloudBase.replace(/\\/$/, '')\n const url = `${base}/api/orgs/resolve?key=${encodeURIComponent(orgKey.trim())}`\n const res = await doFetch(url)\n if (!res || !res.ok) return null\n const data = await res.json()\n if (!data || typeof data !== 'object') return null\n if (typeof data.bridgeUrl !== 'string' || data.bridgeUrl.trim() === '') return null\n\n const bridgeMode = typeof data.bridgeMode === 'string' ? data.bridgeMode : 'C'\n return {\n bridgeMode,\n bridgeUrl: data.bridgeUrl,\n orgId: typeof data.orgId === 'string' ? data.orgId : null,\n tokenSource: typeof data.tokenSource === 'string' ? data.tokenSource : null,\n // sorb-cloud's /api/orgs/resolve returns this as a boolean (entitlement\n // flag), not an object \u2014 see cloud src/lib/orgResolve.ts.\n previewPersistence:\n typeof data.previewPersistence === 'boolean' ? data.previewPersistence : null,\n transport: data.transport === 'poll' || data.transport === 'sse' ? data.transport : bridgeMode === 'A' ? 'sse' : 'poll',\n }\n } catch (e) {\n void e\n return null\n }\n}\n\n/**\n * Merge a resolved org connection into an effective `preview` config, without\n * mutating the inputs. When `resolved` is falsy this is the identity function\n * on `config.preview` \u2014 the byte-for-byte back-compat path.\n *\n * @param {import('./types').SorbConfig} config\n * @param {import('./types').ResolvedConnection|null} resolved\n * @returns {import('./types').PreviewConfig}\n */\nexport const buildEffectivePreviewConfig = (config, resolved) => {\n const base = (config && config.preview) || {}\n if (!resolved) return base\n const orgKey = getOrgKey(config)\n return {\n ...base,\n enabled: true,\n origin: resolved.bridgeUrl,\n allowedOrigins: [...(Array.isArray(base.allowedOrigins) ? base.allowedOrigins : []), resolved.bridgeUrl],\n key: base.key || orgKey || undefined,\n }\n}\n\n/**\n * Build the effective SorbConfig used for the rest of the provider's logic:\n * `config` untouched, except `preview` merged with the resolved connection\n * (if any). Pure, so it's trivially testable independent of React/fetch.\n *\n * @param {import('./types').SorbConfig} config\n * @param {import('./types').ResolvedConnection|null} resolved\n * @returns {import('./types').SorbConfig}\n */\nexport const buildEffectiveConfig = (config, resolved) => {\n if (!resolved) return config\n return { ...config, preview: buildEffectivePreviewConfig(config, resolved) }\n}\n", "// sse.js \u2014 hosted-relay preview subscription (Phase E1, hosted-bridge-modes).\n//\n// When the resolved connection is a hosted relay (Mode A), SorbProvider\n// subscribes to preview updates via Server-Sent Events instead of the poll\n// loop kept for Mode C / non-SSE bridges. Pure URL-building + frame-parsing\n// live here so they're node:test-able without a real EventSource/DOM; the\n// thin `createPreviewSubscription` wiring is exercised with a fake\n// EventSource constructor in tests.\n//\n// TODO(juice SSE contract \u2014 reconcile when the sorb-juice agent lands the\n// real endpoint): assumed shape \u2014\n//\n// new EventSource(`${bridgeUrl}/orgs/${orgId}/preview/${previewId}/subscribe`)\n// (auth: EventSource can't set custom headers, so the bearer key is passed\n// as a `?key=` query param until an EventSource polyfill with header\n// support is adopted \u2014 flagged for reconciliation, not decided here)\n//\n// `message` event, `evt.data` = JSON:\n// { type: 'snapshot' | 'update', tokens: TokenSet } \u2014 apply tokens\n// { type: 'ping' } \u2014 keepalive, ignored\n//\n// Relay-spike precedent (experiments/sorb-bridge-modes/relay-spike/NOTES.md):\n// \"initial snapshot on subscribe + periodic ping\" is exactly this shape.\n\n/**\n * Build the subscribe URL for a hosted-relay preview.\n * @param {string} bridgeUrl\n * @param {string} orgId\n * @param {string} previewId\n * @param {string} [key] Bearer key, sent as `?key=` (see TODO above).\n * @returns {string}\n */\nexport const buildSubscribeUrl = (bridgeUrl, orgId, previewId, key) => {\n const base = String(bridgeUrl).replace(/\\/$/, '')\n const path = `${base}/orgs/${encodeURIComponent(orgId)}/preview/${encodeURIComponent(previewId)}/subscribe`\n if (typeof key === 'string' && key.trim() !== '') {\n return `${path}?key=${encodeURIComponent(key.trim())}`\n }\n return path\n}\n\n/**\n * Parse one SSE frame's `data` payload. Returns `null` for anything that\n * isn't a recognised, well-formed frame \u2014 callers should simply ignore it\n * (never throw on an unexpected/future frame shape).\n *\n * @param {string} raw\n * @returns {{ type: 'snapshot'|'update', tokens: import('./types').TokenSet } | { type: 'delete', tokens: null } | { type: 'ping' } | null}\n */\nexport const parsePreviewFrame = (raw) => {\n let frame\n try {\n frame = JSON.parse(raw)\n } catch (e) {\n void e\n return null\n }\n if (!frame || typeof frame !== 'object') return null\n if (frame.type === 'ping') return { type: 'ping' }\n // juice emits a delete frame (tokens:null) when a preview is removed/expires\n // server-side \u2014 the subscriber should revert to committed tokens.\n if (frame.type === 'delete') return { type: 'delete', tokens: null }\n if ((frame.type === 'snapshot' || frame.type === 'update') && frame.tokens && typeof frame.tokens === 'object') {\n return { type: frame.type, tokens: frame.tokens }\n }\n return null\n}\n\n/**\n * Open an SSE subscription and wire parsed token frames to `onTokens`.\n * Returns an unsubscribe function, or `null` if no usable EventSource\n * constructor was provided (caller should fall back to polling).\n *\n * @param {{\n * EventSourceImpl?: typeof EventSource,\n * url: string,\n * onTokens: (tokens: import('./types').TokenSet) => void,\n * onDelete?: () => void,\n * onError?: (evt: unknown) => void,\n * }} opts\n * @returns {(() => void) | null}\n */\nexport const createPreviewSubscription = ({ EventSourceImpl, url, onTokens, onDelete, onError }) => {\n if (typeof EventSourceImpl !== 'function') return null\n\n const es = new EventSourceImpl(url)\n\n es.onmessage = (evt) => {\n const parsed = parsePreviewFrame(evt && evt.data)\n if (!parsed || parsed.type === 'ping') return\n if (parsed.type === 'delete') {\n if (onDelete) onDelete()\n return\n }\n onTokens(parsed.tokens)\n }\n\n const handleError = (evt) => {\n if (onError) onError(evt)\n }\n if (typeof es.addEventListener === 'function') {\n es.addEventListener('error', handleError)\n } else {\n es.onerror = handleError\n }\n\n return () => {\n try {\n es.close()\n } catch (e) {\n void e\n }\n }\n}\n", "/**\n * Pure (no-DOM) preview-body classification \u2014 real-dark-mode phase 2 (spec\n * P2). The bridge's `/preview/:id` fetch response AND the SSE `onTokens`\n * push carry the SAME body shape, which is EITHER:\n *\n * - legacy flat map: `{ \"--token\": \"value\", ... }`\n * - mode-aware wrapper: `{ tokens: {...light}, darkTokens\uFF1F: {...dark},\n * darkMode\uFF1F: DarkModeConvention }`\n *\n * Kept separate from `TokenProvider.jsx` (which owns the DOM side-effects \u2014\n * `injectModeStylesheet`/`applyTokens`) so the detection + resolution logic\n * is unit-testable without a DOM stub.\n */\n\n/**\n * @param {unknown} body\n * @returns {boolean} true when `body` uses the mode-aware wrapper shape.\n */\nexport const isModeAwarePreviewBody = (body) =>\n !!body && typeof body === 'object' && !Array.isArray(body) && 'tokens' in body\n\n/**\n * @typedef {{ kind: 'flat', tokens: import('./types').TokenSet }} FlatPreviewResolution\n * @typedef {{\n * kind: 'mode-aware',\n * lightTokens: import('./types').TokenSet,\n * darkTokens: import('./types').TokenSet,\n * darkMode: import('@sorb/core').DarkModeConvention,\n * }} ModeAwarePreviewResolution\n */\n\n/**\n * Resolves a raw preview body into either a flat-apply instruction or a\n * mode-aware-inject instruction. Never touches the DOM.\n *\n * - Legacy flat body \u21D2 `{ kind: 'flat', tokens: body }` (byte-identical\n * back-compat path \u2014 the caller must still call the exact same\n * `applyTokens` it always has).\n * - Mode-aware body with NO `darkTokens` (absent/empty) \u21D2 still `'flat'`,\n * using `body.tokens` as the flat map (spec: \"treat body.tokens as the\n * flat map\").\n * - Mode-aware body WITH a non-empty `darkTokens` \u21D2 `'mode-aware'`, with\n * `darkMode` resolved from `body.darkMode`, falling back to\n * `fallbackDarkMode` (the active target's convention) when the bridge\n * didn't send one.\n *\n * @param {unknown} body\n * @param {import('@sorb/core').DarkModeConvention | undefined} fallbackDarkMode\n * @returns {FlatPreviewResolution | ModeAwarePreviewResolution}\n */\nexport const resolvePreviewBody = (body, fallbackDarkMode) => {\n if (!isModeAwarePreviewBody(body)) {\n return { kind: 'flat', tokens: /** @type {import('./types').TokenSet} */ (body) }\n }\n const wrapper = /** @type {{ tokens: import('./types').TokenSet, darkTokens?: import('./types').TokenSet, darkMode?: import('@sorb/core').DarkModeConvention }} */ (\n body\n )\n const darkTokens = wrapper.darkTokens\n if (darkTokens && Object.keys(darkTokens).length > 0) {\n return {\n kind: 'mode-aware',\n lightTokens: wrapper.tokens,\n darkTokens,\n darkMode: wrapper.darkMode ?? fallbackDarkMode,\n }\n }\n return { kind: 'flat', tokens: wrapper.tokens }\n}\n", "/**\n * Pure (no-DOM) resolution of what `setMode` (`TokenProvider.jsx`) should do\n * to the document for a given `darkMode` convention + requested mode \u2014 P2a\n * multi-framework `setMode` support. Kept separate from `TokenProvider.jsx`\n * (which owns the actual DOM writes) so the strategy dispatch is\n * unit-testable without a DOM stub or a React render harness.\n */\n\n/**\n * Derives the class name a `strategy: 'class'` convention's `darkSelector`\n * names (e.g. `'.dark'` \u2192 `'dark'`). Falls back to `'dark'` if the selector\n * isn't a bare single-class selector (defensive; every shipped convention\n * names one).\n * @param {import('@sorb/core').DarkModeConvention | undefined} darkModeConvention\n * @returns {string}\n */\nexport const darkClassName = (darkModeConvention) => {\n const selector = String(darkModeConvention?.darkSelector || '').trim()\n const match = /^\\.([a-zA-Z0-9_-]+)$/.exec(selector)\n return match ? match[1] : 'dark'\n}\n\n/**\n * @typedef {{ type: 'none' }} NoneAction\n * @typedef {{ type: 'attr-set', attribute: string, value: 'light'|'dark' }} AttrSetAction\n * @typedef {{ type: 'attr-remove', attribute: string }} AttrRemoveAction\n * @typedef {{ type: 'class-add', className: string }} ClassAddAction\n * @typedef {{ type: 'class-remove', className: string }} ClassRemoveAction\n */\n\n/**\n * Resolves the DOM action `setMode(next)` should perform for the given\n * convention, without touching the DOM.\n *\n * - `strategy: 'media'` \u21D2 `{ type: 'none' }` \u2014 pure OS, no manual override.\n * - `strategy: 'class'` \u21D2 `next === 'dark'` adds the class; `'light'` AND\n * `'auto'` both remove it (no separate \"light\" class in e.g. Tailwind's\n * convention).\n * - `strategy: 'attribute'` (default, incl. undefined convention) \u21D2\n * `next === 'auto'` removes the attribute (media governs); `'light'`/\n * `'dark'` set it.\n *\n * @param {import('@sorb/core').DarkModeConvention | undefined} darkModeConvention\n * @param {'auto'|'light'|'dark'} next\n * @returns {NoneAction | AttrSetAction | AttrRemoveAction | ClassAddAction | ClassRemoveAction}\n */\nexport const resolveModeAction = (darkModeConvention, next) => {\n const strategy = darkModeConvention?.strategy || 'attribute'\n\n if (strategy === 'media') {\n return { type: 'none' }\n }\n\n if (strategy === 'class') {\n const className = darkClassName(darkModeConvention)\n return next === 'dark' ? { type: 'class-add', className } : { type: 'class-remove', className }\n }\n\n const attribute = darkModeConvention?.attribute || 'data-bs-theme'\n return next === 'auto' ? { type: 'attr-remove', attribute } : { type: 'attr-set', attribute, value: next }\n}\n", "// @sorb/leaf-core \u2014 the framework-free injector (component-compat-roadmap P0).\n//\n// Everything `SorbProvider` (`TokenProvider.jsx`) does at runtime, minus\n// React: resolve the bridge connection, load committed/preview tokens, apply\n// them via the mode-aware `<style>` injector or the legacy inline\n// `applyTokens` path, and expose `setMode`/mode state through a tiny\n// pub-sub store. `sorbInit(config)` is the ONE entry a non-React host needs.\n//\n// This module is pure JS with no React import \u2014 that's the whole point (the\n// P0 acceptance test: a plain-HTML page can drive it with zero React in the\n// bundle). `TokenProvider.jsx` is now a thin wrapper that subscribes to the\n// instance this returns instead of re-implementing the logic below.\nimport { applyTokens, clearTokenOverrides, injectModeStylesheet, clearModeStylesheet } from './apply.js'\nimport { buildModeStylesheet } from './modeStylesheet.js'\nimport { reactBootstrapTarget } from './targets/reactBootstrap.js'\nimport { shouldLoadPreview } from './previewGuard.js'\nimport { checkPreviewVocabulary } from './previewVocab.js'\nimport { bridgeHeaders } from './bridgeAuth.js'\nimport { shouldResolveOrgConnection, getOrgKey, resolveOrgConnection, buildEffectiveConfig } from './connection.js'\nimport { buildSubscribeUrl, createPreviewSubscription } from './sse.js'\nimport { resolvePreviewBody } from './previewMode.js'\nimport { resolveModeAction } from './modeAction.js'\n\n// EventSource/matchMedia only exist in browsers (and some polyfilled envs) \u2014\n// never reference the bare global at module scope so this file stays\n// node:test-safe (identical guard to the one TokenProvider.jsx used).\nconst EventSourceCtor = typeof EventSource !== 'undefined' ? EventSource : null\nconst matchMediaFn = typeof matchMedia !== 'undefined' ? matchMedia : null\nconst DARK_MEDIA_QUERY = '(prefers-color-scheme: dark)'\n\n/**\n * Dev-only warning that never throws outside a Node-like env.\n * @param {string} msg\n * @returns {void}\n */\nconst devWarn = (msg) => {\n try {\n if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(`[sorb] ${msg}`)\n }\n } catch (e) {\n void e\n }\n}\n\n// Tracks which deprecated token ids have already been warned this session.\n// Single module-level set \u2014 shared by every `sorbInit` call (and, via\n// TokenProvider.jsx's re-export, every `SorbProvider` too) so a page mixing\n// both entry points still only warns once per token id.\nexport const warnedDeprecations = new Set()\n\nfunction warnDeprecated(resolved) {\n if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') return\n for (let i = 0; i < resolved.length; i++) {\n const token = resolved[i]\n if (!token.deprecated) continue\n if (warnedDeprecations.has(token.id)) continue\n warnedDeprecations.add(token.id)\n const replacedBy =\n token.replacedBy ||\n (token.$extensions && token.$extensions.sorb && token.$extensions.sorb.replacedBy) ||\n null\n if (replacedBy) {\n console.warn('[@sorb/leaf] Deprecated token: ' + token.id + ' \u2014 use ' + replacedBy + ' instead')\n } else {\n console.warn('[@sorb/leaf] Deprecated token: ' + token.id + ' is deprecated')\n }\n }\n}\n\n/**\n * @typedef {{\n * tokens: import('./types').TokenSet,\n * isPreview: boolean,\n * previewId: string|null,\n * previewMismatch: boolean,\n * mode: 'auto'|'light'|'dark',\n * resolvedScheme: 'light'|'dark',\n * }} SorbState\n *\n * @typedef {{\n * getState: () => SorbState,\n * subscribe: (listener: (state: SorbState) => void) => (() => void),\n * setMode: (next: 'auto'|'light'|'dark') => void,\n * clearPreview: () => void,\n * destroy: () => void,\n * }} SorbInstance\n */\n\n/**\n * Framework-free Sorb entry point. Resolves the connection, loads\n * committed/preview tokens onto `document.documentElement`, and returns a\n * small store (`getState`/`subscribe`) plus `setMode`/`clearPreview`. No\n * React, no JSX \u2014 safe to call from a plain `<script type=\"module\">`.\n *\n * Byte-identical DOM behavior to `SorbProvider`: same guard/vocab/mode-aware\n * injection logic, just driven by a manual pub-sub store instead of React\n * state.\n *\n * @param {import('./types').SorbConfig} config\n * @returns {SorbInstance}\n */\nexport function sorbInit(config) {\n let activeTokens = config.tokens\n let isPreview = false\n let previewId = null\n let previewMismatch = false\n let pollId = null\n let cancelled = false\n let unsubscribeSSE = null\n\n const hasDarkMode = !!(config.darkTokens && Object.keys(config.darkTokens).length > 0)\n const darkModeConvention = config.darkModeConvention || reactBootstrapTarget.darkMode\n\n let mode = 'auto'\n let systemScheme = matchMediaFn ? (matchMediaFn(DARK_MEDIA_QUERY).matches ? 'dark' : 'light') : 'light'\n\n const listeners = new Set()\n const getState = () => ({\n tokens: activeTokens,\n isPreview,\n previewId,\n previewMismatch,\n mode,\n resolvedScheme: mode === 'auto' ? systemScheme : mode,\n })\n const notify = () => {\n const state = getState()\n listeners.forEach((listener) => listener(state))\n }\n const subscribe = (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n }\n\n let mql = null\n const onSchemeChange = (e) => {\n systemScheme = e.matches ? 'dark' : 'light'\n notify()\n }\n if (matchMediaFn) {\n mql = matchMediaFn(DARK_MEDIA_QUERY)\n if (typeof mql.addEventListener === 'function') mql.addEventListener('change', onSchemeChange)\n else if (typeof mql.addListener === 'function') mql.addListener(onSchemeChange)\n }\n\n // Tracks the token map currently written as INLINE `--x` custom properties\n // (flat path) so switching TO the mode-aware `<style>` path can clear\n // those stale inline overrides first \u2014 same reasoning as TokenProvider.jsx.\n let inlineTokens = null\n\n const applyFlat = (tokens) => {\n clearModeStylesheet()\n applyTokens(tokens)\n inlineTokens = tokens\n }\n\n const applyModeAware = (lightTokens, darkTokens, convention) => {\n if (inlineTokens) {\n clearTokenOverrides(inlineTokens)\n inlineTokens = null\n }\n injectModeStylesheet(buildModeStylesheet(lightTokens, darkTokens, convention))\n }\n\n const loadCommitted = () => {\n if (hasDarkMode) {\n applyModeAware(config.tokens, config.darkTokens, darkModeConvention)\n } else {\n applyFlat(config.tokens)\n }\n activeTokens = config.tokens\n isPreview = false\n previewId = null\n previewMismatch = false\n notify()\n }\n\n const applyPreviewTokens = (body, id, effectiveConfig) => {\n const resolved = resolvePreviewBody(body, darkModeConvention)\n let flatTokens\n if (resolved.kind === 'mode-aware') {\n applyModeAware(resolved.lightTokens, resolved.darkTokens, resolved.darkMode)\n flatTokens = resolved.lightTokens\n } else {\n applyFlat(resolved.tokens)\n flatTokens = resolved.tokens\n }\n activeTokens = flatTokens\n isPreview = true\n previewId = id\n previewMismatch = checkPreviewVocabulary({\n tokens: flatTokens,\n expectPrefixes: effectiveConfig.preview?.expectPrefixes,\n previewId: id,\n })\n notify()\n }\n\n const loadPreview = async (id, effectiveConfig) => {\n const cfg = effectiveConfig || config\n const guard = shouldLoadPreview(cfg)\n if (!guard.allowed) {\n loadCommitted()\n return false\n }\n const origin = guard.origin\n try {\n const res = await fetch(`${origin}/preview/${id}`, {\n headers: bridgeHeaders(cfg.preview?.key),\n })\n if (!res.ok) throw new Error('preview not found')\n const tokens = await res.json()\n applyPreviewTokens(tokens, id, cfg)\n return true\n } catch (e) {\n // local server not running, preview expired, or network error \u2014\n // fall back silently, never break the page.\n void e\n loadCommitted()\n return false\n }\n }\n\n const clearPreview = () => {\n if (pollId) {\n clearInterval(pollId)\n pollId = null\n }\n if (typeof location !== 'undefined' && typeof history !== 'undefined') {\n const params = new URLSearchParams(location.search)\n params.delete('preview')\n const qs = params.toString()\n history.replaceState(null, '', qs ? `?${qs}` : location.pathname)\n }\n loadCommitted()\n }\n\n const setMode = (next) => {\n mode = next\n if (typeof document !== 'undefined') {\n const action = resolveModeAction(darkModeConvention, next)\n switch (action.type) {\n case 'attr-set':\n document.documentElement.setAttribute(action.attribute, action.value)\n break\n case 'attr-remove':\n document.documentElement.removeAttribute(action.attribute)\n break\n case 'class-add':\n document.documentElement.classList.add(action.className)\n break\n case 'class-remove':\n document.documentElement.classList.remove(action.className)\n break\n case 'none':\n default:\n break\n }\n }\n notify()\n }\n\n const destroy = () => {\n cancelled = true\n if (pollId) clearInterval(pollId)\n if (unsubscribeSSE) unsubscribeSSE()\n if (mql) {\n if (typeof mql.removeEventListener === 'function') mql.removeEventListener('change', onSchemeChange)\n else if (typeof mql.removeListener === 'function') mql.removeListener(onSchemeChange)\n }\n listeners.clear()\n }\n\n const init = async () => {\n if (config.resolved && config.resolved.length) warnDeprecated(config.resolved)\n\n let effectiveConfig = config\n let resolvedConnection = null\n if (shouldResolveOrgConnection(config)) {\n resolvedConnection = await resolveOrgConnection(getOrgKey(config), {\n cloudBase: config.cloudBase,\n })\n if (cancelled) return\n effectiveConfig = buildEffectiveConfig(config, resolvedConnection)\n }\n\n const guard = shouldLoadPreview(effectiveConfig)\n const id = typeof location !== 'undefined' ? new URLSearchParams(location.search).get('preview') : null\n\n if (!guard.allowed || !id) {\n if (id && !guard.allowed) {\n devWarn(\n `ignoring ?preview= \u2014 preview not permitted (${guard.reason ?? 'blocked'}); ` +\n 'loading committed tokens',\n )\n }\n loadCommitted()\n return\n }\n\n const ok = await loadPreview(id, effectiveConfig)\n if (!ok || cancelled) return\n\n const useSSE =\n resolvedConnection &&\n resolvedConnection.transport === 'sse' &&\n resolvedConnection.orgId &&\n EventSourceCtor\n\n if (useSSE) {\n const url = buildSubscribeUrl(\n resolvedConnection.bridgeUrl,\n resolvedConnection.orgId,\n id,\n effectiveConfig.preview?.key,\n )\n unsubscribeSSE = createPreviewSubscription({\n EventSourceImpl: EventSourceCtor,\n url,\n onTokens: (tokens) => applyPreviewTokens(tokens, id, effectiveConfig),\n onDelete: () => loadCommitted(),\n onError: () => devWarn('SSE preview subscription error \u2014 preview may be stale'),\n })\n }\n\n if (!unsubscribeSSE) {\n const interval = effectiveConfig.preview?.pollInterval ?? 1500\n pollId = setInterval(() => loadPreview(id, effectiveConfig), interval)\n }\n }\n\n init()\n\n return { getState, subscribe, setMode, clearPreview, destroy }\n}\n", "// Runtime shim for the Legacy-React adapter (roadmap \u00A76, Phase 2).\n//\n// A hardcoded literal in a legacy app (e.g. `background: #0F65EF`) does NOT\n// reference a CSS custom property, so `applyTokens` alone can never re-theme it.\n// This shim closes that gap NON-DESTRUCTIVELY: at render it finds elements whose\n// computed style for a mapped property equals a `raw` value in the legacyMap and\n// overrides that element's *inline* style to `var(--<cssVar>, <raw>)`.\n//\n// - non-destructive : no source edit; only inline style is set at runtime.\n// - reversible : `clearLegacyMap(handle)` restores the original inline value.\n// - live-re-themeable: the `var(--cssVar, raw)` re-resolves whenever the token\n// flips (via `applyTokens`), with `raw` as the fallback.\n//\n// The decision logic lives in the pure `computeLegacyOverride` so it can be\n// unit-tested without a real browser; the DOM walker is a thin wrapper.\n\n/**\n * Map a CSS property name (camelCase from JS style objects, or kebab-case from\n * computed style) to a canonical kebab-case form for comparison.\n * @param {string} prop\n * @returns {string}\n */\nexport const normalizeProp = (prop) => {\n if (typeof prop !== 'string') return ''\n return prop\n .trim()\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/_/g, '-')\n .toLowerCase()\n}\n\n/**\n * Canonicalize a color literal to its `rgb(r, g, b)` / `rgba(r, g, b, a)` form.\n * This is the key to matching an authored hex `raw` (`#0F65EF`) against the\n * *computed* value \u2014 browsers (and jsdom) always report computed colors as\n * `rgb()`/`rgba()`, never hex. Handles #rgb / #rrggbb / #rrggbbaa and existing\n * rgb()/rgba() (whitespace-collapsed). Returns null if it isn't a color literal.\n * @param {string} v lowercased, whitespace-collapsed value\n * @returns {string|null}\n */\nconst canonicalizeColor = (v) => {\n // #rgb, #rrggbb, #rrggbbaa (and #rgba)\n const hex = v.match(/^#([0-9a-f]{3,8})$/)\n if (hex) {\n let h = hex[1]\n if (h.length === 3 || h.length === 4) {\n h = h.split('').map((c) => c + c).join('')\n }\n if (h.length !== 6 && h.length !== 8) return null\n const r = parseInt(h.slice(0, 2), 16)\n const g = parseInt(h.slice(2, 4), 16)\n const b = parseInt(h.slice(4, 6), 16)\n if (h.length === 8) {\n const a = parseInt(h.slice(6, 8), 16) / 255\n // round alpha to 3 dp, strip trailing zeros, to match rgba() printing\n const as = String(Math.round(a * 1000) / 1000)\n return `rgba(${r}, ${g}, ${b}, ${as})`\n }\n return `rgb(${r}, ${g}, ${b})`\n }\n // existing rgb()/rgba() \u2192 normalize spacing/commas\n const fn = v.match(/^(rgba?)\\(([^)]*)\\)$/)\n if (fn) {\n const parts = fn[2].split(',').map((p) => p.trim()).filter((p) => p !== '')\n if (parts.length === 3) return `rgb(${parts[0]}, ${parts[1]}, ${parts[2]})`\n if (parts.length === 4) return `rgba(${parts[0]}, ${parts[1]}, ${parts[2]}, ${parts[3]})`\n }\n return null\n}\n\n/**\n * Normalize a style *value* so an authored literal (`\"#0F65EF\"`, `\"4\"`, `\"4px\"`)\n * compares equal to its computed-style form. Trims, lowercases, collapses\n * whitespace, canonicalizes colors to `rgb()/rgba()` (so hex `raw` matches the\n * computed `rgb()`), and treats a bare unitless number as its `px` form (covers\n * `borderRadius: 4` \u2192 `\"4px\"`).\n * @param {string|number} value\n * @returns {string}\n */\nexport const normalizeValue = (value) => {\n if (value == null) return ''\n let v = String(value).trim().toLowerCase()\n if (v === '') return ''\n\n // collapse internal whitespace (e.g. \"rgb( 15 , 101 , 239 )\")\n v = v.replace(/\\s+/g, ' ')\n\n // colors \u2192 canonical rgb()/rgba() so hex and rgb compare equal\n const color = canonicalizeColor(v)\n if (color) return color\n\n // bare unitless number \u2192 px (React style numbers, `borderRadius: 4`)\n if (/^-?\\d*\\.?\\d+$/.test(v)) v = `${v}px`\n\n return v\n}\n\n/**\n * @typedef {import('./types').LegacyMapRow} LegacyMapRow\n */\n\n/**\n * Index a legacyMap into a `prop \u2192 [{ normValue, cssVar, raw }]` lookup so the\n * decision function is O(1)-per-prop instead of scanning the whole array.\n * @param {LegacyMapRow[]} legacyMap\n * @returns {Map<string, Array<{ normValue: string, cssVar: string, raw: string }>>}\n */\nexport const indexLegacyMap = (legacyMap) => {\n /** @type {Map<string, Array<{ normValue: string, cssVar: string, raw: string }>>} */\n const idx = new Map()\n if (!Array.isArray(legacyMap)) return idx\n for (const row of legacyMap) {\n if (!row || row.cssVar == null || row.raw == null || row.prop == null) continue\n const p = normalizeProp(row.prop)\n const entry = {\n normValue: normalizeValue(row.raw),\n cssVar: String(row.cssVar).replace(/^--/, ''),\n raw: String(row.raw),\n }\n const list = idx.get(p)\n if (list) list.push(entry)\n else idx.set(p, [entry])\n }\n return idx\n}\n\n/**\n * PURE decision logic. Given a property, the element's *computed* value for that\n * property, and the legacyMap (array or pre-built index), return the override\n * string `var(--<cssVar>, <raw>)` when the value matches a mapped `raw`, else\n * null. This is the unit-tested core of the shim.\n *\n * @param {string} prop CSS property (camelCase or kebab-case)\n * @param {string|number} computedValue the element's computed value for `prop`\n * @param {LegacyMapRow[]|Map<string, any[]>} legacyMap rows, or an index from `indexLegacyMap`\n * @returns {string|null}\n */\nexport const computeLegacyOverride = (prop, computedValue, legacyMap) => {\n const idx = legacyMap instanceof Map ? legacyMap : indexLegacyMap(legacyMap)\n const list = idx.get(normalizeProp(prop))\n if (!list || list.length === 0) return null\n const target = normalizeValue(computedValue)\n if (target === '') return null\n for (const entry of list) {\n if (entry.normValue === target) {\n return `var(--${entry.cssVar}, ${entry.raw})`\n }\n }\n return null\n}\n\nexport {}\n", "// DOM-applying wrapper for the legacy-map shim. Thin by design: all matching\n// decisions defer to `computeLegacyOverride` (pure, in legacyMap.js); this file\n// only walks the tree, reads computed style, and writes/restores inline styles.\n\nimport { computeLegacyOverride, indexLegacyMap, normalizeProp } from './legacyMap.js'\n\n/**\n * @typedef {import('./types').LegacyMapRow} LegacyMapRow\n * @typedef {import('./types').LegacyMapHandle} LegacyMapHandle\n */\n\n/**\n * Walk `root` (and its descendants), and for every element whose computed value\n * for a mapped property equals a `raw` in the legacyMap, override that element's\n * INLINE style for that property to `var(--<cssVar>, <raw>)`. Returns a handle\n * that `clearLegacyMap` uses to restore the original inline values.\n *\n * Non-destructive: only inline `element.style[prop]` is touched, and the prior\n * inline value (often empty) is captured so it can be restored exactly.\n *\n * @param {Element|Document|null} [root=document.body] subtree to remap\n * @param {LegacyMapRow[]} legacyMap the report's `auto` rows\n * @returns {LegacyMapHandle}\n */\nexport const applyLegacyMap = (root, legacyMap) => {\n /** @type {Array<{ el: HTMLElement, prop: string, prev: string }>} */\n const restores = []\n const handle = { restores }\n\n if (typeof document === 'undefined') return handle\n const start = root ?? document.body\n if (!start || !Array.isArray(legacyMap) || legacyMap.length === 0) return handle\n\n const idx = indexLegacyMap(legacyMap)\n if (idx.size === 0) return handle\n\n // Properties we care about, kebab-cased \u2014 used both to read computed style and\n // to write inline style (kebab works with CSSStyleDeclaration.setProperty).\n const props = Array.from(idx.keys())\n\n const getView = () => {\n const doc = start.ownerDocument || (start.nodeType === 9 ? start : document)\n return (doc.defaultView || (typeof window !== 'undefined' ? window : null))\n }\n const view = getView()\n if (!view || typeof view.getComputedStyle !== 'function') return handle\n\n /** @param {Element} el */\n const visit = (el) => {\n if (!el || el.nodeType !== 1) return\n const cs = view.getComputedStyle(el)\n for (const prop of props) {\n const computed = cs.getPropertyValue(prop)\n const override = computeLegacyOverride(prop, computed, idx)\n if (override == null) continue\n // capture prior inline value (kebab-safe) so restore is exact\n const prev = el.style.getPropertyValue(prop)\n restores.push({ el: /** @type {HTMLElement} */ (el), prop, prev })\n el.style.setProperty(prop, override)\n }\n }\n\n // include `start` itself if it's an element, plus all descendant elements\n if (start.nodeType === 1) visit(/** @type {Element} */ (start))\n const all = start.querySelectorAll ? start.querySelectorAll('*') : []\n for (const el of all) visit(el)\n\n return handle\n}\n\n/**\n * Restore every inline style override recorded by `applyLegacyMap`, returning\n * each element to its original (usually empty) inline value.\n * @param {LegacyMapHandle|null} handle\n * @returns {void}\n */\nexport const clearLegacyMap = (handle) => {\n if (!handle || !Array.isArray(handle.restores)) return\n for (const { el, prop, prev } of handle.restores) {\n if (!el || !el.style) continue\n if (prev === '' || prev == null) el.style.removeProperty(prop)\n else el.style.setProperty(prop, prev)\n }\n handle.restores = []\n}\n\nexport { normalizeProp }\n", "import React from 'react'\nimport { usePreviewState } from './hooks'\n\n/**\n * Drop-in banner that appears at the bottom of the screen when a\n * Sorb preview is active. Includes an \"Exit preview\" button.\n *\n * Only renders when preview.enabled is true AND a preview is loaded.\n * Safe to include unconditionally \u2014 renders nothing in production.\n *\n * @example\n * // In your app root, after <SorbProvider>\n * <PreviewBanner />\n */\nexport const PreviewBanner = () => {\n const { isPreview, previewId, previewMismatch, clearPreview } = usePreviewState()\n if (!isPreview) return null\n\n // B4: on a vocabulary mismatch the preview is active but likely re-skins\n // nothing \u2014 warn the viewer instead of showing a normal \"live\" banner. The\n // warning colours are token-bindable (`--sorb-preview-warning-*`) with amber\n // fallbacks so a consumer can theme them (e.g. to its own --bs-warning).\n const background = previewMismatch\n ? 'var(--sorb-preview-warning-bg, #B54708)'\n : '#3B5BDB'\n const accent = previewMismatch\n ? 'var(--sorb-preview-warning-accent, #F59E0B)'\n : 'transparent'\n\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n style={{\n position: 'fixed',\n bottom: 0,\n left: 0,\n right: 0,\n background,\n borderTop: `3px solid ${accent}`,\n color: '#fff',\n padding: '10px 20px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '12px',\n fontSize: '13px',\n lineHeight: '1.4',\n zIndex: 99999,\n fontFamily:\n 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n boxShadow: '0 -2px 12px rgba(0,0,0,0.15)',\n }}\n >\n <span>\n <strong style={{ fontWeight: 600 }}>\n {previewMismatch ? 'Sorb preview active \u2014 may not re-skin' : 'Sorb preview active'}\n </strong>\n {previewId && (\n <code\n style={{\n marginLeft: '8px',\n opacity: 0.75,\n fontSize: '11px',\n background: 'rgba(255,255,255,0.15)',\n padding: '2px 6px',\n borderRadius: '4px',\n }}\n >\n {previewId}\n </code>\n )}\n <span style={{ marginLeft: '8px', opacity: 0.75, fontSize: '12px' }}>\n {previewMismatch\n ? 'No matching tokens for this app \u2014 colours may be unchanged'\n : 'Token changes from Figma are live'}\n </span>\n </span>\n <button\n onClick={clearPreview}\n style={{\n flexShrink: 0,\n background: 'rgba(255,255,255,0.2)',\n border: '1px solid rgba(255,255,255,0.3)',\n color: '#fff',\n padding: '5px 14px',\n borderRadius: '6px',\n cursor: 'pointer',\n fontSize: '12px',\n fontWeight: 500,\n transition: 'background 0.15s',\n }}\n onMouseEnter={(e) =>\n (e.target.style.background = 'rgba(255,255,255,0.3)')\n }\n onMouseLeave={(e) =>\n (e.target.style.background = 'rgba(255,255,255,0.2)')\n }\n >\n Exit preview\n </button>\n </div>\n )\n}\n", "import { useTokenContext } from './context'\n\n/**\n * Returns the full active token set (committed or preview).\n * @returns {import('./types').TokenSet}\n */\nexport const useTokens = () => {\n return useTokenContext().tokens\n}\n\n/**\n * Returns a single token value by key.\n *\n * @param {string} key\n * @returns {string}\n * @example\n * const primary = useToken('color-primary') // \u2192 '#3B5BDB'\n */\nexport const useToken = (key) => {\n const tokens = useTokenContext().tokens\n const value = tokens[key]\n if (value === undefined && process.env.NODE_ENV === 'development') {\n console.warn(`[Sorb] Token not found: \"${key}\"`)\n }\n return String(value ?? '')\n}\n\n/**\n * Returns whether a preview token set is currently active.\n * Useful for showing a preview indicator in your app.\n * @returns {boolean}\n */\nexport const useIsPreview = () => {\n return useTokenContext().isPreview\n}\n\n/**\n * Returns full preview state \u2014 useful for building a preview banner.\n *\n * `previewMismatch` is true when a preview loaded but its tokens don't match the\n * app's `preview.expectPrefixes` (vocabulary mismatch \u2014 see B4); use it to render\n * a warning state. Always false unless the guard is opted into.\n *\n * @example\n * const { isPreview, previewId, previewMismatch, clearPreview } = usePreviewState()\n */\nexport const usePreviewState = () => {\n const { isPreview, previewId, previewMismatch, clearPreview } = useTokenContext()\n return { isPreview, previewId, previewMismatch, clearPreview }\n}\n\n/**\n * Real-dark-mode (spec D3): the manual mode selection + the live-resolved\n * scheme actually in effect.\n *\n * `mode` is meaningful for every app; `setMode('light'|'dark')` always\n * works. It only visibly changes anything once the consumer's `SorbConfig`\n * carries a `darkTokens` set (otherwise there's no dark stylesheet for the\n * attribute toggle to select).\n *\n * @returns {{ mode: 'auto'|'light'|'dark', setMode: (mode: 'auto'|'light'|'dark') => void, resolvedScheme: 'light'|'dark' }}\n * @example\n * const { mode, setMode, resolvedScheme } = useTheme()\n */\nexport const useTheme = () => {\n const { mode, setMode, resolvedScheme } = useTokenContext()\n return { mode, setMode, resolvedScheme }\n}\n", "import React from 'react'\nimport { useTheme } from './hooks'\n\nconst OPTIONS = [\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n { value: 'auto', label: 'Auto' },\n]\n\n/**\n * Drop-in Light / Dark / Auto mode toggle (real-dark-mode spec D3).\n *\n * Purely a thin `useTheme()` view \u2014 three buttons that call `setMode`, with\n * the active one highlighted. Renders unconditionally (safe even in a\n * single-mode app, where `setMode` still works but has nothing to visibly\n * toggle since there's no injected dark stylesheet).\n *\n * Unstyled beyond minimal inline layout \u2014 bring your own CSS/className to\n * match your app, same philosophy as `PreviewBanner`.\n *\n * @param {{ className?: string }} [props]\n * @example\n * // In your app root, alongside <PreviewBanner>\n * <ThemeToggle />\n */\nexport const ThemeToggle = ({ className } = {}) => {\n const { mode, setMode } = useTheme()\n\n return (\n <div\n role=\"radiogroup\"\n aria-label=\"Color mode\"\n className={className}\n style={{\n display: 'inline-flex',\n gap: '4px',\n fontFamily:\n 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n fontSize: '13px',\n }}\n >\n {OPTIONS.map(({ value, label }) => {\n const active = mode === value\n return (\n <button\n key={value}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n onClick={() => setMode(value)}\n style={{\n padding: '4px 10px',\n borderRadius: '6px',\n border: '1px solid rgba(0,0,0,0.15)',\n background: active ? 'var(--sorb-theme-toggle-active-bg, #3B5BDB)' : 'transparent',\n color: active ? '#fff' : 'inherit',\n cursor: 'pointer',\n fontWeight: active ? 600 : 400,\n }}\n >\n {label}\n </button>\n )\n })}\n </div>\n )\n}\n", "// verify.js \u2014 RUNNING-APP token verification (e2e-fix W2).\n//\n// Reports the values the running app ACTUALLY resolved for a set of tokens (read\n// off `:root` \u2014 where SorbProvider's applyTokens wrote the committed/preview\n// values) to the bridge's `POST /verify/app`, which diffs them against the\n// committed resolved map. This is what makes \"verify-before-merge in your running\n// app\" true in code: it asserts the live DOM resolves to the bound token values,\n// not Figma-side geometry.\n//\n// SSR-safe: no DOM \u2192 returns a clear `{ ok:false, reason:'no-dom' }` rather than\n// throwing (safe to call from a server-rendered component's effect). `fetch` is\n// injectable for tests.\n\nimport { bridgeHeaders } from './bridgeAuth.js'\n\n/** Normalize a token name to a `--cssVar`. */\nconst toCssVar = (name) => {\n const s = String(name).trim()\n return s.startsWith('--') ? s : `--${s}`\n}\n\n/**\n * Read each token's resolved value off `:root` and ask the bridge whether the\n * running app matches the committed resolved map.\n *\n * Precondition: call from inside a mounted `<SorbProvider>` \u2014 it applies the\n * resolved token literals onto `:root`. Without it, custom props read back as\n * `var(...)` refs (outputReferences css) and the result is `{ ok:false,\n * reason:'provider-not-applied' }` rather than a misleading mismatch.\n *\n * @param {string[]} tokens Token names or `--cssVar`s to check (e.g. `'button-primary-bg-default'`).\n * @param {{ origin?: string, key?: string, fetch?: typeof globalThis.fetch }} [opts]\n * `key` is the hosted-bridge bearer key (`config.preview.key`). Omit for the\n * no-auth localhost bridge \u2014 no `Authorization` header is then sent.\n * @returns {Promise<{ok:boolean, reason?:string, checked?:number, matched?:number, mismatches?:Array<{cssVar:string,expected:any,got:any}>, unknown?:string[], error?:string}>}\n */\nexport const verifyResolved = async (tokens, { origin = 'http://localhost:7777', key, fetch: fetchImpl } = {}) => {\n if (typeof document === 'undefined' || !document.documentElement) {\n return { ok: false, reason: 'no-dom' }\n }\n if (!Array.isArray(tokens) || tokens.length === 0) {\n return { ok: false, reason: 'no-tokens' }\n }\n const cs = getComputedStyle(document.documentElement)\n /** @type {Record<string,string>} */\n const values = {}\n for (const t of tokens) {\n const cssVar = toCssVar(t)\n values[cssVar] = cs.getPropertyValue(cssVar).trim()\n }\n // Precondition: SorbProvider must have applied the resolved literals onto :root.\n // `variables.css` is built with outputReferences, so an un-applied custom prop\n // reads back as a `var(--\u2026)` reference, not a value \u2014 verifying that is\n // meaningless. Detect it and say so plainly instead of reporting false mismatches.\n const unapplied = Object.entries(values)\n .filter(([, v]) => v.startsWith('var('))\n .map(([k]) => k)\n if (unapplied.length) return { ok: false, reason: 'provider-not-applied', unapplied }\n const f = fetchImpl || (typeof fetch !== 'undefined' ? fetch : globalThis.fetch)\n if (typeof f !== 'function') return { ok: false, reason: 'no-fetch' }\n const base = String(origin).replace(/\\/+$/, '')\n try {\n const res = await f(`${base}/verify/app`, {\n method: 'POST',\n // Hosted bridge needs the bearer key; localhost (no key) sends no header.\n headers: bridgeHeaders(key, { 'Content-Type': 'application/json' }),\n body: JSON.stringify({ values }),\n })\n if (!res.ok) {\n let detail = ''\n try {\n const b = await res.json()\n detail = b && b.error ? b.error : ''\n } catch (e) {\n void e\n }\n return { ok: false, reason: 'bridge-error', error: `${res.status}${detail ? ` \u2014 ${detail}` : ''}` }\n }\n return await res.json()\n } catch (e) {\n // Bridge not running / network error \u2014 never throw into the app.\n return { ok: false, reason: 'bridge-unreachable', error: e && e.message }\n }\n}\n", "/**\n * Reference `darkMode` conventions (real-dark-mode spec P2a) for\n * TargetAdapters beyond `react-bootstrap`. The connectors roadmap builds the\n * full adapters (Tailwind, a generic `data-theme` host, \u2026) later \u2014 this file\n * only defines the *convention* shape so `buildModeStylesheet`\n * (`modeStylesheet.js`) and `SorbProvider`'s `setMode` (`TokenProvider.jsx`)\n * already know how to drive them once those adapters land and pass one of\n * these (or an equivalent) as `config.darkModeConvention` /\n * `TargetAdapter.darkMode`.\n *\n * Not wired into the `@sorb/core` connector registry \u2014 these are plain data,\n * exported for adapters to import/spread, not registered TargetAdapters\n * themselves (this repo owns react-bootstrap's registration only).\n */\n\n/**\n * Tailwind's `darkMode: 'class'` convention \u2014 a `.dark` class toggled on\n * `documentElement` (typically `<html>`). Tailwind has no canonical \"light\"\n * class (light is just the absence of `.dark`), so `lightSelector` is\n * omitted: a manual \"light\" choice cannot out-rank an OS dark preference\n * under this convention (see `modeAction.js`'s `resolveModeAction`) \u2014 a\n * known limitation of class-only theming without a light marker.\n *\n * @type {import('@sorb/core').DarkModeConvention}\n */\nexport const tailwindDarkMode = {\n strategy: 'class',\n darkSelector: '.dark',\n}\n\n/**\n * A generic `[data-theme=\"...\"]` attribute convention \u2014 the same shape as\n * `react-bootstrap`'s `data-bs-theme` but under the more common\n * `data-theme` attribute name, for hosts that don't use Bootstrap's specific\n * convention.\n *\n * @type {import('@sorb/core').DarkModeConvention}\n */\nexport const dataThemeDarkMode = {\n strategy: 'attribute',\n attribute: 'data-theme',\n darkSelector: '[data-theme=\"dark\"]',\n lightSelector: '[data-theme=\"light\"]',\n}\n", "/**\n * The `mantine` TargetAdapter \u2014 Sorb's Mantine v7 framework target\n * (framework-targets-productization T2, the react-bootstrap pattern's second\n * promotion). Descriptive re-cast of the P2 spike (`sorb-demo-mantine/sd/\n * mantine-format.js`), now backed by the promoted `@sorb/seed` format\n * `sorb/mantine-vars` (`sorbMantineVars`).\n *\n * Non-React-specific host: Mantine's live preview is pure CSS (the\n * `sorb/mantine-vars` `:root { --mantine-*: var(--token) !important }`\n * override layer) + `sorbInit`/`applyTokens` swapping the underlying Sorb\n * vars \u2014 no adapter-level `inject` needed (field-correction: non-React\n * targets need no `inject`; that seam stays deferred to leaf-core).\n */\nimport * as core from '@sorb/core'\n\n// The Style-Dictionary format id that emits this target's token set, from\n// `@sorb/seed`'s named-format registry (`sorb-seed/src/emit/sorbMantine.js`):\n// export const SORB_MANTINE_VARS = 'sorb/mantine-vars'\n// Inlined as a string (not imported) so `@sorb/leaf` doesn't take a\n// build-time dependency on `@sorb/seed` \u2014 the format id is a stable,\n// documented string contract, not a JS binding (same posture as\n// `reactBootstrap.js`'s `SORB_TOKENSET_FORMAT_ID`).\nconst SORB_MANTINE_VARS_FORMAT_ID = 'sorb/mantine-vars'\n\n/**\n * @type {import('@sorb/core').TargetAdapter}\n */\nexport const mantineTarget = {\n id: 'mantine',\n emitFormat: SORB_MANTINE_VARS_FORMAT_ID,\n // Kit-vocab expectPrefixes (field-correction, non-negotiable): the\n // payload-side kit namespace, NEVER the framework's own `mantine-`\n // var prefix \u2014 a framework-prefix guard false-positives on every working\n // preview (verified P2/P3 across the demo program). Overridable via\n // `config.preview.expectPrefixes`.\n expectPrefixes: ['color-', 'button-', 'radius-'],\n // Left undefined on purpose \u2014 see file header.\n inject: undefined,\n // CONVENTION-DECLARED, NOT demo-verified \u2014 the Mantine JJ demo never built\n // dark mode (acid-wash is a variant push, not a mode). Mantine v7's\n // documented color-scheme convention sets a `data-mantine-color-scheme`\n // attribute (MantineProvider manages it; `useMantineColorScheme` /\n // `<ColorSchemeScript>` toggle it). Feeds the real-dark-mode program's D1\n // phase; verification lands there, not here.\n darkMode: {\n strategy: 'attribute',\n attribute: 'data-mantine-color-scheme',\n darkSelector: '[data-mantine-color-scheme=\"dark\"]',\n lightSelector: '[data-mantine-color-scheme=\"light\"]',\n },\n}\n\n// Register into the @sorb/core registry WHEN this build's core supports it \u2014\n// see reactBootstrap.js for the full rationale (published-core lag guard).\nif (typeof core.registerTarget === 'function') {\n core.registerTarget(mantineTarget)\n}\n\nexport default mantineTarget\n", "/**\n * The `tailwind-v4` TargetAdapter \u2014 framework-targets-productization T1(A):\n * plain Tailwind v4 utilities theming through Sorb's `@theme inline` format\n * (`sorb/tailwind-theme`, `@sorb/seed`), with NO shadcn semantic-var layer.\n * (For shadcn/ui's component vocabulary, see `./shadcn.js`.)\n *\n * Non-React target: live preview is pure CSS (the runtime var-swap re-themes\n * `@theme inline` utilities with zero Tailwind-specific bridge code) + a\n * `variables.css`/`sorbInit` var-chain \u2014 no adapter-level `inject` needed.\n * `inject` is left undefined per the same rationale as `reactBootstrap.js`'s\n * header (the seam is deferred to a future leaf-core/emit split).\n */\nimport * as core from '@sorb/core'\nimport { tailwindDarkMode } from '../darkModeConventions.js'\n\n// The Style-Dictionary format id that emits this target's token set\n// (`@sorb/seed`'s `SORB_TAILWIND`). Inlined as a string (not imported) so\n// `@sorb/leaf` doesn't take a build-time dependency on `@sorb/seed` \u2014 the\n// format id is a stable, documented string contract, not a JS binding.\nconst SORB_TAILWIND_FORMAT_ID = 'sorb/tailwind-theme'\n\n/**\n * @type {import('@sorb/core').TargetAdapter}\n */\nexport const tailwindV4Target = {\n id: 'tailwind-v4',\n emitFormat: SORB_TAILWIND_FORMAT_ID,\n // Payload-side KIT vocabulary (framework-targets-productization field-\n // correction), never a framework var prefix \u2014 a plain Sorb kit's own\n // token-family prefixes, matching what `@theme inline` references.\n expectPrefixes: ['color-', 'radius-', 'space-', 'font-'],\n // Left undefined on purpose \u2014 see file header.\n inject: undefined,\n // CONVENTION-DECLARED, not demo-verified (the JJ demos never built dark\n // mode): Tailwind's documented `darkMode: 'class'` convention \u2014 a `.dark`\n // class toggled on `documentElement`. Feeds the real-dark-mode program's D1\n // phase; verification lands there.\n darkMode: tailwindDarkMode,\n}\n\n// Register into the @sorb/core registry WHEN this build's core supports it \u2014\n// same feature-detect rationale as `reactBootstrap.js` (published core can\n// lag the connector contract across the polyrepo's publish order).\nif (typeof core.registerTarget === 'function') {\n core.registerTarget(tailwindV4Target)\n}\n\nexport default tailwindV4Target\n", "/**\n * The `shadcn` TargetAdapter \u2014 framework-targets-productization T1(A):\n * Tailwind v4 + shadcn/ui's component vocabulary, themed through Sorb's\n * `sorb/shadcn-theme` format (`@sorb/seed`) \u2014 the `:root{}` shadcn-var\u2192role\n * map + `@theme inline{}` Tailwind-utility bindings. (For plain Tailwind\n * utilities with no shadcn layer, see `./tailwindV4.js`.)\n *\n * Non-React target: live preview is pure CSS (the runtime var-swap re-themes\n * shadcn components \u2014 `bg-primary`, `text-foreground`, `border-input`, \u2026 \u2014\n * with zero shadcn-specific bridge code) + a `variables.css`/`sorbInit`\n * var-chain \u2014 no adapter-level `inject` needed. `inject` is left undefined\n * per the same rationale as `reactBootstrap.js`'s header (the seam is\n * deferred to a future leaf-core/emit split).\n */\nimport * as core from '@sorb/core'\nimport { tailwindDarkMode } from '../darkModeConventions.js'\n\n// The Style-Dictionary format id that emits this target's token set\n// (`@sorb/seed`'s `SORB_SHADCN`). Inlined as a string (not imported) so\n// `@sorb/leaf` doesn't take a build-time dependency on `@sorb/seed` \u2014 the\n// format id is a stable, documented string contract, not a JS binding.\nconst SORB_SHADCN_FORMAT_ID = 'sorb/shadcn-theme'\n\n/**\n * @type {import('@sorb/core').TargetAdapter}\n */\nexport const shadcnTarget = {\n id: 'shadcn',\n emitFormat: SORB_SHADCN_FORMAT_ID,\n // Payload-side KIT vocabulary (framework-targets-productization field-\n // correction), never a framework/shadcn var prefix \u2014 shadcn's own vars\n // (`--background`, `--primary`, \u2026) are the OUTPUT of this format, not the\n // guarded payload; the guard is against the underlying Sorb kit vocab the\n // format's :root map references.\n expectPrefixes: ['color-', 'radius-', 'space-', 'font-'],\n // Left undefined on purpose \u2014 see file header.\n inject: undefined,\n // CONVENTION-DECLARED, not demo-verified (the JJ demos never built dark\n // mode): shadcn ships on top of Tailwind's `darkMode: 'class'` convention\n // (a `.dark` class toggled on `documentElement`, per shadcn/ui's own\n // docs). Feeds the real-dark-mode program's D1 phase; verification lands\n // there.\n darkMode: tailwindDarkMode,\n}\n\n// Register into the @sorb/core registry WHEN this build's core supports it \u2014\n// same feature-detect rationale as `reactBootstrap.js` (published core can\n// lag the connector contract across the polyrepo's publish order).\nif (typeof core.registerTarget === 'function') {\n core.registerTarget(shadcnTarget)\n}\n\nexport default shadcnTarget\n", "/**\n * The `primevue` TargetAdapter \u2014 Sorb's PrimeVue v4 framework target\n * (framework-targets-productization T4, the react-bootstrap pattern's fourth\n * promotion, and the first backed by a JS-EMITTING format). Descriptive\n * re-cast of the P4/P4a spike (`sorb-demo-primevue/src/jjPreset.js`), now\n * backed by the promoted `@sorb/seed` format `sorb/primevue-preset`\n * (`sorbPrimevuePreset`).\n *\n * Yes, this lives in `sorb-leaf` even though PrimeVue is a Vue component kit\n * (per the productization spec's pattern-fidelity decision) \u2014 the adapter is\n * pure descriptive data (`id`/`emitFormat`/`expectPrefixes`/`darkMode`)\n * importing only `@sorb/core`, not a React or Vue integration; it doesn't run\n * inside a Vue app. Revisit its home if/when a leaf-core package split lands.\n *\n * Non-React-specific host: PrimeVue's live preview is pure `var()`-chain (the\n * generated preset's `--p-*` custom properties each verbatim-indirect onto a\n * Sorb CSS var) + `sorbInit`/`applyTokens` swapping the underlying Sorb vars \u2014\n * no adapter-level `inject` needed (field-correction: non-React targets need\n * no `inject`; that seam stays deferred to leaf-core).\n */\nimport * as core from '@sorb/core'\n\n// The Style-Dictionary format id that emits this target's token set, from\n// `@sorb/seed`'s named-format registry (`sorb-seed/src/emit/sorbPrimevue.js`):\n// export const SORB_PRIMEVUE_PRESET = 'sorb/primevue-preset'\n// Inlined as a string (not imported) so `@sorb/leaf` doesn't take a\n// build-time dependency on `@sorb/seed` \u2014 the format id is a stable,\n// documented string contract, not a JS binding (same posture as\n// `reactBootstrap.js`'s `SORB_TOKENSET_FORMAT_ID`).\nconst SORB_PRIMEVUE_PRESET_FORMAT_ID = 'sorb/primevue-preset'\n\n/**\n * @type {import('@sorb/core').TargetAdapter}\n */\nexport const primevueTarget = {\n id: 'primevue',\n emitFormat: SORB_PRIMEVUE_PRESET_FORMAT_ID,\n // Kit-vocab expectPrefixes (field-correction, non-negotiable): the\n // payload-side kit namespace, NEVER a PrimeVue-owned prefix (`p-`) \u2014 a\n // framework-prefix guard false-positives on every working preview\n // (verified P2/P3 across the demo program). This target's preset draws\n // from a wider slice of the kit vocab than Mantine/MUI (component-tier\n // overrides for Tag/Toast/Menubar), hence the longer list. Overridable via\n // `config.preview.expectPrefixes`.\n expectPrefixes: ['color-', 'button-', 'card-', 'badge-', 'input-', 'nav-', 'toast-', 'radius-'],\n // Left undefined on purpose \u2014 see file header.\n inject: undefined,\n // CONVENTION-DECLARED, NOT demo-verified \u2014 the PrimeVue JJ demo never\n // built dark mode (acid-wash is a variant push, not a mode). PrimeVue v4's\n // documented dark-mode convention is a `.p-dark` selector class (default\n // `darkModeSelector` in `definePreset`/PrimeVue config), toggled on an\n // ancestor (typically `<html>`). Feeds the real-dark-mode program's D1\n // phase; verification lands there, not here.\n darkMode: {\n strategy: 'class',\n darkSelector: '.p-dark',\n },\n}\n\n// Register into the @sorb/core registry WHEN this build's core supports it \u2014\n// see reactBootstrap.js for the full rationale (published-core lag guard).\nif (typeof core.registerTarget === 'function') {\n core.registerTarget(primevueTarget)\n}\n\nexport default primevueTarget\n", "/**\n * The `mui` TargetAdapter \u2014 Sorb's MUI v6 framework target\n * (framework-targets-productization T3, the react-bootstrap pattern's third\n * promotion). Descriptive re-cast of the P3 spike (`sorb-demo-mui/sd.config.js:18-86`),\n * now backed by the promoted `@sorb/seed` format `sorb/mui-vars`\n * (`sorbMuiVars`).\n *\n * Non-React-specific host: MUI's live preview is pure CSS (the\n * `sorb/mui-vars` `:root, [data-mui-color-scheme] { --mui-*: var(--token,\n * seed) !important }` override layer) + `sorbInit`/`applyTokens` swapping the\n * underlying Sorb vars \u2014 no adapter-level `inject` needed (field-correction:\n * non-React targets need no `inject`; that seam stays deferred to leaf-core).\n */\nimport * as core from '@sorb/core'\n\n// The Style-Dictionary format id that emits this target's token set, from\n// `@sorb/seed`'s named-format registry (`sorb-seed/src/emit/sorbMui.js`):\n// export const SORB_MUI_VARS = 'sorb/mui-vars'\n// Inlined as a string (not imported) so `@sorb/leaf` doesn't take a\n// build-time dependency on `@sorb/seed` \u2014 the format id is a stable,\n// documented string contract, not a JS binding (same posture as\n// `reactBootstrap.js`'s `SORB_TOKENSET_FORMAT_ID` / `mantine.js`'s\n// `SORB_MANTINE_VARS_FORMAT_ID`).\nconst SORB_MUI_VARS_FORMAT_ID = 'sorb/mui-vars'\n\n/**\n * @type {import('@sorb/core').TargetAdapter}\n */\nexport const muiTarget = {\n id: 'mui',\n emitFormat: SORB_MUI_VARS_FORMAT_ID,\n // Kit-vocab expectPrefixes (field-correction, non-negotiable): the\n // payload-side kit namespace, NEVER the framework's own `mui-` var\n // prefix \u2014 a framework-prefix guard false-positives on every working\n // preview (verified P2/P3 across the demo program). Overridable via\n // `config.preview.expectPrefixes`.\n expectPrefixes: ['color-', 'radius-'],\n // Left undefined on purpose \u2014 see file header.\n inject: undefined,\n // CONVENTION-DECLARED, NOT demo-verified \u2014 the MUI JJ demo never built\n // dark mode (acid-wash is a variant push, not a mode). MUI v6's documented\n // `cssVariables: { colorSchemeSelector: 'data' }` convention sets a\n // `data-mui-color-scheme` attribute (`InitColorSchemeScript` / MUI's\n // `ThemeProvider` manage it). Feeds the real-dark-mode program's D1 phase;\n // verification lands there, not here.\n darkMode: {\n strategy: 'attribute',\n attribute: 'data-mui-color-scheme',\n darkSelector: '[data-mui-color-scheme=\"dark\"]',\n lightSelector: '[data-mui-color-scheme=\"light\"]',\n },\n}\n\n// Register into the @sorb/core registry WHEN this build's core supports it \u2014\n// see reactBootstrap.js for the full rationale (published-core lag guard).\nif (typeof core.registerTarget === 'function') {\n core.registerTarget(muiTarget)\n}\n\nexport default muiTarget\n", "/**\n * The `angular-material` TargetAdapter \u2014 Sorb's Angular Material 20 (M3)\n * framework target (framework-targets-productization T5, the react-bootstrap\n * pattern's fifth promotion). Descriptive re-cast of the demo integration\n * (`sorb-demo-angular/sd.config.js:96-113`), now backed by the promoted\n * `@sorb/seed` format `sorb/mat-sys-vars` (`sorbMatSysVars`).\n *\n * Yes, this lives in `sorb-leaf` even though Angular Material is an Angular\n * component kit (per the productization spec's pattern-fidelity decision) \u2014\n * the adapter is pure descriptive data (`id`/`emitFormat`/`expectPrefixes`/\n * `darkMode`) importing only `@sorb/core`; it doesn't run inside an Angular\n * app. Revisit its home if/when a leaf-core package split lands.\n *\n * Non-React-specific host: Angular Material's live preview is pure\n * `var()`-chain (the `sorb/mat-sys-vars` `:root { --mat-sys-*:\n * var(--token) !important }` override layer) + `sorbInit`/`applyTokens`\n * swapping the underlying Sorb vars \u2014 no adapter-level `inject` needed\n * (field-correction: non-React targets need no `inject`; that seam stays\n * deferred to leaf-core).\n *\n * DARK MODE \u2014 CONVENTION-DECLARED, UNCONFIRMED (spec risk table: \"Angular M3\n * dark convention unconfirmed\"): Angular Material 20's `mat.theme()` mixin\n * does NOT emit a fixed class/attribute selector the way Bootstrap\n * (`data-bs-theme`) or Mantine (`data-mantine-color-scheme`) do. Per the\n * Angular Material 20 docs (material.angular.dev/guide/theming +\n * angular/components `guides/theming.md`), `mat.theme()`'s color values use\n * the CSS `light-dark()` function and switch on the `color-scheme` CSS\n * property \u2014 there is no single canonical class or attribute name; apps\n * commonly toggle a class on `<html>`/`<body>` (naming varies:\n * `.dark-theme`, `.theme-dark`, \u2026) that itself sets `color-scheme: dark`.\n * Per the productization spec's mitigation (\"if ambiguous, declare\n * strategy:'class' with a header caveat\"), this adapter declares a `.dark`\n * class selector (matching this codebase's other class-strategy convention,\n * `tailwindDarkMode` in `darkModeConventions.js`) as the best-known default \u2014\n * a consumer whose app uses a different class name overrides via\n * `config.darkModeConvention` (real-dark-mode program, not this phase).\n * UNCONFIRMED: verification is explicitly out of scope here and belongs to\n * the real-dark-mode program (`spec/sorb/dark-mode-real-implementation.md`,\n * D1); this declaration only feeds that program.\n */\nimport * as core from '@sorb/core'\n\n// The Style-Dictionary format id that emits this target's token set, from\n// `@sorb/seed`'s named-format registry (`sorb-seed/src/emit/sorbMatSys.js`):\n// export const SORB_MAT_SYS_VARS = 'sorb/mat-sys-vars'\n// Inlined as a string (not imported) so `@sorb/leaf` doesn't take a\n// build-time dependency on `@sorb/seed` \u2014 the format id is a stable,\n// documented string contract, not a JS binding (same posture as\n// `reactBootstrap.js`'s `SORB_TOKENSET_FORMAT_ID`).\nconst SORB_MAT_SYS_VARS_FORMAT_ID = 'sorb/mat-sys-vars'\n\n/**\n * @type {import('@sorb/core').TargetAdapter}\n */\nexport const angularMaterialTarget = {\n id: 'angular-material',\n emitFormat: SORB_MAT_SYS_VARS_FORMAT_ID,\n // Kit-vocab expectPrefixes (field-correction, non-negotiable): the\n // payload-side kit namespace, NEVER Angular Material's own `mat-sys-`\n // var prefix \u2014 a framework-prefix guard false-positives on every working\n // preview (verified P2/P3 across the demo program). Overridable via\n // `config.preview.expectPrefixes`.\n expectPrefixes: ['color-', 'radius-'],\n // Left undefined on purpose \u2014 see file header. Non-React (Angular) target;\n // the leaf-core inject seam stays deferred.\n inject: undefined,\n // CONVENTION-DECLARED + UNCONFIRMED \u2014 see file header \"DARK MODE\" section.\n // Best-known default given Angular Material 20's `light-dark()`/\n // `color-scheme` mechanism has no single canonical selector name.\n darkMode: {\n strategy: 'class',\n darkSelector: '.dark',\n },\n}\n\n// Register into the @sorb/core registry WHEN this build's core supports it \u2014\n// see reactBootstrap.js for the full rationale (published-core lag guard).\nif (typeof core.registerTarget === 'function') {\n core.registerTarget(angularMaterialTarget)\n}\n\nexport default angularMaterialTarget\n"],
5
+ "mappings": "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",
6
6
  "names": ["matchMediaFn", "DARK_MEDIA_QUERY", "React", "jsx", "React", "jsx"]
7
7
  }