@datatechsolutions/tympan-tokens 0.3.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 (329) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +318 -0
  3. package/dist/contrast-report.md +13955 -0
  4. package/dist/dtcg/astrlabe.dark-high.tokens.json +2947 -0
  5. package/dist/dtcg/astrlabe.dark.tokens.json +2947 -0
  6. package/dist/dtcg/astrlabe.light-high.tokens.json +2947 -0
  7. package/dist/dtcg/astrlabe.light.tokens.json +2947 -0
  8. package/dist/dtcg/base.tokens.json +422 -0
  9. package/dist/dtcg/density.comfortable.tokens.json +48 -0
  10. package/dist/dtcg/density.compact.tokens.json +48 -0
  11. package/dist/dtcg/density.default.tokens.json +48 -0
  12. package/dist/dtcg/fakhir.dark-high.tokens.json +2971 -0
  13. package/dist/dtcg/fakhir.dark.tokens.json +2971 -0
  14. package/dist/dtcg/fakhir.light-high.tokens.json +2971 -0
  15. package/dist/dtcg/fakhir.light.tokens.json +2971 -0
  16. package/dist/dtcg/flow.tokens.json +675 -0
  17. package/dist/dtcg/high-contrast.dark.tokens.json +2943 -0
  18. package/dist/dtcg/high-contrast.light.tokens.json +2943 -0
  19. package/dist/dtcg/neutral.dark-high.tokens.json +2947 -0
  20. package/dist/dtcg/neutral.dark.tokens.json +2947 -0
  21. package/dist/dtcg/neutral.light-high.tokens.json +2947 -0
  22. package/dist/dtcg/neutral.light.tokens.json +2947 -0
  23. package/dist/dtcg/print/print-aquarela.dark.tokens.json +3014 -0
  24. package/dist/dtcg/print/print-aquarela.light.tokens.json +3009 -0
  25. package/dist/dtcg/print/print-art-nouveau.dark.tokens.json +2944 -0
  26. package/dist/dtcg/print/print-art-nouveau.light.tokens.json +2944 -0
  27. package/dist/dtcg/print/print-atlas-oficial.dark.tokens.json +2945 -0
  28. package/dist/dtcg/print/print-atlas-oficial.light.tokens.json +2945 -0
  29. package/dist/dtcg/print/print-azulejo-modernista.dark.tokens.json +2946 -0
  30. package/dist/dtcg/print/print-azulejo-modernista.light.tokens.json +2946 -0
  31. package/dist/dtcg/print/print-bauhaus.dark.tokens.json +2946 -0
  32. package/dist/dtcg/print/print-bauhaus.light.tokens.json +2942 -0
  33. package/dist/dtcg/print/print-blocos-coloridos.dark.tokens.json +2974 -0
  34. package/dist/dtcg/print/print-blocos-coloridos.light.tokens.json +2967 -0
  35. package/dist/dtcg/print/print-brutalista.dark.tokens.json +2956 -0
  36. package/dist/dtcg/print/print-brutalista.light.tokens.json +2956 -0
  37. package/dist/dtcg/print/print-caderno.dark.tokens.json +2958 -0
  38. package/dist/dtcg/print/print-caderno.light.tokens.json +2954 -0
  39. package/dist/dtcg/print/print-cartao-postal.dark.tokens.json +2958 -0
  40. package/dist/dtcg/print/print-cartao-postal.light.tokens.json +2954 -0
  41. package/dist/dtcg/print/print-cientifico.dark.tokens.json +2944 -0
  42. package/dist/dtcg/print/print-cientifico.light.tokens.json +2944 -0
  43. package/dist/dtcg/print/print-concretismo.dark.tokens.json +2946 -0
  44. package/dist/dtcg/print/print-concretismo.light.tokens.json +2942 -0
  45. package/dist/dtcg/print/print-construtivismo.dark.tokens.json +2946 -0
  46. package/dist/dtcg/print/print-construtivismo.light.tokens.json +2946 -0
  47. package/dist/dtcg/print/print-cordel.dark.tokens.json +2958 -0
  48. package/dist/dtcg/print/print-cordel.light.tokens.json +2954 -0
  49. package/dist/dtcg/print/print-dados-br.dark.tokens.json +2959 -0
  50. package/dist/dtcg/print/print-dados-br.light.tokens.json +2956 -0
  51. package/dist/dtcg/print/print-dashboard.dark.tokens.json +3015 -0
  52. package/dist/dtcg/print/print-dashboard.light.tokens.json +3007 -0
  53. package/dist/dtcg/print/print-diagrama-modernista.dark.tokens.json +2946 -0
  54. package/dist/dtcg/print/print-diagrama-modernista.light.tokens.json +2942 -0
  55. package/dist/dtcg/print/print-divulgacao.dark.tokens.json +2942 -0
  56. package/dist/dtcg/print/print-divulgacao.light.tokens.json +2938 -0
  57. package/dist/dtcg/print/print-fluxo-historico.dark.tokens.json +2944 -0
  58. package/dist/dtcg/print/print-fluxo-historico.light.tokens.json +2941 -0
  59. package/dist/dtcg/print/print-grade-holandesa.dark.tokens.json +2946 -0
  60. package/dist/dtcg/print/print-grade-holandesa.light.tokens.json +2942 -0
  61. package/dist/dtcg/print/print-graficos-1900.dark.tokens.json +2959 -0
  62. package/dist/dtcg/print/print-graficos-1900.light.tokens.json +2955 -0
  63. package/dist/dtcg/print/print-infografico-ilustrado.dark.tokens.json +2974 -0
  64. package/dist/dtcg/print/print-infografico-ilustrado.light.tokens.json +2970 -0
  65. package/dist/dtcg/print/print-isotype.dark.tokens.json +2946 -0
  66. package/dist/dtcg/print/print-isotype.light.tokens.json +2946 -0
  67. package/dist/dtcg/print/print-jornal-1959.dark.tokens.json +2944 -0
  68. package/dist/dtcg/print/print-jornal-1959.light.tokens.json +2944 -0
  69. package/dist/dtcg/print/print-jornal.dark.tokens.json +2958 -0
  70. package/dist/dtcg/print/print-jornal.light.tokens.json +2951 -0
  71. package/dist/dtcg/print/print-mapa-de-metro.dark.tokens.json +2946 -0
  72. package/dist/dtcg/print/print-mapa-de-metro.light.tokens.json +2946 -0
  73. package/dist/dtcg/print/print-memphis.dark.tokens.json +2942 -0
  74. package/dist/dtcg/print/print-memphis.light.tokens.json +2938 -0
  75. package/dist/dtcg/print/print-minimo-de-tinta.dark.tokens.json +2958 -0
  76. package/dist/dtcg/print/print-minimo-de-tinta.light.tokens.json +2951 -0
  77. package/dist/dtcg/print/print-papel-recortado.dark.tokens.json +2946 -0
  78. package/dist/dtcg/print/print-papel-recortado.light.tokens.json +2942 -0
  79. package/dist/dtcg/print/print-papel-salmao.dark.tokens.json +2944 -0
  80. package/dist/dtcg/print/print-papel-salmao.light.tokens.json +2941 -0
  81. package/dist/dtcg/print/print-pictogramas.dark.tokens.json +2946 -0
  82. package/dist/dtcg/print/print-pictogramas.light.tokens.json +2942 -0
  83. package/dist/dtcg/print/print-pop-art.dark.tokens.json +2942 -0
  84. package/dist/dtcg/print/print-pop-art.light.tokens.json +2938 -0
  85. package/dist/dtcg/print/print-prancheta-clara.dark.tokens.json +2960 -0
  86. package/dist/dtcg/print/print-prancheta-clara.light.tokens.json +2956 -0
  87. package/dist/dtcg/print/print-prancheta.dark.tokens.json +2956 -0
  88. package/dist/dtcg/print/print-prancheta.light.tokens.json +2960 -0
  89. package/dist/dtcg/print/print-proporcao-modular.dark.tokens.json +2945 -0
  90. package/dist/dtcg/print/print-proporcao-modular.light.tokens.json +2941 -0
  91. package/dist/dtcg/print/print-riso.dark.tokens.json +2960 -0
  92. package/dist/dtcg/print/print-riso.light.tokens.json +2956 -0
  93. package/dist/dtcg/print/print-semanario.dark.tokens.json +2944 -0
  94. package/dist/dtcg/print/print-semanario.light.tokens.json +2937 -0
  95. package/dist/dtcg/print/print-sinalizacao.dark.tokens.json +2946 -0
  96. package/dist/dtcg/print/print-sinalizacao.light.tokens.json +2942 -0
  97. package/dist/dtcg/print/print-suico.dark.tokens.json +2960 -0
  98. package/dist/dtcg/print/print-suico.light.tokens.json +2956 -0
  99. package/dist/dtcg/print/print-tropicalia.dark.tokens.json +2945 -0
  100. package/dist/dtcg/print/print-tropicalia.light.tokens.json +2941 -0
  101. package/dist/dtcg/print-aquarela.dark-high.tokens.json +3014 -0
  102. package/dist/dtcg/print-aquarela.dark.tokens.json +3014 -0
  103. package/dist/dtcg/print-aquarela.light-high.tokens.json +3014 -0
  104. package/dist/dtcg/print-aquarela.light.tokens.json +3009 -0
  105. package/dist/dtcg/print-art-nouveau.dark-high.tokens.json +2944 -0
  106. package/dist/dtcg/print-art-nouveau.dark.tokens.json +2944 -0
  107. package/dist/dtcg/print-art-nouveau.light-high.tokens.json +2944 -0
  108. package/dist/dtcg/print-art-nouveau.light.tokens.json +2944 -0
  109. package/dist/dtcg/print-atlas-oficial.dark-high.tokens.json +2945 -0
  110. package/dist/dtcg/print-atlas-oficial.dark.tokens.json +2945 -0
  111. package/dist/dtcg/print-atlas-oficial.light-high.tokens.json +2945 -0
  112. package/dist/dtcg/print-atlas-oficial.light.tokens.json +2945 -0
  113. package/dist/dtcg/print-azulejo-modernista.dark-high.tokens.json +2946 -0
  114. package/dist/dtcg/print-azulejo-modernista.dark.tokens.json +2946 -0
  115. package/dist/dtcg/print-azulejo-modernista.light-high.tokens.json +2946 -0
  116. package/dist/dtcg/print-azulejo-modernista.light.tokens.json +2946 -0
  117. package/dist/dtcg/print-bauhaus.dark-high.tokens.json +2946 -0
  118. package/dist/dtcg/print-bauhaus.dark.tokens.json +2946 -0
  119. package/dist/dtcg/print-bauhaus.light-high.tokens.json +2946 -0
  120. package/dist/dtcg/print-bauhaus.light.tokens.json +2942 -0
  121. package/dist/dtcg/print-blocos-coloridos.dark-high.tokens.json +2974 -0
  122. package/dist/dtcg/print-blocos-coloridos.dark.tokens.json +2974 -0
  123. package/dist/dtcg/print-blocos-coloridos.light-high.tokens.json +2974 -0
  124. package/dist/dtcg/print-blocos-coloridos.light.tokens.json +2967 -0
  125. package/dist/dtcg/print-brutalista.dark-high.tokens.json +2956 -0
  126. package/dist/dtcg/print-brutalista.dark.tokens.json +2956 -0
  127. package/dist/dtcg/print-brutalista.light-high.tokens.json +2956 -0
  128. package/dist/dtcg/print-brutalista.light.tokens.json +2956 -0
  129. package/dist/dtcg/print-caderno.dark-high.tokens.json +2958 -0
  130. package/dist/dtcg/print-caderno.dark.tokens.json +2958 -0
  131. package/dist/dtcg/print-caderno.light-high.tokens.json +2958 -0
  132. package/dist/dtcg/print-caderno.light.tokens.json +2954 -0
  133. package/dist/dtcg/print-cartao-postal.dark-high.tokens.json +2958 -0
  134. package/dist/dtcg/print-cartao-postal.dark.tokens.json +2958 -0
  135. package/dist/dtcg/print-cartao-postal.light-high.tokens.json +2958 -0
  136. package/dist/dtcg/print-cartao-postal.light.tokens.json +2954 -0
  137. package/dist/dtcg/print-cientifico.dark-high.tokens.json +2944 -0
  138. package/dist/dtcg/print-cientifico.dark.tokens.json +2944 -0
  139. package/dist/dtcg/print-cientifico.light-high.tokens.json +2944 -0
  140. package/dist/dtcg/print-cientifico.light.tokens.json +2944 -0
  141. package/dist/dtcg/print-concretismo.dark-high.tokens.json +2946 -0
  142. package/dist/dtcg/print-concretismo.dark.tokens.json +2946 -0
  143. package/dist/dtcg/print-concretismo.light-high.tokens.json +2946 -0
  144. package/dist/dtcg/print-concretismo.light.tokens.json +2942 -0
  145. package/dist/dtcg/print-construtivismo.dark-high.tokens.json +2946 -0
  146. package/dist/dtcg/print-construtivismo.dark.tokens.json +2946 -0
  147. package/dist/dtcg/print-construtivismo.light-high.tokens.json +2946 -0
  148. package/dist/dtcg/print-construtivismo.light.tokens.json +2946 -0
  149. package/dist/dtcg/print-cordel.dark-high.tokens.json +2958 -0
  150. package/dist/dtcg/print-cordel.dark.tokens.json +2958 -0
  151. package/dist/dtcg/print-cordel.light-high.tokens.json +2958 -0
  152. package/dist/dtcg/print-cordel.light.tokens.json +2954 -0
  153. package/dist/dtcg/print-dados-br.dark-high.tokens.json +2959 -0
  154. package/dist/dtcg/print-dados-br.dark.tokens.json +2959 -0
  155. package/dist/dtcg/print-dados-br.light-high.tokens.json +2959 -0
  156. package/dist/dtcg/print-dados-br.light.tokens.json +2956 -0
  157. package/dist/dtcg/print-dashboard.dark-high.tokens.json +3015 -0
  158. package/dist/dtcg/print-dashboard.dark.tokens.json +3015 -0
  159. package/dist/dtcg/print-dashboard.light-high.tokens.json +3015 -0
  160. package/dist/dtcg/print-dashboard.light.tokens.json +3007 -0
  161. package/dist/dtcg/print-diagrama-modernista.dark-high.tokens.json +2946 -0
  162. package/dist/dtcg/print-diagrama-modernista.dark.tokens.json +2946 -0
  163. package/dist/dtcg/print-diagrama-modernista.light-high.tokens.json +2946 -0
  164. package/dist/dtcg/print-diagrama-modernista.light.tokens.json +2942 -0
  165. package/dist/dtcg/print-divulgacao.dark-high.tokens.json +2942 -0
  166. package/dist/dtcg/print-divulgacao.dark.tokens.json +2942 -0
  167. package/dist/dtcg/print-divulgacao.light-high.tokens.json +2942 -0
  168. package/dist/dtcg/print-divulgacao.light.tokens.json +2938 -0
  169. package/dist/dtcg/print-fluxo-historico.dark-high.tokens.json +2944 -0
  170. package/dist/dtcg/print-fluxo-historico.dark.tokens.json +2944 -0
  171. package/dist/dtcg/print-fluxo-historico.light-high.tokens.json +2944 -0
  172. package/dist/dtcg/print-fluxo-historico.light.tokens.json +2941 -0
  173. package/dist/dtcg/print-grade-holandesa.dark-high.tokens.json +2946 -0
  174. package/dist/dtcg/print-grade-holandesa.dark.tokens.json +2946 -0
  175. package/dist/dtcg/print-grade-holandesa.light-high.tokens.json +2946 -0
  176. package/dist/dtcg/print-grade-holandesa.light.tokens.json +2942 -0
  177. package/dist/dtcg/print-graficos-1900.dark-high.tokens.json +2959 -0
  178. package/dist/dtcg/print-graficos-1900.dark.tokens.json +2959 -0
  179. package/dist/dtcg/print-graficos-1900.light-high.tokens.json +2959 -0
  180. package/dist/dtcg/print-graficos-1900.light.tokens.json +2955 -0
  181. package/dist/dtcg/print-infografico-ilustrado.dark-high.tokens.json +2974 -0
  182. package/dist/dtcg/print-infografico-ilustrado.dark.tokens.json +2974 -0
  183. package/dist/dtcg/print-infografico-ilustrado.light-high.tokens.json +2974 -0
  184. package/dist/dtcg/print-infografico-ilustrado.light.tokens.json +2970 -0
  185. package/dist/dtcg/print-isotype.dark-high.tokens.json +2946 -0
  186. package/dist/dtcg/print-isotype.dark.tokens.json +2946 -0
  187. package/dist/dtcg/print-isotype.light-high.tokens.json +2946 -0
  188. package/dist/dtcg/print-isotype.light.tokens.json +2946 -0
  189. package/dist/dtcg/print-jornal-1959.dark-high.tokens.json +2944 -0
  190. package/dist/dtcg/print-jornal-1959.dark.tokens.json +2944 -0
  191. package/dist/dtcg/print-jornal-1959.light-high.tokens.json +2944 -0
  192. package/dist/dtcg/print-jornal-1959.light.tokens.json +2944 -0
  193. package/dist/dtcg/print-jornal.dark-high.tokens.json +2958 -0
  194. package/dist/dtcg/print-jornal.dark.tokens.json +2958 -0
  195. package/dist/dtcg/print-jornal.light-high.tokens.json +2958 -0
  196. package/dist/dtcg/print-jornal.light.tokens.json +2951 -0
  197. package/dist/dtcg/print-mapa-de-metro.dark-high.tokens.json +2946 -0
  198. package/dist/dtcg/print-mapa-de-metro.dark.tokens.json +2946 -0
  199. package/dist/dtcg/print-mapa-de-metro.light-high.tokens.json +2946 -0
  200. package/dist/dtcg/print-mapa-de-metro.light.tokens.json +2946 -0
  201. package/dist/dtcg/print-memphis.dark-high.tokens.json +2942 -0
  202. package/dist/dtcg/print-memphis.dark.tokens.json +2942 -0
  203. package/dist/dtcg/print-memphis.light-high.tokens.json +2942 -0
  204. package/dist/dtcg/print-memphis.light.tokens.json +2938 -0
  205. package/dist/dtcg/print-minimo-de-tinta.dark-high.tokens.json +2958 -0
  206. package/dist/dtcg/print-minimo-de-tinta.dark.tokens.json +2958 -0
  207. package/dist/dtcg/print-minimo-de-tinta.light-high.tokens.json +2958 -0
  208. package/dist/dtcg/print-minimo-de-tinta.light.tokens.json +2951 -0
  209. package/dist/dtcg/print-papel-recortado.dark-high.tokens.json +2946 -0
  210. package/dist/dtcg/print-papel-recortado.dark.tokens.json +2946 -0
  211. package/dist/dtcg/print-papel-recortado.light-high.tokens.json +2946 -0
  212. package/dist/dtcg/print-papel-recortado.light.tokens.json +2942 -0
  213. package/dist/dtcg/print-papel-salmao.dark-high.tokens.json +2944 -0
  214. package/dist/dtcg/print-papel-salmao.dark.tokens.json +2944 -0
  215. package/dist/dtcg/print-papel-salmao.light-high.tokens.json +2944 -0
  216. package/dist/dtcg/print-papel-salmao.light.tokens.json +2941 -0
  217. package/dist/dtcg/print-pictogramas.dark-high.tokens.json +2946 -0
  218. package/dist/dtcg/print-pictogramas.dark.tokens.json +2946 -0
  219. package/dist/dtcg/print-pictogramas.light-high.tokens.json +2946 -0
  220. package/dist/dtcg/print-pictogramas.light.tokens.json +2942 -0
  221. package/dist/dtcg/print-pop-art.dark-high.tokens.json +2942 -0
  222. package/dist/dtcg/print-pop-art.dark.tokens.json +2942 -0
  223. package/dist/dtcg/print-pop-art.light-high.tokens.json +2942 -0
  224. package/dist/dtcg/print-pop-art.light.tokens.json +2938 -0
  225. package/dist/dtcg/print-prancheta-clara.dark-high.tokens.json +2960 -0
  226. package/dist/dtcg/print-prancheta-clara.dark.tokens.json +2960 -0
  227. package/dist/dtcg/print-prancheta-clara.light-high.tokens.json +2960 -0
  228. package/dist/dtcg/print-prancheta-clara.light.tokens.json +2956 -0
  229. package/dist/dtcg/print-prancheta.dark-high.tokens.json +2960 -0
  230. package/dist/dtcg/print-prancheta.dark.tokens.json +2956 -0
  231. package/dist/dtcg/print-prancheta.light-high.tokens.json +2960 -0
  232. package/dist/dtcg/print-prancheta.light.tokens.json +2960 -0
  233. package/dist/dtcg/print-proporcao-modular.dark-high.tokens.json +2945 -0
  234. package/dist/dtcg/print-proporcao-modular.dark.tokens.json +2945 -0
  235. package/dist/dtcg/print-proporcao-modular.light-high.tokens.json +2945 -0
  236. package/dist/dtcg/print-proporcao-modular.light.tokens.json +2941 -0
  237. package/dist/dtcg/print-riso.dark-high.tokens.json +2960 -0
  238. package/dist/dtcg/print-riso.dark.tokens.json +2960 -0
  239. package/dist/dtcg/print-riso.light-high.tokens.json +2960 -0
  240. package/dist/dtcg/print-riso.light.tokens.json +2956 -0
  241. package/dist/dtcg/print-semanario.dark-high.tokens.json +2944 -0
  242. package/dist/dtcg/print-semanario.dark.tokens.json +2944 -0
  243. package/dist/dtcg/print-semanario.light-high.tokens.json +2944 -0
  244. package/dist/dtcg/print-semanario.light.tokens.json +2937 -0
  245. package/dist/dtcg/print-sinalizacao.dark-high.tokens.json +2946 -0
  246. package/dist/dtcg/print-sinalizacao.dark.tokens.json +2946 -0
  247. package/dist/dtcg/print-sinalizacao.light-high.tokens.json +2946 -0
  248. package/dist/dtcg/print-sinalizacao.light.tokens.json +2942 -0
  249. package/dist/dtcg/print-suico.dark-high.tokens.json +2960 -0
  250. package/dist/dtcg/print-suico.dark.tokens.json +2960 -0
  251. package/dist/dtcg/print-suico.light-high.tokens.json +2960 -0
  252. package/dist/dtcg/print-suico.light.tokens.json +2956 -0
  253. package/dist/dtcg/print-tropicalia.dark-high.tokens.json +2945 -0
  254. package/dist/dtcg/print-tropicalia.dark.tokens.json +2945 -0
  255. package/dist/dtcg/print-tropicalia.light-high.tokens.json +2945 -0
  256. package/dist/dtcg/print-tropicalia.light.tokens.json +2941 -0
  257. package/dist/dtcg/tympan.dark-high.tokens.json +2971 -0
  258. package/dist/dtcg/tympan.dark.tokens.json +2971 -0
  259. package/dist/dtcg/tympan.light-high.tokens.json +2971 -0
  260. package/dist/dtcg/tympan.light.tokens.json +2971 -0
  261. package/dist/index.d.ts +642 -0
  262. package/dist/index.js +4873 -0
  263. package/dist/index.js.map +1 -0
  264. package/dist/print-aliases.d.ts +54 -0
  265. package/dist/print-aliases.js +71 -0
  266. package/dist/print-aliases.js.map +1 -0
  267. package/dist/print-themes/print-aquarela.css +1483 -0
  268. package/dist/print-themes/print-art-nouveau.css +1467 -0
  269. package/dist/print-themes/print-atlas-oficial.css +1467 -0
  270. package/dist/print-themes/print-azulejo-modernista.css +1467 -0
  271. package/dist/print-themes/print-bauhaus.css +1467 -0
  272. package/dist/print-themes/print-blocos-coloridos.css +1467 -0
  273. package/dist/print-themes/print-brutalista.css +1475 -0
  274. package/dist/print-themes/print-caderno.css +1483 -0
  275. package/dist/print-themes/print-cartao-postal.css +1483 -0
  276. package/dist/print-themes/print-cientifico.css +1467 -0
  277. package/dist/print-themes/print-concretismo.css +1467 -0
  278. package/dist/print-themes/print-construtivismo.css +1467 -0
  279. package/dist/print-themes/print-cordel.css +1483 -0
  280. package/dist/print-themes/print-dados-br.css +1475 -0
  281. package/dist/print-themes/print-dashboard.css +1475 -0
  282. package/dist/print-themes/print-diagrama-modernista.css +1467 -0
  283. package/dist/print-themes/print-divulgacao.css +1467 -0
  284. package/dist/print-themes/print-fluxo-historico.css +1475 -0
  285. package/dist/print-themes/print-grade-holandesa.css +1475 -0
  286. package/dist/print-themes/print-graficos-1900.css +1483 -0
  287. package/dist/print-themes/print-infografico-ilustrado.css +1467 -0
  288. package/dist/print-themes/print-isotype.css +1467 -0
  289. package/dist/print-themes/print-jornal-1959.css +1467 -0
  290. package/dist/print-themes/print-jornal.css +1475 -0
  291. package/dist/print-themes/print-mapa-de-metro.css +1467 -0
  292. package/dist/print-themes/print-memphis.css +1467 -0
  293. package/dist/print-themes/print-minimo-de-tinta.css +1475 -0
  294. package/dist/print-themes/print-papel-recortado.css +1467 -0
  295. package/dist/print-themes/print-papel-salmao.css +1467 -0
  296. package/dist/print-themes/print-pictogramas.css +1467 -0
  297. package/dist/print-themes/print-pop-art.css +1467 -0
  298. package/dist/print-themes/print-prancheta-clara.css +1483 -0
  299. package/dist/print-themes/print-prancheta.css +1483 -0
  300. package/dist/print-themes/print-proporcao-modular.css +1467 -0
  301. package/dist/print-themes/print-riso.css +1483 -0
  302. package/dist/print-themes/print-semanario.css +1467 -0
  303. package/dist/print-themes/print-sinalizacao.css +1467 -0
  304. package/dist/print-themes/print-suico.css +1475 -0
  305. package/dist/print-themes/print-tropicalia.css +1467 -0
  306. package/dist/print-themes.css +57215 -0
  307. package/dist/print-themes.json +236 -0
  308. package/dist/tokens.css +64416 -0
  309. package/dist/tokens.json +31449 -0
  310. package/dist/values.d.ts +14 -0
  311. package/dist/values.js +31454 -0
  312. package/package.json +67 -0
  313. package/src/base/motion.tokens.json +15 -0
  314. package/src/base/space.tokens.json +122 -0
  315. package/src/base/type.tokens.json +227 -0
  316. package/src/base/z.tokens.json +13 -0
  317. package/src/color.ts +239 -0
  318. package/src/dtcg.ts +102 -0
  319. package/src/flow.ts +130 -0
  320. package/src/index.ts +17 -0
  321. package/src/presets.ts +135 -0
  322. package/src/presets.ts.diff +26 -0
  323. package/src/print-aliases.ts +84 -0
  324. package/src/print-presets.ts +1611 -0
  325. package/src/print-themes.ts +404 -0
  326. package/src/scripts.ts +75 -0
  327. package/src/stylesheet.ts +238 -0
  328. package/src/theme.ts +553 -0
  329. package/src/theme.ts.rej +16 -0
