@clhaas/palette-kit 0.1.8 → 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 (295) hide show
  1. package/.codex/skills/color-pipeline-implementer/SKILL.md +23 -0
  2. package/.codex/skills/commit-message-crafter/SKILL.md +63 -0
  3. package/.codex/skills/commit-message-crafter/references/benchmarks.md +20 -0
  4. package/.codex/skills/contrast-solver-helper/SKILL.md +20 -0
  5. package/.codex/skills/exporters-builder/SKILL.md +20 -0
  6. package/.codex/skills/markdownlint-writer/SKILL.md +32 -0
  7. package/.codex/skills/phase-implementation-runbook/SKILL.md +92 -0
  8. package/.codex/skills/type-contract-auditor/SKILL.md +21 -0
  9. package/.github/skills/review-guide/SKILL.md +23 -0
  10. package/.github/skills/review-guide/references/review-guide-v0.3.md +629 -0
  11. package/.markdownlint.json +4 -0
  12. package/AGENTS.md +16 -0
  13. package/CHANGELOG.md +34 -0
  14. package/README.md +79 -169
  15. package/biome.json +43 -0
  16. package/dist/cli/args.d.ts +12 -0
  17. package/dist/cli/args.js +56 -0
  18. package/dist/cli/args.test.js +22 -0
  19. package/dist/cli/codegen/__snapshots__/tokens.test.js.snap +87 -0
  20. package/dist/cli/codegen/tokens.d.ts +12 -0
  21. package/dist/cli/codegen/tokens.js +139 -0
  22. package/dist/cli/codegen/tokens.test.d.ts +1 -0
  23. package/dist/cli/codegen/tokens.test.js +51 -0
  24. package/dist/cli/config.d.ts +40 -0
  25. package/dist/cli/config.js +34 -0
  26. package/dist/cli/validate.d.ts +2 -0
  27. package/dist/cli/validate.js +33 -0
  28. package/dist/cli/validate.test.d.ts +1 -0
  29. package/dist/cli/validate.test.js +40 -0
  30. package/dist/cli.js +138 -140
  31. package/dist/contrast/apca.d.ts +2 -2
  32. package/dist/contrast/apca.js +14 -4
  33. package/dist/contrast/apca.test.d.ts +1 -0
  34. package/dist/contrast/apca.test.js +16 -0
  35. package/dist/contrast/index.d.ts +4 -0
  36. package/dist/contrast/index.js +4 -0
  37. package/dist/contrast/scoring.d.ts +4 -0
  38. package/dist/contrast/scoring.js +31 -0
  39. package/dist/contrast/scoring.test.d.ts +1 -0
  40. package/dist/contrast/scoring.test.js +148 -0
  41. package/dist/contrast/solver.d.ts +13 -0
  42. package/dist/contrast/solver.js +170 -0
  43. package/dist/contrast/solver.test.d.ts +1 -0
  44. package/dist/contrast/solver.test.js +75 -0
  45. package/dist/contrast/types.d.ts +17 -0
  46. package/dist/contrast/types.js +1 -0
  47. package/dist/contrast/utils.d.ts +4 -0
  48. package/dist/contrast/utils.js +18 -0
  49. package/dist/contrast/wcag2.d.ts +3 -0
  50. package/dist/contrast/wcag2.js +19 -0
  51. package/dist/contrast/wcag2.test.d.ts +1 -0
  52. package/dist/contrast/wcag2.test.js +17 -0
  53. package/dist/core/createTheme.d.ts +35 -0
  54. package/dist/core/createTheme.js +24 -0
  55. package/dist/core/dx-helpers.test.d.ts +1 -0
  56. package/dist/core/dx-helpers.test.js +61 -0
  57. package/dist/core/index.d.ts +2 -0
  58. package/dist/core/index.js +2 -0
  59. package/dist/core/onSolid.test.d.ts +1 -0
  60. package/dist/core/onSolid.test.js +118 -0
  61. package/dist/core/qa.v1.test.d.ts +1 -0
  62. package/dist/core/qa.v1.test.js +112 -0
  63. package/dist/core/resolve.d.ts +3 -0
  64. package/dist/core/resolve.js +8 -0
  65. package/dist/core/resolve.test.d.ts +1 -0
  66. package/dist/core/resolve.test.js +89 -0
  67. package/dist/core/resolveMany.d.ts +8 -0
  68. package/dist/core/resolveMany.js +17 -0
  69. package/dist/core/tokenRegistry.d.ts +23 -0
  70. package/dist/core/tokenRegistry.js +83 -0
  71. package/dist/core/tokenRegistry.test.d.ts +1 -0
  72. package/dist/core/tokenRegistry.test.js +133 -0
  73. package/dist/engine/applyOperators.d.ts +3 -0
  74. package/dist/engine/applyOperators.js +23 -0
  75. package/dist/engine/context.d.ts +4 -0
  76. package/dist/engine/context.js +1 -0
  77. package/dist/engine/gamut.d.ts +13 -0
  78. package/dist/engine/gamut.js +101 -0
  79. package/dist/engine/gamut.test.d.ts +1 -0
  80. package/dist/engine/gamut.test.js +23 -0
  81. package/dist/engine/generateScale.d.ts +15 -0
  82. package/dist/engine/generateScale.js +29 -0
  83. package/dist/engine/generateScale.test.d.ts +1 -0
  84. package/dist/engine/generateScale.test.js +32 -0
  85. package/dist/engine/index.d.ts +8 -0
  86. package/dist/engine/index.js +4 -0
  87. package/dist/engine/normalize.d.ts +43 -0
  88. package/dist/engine/normalize.js +403 -0
  89. package/dist/engine/normalize.test.d.ts +1 -0
  90. package/dist/engine/normalize.test.js +136 -0
  91. package/dist/engine/onSolid.d.ts +3 -0
  92. package/dist/engine/onSolid.js +110 -0
  93. package/dist/engine/resolveBaseColor.d.ts +25 -0
  94. package/dist/engine/resolveBaseColor.js +127 -0
  95. package/dist/engine/resolveBaseColor.test.d.ts +1 -0
  96. package/dist/engine/resolveBaseColor.test.js +97 -0
  97. package/dist/export/__snapshots__/exportTheme.test.js.snap +74 -0
  98. package/dist/export/exportTheme.d.ts +47 -0
  99. package/dist/export/exportTheme.js +170 -0
  100. package/dist/export/exportTheme.test.d.ts +1 -0
  101. package/dist/export/exportTheme.test.js +118 -0
  102. package/dist/export/index.d.ts +1 -0
  103. package/dist/export/index.js +1 -0
  104. package/dist/export/serializeColor.d.ts +1 -0
  105. package/dist/export/serializeColor.js +1 -0
  106. package/dist/export/serializeColor.test.d.ts +1 -0
  107. package/dist/export/serializeColor.test.js +54 -0
  108. package/dist/export.d.ts +1 -0
  109. package/dist/export.js +1 -0
  110. package/dist/index.d.ts +3 -22
  111. package/dist/index.js +2 -18
  112. package/dist/operators/emphasis.d.ts +3 -0
  113. package/dist/operators/emphasis.js +113 -0
  114. package/dist/operators/emphasis.test.d.ts +1 -0
  115. package/dist/operators/emphasis.test.js +69 -0
  116. package/dist/operators/index.d.ts +3 -0
  117. package/dist/operators/index.js +2 -0
  118. package/dist/operators/state.d.ts +3 -0
  119. package/dist/operators/state.js +102 -0
  120. package/dist/operators/state.test.d.ts +1 -0
  121. package/dist/operators/state.test.js +48 -0
  122. package/dist/operators/types.d.ts +13 -0
  123. package/dist/operators/types.js +1 -0
  124. package/dist/operators/utils.d.ts +16 -0
  125. package/dist/operators/utils.js +23 -0
  126. package/dist/presets/curves.d.ts +28 -0
  127. package/dist/presets/curves.js +145 -0
  128. package/dist/presets/index.d.ts +2 -0
  129. package/dist/presets/index.js +1 -0
  130. package/dist/presets/tokens/index.d.ts +3 -0
  131. package/dist/presets/tokens/index.js +3 -0
  132. package/dist/presets/tokens/minimal-ui.d.ts +6 -0
  133. package/dist/presets/tokens/minimal-ui.js +53 -0
  134. package/dist/presets/tokens/modern-ui.d.ts +5 -0
  135. package/dist/presets/tokens/modern-ui.js +83 -0
  136. package/dist/presets/tokens/presets.test.d.ts +1 -0
  137. package/dist/presets/tokens/presets.test.js +31 -0
  138. package/dist/presets/tokens/radixLike-ui.d.ts +6 -0
  139. package/dist/presets/tokens/radixLike-ui.js +77 -0
  140. package/dist/serialize/index.d.ts +1 -0
  141. package/dist/serialize/index.js +1 -0
  142. package/dist/serialize/normalizeOutput.d.ts +6 -0
  143. package/dist/serialize/normalizeOutput.js +45 -0
  144. package/dist/serialize/serializeColor.d.ts +21 -0
  145. package/dist/serialize/serializeColor.js +178 -0
  146. package/dist/serialize/serializeResolved.test.d.ts +1 -0
  147. package/dist/serialize/serializeResolved.test.js +45 -0
  148. package/dist/serialize.d.ts +1 -0
  149. package/dist/serialize.js +1 -0
  150. package/dist/types/index.d.ts +187 -0
  151. package/dist/types/index.js +1 -0
  152. package/dist/utils/clamp.d.ts +1 -0
  153. package/dist/utils/clamp.js +1 -0
  154. package/dist/utils/index.d.ts +1 -0
  155. package/dist/utils/index.js +1 -0
  156. package/dist/utils/lerp.d.ts +1 -0
  157. package/dist/utils/lerp.js +1 -0
  158. package/dist/utils/parseColor.d.ts +6 -0
  159. package/dist/utils/parseColor.js +67 -0
  160. package/dist/utils/parseColor.test.d.ts +1 -0
  161. package/dist/utils/parseColor.test.js +51 -0
  162. package/dist/utils/smoothstep.d.ts +1 -0
  163. package/dist/utils/smoothstep.js +5 -0
  164. package/package.json +19 -12
  165. package/planning/phase-10-review.md +550 -0
  166. package/planning/phase-7-review.md +411 -0
  167. package/planning/phase-8-review.md +669 -0
  168. package/planning/phase-9-review.md +564 -0
  169. package/planning/roadmap-v0.3.md +284 -0
  170. package/planning/spec-serializer-v0.3.md +324 -0
  171. package/planning/spec-v0.3.md +305 -0
  172. package/src/cli/args.test.ts +28 -0
  173. package/src/cli/args.ts +66 -0
  174. package/src/cli/codegen/__snapshots__/tokens.test.ts.snap +87 -0
  175. package/src/cli/codegen/tokens.test.ts +61 -0
  176. package/src/cli/codegen/tokens.ts +191 -0
  177. package/src/cli/config.ts +71 -0
  178. package/src/cli/validate.test.ts +49 -0
  179. package/src/cli/validate.ts +38 -0
  180. package/src/cli.ts +183 -0
  181. package/src/contrast/apca.test.ts +20 -0
  182. package/src/contrast/apca.ts +26 -0
  183. package/src/contrast/index.ts +4 -0
  184. package/src/contrast/scoring.test.ts +188 -0
  185. package/src/contrast/scoring.ts +48 -0
  186. package/src/contrast/solver.test.ts +147 -0
  187. package/src/contrast/solver.ts +235 -0
  188. package/src/contrast/types.ts +20 -0
  189. package/src/contrast/utils.ts +28 -0
  190. package/src/contrast/wcag2.test.ts +21 -0
  191. package/src/contrast/wcag2.ts +24 -0
  192. package/src/core/createTheme.ts +78 -0
  193. package/src/core/dx-helpers.test.ts +82 -0
  194. package/src/core/index.ts +7 -0
  195. package/src/core/onSolid.test.ts +146 -0
  196. package/src/core/qa.v1.test.ts +149 -0
  197. package/src/core/resolve.test.ts +99 -0
  198. package/src/core/resolve.ts +11 -0
  199. package/src/core/resolveMany.ts +22 -0
  200. package/src/core/tokenRegistry.test.ts +153 -0
  201. package/src/core/tokenRegistry.ts +114 -0
  202. package/src/engine/applyOperators.ts +32 -0
  203. package/src/engine/context.ts +8 -0
  204. package/src/engine/gamut.test.ts +30 -0
  205. package/src/engine/gamut.ts +144 -0
  206. package/src/engine/generateScale.test.ts +46 -0
  207. package/src/engine/generateScale.ts +48 -0
  208. package/src/engine/index.ts +8 -0
  209. package/src/engine/normalize.test.ts +222 -0
  210. package/src/engine/normalize.ts +550 -0
  211. package/src/engine/onSolid.ts +178 -0
  212. package/src/engine/resolveBaseColor.test.ts +117 -0
  213. package/src/engine/resolveBaseColor.ts +203 -0
  214. package/src/export/__snapshots__/exportTheme.test.ts.snap +74 -0
  215. package/src/export/exportTheme.test.ts +144 -0
  216. package/src/export/exportTheme.ts +251 -0
  217. package/src/export/index.ts +1 -0
  218. package/src/export/serializeColor.test.ts +73 -0
  219. package/src/export/serializeColor.ts +1 -0
  220. package/src/export.ts +1 -0
  221. package/src/index.ts +3 -0
  222. package/src/operators/emphasis.test.ts +85 -0
  223. package/src/operators/emphasis.ts +132 -0
  224. package/src/operators/index.ts +3 -0
  225. package/src/operators/state.test.ts +66 -0
  226. package/src/operators/state.ts +122 -0
  227. package/src/operators/types.ts +14 -0
  228. package/src/operators/utils.ts +44 -0
  229. package/src/presets/curves.ts +168 -0
  230. package/src/presets/index.ts +2 -0
  231. package/src/presets/tokens/index.ts +3 -0
  232. package/src/presets/tokens/minimal-ui.ts +55 -0
  233. package/src/presets/tokens/modern-ui.ts +85 -0
  234. package/src/presets/tokens/presets.test.ts +46 -0
  235. package/src/presets/tokens/radixLike-ui.ts +79 -0
  236. package/src/serialize/index.ts +1 -0
  237. package/src/serialize/normalizeOutput.ts +63 -0
  238. package/src/serialize/serializeColor.ts +260 -0
  239. package/src/serialize/serializeResolved.test.ts +57 -0
  240. package/src/serialize.ts +1 -0
  241. package/src/types/index.ts +207 -0
  242. package/src/utils/clamp.ts +2 -0
  243. package/src/utils/index.ts +1 -0
  244. package/src/utils/lerp.ts +1 -0
  245. package/src/utils/parseColor.test.ts +66 -0
  246. package/src/utils/parseColor.ts +87 -0
  247. package/src/utils/smoothstep.ts +6 -0
  248. package/tsconfig.build.json +11 -0
  249. package/tsconfig.json +15 -0
  250. package/dist/alpha/generateAlphaScale.d.ts +0 -5
  251. package/dist/alpha/generateAlphaScale.js +0 -34
  252. package/dist/contrast/onSolid.d.ts +0 -6
  253. package/dist/contrast/onSolid.js +0 -28
  254. package/dist/contrast/solveText.d.ts +0 -2
  255. package/dist/contrast/solveText.js +0 -31
  256. package/dist/createTheme.d.ts +0 -38
  257. package/dist/createTheme.js +0 -148
  258. package/dist/data/radixSeeds.d.ts +0 -3
  259. package/dist/data/radixSeeds.js +0 -34
  260. package/dist/diagnostics/analyzeScale.d.ts +0 -2
  261. package/dist/diagnostics/analyzeScale.js +0 -7
  262. package/dist/diagnostics/analyzeTheme.d.ts +0 -2
  263. package/dist/diagnostics/analyzeTheme.js +0 -35
  264. package/dist/diagnostics/warnings.d.ts +0 -2
  265. package/dist/diagnostics/warnings.js +0 -20
  266. package/dist/engine/curves.d.ts +0 -9
  267. package/dist/engine/curves.js +0 -48
  268. package/dist/engine/oklch.d.ts +0 -8
  269. package/dist/engine/oklch.js +0 -40
  270. package/dist/engine/templates.d.ts +0 -14
  271. package/dist/engine/templates.js +0 -45
  272. package/dist/exporters/selectColorMode.d.ts +0 -2
  273. package/dist/exporters/selectColorMode.js +0 -19
  274. package/dist/exporters/toCssVars.d.ts +0 -13
  275. package/dist/exporters/toCssVars.js +0 -108
  276. package/dist/exporters/toJson.d.ts +0 -3
  277. package/dist/exporters/toJson.js +0 -25
  278. package/dist/exporters/toReactNative.d.ts +0 -54
  279. package/dist/exporters/toReactNative.js +0 -33
  280. package/dist/exporters/toTailwind.d.ts +0 -17
  281. package/dist/exporters/toTailwind.js +0 -111
  282. package/dist/exporters/toTs.d.ts +0 -3
  283. package/dist/exporters/toTs.js +0 -43
  284. package/dist/generateScale.d.ts +0 -48
  285. package/dist/generateScale.js +0 -274
  286. package/dist/overlays/generateOverlayScale.d.ts +0 -2
  287. package/dist/overlays/generateOverlayScale.js +0 -34
  288. package/dist/text/generateTextScale.d.ts +0 -8
  289. package/dist/text/generateTextScale.js +0 -18
  290. package/dist/text/resolveOnBgText.d.ts +0 -9
  291. package/dist/text/resolveOnBgText.js +0 -28
  292. package/dist/tokens/presetRadixLikeUi.d.ts +0 -5
  293. package/dist/tokens/presetRadixLikeUi.js +0 -55
  294. package/dist/types.d.ts +0 -69
  295. /package/dist/{types.js → cli/args.test.d.ts} +0 -0
