@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
@@ -0,0 +1,404 @@
1
+
2
+ function createTextureSvg(style: any): string | undefined {
3
+ const papel = style.papel
4
+ if (!papel || papel.textura === 'nenhuma' || papel.intensidade <= 0) return undefined
5
+ const k = papel.intensidade
6
+ const n3 = (x: number) => Math.round(x * 1000) / 1000
7
+ const matriz = (cor: string, alfa: number, limiar: number) => {
8
+ const c = parseColor(cor)
9
+ return `0 0 0 0 ${n3(c.r)} 0 0 0 0 ${n3(c.g)} 0 0 0 0 ${n3(c.b)} 0 0 0 ${n3(alfa)} ${n3(limiar)}`
10
+ }
11
+
12
+ const tinta = style.cor.tinta
13
+ let defs = ''
14
+ let corpo = ''
15
+
16
+ if (papel.textura === 'grao') {
17
+ defs = `
18
+ <filter id="f" x="0" y="0" width="100%" height="100%">
19
+ <feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="2" seed="21" stitchTiles="stitch" />
20
+ <feColorMatrix values="${matriz(tinta, 0.9 * k, -0.34)}" />
21
+ </filter>
22
+ `
23
+ corpo = `<rect width="100%" height="100%" filter="url(#f)" />`
24
+ } else if (papel.textura === 'fibra') {
25
+ defs = `
26
+ <filter id="f" x="0" y="0" width="100%" height="100%">
27
+ <feTurbulence type="fractalNoise" baseFrequency="0.035 0.09" numOctaves="3" seed="4" />
28
+ <feColorMatrix values="${matriz(tinta, 0.55 * k, -0.2)}" />
29
+ </filter>
30
+ <filter id="g" x="0" y="0" width="100%" height="100%">
31
+ <feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="2" seed="11" stitchTiles="stitch" />
32
+ <feColorMatrix values="${matriz(tinta, 1.1 * k, -0.45)}" />
33
+ </filter>
34
+ `
35
+ corpo = `
36
+ <rect width="100%" height="100%" filter="url(#f)" opacity="0.6" />
37
+ <rect width="100%" height="100%" filter="url(#g)" />
38
+ `
39
+ } else if (papel.textura === 'pauta') {
40
+ const linha = style.pb ? '#bdbdbd' : '#b7cbe0'
41
+ const passo = n3(7 * 3.7795)
42
+ defs = `
43
+ <pattern id="p" width="10" height="${passo}" patternUnits="userSpaceOnUse" y="${n3(16 * 3.7795)}">
44
+ <line x1="0" x2="10" y1="${n3(7 * 3.7795 - 0.5)}" y2="${n3(7 * 3.7795 - 0.5)}" stroke="${linha}" stroke-width="0.9" />
45
+ </pattern>
46
+ `
47
+ corpo = `
48
+ <g opacity="${Math.min(1, 0.4 + k)}">
49
+ <rect width="100%" height="100%" fill="url(#p)" />
50
+ </g>
51
+ `
52
+ } else if (papel.textura === 'milimetrado') {
53
+ const mm = 3.7795
54
+ const cm = 37.795
55
+ const mmStr = n3(mm)
56
+ const cmStr = n3(cm)
57
+ const op1 = n3(0.09 * k)
58
+ const op2 = n3(0.22 * k)
59
+ const linha = style.cor.linha
60
+ defs = `
61
+ <pattern id="mm" width="${mmStr}" height="${mmStr}" patternUnits="userSpaceOnUse">
62
+ <path d="M ${mmStr} 0 L 0 0 0 ${mmStr}" fill="none" stroke="${linha}" stroke-opacity="${op1}" stroke-width="0.5" />
63
+ </pattern>
64
+ <pattern id="cm" width="${cmStr}" height="${cmStr}" patternUnits="userSpaceOnUse">
65
+ <path d="M ${cmStr} 0 L 0 0 0 ${cmStr}" fill="none" stroke="${linha}" stroke-opacity="${op2}" stroke-width="0.8" />
66
+ </pattern>
67
+ `
68
+ corpo = `
69
+ <rect width="100%" height="100%" fill="url(#mm)" />
70
+ <rect width="100%" height="100%" fill="url(#cm)" />
71
+ `
72
+ } else {
73
+ return undefined
74
+ }
75
+
76
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><defs>${defs}</defs>${corpo}</svg>`
77
+ const cleanSvg = svg.replace(/>\s+</g, '><').trim()
78
+ return `url('data:image/svg+xml;utf8,${encodeURIComponent(cleanSvg)}')`
79
+ }
80
+
81
+
82
+ // UI themes derived from the book styles of print-presets.ts. One function,
83
+ // `printStyleToTheme`, maps a PrintStyle onto a ThemeConfig: the paper and ink
84
+ // become the surfaces and text of the style's native mode (light for paper
85
+ // styles, dark for dark-paper styles), the first legible chromatic accent
86
+ // becomes the brand, the proof-state colours become the semantic tones, the
87
+ // display, body and mono families become the font roles, and the corner
88
+ // radius, panel and chart treatment choose radius, glass, call to action and
89
+ // elevation. The other mode is generated from the same hues. Every exact
90
+ // colour is kept as a pin only while the generator's WCAG 2.2 AA pairs hold;
91
+ // a pin that fails is dropped and the role is regenerated (and nudged) from
92
+ // the style's hue, so identity is kept wherever contrast allows.
93
+
94
+ import { contrastRatio, deltaE2000, luminance, oklchToRgb, parseColor, rgbToOklch, toCss } from './color.ts'
95
+ import { PRINT_THEME_PREFIX } from './print-aliases.ts'
96
+ import { googleFontsUrl, printPresets, type PrintPresetName, type PrintStyle } from './print-presets.ts'
97
+ import {
98
+ DEFAULT_CHART_HUES,
99
+ parseFontStack,
100
+ resolveTheme,
101
+ type Mode,
102
+ type RoleName,
103
+ type Seed,
104
+ type SeedName,
105
+ type ThemeConfig,
106
+ } from './theme.ts'
107
+
108
+
109
+ /** Chroma under which a colour counts as grey (ink, paper, rules). */
110
+ const CHROMATIC = 0.05
111
+ /** One millimetre of the print radius in CSS pixels (96 dpi). */
112
+ const MM = 96 / 25.4
113
+
114
+ const oklch = (c: string) => rgbToOklch(parseColor(c))
115
+ const chromatic = (c: string) => oklch(c).c >= CHROMATIC
116
+ const ratio = (a: string, b: string) => contrastRatio(parseColor(a), parseColor(b))
117
+ const shiftL = (c: string, dl: number, chromaScale = 1, alpha = 1): string => {
118
+ const v = oklch(c)
119
+ return toCss(oklchToRgb({ l: Math.min(0.998, Math.max(0.02, v.l + dl)), c: v.c * chromaScale, h: v.h }, alpha))
120
+ }
121
+ const seedOf = (c: string, fallback?: Seed): Seed => {
122
+ const v = oklch(c)
123
+ if (fallback && v.c < CHROMATIC) return fallback
124
+ return { hue: Math.round(v.h * 10) / 10, chroma: Math.round(v.c * 1000) / 1000 }
125
+ }
126
+ const hueGap = (a: number, b: number) => {
127
+ const d = Math.abs(a - b) % 360
128
+ return d > 180 ? 360 - d : d
129
+ }
130
+
131
+ /** Default semantic seeds, used where a style's proof colour is grey. */
132
+ const TONE_FALLBACK: Record<'danger' | 'warning' | 'success' | 'info', Seed> = {
133
+ danger: { hue: 18, chroma: 0.19 },
134
+ warning: { hue: 70, chroma: 0.14 },
135
+ success: { hue: 150, chroma: 0.14 },
136
+ info: { hue: 255, chroma: 0.06 },
137
+ }
138
+
139
+ /** Per-style adjustments where the derivation misjudges; merged over the derived config. */
140
+ export interface PrintThemeOverride {
141
+ /** Brand colour to use instead of the derived one. */
142
+ brand?: string
143
+ glass?: boolean
144
+ cta?: ThemeConfig['cta']
145
+ elevation?: ThemeConfig['elevation']
146
+ /** Radius in px. */
147
+ radius?: number
148
+ /** Extra pins per mode (applied before the contrast check, dropped if they fail like any pin). */
149
+ pins?: ThemeConfig['pins']
150
+ }
151
+
152
+ /**
153
+ * Where the derivation reads a style differently from its tradition. Kept
154
+ * short on purpose: every entry is a judgement the data cannot express.
155
+ */
156
+ export const PRINT_THEME_OVERRIDES: Partial<Record<PrintPresetName, PrintThemeOverride>> = {}
157
+
158
+ /** The colour moved along OKLCH lightness (hue and chroma kept) until it reaches `min` against `over`. */
159
+ export function legibleOn(colour: string, over: string, min = 4.6): string {
160
+ const v = oklch(colour)
161
+ const step = luminance(parseColor(over)) > 0.2 ? -0.005 : 0.005
162
+ let out = colour
163
+ for (let i = 0; i < 200 && ratio(out, over) < min; i++) {
164
+ v.l = Math.min(0.995, Math.max(0.02, v.l + step))
165
+ out = toCss(oklchToRgb(v))
166
+ }
167
+ return out
168
+ }
169
+
170
+ /**
171
+ * The accent that represents a style, before any legibility adjustment: the
172
+ * first chromatic accent that nearly reads on the paper (3:1), else the most
173
+ * legible chromatic accent, else the first chromatic ornament, else the ink
174
+ * (or, on dark paper, the paper itself).
175
+ */
176
+ export function printStyleAccent(style: PrintStyle): string {
177
+ const c = style.cor
178
+ const darkPaper = luminance(parseColor(c.papel)) < 0.2
179
+ const accents = [c.destaque, c.destaque2].filter(chromatic)
180
+ const near = accents.find((x) => ratio(x, c.papel) >= 3)
181
+ if (near) return near
182
+ if (accents.length) return [...accents].sort((a, b) => ratio(b, c.papel) - ratio(a, c.papel))[0]!
183
+ const ornament = (c.ornamento ?? []).find(chromatic)
184
+ if (ornament) return ornament
185
+ return darkPaper ? c.papel : c.tinta
186
+ }
187
+
188
+ function chartHues(style: PrintStyle): number[] {
189
+ const c = style.cor
190
+ const sources = [c.destaque, c.destaque2, ...(c.ornamento ?? []), c.prova.refutada, c.prova.sustentada, c.prova['nao-da-para-afirmar'], c.marcaTexto]
191
+ const hues: number[] = []
192
+ for (const s of sources) {
193
+ const v = oklch(s)
194
+ if (v.c < CHROMATIC) continue
195
+ if (hues.every((h) => hueGap(h, v.h) >= 30)) hues.push(Math.round(v.h))
196
+ }
197
+ for (const h of DEFAULT_CHART_HUES) {
198
+ if (hues.length >= 8) break
199
+ if (hues.every((x) => hueGap(x, h) >= 30)) hues.push(h)
200
+ }
201
+ for (const h of DEFAULT_CHART_HUES) if (hues.length < 8 && !hues.includes(h)) hues.push(h)
202
+ return hues.slice(0, 8)
203
+ }
204
+
205
+ /** Families of a print stack for a UI role; `mono` is kept only when the stack is really monospace. */
206
+ function fontsOf(style: PrintStyle): { fonts: NonNullable<ThemeConfig['fonts']>; url?: string } {
207
+ const display = parseFontStack(style.fontes.titulo)
208
+ const body = parseFontStack(style.fontes.corpo)
209
+ const monoStack = parseFontStack(style.fontes.mono)
210
+ const fonts: any = { display, body, serif: display, sans: body }
211
+ if (monoStack.at(-1) === 'monospace') { fonts.mono = monoStack; fonts.mono = monoStack; }
212
+ const used = new Set([display[0], body[0], fonts.mono?.[0]].filter(Boolean))
213
+ const specs = style.googleFonts.filter((g) => used.has(g.split(':')[0]))
214
+ const url = googleFontsUrl({ googleFonts: specs }) ?? undefined
215
+ return { fonts, url }
216
+ }
217
+
218
+ /**
219
+ * Exact colours of the style's own mode (paper as background, ink as text).
220
+ * Surfaces step lighter than the paper, the sunken well a little darker.
221
+ */
222
+ function nativePins(style: PrintStyle, brand: string, glass: boolean, darkPaper: boolean): Partial<Record<RoleName, string>> {
223
+ const c = style.cor
224
+ const paper = c.papel
225
+ const dl = 0
226
+ const surface = shiftL(paper, dl, 1)
227
+ const raised = shiftL(paper, dl, 1)
228
+ const pins: Partial<Record<RoleName, string>> = {
229
+ bg: paper,
230
+ 'surface-solid': surface,
231
+ 'surface-raised-solid': raised,
232
+ surface: glass ? shiftL(paper, dl, 0.7, 0.82) : surface,
233
+ 'surface-raised': glass ? shiftL(paper, dl * 1.8, 0.6, 0.94) : raised,
234
+ 'surface-sunken': shiftL(paper, darkPaper ? -0.04 : -0.03, 1.1),
235
+ secondary: raised,
236
+ ink: c.tinta,
237
+ 'ink-2': c.tinta2,
238
+ 'ink-3': c.tinta3,
239
+ 'on-secondary': c.tinta,
240
+ brand,
241
+ 'focus-ring': brand,
242
+ 'cta-solid': brand,
243
+ 'on-brand': ratio(paper, brand) >= ratio(c.tinta, brand) ? paper : c.tinta,
244
+ 'on-cta': ratio(paper, brand) >= ratio(c.tinta, brand) ? paper : c.tinta,
245
+ }
246
+ // Rules: a pale printed rule is used as is; an ink-weight rule is thinned with alpha.
247
+ const lineRgb = parseColor(c.linha)
248
+ const lineAlpha = (a: number) => toCss({ ...lineRgb, a })
249
+ if (ratio(c.linha, paper) >= 3) {
250
+ pins.line = lineAlpha(0.3)
251
+ pins['line-soft'] = lineAlpha(0.16)
252
+ pins['line-strong'] = lineAlpha(0.55)
253
+ } else {
254
+ pins.line = c.linha
255
+ pins['line-soft'] = lineAlpha(0.6)
256
+ pins['line-strong'] = shiftL(c.linha, darkPaper ? 0.12 : -0.12)
257
+ }
258
+ // The highlighter tint is the soft brand (selected nav item, soft badges) when it reads against the paper.
259
+ if (deltaE2000(parseColor(c.marcaTexto), parseColor(paper)) >= 6) {
260
+ pins['brand-soft'] = c.marcaTexto
261
+ pins['nav-active'] = c.marcaTexto
262
+ }
263
+ for (const [tone, colour] of [
264
+ ['danger', c.prova.refutada],
265
+ ['success', c.prova.sustentada],
266
+ ['warning', c.prova['nao-da-para-afirmar']],
267
+ ] as const) {
268
+ if (chromatic(colour)) pins[tone] = colour
269
+ }
270
+ return pins
271
+ }
272
+
273
+ /**
274
+ * Exact colours of the other mode, over the generated background: the paper
275
+ * colour becomes the ink, and the accent is tried as the brand as printed (a
276
+ * grey accent, as in one-ink styles, is replaced by the paper colour).
277
+ */
278
+ function counterPins(style: PrintStyle, accent: string): Partial<Record<RoleName, string>> {
279
+ const brand = chromatic(accent) ? accent : style.cor.papel
280
+ const pins: Partial<Record<RoleName, string>> = { ink: style.cor.papel, brand, 'focus-ring': brand }
281
+ if (!chromatic(accent)) pins['cta-solid'] = brand
282
+ return pins
283
+ }
284
+
285
+ /** Resolves both modes and drops every pin that takes part in a failing pair, until all pairs pass. */
286
+ function settlePins(config: ThemeConfig): ThemeConfig {
287
+ const pins: Record<Mode, Partial<Record<RoleName, string>>> = { light: { ...config.pins?.light }, dark: { ...config.pins?.dark } }
288
+ for (const mode of ['light', 'dark'] as const) {
289
+ for (let round = 0; round < 12; round++) {
290
+ const failing = resolveTheme({ ...config, pins }, mode).report.filter((r) => !r.pass)
291
+ if (!failing.length) break
292
+ let dropped = false
293
+ // Foreground pins first; a background pin only when its foreground is already generated.
294
+ for (const r of failing) {
295
+ const fg = r.fg as RoleName
296
+ if (fg in pins[mode]) {
297
+ delete pins[mode][fg]
298
+ dropped = true
299
+ }
300
+ }
301
+ if (!dropped) {
302
+ for (const r of failing) {
303
+ for (const layer of r.over) {
304
+ if (layer in pins[mode]) {
305
+ delete pins[mode][layer as RoleName]
306
+ dropped = true
307
+ }
308
+ }
309
+ }
310
+ }
311
+ if (!dropped) break
312
+ }
313
+ }
314
+ return { ...config, pins }
315
+ }
316
+
317
+ /**
318
+ * The UI theme of a book style, in light and dark. The name is
319
+ * `print-<style name>`; the label is the style's own.
320
+ */
321
+ export function printStyleToTheme(style: PrintStyle, override?: PrintThemeOverride): ThemeConfig {
322
+ return settlePins(draftPrintTheme(style, override))
323
+ }
324
+
325
+ /**
326
+ * Exact print colours the derivation had to give up for contrast, per mode
327
+ * (role -> the print colour that was dropped and regenerated).
328
+ */
329
+ export function printThemeDroppedPins(style: PrintStyle, override?: PrintThemeOverride): Record<Mode, Partial<Record<RoleName, string>>> {
330
+ const draft = draftPrintTheme(style, override)
331
+ const settled = settlePins(draft)
332
+ const out: Record<Mode, Partial<Record<RoleName, string>>> = { light: {}, dark: {} }
333
+ for (const mode of ['light', 'dark'] as const) {
334
+ for (const [role, value] of Object.entries(draft.pins?.[mode] ?? {}) as Array<[RoleName, string]>) {
335
+ if (!(role in (settled.pins?.[mode] ?? {}))) out[mode][role] = value
336
+ }
337
+ }
338
+ return out
339
+ }
340
+
341
+ function draftPrintTheme(style: PrintStyle, override: PrintThemeOverride = PRINT_THEME_OVERRIDES[style.name as PrintPresetName] ?? {}): ThemeConfig {
342
+ const c = style.cor
343
+ const darkPaper = luminance(parseColor(c.papel)) < 0.2
344
+ const accent = override.brand ?? printStyleAccent(style)
345
+ // The brand is text on the paper (links, active states): the accent at a legible lightness.
346
+ const brand = legibleOn(accent, c.papel)
347
+ const e = style.estrutura
348
+
349
+ // Neutral hue: from the paper, or the ink when the paper is plain white or black.
350
+ const paper = oklch(c.papel)
351
+ const ink = oklch(c.tinta)
352
+ const tinted = paper.c >= ink.c ? paper : ink
353
+ const neutral: Seed = { hue: Math.round(tinted.h * 10) / 10, chroma: Math.min(0.02, Math.round(tinted.c * 1000) / 1000) }
354
+ const brandSeed = seedOf(accent)
355
+ const seeds: Record<SeedName, Seed> = {
356
+ brand: { hue: brandSeed.hue, chroma: Math.max(brandSeed.chroma, 0.01) },
357
+ neutral,
358
+ danger: seedOf(c.prova.refutada, TONE_FALLBACK.danger),
359
+ warning: seedOf(c.prova['nao-da-para-afirmar'], TONE_FALLBACK.warning),
360
+ success: seedOf(c.prova.sustentada, TONE_FALLBACK.success),
361
+ info: TONE_FALLBACK.info,
362
+ }
363
+
364
+ // Surface treatment: soft (glass, gradient, blurred shadow) only for the card and wash styles.
365
+ const soft = style.grafico === 'aquarela' || (e.painel === 'nenhum' && style.raio > 1)
366
+ const glass = override.glass ?? soft
367
+ const offset = e.tituloEstilo === 'sombra' || e.contornoBarra === true || e.painel === 'dossie'
368
+ const elevation = override.elevation ?? (offset ? 'offset' : soft || e.painel === 'cartao' ? 'soft' : 'flat')
369
+ const { fonts, url } = fontsOf(style)
370
+
371
+ const native = nativePins(style, brand, glass, darkPaper)
372
+ const counter = counterPins(style, accent)
373
+ const bgTexture = createTextureSvg(style)
374
+ const nativeMode: Mode = darkPaper ? 'dark' : 'light'
375
+ const counterMode: Mode = darkPaper ? 'light' : 'dark'
376
+
377
+ const config: ThemeConfig = {
378
+ name: `${PRINT_THEME_PREFIX}${style.name}`,
379
+ label: style.label,
380
+ seeds,
381
+ chartHues: chartHues(style),
382
+ radius: override.radius ?? Math.min(16, Math.round(style.raio * MM)),
383
+ contrast: 'default',
384
+ glass,
385
+ cta: override.cta ?? (soft ? 'gradient' : 'solid'),
386
+ elevation,
387
+ fonts,
388
+ ...(url ? { fontsUrl: url } : {}),
389
+ ...(bgTexture ? { strings: { "bg-image": bgTexture } } : {}),
390
+ pins: {
391
+ [nativeMode]: { ...native, ...override.pins?.[nativeMode] },
392
+ [counterMode]: { ...counter, ...override.pins?.[counterMode] },
393
+ },
394
+ }
395
+ return config
396
+ }
397
+
398
+ /** Every book style as a UI theme, in the order of `printPresets`. */
399
+ export const printThemePresets: readonly ThemeConfig[] = (Object.values(printPresets) as PrintStyle[]).map((s) => printStyleToTheme(s))
400
+
401
+ /** Stylesheet URL of the families of each print theme, by theme name (for ThemeProvider's `fonts`). */
402
+ export const printThemeFontUrls: Readonly<Record<string, string>> = Object.fromEntries(
403
+ printThemePresets.filter((t) => t.fontsUrl).map((t) => [t.name, t.fontsUrl!]),
404
+ )
package/src/scripts.ts ADDED
@@ -0,0 +1,75 @@
1
+ // Per-script typography (`:lang()` overrides). Tympan serves the humanities and
2
+ // the exact sciences in any language, so the base stacks (IBM Plex / Source
3
+ // Serif with Noto fallbacks) are adapted per writing system:
4
+ // - the script's Noto family is moved to the front (CJK needs the right
5
+ // regional glyph set; Arabic and Indic need their shaping fonts first);
6
+ // - letter-spacing is removed where it breaks joining or reads badly
7
+ // (Arabic, Indic, Thai, CJK) and uppercase eyebrows lose their meaning;
8
+ // - line heights grow for scripts with tall stacks or marks;
9
+ // - line breaking follows the script (CJK strict, Thai by dictionary).
10
+ import type { VarList } from './stylesheet.ts'
11
+
12
+ interface ScriptRule {
13
+ /** BCP 47 language tags matched with :lang(). */
14
+ langs: string[]
15
+ sans: string[]
16
+ serif?: string[]
17
+ /** Line-height multiplier applied to every --ty-font-line-height-* token. */
18
+ leading?: number
19
+ /** Letter-spacing off (tracking tokens set to 0). */
20
+ noTracking?: boolean
21
+ /** Extra declarations for the element itself. */
22
+ text?: string[]
23
+ }
24
+
25
+ export const SCRIPT_RULES: ScriptRule[] = [
26
+ { langs: ['ar', 'fa', 'ur', 'ps', 'ckb', 'sd', 'ug'], sans: ['Noto Sans Arabic', 'Noto Naskh Arabic'], serif: ['Noto Naskh Arabic'], leading: 1.2, noTracking: true },
27
+ { langs: ['he', 'yi'], sans: ['Noto Sans Hebrew'], serif: ['Noto Serif Hebrew'], leading: 1.1, noTracking: true },
28
+ { langs: ['hi', 'mr', 'ne', 'sa', 'kok', 'mai'], sans: ['Noto Sans Devanagari'], serif: ['Noto Serif Devanagari'], leading: 1.25, noTracking: true },
29
+ { langs: ['bn', 'as'], sans: ['Noto Sans Bengali'], serif: ['Noto Serif Bengali'], leading: 1.25, noTracking: true },
30
+ { langs: ['ta'], sans: ['Noto Sans Tamil'], serif: ['Noto Serif Tamil'], leading: 1.25, noTracking: true },
31
+ { langs: ['te'], sans: ['Noto Sans Telugu'], leading: 1.25, noTracking: true },
32
+ { langs: ['kn'], sans: ['Noto Sans Kannada'], leading: 1.25, noTracking: true },
33
+ { langs: ['ml'], sans: ['Noto Sans Malayalam'], leading: 1.25, noTracking: true },
34
+ { langs: ['gu'], sans: ['Noto Sans Gujarati'], leading: 1.25, noTracking: true },
35
+ { langs: ['pa'], sans: ['Noto Sans Gurmukhi'], leading: 1.25, noTracking: true },
36
+ { langs: ['si'], sans: ['Noto Sans Sinhala'], leading: 1.25, noTracking: true },
37
+ { langs: ['th'], sans: ['Noto Sans Thai'], serif: ['Noto Serif Thai'], leading: 1.25, noTracking: true, text: ['word-break: normal;', 'line-break: auto;'] },
38
+ { langs: ['lo'], sans: ['Noto Sans Lao'], leading: 1.25, noTracking: true },
39
+ { langs: ['km'], sans: ['Noto Sans Khmer'], leading: 1.25, noTracking: true },
40
+ { langs: ['my'], sans: ['Noto Sans Myanmar'], leading: 1.35, noTracking: true },
41
+ { langs: ['am', 'ti', 'gez'], sans: ['Noto Sans Ethiopic'], serif: ['Noto Serif Ethiopic'], leading: 1.15, noTracking: true },
42
+ { langs: ['hy'], sans: ['Noto Sans Armenian'] },
43
+ { langs: ['ka'], sans: ['Noto Sans Georgian'] },
44
+ { langs: ['ja'], sans: ['Noto Sans JP'], serif: ['Noto Serif JP'], leading: 1.15, noTracking: true, text: ['line-break: strict;', 'word-break: normal;', 'overflow-wrap: anywhere;'] },
45
+ { langs: ['zh', 'zh-Hans', 'zh-CN', 'zh-SG'], sans: ['Noto Sans SC'], serif: ['Noto Serif SC'], leading: 1.15, noTracking: true, text: ['line-break: strict;', 'word-break: normal;', 'overflow-wrap: anywhere;'] },
46
+ { langs: ['zh-Hant', 'zh-TW', 'zh-HK', 'zh-MO'], sans: ['Noto Sans TC'], serif: ['Noto Serif TC'], leading: 1.15, noTracking: true, text: ['line-break: strict;', 'word-break: normal;', 'overflow-wrap: anywhere;'] },
47
+ { langs: ['ko'], sans: ['Noto Sans KR'], serif: ['Noto Serif KR'], leading: 1.15, noTracking: true, text: ['word-break: keep-all;', 'overflow-wrap: anywhere;'] },
48
+ ]
49
+
50
+ const quote = (family: string) => (/^[\w-]+$/.test(family) && !/\s/.test(family) ? family : `"${family}"`)
51
+
52
+ function scaledPx(value: string, factor: number): string {
53
+ const m = /^(\d+(?:\.\d+)?)px$/.exec(value.trim())
54
+ if (!m) return value
55
+ // Round up to an even pixel so text keeps sitting on the 4 px rhythm's half-steps.
56
+ return `${Math.ceil((Number(m[1]) * factor) / 2) * 2}px`
57
+ }
58
+
59
+ /** The `:lang()` blocks, derived from the base token values. */
60
+ export function scriptRules(base: VarList): string {
61
+ const value = (name: string) => base.find(([n]) => n === name)?.[1] ?? ''
62
+ const sansBase = value('--ty-font-sans')
63
+ const serifBase = value('--ty-font-serif')
64
+ const leadings = base.filter(([n]) => n.startsWith('--ty-font-line-height-'))
65
+ const trackings = base.filter(([n]) => n.startsWith('--ty-font-tracking-'))
66
+ return SCRIPT_RULES.map((r) => {
67
+ const decls: string[] = [`--ty-font-sans: ${r.sans.map(quote).join(', ')}, ${sansBase};`]
68
+ if (r.serif) decls.push(`--ty-font-serif: ${r.serif.map(quote).join(', ')}, ${serifBase};`)
69
+ if (r.leading) for (const [n, v] of leadings) decls.push(`${n}: ${scaledPx(v, r.leading)};`)
70
+ if (r.noTracking) for (const [n] of trackings) decls.push(`${n}: 0em;`)
71
+ decls.push(...(r.text ?? []))
72
+ const selectors = r.langs.map((l) => `:lang(${l})`).join(',\n')
73
+ return `${selectors} {\n${decls.map((d) => ` ${d}`).join('\n')}\n}`
74
+ }).join('\n\n')
75
+ }