@theme-registry/refract 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/dist/_createTheme-255ff48e.esm.js +2 -0
  3. package/dist/_createTheme-255ff48e.esm.js.map +1 -0
  4. package/dist/_createTheme-41c01033.cjs.js +2 -0
  5. package/dist/_createTheme-41c01033.cjs.js.map +1 -0
  6. package/dist/_errors-be768b25.cjs.js +2 -0
  7. package/dist/_errors-be768b25.cjs.js.map +1 -0
  8. package/dist/_errors-d75a5c74.esm.js +2 -0
  9. package/dist/_errors-d75a5c74.esm.js.map +1 -0
  10. package/dist/adapter-kit.cjs.js +2 -0
  11. package/dist/adapter-kit.cjs.js.map +1 -0
  12. package/dist/adapter-kit.d.ts +88 -0
  13. package/dist/adapter-kit.esm.js +2 -0
  14. package/dist/adapter-kit.esm.js.map +1 -0
  15. package/dist/build/auditCommand.d.ts +19 -0
  16. package/dist/build/buildCommand.d.ts +23 -0
  17. package/dist/build/cli.d.ts +2 -0
  18. package/dist/build/config.d.ts +58 -0
  19. package/dist/build/diff.d.ts +56 -0
  20. package/dist/build/diffCommand.d.ts +29 -0
  21. package/dist/build/emit.d.ts +20 -0
  22. package/dist/build/emitTheme.d.ts +39 -0
  23. package/dist/build/guide.d.ts +34 -0
  24. package/dist/build/importCommand.d.ts +42 -0
  25. package/dist/build/index.d.ts +33 -0
  26. package/dist/build/init.d.ts +32 -0
  27. package/dist/build/paths.d.ts +42 -0
  28. package/dist/build/skillsCommand.d.ts +53 -0
  29. package/dist/build/tokensCommand.d.ts +17 -0
  30. package/dist/build/vendor.d.ts +39 -0
  31. package/dist/build.cjs.js +2 -0
  32. package/dist/build.cjs.js.map +1 -0
  33. package/dist/build.esm.js +2 -0
  34. package/dist/build.esm.js.map +1 -0
  35. package/dist/cli.js +8250 -0
  36. package/dist/cli.js.map +1 -0
  37. package/dist/color-math.cjs.js +2 -0
  38. package/dist/color-math.cjs.js.map +1 -0
  39. package/dist/color-math.esm.js +2 -0
  40. package/dist/color-math.esm.js.map +1 -0
  41. package/dist/core/ThemeAdapter.d.ts +234 -0
  42. package/dist/core/createTheme.d.ts +96 -0
  43. package/dist/core/cssProperties.d.ts +8 -0
  44. package/dist/core/defineAdapter.d.ts +25 -0
  45. package/dist/core/derive/crossProperty.d.ts +31 -0
  46. package/dist/core/derive/index.d.ts +11 -0
  47. package/dist/core/derive/resolveTokens.d.ts +27 -0
  48. package/dist/core/errors.d.ts +24 -0
  49. package/dist/core/index.d.ts +16 -0
  50. package/dist/core/media/containers.d.ts +20 -0
  51. package/dist/core/media/defaults.d.ts +3 -0
  52. package/dist/core/media/descriptors.d.ts +12 -0
  53. package/dist/core/media/index.d.ts +11 -0
  54. package/dist/core/media/queries.d.ts +20 -0
  55. package/dist/core/model/buildModel.d.ts +116 -0
  56. package/dist/core/model/index.d.ts +14 -0
  57. package/dist/core/model/interpreted.d.ts +37 -0
  58. package/dist/core/model/mergeRuleSet.d.ts +68 -0
  59. package/dist/core/model/model.d.ts +260 -0
  60. package/dist/core/noopAdapter.d.ts +26 -0
  61. package/dist/core/normalize/index.d.ts +15 -0
  62. package/dist/core/normalize/properties.d.ts +20 -0
  63. package/dist/core/normalize/recipeResolver.d.ts +19 -0
  64. package/dist/core/normalize/recipes.d.ts +38 -0
  65. package/dist/core/normalize/responsive.d.ts +40 -0
  66. package/dist/core/normalize/types.d.ts +261 -0
  67. package/dist/core/rawTheme.d.ts +53 -0
  68. package/dist/core/ref.d.ts +13 -0
  69. package/dist/core/subsystem.d.ts +115 -0
  70. package/dist/core/types.d.ts +31 -0
  71. package/dist/core/units.d.ts +93 -0
  72. package/dist/dtcg/export.d.ts +48 -0
  73. package/dist/dtcg/import.d.ts +43 -0
  74. package/dist/dtcg/index.d.ts +21 -0
  75. package/dist/dtcg/parse.d.ts +6 -0
  76. package/dist/dtcg/types.d.ts +69 -0
  77. package/dist/dtcg.cjs.js +2 -0
  78. package/dist/dtcg.cjs.js.map +1 -0
  79. package/dist/dtcg.esm.js +2 -0
  80. package/dist/dtcg.esm.js.map +1 -0
  81. package/dist/index.cjs.js +2 -0
  82. package/dist/index.cjs.js.map +1 -0
  83. package/dist/index.d.ts +27 -0
  84. package/dist/index.esm.js +2 -0
  85. package/dist/index.esm.js.map +1 -0
  86. package/dist/subsystems/animation/index.d.ts +13 -0
  87. package/dist/subsystems/animation/recipes.d.ts +20 -0
  88. package/dist/subsystems/animation/types.d.ts +52 -0
  89. package/dist/subsystems/borders/index.d.ts +10 -0
  90. package/dist/subsystems/borders/recipes.d.ts +29 -0
  91. package/dist/subsystems/borders/types.d.ts +50 -0
  92. package/dist/subsystems/colors/audit.d.ts +67 -0
  93. package/dist/subsystems/colors/colorInput.d.ts +17 -0
  94. package/dist/subsystems/colors/index.d.ts +12 -0
  95. package/dist/subsystems/colors/keywords.d.ts +9 -0
  96. package/dist/subsystems/colors/normalize.d.ts +26 -0
  97. package/dist/subsystems/colors/recipes.d.ts +21 -0
  98. package/dist/subsystems/colors/types.d.ts +98 -0
  99. package/dist/subsystems/colors/utils.d.ts +104 -0
  100. package/dist/subsystems/components/index.d.ts +13 -0
  101. package/dist/subsystems/components/recipes.d.ts +22 -0
  102. package/dist/subsystems/components/types.d.ts +46 -0
  103. package/dist/subsystems/effects/index.d.ts +9 -0
  104. package/dist/subsystems/effects/recipes.d.ts +24 -0
  105. package/dist/subsystems/effects/types.d.ts +63 -0
  106. package/dist/subsystems/effects/utils.d.ts +57 -0
  107. package/dist/subsystems/globals/index.d.ts +21 -0
  108. package/dist/subsystems/globals/presets.d.ts +33 -0
  109. package/dist/subsystems/globals/types.d.ts +48 -0
  110. package/dist/subsystems/index.d.ts +21 -0
  111. package/dist/subsystems/layout/index.d.ts +14 -0
  112. package/dist/subsystems/layout/normalize.d.ts +35 -0
  113. package/dist/subsystems/layout/recipes.d.ts +16 -0
  114. package/dist/subsystems/layout/structural.d.ts +37 -0
  115. package/dist/subsystems/layout/types.d.ts +154 -0
  116. package/dist/subsystems/typography/index.d.ts +9 -0
  117. package/dist/subsystems/typography/normalize.d.ts +17 -0
  118. package/dist/subsystems/typography/recipes.d.ts +21 -0
  119. package/dist/subsystems/typography/types.d.ts +49 -0
  120. package/package.json +83 -0
  121. package/skills/adapter-scaffold/SKILL.md +85 -0
  122. package/skills/adapter-usage/SKILL.md +75 -0
  123. package/skills/build-config/SKILL.md +77 -0
  124. package/skills/colors/SKILL.md +134 -0
  125. package/skills/consuming-the-output/SKILL.md +62 -0
  126. package/skills/dtcg-import/SKILL.md +76 -0
  127. package/skills/layout/SKILL.md +65 -0
  128. package/skills/overrides-and-child-themes/SKILL.md +70 -0
  129. package/skills/recipes-and-composition/SKILL.md +110 -0
  130. package/skills/theme-authoring/SKILL.md +107 -0
  131. package/skills/theme-foundations/SKILL.md +127 -0
  132. package/skills/troubleshooting/SKILL.md +97 -0
  133. package/skills/typography/SKILL.md +66 -0
  134. package/skills/visual-effects/SKILL.md +96 -0
  135. package/src/subsystems/colors/utils.ts +299 -0
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("./_errors-be768b25.cjs.js"),r=require("./_createTheme-41c01033.cjs.js"),o=require("./color-math.cjs.js");const t=e=>{const[r,o]=e.split(":");if(!r||!o)return;const t=o.indexOf(".");return t<0?void 0:{subsystem:r,group:o.slice(0,t),variant:o.slice(t+1)}},s=(e,r)=>{var o,s,n;const i=t(r);if(i)return null===(n=null===(s=null===(o=e.subsystems[i.subsystem])||void 0===o?void 0:o.ruleSets)||void 0===s?void 0:s[i.group])||void 0===n?void 0:n[i.variant]},n=(e,r)=>{for(const[o,t]of Object.entries(r))e[o]={...t}},i=e=>{var r,o,t,s,n,i;return`${null!==(r=e.breakpoint)&&void 0!==r?r:""}|${null!==(o=e.query)&&void 0!==o?o:""}|${null!==(t=e.orientation)&&void 0!==t?t:""}|${null!==(s=e.state)&&void 0!==s?s:""}|${null!==(n=e.container)&&void 0!==n?n:""}|${null!==(i=e.size)&&void 0!==i?i:""}`};function a(e){var r;const o=[];for(const[t,s]of Object.entries(e.subsystems))for(const[e,n]of Object.entries(null!==(r=s.ruleSets)&&void 0!==r?r:{}))for(const r of Object.keys(n))o.push({subsystem:t,group:e,variant:r});return o}function l(e){return{name:e.name,version:e.version,allowedStates:e.allowedStates,bind(r,o){var t,s,n,i;const l=e.bind(r,o),p=null!==(t=l.renderAllRecipes)&&void 0!==t?t:()=>l.join(a(r).map(({subsystem:e,group:r,variant:o})=>l.renderRecipe(e,r,o))),u=null!==(s=l.renderAllVariables)&&void 0!==s?s:()=>l.join(Object.keys(r.subsystems).map(e=>l.renderVariables(e))),c=null!==(n=l.renderAll)&&void 0!==n?n:()=>l.join([u(),p()]),d=null!==(i=l.describeUsage)&&void 0!==i?i:()=>({format:e.name,summary:[`This theme was built with the "${e.name}" refract adapter.`],recipes:a(r).map(({subsystem:e,group:r,variant:o})=>({subsystem:e,group:r,variant:o,name:l.recipeName(e,r,o)}))});return{...l,renderAllRecipes:p,renderAllVariables:u,renderAll:c,describeUsage:d}}}}const p=e=>e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4),u=([e,r,o])=>.2126*p(e/255)+.7152*p(r/255)+.0722*p(o/255),c={fail:0,"AA-large":1,AA:2,AAA:3},d=2.4,v=.2126729,f=.7151522,b=.072175,m=.56,g=.57,R=.62,y=.65,S=.022,x=1.414,h=1.14,E=.027,A=1.14,T=.027,w=5e-4,M=.1,k=([e,r,o])=>v*Math.pow(e/255,d)+f*Math.pow(r/255,d)+b*Math.pow(o/255,d),_=(e,r)=>{const o=e=>e>S?e:e+Math.pow(S-e,x),t=o(k(e)),s=o(k(r));if(Math.abs(s-t)<w)return 0;let n;if(s>t){const e=(Math.pow(s,m)-Math.pow(t,g))*h;n=e<M?0:e-E}else{const e=(Math.pow(s,y)-Math.pow(t,R))*A;n=e>-M?0:e+T}return 100*n},O=(e,r)=>{const o=10**r;return Math.round(e*o)/o},C=(e,r)=>{if(void 0!==r.ref)try{return String(e.resolveToken(r.ref))}catch{return}if("string"==typeof r.value)return r.value},P="color",$=["background-color","background"],N=e=>{if(e)for(const r of $)if(e[r])return e[r]},j=(e,r,t,s,n)=>{let i,a;try{void 0!==t&&(i=o.parseColor(t).rgb)}catch{}try{void 0!==s&&(a=o.parseColor(s).rgb)}catch{}if(!i||!a)return{kind:e,label:r,fg:t,bg:s,skipped:i||a?i?"bg not a colour":"fg not a colour":"no derivable fg/bg"};const l=((e,r)=>{const o=u(e),t=u(r);return(Math.max(o,t)+.05)/(Math.min(o,t)+.05)})(i,a),p=((e,r)=>r?e>=4.5?"AAA":e>=3?"AA":"fail":e>=7?"AAA":e>=4.5?"AA":e>=3?"AA-large":"fail")(l,n.largeText),d=c[p]>=c[n.minWcag];return{kind:e,label:r,fg:t,bg:s,wcagRatio:O(l,2),wcagLevel:p,apcaLc:O(_(i,a),1),pass:d}};exports.RefractError=e.RefractError,exports.BREAKPOINT_EPSILON=r.BREAKPOINT_EPSILON,exports.CSS_UNITS=r.CSS_UNITS,exports.DEFAULT_BASE_FONT_SIZE=r.DEFAULT_BASE_FONT_SIZE,exports.DEFAULT_BREAKPOINTS=r.DEFAULT_BREAKPOINTS,exports.DEFAULT_RESPONSIVE_QUERY=r.DEFAULT_RESPONSIVE_QUERY,exports.KNOWN_CSS_PROPERTIES=r.KNOWN_CSS_PROPERTIES,exports.LENGTH_REGISTRY=r.LENGTH_REGISTRY,exports.animationSubsystem=r.animationSubsystem,exports.bakeCrossPropertyDerivations=r.bakeCrossPropertyDerivations,exports.bordersSubsystem=r.bordersSubsystem,exports.buildComponentRuleSetFromInterpreted=r.buildComponentRuleSetFromInterpreted,exports.buildContainerDescriptors=r.buildContainerDescriptors,exports.buildDerivationRegistry=r.buildDerivationRegistry,exports.buildMediaDescriptor=r.buildMediaDescriptor,exports.buildPropertiesModel=r.buildPropertiesModel,exports.buildPropertyModel=r.buildPropertyModel,exports.buildRuleSetFromInterpreted=r.buildRuleSetFromInterpreted,exports.buildRuleSetGroupFromInterpreted=r.buildRuleSetGroupFromInterpreted,exports.buildSubsystemModel=r.buildSubsystemModel,exports.buildThemeModel=r.buildThemeModel,exports.buildTokenMap=r.buildTokenMap,exports.colorsSubsystem=r.colorsSubsystem,exports.componentsSubsystem=r.componentsSubsystem,exports.containerQueryString=r.containerQueryString,exports.createRecipeVariantResolver=r.createRecipeVariantResolver,exports.createTheme=r.createTheme,exports.effectsSubsystem=r.effectsSubsystem,exports.extractComponentReferences=r.extractComponentReferences,exports.formatWidth=r.formatWidth,exports.globalsSubsystem=r.globalsSubsystem,exports.isKnownCssProperty=r.isKnownCssProperty,exports.layoutSubsystem=r.layoutSubsystem,exports.mediaQuery=r.mediaQuery,exports.mediaQueryString=r.mediaQueryString,exports.normalizePropertyValue=r.normalizePropertyValue,exports.normalizeRecipeGroup=r.normalizeRecipeGroup,exports.normalizeResponsiveOverrides=r.normalizeResponsiveOverrides,exports.parseLength=r.parseLength,exports.pathifyProperties=r.pathifyProperties,exports.pathifyRuleSetGroup=r.pathifyRuleSetGroup,exports.resolveLengthRef=r.resolveLengthRef,exports.resolveMediaConfig=r.resolveMediaConfig,exports.resolveModelUnits=r.resolveModelUnits,exports.resolveRoleUnit=r.resolveRoleUnit,exports.resolveToken=r.resolveToken,exports.resolveTokenMap=r.resolveTokenMap,exports.sortBreakpointKeys=r.sortBreakpointKeys,exports.typographySubsystem=r.typographySubsystem,exports.validateNormalizedResponsiveRefs=r.validateNormalizedResponsiveRefs,exports.audit=(r,o={})=>{var t,s,n,i,a,l,p,u,c,d,v;const f={largeText:null!==(t=o.largeText)&&void 0!==t&&t,minWcag:null!==(s=o.minWcag)&&void 0!==s?s:"AA"},b=null===(n=o.includeRecipes)||void 0===n||n,m=[];if(null===(i=o.includePalettes)||void 0===i||i)for(const e of Object.keys(r.tokens)){const o=/^colors\.([^.]+)\.text$/.exec(e);if(!o)continue;const t=`colors.${o[1]}`;let s,n;try{s=String(r.resolveToken(e))}catch{}try{n=String(r.resolveToken(t))}catch{}m.push(j("palette",t,s,n,f))}if(b)for(const[e,o]of Object.entries(r.model.subsystems))if(o.ruleSets)for(const[t,s]of Object.entries(o.ruleSets))for(const[o,n]of Object.entries(s)){const s=n.declarations[P],i=N(n.declarations),b=`${e}.${t}.${o}`;s&&i&&m.push(j("recipe",b,C(r,s),C(r,i),f));for(const e of null!==(a=n.overrides)&&void 0!==a?a:[]){const o=null!==(p=null===(l=e.declarations)||void 0===l?void 0:l[P])&&void 0!==p?p:s,t=null!==(u=N(e.declarations))&&void 0!==u?u:i;if(!e.declarations||!e.declarations[P]&&!N(e.declarations))continue;if(!o||!t)continue;const n=null!==(v=null!==(d=null!==(c=e.state)&&void 0!==c?c:e.breakpoint)&&void 0!==d?d:e.query)&&void 0!==v?v:"override";m.push(j("recipe",`${b} (${n})`,C(r,o),C(r,t),f))}}const g=m.filter(e=>!e.skipped),R=g.filter(e=>!1===e.pass),y=g.reduce((e,r)=>{var o,t;return void 0===e||(null!==(o=r.wcagRatio)&&void 0!==o?o:1/0)<(null!==(t=e.wcagRatio)&&void 0!==t?t:1/0)?r:e},void 0),S={pairings:m,summary:{total:g.length,passed:g.length-R.length,failed:R.length,skipped:m.length-g.length,worst:y},ok:0===R.length};if(o.strict&&R.length>0){const r=R.map(e=>`${e.label} (${e.wcagRatio}:1, ${e.wcagLevel})`).join(", ");throw new e.RefractError("REFRACT_E_AUDIT",`refract audit: ${R.length} pairing(s) fail WCAG ${f.minWcag} — ${r}. Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,R.map(e=>`${e.label} (${e.wcagRatio}:1, ${e.wcagLevel})`))}return S},exports.createNoopAdapter=function(){return l({name:"noop",version:1,bind:()=>({recipeName:()=>"",renderRecipe:()=>"",renderVariables:()=>"",join:e=>e.join(""),emit:()=>({files:{}})})})},exports.defineAdapter=l,exports.mergeComponentRuleSet=(r,o,t)=>{var a,l,p,u,c,d;const v=null===(p=null===(l=null===(a=r.subsystems.components)||void 0===a?void 0:a.ruleSets)||void 0===l?void 0:l[o])||void 0===p?void 0:p[t];if(!v)throw new e.RefractError("REFRACT_E_REFERENCE",`mergeComponentRuleSet: no component rule-set "${o}.${t}"`);const f=[];for(const o of null!==(u=v.references)&&void 0!==u?u:[]){const t=s(r,o);if(!t)throw new e.RefractError("REFRACT_E_REFERENCE",`mergeComponentRuleSet: unresolved reference "${o}"`);f.push(t)}f.push(v);const b={},m={},g=new Map;for(const e of f){n(b,e.declarations);for(const r of e.overrides)if(r.declarations)if(void 0!==r.breakpoint||void 0!==r.container){const e=i(r);let o=g.get(e);o||(o={...void 0!==r.breakpoint?{breakpoint:r.breakpoint}:{},...void 0!==r.query?{query:r.query}:{},...void 0!==r.orientation?{orientation:r.orientation}:{},...void 0!==r.state?{state:r.state}:{},...void 0!==r.container?{container:r.container}:{},...void 0!==r.size?{size:r.size}:{},declarations:{}},g.set(e,o)),n(o.declarations,r.declarations)}else void 0!==r.state?(null!==(c=m[d=r.state])&&void 0!==c||(m[d]={}),n(m[r.state],r.declarations)):n(b,r.declarations)}const R=[...g.values()],y=new Set,S=[],x=e=>{for(const r of Object.values(e))void 0===r.ref||y.has(r.ref)||(y.add(r.ref),S.push(r.ref))};x(b);for(const e of Object.values(m))x(e);for(const e of R)x(e.declarations);return{base:b,states:m,responsive:R,referencedPaths:S}},exports.parseRuleSetReference=t,exports.ref=e=>({ref:e});
2
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/core/model/mergeRuleSet.ts","../src/core/defineAdapter.ts","../src/subsystems/colors/audit.ts","../src/core/noopAdapter.ts","../src/core/ref.ts"],"sourcesContent":["/**\n * Format-neutral component merge (§9c).\n *\n * `mergeComponentRuleSet` flattens one component variant into a single\n * self-contained rule-set: its referenced recipes' declarations + its own `css`\n * delta, unioned. The result is pure Model data — declarations stay as {@link Ref}s\n * carrying `{ ref, value }` — so an adapter renders it as baked values (inline) or\n * `var(--…)` / `theme.…` (referenced) without any format decision leaking in here.\n *\n * This is the ONLY new machinery the `components` emit mode needs, shared by the CSS\n * and future SC adapters. It is **on-demand** (an adapter calls it in `emit()`), never\n * materialized on `ThemeModel` / the runtime `theme`. It does NOT mutate the authored\n * `RuleSet` / declarations — the merged view is freshly derived (Refs shallow-cloned).\n *\n * Precedence (LOCKED, §9): authored **reference order** first (later refs override\n * earlier per property key), then the component's own declarations **last / highest**\n * (`css` delta wins over subsystem recipes). Same rule per condition bucket.\n */\nimport type {\n Orientation,\n Ref,\n ResponsiveQueryKind,\n RuleSet,\n RuleSetOverride,\n ThemeModel,\n} from \"./model\";\nimport { RefractError } from \"../errors\";\n\n/**\n * One flattened conditioned bucket — a distinct `(breakpoint, query, orientation, state, container, size)`\n * key. A **viewport** entry carries `breakpoint`; a **container** entry (§10.5) carries `container` + `size`\n * (and no `breakpoint`). The adapter emits the former as `@media`, the latter as `@container`.\n */\nexport type MergedResponsiveEntry = {\n breakpoint?: string;\n query?: ResponsiveQueryKind;\n orientation?: Orientation;\n state?: string;\n container?: string;\n size?: string;\n declarations: Record<string, Ref>;\n};\n\n/**\n * A component variant flattened into one self-contained rule-set.\n *\n * - `base` — merged no-condition declarations.\n * - `states` — merged declarations keyed by `state` (no breakpoint).\n * - `responsive` — one entry per distinct `(breakpoint, query, orientation, state)` merge key.\n * - `referencedPaths` — every distinct token path (`Ref.ref`) appearing across all buckets,\n * first-appearance order. What non-inline rendering tree-shakes the vars file to.\n */\nexport type MergedRuleSet = {\n base: Record<string, Ref>;\n states: Record<string, Record<string, Ref>>;\n responsive: MergedResponsiveEntry[];\n referencedPaths: string[];\n};\n\n/** The address parts of a component reference (`\"colors:solid.primary\"`). */\nexport type RuleSetReference = { subsystem: string; group: string; variant: string };\n\n/**\n * Parse a component reference (`\"subsystem:group.variant\"`) into its address parts.\n * Format-neutral core twin of the CSS adapter's `parseComponentReference` (which stays\n * for the option-C class-list path). Returns `undefined` on a malformed reference.\n */\nexport const parseRuleSetReference = (reference: string): RuleSetReference | undefined => {\n const [subsystem, rest] = reference.split(\":\");\n if (!subsystem || !rest) return undefined;\n const dot = rest.indexOf(\".\");\n if (dot < 0) return undefined;\n return { subsystem, group: rest.slice(0, dot), variant: rest.slice(dot + 1) };\n};\n\n/** Resolve a reference to its authored `RuleSet`, or `undefined` if it doesn't address one. */\nconst resolveReference = (model: ThemeModel, reference: string): RuleSet | undefined => {\n const parsed = parseRuleSetReference(reference);\n if (!parsed) return undefined;\n return model.subsystems[parsed.subsystem]?.ruleSets?.[parsed.group]?.[parsed.variant];\n};\n\n/** Fold `source` declarations into `target` (later source wins), shallow-cloning each Ref. */\nconst mergeDeclarations = (target: Record<string, Ref>, source: Record<string, Ref>): void => {\n for (const [prop, ref] of Object.entries(source)) target[prop] = { ...ref };\n};\n\n/** Stable string key for a conditioned bucket — `(breakpoint, query, orientation, state, container, size)`. */\nconst responsiveKey = (o: RuleSetOverride): string =>\n `${o.breakpoint ?? \"\"}|${o.query ?? \"\"}|${o.orientation ?? \"\"}|${o.state ?? \"\"}|${o.container ?? \"\"}|${o.size ?? \"\"}`;\n\n/**\n * Flatten one component variant into a self-contained {@link MergedRuleSet}.\n *\n * Reads `model.subsystems.components.ruleSets[group][variant]` — its `references`\n * (resolved in authored order), own base `declarations`, and `overrides` — and unions\n * them under the locked precedence. Throws on a missing component or an unresolved reference.\n */\nexport const mergeComponentRuleSet = (\n model: ThemeModel,\n group: string,\n variant: string,\n): MergedRuleSet => {\n const own = model.subsystems.components?.ruleSets?.[group]?.[variant];\n if (!own) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: no component rule-set \"${group}.${variant}\"`);\n }\n\n // Sources in precedence order: referenced rule-sets left-to-right, then the component's own last.\n const sources: RuleSet[] = [];\n for (const reference of own.references ?? []) {\n const resolved = resolveReference(model, reference);\n if (!resolved) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: unresolved reference \"${reference}\"`);\n }\n sources.push(resolved);\n }\n sources.push(own);\n\n const base: Record<string, Ref> = {};\n const states: Record<string, Record<string, Ref>> = {};\n const responsiveByKey = new Map<string, MergedResponsiveEntry>();\n\n for (const source of sources) {\n mergeDeclarations(base, source.declarations);\n\n for (const override of source.overrides) {\n if (!override.declarations) continue;\n // A breakpoint OR container condition → a conditioned bucket (viewport → @media, container →\n // @container). Container overrides MUST route here, not fold into base (§10.5 correctness).\n if (override.breakpoint !== undefined || override.container !== undefined) {\n const key = responsiveKey(override);\n let entry = responsiveByKey.get(key);\n if (!entry) {\n entry = {\n ...(override.breakpoint !== undefined ? { breakpoint: override.breakpoint } : {}),\n ...(override.query !== undefined ? { query: override.query } : {}),\n ...(override.orientation !== undefined ? { orientation: override.orientation } : {}),\n ...(override.state !== undefined ? { state: override.state } : {}),\n ...(override.container !== undefined ? { container: override.container } : {}),\n ...(override.size !== undefined ? { size: override.size } : {}),\n declarations: {},\n };\n responsiveByKey.set(key, entry);\n }\n mergeDeclarations(entry.declarations, override.declarations);\n } else if (override.state !== undefined) {\n (states[override.state] ??= {});\n mergeDeclarations(states[override.state], override.declarations);\n } else {\n // Unconditional override (only variant/target, no breakpoint/state) — folds into base.\n mergeDeclarations(base, override.declarations);\n }\n }\n }\n\n const responsive = [...responsiveByKey.values()];\n\n // referencedPaths — every distinct token path across all buckets, first-appearance order.\n const seen = new Set<string>();\n const referencedPaths: string[] = [];\n const collect = (decls: Record<string, Ref>): void => {\n for (const ref of Object.values(decls)) {\n if (ref.ref !== undefined && !seen.has(ref.ref)) {\n seen.add(ref.ref);\n referencedPaths.push(ref.ref);\n }\n }\n };\n collect(base);\n for (const decls of Object.values(states)) collect(decls);\n for (const entry of responsive) collect(entry.declarations);\n\n return { base, states, responsive, referencedPaths };\n};\n","/**\n * `defineAdapter` — turns an `AdapterSpec` (identity + a `bind` returning the four\n * required primitives) into a full `ThemeAdapter` whose `bind` yields a complete\n * `BoundAdapter` with the DEFAULTED aggregators supplied.\n *\n * The defaults are pure Model walks: the Model enumerates every subsystem and every\n * (group, variant), so core loops it, calls the author's per-unit renderers, and\n * `join`s the results. Model/ctx are already bound, so the aggregators take no args.\n * An author can still override any aggregator (a format whose full document isn't a\n * flat concatenation).\n */\n\nimport type { ThemeModel } from \"./model\";\nimport type {\n AdapterSpec,\n ThemeAdapter,\n BoundAdapter,\n RenderContext,\n UsageDescriptor,\n} from \"./ThemeAdapter\";\n\n/** Every rule-set address in the Model — `(subsystem, group, variant)` triples. */\nfunction eachRuleSet(model: ThemeModel): Array<{ subsystem: string; group: string; variant: string }> {\n const out: Array<{ subsystem: string; group: string; variant: string }> = [];\n for (const [subsystem, sub] of Object.entries(model.subsystems)) {\n for (const [group, ruleSet] of Object.entries(sub.ruleSets ?? {})) {\n for (const variant of Object.keys(ruleSet)) {\n out.push({ subsystem, group, variant });\n }\n }\n }\n return out;\n}\n\n/**\n * Complete an `AdapterSpec` into a `ThemeAdapter`.\n *\n * Wraps the author's `bind` so the returned `BoundAdapter` gains the defaulted\n * aggregators (`renderAllRecipes` / `renderAllVariables` / `renderAll`) built from\n * the required primitives — unless the spec already provides its own override.\n * `name` / `version` pass through unchanged.\n *\n * @param spec identity (`name`/`version`) + a `bind(model, ctx)` returning the\n * required render primitives (and any optional overrides).\n * @returns a full adapter whose `bind(model, ctx)` yields a complete `BoundAdapter`.\n */\nexport function defineAdapter<TUnit>(spec: AdapterSpec<TUnit>): ThemeAdapter<TUnit> {\n return {\n name: spec.name,\n version: spec.version,\n allowedStates: spec.allowedStates,\n bind(model: ThemeModel, ctx: RenderContext): BoundAdapter<TUnit> {\n const b = spec.bind(model, ctx);\n\n const renderAllRecipes =\n b.renderAllRecipes ??\n ((): TUnit =>\n b.join(\n eachRuleSet(model).map(({ subsystem, group, variant }) =>\n b.renderRecipe(subsystem, group, variant),\n ),\n ));\n\n const renderAllVariables =\n b.renderAllVariables ??\n ((): TUnit => b.join(Object.keys(model.subsystems).map(subsystem => b.renderVariables(subsystem))));\n\n const renderAll =\n b.renderAll ?? ((): TUnit => b.join([renderAllVariables(), renderAllRecipes()]));\n\n // Generic self-documentation: the recipe identities are format-correct via `recipeName`; an\n // adapter overrides `describeUsage` to add format-specific import prose to `summary`.\n const describeUsage =\n b.describeUsage ??\n ((): UsageDescriptor => ({\n format: spec.name,\n summary: [`This theme was built with the \"${spec.name}\" refract adapter.`],\n recipes: eachRuleSet(model).map(({ subsystem, group, variant }) => ({\n subsystem,\n group,\n variant,\n name: b.recipeName(subsystem, group, variant),\n })),\n }));\n\n return { ...b, renderAllRecipes, renderAllVariables, renderAll, describeUsage };\n },\n };\n}\n","/**\n * Contrast audit (opt-in) — scores a built theme's colour pairings for **WCAG 2** contrast ratio\n * (the compliance standard) plus an **advisory APCA** Lc reading. It reports; it never mutates the\n * theme and never \"fixes\" a colour. `audit()` returns structured results by default; a caller (or the\n * `refract audit --strict` CLI) can throw on failures.\n *\n * Which pairings: every palette's `base` ↔ `text`, and every recipe's foreground (`color`) ↔\n * background (`background-color` / `background`) across all subsystems' rule-sets (base + state\n * overrides). A side that isn't a derivable colour (`transparent`, a `var()`, a keyword literal) is\n * reported as `skipped`, not a failure.\n *\n * Colour math is inlined here on purpose: `utils.ts` is vendored to consumers (`build/vendor.ts`) and\n * kept dependency-free / minimal, so we don't widen its export surface for a non-vendored sibling. We\n * reuse only the already-exported {@link parseColor}.\n */\nimport type { Theme, Ref } from \"../../core\";\nimport { RefractError } from \"../../core/errors\";\nimport { parseColor, type RGBTuple } from \"./utils\";\n\n// ── WCAG 2.x ──────────────────────────────────────────────────────────────\n// Relative luminance per WCAG 2: linearize each sRGB channel, weight by the luma coefficients.\nconst srgbToLinear = (c: number): number => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));\nconst relLuminance = ([r, g, b]: RGBTuple): number =>\n 0.2126 * srgbToLinear(r / 255) + 0.7152 * srgbToLinear(g / 255) + 0.0722 * srgbToLinear(b / 255);\n\n/** WCAG 2 contrast ratio (1–21) between two sRGB colours; order-independent. */\nconst wcagRatio = (a: RGBTuple, b: RGBTuple): number => {\n const la = relLuminance(a);\n const lb = relLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n};\n\nexport type WcagLevel = \"AAA\" | \"AA\" | \"AA-large\" | \"fail\";\nconst LEVEL_RANK: Record<WcagLevel, number> = { fail: 0, \"AA-large\": 1, AA: 2, AAA: 3 };\n\n/** Map a ratio to a level. For normal text 3–4.5 is \"AA-large\" (passes only at large sizes). */\nconst wcagLevel = (ratio: number, large: boolean): WcagLevel => {\n if (large) return ratio >= 4.5 ? \"AAA\" : ratio >= 3 ? \"AA\" : \"fail\";\n return ratio >= 7 ? \"AAA\" : ratio >= 4.5 ? \"AA\" : ratio >= 3 ? \"AA-large\" : \"fail\";\n};\n\n// ── APCA (advisory) ───────────────────────────────────────────────────────\n// APCA 0.1.9 / formula 0.98G-4g (SAPC). Advisory only — NOT a WCAG substitute — and the draft may\n// still shift, so the constants are pinned here. Returns a signed Lc (polarity-aware).\nconst APCA = {\n mainTRC: 2.4,\n sRco: 0.2126729, sGco: 0.7151522, sBco: 0.072175,\n normBG: 0.56, normTXT: 0.57, revTXT: 0.62, revBG: 0.65,\n blkThrs: 0.022, blkClmp: 1.414,\n scaleBoW: 1.14, loBoWoffset: 0.027,\n scaleWoB: 1.14, loWoBoffset: 0.027,\n deltaYmin: 0.0005, loClip: 0.1,\n} as const;\n\nconst apcaY = ([r, g, b]: RGBTuple): number =>\n APCA.sRco * Math.pow(r / 255, APCA.mainTRC) +\n APCA.sGco * Math.pow(g / 255, APCA.mainTRC) +\n APCA.sBco * Math.pow(b / 255, APCA.mainTRC);\n\n/** Signed APCA lightness contrast (Lc) of `text` over `bg`. Positive = dark-on-light, negative = light-on-dark. */\nconst apcaLc = (text: RGBTuple, bg: RGBTuple): number => {\n const clamp = (y: number): number => (y > APCA.blkThrs ? y : y + Math.pow(APCA.blkThrs - y, APCA.blkClmp));\n const yTxt = clamp(apcaY(text));\n const yBg = clamp(apcaY(bg));\n if (Math.abs(yBg - yTxt) < APCA.deltaYmin) return 0;\n let out: number;\n if (yBg > yTxt) {\n const sapc = (Math.pow(yBg, APCA.normBG) - Math.pow(yTxt, APCA.normTXT)) * APCA.scaleBoW;\n out = sapc < APCA.loClip ? 0 : sapc - APCA.loBoWoffset;\n } else {\n const sapc = (Math.pow(yBg, APCA.revBG) - Math.pow(yTxt, APCA.revTXT)) * APCA.scaleWoB;\n out = sapc > -APCA.loClip ? 0 : sapc + APCA.loWoBoffset;\n }\n return out * 100;\n};\n\n// ── audit ─────────────────────────────────────────────────────────────────\n\nexport type PairingKind = \"palette\" | \"recipe\";\n\nexport interface PairingScore {\n kind: PairingKind;\n /** Human label, e.g. `colors.brand` or `components.buttons.primary (:hover)`. */\n label: string;\n /** Resolved foreground colour string, or `undefined` when it isn't a derivable colour. */\n fg?: string;\n /** Resolved background colour string, or `undefined` when it isn't a derivable colour. */\n bg?: string;\n /** WCAG 2 contrast ratio (1–21, 2 dp). Absent when skipped. */\n wcagRatio?: number;\n /** WCAG level at the configured text size. Absent when skipped. */\n wcagLevel?: WcagLevel;\n /** Advisory APCA Lc (signed, 1 dp). Absent when skipped. */\n apcaLc?: number;\n /** Whether this pairing met the pass bar (`minWcag`). Absent when skipped. */\n pass?: boolean;\n /** Set when a side isn't a derivable colour — then the score fields are absent. */\n skipped?: string;\n}\n\nexport interface AuditOptions {\n /** Throw an aggregated error when any pairing fails, instead of only reporting. Default `false`. */\n strict?: boolean;\n /** Treat the foreground as large text (relaxed WCAG thresholds). Default `false`. */\n largeText?: boolean;\n /** The pass bar. Default `\"AA\"`. `\"AA-large\"` accepts the 3:1 tier. */\n minWcag?: WcagLevel;\n /** Audit component/recipe fg↔bg pairs. Default `true`. */\n includeRecipes?: boolean;\n /** Audit palette base↔text pairs. Default `true`. */\n includePalettes?: boolean;\n}\n\nexport interface AuditResult {\n pairings: PairingScore[];\n summary: {\n total: number;\n passed: number;\n failed: number;\n skipped: number;\n /** The lowest-ratio scored pairing (the worst offender), if any were scored. */\n worst?: PairingScore;\n };\n /** `true` when no scored pairing failed the pass bar. */\n ok: boolean;\n}\n\nconst round = (n: number, dp: number): number => {\n const f = 10 ** dp;\n return Math.round(n * f) / f;\n};\n\n/** Resolve a rule-set declaration `Ref` to a colour string, or `undefined` if it isn't one. */\nconst refToColor = (theme: Theme, ref: Ref): string | undefined => {\n if (ref.ref !== undefined) {\n try {\n return String(theme.resolveToken(ref.ref));\n } catch {\n return undefined;\n }\n }\n if (typeof ref.value === \"string\") return ref.value;\n return undefined;\n};\n\nconst FG_KEY = \"color\";\nconst BG_KEYS = [\"background-color\", \"background\"] as const;\nconst pickBg = (decls: Record<string, Ref> | undefined): Ref | undefined => {\n if (!decls) return undefined;\n for (const k of BG_KEYS) if (decls[k]) return decls[k];\n return undefined;\n};\n\n/** Score one fg/bg pairing (colours already resolved to strings), or a skipped record. */\nconst scorePair = (\n kind: PairingKind,\n label: string,\n fg: string | undefined,\n bg: string | undefined,\n options: Required<Pick<AuditOptions, \"largeText\" | \"minWcag\">>,\n): PairingScore => {\n let fgRgb: RGBTuple | undefined;\n let bgRgb: RGBTuple | undefined;\n try {\n if (fg !== undefined) fgRgb = parseColor(fg).rgb;\n } catch { /* not a derivable colour */ }\n try {\n if (bg !== undefined) bgRgb = parseColor(bg).rgb;\n } catch { /* not a derivable colour */ }\n\n if (!fgRgb || !bgRgb) {\n return { kind, label, fg, bg, skipped: !fgRgb && !bgRgb ? \"no derivable fg/bg\" : !fgRgb ? \"fg not a colour\" : \"bg not a colour\" };\n }\n\n const ratio = wcagRatio(fgRgb, bgRgb);\n const level = wcagLevel(ratio, options.largeText);\n const pass = LEVEL_RANK[level] >= LEVEL_RANK[options.minWcag];\n return {\n kind, label, fg, bg,\n wcagRatio: round(ratio, 2),\n wcagLevel: level,\n apcaLc: round(apcaLc(fgRgb, bgRgb), 1),\n pass,\n };\n};\n\n/**\n * Audit a built theme's colour pairings. Pure — reads `theme.tokens` / `theme.resolveToken` /\n * `theme.model` only. In `strict` mode, throws one aggregated error listing every failing pairing.\n */\nexport const audit = (theme: Theme, options: AuditOptions = {}): AuditResult => {\n const opts = {\n largeText: options.largeText ?? false,\n minWcag: options.minWcag ?? (\"AA\" as WcagLevel),\n };\n const includeRecipes = options.includeRecipes ?? true;\n const includePalettes = options.includePalettes ?? true;\n const pairings: PairingScore[] = [];\n\n // Palettes: base ↔ text. A palette advertises a pairing by having a `colors.<name>.text` token.\n if (includePalettes) {\n for (const path of Object.keys(theme.tokens)) {\n const m = /^colors\\.([^.]+)\\.text$/.exec(path);\n if (!m) continue;\n const base = `colors.${m[1]}`;\n let fg: string | undefined, bg: string | undefined;\n try { fg = String(theme.resolveToken(path)); } catch { /* skip */ }\n try { bg = String(theme.resolveToken(base)); } catch { /* skip */ }\n pairings.push(scorePair(\"palette\", base, fg, bg, opts));\n }\n }\n\n // Recipes: every subsystem's rule-sets — the base declarations + each state/breakpoint override.\n if (includeRecipes) {\n for (const [subsystem, subModel] of Object.entries(theme.model.subsystems)) {\n if (!subModel.ruleSets) continue;\n for (const [group, ruleSetGroup] of Object.entries(subModel.ruleSets)) {\n for (const [variant, ruleSet] of Object.entries(ruleSetGroup)) {\n const baseFg = ruleSet.declarations[FG_KEY];\n const baseBg = pickBg(ruleSet.declarations);\n const label = `${subsystem}.${group}.${variant}`;\n if (baseFg && baseBg) {\n pairings.push(scorePair(\"recipe\", label, refToColor(theme, baseFg), refToColor(theme, baseBg), opts));\n }\n // Overrides (e.g. :hover) can swap bg or fg — score the effective pairing at that condition.\n for (const override of ruleSet.overrides ?? []) {\n const oFg = override.declarations?.[FG_KEY] ?? baseFg;\n const oBg = pickBg(override.declarations) ?? baseBg;\n if (!override.declarations || (!override.declarations[FG_KEY] && !pickBg(override.declarations))) continue;\n if (!oFg || !oBg) continue;\n const cond = override.state ?? override.breakpoint ?? override.query ?? \"override\";\n pairings.push(scorePair(\"recipe\", `${label} (${cond})`, refToColor(theme, oFg), refToColor(theme, oBg), opts));\n }\n }\n }\n }\n }\n\n const scored = pairings.filter(p => !p.skipped);\n const failed = scored.filter(p => p.pass === false);\n const worst = scored.reduce<PairingScore | undefined>(\n (w, p) => (w === undefined || (p.wcagRatio ?? Infinity) < (w.wcagRatio ?? Infinity) ? p : w),\n undefined,\n );\n const result: AuditResult = {\n pairings,\n summary: {\n total: scored.length,\n passed: scored.length - failed.length,\n failed: failed.length,\n skipped: pairings.length - scored.length,\n worst,\n },\n ok: failed.length === 0,\n };\n\n if (options.strict && failed.length > 0) {\n const list = failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`).join(\", \");\n throw new RefractError(\n \"REFRACT_E_AUDIT\",\n `refract audit: ${failed.length} pairing(s) fail WCAG ${opts.minWcag} — ${list}. ` +\n `Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,\n failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`),\n );\n }\n\n return result;\n};\n","/**\n * `createNoopAdapter` — the trivial, built-in null adapter (monorepo split, friction 2).\n *\n * `createTheme` requires an `adapter`, but some consumers of the built `Theme` never touch\n * adapter-produced strings — they read only the format-neutral `theme.tokens` / `theme.resolveToken`\n * / `theme.model` (the DTCG export is the canonical example: `toDTCG` walks the flat token map and the\n * breakpoints, never a rendered rule). Those callers need *a* valid adapter purely to satisfy the\n * contract; the output is discarded.\n *\n * Before the split the CLI's `tokens` command reached for `createCssAdapter` as that throwaway builder\n * — which forced a core→adapter dependency (`src/build` importing `src/adapters/css`). The monorepo\n * guiding rule is that the dependency arrow points ONLY into core, so core now ships its own null\n * object: `createNoopAdapter()` emits nothing (empty strings, an empty `emit()`), lets `createTheme`\n * build the Model + token map exactly as any adapter would, and keeps `src/build` free of every\n * adapter package.\n *\n * It's a `ThemeAdapter` like any other (built through {@link defineAdapter}, so it gets the defaulted\n * aggregators for free), just with render primitives that produce empty output.\n */\n\nimport { defineAdapter } from \"./defineAdapter\";\nimport type { ThemeAdapter } from \"./ThemeAdapter\";\n\n/**\n * A no-op adapter: every render primitive returns an empty string and `emit()` writes no files. Use it\n * whenever a `Theme` is needed only for its format-neutral data (`tokens` / `resolveToken` / `model`)\n * and the rendered output is irrelevant — e.g. the `refract tokens` DTCG export.\n */\nexport function createNoopAdapter(): ThemeAdapter<string> {\n return defineAdapter<string>({\n name: \"noop\",\n version: 1,\n bind: () => ({\n recipeName: () => \"\",\n renderRecipe: () => \"\",\n renderVariables: () => \"\",\n join: parts => parts.join(\"\"),\n emit: () => ({ files: {} }),\n }),\n });\n}\n","/**\n * `ref(path)` — author a token **reference** inside a `css` delta or a globals element rule.\n *\n * Inside a `css` block (and globals element declarations) a bare string is a **literal** CSS value —\n * `display: \"flex\"` emits `flex`. To emit a token reference instead, wrap the token path in `ref()`:\n * `color: ref(\"colors.brand.text\")` → `var(--…)`. The JSON-safe equivalent is the plain object form\n * `{ ref: \"colors.brand.text\" }`; both produce the same Model reference, so a `theme.raw.json` needs no\n * function. (Top-level recipe composition fields — `colors: \"solid.brand\"` — are unaffected: a bare\n * string there is always a reference.)\n */\nexport const ref = (path: string): { ref: string } => ({ ref: path });\n"],"names":["parseRuleSetReference","reference","subsystem","rest","split","dot","indexOf","group","slice","variant","resolveReference","model","parsed","_c","_a","subsystems","ruleSets","_b","mergeDeclarations","target","source","prop","ref","Object","entries","responsiveKey","o","_d","_e","_f","breakpoint","query","orientation","state","container","size","eachRuleSet","out","sub","ruleSet","keys","push","defineAdapter","spec","name","version","allowedStates","bind","ctx","b","renderAllRecipes","join","map","renderRecipe","renderAllVariables","renderVariables","renderAll","describeUsage","format","summary","recipes","recipeName","srgbToLinear","c","Math","pow","relLuminance","r","g","LEVEL_RANK","fail","AA","AAA","APCA","apcaY","apcaLc","text","bg","clamp","y","yTxt","yBg","abs","sapc","round","n","dp","f","refToColor","theme","undefined","String","resolveToken","value","FG_KEY","BG_KEYS","pickBg","decls","k","scorePair","kind","label","fg","options","fgRgb","bgRgb","parseColor","rgb","skipped","ratio","a","la","lb","max","min","wcagRatio","level","large","wcagLevel","largeText","pass","minWcag","opts","includeRecipes","pairings","includePalettes","path","tokens","m","exec","base","subModel","ruleSetGroup","baseFg","declarations","baseBg","override","overrides","oFg","_g","oBg","_h","cond","_l","_j","_k","scored","filter","p","failed","worst","reduce","w","Infinity","result","total","length","passed","ok","strict","list","RefractError","parts","emit","files","own","components","sources","references","resolved","states","responsiveByKey","Map","key","entry","get","set","responsive","values","seen","Set","referencedPaths","collect","has","add"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `@theme-registry/refract` — the core package barrel (Model-first, adapter-required surface).
3
+ *
4
+ * Post monorepo split (context.md §3) core ships ZERO adapter *implementations* — every adapter
5
+ * (CSS/SC/SCSS/JSON) is now its own sibling package (`@theme-registry/refract-css`, …). Core keeps
6
+ * everything adapter-*enabling*: the `ThemeModel`/`RawTheme`/`Ref` types, `createTheme`, the
7
+ * `defineAdapter`/`ThemeAdapter` contract, and the trivial built-in `createNoopAdapter` (a null
8
+ * adapter for callers — like the DTCG export — that only read `theme.tokens`/`resolveToken`/`model`).
9
+ *
10
+ * Headline entry points:
11
+ * - `createTheme(raw, { adapter })` — the entry point. `adapter` is **required** (core ships no
12
+ * real output adapter); it builds the format-neutral {@link ThemeModel} first, then lowers via the
13
+ * adapter. Install the adapter package for the format you want.
14
+ * - `defineAdapter(spec)` — author a custom adapter (fills the defaulted render methods).
15
+ * - `createNoopAdapter()` — the built-in null adapter (renders nothing; for token-only consumers).
16
+ * - Model / adapter / theme types — `ThemeModel`, `SubsystemModel`, `RuleSet`, `RuleSetGroup`,
17
+ * `PropertyModel`, `Ref`, `ThemeAdapter`, `AdapterSpec`, `RenderContext`, `Theme`, `CreateThemeOptions`.
18
+ * - The subsystem descriptors (`colorsSubsystem` … `componentsSubsystem`) for extension.
19
+ *
20
+ * The shared adapter-authoring helpers (naming overrides, `createNamer`, `sanitizeSegment`) live at
21
+ * the dedicated `./adapter-kit` subpath; the OKLCH colour-math helpers at `./color-math`; the DTCG
22
+ * interop (`fromDTCG` / `toDTCG` / `parseDTCGDocument`) at `./dtcg`; the Node-only build API +
23
+ * `defineConfig` at `./build`. None of those ride this `.` barrel (they'd drag Node/typescript or
24
+ * adapter-only concerns onto the runtime surface).
25
+ */
26
+ export * from "./core";
27
+ export * from "./subsystems";
@@ -0,0 +1,2 @@
1
+ import{R as $}from"./_errors-d75a5c74.esm.js";export{B as BREAKPOINT_EPSILON,C as CSS_UNITS,v as DEFAULT_BASE_FONT_SIZE,D as DEFAULT_BREAKPOINTS,A as DEFAULT_RESPONSIVE_QUERY,K as KNOWN_CSS_PROPERTIES,L as LENGTH_REGISTRY,U as animationSubsystem,N as bakeCrossPropertyDerivations,T as bordersSubsystem,g as buildComponentRuleSetFromInterpreted,t as buildContainerDescriptors,I as buildDerivationRegistry,l as buildMediaDescriptor,a as buildPropertiesModel,b as buildPropertyModel,c as buildRuleSetFromInterpreted,d as buildRuleSetGroupFromInterpreted,h as buildSubsystemModel,j as buildThemeModel,k as buildTokenMap,P as colorsSubsystem,V as componentsSubsystem,q as containerQueryString,H as createRecipeVariantResolver,O as createTheme,S as effectsSubsystem,f as extractComponentReferences,m as formatWidth,W as globalsSubsystem,i as isKnownCssProperty,R as layoutSubsystem,o as mediaQuery,n as mediaQueryString,z as normalizePropertyValue,G as normalizeRecipeGroup,E as normalizeResponsiveOverrides,u as parseLength,e as pathifyProperties,p as pathifyRuleSetGroup,x as resolveLengthRef,r as resolveMediaConfig,y as resolveModelUnits,w as resolveRoleUnit,J as resolveToken,M as resolveTokenMap,s as sortBreakpointKeys,Q as typographySubsystem,F as validateNormalizedResponsiveRefs}from"./_createTheme-255ff48e.esm.js";import{parseColor as _}from"./color-math.esm.js";const Y=e=>{const[o,t]=e.split(":");if(!o||!t)return;const r=t.indexOf(".");return r<0?void 0:{subsystem:o,group:t.slice(0,r),variant:t.slice(r+1)}},Z=(e,o)=>{var t,r,s;const n=Y(o);if(n)return null===(s=null===(r=null===(t=e.subsystems[n.subsystem])||void 0===t?void 0:t.ruleSets)||void 0===r?void 0:r[n.group])||void 0===s?void 0:s[n.variant]},X=(e,o)=>{for(const[t,r]of Object.entries(o))e[t]={...r}},ee=e=>{var o,t,r,s,n,a;return`${null!==(o=e.breakpoint)&&void 0!==o?o:""}|${null!==(t=e.query)&&void 0!==t?t:""}|${null!==(r=e.orientation)&&void 0!==r?r:""}|${null!==(s=e.state)&&void 0!==s?s:""}|${null!==(n=e.container)&&void 0!==n?n:""}|${null!==(a=e.size)&&void 0!==a?a:""}`},oe=(e,o,t)=>{var r,s,n,a,i,l;const c=null===(n=null===(s=null===(r=e.subsystems.components)||void 0===r?void 0:r.ruleSets)||void 0===s?void 0:s[o])||void 0===n?void 0:n[t];if(!c)throw new $("REFRACT_E_REFERENCE",`mergeComponentRuleSet: no component rule-set "${o}.${t}"`);const u=[];for(const o of null!==(a=c.references)&&void 0!==a?a:[]){const t=Z(e,o);if(!t)throw new $("REFRACT_E_REFERENCE",`mergeComponentRuleSet: unresolved reference "${o}"`);u.push(t)}u.push(c);const d={},p={},v=new Map;for(const e of u){X(d,e.declarations);for(const o of e.overrides)if(o.declarations)if(void 0!==o.breakpoint||void 0!==o.container){const e=ee(o);let t=v.get(e);t||(t={...void 0!==o.breakpoint?{breakpoint:o.breakpoint}:{},...void 0!==o.query?{query:o.query}:{},...void 0!==o.orientation?{orientation:o.orientation}:{},...void 0!==o.state?{state:o.state}:{},...void 0!==o.container?{container:o.container}:{},...void 0!==o.size?{size:o.size}:{},declarations:{}},v.set(e,t)),X(t.declarations,o.declarations)}else void 0!==o.state?(null!==(i=p[l=o.state])&&void 0!==i||(p[l]={}),X(p[o.state],o.declarations)):X(d,o.declarations)}const f=[...v.values()],m=new Set,b=[],g=e=>{for(const o of Object.values(e))void 0===o.ref||m.has(o.ref)||(m.add(o.ref),b.push(o.ref))};g(d);for(const e of Object.values(p))g(e);for(const e of f)g(e.declarations);return{base:d,states:p,responsive:f,referencedPaths:b}},te=e=>({ref:e});function re(e){var o;const t=[];for(const[r,s]of Object.entries(e.subsystems))for(const[e,n]of Object.entries(null!==(o=s.ruleSets)&&void 0!==o?o:{}))for(const o of Object.keys(n))t.push({subsystem:r,group:e,variant:o});return t}function se(e){return{name:e.name,version:e.version,allowedStates:e.allowedStates,bind(o,t){var r,s,n,a;const i=e.bind(o,t),l=null!==(r=i.renderAllRecipes)&&void 0!==r?r:()=>i.join(re(o).map(({subsystem:e,group:o,variant:t})=>i.renderRecipe(e,o,t))),c=null!==(s=i.renderAllVariables)&&void 0!==s?s:()=>i.join(Object.keys(o.subsystems).map(e=>i.renderVariables(e))),u=null!==(n=i.renderAll)&&void 0!==n?n:()=>i.join([c(),l()]),d=null!==(a=i.describeUsage)&&void 0!==a?a:()=>({format:e.name,summary:[`This theme was built with the "${e.name}" refract adapter.`],recipes:re(o).map(({subsystem:e,group:o,variant:t})=>({subsystem:e,group:o,variant:t,name:i.recipeName(e,o,t)}))});return{...i,renderAllRecipes:l,renderAllVariables:c,renderAll:u,describeUsage:d}}}}function ne(){return se({name:"noop",version:1,bind:()=>({recipeName:()=>"",renderRecipe:()=>"",renderVariables:()=>"",join:e=>e.join(""),emit:()=>({files:{}})})})}const ae=e=>e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4),ie=([e,o,t])=>.2126*ae(e/255)+.7152*ae(o/255)+.0722*ae(t/255),le={fail:0,"AA-large":1,AA:2,AAA:3},ce=2.4,ue=.2126729,de=.7151522,pe=.072175,ve=.56,fe=.57,me=.62,be=.65,ge=.022,he=1.414,ye=1.14,Re=.027,Se=1.14,Ae=.027,we=5e-4,Ee=.1,Te=([e,o,t])=>ue*Math.pow(e/255,ce)+de*Math.pow(o/255,ce)+pe*Math.pow(t/255,ce),ke=(e,o)=>{const t=e=>e>ge?e:e+Math.pow(ge-e,he),r=t(Te(e)),s=t(Te(o));if(Math.abs(s-r)<we)return 0;let n;if(s>r){const e=(Math.pow(s,ve)-Math.pow(r,fe))*ye;n=e<Ee?0:e-Re}else{const e=(Math.pow(s,be)-Math.pow(r,me))*Se;n=e>-Ee?0:e+Ae}return 100*n},$e=(e,o)=>{const t=10**o;return Math.round(e*t)/t},Me=(e,o)=>{if(void 0!==o.ref)try{return String(e.resolveToken(o.ref))}catch{return}if("string"==typeof o.value)return o.value},je="color",Oe=["background-color","background"],_e=e=>{if(e)for(const o of Oe)if(e[o])return e[o]},Ce=(e,o,t,r,s)=>{let n,a;try{void 0!==t&&(n=_(t).rgb)}catch{}try{void 0!==r&&(a=_(r).rgb)}catch{}if(!n||!a)return{kind:e,label:o,fg:t,bg:r,skipped:n||a?n?"bg not a colour":"fg not a colour":"no derivable fg/bg"};const i=((e,o)=>{const t=ie(e),r=ie(o);return(Math.max(t,r)+.05)/(Math.min(t,r)+.05)})(n,a),l=((e,o)=>o?e>=4.5?"AAA":e>=3?"AA":"fail":e>=7?"AAA":e>=4.5?"AA":e>=3?"AA-large":"fail")(i,s.largeText),c=le[l]>=le[s.minWcag];return{kind:e,label:o,fg:t,bg:r,wcagRatio:$e(i,2),wcagLevel:l,apcaLc:$e(ke(n,a),1),pass:c}},Ne=(e,o={})=>{var t,r,s,n,a,i,l,c,u,d,p;const v={largeText:null!==(t=o.largeText)&&void 0!==t&&t,minWcag:null!==(r=o.minWcag)&&void 0!==r?r:"AA"},f=null===(s=o.includeRecipes)||void 0===s||s,m=[];if(null===(n=o.includePalettes)||void 0===n||n)for(const o of Object.keys(e.tokens)){const t=/^colors\.([^.]+)\.text$/.exec(o);if(!t)continue;const r=`colors.${t[1]}`;let s,n;try{s=String(e.resolveToken(o))}catch{}try{n=String(e.resolveToken(r))}catch{}m.push(Ce("palette",r,s,n,v))}if(f)for(const[o,t]of Object.entries(e.model.subsystems))if(t.ruleSets)for(const[r,s]of Object.entries(t.ruleSets))for(const[t,n]of Object.entries(s)){const s=n.declarations[je],f=_e(n.declarations),b=`${o}.${r}.${t}`;s&&f&&m.push(Ce("recipe",b,Me(e,s),Me(e,f),v));for(const o of null!==(a=n.overrides)&&void 0!==a?a:[]){const t=null!==(l=null===(i=o.declarations)||void 0===i?void 0:i[je])&&void 0!==l?l:s,r=null!==(c=_e(o.declarations))&&void 0!==c?c:f;if(!o.declarations||!o.declarations[je]&&!_e(o.declarations))continue;if(!t||!r)continue;const n=null!==(p=null!==(d=null!==(u=o.state)&&void 0!==u?u:o.breakpoint)&&void 0!==d?d:o.query)&&void 0!==p?p:"override";m.push(Ce("recipe",`${b} (${n})`,Me(e,t),Me(e,r),v))}}const b=m.filter(e=>!e.skipped),g=b.filter(e=>!1===e.pass),h=b.reduce((e,o)=>{var t,r;return void 0===e||(null!==(t=o.wcagRatio)&&void 0!==t?t:1/0)<(null!==(r=e.wcagRatio)&&void 0!==r?r:1/0)?o:e},void 0),y={pairings:m,summary:{total:b.length,passed:b.length-g.length,failed:g.length,skipped:m.length-b.length,worst:h},ok:0===g.length};if(o.strict&&g.length>0){const e=g.map(e=>`${e.label} (${e.wcagRatio}:1, ${e.wcagLevel})`).join(", ");throw new $("REFRACT_E_AUDIT",`refract audit: ${g.length} pairing(s) fail WCAG ${v.minWcag} — ${e}. Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,g.map(e=>`${e.label} (${e.wcagRatio}:1, ${e.wcagLevel})`))}return y};export{$ as RefractError,Ne as audit,ne as createNoopAdapter,se as defineAdapter,oe as mergeComponentRuleSet,Y as parseRuleSetReference,te as ref};
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/core/model/mergeRuleSet.ts","../src/core/ref.ts","../src/core/defineAdapter.ts","../src/core/noopAdapter.ts","../src/subsystems/colors/audit.ts"],"sourcesContent":["/**\n * Format-neutral component merge (§9c).\n *\n * `mergeComponentRuleSet` flattens one component variant into a single\n * self-contained rule-set: its referenced recipes' declarations + its own `css`\n * delta, unioned. The result is pure Model data — declarations stay as {@link Ref}s\n * carrying `{ ref, value }` — so an adapter renders it as baked values (inline) or\n * `var(--…)` / `theme.…` (referenced) without any format decision leaking in here.\n *\n * This is the ONLY new machinery the `components` emit mode needs, shared by the CSS\n * and future SC adapters. It is **on-demand** (an adapter calls it in `emit()`), never\n * materialized on `ThemeModel` / the runtime `theme`. It does NOT mutate the authored\n * `RuleSet` / declarations — the merged view is freshly derived (Refs shallow-cloned).\n *\n * Precedence (LOCKED, §9): authored **reference order** first (later refs override\n * earlier per property key), then the component's own declarations **last / highest**\n * (`css` delta wins over subsystem recipes). Same rule per condition bucket.\n */\nimport type {\n Orientation,\n Ref,\n ResponsiveQueryKind,\n RuleSet,\n RuleSetOverride,\n ThemeModel,\n} from \"./model\";\nimport { RefractError } from \"../errors\";\n\n/**\n * One flattened conditioned bucket — a distinct `(breakpoint, query, orientation, state, container, size)`\n * key. A **viewport** entry carries `breakpoint`; a **container** entry (§10.5) carries `container` + `size`\n * (and no `breakpoint`). The adapter emits the former as `@media`, the latter as `@container`.\n */\nexport type MergedResponsiveEntry = {\n breakpoint?: string;\n query?: ResponsiveQueryKind;\n orientation?: Orientation;\n state?: string;\n container?: string;\n size?: string;\n declarations: Record<string, Ref>;\n};\n\n/**\n * A component variant flattened into one self-contained rule-set.\n *\n * - `base` — merged no-condition declarations.\n * - `states` — merged declarations keyed by `state` (no breakpoint).\n * - `responsive` — one entry per distinct `(breakpoint, query, orientation, state)` merge key.\n * - `referencedPaths` — every distinct token path (`Ref.ref`) appearing across all buckets,\n * first-appearance order. What non-inline rendering tree-shakes the vars file to.\n */\nexport type MergedRuleSet = {\n base: Record<string, Ref>;\n states: Record<string, Record<string, Ref>>;\n responsive: MergedResponsiveEntry[];\n referencedPaths: string[];\n};\n\n/** The address parts of a component reference (`\"colors:solid.primary\"`). */\nexport type RuleSetReference = { subsystem: string; group: string; variant: string };\n\n/**\n * Parse a component reference (`\"subsystem:group.variant\"`) into its address parts.\n * Format-neutral core twin of the CSS adapter's `parseComponentReference` (which stays\n * for the option-C class-list path). Returns `undefined` on a malformed reference.\n */\nexport const parseRuleSetReference = (reference: string): RuleSetReference | undefined => {\n const [subsystem, rest] = reference.split(\":\");\n if (!subsystem || !rest) return undefined;\n const dot = rest.indexOf(\".\");\n if (dot < 0) return undefined;\n return { subsystem, group: rest.slice(0, dot), variant: rest.slice(dot + 1) };\n};\n\n/** Resolve a reference to its authored `RuleSet`, or `undefined` if it doesn't address one. */\nconst resolveReference = (model: ThemeModel, reference: string): RuleSet | undefined => {\n const parsed = parseRuleSetReference(reference);\n if (!parsed) return undefined;\n return model.subsystems[parsed.subsystem]?.ruleSets?.[parsed.group]?.[parsed.variant];\n};\n\n/** Fold `source` declarations into `target` (later source wins), shallow-cloning each Ref. */\nconst mergeDeclarations = (target: Record<string, Ref>, source: Record<string, Ref>): void => {\n for (const [prop, ref] of Object.entries(source)) target[prop] = { ...ref };\n};\n\n/** Stable string key for a conditioned bucket — `(breakpoint, query, orientation, state, container, size)`. */\nconst responsiveKey = (o: RuleSetOverride): string =>\n `${o.breakpoint ?? \"\"}|${o.query ?? \"\"}|${o.orientation ?? \"\"}|${o.state ?? \"\"}|${o.container ?? \"\"}|${o.size ?? \"\"}`;\n\n/**\n * Flatten one component variant into a self-contained {@link MergedRuleSet}.\n *\n * Reads `model.subsystems.components.ruleSets[group][variant]` — its `references`\n * (resolved in authored order), own base `declarations`, and `overrides` — and unions\n * them under the locked precedence. Throws on a missing component or an unresolved reference.\n */\nexport const mergeComponentRuleSet = (\n model: ThemeModel,\n group: string,\n variant: string,\n): MergedRuleSet => {\n const own = model.subsystems.components?.ruleSets?.[group]?.[variant];\n if (!own) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: no component rule-set \"${group}.${variant}\"`);\n }\n\n // Sources in precedence order: referenced rule-sets left-to-right, then the component's own last.\n const sources: RuleSet[] = [];\n for (const reference of own.references ?? []) {\n const resolved = resolveReference(model, reference);\n if (!resolved) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: unresolved reference \"${reference}\"`);\n }\n sources.push(resolved);\n }\n sources.push(own);\n\n const base: Record<string, Ref> = {};\n const states: Record<string, Record<string, Ref>> = {};\n const responsiveByKey = new Map<string, MergedResponsiveEntry>();\n\n for (const source of sources) {\n mergeDeclarations(base, source.declarations);\n\n for (const override of source.overrides) {\n if (!override.declarations) continue;\n // A breakpoint OR container condition → a conditioned bucket (viewport → @media, container →\n // @container). Container overrides MUST route here, not fold into base (§10.5 correctness).\n if (override.breakpoint !== undefined || override.container !== undefined) {\n const key = responsiveKey(override);\n let entry = responsiveByKey.get(key);\n if (!entry) {\n entry = {\n ...(override.breakpoint !== undefined ? { breakpoint: override.breakpoint } : {}),\n ...(override.query !== undefined ? { query: override.query } : {}),\n ...(override.orientation !== undefined ? { orientation: override.orientation } : {}),\n ...(override.state !== undefined ? { state: override.state } : {}),\n ...(override.container !== undefined ? { container: override.container } : {}),\n ...(override.size !== undefined ? { size: override.size } : {}),\n declarations: {},\n };\n responsiveByKey.set(key, entry);\n }\n mergeDeclarations(entry.declarations, override.declarations);\n } else if (override.state !== undefined) {\n (states[override.state] ??= {});\n mergeDeclarations(states[override.state], override.declarations);\n } else {\n // Unconditional override (only variant/target, no breakpoint/state) — folds into base.\n mergeDeclarations(base, override.declarations);\n }\n }\n }\n\n const responsive = [...responsiveByKey.values()];\n\n // referencedPaths — every distinct token path across all buckets, first-appearance order.\n const seen = new Set<string>();\n const referencedPaths: string[] = [];\n const collect = (decls: Record<string, Ref>): void => {\n for (const ref of Object.values(decls)) {\n if (ref.ref !== undefined && !seen.has(ref.ref)) {\n seen.add(ref.ref);\n referencedPaths.push(ref.ref);\n }\n }\n };\n collect(base);\n for (const decls of Object.values(states)) collect(decls);\n for (const entry of responsive) collect(entry.declarations);\n\n return { base, states, responsive, referencedPaths };\n};\n","/**\n * `ref(path)` — author a token **reference** inside a `css` delta or a globals element rule.\n *\n * Inside a `css` block (and globals element declarations) a bare string is a **literal** CSS value —\n * `display: \"flex\"` emits `flex`. To emit a token reference instead, wrap the token path in `ref()`:\n * `color: ref(\"colors.brand.text\")` → `var(--…)`. The JSON-safe equivalent is the plain object form\n * `{ ref: \"colors.brand.text\" }`; both produce the same Model reference, so a `theme.raw.json` needs no\n * function. (Top-level recipe composition fields — `colors: \"solid.brand\"` — are unaffected: a bare\n * string there is always a reference.)\n */\nexport const ref = (path: string): { ref: string } => ({ ref: path });\n","/**\n * `defineAdapter` — turns an `AdapterSpec` (identity + a `bind` returning the four\n * required primitives) into a full `ThemeAdapter` whose `bind` yields a complete\n * `BoundAdapter` with the DEFAULTED aggregators supplied.\n *\n * The defaults are pure Model walks: the Model enumerates every subsystem and every\n * (group, variant), so core loops it, calls the author's per-unit renderers, and\n * `join`s the results. Model/ctx are already bound, so the aggregators take no args.\n * An author can still override any aggregator (a format whose full document isn't a\n * flat concatenation).\n */\n\nimport type { ThemeModel } from \"./model\";\nimport type {\n AdapterSpec,\n ThemeAdapter,\n BoundAdapter,\n RenderContext,\n UsageDescriptor,\n} from \"./ThemeAdapter\";\n\n/** Every rule-set address in the Model — `(subsystem, group, variant)` triples. */\nfunction eachRuleSet(model: ThemeModel): Array<{ subsystem: string; group: string; variant: string }> {\n const out: Array<{ subsystem: string; group: string; variant: string }> = [];\n for (const [subsystem, sub] of Object.entries(model.subsystems)) {\n for (const [group, ruleSet] of Object.entries(sub.ruleSets ?? {})) {\n for (const variant of Object.keys(ruleSet)) {\n out.push({ subsystem, group, variant });\n }\n }\n }\n return out;\n}\n\n/**\n * Complete an `AdapterSpec` into a `ThemeAdapter`.\n *\n * Wraps the author's `bind` so the returned `BoundAdapter` gains the defaulted\n * aggregators (`renderAllRecipes` / `renderAllVariables` / `renderAll`) built from\n * the required primitives — unless the spec already provides its own override.\n * `name` / `version` pass through unchanged.\n *\n * @param spec identity (`name`/`version`) + a `bind(model, ctx)` returning the\n * required render primitives (and any optional overrides).\n * @returns a full adapter whose `bind(model, ctx)` yields a complete `BoundAdapter`.\n */\nexport function defineAdapter<TUnit>(spec: AdapterSpec<TUnit>): ThemeAdapter<TUnit> {\n return {\n name: spec.name,\n version: spec.version,\n allowedStates: spec.allowedStates,\n bind(model: ThemeModel, ctx: RenderContext): BoundAdapter<TUnit> {\n const b = spec.bind(model, ctx);\n\n const renderAllRecipes =\n b.renderAllRecipes ??\n ((): TUnit =>\n b.join(\n eachRuleSet(model).map(({ subsystem, group, variant }) =>\n b.renderRecipe(subsystem, group, variant),\n ),\n ));\n\n const renderAllVariables =\n b.renderAllVariables ??\n ((): TUnit => b.join(Object.keys(model.subsystems).map(subsystem => b.renderVariables(subsystem))));\n\n const renderAll =\n b.renderAll ?? ((): TUnit => b.join([renderAllVariables(), renderAllRecipes()]));\n\n // Generic self-documentation: the recipe identities are format-correct via `recipeName`; an\n // adapter overrides `describeUsage` to add format-specific import prose to `summary`.\n const describeUsage =\n b.describeUsage ??\n ((): UsageDescriptor => ({\n format: spec.name,\n summary: [`This theme was built with the \"${spec.name}\" refract adapter.`],\n recipes: eachRuleSet(model).map(({ subsystem, group, variant }) => ({\n subsystem,\n group,\n variant,\n name: b.recipeName(subsystem, group, variant),\n })),\n }));\n\n return { ...b, renderAllRecipes, renderAllVariables, renderAll, describeUsage };\n },\n };\n}\n","/**\n * `createNoopAdapter` — the trivial, built-in null adapter (monorepo split, friction 2).\n *\n * `createTheme` requires an `adapter`, but some consumers of the built `Theme` never touch\n * adapter-produced strings — they read only the format-neutral `theme.tokens` / `theme.resolveToken`\n * / `theme.model` (the DTCG export is the canonical example: `toDTCG` walks the flat token map and the\n * breakpoints, never a rendered rule). Those callers need *a* valid adapter purely to satisfy the\n * contract; the output is discarded.\n *\n * Before the split the CLI's `tokens` command reached for `createCssAdapter` as that throwaway builder\n * — which forced a core→adapter dependency (`src/build` importing `src/adapters/css`). The monorepo\n * guiding rule is that the dependency arrow points ONLY into core, so core now ships its own null\n * object: `createNoopAdapter()` emits nothing (empty strings, an empty `emit()`), lets `createTheme`\n * build the Model + token map exactly as any adapter would, and keeps `src/build` free of every\n * adapter package.\n *\n * It's a `ThemeAdapter` like any other (built through {@link defineAdapter}, so it gets the defaulted\n * aggregators for free), just with render primitives that produce empty output.\n */\n\nimport { defineAdapter } from \"./defineAdapter\";\nimport type { ThemeAdapter } from \"./ThemeAdapter\";\n\n/**\n * A no-op adapter: every render primitive returns an empty string and `emit()` writes no files. Use it\n * whenever a `Theme` is needed only for its format-neutral data (`tokens` / `resolveToken` / `model`)\n * and the rendered output is irrelevant — e.g. the `refract tokens` DTCG export.\n */\nexport function createNoopAdapter(): ThemeAdapter<string> {\n return defineAdapter<string>({\n name: \"noop\",\n version: 1,\n bind: () => ({\n recipeName: () => \"\",\n renderRecipe: () => \"\",\n renderVariables: () => \"\",\n join: parts => parts.join(\"\"),\n emit: () => ({ files: {} }),\n }),\n });\n}\n","/**\n * Contrast audit (opt-in) — scores a built theme's colour pairings for **WCAG 2** contrast ratio\n * (the compliance standard) plus an **advisory APCA** Lc reading. It reports; it never mutates the\n * theme and never \"fixes\" a colour. `audit()` returns structured results by default; a caller (or the\n * `refract audit --strict` CLI) can throw on failures.\n *\n * Which pairings: every palette's `base` ↔ `text`, and every recipe's foreground (`color`) ↔\n * background (`background-color` / `background`) across all subsystems' rule-sets (base + state\n * overrides). A side that isn't a derivable colour (`transparent`, a `var()`, a keyword literal) is\n * reported as `skipped`, not a failure.\n *\n * Colour math is inlined here on purpose: `utils.ts` is vendored to consumers (`build/vendor.ts`) and\n * kept dependency-free / minimal, so we don't widen its export surface for a non-vendored sibling. We\n * reuse only the already-exported {@link parseColor}.\n */\nimport type { Theme, Ref } from \"../../core\";\nimport { RefractError } from \"../../core/errors\";\nimport { parseColor, type RGBTuple } from \"./utils\";\n\n// ── WCAG 2.x ──────────────────────────────────────────────────────────────\n// Relative luminance per WCAG 2: linearize each sRGB channel, weight by the luma coefficients.\nconst srgbToLinear = (c: number): number => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));\nconst relLuminance = ([r, g, b]: RGBTuple): number =>\n 0.2126 * srgbToLinear(r / 255) + 0.7152 * srgbToLinear(g / 255) + 0.0722 * srgbToLinear(b / 255);\n\n/** WCAG 2 contrast ratio (1–21) between two sRGB colours; order-independent. */\nconst wcagRatio = (a: RGBTuple, b: RGBTuple): number => {\n const la = relLuminance(a);\n const lb = relLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n};\n\nexport type WcagLevel = \"AAA\" | \"AA\" | \"AA-large\" | \"fail\";\nconst LEVEL_RANK: Record<WcagLevel, number> = { fail: 0, \"AA-large\": 1, AA: 2, AAA: 3 };\n\n/** Map a ratio to a level. For normal text 3–4.5 is \"AA-large\" (passes only at large sizes). */\nconst wcagLevel = (ratio: number, large: boolean): WcagLevel => {\n if (large) return ratio >= 4.5 ? \"AAA\" : ratio >= 3 ? \"AA\" : \"fail\";\n return ratio >= 7 ? \"AAA\" : ratio >= 4.5 ? \"AA\" : ratio >= 3 ? \"AA-large\" : \"fail\";\n};\n\n// ── APCA (advisory) ───────────────────────────────────────────────────────\n// APCA 0.1.9 / formula 0.98G-4g (SAPC). Advisory only — NOT a WCAG substitute — and the draft may\n// still shift, so the constants are pinned here. Returns a signed Lc (polarity-aware).\nconst APCA = {\n mainTRC: 2.4,\n sRco: 0.2126729, sGco: 0.7151522, sBco: 0.072175,\n normBG: 0.56, normTXT: 0.57, revTXT: 0.62, revBG: 0.65,\n blkThrs: 0.022, blkClmp: 1.414,\n scaleBoW: 1.14, loBoWoffset: 0.027,\n scaleWoB: 1.14, loWoBoffset: 0.027,\n deltaYmin: 0.0005, loClip: 0.1,\n} as const;\n\nconst apcaY = ([r, g, b]: RGBTuple): number =>\n APCA.sRco * Math.pow(r / 255, APCA.mainTRC) +\n APCA.sGco * Math.pow(g / 255, APCA.mainTRC) +\n APCA.sBco * Math.pow(b / 255, APCA.mainTRC);\n\n/** Signed APCA lightness contrast (Lc) of `text` over `bg`. Positive = dark-on-light, negative = light-on-dark. */\nconst apcaLc = (text: RGBTuple, bg: RGBTuple): number => {\n const clamp = (y: number): number => (y > APCA.blkThrs ? y : y + Math.pow(APCA.blkThrs - y, APCA.blkClmp));\n const yTxt = clamp(apcaY(text));\n const yBg = clamp(apcaY(bg));\n if (Math.abs(yBg - yTxt) < APCA.deltaYmin) return 0;\n let out: number;\n if (yBg > yTxt) {\n const sapc = (Math.pow(yBg, APCA.normBG) - Math.pow(yTxt, APCA.normTXT)) * APCA.scaleBoW;\n out = sapc < APCA.loClip ? 0 : sapc - APCA.loBoWoffset;\n } else {\n const sapc = (Math.pow(yBg, APCA.revBG) - Math.pow(yTxt, APCA.revTXT)) * APCA.scaleWoB;\n out = sapc > -APCA.loClip ? 0 : sapc + APCA.loWoBoffset;\n }\n return out * 100;\n};\n\n// ── audit ─────────────────────────────────────────────────────────────────\n\nexport type PairingKind = \"palette\" | \"recipe\";\n\nexport interface PairingScore {\n kind: PairingKind;\n /** Human label, e.g. `colors.brand` or `components.buttons.primary (:hover)`. */\n label: string;\n /** Resolved foreground colour string, or `undefined` when it isn't a derivable colour. */\n fg?: string;\n /** Resolved background colour string, or `undefined` when it isn't a derivable colour. */\n bg?: string;\n /** WCAG 2 contrast ratio (1–21, 2 dp). Absent when skipped. */\n wcagRatio?: number;\n /** WCAG level at the configured text size. Absent when skipped. */\n wcagLevel?: WcagLevel;\n /** Advisory APCA Lc (signed, 1 dp). Absent when skipped. */\n apcaLc?: number;\n /** Whether this pairing met the pass bar (`minWcag`). Absent when skipped. */\n pass?: boolean;\n /** Set when a side isn't a derivable colour — then the score fields are absent. */\n skipped?: string;\n}\n\nexport interface AuditOptions {\n /** Throw an aggregated error when any pairing fails, instead of only reporting. Default `false`. */\n strict?: boolean;\n /** Treat the foreground as large text (relaxed WCAG thresholds). Default `false`. */\n largeText?: boolean;\n /** The pass bar. Default `\"AA\"`. `\"AA-large\"` accepts the 3:1 tier. */\n minWcag?: WcagLevel;\n /** Audit component/recipe fg↔bg pairs. Default `true`. */\n includeRecipes?: boolean;\n /** Audit palette base↔text pairs. Default `true`. */\n includePalettes?: boolean;\n}\n\nexport interface AuditResult {\n pairings: PairingScore[];\n summary: {\n total: number;\n passed: number;\n failed: number;\n skipped: number;\n /** The lowest-ratio scored pairing (the worst offender), if any were scored. */\n worst?: PairingScore;\n };\n /** `true` when no scored pairing failed the pass bar. */\n ok: boolean;\n}\n\nconst round = (n: number, dp: number): number => {\n const f = 10 ** dp;\n return Math.round(n * f) / f;\n};\n\n/** Resolve a rule-set declaration `Ref` to a colour string, or `undefined` if it isn't one. */\nconst refToColor = (theme: Theme, ref: Ref): string | undefined => {\n if (ref.ref !== undefined) {\n try {\n return String(theme.resolveToken(ref.ref));\n } catch {\n return undefined;\n }\n }\n if (typeof ref.value === \"string\") return ref.value;\n return undefined;\n};\n\nconst FG_KEY = \"color\";\nconst BG_KEYS = [\"background-color\", \"background\"] as const;\nconst pickBg = (decls: Record<string, Ref> | undefined): Ref | undefined => {\n if (!decls) return undefined;\n for (const k of BG_KEYS) if (decls[k]) return decls[k];\n return undefined;\n};\n\n/** Score one fg/bg pairing (colours already resolved to strings), or a skipped record. */\nconst scorePair = (\n kind: PairingKind,\n label: string,\n fg: string | undefined,\n bg: string | undefined,\n options: Required<Pick<AuditOptions, \"largeText\" | \"minWcag\">>,\n): PairingScore => {\n let fgRgb: RGBTuple | undefined;\n let bgRgb: RGBTuple | undefined;\n try {\n if (fg !== undefined) fgRgb = parseColor(fg).rgb;\n } catch { /* not a derivable colour */ }\n try {\n if (bg !== undefined) bgRgb = parseColor(bg).rgb;\n } catch { /* not a derivable colour */ }\n\n if (!fgRgb || !bgRgb) {\n return { kind, label, fg, bg, skipped: !fgRgb && !bgRgb ? \"no derivable fg/bg\" : !fgRgb ? \"fg not a colour\" : \"bg not a colour\" };\n }\n\n const ratio = wcagRatio(fgRgb, bgRgb);\n const level = wcagLevel(ratio, options.largeText);\n const pass = LEVEL_RANK[level] >= LEVEL_RANK[options.minWcag];\n return {\n kind, label, fg, bg,\n wcagRatio: round(ratio, 2),\n wcagLevel: level,\n apcaLc: round(apcaLc(fgRgb, bgRgb), 1),\n pass,\n };\n};\n\n/**\n * Audit a built theme's colour pairings. Pure — reads `theme.tokens` / `theme.resolveToken` /\n * `theme.model` only. In `strict` mode, throws one aggregated error listing every failing pairing.\n */\nexport const audit = (theme: Theme, options: AuditOptions = {}): AuditResult => {\n const opts = {\n largeText: options.largeText ?? false,\n minWcag: options.minWcag ?? (\"AA\" as WcagLevel),\n };\n const includeRecipes = options.includeRecipes ?? true;\n const includePalettes = options.includePalettes ?? true;\n const pairings: PairingScore[] = [];\n\n // Palettes: base ↔ text. A palette advertises a pairing by having a `colors.<name>.text` token.\n if (includePalettes) {\n for (const path of Object.keys(theme.tokens)) {\n const m = /^colors\\.([^.]+)\\.text$/.exec(path);\n if (!m) continue;\n const base = `colors.${m[1]}`;\n let fg: string | undefined, bg: string | undefined;\n try { fg = String(theme.resolveToken(path)); } catch { /* skip */ }\n try { bg = String(theme.resolveToken(base)); } catch { /* skip */ }\n pairings.push(scorePair(\"palette\", base, fg, bg, opts));\n }\n }\n\n // Recipes: every subsystem's rule-sets — the base declarations + each state/breakpoint override.\n if (includeRecipes) {\n for (const [subsystem, subModel] of Object.entries(theme.model.subsystems)) {\n if (!subModel.ruleSets) continue;\n for (const [group, ruleSetGroup] of Object.entries(subModel.ruleSets)) {\n for (const [variant, ruleSet] of Object.entries(ruleSetGroup)) {\n const baseFg = ruleSet.declarations[FG_KEY];\n const baseBg = pickBg(ruleSet.declarations);\n const label = `${subsystem}.${group}.${variant}`;\n if (baseFg && baseBg) {\n pairings.push(scorePair(\"recipe\", label, refToColor(theme, baseFg), refToColor(theme, baseBg), opts));\n }\n // Overrides (e.g. :hover) can swap bg or fg — score the effective pairing at that condition.\n for (const override of ruleSet.overrides ?? []) {\n const oFg = override.declarations?.[FG_KEY] ?? baseFg;\n const oBg = pickBg(override.declarations) ?? baseBg;\n if (!override.declarations || (!override.declarations[FG_KEY] && !pickBg(override.declarations))) continue;\n if (!oFg || !oBg) continue;\n const cond = override.state ?? override.breakpoint ?? override.query ?? \"override\";\n pairings.push(scorePair(\"recipe\", `${label} (${cond})`, refToColor(theme, oFg), refToColor(theme, oBg), opts));\n }\n }\n }\n }\n }\n\n const scored = pairings.filter(p => !p.skipped);\n const failed = scored.filter(p => p.pass === false);\n const worst = scored.reduce<PairingScore | undefined>(\n (w, p) => (w === undefined || (p.wcagRatio ?? Infinity) < (w.wcagRatio ?? Infinity) ? p : w),\n undefined,\n );\n const result: AuditResult = {\n pairings,\n summary: {\n total: scored.length,\n passed: scored.length - failed.length,\n failed: failed.length,\n skipped: pairings.length - scored.length,\n worst,\n },\n ok: failed.length === 0,\n };\n\n if (options.strict && failed.length > 0) {\n const list = failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`).join(\", \");\n throw new RefractError(\n \"REFRACT_E_AUDIT\",\n `refract audit: ${failed.length} pairing(s) fail WCAG ${opts.minWcag} — ${list}. ` +\n `Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,\n failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`),\n );\n }\n\n return result;\n};\n"],"names":["parseRuleSetReference","reference","subsystem","rest","split","dot","indexOf","group","slice","variant","resolveReference","model","parsed","_c","_a","subsystems","ruleSets","_b","mergeDeclarations","target","source","prop","ref","Object","entries","responsiveKey","o","_d","_e","_f","breakpoint","query","orientation","state","container","size","mergeComponentRuleSet","own","components","RefractError","sources","references","resolved","push","base","states","responsiveByKey","Map","declarations","override","overrides","undefined","key","entry","get","set","responsive","values","seen","Set","referencedPaths","collect","decls","has","add","path","eachRuleSet","out","sub","ruleSet","keys","defineAdapter","spec","name","version","allowedStates","bind","ctx","b","renderAllRecipes","join","map","renderRecipe","renderAllVariables","renderVariables","renderAll","describeUsage","format","summary","recipes","recipeName","createNoopAdapter","parts","emit","files","srgbToLinear","c","Math","pow","relLuminance","r","g","LEVEL_RANK","fail","AA","AAA","APCA","apcaY","apcaLc","text","bg","clamp","y","yTxt","yBg","abs","sapc","round","n","dp","f","refToColor","theme","String","resolveToken","value","FG_KEY","BG_KEYS","pickBg","k","scorePair","kind","label","fg","options","fgRgb","bgRgb","parseColor","rgb","skipped","ratio","a","la","lb","max","min","wcagRatio","level","large","wcagLevel","largeText","pass","minWcag","audit","opts","includeRecipes","pairings","includePalettes","tokens","m","exec","subModel","ruleSetGroup","baseFg","baseBg","oFg","_g","oBg","_h","cond","_l","_j","_k","scored","filter","p","failed","worst","reduce","w","Infinity","result","total","length","passed","ok","strict","list"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The animation subsystem (§10.2).
3
+ *
4
+ * Owns three things: **motion tokens** (`duration`/`easing`/`delay`) via the shared property
5
+ * normalize (like effects — no finalize hook), **animation-shorthand recipes** via `interpretRecipe`,
6
+ * and **keyframes** via the generic `buildStructural` hook (the third `buildStructural` user, after
7
+ * layout + reset). Keyframes are the new Model primitive: a named, ordered `{ stop, declarations }`
8
+ * step list carried on `SubsystemModel.keyframes` — neither a token nor a rule-set. It grows a hook,
9
+ * never the spine. Transitions stay in `effects` (golden-locked).
10
+ */
11
+ import type { Subsystem } from "../../core/subsystem";
12
+ export declare const animationSubsystem: Subsystem;
13
+ export type { AnimationRaw } from "./types";
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Animation's `interpretRecipe` hook (§10.2) — resolves an animation recipe variant into the
3
+ * `animation-*` longhand {@link Ref}s the CSS adapter composes into an `animation:` shorthand.
4
+ *
5
+ * `duration`/`easing`/`delay` name a **variant** of the matching motion-token property (mirrors the
6
+ * effects interpreter's variant-path resolution) → `animation.<prop>[.<variant>]` token-path refs.
7
+ * `keyframes` names a keyframe → an `animation.keyframes.<name>` ref the adapter resolves to the bare
8
+ * keyframe identifier. Remaining `animation-*` literals pass through as `{ value }`. No `var(--…)`
9
+ * strings — the adapter maps paths to vars (and the keyframe ref to a name) at render time.
10
+ */
11
+ import type { InterpretedRecipeVariant } from "../../core/model";
12
+ import type { NormalizedRecipeVariant } from "../../core/normalize";
13
+ import type { RecipeInterpretContext } from "../../core/subsystem";
14
+ import type { AnimationRecipeProps } from "./types";
15
+ /**
16
+ * Interpret one animation recipe variant into base + responsive/state override declarations, each an
17
+ * `animation-*` longhand {@link Ref}. A responsive `variant:` swap inherits the sibling's base
18
+ * declarations (via `ctx.resolveRecipeVariant`), exactly like the effects interpreter.
19
+ */
20
+ export declare const interpretAnimationRecipeVariant: (variantName: string, variant: NormalizedRecipeVariant<AnimationRecipeProps, string>, ctx: RecipeInterpretContext) => InterpretedRecipeVariant<string>;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The animation subsystem's authoring types (§10.2).
3
+ *
4
+ * `animation` owns **motion tokens** (`duration` / `easing` / `delay`, each a regular property with
5
+ * a base + variants, exactly like effects' `transitions`), **keyframes** (the new Model primitive —
6
+ * a named, ordered `@keyframes`-shaped definition), and **animation-shorthand recipes** (a recipe
7
+ * that names a keyframe + motion tokens and lowers to one class carrying an `animation:` shorthand).
8
+ * Transitions stay in `effects` (golden-locked). Authoring type only.
9
+ */
10
+ import type { PropertyValue, RecipeBlock } from "../../core/normalize";
11
+ /** A motion token value — `duration`/`delay` are numbers (ms), `easing` is a string. Base + variants. */
12
+ export type AnimationTokenValue = PropertyValue<string | number>;
13
+ /**
14
+ * One step's declarations — kebab-case CSS property → a **literal** geometric value (`opacity: 0`,
15
+ * `transform: "translateY(20px)"`) or a **token reference** (`{ ref: "colors.surface" }`) resolved
16
+ * late by the adapter, so a keyframe can animate a themed value.
17
+ */
18
+ export type KeyframeStepDeclarations = Record<string, string | number | {
19
+ ref: string;
20
+ }>;
21
+ /**
22
+ * A keyframe definition — step selector (`from` / `to` / `"0%"` / `"50%"` / grouped `"0%, 100%"`) →
23
+ * that step's declarations. Authoring order is preserved into the Model's ordered step list.
24
+ */
25
+ export type KeyframeDefinition = Record<string, KeyframeStepDeclarations>;
26
+ /**
27
+ * An animation recipe declaration block. `keyframes` names a keyframe; `duration`/`easing`/`delay`
28
+ * name a **variant** of the matching motion-token property (`"base"` → the base, `"fast"` → the
29
+ * `fast` variant). The remaining keys are literal `animation-*` sub-properties passed through to the
30
+ * composed shorthand.
31
+ */
32
+ export type AnimationRecipeProps = {
33
+ keyframes?: string;
34
+ duration?: string;
35
+ easing?: string;
36
+ delay?: string;
37
+ iterationCount?: string | number;
38
+ direction?: string;
39
+ fillMode?: string;
40
+ playState?: string;
41
+ [property: string]: string | number | undefined;
42
+ };
43
+ /**
44
+ * The authored `rawTheme.animation` slice. An **open** map: keys are motion-token names
45
+ * (`duration`, `easing`, `delay`), each an {@link AnimationTokenValue}; the reserved `keyframes` key
46
+ * holds the keyframe definitions and the reserved `recipes` key an animation-recipe block.
47
+ */
48
+ export interface AnimationRaw {
49
+ keyframes?: Record<string, KeyframeDefinition>;
50
+ recipes?: RecipeBlock<AnimationRecipeProps>;
51
+ [property: string]: AnimationTokenValue | Record<string, KeyframeDefinition> | RecipeBlock<AnimationRecipeProps> | undefined;
52
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The borders subsystem (§14) — a "regular" subsystem (no property finalize hook; values pass
3
+ * straight through the shared normalize) carved out of effects. Owns the stroke geometry
4
+ * vocabulary (width / style / offset / radius) and interprets border/outline recipes via the
5
+ * `(as, side, aspect)` → css-property computation, with `color` a value-level `colors.*` ref.
6
+ * It grows a hook, never the spine.
7
+ */
8
+ import type { Subsystem } from "../../core/subsystem";
9
+ export declare const bordersSubsystem: Subsystem;
10
+ export type { BordersRaw, BordersPropertyValue } from "./types";
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Borders' `interpretRecipe` hook (§14.2) — resolves recipe declarations to token-path Refs.
3
+ *
4
+ * The novel logic vs a fixed prop→css map: the CSS property is **computed** from
5
+ * `(as, side, aspect)`. `as` (the render target, default `"border"`) + the optional per-side
6
+ * modifier route each geometry aspect to its longhand:
7
+ * - `border` + `left` + `width` → `border-left-width`
8
+ * - `outline` + `width` → `outline-width`
9
+ * - `border` + `radius` → `border-radius` (radius is border-only edge geometry)
10
+ * - `outline` + `offset` → `outline-offset` (offset is outline-only)
11
+ * - `outline` + `color` → `outline-color`
12
+ *
13
+ * Geometry aspects (`width`/`style`/`offset`/`radius`) name a **variant** of the matching borders
14
+ * property by bare name — lowered to a `borders.<aspect>[.<variant>]` {@link Ref}. `color` is the
15
+ * value-level exception (§14.4): its value is already a `colors.*` **token** path, passed straight
16
+ * through as `{ ref: "colors.*" }` — the CSS adapter resolves it against the global path→var map
17
+ * (colors is processed first). No `var(--…)` strings — the adapter maps paths to vars at render.
18
+ */
19
+ import type { InterpretedRecipeVariant } from "../../core/model";
20
+ import type { NormalizedRecipeVariant } from "../../core/normalize";
21
+ import type { RecipeInterpretContext } from "../../core/subsystem";
22
+ import type { BordersRecipeProps } from "./types";
23
+ /**
24
+ * Interpret one borders recipe variant into base + responsive/state override declarations, each a
25
+ * token-path {@link Ref}. `as`/`side` are read from the variant base (the render target is a
26
+ * variant-level identity); a responsive entry may override them, else it inherits the base's. A
27
+ * responsive `variant:` swap inherits the sibling's already-interpreted base declarations.
28
+ */
29
+ export declare const interpretBordersRecipeVariant: (variantName: string, variant: NormalizedRecipeVariant<BordersRecipeProps, string>, ctx: RecipeInterpretContext) => InterpretedRecipeVariant<string>;
@@ -0,0 +1,50 @@
1
+ import type { PropertyValue, RecipeBlock } from "../../core/normalize";
2
+ /**
3
+ * Borders' property + recipe types (§14). A dedicated **stroke** subsystem carved out of the
4
+ * effects grab-bag: border + outline share one geometry vocabulary (width / style / offset /
5
+ * radius), diverging only at the render target (the recipe-level `as` verb). Color is NEVER a
6
+ * borders token — a borders recipe carries a value-level `colors.*` ref instead (§14.4).
7
+ */
8
+ /** border-width / outline-width (px; number, variants). */
9
+ export type BorderWidthValue = PropertyValue<number>;
10
+ /** border-style / outline-style (`solid` / `dashed` / … + `auto` for outlines). */
11
+ export type BorderStyleValue = PropertyValue<string>;
12
+ /** outline-offset (px; only meaningful under `as: "outline"`). */
13
+ export type BorderOffsetValue = PropertyValue<number>;
14
+ /** border-radius (px; **moved in from effects** — edge geometry, §14.1). `9999px`-style strings allowed. */
15
+ export type BorderRadiusValue = PropertyValue<number | string>;
16
+ /**
17
+ * A borders recipe declaration block (§14.2). `as` + `side` are **modifiers**, not aspect
18
+ * declarations: the interpreter computes each CSS property from `(as, side, aspect)` — `border`+
19
+ * `left`+`width` → `border-left-width`, `outline`+`offset` → `outline-offset`. The geometry
20
+ * aspects (`width`/`style`/`offset`/`radius`) name a **variant** of the matching borders property
21
+ * by bare name (`"thick"` → `borders.width.thick`); `color` is the value-level `colors.*` ref.
22
+ */
23
+ export type BordersRecipeProps = {
24
+ /** Render target — `"border"` (default) or `"outline"`. Routes every aspect to its longhand. */
25
+ as?: "border" | "outline";
26
+ /** Per-side modifier (border only) — routes to `border-<side>-{width,style,color}`. */
27
+ side?: "top" | "right" | "bottom" | "left";
28
+ width?: string;
29
+ style?: string;
30
+ offset?: string;
31
+ radius?: string;
32
+ /** Value-level color ref — a `colors.*` **token** path (`"colors.primary"`), never a borders token. */
33
+ color?: string;
34
+ [property: string]: string | undefined;
35
+ };
36
+ /**
37
+ * A borders property value (§8a / §14). Borders geometry spans numbers and strings
38
+ * (`width`/`offset` numbers, `radius` `number | string`, `style` strings), so the value unions
39
+ * `string | number`.
40
+ */
41
+ export type BordersPropertyValue = PropertyValue<string | number>;
42
+ /**
43
+ * The authored `raw.borders` slice (§8a / §14). An **open** map: keys are borders property names
44
+ * (`width`, `style`, `offset`, `radius`), each a {@link BordersPropertyValue}; the reserved
45
+ * `recipes` key is a {@link RecipeBlock} of borders recipes. Authoring type only.
46
+ */
47
+ export interface BordersRaw {
48
+ recipes?: RecipeBlock<BordersRecipeProps>;
49
+ [property: string]: BordersPropertyValue | RecipeBlock<BordersRecipeProps> | undefined;
50
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Contrast audit (opt-in) — scores a built theme's colour pairings for **WCAG 2** contrast ratio
3
+ * (the compliance standard) plus an **advisory APCA** Lc reading. It reports; it never mutates the
4
+ * theme and never "fixes" a colour. `audit()` returns structured results by default; a caller (or the
5
+ * `refract audit --strict` CLI) can throw on failures.
6
+ *
7
+ * Which pairings: every palette's `base` ↔ `text`, and every recipe's foreground (`color`) ↔
8
+ * background (`background-color` / `background`) across all subsystems' rule-sets (base + state
9
+ * overrides). A side that isn't a derivable colour (`transparent`, a `var()`, a keyword literal) is
10
+ * reported as `skipped`, not a failure.
11
+ *
12
+ * Colour math is inlined here on purpose: `utils.ts` is vendored to consumers (`build/vendor.ts`) and
13
+ * kept dependency-free / minimal, so we don't widen its export surface for a non-vendored sibling. We
14
+ * reuse only the already-exported {@link parseColor}.
15
+ */
16
+ import type { Theme } from "../../core";
17
+ export type WcagLevel = "AAA" | "AA" | "AA-large" | "fail";
18
+ export type PairingKind = "palette" | "recipe";
19
+ export interface PairingScore {
20
+ kind: PairingKind;
21
+ /** Human label, e.g. `colors.brand` or `components.buttons.primary (:hover)`. */
22
+ label: string;
23
+ /** Resolved foreground colour string, or `undefined` when it isn't a derivable colour. */
24
+ fg?: string;
25
+ /** Resolved background colour string, or `undefined` when it isn't a derivable colour. */
26
+ bg?: string;
27
+ /** WCAG 2 contrast ratio (1–21, 2 dp). Absent when skipped. */
28
+ wcagRatio?: number;
29
+ /** WCAG level at the configured text size. Absent when skipped. */
30
+ wcagLevel?: WcagLevel;
31
+ /** Advisory APCA Lc (signed, 1 dp). Absent when skipped. */
32
+ apcaLc?: number;
33
+ /** Whether this pairing met the pass bar (`minWcag`). Absent when skipped. */
34
+ pass?: boolean;
35
+ /** Set when a side isn't a derivable colour — then the score fields are absent. */
36
+ skipped?: string;
37
+ }
38
+ export interface AuditOptions {
39
+ /** Throw an aggregated error when any pairing fails, instead of only reporting. Default `false`. */
40
+ strict?: boolean;
41
+ /** Treat the foreground as large text (relaxed WCAG thresholds). Default `false`. */
42
+ largeText?: boolean;
43
+ /** The pass bar. Default `"AA"`. `"AA-large"` accepts the 3:1 tier. */
44
+ minWcag?: WcagLevel;
45
+ /** Audit component/recipe fg↔bg pairs. Default `true`. */
46
+ includeRecipes?: boolean;
47
+ /** Audit palette base↔text pairs. Default `true`. */
48
+ includePalettes?: boolean;
49
+ }
50
+ export interface AuditResult {
51
+ pairings: PairingScore[];
52
+ summary: {
53
+ total: number;
54
+ passed: number;
55
+ failed: number;
56
+ skipped: number;
57
+ /** The lowest-ratio scored pairing (the worst offender), if any were scored. */
58
+ worst?: PairingScore;
59
+ };
60
+ /** `true` when no scored pairing failed the pass bar. */
61
+ ok: boolean;
62
+ }
63
+ /**
64
+ * Audit a built theme's colour pairings. Pure — reads `theme.tokens` / `theme.resolveToken` /
65
+ * `theme.model` only. In `strict` mode, throws one aggregated error listing every failing pairing.
66
+ */
67
+ export declare const audit: (theme: Theme, options?: AuditOptions) => AuditResult;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Build-time colour **input** parsing.
3
+ *
4
+ * Kept out of `utils.ts` on purpose: `utils.ts` is vendored to consumers (see `build/vendor.ts`) and
5
+ * must stay import-free, but input parsing needs the CSS-keyword table. `coerceColorInput` normalizes
6
+ * any authored colour — hex, `[r, g, b]`, `oklch()`, `hsl()/hsla()`, `rgb()/rgba()`, or a CSS named
7
+ * keyword — to the subsystem's canonical `rgb()` / `rgba()` form (derivation still runs in OKLCH). A
8
+ * `var(--…)` (and `currentColor` / `transparent`) is rejected — none can be tonally derived at build.
9
+ */
10
+ import { type RGBTuple } from "./utils";
11
+ /**
12
+ * Coerce an authored colour value to the canonical `rgb(r, g, b)` / `rgba(…)` string. A colour may be a
13
+ * hex string (`"#4dabf7"` / `"#4af"`), an `[r, g, b]` tuple (0–255), or any CSS colour — `oklch()`,
14
+ * `hsl()/hsla()`, `rgb()/rgba()`, or a named keyword (`"rebeccapurple"`). Only a `var(--…)` (and
15
+ * `currentColor` / `transparent`) is rejected. Applies to base + `text` + literal variants/modes.
16
+ */
17
+ export declare const coerceColorInput: (value: string | RGBTuple) => string;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The colors subsystem (Step 0d — properties only).
3
+ *
4
+ * Iterates `raw.colors` (skipping the reserved `recipes` key), running the shared
5
+ * property normalize + colors' palette-step synthesis per colour. Recipes / CSS
6
+ * lowering land in Step 1; this file grows a hook, never the spine.
7
+ */
8
+ import type { Subsystem } from "../../core/subsystem";
9
+ export declare const colorsSubsystem: Subsystem;
10
+ export type { ColorsRaw } from "./types";
11
+ export { audit } from "./audit";
12
+ export type { AuditResult, AuditOptions, PairingScore, PairingKind, WcagLevel } from "./audit";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The CSS named colours (CSS Color Module Level 4 `<named-color>` list), mapped to their canonical
3
+ * 6-digit hex. Authored colours may be given by keyword (`rebeccapurple`, `tomato`, …); the input
4
+ * gate normalizes them to the subsystem's canonical `rgb()` form like any other input.
5
+ *
6
+ * `transparent` and `currentColor` are intentionally absent — neither is an opaque, tonally-derivable
7
+ * colour, so they fall through to the input gate's rejection with a clear message.
8
+ */
9
+ export declare const CSS_COLOR_KEYWORDS: Record<string, string>;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Colors' `normalizeProperty` hook — palette variant synthesis (§13).
3
+ *
4
+ * After the shared normalize pass, each palette colour synthesizes its variants:
5
+ * - **auto variants** — numeric tonal `steps` (`100…900`) when declared, else the default named
6
+ * set (`light` / `lighter` / `dark` / `darker`);
7
+ * - **derivation-spec variants** — authored `{ darken | lighten | alpha, ref? }` (§13.3), each
8
+ * resolved against its source (base by default, or another variant via `ref`).
9
+ *
10
+ * Every generated variant carries both its baked value (for the CSS lowering today) and `derive`
11
+ * metadata (`{ ref, fn, arg }`) so the Model stores it as a derived `Ref` that re-resolves for free
12
+ * when its source is overridden. All colour maths runs in rgb space (see `./utils`); a colour that
13
+ * carries derivations must have a parseable rgb base (hex or `[r,g,b]`).
14
+ */
15
+ import type { NormalizedPaletteValue, PaletteDerivationSpec } from "./types";
16
+ /**
17
+ * Merge synthesized variants (auto + derivation-spec) and baked modes into a normalized palette
18
+ * colour. Author-declared variants win over generated ones on name collision. Returns the input
19
+ * unchanged when nothing is produced (a plain non-derivable colour stays byte-identical).
20
+ *
21
+ * @param name The colour's property name — used to build token paths (`colors.<name>.<v>`).
22
+ * @param normalized The colour after the shared property normalize pass (base already coerced).
23
+ * @param derivationSpecs Authored `{ darken|lighten|alpha, ref? }` variants, split out upstream
24
+ * (core normalize can't interpret them — they have no `base`).
25
+ */
26
+ export declare const finalizePaletteNormalization: (name: string, normalized0: NormalizedPaletteValue, derivationSpecs?: Record<string, PaletteDerivationSpec>) => NormalizedPaletteValue;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Colors' `interpretRecipe` hook — resolves palette recipe declarations to Refs.
3
+ *
4
+ * A palette recipe prop value either **names a palette reference** (`"primary"`,
5
+ * `"primary.text"`, `"neutral.light"`) or is a literal. This interpreter emits a
6
+ * format-neutral {@link Ref} for each declaration — a **canonical token path**
7
+ * (`{ ref: "colors.primary", value: "#4dabf7" }`) for a reference, or `{ value }` for a
8
+ * literal. It emits refs **directly** (no `var(--…)` strings); the CSS adapter maps the
9
+ * token path to a `var(--…)` at render time. So `theme.model` carries no CSS syntax.
10
+ */
11
+ import type { InterpretedRecipeVariant } from "../../core/model";
12
+ import type { NormalizedRecipeVariant } from "../../core/normalize";
13
+ import type { RecipeInterpretContext } from "../../core/subsystem";
14
+ import type { PaletteRecipeProps } from "./types";
15
+ /**
16
+ * Interpret one palette recipe variant into base + responsive/state override declarations,
17
+ * each a token-path {@link Ref}. Sibling `variant:` swaps inherit the sibling's base
18
+ * declarations (via `ctx.resolveRecipeVariant`); a `target` may only scope to the variant
19
+ * itself.
20
+ */
21
+ export declare const interpretPaletteRecipeVariant: (variantName: string, variant: NormalizedRecipeVariant<PaletteRecipeProps, string>, ctx: RecipeInterpretContext) => InterpretedRecipeVariant<string>;