@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.
- package/LICENSE +105 -0
- package/README.md +318 -0
- package/dist/contrast-report.md +13955 -0
- package/dist/dtcg/astrlabe.dark-high.tokens.json +2947 -0
- package/dist/dtcg/astrlabe.dark.tokens.json +2947 -0
- package/dist/dtcg/astrlabe.light-high.tokens.json +2947 -0
- package/dist/dtcg/astrlabe.light.tokens.json +2947 -0
- package/dist/dtcg/base.tokens.json +422 -0
- package/dist/dtcg/density.comfortable.tokens.json +48 -0
- package/dist/dtcg/density.compact.tokens.json +48 -0
- package/dist/dtcg/density.default.tokens.json +48 -0
- package/dist/dtcg/fakhir.dark-high.tokens.json +2971 -0
- package/dist/dtcg/fakhir.dark.tokens.json +2971 -0
- package/dist/dtcg/fakhir.light-high.tokens.json +2971 -0
- package/dist/dtcg/fakhir.light.tokens.json +2971 -0
- package/dist/dtcg/flow.tokens.json +675 -0
- package/dist/dtcg/high-contrast.dark.tokens.json +2943 -0
- package/dist/dtcg/high-contrast.light.tokens.json +2943 -0
- package/dist/dtcg/neutral.dark-high.tokens.json +2947 -0
- package/dist/dtcg/neutral.dark.tokens.json +2947 -0
- package/dist/dtcg/neutral.light-high.tokens.json +2947 -0
- package/dist/dtcg/neutral.light.tokens.json +2947 -0
- package/dist/dtcg/print/print-aquarela.dark.tokens.json +3014 -0
- package/dist/dtcg/print/print-aquarela.light.tokens.json +3009 -0
- package/dist/dtcg/print/print-art-nouveau.dark.tokens.json +2944 -0
- package/dist/dtcg/print/print-art-nouveau.light.tokens.json +2944 -0
- package/dist/dtcg/print/print-atlas-oficial.dark.tokens.json +2945 -0
- package/dist/dtcg/print/print-atlas-oficial.light.tokens.json +2945 -0
- package/dist/dtcg/print/print-azulejo-modernista.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-azulejo-modernista.light.tokens.json +2946 -0
- package/dist/dtcg/print/print-bauhaus.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-bauhaus.light.tokens.json +2942 -0
- package/dist/dtcg/print/print-blocos-coloridos.dark.tokens.json +2974 -0
- package/dist/dtcg/print/print-blocos-coloridos.light.tokens.json +2967 -0
- package/dist/dtcg/print/print-brutalista.dark.tokens.json +2956 -0
- package/dist/dtcg/print/print-brutalista.light.tokens.json +2956 -0
- package/dist/dtcg/print/print-caderno.dark.tokens.json +2958 -0
- package/dist/dtcg/print/print-caderno.light.tokens.json +2954 -0
- package/dist/dtcg/print/print-cartao-postal.dark.tokens.json +2958 -0
- package/dist/dtcg/print/print-cartao-postal.light.tokens.json +2954 -0
- package/dist/dtcg/print/print-cientifico.dark.tokens.json +2944 -0
- package/dist/dtcg/print/print-cientifico.light.tokens.json +2944 -0
- package/dist/dtcg/print/print-concretismo.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-concretismo.light.tokens.json +2942 -0
- package/dist/dtcg/print/print-construtivismo.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-construtivismo.light.tokens.json +2946 -0
- package/dist/dtcg/print/print-cordel.dark.tokens.json +2958 -0
- package/dist/dtcg/print/print-cordel.light.tokens.json +2954 -0
- package/dist/dtcg/print/print-dados-br.dark.tokens.json +2959 -0
- package/dist/dtcg/print/print-dados-br.light.tokens.json +2956 -0
- package/dist/dtcg/print/print-dashboard.dark.tokens.json +3015 -0
- package/dist/dtcg/print/print-dashboard.light.tokens.json +3007 -0
- package/dist/dtcg/print/print-diagrama-modernista.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-diagrama-modernista.light.tokens.json +2942 -0
- package/dist/dtcg/print/print-divulgacao.dark.tokens.json +2942 -0
- package/dist/dtcg/print/print-divulgacao.light.tokens.json +2938 -0
- package/dist/dtcg/print/print-fluxo-historico.dark.tokens.json +2944 -0
- package/dist/dtcg/print/print-fluxo-historico.light.tokens.json +2941 -0
- package/dist/dtcg/print/print-grade-holandesa.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-grade-holandesa.light.tokens.json +2942 -0
- package/dist/dtcg/print/print-graficos-1900.dark.tokens.json +2959 -0
- package/dist/dtcg/print/print-graficos-1900.light.tokens.json +2955 -0
- package/dist/dtcg/print/print-infografico-ilustrado.dark.tokens.json +2974 -0
- package/dist/dtcg/print/print-infografico-ilustrado.light.tokens.json +2970 -0
- package/dist/dtcg/print/print-isotype.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-isotype.light.tokens.json +2946 -0
- package/dist/dtcg/print/print-jornal-1959.dark.tokens.json +2944 -0
- package/dist/dtcg/print/print-jornal-1959.light.tokens.json +2944 -0
- package/dist/dtcg/print/print-jornal.dark.tokens.json +2958 -0
- package/dist/dtcg/print/print-jornal.light.tokens.json +2951 -0
- package/dist/dtcg/print/print-mapa-de-metro.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-mapa-de-metro.light.tokens.json +2946 -0
- package/dist/dtcg/print/print-memphis.dark.tokens.json +2942 -0
- package/dist/dtcg/print/print-memphis.light.tokens.json +2938 -0
- package/dist/dtcg/print/print-minimo-de-tinta.dark.tokens.json +2958 -0
- package/dist/dtcg/print/print-minimo-de-tinta.light.tokens.json +2951 -0
- package/dist/dtcg/print/print-papel-recortado.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-papel-recortado.light.tokens.json +2942 -0
- package/dist/dtcg/print/print-papel-salmao.dark.tokens.json +2944 -0
- package/dist/dtcg/print/print-papel-salmao.light.tokens.json +2941 -0
- package/dist/dtcg/print/print-pictogramas.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-pictogramas.light.tokens.json +2942 -0
- package/dist/dtcg/print/print-pop-art.dark.tokens.json +2942 -0
- package/dist/dtcg/print/print-pop-art.light.tokens.json +2938 -0
- package/dist/dtcg/print/print-prancheta-clara.dark.tokens.json +2960 -0
- package/dist/dtcg/print/print-prancheta-clara.light.tokens.json +2956 -0
- package/dist/dtcg/print/print-prancheta.dark.tokens.json +2956 -0
- package/dist/dtcg/print/print-prancheta.light.tokens.json +2960 -0
- package/dist/dtcg/print/print-proporcao-modular.dark.tokens.json +2945 -0
- package/dist/dtcg/print/print-proporcao-modular.light.tokens.json +2941 -0
- package/dist/dtcg/print/print-riso.dark.tokens.json +2960 -0
- package/dist/dtcg/print/print-riso.light.tokens.json +2956 -0
- package/dist/dtcg/print/print-semanario.dark.tokens.json +2944 -0
- package/dist/dtcg/print/print-semanario.light.tokens.json +2937 -0
- package/dist/dtcg/print/print-sinalizacao.dark.tokens.json +2946 -0
- package/dist/dtcg/print/print-sinalizacao.light.tokens.json +2942 -0
- package/dist/dtcg/print/print-suico.dark.tokens.json +2960 -0
- package/dist/dtcg/print/print-suico.light.tokens.json +2956 -0
- package/dist/dtcg/print/print-tropicalia.dark.tokens.json +2945 -0
- package/dist/dtcg/print/print-tropicalia.light.tokens.json +2941 -0
- package/dist/dtcg/print-aquarela.dark-high.tokens.json +3014 -0
- package/dist/dtcg/print-aquarela.dark.tokens.json +3014 -0
- package/dist/dtcg/print-aquarela.light-high.tokens.json +3014 -0
- package/dist/dtcg/print-aquarela.light.tokens.json +3009 -0
- package/dist/dtcg/print-art-nouveau.dark-high.tokens.json +2944 -0
- package/dist/dtcg/print-art-nouveau.dark.tokens.json +2944 -0
- package/dist/dtcg/print-art-nouveau.light-high.tokens.json +2944 -0
- package/dist/dtcg/print-art-nouveau.light.tokens.json +2944 -0
- package/dist/dtcg/print-atlas-oficial.dark-high.tokens.json +2945 -0
- package/dist/dtcg/print-atlas-oficial.dark.tokens.json +2945 -0
- package/dist/dtcg/print-atlas-oficial.light-high.tokens.json +2945 -0
- package/dist/dtcg/print-atlas-oficial.light.tokens.json +2945 -0
- package/dist/dtcg/print-azulejo-modernista.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-azulejo-modernista.dark.tokens.json +2946 -0
- package/dist/dtcg/print-azulejo-modernista.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-azulejo-modernista.light.tokens.json +2946 -0
- package/dist/dtcg/print-bauhaus.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-bauhaus.dark.tokens.json +2946 -0
- package/dist/dtcg/print-bauhaus.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-bauhaus.light.tokens.json +2942 -0
- package/dist/dtcg/print-blocos-coloridos.dark-high.tokens.json +2974 -0
- package/dist/dtcg/print-blocos-coloridos.dark.tokens.json +2974 -0
- package/dist/dtcg/print-blocos-coloridos.light-high.tokens.json +2974 -0
- package/dist/dtcg/print-blocos-coloridos.light.tokens.json +2967 -0
- package/dist/dtcg/print-brutalista.dark-high.tokens.json +2956 -0
- package/dist/dtcg/print-brutalista.dark.tokens.json +2956 -0
- package/dist/dtcg/print-brutalista.light-high.tokens.json +2956 -0
- package/dist/dtcg/print-brutalista.light.tokens.json +2956 -0
- package/dist/dtcg/print-caderno.dark-high.tokens.json +2958 -0
- package/dist/dtcg/print-caderno.dark.tokens.json +2958 -0
- package/dist/dtcg/print-caderno.light-high.tokens.json +2958 -0
- package/dist/dtcg/print-caderno.light.tokens.json +2954 -0
- package/dist/dtcg/print-cartao-postal.dark-high.tokens.json +2958 -0
- package/dist/dtcg/print-cartao-postal.dark.tokens.json +2958 -0
- package/dist/dtcg/print-cartao-postal.light-high.tokens.json +2958 -0
- package/dist/dtcg/print-cartao-postal.light.tokens.json +2954 -0
- package/dist/dtcg/print-cientifico.dark-high.tokens.json +2944 -0
- package/dist/dtcg/print-cientifico.dark.tokens.json +2944 -0
- package/dist/dtcg/print-cientifico.light-high.tokens.json +2944 -0
- package/dist/dtcg/print-cientifico.light.tokens.json +2944 -0
- package/dist/dtcg/print-concretismo.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-concretismo.dark.tokens.json +2946 -0
- package/dist/dtcg/print-concretismo.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-concretismo.light.tokens.json +2942 -0
- package/dist/dtcg/print-construtivismo.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-construtivismo.dark.tokens.json +2946 -0
- package/dist/dtcg/print-construtivismo.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-construtivismo.light.tokens.json +2946 -0
- package/dist/dtcg/print-cordel.dark-high.tokens.json +2958 -0
- package/dist/dtcg/print-cordel.dark.tokens.json +2958 -0
- package/dist/dtcg/print-cordel.light-high.tokens.json +2958 -0
- package/dist/dtcg/print-cordel.light.tokens.json +2954 -0
- package/dist/dtcg/print-dados-br.dark-high.tokens.json +2959 -0
- package/dist/dtcg/print-dados-br.dark.tokens.json +2959 -0
- package/dist/dtcg/print-dados-br.light-high.tokens.json +2959 -0
- package/dist/dtcg/print-dados-br.light.tokens.json +2956 -0
- package/dist/dtcg/print-dashboard.dark-high.tokens.json +3015 -0
- package/dist/dtcg/print-dashboard.dark.tokens.json +3015 -0
- package/dist/dtcg/print-dashboard.light-high.tokens.json +3015 -0
- package/dist/dtcg/print-dashboard.light.tokens.json +3007 -0
- package/dist/dtcg/print-diagrama-modernista.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-diagrama-modernista.dark.tokens.json +2946 -0
- package/dist/dtcg/print-diagrama-modernista.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-diagrama-modernista.light.tokens.json +2942 -0
- package/dist/dtcg/print-divulgacao.dark-high.tokens.json +2942 -0
- package/dist/dtcg/print-divulgacao.dark.tokens.json +2942 -0
- package/dist/dtcg/print-divulgacao.light-high.tokens.json +2942 -0
- package/dist/dtcg/print-divulgacao.light.tokens.json +2938 -0
- package/dist/dtcg/print-fluxo-historico.dark-high.tokens.json +2944 -0
- package/dist/dtcg/print-fluxo-historico.dark.tokens.json +2944 -0
- package/dist/dtcg/print-fluxo-historico.light-high.tokens.json +2944 -0
- package/dist/dtcg/print-fluxo-historico.light.tokens.json +2941 -0
- package/dist/dtcg/print-grade-holandesa.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-grade-holandesa.dark.tokens.json +2946 -0
- package/dist/dtcg/print-grade-holandesa.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-grade-holandesa.light.tokens.json +2942 -0
- package/dist/dtcg/print-graficos-1900.dark-high.tokens.json +2959 -0
- package/dist/dtcg/print-graficos-1900.dark.tokens.json +2959 -0
- package/dist/dtcg/print-graficos-1900.light-high.tokens.json +2959 -0
- package/dist/dtcg/print-graficos-1900.light.tokens.json +2955 -0
- package/dist/dtcg/print-infografico-ilustrado.dark-high.tokens.json +2974 -0
- package/dist/dtcg/print-infografico-ilustrado.dark.tokens.json +2974 -0
- package/dist/dtcg/print-infografico-ilustrado.light-high.tokens.json +2974 -0
- package/dist/dtcg/print-infografico-ilustrado.light.tokens.json +2970 -0
- package/dist/dtcg/print-isotype.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-isotype.dark.tokens.json +2946 -0
- package/dist/dtcg/print-isotype.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-isotype.light.tokens.json +2946 -0
- package/dist/dtcg/print-jornal-1959.dark-high.tokens.json +2944 -0
- package/dist/dtcg/print-jornal-1959.dark.tokens.json +2944 -0
- package/dist/dtcg/print-jornal-1959.light-high.tokens.json +2944 -0
- package/dist/dtcg/print-jornal-1959.light.tokens.json +2944 -0
- package/dist/dtcg/print-jornal.dark-high.tokens.json +2958 -0
- package/dist/dtcg/print-jornal.dark.tokens.json +2958 -0
- package/dist/dtcg/print-jornal.light-high.tokens.json +2958 -0
- package/dist/dtcg/print-jornal.light.tokens.json +2951 -0
- package/dist/dtcg/print-mapa-de-metro.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-mapa-de-metro.dark.tokens.json +2946 -0
- package/dist/dtcg/print-mapa-de-metro.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-mapa-de-metro.light.tokens.json +2946 -0
- package/dist/dtcg/print-memphis.dark-high.tokens.json +2942 -0
- package/dist/dtcg/print-memphis.dark.tokens.json +2942 -0
- package/dist/dtcg/print-memphis.light-high.tokens.json +2942 -0
- package/dist/dtcg/print-memphis.light.tokens.json +2938 -0
- package/dist/dtcg/print-minimo-de-tinta.dark-high.tokens.json +2958 -0
- package/dist/dtcg/print-minimo-de-tinta.dark.tokens.json +2958 -0
- package/dist/dtcg/print-minimo-de-tinta.light-high.tokens.json +2958 -0
- package/dist/dtcg/print-minimo-de-tinta.light.tokens.json +2951 -0
- package/dist/dtcg/print-papel-recortado.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-papel-recortado.dark.tokens.json +2946 -0
- package/dist/dtcg/print-papel-recortado.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-papel-recortado.light.tokens.json +2942 -0
- package/dist/dtcg/print-papel-salmao.dark-high.tokens.json +2944 -0
- package/dist/dtcg/print-papel-salmao.dark.tokens.json +2944 -0
- package/dist/dtcg/print-papel-salmao.light-high.tokens.json +2944 -0
- package/dist/dtcg/print-papel-salmao.light.tokens.json +2941 -0
- package/dist/dtcg/print-pictogramas.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-pictogramas.dark.tokens.json +2946 -0
- package/dist/dtcg/print-pictogramas.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-pictogramas.light.tokens.json +2942 -0
- package/dist/dtcg/print-pop-art.dark-high.tokens.json +2942 -0
- package/dist/dtcg/print-pop-art.dark.tokens.json +2942 -0
- package/dist/dtcg/print-pop-art.light-high.tokens.json +2942 -0
- package/dist/dtcg/print-pop-art.light.tokens.json +2938 -0
- package/dist/dtcg/print-prancheta-clara.dark-high.tokens.json +2960 -0
- package/dist/dtcg/print-prancheta-clara.dark.tokens.json +2960 -0
- package/dist/dtcg/print-prancheta-clara.light-high.tokens.json +2960 -0
- package/dist/dtcg/print-prancheta-clara.light.tokens.json +2956 -0
- package/dist/dtcg/print-prancheta.dark-high.tokens.json +2960 -0
- package/dist/dtcg/print-prancheta.dark.tokens.json +2956 -0
- package/dist/dtcg/print-prancheta.light-high.tokens.json +2960 -0
- package/dist/dtcg/print-prancheta.light.tokens.json +2960 -0
- package/dist/dtcg/print-proporcao-modular.dark-high.tokens.json +2945 -0
- package/dist/dtcg/print-proporcao-modular.dark.tokens.json +2945 -0
- package/dist/dtcg/print-proporcao-modular.light-high.tokens.json +2945 -0
- package/dist/dtcg/print-proporcao-modular.light.tokens.json +2941 -0
- package/dist/dtcg/print-riso.dark-high.tokens.json +2960 -0
- package/dist/dtcg/print-riso.dark.tokens.json +2960 -0
- package/dist/dtcg/print-riso.light-high.tokens.json +2960 -0
- package/dist/dtcg/print-riso.light.tokens.json +2956 -0
- package/dist/dtcg/print-semanario.dark-high.tokens.json +2944 -0
- package/dist/dtcg/print-semanario.dark.tokens.json +2944 -0
- package/dist/dtcg/print-semanario.light-high.tokens.json +2944 -0
- package/dist/dtcg/print-semanario.light.tokens.json +2937 -0
- package/dist/dtcg/print-sinalizacao.dark-high.tokens.json +2946 -0
- package/dist/dtcg/print-sinalizacao.dark.tokens.json +2946 -0
- package/dist/dtcg/print-sinalizacao.light-high.tokens.json +2946 -0
- package/dist/dtcg/print-sinalizacao.light.tokens.json +2942 -0
- package/dist/dtcg/print-suico.dark-high.tokens.json +2960 -0
- package/dist/dtcg/print-suico.dark.tokens.json +2960 -0
- package/dist/dtcg/print-suico.light-high.tokens.json +2960 -0
- package/dist/dtcg/print-suico.light.tokens.json +2956 -0
- package/dist/dtcg/print-tropicalia.dark-high.tokens.json +2945 -0
- package/dist/dtcg/print-tropicalia.dark.tokens.json +2945 -0
- package/dist/dtcg/print-tropicalia.light-high.tokens.json +2945 -0
- package/dist/dtcg/print-tropicalia.light.tokens.json +2941 -0
- package/dist/dtcg/tympan.dark-high.tokens.json +2971 -0
- package/dist/dtcg/tympan.dark.tokens.json +2971 -0
- package/dist/dtcg/tympan.light-high.tokens.json +2971 -0
- package/dist/dtcg/tympan.light.tokens.json +2971 -0
- package/dist/index.d.ts +642 -0
- package/dist/index.js +4873 -0
- package/dist/index.js.map +1 -0
- package/dist/print-aliases.d.ts +54 -0
- package/dist/print-aliases.js +71 -0
- package/dist/print-aliases.js.map +1 -0
- package/dist/print-themes/print-aquarela.css +1483 -0
- package/dist/print-themes/print-art-nouveau.css +1467 -0
- package/dist/print-themes/print-atlas-oficial.css +1467 -0
- package/dist/print-themes/print-azulejo-modernista.css +1467 -0
- package/dist/print-themes/print-bauhaus.css +1467 -0
- package/dist/print-themes/print-blocos-coloridos.css +1467 -0
- package/dist/print-themes/print-brutalista.css +1475 -0
- package/dist/print-themes/print-caderno.css +1483 -0
- package/dist/print-themes/print-cartao-postal.css +1483 -0
- package/dist/print-themes/print-cientifico.css +1467 -0
- package/dist/print-themes/print-concretismo.css +1467 -0
- package/dist/print-themes/print-construtivismo.css +1467 -0
- package/dist/print-themes/print-cordel.css +1483 -0
- package/dist/print-themes/print-dados-br.css +1475 -0
- package/dist/print-themes/print-dashboard.css +1475 -0
- package/dist/print-themes/print-diagrama-modernista.css +1467 -0
- package/dist/print-themes/print-divulgacao.css +1467 -0
- package/dist/print-themes/print-fluxo-historico.css +1475 -0
- package/dist/print-themes/print-grade-holandesa.css +1475 -0
- package/dist/print-themes/print-graficos-1900.css +1483 -0
- package/dist/print-themes/print-infografico-ilustrado.css +1467 -0
- package/dist/print-themes/print-isotype.css +1467 -0
- package/dist/print-themes/print-jornal-1959.css +1467 -0
- package/dist/print-themes/print-jornal.css +1475 -0
- package/dist/print-themes/print-mapa-de-metro.css +1467 -0
- package/dist/print-themes/print-memphis.css +1467 -0
- package/dist/print-themes/print-minimo-de-tinta.css +1475 -0
- package/dist/print-themes/print-papel-recortado.css +1467 -0
- package/dist/print-themes/print-papel-salmao.css +1467 -0
- package/dist/print-themes/print-pictogramas.css +1467 -0
- package/dist/print-themes/print-pop-art.css +1467 -0
- package/dist/print-themes/print-prancheta-clara.css +1483 -0
- package/dist/print-themes/print-prancheta.css +1483 -0
- package/dist/print-themes/print-proporcao-modular.css +1467 -0
- package/dist/print-themes/print-riso.css +1483 -0
- package/dist/print-themes/print-semanario.css +1467 -0
- package/dist/print-themes/print-sinalizacao.css +1467 -0
- package/dist/print-themes/print-suico.css +1475 -0
- package/dist/print-themes/print-tropicalia.css +1467 -0
- package/dist/print-themes.css +57215 -0
- package/dist/print-themes.json +236 -0
- package/dist/tokens.css +64416 -0
- package/dist/tokens.json +31449 -0
- package/dist/values.d.ts +14 -0
- package/dist/values.js +31454 -0
- package/package.json +67 -0
- package/src/base/motion.tokens.json +15 -0
- package/src/base/space.tokens.json +122 -0
- package/src/base/type.tokens.json +227 -0
- package/src/base/z.tokens.json +13 -0
- package/src/color.ts +239 -0
- package/src/dtcg.ts +102 -0
- package/src/flow.ts +130 -0
- package/src/index.ts +17 -0
- package/src/presets.ts +135 -0
- package/src/presets.ts.diff +26 -0
- package/src/print-aliases.ts +84 -0
- package/src/print-presets.ts +1611 -0
- package/src/print-themes.ts +404 -0
- package/src/scripts.ts +75 -0
- package/src/stylesheet.ts +238 -0
- package/src/theme.ts +553 -0
- 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
|
+
}
|
package/src/theme.ts.rej
ADDED
|
@@ -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
|