package/src/theme.ts ADDED
@@ -0,0 +1,553 @@
1
+ // Deterministic theme generator. Input: seed hues and chroma, a radius base,
2
+ // contrast level, glass on/off and optional pinned colours. Output: 11-step
3
+ // OKLCH ramps, paired semantic roles (X / on-X), shadows, radii and glass
4
+ // values for one mode, with every declared contrast pair checked and, where a
5
+ // role is not pinned, nudged along its lightness axis until WCAG 2.2 AA holds.
6
+ //
7
+ // The role model (paired surface/foreground roles, one radius base deriving
8
+ // the radius scale, themes as a swap of custom properties) and the idea of
9
+ // 11-step ramps in OKLCH are publicly documented concepts (sources in
10
+ // PROVENANCE.md). No code or values were taken from them; the lightness curve,
11
+ // chroma curve, hues and role recipes below are this project's own.
12
+
13
+ import { apcaContrast, contrastRatio, flatten, oklchToRgb, parseColor, rgbToOklch, toCss, type Oklch, type Rgba } from './color.ts'
14
+
15
+ export type Mode = 'light' | 'dark'
16
+ export type ContrastLevel = 'default' | 'high'
17
+ export type Density = 'compact' | 'default' | 'comfortable'
18
+
19
+ export interface Seed {
20
+ /** OKLCH hue in degrees. */
21
+ hue: number
22
+ /** Peak OKLCH chroma of the ramp (0..~0.37). */
23
+ chroma: number
24
+ }
25
+
26
+ export type SeedName = 'brand' | 'neutral' | 'danger' | 'warning' | 'success' | 'info'
27
+
28
+ /**
29
+ * Typographic roles a theme may set. They map onto the base font tokens the
30
+ * components read: `display` -> `--ty-font-serif` (headings h1 to h3 and KPI
31
+ * numbers), `body` -> `--ty-font-sans` (everything else), `mono` ->
32
+ * `--ty-font-mono` (identifiers). A role left out keeps the base stack.
33
+ */
34
+ export type FontRole = 'display' | 'body' | 'mono' | 'sans' | 'serif'
35
+
36
+ /** CSS token of each font role (`--ty-font-<name>`). */
37
+ export const FONT_ROLE_TOKENS: Record<FontRole, 'serif' | 'sans' | 'mono'> = { display: 'serif', body: 'sans', mono: 'mono', sans: 'sans', serif: 'serif' }
38
+
39
+ /** Elevation treatment: blurred shadows, none (flat print), or a hard offset shadow without blur. */
40
+ export type Elevation = 'soft' | 'flat' | 'offset'
41
+
42
+ export interface ThemeConfig {
43
+ /** Identifier used in `data-ty-theme`. Lowercase letters, digits and dashes. */
44
+ name: string
45
+ /** Human label (customizer, docs). */
46
+ label?: string
47
+ seeds: Record<SeedName, Seed>
48
+ /** Hues of the eight chart / categorical colours. */
49
+ chartHues?: number[]
50
+ /** Control radius in px; card and sheet radii derive from it. */
51
+ radius: number
52
+ contrast: ContrastLevel
53
+ /** Translucent blurred surfaces when true; opaque when false. */
54
+ glass: boolean
55
+ /** Call-to-action fill: brand gradient or solid brand. */
56
+ cta: 'gradient' | 'solid'
57
+ /** Exact colours that override generated roles (CSS colour strings). */
58
+ pins?: Partial<Record<Mode, Partial<Record<RoleName, string>>>>
59
+ /** Exact gradient stops for the call to action, per mode. */
60
+ ctaPins?: Partial<Record<Mode, string[]>>
61
+ /** Font families per role, most preferred first, ending with a generic family. */
62
+ fonts?: Partial<Record<FontRole, string[]>>
63
+ /**
64
+ * Stylesheet URL that loads the families of `fonts` (for example a Google
65
+ * Fonts css2 URL). The token CSS never fetches it; the host or
66
+ * ThemeProvider's `fonts` map adds the link.
67
+ */
68
+ fontsUrl?: string
69
+ /** Shadow treatment; `soft` when omitted. */
70
+ elevation?: Elevation
71
+ /** Arbitrary string variables (e.g. for textures) */
72
+ strings?: Record<string, string>
73
+ }
74
+
75
+ export const RAMP_STEPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950] as const
76
+ export type RampStep = (typeof RAMP_STEPS)[number]
77
+
78
+ // Lightness and relative chroma per step (this project's own curve: near
79
+ // white at 50, near black at 950, chroma peaking around 500-600).
80
+ const RAMP_L = [0.975, 0.94, 0.885, 0.815, 0.725, 0.635, 0.55, 0.47, 0.395, 0.325, 0.255]
81
+ const RAMP_C = [0.1, 0.2, 0.38, 0.6, 0.84, 1, 0.97, 0.88, 0.76, 0.62, 0.5]
82
+
83
+ /** 11-step ramp for a seed. */
84
+ export function generateRamp(seed: Seed): Record<RampStep, Rgba> {
85
+ const out = {} as Record<RampStep, Rgba>
86
+ RAMP_STEPS.forEach((step, i) => {
87
+ out[step] = oklchToRgb({ l: RAMP_L[i] ?? 0.5, c: seed.chroma * (RAMP_C[i] ?? 1), h: seed.hue })
88
+ })
89
+ return out
90
+ }
91
+
92
+ /** Seed derived from an existing colour (keeps hue; chroma scaled to a ramp peak). */
93
+ export function seedFromColor(color: string, peakChroma?: number): Seed {
94
+ const { c, h } = rgbToOklch(parseColor(color))
95
+ return { hue: Math.round(h * 10) / 10, chroma: Math.round((peakChroma ?? c) * 1000) / 1000 }
96
+ }
97
+
98
+ // ---------------------------------------------------------------------------
99
+ // Roles
100
+ // ---------------------------------------------------------------------------
101
+
102
+ export const ROLE_NAMES = [
103
+ 'bg', 'on-bg',
104
+ 'surface', 'on-surface', 'surface-raised', 'on-surface-raised', 'surface-sunken', 'on-surface-sunken',
105
+ 'surface-solid', 'surface-raised-solid',
106
+ 'ink', 'ink-2', 'ink-3',
107
+ 'line', 'line-soft', 'line-strong', 'input',
108
+ 'focus-ring',
109
+ 'brand', 'on-brand', 'brand-strong', 'brand-soft', 'on-brand-soft',
110
+ 'cta-solid', 'on-cta',
111
+ 'secondary', 'on-secondary',
112
+ 'danger', 'on-danger', 'danger-soft', 'on-danger-soft',
113
+ 'warning', 'on-warning', 'warning-soft', 'on-warning-soft',
114
+ 'success', 'on-success', 'success-soft', 'on-success-soft',
115
+ 'info', 'on-info', 'info-soft', 'on-info-soft',
116
+ 'neutral', 'on-neutral', 'neutral-soft', 'on-neutral-soft',
117
+ 'proof-proved', 'proof-proved-soft', 'proof-pending', 'proof-pending-soft', 'proof-refuted', 'proof-refuted-soft',
118
+ 'proof-not-disclosed', 'proof-not-disclosed-soft', 'proof-none', 'proof-none-soft',
119
+ 'actor-person', 'actor-person-soft', 'actor-agent', 'actor-agent-soft', 'actor-system', 'actor-system-soft',
120
+ 'chart-1', 'chart-2', 'chart-3', 'chart-4', 'chart-5', 'chart-6', 'chart-7', 'chart-8',
121
+ 'nav-bg', 'on-nav', 'nav-active', 'on-nav-active', 'nav-line',
122
+ 'backdrop', 'ambient-1', 'ambient-2',
123
+ ] as const
124
+ export type RoleName = (typeof ROLE_NAMES)[number]
125
+
126
+ /** Design-direction names kept as aliases of the role model. */
127
+ export const ROLE_ALIASES: Record<string, RoleName> = {
128
+ accent: 'brand',
129
+ 'accent-strong': 'brand-strong',
130
+ 'accent-soft': 'brand-soft',
131
+ 'accent-ink': 'on-brand',
132
+ 'on-accent': 'on-brand',
133
+ 'on-accent-soft': 'on-brand-soft',
134
+ 'categorical-1': 'chart-1',
135
+ 'categorical-2': 'chart-2',
136
+ 'categorical-3': 'chart-3',
137
+ 'categorical-4': 'chart-4',
138
+ 'categorical-5': 'chart-5',
139
+ 'categorical-6': 'chart-6',
140
+ 'categorical-7': 'chart-7',
141
+ 'categorical-8': 'chart-8',
142
+ }
143
+
144
+ interface Recipe {
145
+ seed: SeedName | 'chart' | 'ambient'
146
+ /** OKLCH lightness. */
147
+ l: number
148
+ /** Multiplier of the seed chroma. */
149
+ c?: number
150
+ /** Opacity. */
151
+ a?: number
152
+ /** Hue override (chart and ambient). */
153
+ h?: number
154
+ }
155
+
156
+ const TONES = ['danger', 'warning', 'success', 'info', 'neutral'] as const
157
+
158
+ function recipes(mode: Mode, contrast: ContrastLevel, glass: boolean): Partial<Record<RoleName, Recipe>> {
159
+ const dark = mode === 'dark'
160
+ const high = contrast === 'high'
161
+ const pick = (light: number, darkV: number) => (dark ? darkV : light)
162
+ const softA = pick(0.1, 0.14) * (high ? 1.6 : 1)
163
+ const r: Partial<Record<RoleName, Recipe>> = {
164
+ bg: { seed: 'neutral', l: pick(0.975, 0.165), c: 0.5 },
165
+ surface: { seed: 'neutral', l: pick(0.993, 0.235), c: 0.4, a: glass ? pick(0.82, 0.72) : 1 },
166
+ 'surface-raised': { seed: 'neutral', l: pick(0.993, 0.275), c: 0.4, a: glass ? pick(0.94, 0.86) : 1 },
167
+ 'surface-solid': { seed: 'neutral', l: pick(0.993, 0.235), c: 0.4 },
168
+ 'surface-raised-solid': { seed: 'neutral', l: pick(0.993, 0.275), c: 0.4 },
169
+ 'surface-sunken': { seed: 'neutral', l: pick(0.955, 0.195), c: 0.6 },
170
+ ink: { seed: 'neutral', l: pick(0.21, 0.955), c: 2 },
171
+ 'ink-2': { seed: 'neutral', l: high ? pick(0.27, 0.93) : pick(0.37, 0.87), c: 2 },
172
+ 'ink-3': { seed: 'neutral', l: high ? pick(0.33, 0.9) : pick(0.5, 0.72), c: 2 },
173
+ line: { seed: 'neutral', l: pick(0.55, 0.78), c: 2.5, a: high ? pick(0.45, 0.4) : pick(0.22, 0.16) },
174
+ 'line-soft': { seed: 'neutral', l: pick(0.55, 0.78), c: 2.5, a: high ? pick(0.3, 0.25) : pick(0.12, 0.09) },
175
+ 'line-strong': { seed: 'neutral', l: pick(0.55, 0.78), c: 2.5, a: high ? pick(0.75, 0.65) : pick(0.38, 0.3) },
176
+ input: { seed: 'neutral', l: high ? pick(0.42, 0.78) : pick(0.6, 0.58), c: 2.5 },
177
+ 'focus-ring': { seed: 'brand', l: high ? pick(0.4, 0.85) : pick(0.47, 0.79), c: 0.75 },
178
+ brand: { seed: 'brand', l: high ? pick(0.4, 0.85) : pick(0.47, 0.79), c: 0.75 },
179
+ 'brand-strong': { seed: 'brand', l: high ? pick(0.33, 0.9) : pick(0.4, 0.87), c: 0.7 },
180
+ 'brand-soft': { seed: 'brand', l: pick(0.55, 0.75), c: 0.8, a: softA },
181
+ 'on-brand-soft': { seed: 'brand', l: high ? pick(0.36, 0.88) : pick(0.44, 0.82), c: 0.75 },
182
+ 'on-brand': { seed: 'brand', l: pick(0.985, 0.25), c: 0.15 },
183
+ 'cta-solid': { seed: 'brand', l: pick(0.45, 0.45), c: 0.8 },
184
+ 'on-cta': { seed: 'brand', l: 0.985, c: 0.1 },
185
+ secondary: { seed: 'neutral', l: pick(0.993, 0.275), c: 0.4, a: glass ? pick(0.7, 0.6) : 1 },
186
+ 'on-secondary': { seed: 'neutral', l: pick(0.21, 0.955), c: 2 },
187
+ backdrop: { seed: 'neutral', l: pick(0.2, 0.1), c: 2, a: pick(0.4, 0.6) },
188
+ 'ambient-1': { seed: 'brand', l: 0.72, c: 0.9, a: glass ? pick(0.07, 0.12) : 0 },
189
+ 'ambient-2': { seed: 'ambient', l: 0.75, c: 0.12, h: 230, a: glass ? pick(0.05, 0.08) : 0 },
190
+ }
191
+ for (const tone of TONES) {
192
+ const chroma = tone === 'neutral' ? 2 : 1
193
+ r[tone] = { seed: tone, l: high ? pick(0.44, 0.8) : pick(0.51, 0.74), c: chroma }
194
+ r[`${tone}-soft`] = { seed: tone, l: pick(0.6, 0.7), c: chroma, a: softA }
195
+ r[`on-${tone}-soft`] = { seed: tone, l: high ? pick(0.38, 0.86) : pick(0.45, 0.8), c: chroma }
196
+ r[`on-${tone}`] = { seed: 'neutral', l: pick(0.985, 0.18), c: 0.3 }
197
+ }
198
+ return r
199
+ }
200
+
201
+ /** Contrast pairs every theme must satisfy (WCAG 2.2 AA). */
202
+ export interface ContrastPair {
203
+ fg: RoleName | `cta-stop-${number}` | 'focus-ring'
204
+ /** Background stack from top to bottom; translucent layers are composited. */
205
+ over: Array<RoleName | `cta-stop-${number}`>
206
+ min: 4.5 | 3
207
+ kind: 'text' | 'ui'
208
+ }
209
+
210
+ export function contrastPairs(ctaStops: number): ContrastPair[] {
211
+ const pairs: ContrastPair[] = []
212
+ const text = (fg: ContrastPair['fg'], ...over: ContrastPair['over']) => pairs.push({ fg, over, min: 4.5, kind: 'text' })
213
+ const ui = (fg: ContrastPair['fg'], ...over: ContrastPair['over']) => pairs.push({ fg, over, min: 3, kind: 'ui' })
214
+ for (const ink of ['ink', 'ink-2', 'ink-3'] as const) {
215
+ text(ink, 'bg')
216
+ text(ink, 'surface', 'bg')
217
+ text(ink, 'surface-raised', 'bg')
218
+ text(ink, 'surface-sunken')
219
+ }
220
+ text('on-bg', 'bg')
221
+ text('on-surface', 'surface', 'bg')
222
+ text('on-surface-raised', 'surface-raised', 'bg')
223
+ text('on-surface-sunken', 'surface-sunken')
224
+ text('brand', 'bg')
225
+ text('brand', 'surface', 'bg')
226
+ text('brand', 'surface-raised', 'bg')
227
+ text('brand-strong', 'surface', 'bg')
228
+ text('on-brand', 'brand')
229
+ text('on-brand-soft', 'brand-soft', 'surface', 'bg')
230
+ text('on-cta', 'cta-solid')
231
+ for (let i = 0; i < ctaStops; i++) text('on-cta', `cta-stop-${i}`)
232
+ text('on-secondary', 'secondary', 'bg')
233
+ for (const tone of TONES) {
234
+ text(tone, 'surface', 'bg')
235
+ text(tone, 'surface-raised', 'bg')
236
+ text(`on-${tone}`, tone)
237
+ text(`on-${tone}-soft`, `${tone}-soft`, 'surface', 'bg')
238
+ }
239
+ for (const p of ['proved', 'pending', 'refuted', 'not-disclosed', 'none'] as const) {
240
+ text(`proof-${p}`, 'surface', 'bg')
241
+ text(`proof-${p}`, `proof-${p}-soft`, 'surface', 'bg')
242
+ }
243
+ for (const a of ['person', 'agent', 'system'] as const) text(`actor-${a}`, `actor-${a}-soft`, 'surface', 'bg')
244
+ text('on-nav', 'nav-bg', 'bg')
245
+ text('on-nav-active', 'nav-active', 'nav-bg', 'bg')
246
+ ui('input', 'surface', 'bg')
247
+ ui('input', 'bg')
248
+ ui('input', 'surface-raised', 'bg')
249
+ ui('focus-ring', 'bg')
250
+ ui('focus-ring', 'surface', 'bg')
251
+ ui('focus-ring', 'surface-raised', 'bg')
252
+ ui('brand', 'surface-sunken')
253
+ for (let i = 1; i <= 8; i++) ui(`chart-${i}` as RoleName, 'surface', 'bg')
254
+ return pairs
255
+ }
256
+
257
+ // ---------------------------------------------------------------------------
258
+ // Resolution
259
+ // ---------------------------------------------------------------------------
260
+
261
+ export interface ShadowLayer {
262
+ x: number
263
+ y: number
264
+ blur: number
265
+ spread: number
266
+ color: Rgba
267
+ inset?: boolean
268
+ }
269
+
270
+ export interface ContrastResult {
271
+ fg: string
272
+ over: string[]
273
+ kind: 'text' | 'ui'
274
+ min: number
275
+ ratio: number
276
+ apca: number
277
+ pass: boolean
278
+ }
279
+
280
+ export interface ResolvedTheme {
281
+ name: string
282
+ mode: Mode
283
+ contrast: ContrastLevel
284
+ colors: Record<string, Rgba>
285
+ ramps: Record<SeedName, Record<RampStep, Rgba>>
286
+ cta: { angle: number; stops: Rgba[] }
287
+ shadows: Record<'sheet' | 'raised' | 'floating' | 'modal' | 'sheet-inset', ShadowLayer[]>
288
+ /** Pixel dimensions (radius, glass blur, focus width). */
289
+ dimensions: Record<string, number>
290
+ /** Font stacks keyed by token name (`serif`, `sans`, `mono`); empty when the theme keeps the base stacks. */
291
+ fonts: Partial<Record<'serif' | 'sans' | 'mono', string[]>>
292
+ numbers: Record<string, number>
293
+ strings?: Record<string, string>
294
+ report: ContrastResult[]
295
+ }
296
+
297
+ /** Hues of the eight chart colours when a theme sets none. */
298
+ export const DEFAULT_CHART_HUES = [250, 62, 165, 335, 215, 35, 110, 290]
299
+
300
+ function colorFrom(recipe: Recipe, seeds: Record<SeedName, Seed>): Oklch & { a: number } {
301
+ const seed = recipe.seed === 'chart' || recipe.seed === 'ambient' ? undefined : seeds[recipe.seed]
302
+ const chroma = seed ? seed.chroma * (recipe.c ?? 1) : (recipe.c ?? 0.1)
303
+ return { l: recipe.l, c: chroma, h: recipe.h ?? seed?.hue ?? 0, a: recipe.a ?? 1 }
304
+ }
305
+
306
+ /** Resolves one theme in one mode. */
307
+ export function resolveTheme(config: ThemeConfig, mode: Mode, contrastOverride?: ContrastLevel): ResolvedTheme {
308
+ const contrast = contrastOverride ?? config.contrast
309
+ const dark = mode === 'dark'
310
+ const recipeMap = recipes(mode, contrast, config.glass)
311
+ const lch: Partial<Record<RoleName, Oklch & { a: number }>> = {}
312
+ for (const [role, recipe] of Object.entries(recipeMap) as Array<[RoleName, Recipe]>) lch[role] = colorFrom(recipe, config.seeds)
313
+
314
+ const chartHues = config.chartHues ?? DEFAULT_CHART_HUES
315
+ chartHues.slice(0, 8).forEach((h, i) => {
316
+ lch[`chart-${i + 1}` as RoleName] = { l: dark ? 0.76 : 0.55, c: dark ? 0.13 : 0.14, h, a: 1 }
317
+ })
318
+
319
+ const pinned = new Set<RoleName>()
320
+ const colors: Record<string, Rgba> = {}
321
+ const pins = config.pins?.[mode] ?? {}
322
+ const pinnedValue = (role: RoleName): Rgba | undefined => {
323
+ // Pins are exact design values; the high-contrast variant regenerates.
324
+ const v = contrast === config.contrast ? pins[role] : undefined
325
+ return v ? parseColor(v) : undefined
326
+ }
327
+ const materialise = (role: RoleName) => {
328
+ const p = pinnedValue(role)
329
+ if (p) {
330
+ pinned.add(role)
331
+ colors[role] = p
332
+ return
333
+ }
334
+ const v = lch[role]
335
+ if (v) colors[role] = oklchToRgb(v, v.a)
336
+ }
337
+ for (const role of Object.keys(lch) as RoleName[]) materialise(role)
338
+
339
+ // Roles defined as copies of others (after pins so they follow them).
340
+ const copy = (role: RoleName, from: RoleName) => {
341
+ const p = pinnedValue(role)
342
+ if (p) {
343
+ pinned.add(role)
344
+ colors[role] = p
345
+ } else if (colors[from]) {
346
+ colors[role] = { ...colors[from]! }
347
+ if (lch[from]) lch[role] = { ...lch[from]! }
348
+ }
349
+ }
350
+ const aliasRoles = (): void => {
351
+ copy('on-bg', 'ink-2')
352
+ copy('on-surface', 'ink-2')
353
+ copy('on-surface-raised', 'ink-2')
354
+ copy('on-surface-sunken', 'ink-2')
355
+ copy('proof-proved', 'on-success-soft')
356
+ copy('proof-proved-soft', 'success-soft')
357
+ copy('proof-pending', 'on-warning-soft')
358
+ copy('proof-pending-soft', 'warning-soft')
359
+ copy('proof-refuted', 'on-danger-soft')
360
+ copy('proof-refuted-soft', 'danger-soft')
361
+ copy('proof-not-disclosed', 'on-neutral-soft')
362
+ copy('proof-not-disclosed-soft', 'neutral-soft')
363
+ copy('proof-none', 'ink-3')
364
+ copy('proof-none-soft', 'neutral-soft')
365
+ copy('actor-person', 'on-brand-soft')
366
+ copy('actor-person-soft', 'brand-soft')
367
+ copy('actor-agent', 'ink-2')
368
+ copy('actor-agent-soft', 'neutral-soft')
369
+ copy('actor-system', 'ink-3')
370
+ copy('actor-system-soft', 'neutral-soft')
371
+ copy('nav-bg', 'surface')
372
+ copy('on-nav', 'ink-2')
373
+ copy('nav-active', 'brand-soft')
374
+ copy('on-nav-active', 'on-brand-soft')
375
+ copy('nav-line', 'line')
376
+ }
377
+ aliasRoles()
378
+
379
+ // Call to action stops.
380
+ const brand = config.seeds.brand
381
+ const ctaPin = config.ctaPins?.[mode]
382
+ let ctaStops: Rgba[]
383
+ if (ctaPin && contrast === config.contrast) ctaStops = ctaPin.map(parseColor)
384
+ else if (config.cta === 'solid') ctaStops = [colors['cta-solid']!]
385
+ else
386
+ ctaStops = [
387
+ oklchToRgb({ l: 0.5, c: brand.chroma * 0.85, h: brand.hue - 12 }),
388
+ oklchToRgb({ l: 0.47, c: brand.chroma * 0.8, h: brand.hue + 8 }),
389
+ oklchToRgb({ l: 0.47, c: brand.chroma * 0.85, h: brand.hue + 60 }),
390
+ ]
391
+
392
+ // Contrast enforcement: nudge non-pinned foreground roles along lightness.
393
+ const pairs = contrastPairs(ctaStops.length)
394
+ const layer = (name: string): Rgba => {
395
+ const m = /^cta-stop-(\d+)$/.exec(name)
396
+ if (m) return ctaStops[Number(m[1])]!
397
+ return colors[name] ?? { r: 1, g: 1, b: 1, a: 1 }
398
+ }
399
+ const measure = (pair: ContrastPair) => {
400
+ const bgc = flatten([...pair.over.map(layer), dark ? layer('bg') : layer('bg')])
401
+ const fgc = flatten([layer(pair.fg), bgc])
402
+ return { ratio: contrastRatio(fgc, bgc), apca: apcaContrast(fgc, bgc), bgc }
403
+ }
404
+ for (let pass = 0; pass < 3; pass++) {
405
+ for (const pair of pairs) {
406
+ const role = pair.fg as RoleName
407
+ if (pinned.has(role) || !lch[role]) continue
408
+ let guard = 0
409
+ let m = measure(pair)
410
+ while (m.ratio < pair.min && guard++ < 80) {
411
+ const v = lch[role]!
412
+ const bgL = rgbToOklch(m.bgc).l
413
+ const step = bgL > 0.6 ? -0.01 : 0.01
414
+ v.l = Math.min(0.995, Math.max(0.02, v.l + step))
415
+ colors[role] = oklchToRgb(v, v.a)
416
+ m = measure(pair)
417
+ }
418
+ }
419
+ aliasRoles()
420
+ }
421
+
422
+
423
+ const report: ContrastResult[] = pairs.map((pair) => {
424
+ const m = measure(pair)
425
+ return {
426
+ fg: pair.fg,
427
+ over: pair.over,
428
+ kind: pair.kind,
429
+ min: pair.min,
430
+ ratio: Math.round(m.ratio * 100) / 100,
431
+ apca: Math.round(m.apca * 10) / 10,
432
+ pass: m.ratio >= pair.min - 1e-9,
433
+ }
434
+ })
435
+
436
+ // Aliases of the design-direction vocabulary.
437
+ for (const [alias, role] of Object.entries(ROLE_ALIASES)) if (colors[role]) colors[alias] = colors[role]!
438
+
439
+ const ramps = Object.fromEntries(
440
+ (Object.keys(config.seeds) as SeedName[]).map((s) => [s, generateRamp(config.seeds[s])]),
441
+ ) as Record<SeedName, Record<RampStep, Rgba>>
442
+
443
+ const tint = oklchToRgb({ l: dark ? 0.12 : 0.2, c: config.seeds.neutral.chroma * 2, h: config.seeds.neutral.hue })
444
+ const shade = (alpha: number) => ({ ...tint, a: Math.min(0.9, alpha * (dark ? 2 : 1)) })
445
+ const inset: ShadowLayer = { x: 0, y: 1, blur: 0, spread: 0, inset: true, color: { r: 1, g: 1, b: 1, a: dark && config.glass ? 0.06 : 0 } }
446
+ const elevation = config.elevation ?? 'soft'
447
+ let shadows: ResolvedTheme['shadows']
448
+ if (elevation === 'flat') {
449
+ // Print-flat: surfaces sit on the page; only overlays keep a faint separation.
450
+ const none: ShadowLayer[] = [{ x: 0, y: 0, blur: 0, spread: 0, color: { ...tint, a: 0 } }]
451
+ shadows = { sheet: none, raised: none, floating: [{ x: 0, y: 2, blur: 6, spread: -2, color: shade(0.12) }], modal: [{ x: 0, y: 16, blur: 40, spread: -16, color: shade(0.3) }], 'sheet-inset': [inset] }
452
+ } else if (elevation === 'offset') {
453
+ // Hard shadow in the ink colour, no blur (cut-paper and poster styles).
454
+ const ink = colors.ink ?? tint
455
+ const hard = (d: number): ShadowLayer[] => [{ x: d, y: d, blur: 0, spread: 0, color: { ...ink, a: 1 } }]
456
+ shadows = { sheet: hard(3), raised: hard(2), floating: hard(4), modal: hard(6), 'sheet-inset': [inset] }
457
+ } else {
458
+ shadows = {
459
+ sheet: [
460
+ { x: 0, y: 1, blur: 2, spread: 0, color: shade(0.04) },
461
+ { x: 0, y: 8, blur: 24, spread: -12, color: shade(0.1) },
462
+ ],
463
+ raised: [{ x: 0, y: 4, blur: 12, spread: -2, color: shade(0.08) }],
464
+ floating: [{ x: 0, y: 12, blur: 24, spread: -8, color: shade(0.14) }],
465
+ modal: [{ x: 0, y: 40, blur: 100, spread: -30, color: shade(0.35) }],
466
+ 'sheet-inset': [inset],
467
+ }
468
+ }
469
+
470
+ const R = config.radius
471
+ const dimensions: Record<string, number> = {
472
+ radius: R,
473
+ 'radius-control': R,
474
+ 'radius-card': Math.round(R * 1.6),
475
+ 'radius-sheet': Math.round(R * 2.4),
476
+ 'radius-pill': 999,
477
+ 'radius-agent': Math.max(2, Math.round(R * 0.6)),
478
+ 'focus-width': contrast === 'high' ? 3 : 2,
479
+ 'glass-blur-sheet': config.glass ? 20 : 0,
480
+ 'glass-blur-floating': config.glass ? 24 : 0,
481
+ }
482
+ const numbers: Record<string, number> = { 'glass-saturate': config.glass ? 1.15 : 1 }
483
+
484
+ const fonts: ResolvedTheme['fonts'] = {}
485
+ for (const role of ['display', 'body', 'mono'] as const) {
486
+ const list = config.fonts?.[role]
487
+ if (list?.length) fonts[FONT_ROLE_TOKENS[role]] = [...list]
488
+ }
489
+
490
+ return { name: config.name, mode, contrast, colors, ramps, cta: { angle: 135, stops: ctaStops }, shadows, dimensions, numbers, fonts, strings: config.strings ?? {}, report }
491
+ }
492
+
493
+ // ---------------------------------------------------------------------------
494
+ // Density (independent of the theme)
495
+ // ---------------------------------------------------------------------------
496
+
497
+ export const DENSITIES: Record<Density, Record<string, number>> = {
498
+ compact: { 'control-height': 36, 'control-height-touch': 44, 'control-height-compact': 28, density: 0.875 },
499
+ default: { 'control-height': 40, 'control-height-touch': 44, 'control-height-compact': 32, density: 1 },
500
+ comfortable: { 'control-height': 44, 'control-height-touch': 48, 'control-height-compact': 36, density: 1.125 },
501
+ }
502
+
503
+ // ---------------------------------------------------------------------------
504
+ // Serialisation to CSS custom property lists
505
+ // ---------------------------------------------------------------------------
506
+
507
+ export function shadowToCss(layers: ShadowLayer[]): string {
508
+ return layers
509
+ .map((l) => `${l.inset ? 'inset ' : ''}${l.x}px ${l.y}px ${l.blur}px ${l.spread}px ${toCss(l.color)}`)
510
+ .join(', ')
511
+ }
512
+
513
+ export function gradientToCss(angle: number, stops: Rgba[]): string {
514
+ const list = stops.length === 1 ? [stops[0]!, stops[0]!] : stops
515
+ return `linear-gradient(${angle}deg, ${list.map((s, i) => `${toCss(s)} ${Math.round((i / (list.length - 1)) * 100)}%`).join(', ')})`
516
+ }
517
+
518
+ /** Ordered `[--ty-name, value]` pairs for one resolved theme. */
519
+ export function themeVariables(t: ResolvedTheme): Array<[string, string]> {
520
+ const out: Array<[string, string]> = []
521
+ for (const [name, c] of Object.entries(t.colors)) out.push([`--ty-${name}`, toCss(c)])
522
+ out.push(['--ty-cta', gradientToCss(t.cta.angle, t.cta.stops)])
523
+ for (const [seed, ramp] of Object.entries(t.ramps)) {
524
+ for (const step of RAMP_STEPS) out.push([`--ty-${seed}-${step}`, toCss(ramp[step])])
525
+ }
526
+ for (const [name, layers] of Object.entries(t.shadows)) out.push([`--ty-shadow-${name}`, shadowToCss(layers)])
527
+ for (const [name, px] of Object.entries(t.dimensions)) out.push([`--ty-${name}`, `${px}px`])
528
+ for (const [name, n] of Object.entries(t.numbers)) out.push([`--ty-${name}`, String(n)])
529
+ for (const [name, list] of Object.entries(t.fonts)) out.push([`--ty-font-${name}`, fontStackToCss(list)])
530
+ for (const [name, s] of Object.entries(t.strings ?? {})) out.push([`--ty-${name}`, s])
531
+ return out
532
+ }
533
+
534
+ /**
535
+ * CSS `font-family` value of a family list: names with spaces or digits are
536
+ * quoted, keywords and single identifiers are not (the same rule as the
537
+ * Style Dictionary font-family transform of the build).
538
+ */
539
+ export function fontStackToCss(families: readonly string[]): string {
540
+ return families.map((f) => (/[\s\d]/.test(f) && !/^[\w-]+$/.test(f) ? `'${f}'` : f)).join(', ')
541
+ }
542
+
543
+ /** Family list of a CSS `font-family` value (quotes removed). */
544
+ export function parseFontStack(stack: string): string[] {
545
+ return stack
546
+ .split(',')
547
+ .map((f) => f.trim().replace(/^["']|["']$/g, ''))
548
+ .filter(Boolean)
549
+ }
550
+
551
+ export function densityVariables(density: Density): Array<[string, string]> {
552
+ return Object.entries(DENSITIES[density]).map(([k, v]) => [`--ty-${k}`, k === 'density' ? String(v) : `${v}px`])
553
+ }
@@ -0,0 +1,16 @@
1
+ @@ -86,6 +88,7 @@
2
+ dimensions: Record<string, number>
3
+ numbers: Record<string, number>
4
+ fonts: Record<string, string[]>
5
+ + strings: Record<string, string>
6
+ report: Array<{ fg: string; over: string[]; kind: string; ratio: number; min: number; apca: number }>
7
+ }
8
+
9
+ @@ -374,6 +377,7 @@
10
+ dimensions: { ...BASE_DIMENSIONS },
11
+ numbers: { ...BASE_NUMBERS },
12
+ fonts: config.fonts ? { ...config.fonts } : {},
13
+ + strings: config.strings ? { ...config.strings } : {},
14
+ report: [],
15
+ }
16
+ if (config.glass) resolved.numbers.glass = 1