@sorb/leaf 0.2.1 → 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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../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"],
4
+ "sourcesContent": ["/**\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"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }