@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
@@ -0,0 +1,305 @@
1
+ # Palette Kit — SPEC v0.3
2
+
3
+ > Especificação formal da versão v0.3 do Palette Kit.
4
+ > Documento orientado à implementação, com foco absoluto em Developer Experience (DX), contratos explícitos e evolução sustentável do produto.
5
+
6
+ ---
7
+
8
+ ## 1. Visão geral
9
+
10
+ A v0.3 transforma o Palette Kit em uma biblioteca **runtime-first**, com **DX elevada por padrão**, contratos públicos claros e **tooling opcional** (serializers, exporters, CLI e codegen).
11
+
12
+ A biblioteca passa a atender bem:
13
+
14
+ - desenvolvedores comuns (uso direto no runtime)
15
+ - times grandes (token registry, exporters, codegen)
16
+ - ambientes web e mobile (web / React Native)
17
+
18
+ ---
19
+
20
+ ## 2. Produto
21
+
22
+ - **Runtime-first** é o caminho oficial
23
+ - CLI, exporters e codegen são **helpers**, não dependências obrigatórias
24
+ - A lib deve ser **útil imediatamente após instalar**
25
+
26
+ ---
27
+
28
+ ## 3. Resolver (core)
29
+
30
+ ### 3.1 Contrato
31
+
32
+ - `createTheme()` permanece como entrypoint
33
+ - `theme.resolve()` e `theme.onSolid()` retornam **BaseResolvedColor**
34
+ - `BaseResolvedColor`:
35
+ - **não é exportado como type**
36
+ - **tem shape estável garantido em toda a linha v0.x**
37
+ - Strings de cor **não** são retornadas automaticamente
38
+
39
+ ### 3.2 Justificativa
40
+
41
+ - Mantém o core agnóstico de output
42
+ - Evita acoplamento com CSS, React Native ou JSON
43
+ - Facilita evolução futura (novos formatos, novos targets)
44
+
45
+ ---
46
+
47
+ ## 4. Serializer público (camadas de DX)
48
+
49
+ ### 4.1 Objetivo
50
+
51
+ Fornecer uma **ponte oficial e tipada** entre o resolver e o mundo real (CSS, RN, JSON), sem esconder decisões importantes do desenvolvedor.
52
+
53
+ ### 4.2 APIs obrigatórias
54
+
55
+ ```ts
56
+ serializeColor(oklch, options?) -> ResolvedColor
57
+ serializeResolved(baseResolved, options?) -> ResolvedColor
58
+ theme.serialize(query, options?) -> ResolvedColor
59
+ ```
60
+
61
+ ### 4.3 Requisitos
62
+
63
+ - Suporte a:
64
+ - `oklch()`
65
+ - `hex`, `rgb()`, `rgba()`
66
+ - `color(display-p3 ...)`
67
+ - Opções:
68
+ - `preferSpace`
69
+ - `includeSpaces`
70
+ - `precision`
71
+ - `strict`
72
+ - Estratégia de gamut mapping default:
73
+ - `preferP3ThenCompress`
74
+ - `ResolvedColor`:
75
+ - contém strings serializadas
76
+ - pode incluir múltiplos espaços
77
+ - pode incluir metadados opcionais
78
+ - **JSDoc obrigatório**, explicando:
79
+ - trade-offs entre espaços de cor
80
+ - implicações de gamut mapping
81
+ - impacto de precisão e strict mode
82
+
83
+ ---
84
+
85
+ ## 5. Exporters públicos (CSS / JSON)
86
+
87
+ ### 5.1 Objetivo
88
+
89
+ Gerar artefatos determinísticos para projetos que desejam tokens persistentes, sem obrigar esse modelo no runtime.
90
+
91
+ ### 5.2 APIs públicas
92
+
93
+ ```ts
94
+ exportThemeCss(theme, tokenMap, options)
95
+ exportThemeJson(theme, tokenMap, options)
96
+ ```
97
+
98
+ ### 5.3 Regras
99
+
100
+ - Exporters **não são obrigatórios** para uso do runtime
101
+ - Outputs devem ser:
102
+ - determinísticos
103
+ - ordenados
104
+ - previsíveis
105
+ - CSS:
106
+ - CSS variables com fallback
107
+ - override progressivo via `@supports`
108
+ - JSON:
109
+ - estrutura estável
110
+ - separação explícita por contexto (`light` / `dark`)
111
+
112
+ ---
113
+
114
+ ## 6. Token Registry (caminho deluxe)
115
+
116
+ ### 6.1 Modelo
117
+
118
+ Tokens são definidos como **objetos ricos**, não apenas nomes:
119
+
120
+ ```ts
121
+ {
122
+ name: "bg.app",
123
+ description: "Application background",
124
+ query: { role, usage, surface },
125
+ category: "background",
126
+ states?: {
127
+ hover?: boolean
128
+ active?: boolean
129
+ }
130
+ }
131
+ ```
132
+
133
+ ### 6.2 Regras
134
+
135
+ - Registry é **declarativo**
136
+ - Tokens:
137
+ - não carregam valores de cor
138
+ - sempre resolvem via `theme.resolve`
139
+ - Registry é consumido por:
140
+ - exporters
141
+ - CLI
142
+ - codegen
143
+
144
+ ---
145
+
146
+ ## 7. Estados — modelo híbrido
147
+
148
+ - Token registry define **tokens base**
149
+ - Estados (`hover`, `active`, etc.) são **operadores**
150
+ - CLI e exporters:
151
+ - podem gerar tokens derivados
152
+ - nunca duplicam lógica de resolução
153
+
154
+ ---
155
+
156
+ ## 8. Presets de token map (obrigatórios)
157
+
158
+ ### Presets oficiais
159
+
160
+ 1. `minimal-ui`
161
+ 2. `radixLike-ui`
162
+ 3. `modern-ui`
163
+
164
+ Cada preset define:
165
+
166
+ - tokens base
167
+ - categorias
168
+ - estados suportados
169
+ - documentação embutida (descrições e intenção semântica)
170
+
171
+ ---
172
+
173
+ ## 9. CLI tooling
174
+
175
+ ### 9.1 `palette-kit init`
176
+
177
+ - Cria `palette.config.ts`
178
+ - Arquivo totalmente tipado
179
+ - Com JSDoc explicativo
180
+ - Sem comportamento mágico
181
+ - Não gera tokens automaticamente
182
+
183
+ ### 9.2 `palette-kit build`
184
+
185
+ - Gera artefatos em `dist/palette/`:
186
+ - `tokens.css`
187
+ - `tokens.json`
188
+ - `tokens.ts`
189
+ - `tokens.d.ts`
190
+ - Pode gerar:
191
+ - `report.md` (opcional)
192
+ - Flag `--watch` é opcional e **não MVP**
193
+
194
+ ---
195
+
196
+ ## 10. Codegen de types (DX máximo)
197
+
198
+ ### 10.1 Objetivos
199
+
200
+ - Autocomplete completo
201
+ - Navegação por objeto
202
+ - Zero custo em runtime
203
+
204
+ ### 10.2 Outputs
205
+
206
+ - Objeto navegável:
207
+
208
+ ```ts
209
+ tokens.bg.app
210
+ tokens.text.primary
211
+ ```
212
+
213
+ - Unions:
214
+
215
+ ```ts
216
+ type TokenName = ...
217
+ type ColorRole = ...
218
+ ```
219
+
220
+ ### 10.3 Regras
221
+
222
+ - JSDoc por token
223
+ - Compatível com editores comuns
224
+ - Core runtime continua aceitando `string`
225
+
226
+ ---
227
+
228
+ ## 11. Autocomplete sem amarrar o core
229
+
230
+ - Runtime:
231
+ - aceita `string`
232
+ - Tooling:
233
+ - gera types específicos por projeto
234
+ - APIs automaticamente se beneficiam desses tipos
235
+
236
+ ---
237
+
238
+ ## 12. `theme.color(role, options)` com inferência forte
239
+
240
+ ### Comportamento
241
+
242
+ - Inferir automaticamente:
243
+ - `usage`
244
+ - `surface`
245
+ - `variant`
246
+ - Inferência baseada no prefixo do role
247
+
248
+ ### Strict mode
249
+
250
+ - `strict: true`
251
+ - erro claro, didático e acionável
252
+ - `strict: false`
253
+ - fallback seguro
254
+ - warning explícito
255
+
256
+ ---
257
+
258
+ ## 13. Ergonomia adicional
259
+
260
+ ### APIs
261
+
262
+ - `resolveMany(queries[])`
263
+ - `withContext("light" | "dark")` retorna um tema bound
264
+
265
+ ### Helpers
266
+
267
+ - `theme.colorCss(...)`
268
+ - `theme.onSolidCss(...)`
269
+
270
+ ---
271
+
272
+ ## 14. Packaging
273
+
274
+ - Um único pacote npm
275
+ - Uso de **subpath exports**:
276
+
277
+ ```json
278
+ {
279
+ "exports": {
280
+ ".": "./dist/index.js",
281
+ "./serialize": "./dist/serialize.js",
282
+ "./export": "./dist/export.js",
283
+ "./cli": "./dist/cli.js"
284
+ }
285
+ }
286
+ ```
287
+
288
+ ---
289
+
290
+ ## 15. Princípios de DX
291
+
292
+ - Runtime-first por default
293
+ - Contratos explícitos e previsíveis
294
+ - Zero comportamento oculto
295
+ - JSDoc tratado como parte da API
296
+ - Determinismo acima de “conveniência mágica”
297
+
298
+ ---
299
+
300
+ ## 16. Critérios de aceite
301
+
302
+ - Build passa
303
+ - Nenhum import circular
304
+ - API pública corresponde integralmente à spec
305
+ - DX validável apenas via autocomplete + hover docs
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import { CliUsageError, parseArgs } from "./args.js";
4
+
5
+ describe("cli args", () => {
6
+ it("parses init command", () => {
7
+ const parsed = parseArgs(["init"]);
8
+ expect(parsed.command).toBe("init");
9
+ });
10
+
11
+ it("parses build command with flags", () => {
12
+ const parsed = parseArgs(["build", "--config", "custom.ts", "--outDir", "out", "--report"]);
13
+ expect(parsed.command).toBe("build");
14
+ expect(parsed.flags.config).toBe("custom.ts");
15
+ expect(parsed.flags.outDir).toBe("out");
16
+ expect(parsed.flags.report).toBe(true);
17
+ });
18
+
19
+ it("recognizes help and version flags", () => {
20
+ expect(parseArgs(["--help"]).help).toBe(true);
21
+ expect(parseArgs(["--version"]).version).toBe(true);
22
+ });
23
+
24
+ it("throws on unknown arguments", () => {
25
+ expect(() => parseArgs(["build", "wat"])).toThrow(CliUsageError);
26
+ });
27
+ });
28
+
@@ -0,0 +1,66 @@
1
+ export class CliUsageError extends Error {
2
+ override name = "CliUsageError";
3
+ }
4
+
5
+ export const HELP_TEXT = `palette-kit <command>
6
+
7
+ Commands:
8
+ palette-kit init [--force] [--path <dir>]
9
+ palette-kit build [--config <path>] [--outDir <dir>] [--report]
10
+
11
+ Options:
12
+ -h, --help Show help
13
+ -v, --version Show version
14
+ `;
15
+
16
+ export type ParsedArgs = {
17
+ command?: string;
18
+ help: boolean;
19
+ version: boolean;
20
+ flags: Record<string, string | boolean>;
21
+ };
22
+
23
+ export const COMMANDS = ["init", "build"] as const;
24
+
25
+ export const parseArgs = (argv: string[]): ParsedArgs => {
26
+ const first = argv[0];
27
+ const command = first && !first.startsWith("-") ? first : undefined;
28
+ const rest = command ? argv.slice(1) : argv;
29
+ const flags: Record<string, string | boolean> = {};
30
+
31
+ let i = 0;
32
+ while (i < rest.length) {
33
+ const value = rest[i];
34
+ if (value === undefined) break;
35
+ if (value === "-h" || value === "--help") {
36
+ flags.help = true;
37
+ i += 1;
38
+ continue;
39
+ }
40
+ if (value === "-v" || value === "--version") {
41
+ flags.version = true;
42
+ i += 1;
43
+ continue;
44
+ }
45
+ if (value.startsWith("--")) {
46
+ const key = value.slice(2);
47
+ const next = rest[i + 1];
48
+ if (next && !next.startsWith("--")) {
49
+ flags[key] = next;
50
+ i += 2;
51
+ } else {
52
+ flags[key] = true;
53
+ i += 1;
54
+ }
55
+ continue;
56
+ }
57
+ throw new CliUsageError(`Unknown argument: ${value}`);
58
+ }
59
+
60
+ return {
61
+ command,
62
+ help: Boolean(flags.help),
63
+ version: Boolean(flags.version),
64
+ flags,
65
+ };
66
+ };
@@ -0,0 +1,87 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`codegen tokens > generates navigable tokens.ts and tokens.d.ts 1`] = `
4
+ "/* This file is generated by palette-kit build (Phase 7). */
5
+
6
+ export const tokens = {
7
+ bg: {
8
+ /**
9
+ * App background.
10
+ * @token bg.app
11
+ * @category bg
12
+ */
13
+ app: "bg.app",
14
+ },
15
+ border: {
16
+ /**
17
+ * Default border color.
18
+ * @token border.default
19
+ * @category border
20
+ */
21
+ "default": "border.default",
22
+ },
23
+ text: {
24
+ /**
25
+ * Primary text on standard surfaces.
26
+ * @token text.primary
27
+ * @category text
28
+ * @states hover
29
+ */
30
+ primary: "text.primary",
31
+ },
32
+ } as const;
33
+
34
+ export const tokenNames = [
35
+ "bg.app",
36
+ "border.default",
37
+ "text.primary"
38
+ ] as const;
39
+
40
+ export type TokenName = (typeof tokenNames)[number];
41
+
42
+ export type ColorRole = TokenName;
43
+ "
44
+ `;
45
+
46
+ exports[`codegen tokens > generates navigable tokens.ts and tokens.d.ts 2`] = `
47
+ "/* This file is generated by palette-kit build (Phase 7). */
48
+
49
+ export declare const tokens: {
50
+ bg: {
51
+ /**
52
+ * App background.
53
+ * @token bg.app
54
+ * @category bg
55
+ */
56
+ app: "bg.app";
57
+ };
58
+ border: {
59
+ /**
60
+ * Default border color.
61
+ * @token border.default
62
+ * @category border
63
+ */
64
+ "default": "border.default";
65
+ };
66
+ text: {
67
+ /**
68
+ * Primary text on standard surfaces.
69
+ * @token text.primary
70
+ * @category text
71
+ * @states hover
72
+ */
73
+ primary: "text.primary";
74
+ };
75
+ };
76
+
77
+ export declare const tokenNames: readonly [
78
+ "bg.app",
79
+ "border.default",
80
+ "text.primary"
81
+ ];
82
+
83
+ export type TokenName = (typeof tokenNames)[number];
84
+
85
+ export type ColorRole = TokenName;
86
+ "
87
+ `;
@@ -0,0 +1,61 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import type { TokenRegistry } from "../../types/index.js";
4
+ import { generateTokenArtifacts } from "./tokens.js";
5
+
6
+ describe("codegen tokens", () => {
7
+ const registry: TokenRegistry = {
8
+ tokens: {
9
+ "bg.app": {
10
+ name: "bg.app",
11
+ description: "App background.",
12
+ category: "bg",
13
+ query: { role: "bg.app", usage: "bg", surface: "app" },
14
+ },
15
+ "text.primary": {
16
+ name: "text.primary",
17
+ description: "Primary text on standard surfaces.",
18
+ category: "text",
19
+ query: { role: "text.primary", usage: "text", surface: "surface" },
20
+ states: { hover: true },
21
+ },
22
+ "border.default": {
23
+ name: "border.default",
24
+ description: "Default border color.",
25
+ category: "border",
26
+ query: { role: "border.default", usage: "border", surface: "surface" },
27
+ },
28
+ },
29
+ };
30
+
31
+ it("generates navigable tokens.ts and tokens.d.ts", () => {
32
+ const { tokensTs, tokensDts } = generateTokenArtifacts(registry);
33
+
34
+ expect(tokensTs).toContain('export const tokens = {');
35
+ expect(tokensTs).toContain('bg: {');
36
+ expect(tokensTs).toContain('app: "bg.app"');
37
+ expect(tokensTs).toContain('text: {');
38
+ expect(tokensTs).toContain('primary: "text.primary"');
39
+
40
+ expect(tokensTs).toMatchSnapshot();
41
+ expect(tokensDts).toMatchSnapshot();
42
+ });
43
+
44
+ it("is deterministic regardless of registry object order", () => {
45
+ const shuffled: TokenRegistry = {
46
+ tokens: {
47
+ "text.primary": registry.tokens["text.primary"],
48
+ "bg.app": registry.tokens["bg.app"],
49
+ "border.default": registry.tokens["border.default"],
50
+ },
51
+ };
52
+
53
+ const a = generateTokenArtifacts(registry);
54
+ const b = generateTokenArtifacts(shuffled);
55
+
56
+ expect(b.tokenNames).toEqual(a.tokenNames);
57
+ expect(b.tokensTs).toBe(a.tokensTs);
58
+ expect(b.tokensDts).toBe(a.tokensDts);
59
+ });
60
+ });
61
+