@@ -1,8 +0,0 @@
1
- import type { ColorHex, ColorP3, OklchColor } from "../types.js";
2
- export declare function hexToOklch(hex: ColorHex): OklchColor;
3
- export declare function oklchToHex(oklch: OklchColor): ColorHex;
4
- export declare function inSrgbGamut(oklch: OklchColor): boolean;
5
- export declare function compressToSrgb(oklch: OklchColor): OklchColor;
6
- export declare function inP3Gamut(oklch: OklchColor): boolean;
7
- export declare function compressToP3(oklch: OklchColor): OklchColor;
8
- export declare function oklchToP3(oklch: OklchColor): ColorP3;
@@ -1,40 +0,0 @@
1
- import Color from "colorjs.io";
2
- export function hexToOklch(hex) {
3
- const color = new Color(hex).to("oklch");
4
- const [l, c, h] = color.coords;
5
- return { l: l ?? 0, c: c ?? 0, h: h ?? 0 };
6
- }
7
- export function oklchToHex(oklch) {
8
- const color = new Color("oklch", [oklch.l, oklch.c, oklch.h]);
9
- return color.to("srgb").toString({ format: "hex" });
10
- }
11
- export function inSrgbGamut(oklch) {
12
- const color = new Color("oklch", [oklch.l, oklch.c, oklch.h]);
13
- return color.inGamut("srgb");
14
- }
15
- export function compressToSrgb(oklch) {
16
- let current = { ...oklch };
17
- let iterations = 0;
18
- while (!inSrgbGamut(current) && current.c > 0 && iterations < 40) {
19
- current = { ...current, c: current.c * 0.95 };
20
- iterations += 1;
21
- }
22
- return current;
23
- }
24
- export function inP3Gamut(oklch) {
25
- const color = new Color("oklch", [oklch.l, oklch.c, oklch.h]);
26
- return color.inGamut("p3");
27
- }
28
- export function compressToP3(oklch) {
29
- let current = { ...oklch };
30
- let iterations = 0;
31
- while (!inP3Gamut(current) && current.c > 0 && iterations < 40) {
32
- current = { ...current, c: current.c * 0.95 };
33
- iterations += 1;
34
- }
35
- return current;
36
- }
37
- export function oklchToP3(oklch) {
38
- const color = new Color("oklch", [oklch.l, oklch.c, oklch.h]);
39
- return color.to("p3").toString({ format: "color" });
40
- }
@@ -1,14 +0,0 @@
1
- import type { OklchColor, Step, TemplateId } from "../types.js";
2
- export declare const templates: {
3
- light: {
4
- neutral: Record<Step, OklchColor>;
5
- warm: Record<Step, OklchColor>;
6
- cool: Record<Step, OklchColor>;
7
- };
8
- dark: {
9
- neutral: Record<Step, OklchColor>;
10
- warm: Record<Step, OklchColor>;
11
- cool: Record<Step, OklchColor>;
12
- };
13
- };
14
- export declare function selectTemplateId(oklch: OklchColor): TemplateId;
@@ -1,45 +0,0 @@
1
- const steps = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
2
- const lightnessLight = [0.99, 0.975, 0.95, 0.92, 0.89, 0.84, 0.77, 0.68, 0.58, 0.5, 0.4, 0.3];
3
- const lightnessDark = [0.12, 0.14, 0.18, 0.22, 0.26, 0.32, 0.4, 0.48, 0.58, 0.66, 0.76, 0.86];
4
- const chromaNeutral = [
5
- 0.01, 0.012, 0.016, 0.02, 0.024, 0.03, 0.04, 0.05, 0.055, 0.045, 0.035, 0.028,
6
- ];
7
- const chromaWarm = [0.02, 0.03, 0.05, 0.08, 0.12, 0.16, 0.18, 0.2, 0.22, 0.19, 0.12, 0.08];
8
- const chromaCool = [0.02, 0.03, 0.05, 0.075, 0.1, 0.14, 0.17, 0.19, 0.21, 0.18, 0.11, 0.08];
9
- const baseHue = {
10
- neutral: 250,
11
- warm: 40,
12
- cool: 220,
13
- };
14
- function buildTemplate(lightness, chroma, hue) {
15
- const output = {};
16
- for (let i = 0; i < steps.length; i += 1) {
17
- const step = steps[i];
18
- output[step] = {
19
- l: lightness[i],
20
- c: chroma[i],
21
- h: hue,
22
- };
23
- }
24
- return output;
25
- }
26
- export const templates = {
27
- light: {
28
- neutral: buildTemplate(lightnessLight, chromaNeutral, baseHue.neutral),
29
- warm: buildTemplate(lightnessLight, chromaWarm, baseHue.warm),
30
- cool: buildTemplate(lightnessLight, chromaCool, baseHue.cool),
31
- },
32
- dark: {
33
- neutral: buildTemplate(lightnessDark, chromaNeutral, baseHue.neutral),
34
- warm: buildTemplate(lightnessDark, chromaWarm, baseHue.warm),
35
- cool: buildTemplate(lightnessDark, chromaCool, baseHue.cool),
36
- },
37
- };
38
- export function selectTemplateId(oklch) {
39
- if (oklch.c < 0.05) {
40
- return "neutral";
41
- }
42
- const hue = ((oklch.h % 360) + 360) % 360;
43
- const isWarm = hue <= 60 || hue >= 330;
44
- return isWarm ? "warm" : "cool";
45
- }
@@ -1,2 +0,0 @@
1
- import type { Theme, ThemeColorMode } from "../types.js";
2
- export declare function selectThemeColorMode(theme: Theme, mode: "srgb" | "p3"): ThemeColorMode;
@@ -1,19 +0,0 @@
1
- export function selectThemeColorMode(theme, mode) {
2
- if (mode === "srgb") {
3
- return theme;
4
- }
5
- const scales = Object.fromEntries(Object.entries(theme.scales).map(([slot, scale]) => {
6
- if (!scale.p3) {
7
- return [slot, scale];
8
- }
9
- return [
10
- slot,
11
- {
12
- ...scale,
13
- light: scale.p3.light,
14
- dark: scale.p3.dark,
15
- },
16
- ];
17
- }));
18
- return { ...theme, scales };
19
- }
@@ -1,13 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- type CssVarsOptions = {
3
- prefix?: string;
4
- includeTokens?: boolean;
5
- includeScales?: boolean;
6
- includeAlpha?: boolean;
7
- includeOverlays?: boolean;
8
- includeP3?: boolean;
9
- lightSelector?: string;
10
- darkSelector?: string;
11
- };
12
- export declare function toCssVars(theme: Theme, options?: CssVarsOptions): string;
13
- export {};
@@ -1,108 +0,0 @@
1
- import Color from "colorjs.io";
2
- function tokenToCssVar(token, prefix) {
3
- const normalized = token.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
4
- const dashed = normalized.replace(/\./g, "-");
5
- return `--${prefix}-${dashed}`;
6
- }
7
- function scaleToCssVar(slot, step, prefix) {
8
- return `--${prefix}-scale-${slot}-${step}`;
9
- }
10
- function alphaToCssVar(slot, step, prefix) {
11
- return `--${prefix}-alpha-${slot}-${step}`;
12
- }
13
- function overlayToCssVar(color, step, prefix) {
14
- return `--${prefix}-overlay-${color}-${step}`;
15
- }
16
- function hexToP3(value) {
17
- return new Color(value).to("p3").toString({ format: "color" });
18
- }
19
- export function toCssVars(theme, options) {
20
- const prefix = options?.prefix ?? "pk";
21
- const includeTokens = options?.includeTokens ?? true;
22
- const includeScales = options?.includeScales ?? true;
23
- const includeAlpha = options?.includeAlpha ?? true;
24
- const includeOverlays = options?.includeOverlays ?? true;
25
- const includeP3 = options?.includeP3 ?? false;
26
- const lightSelector = options?.lightSelector ?? ":root";
27
- const darkSelector = options?.darkSelector ?? ".dark";
28
- const lines = [];
29
- const hasP3 = Object.values(theme.scales).some((scale) => scale.p3);
30
- function emitSelector(selector, mode) {
31
- lines.push(`${selector} {`);
32
- if (includeTokens) {
33
- for (const [token, value] of Object.entries(theme.tokens[mode])) {
34
- lines.push(` ${tokenToCssVar(token, prefix)}: ${value};`);
35
- }
36
- }
37
- if (includeScales) {
38
- for (const [slot, scale] of Object.entries(theme.scales)) {
39
- for (const [step, value] of Object.entries(scale[mode])) {
40
- lines.push(` ${scaleToCssVar(slot, Number(step), prefix)}: ${value};`);
41
- }
42
- }
43
- }
44
- if (includeAlpha && theme.alpha) {
45
- for (const [slot, scale] of Object.entries(theme.alpha)) {
46
- for (const [step, value] of Object.entries(scale[mode])) {
47
- lines.push(` ${alphaToCssVar(slot, Number(step), prefix)}: ${value};`);
48
- }
49
- }
50
- }
51
- if (includeOverlays) {
52
- for (const [step, value] of Object.entries(theme.overlay.black)) {
53
- lines.push(` ${overlayToCssVar("black", Number(step), prefix)}: ${value};`);
54
- }
55
- for (const [step, value] of Object.entries(theme.overlay.white)) {
56
- lines.push(` ${overlayToCssVar("white", Number(step), prefix)}: ${value};`);
57
- }
58
- }
59
- lines.push("}");
60
- }
61
- emitSelector(lightSelector, "light");
62
- lines.push("");
63
- emitSelector(darkSelector, "dark");
64
- if (includeP3 && hasP3) {
65
- lines.push("");
66
- lines.push("@supports (color: color(display-p3 1 1 1)) {");
67
- function emitP3Selector(selector, mode) {
68
- lines.push(` ${selector} {`);
69
- if (includeTokens) {
70
- for (const [token, value] of Object.entries(theme.tokens[mode])) {
71
- lines.push(` ${tokenToCssVar(token, prefix)}: ${hexToP3(value)};`);
72
- }
73
- }
74
- if (includeScales) {
75
- for (const [slot, scale] of Object.entries(theme.scales)) {
76
- const p3Scale = scale.p3?.[mode];
77
- if (!p3Scale) {
78
- continue;
79
- }
80
- for (const [step, value] of Object.entries(p3Scale)) {
81
- lines.push(` ${scaleToCssVar(slot, Number(step), prefix)}: ${value};`);
82
- }
83
- }
84
- }
85
- if (includeAlpha && theme.alpha) {
86
- for (const [slot, scale] of Object.entries(theme.alpha)) {
87
- for (const [step, value] of Object.entries(scale[mode])) {
88
- lines.push(` ${alphaToCssVar(slot, Number(step), prefix)}: ${hexToP3(value)};`);
89
- }
90
- }
91
- }
92
- if (includeOverlays) {
93
- for (const [step, value] of Object.entries(theme.overlay.black)) {
94
- lines.push(` ${overlayToCssVar("black", Number(step), prefix)}: ${hexToP3(value)};`);
95
- }
96
- for (const [step, value] of Object.entries(theme.overlay.white)) {
97
- lines.push(` ${overlayToCssVar("white", Number(step), prefix)}: ${hexToP3(value)};`);
98
- }
99
- }
100
- lines.push(" }");
101
- }
102
- emitP3Selector(lightSelector, "light");
103
- lines.push("");
104
- emitP3Selector(darkSelector, "dark");
105
- lines.push("}");
106
- }
107
- return lines.join("\n");
108
- }
@@ -1,3 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- export declare function toJson(theme: Theme): string;
3
- export declare function toJsonWithMode(theme: Theme, mode: "srgb" | "p3"): string;
@@ -1,25 +0,0 @@
1
- export function toJson(theme) {
2
- return JSON.stringify(theme, null, 2);
3
- }
4
- export function toJsonWithMode(theme, mode) {
5
- if (mode === "p3") {
6
- return JSON.stringify(toP3Theme(theme), null, 2);
7
- }
8
- return JSON.stringify(theme, null, 2);
9
- }
10
- function toP3Theme(theme) {
11
- const scales = Object.fromEntries(Object.entries(theme.scales).map(([slot, scale]) => {
12
- if (!scale.p3) {
13
- return [slot, scale];
14
- }
15
- return [
16
- slot,
17
- {
18
- ...scale,
19
- light: scale.p3.light,
20
- dark: scale.p3.dark,
21
- },
22
- ];
23
- }));
24
- return { ...theme, scales };
25
- }
@@ -1,54 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- type ReactNativeOptions = {
3
- includeTokens?: boolean;
4
- includeScales?: boolean;
5
- includeAlpha?: boolean;
6
- includeOverlays?: boolean;
7
- includeP3?: boolean;
8
- };
9
- type Mode = "light" | "dark";
10
- type ModeTokens<T extends Theme, O extends ReactNativeOptions, M extends Mode> = O extends {
11
- includeTokens: false;
12
- } ? Record<string, never> : T["tokens"][M];
13
- type ModeScales<T extends Theme, O extends ReactNativeOptions, M extends Mode> = O extends {
14
- includeScales: false;
15
- } ? Record<string, never> : {
16
- [K in keyof T["scales"]]: T["scales"][K][M];
17
- };
18
- type ThemeAlpha<T extends Theme> = T["alpha"] extends undefined ? undefined : T["alpha"];
19
- type ModeAlpha<T extends Theme, O extends ReactNativeOptions, M extends Mode> = O extends {
20
- includeAlpha: false;
21
- } ? undefined : ThemeAlpha<T> extends undefined ? undefined : ThemeAlpha<T> extends Record<string, {
22
- light: infer L;
23
- dark: infer D;
24
- }> ? M extends "light" ? Record<string, L> : Record<string, D> : undefined;
25
- type ModeOverlays<T extends Theme, O extends ReactNativeOptions> = O extends {
26
- includeOverlays: false;
27
- } ? undefined : T["overlay"];
28
- type ModeP3<T extends Theme, O extends ReactNativeOptions, M extends Mode> = O extends {
29
- includeP3: true;
30
- } ? Partial<{
31
- [K in keyof T["scales"]]: T["scales"][K] extends {
32
- p3?: {
33
- light: infer L;
34
- dark: infer D;
35
- };
36
- } ? M extends "light" ? L : D : never;
37
- }> : undefined;
38
- type ReactNativeTheme<T extends Theme, O extends ReactNativeOptions> = {
39
- overlay: ModeOverlays<T, O>;
40
- light: {
41
- tokens: ModeTokens<T, O, "light">;
42
- scales: ModeScales<T, O, "light">;
43
- alpha: ModeAlpha<T, O, "light">;
44
- p3: ModeP3<T, O, "light">;
45
- };
46
- dark: {
47
- tokens: ModeTokens<T, O, "dark">;
48
- scales: ModeScales<T, O, "dark">;
49
- alpha: ModeAlpha<T, O, "dark">;
50
- p3: ModeP3<T, O, "dark">;
51
- };
52
- };
53
- export declare function toReactNative<T extends Theme, O extends ReactNativeOptions = ReactNativeOptions>(theme: T, options?: O): ReactNativeTheme<T, O>;
54
- export {};
@@ -1,33 +0,0 @@
1
- export function toReactNative(theme, options) {
2
- const includeTokens = options?.includeTokens ?? true;
3
- const includeScales = options?.includeScales ?? true;
4
- const includeAlpha = options?.includeAlpha ?? true;
5
- const includeOverlays = options?.includeOverlays ?? true;
6
- const includeP3 = options?.includeP3 ?? false;
7
- function buildMode(mode) {
8
- const scales = includeScales
9
- ? Object.fromEntries(Object.entries(theme.scales).map(([slot, scale]) => [slot, scale[mode]]))
10
- : {};
11
- const p3 = includeP3
12
- ? Object.fromEntries(Object.entries(theme.scales)
13
- .filter(([, scale]) => scale.p3?.[mode])
14
- .map(([slot, scale]) => [slot, scale.p3?.[mode]]))
15
- : undefined;
16
- const alpha = includeAlpha
17
- ? (theme.alpha
18
- ? Object.fromEntries(Object.entries(theme.alpha).map(([slot, scale]) => [slot, scale[mode]]))
19
- : undefined)
20
- : undefined;
21
- return {
22
- tokens: (includeTokens ? theme.tokens[mode] : {}),
23
- scales,
24
- alpha,
25
- p3,
26
- };
27
- }
28
- return {
29
- overlay: (includeOverlays ? theme.overlay : undefined),
30
- light: buildMode("light"),
31
- dark: buildMode("dark"),
32
- };
33
- }
@@ -1,17 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- type TailwindOptions = {
3
- mode?: "light" | "dark" | "both";
4
- includeTokens?: boolean;
5
- includeScales?: boolean;
6
- includeAlpha?: boolean;
7
- includeOverlays?: boolean;
8
- includeP3?: boolean;
9
- };
10
- export declare function toTailwind(theme: Theme, options?: TailwindOptions): {
11
- theme: {
12
- extend: {
13
- colors: Record<string, unknown>;
14
- };
15
- };
16
- };
17
- export {};
@@ -1,111 +0,0 @@
1
- function setNested(target, path, value) {
2
- let cursor = target;
3
- for (let i = 0; i < path.length - 1; i += 1) {
4
- const key = path[i];
5
- if (!cursor[key] || typeof cursor[key] !== "object") {
6
- cursor[key] = {};
7
- }
8
- cursor = cursor[key];
9
- }
10
- cursor[path[path.length - 1]] = value;
11
- }
12
- function tokensToNested(tokens) {
13
- const output = {};
14
- for (const [token, value] of Object.entries(tokens)) {
15
- setNested(output, token.split("."), value);
16
- }
17
- return output;
18
- }
19
- function scalesToNested(scales, mode, useP3) {
20
- const output = {};
21
- for (const [slot, scale] of Object.entries(scales)) {
22
- const source = useP3 ? scale.p3?.[mode] : scale[mode];
23
- if (!source) {
24
- continue;
25
- }
26
- const stepMap = {};
27
- for (const [step, value] of Object.entries(source)) {
28
- stepMap[String(step)] = value;
29
- }
30
- output[slot] = stepMap;
31
- }
32
- return output;
33
- }
34
- function alphaToNested(alpha, mode) {
35
- if (!alpha) {
36
- return undefined;
37
- }
38
- const output = {};
39
- for (const [slot, scale] of Object.entries(alpha)) {
40
- const stepMap = {};
41
- for (const [step, value] of Object.entries(scale[mode])) {
42
- stepMap[String(step)] = value;
43
- }
44
- output[slot] = stepMap;
45
- }
46
- return output;
47
- }
48
- function overlaysToNested(overlays) {
49
- const output = {
50
- black: {},
51
- white: {},
52
- };
53
- for (const [step, value] of Object.entries(overlays.black)) {
54
- output.black[String(step)] = value;
55
- }
56
- for (const [step, value] of Object.entries(overlays.white)) {
57
- output.white[String(step)] = value;
58
- }
59
- return output;
60
- }
61
- export function toTailwind(theme, options) {
62
- const mode = options?.mode ?? "both";
63
- const includeTokens = options?.includeTokens ?? true;
64
- const includeScales = options?.includeScales ?? false;
65
- const includeAlpha = options?.includeAlpha ?? false;
66
- const includeOverlays = options?.includeOverlays ?? false;
67
- const includeP3 = options?.includeP3 ?? false;
68
- function buildModeTokens(modeKey, useP3) {
69
- const colors = {};
70
- if (includeTokens) {
71
- colors.tokens = tokensToNested(theme.tokens[modeKey]);
72
- }
73
- if (includeScales) {
74
- colors.scale = scalesToNested(theme.scales, modeKey, useP3);
75
- }
76
- if (includeAlpha && theme.alpha) {
77
- colors.alpha = alphaToNested(theme.alpha, modeKey);
78
- }
79
- if (includeOverlays) {
80
- colors.overlay = overlaysToNested(theme.overlay);
81
- }
82
- return colors;
83
- }
84
- const colors = {};
85
- if (mode === "light" || mode === "both") {
86
- colors.light = buildModeTokens("light");
87
- }
88
- if (mode === "dark" || mode === "both") {
89
- colors.dark = buildModeTokens("dark");
90
- }
91
- if (includeP3) {
92
- const hasP3 = Object.values(theme.scales).some((scale) => scale.p3);
93
- if (hasP3) {
94
- const p3 = {};
95
- if (mode === "light" || mode === "both") {
96
- p3.light = buildModeTokens("light", true);
97
- }
98
- if (mode === "dark" || mode === "both") {
99
- p3.dark = buildModeTokens("dark", true);
100
- }
101
- colors.p3 = p3;
102
- }
103
- }
104
- return {
105
- theme: {
106
- extend: {
107
- colors,
108
- },
109
- },
110
- };
111
- }
@@ -1,3 +0,0 @@
1
- import type { Theme } from "../types.js";
2
- export declare function toTs(theme: Theme): string;
3
- export declare function toTsWithMode(theme: Theme, mode: "srgb" | "p3"): string;
@@ -1,43 +0,0 @@
1
- export function toTs(theme) {
2
- const serialized = JSON.stringify(theme, null, 2);
3
- return `export const theme = ${serialized} as const;\n${typeExports()}`;
4
- }
5
- export function toTsWithMode(theme, mode) {
6
- if (mode === "p3") {
7
- const serialized = JSON.stringify(toP3Theme(theme), null, 2);
8
- return `export const theme = ${serialized} as const;\n${typeExports()}`;
9
- }
10
- const serialized = JSON.stringify(theme, null, 2);
11
- return `export const theme = ${serialized} as const;\n${typeExports()}`;
12
- }
13
- function toP3Theme(theme) {
14
- const scales = Object.fromEntries(Object.entries(theme.scales).map(([slot, scale]) => {
15
- if (!scale.p3) {
16
- return [slot, scale];
17
- }
18
- return [
19
- slot,
20
- {
21
- ...scale,
22
- light: scale.p3.light,
23
- dark: scale.p3.dark,
24
- },
25
- ];
26
- }));
27
- return { ...theme, scales };
28
- }
29
- function typeExports() {
30
- return [
31
- "export type Theme = typeof theme;",
32
- 'export type ThemeScaleName = keyof Theme["scales"];',
33
- 'export type ThemeTokenName = keyof Theme["tokens"]["light"];',
34
- 'export type ThemeTokenMap = Theme["tokens"]["light"];',
35
- 'export type ThemeOverlay = Theme["overlay"];',
36
- 'export type ThemeMode = keyof Theme["tokens"];',
37
- 'export type ThemeScaleStep = keyof Theme["scales"][ThemeScaleName]["light"];',
38
- 'export type ThemeTokenHex = Theme["tokens"][ThemeMode][ThemeTokenName];',
39
- 'export type ThemeScaleHex = Theme["scales"][ThemeScaleName][ThemeMode][ThemeScaleStep];',
40
- 'export type ThemeAlphaHex = Theme["alpha"] extends undefined ? never : Theme["alpha"][ThemeScaleName][ThemeMode][ThemeScaleStep];',
41
- "",
42
- ].join("\n");
43
- }
@@ -1,48 +0,0 @@
1
- import { type CurveConfig } from "./engine/curves.js";
2
- import type { ColorSource, Scale, Step, TemplateId } from "./types.js";
3
- export type AnchorStepOption = Step | "auto" | {
4
- light?: Step | "auto";
5
- dark?: Step | "auto";
6
- };
7
- export type AutoAnchorModeOptions = {
8
- candidateSteps?: Step[];
9
- backgroundStep?: Step;
10
- backgroundSteps?: Step[];
11
- solidStep?: Step;
12
- textStep?: Step;
13
- targetContrast?: number;
14
- minBackgroundL?: number;
15
- maxBackgroundL?: number;
16
- minTextL?: number;
17
- maxTextL?: number;
18
- };
19
- export type AutoAnchorOptions = {
20
- candidateSteps?: Step[];
21
- light?: AutoAnchorModeOptions;
22
- dark?: AutoAnchorModeOptions;
23
- };
24
- export type SeedNormalizeRange = {
25
- minL?: number;
26
- maxL?: number;
27
- minC?: number;
28
- maxC?: number;
29
- };
30
- export type SeedNormalizeOptions = {
31
- enabled?: boolean;
32
- light?: SeedNormalizeRange;
33
- dark?: SeedNormalizeRange;
34
- };
35
- export type GenerateScaleOptions = {
36
- source: ColorSource;
37
- mode?: "light" | "dark" | "both";
38
- anchorStep?: AnchorStepOption;
39
- autoAnchor?: AutoAnchorOptions;
40
- seedNormalize?: SeedNormalizeOptions;
41
- template?: "auto" | TemplateId;
42
- curves?: CurveConfig;
43
- gamut?: {
44
- strategy: "compress" | "clip";
45
- };
46
- p3?: boolean;
47
- };
48
- export declare function generateScale(options: GenerateScaleOptions): Scale;