@clhaas/palette-kit 0.1.7 → 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/.codex/skills/color-pipeline-implementer/SKILL.md +23 -0
- package/.codex/skills/commit-message-crafter/SKILL.md +63 -0
- package/.codex/skills/commit-message-crafter/references/benchmarks.md +20 -0
- package/.codex/skills/contrast-solver-helper/SKILL.md +20 -0
- package/.codex/skills/exporters-builder/SKILL.md +20 -0
- package/.codex/skills/markdownlint-writer/SKILL.md +32 -0
- package/.codex/skills/phase-implementation-runbook/SKILL.md +92 -0
- package/.codex/skills/type-contract-auditor/SKILL.md +21 -0
- package/.github/skills/review-guide/SKILL.md +23 -0
- package/.github/skills/review-guide/references/review-guide-v0.3.md +629 -0
- package/.markdownlint.json +4 -0
- package/AGENTS.md +16 -0
- package/CHANGELOG.md +34 -0
- package/README.md +79 -169
- package/biome.json +43 -0
- package/dist/cli/args.d.ts +12 -0
- package/dist/cli/args.js +56 -0
- package/dist/cli/args.test.js +22 -0
- package/dist/cli/codegen/__snapshots__/tokens.test.js.snap +87 -0
- package/dist/cli/codegen/tokens.d.ts +12 -0
- package/dist/cli/codegen/tokens.js +139 -0
- package/dist/cli/codegen/tokens.test.d.ts +1 -0
- package/dist/cli/codegen/tokens.test.js +51 -0
- package/dist/cli/config.d.ts +40 -0
- package/dist/cli/config.js +34 -0
- package/dist/cli/validate.d.ts +2 -0
- package/dist/cli/validate.js +33 -0
- package/dist/cli/validate.test.d.ts +1 -0
- package/dist/cli/validate.test.js +40 -0
- package/dist/cli.js +138 -140
- package/dist/contrast/apca.d.ts +2 -2
- package/dist/contrast/apca.js +14 -4
- package/dist/contrast/apca.test.d.ts +1 -0
- package/dist/contrast/apca.test.js +16 -0
- package/dist/contrast/index.d.ts +4 -0
- package/dist/contrast/index.js +4 -0
- package/dist/contrast/scoring.d.ts +4 -0
- package/dist/contrast/scoring.js +31 -0
- package/dist/contrast/scoring.test.d.ts +1 -0
- package/dist/contrast/scoring.test.js +148 -0
- package/dist/contrast/solver.d.ts +13 -0
- package/dist/contrast/solver.js +170 -0
- package/dist/contrast/solver.test.d.ts +1 -0
- package/dist/contrast/solver.test.js +75 -0
- package/dist/contrast/types.d.ts +17 -0
- package/dist/contrast/types.js +1 -0
- package/dist/contrast/utils.d.ts +4 -0
- package/dist/contrast/utils.js +18 -0
- package/dist/contrast/wcag2.d.ts +3 -0
- package/dist/contrast/wcag2.js +19 -0
- package/dist/contrast/wcag2.test.d.ts +1 -0
- package/dist/contrast/wcag2.test.js +17 -0
- package/dist/core/createTheme.d.ts +35 -0
- package/dist/core/createTheme.js +24 -0
- package/dist/core/dx-helpers.test.d.ts +1 -0
- package/dist/core/dx-helpers.test.js +61 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/core/onSolid.test.d.ts +1 -0
- package/dist/core/onSolid.test.js +118 -0
- package/dist/core/qa.v1.test.d.ts +1 -0
- package/dist/core/qa.v1.test.js +112 -0
- package/dist/core/resolve.d.ts +3 -0
- package/dist/core/resolve.js +8 -0
- package/dist/core/resolve.test.d.ts +1 -0
- package/dist/core/resolve.test.js +89 -0
- package/dist/core/resolveMany.d.ts +8 -0
- package/dist/core/resolveMany.js +17 -0
- package/dist/core/tokenRegistry.d.ts +23 -0
- package/dist/core/tokenRegistry.js +83 -0
- package/dist/core/tokenRegistry.test.d.ts +1 -0
- package/dist/core/tokenRegistry.test.js +133 -0
- package/dist/engine/applyOperators.d.ts +3 -0
- package/dist/engine/applyOperators.js +23 -0
- package/dist/engine/context.d.ts +4 -0
- package/dist/engine/context.js +1 -0
- package/dist/engine/gamut.d.ts +13 -0
- package/dist/engine/gamut.js +101 -0
- package/dist/engine/gamut.test.d.ts +1 -0
- package/dist/engine/gamut.test.js +23 -0
- package/dist/engine/generateScale.d.ts +15 -0
- package/dist/engine/generateScale.js +29 -0
- package/dist/engine/generateScale.test.d.ts +1 -0
- package/dist/engine/generateScale.test.js +32 -0
- package/dist/engine/index.d.ts +8 -0
- package/dist/engine/index.js +4 -0
- package/dist/engine/normalize.d.ts +43 -0
- package/dist/engine/normalize.js +403 -0
- package/dist/engine/normalize.test.d.ts +1 -0
- package/dist/engine/normalize.test.js +136 -0
- package/dist/engine/onSolid.d.ts +3 -0
- package/dist/engine/onSolid.js +110 -0
- package/dist/engine/resolveBaseColor.d.ts +25 -0
- package/dist/engine/resolveBaseColor.js +127 -0
- package/dist/engine/resolveBaseColor.test.d.ts +1 -0
- package/dist/engine/resolveBaseColor.test.js +97 -0
- package/dist/export/__snapshots__/exportTheme.test.js.snap +74 -0
- package/dist/export/exportTheme.d.ts +47 -0
- package/dist/export/exportTheme.js +170 -0
- package/dist/export/exportTheme.test.d.ts +1 -0
- package/dist/export/exportTheme.test.js +118 -0
- package/dist/export/index.d.ts +1 -0
- package/dist/export/index.js +1 -0
- package/dist/export/serializeColor.d.ts +1 -0
- package/dist/export/serializeColor.js +1 -0
- package/dist/export/serializeColor.test.d.ts +1 -0
- package/dist/export/serializeColor.test.js +54 -0
- package/dist/export.d.ts +1 -0
- package/dist/export.js +1 -0
- package/dist/index.d.ts +3 -20
- package/dist/index.js +2 -17
- package/dist/operators/emphasis.d.ts +3 -0
- package/dist/operators/emphasis.js +113 -0
- package/dist/operators/emphasis.test.d.ts +1 -0
- package/dist/operators/emphasis.test.js +69 -0
- package/dist/operators/index.d.ts +3 -0
- package/dist/operators/index.js +2 -0
- package/dist/operators/state.d.ts +3 -0
- package/dist/operators/state.js +102 -0
- package/dist/operators/state.test.d.ts +1 -0
- package/dist/operators/state.test.js +48 -0
- package/dist/operators/types.d.ts +13 -0
- package/dist/operators/types.js +1 -0
- package/dist/operators/utils.d.ts +16 -0
- package/dist/operators/utils.js +23 -0
- package/dist/presets/curves.d.ts +28 -0
- package/dist/presets/curves.js +145 -0
- package/dist/presets/index.d.ts +2 -0
- package/dist/presets/index.js +1 -0
- package/dist/presets/tokens/index.d.ts +3 -0
- package/dist/presets/tokens/index.js +3 -0
- package/dist/presets/tokens/minimal-ui.d.ts +6 -0
- package/dist/presets/tokens/minimal-ui.js +53 -0
- package/dist/presets/tokens/modern-ui.d.ts +5 -0
- package/dist/presets/tokens/modern-ui.js +83 -0
- package/dist/presets/tokens/presets.test.d.ts +1 -0
- package/dist/presets/tokens/presets.test.js +31 -0
- package/dist/presets/tokens/radixLike-ui.d.ts +6 -0
- package/dist/presets/tokens/radixLike-ui.js +77 -0
- package/dist/serialize/index.d.ts +1 -0
- package/dist/serialize/index.js +1 -0
- package/dist/serialize/normalizeOutput.d.ts +6 -0
- package/dist/serialize/normalizeOutput.js +45 -0
- package/dist/serialize/serializeColor.d.ts +21 -0
- package/dist/serialize/serializeColor.js +178 -0
- package/dist/serialize/serializeResolved.test.d.ts +1 -0
- package/dist/serialize/serializeResolved.test.js +45 -0
- package/dist/serialize.d.ts +1 -0
- package/dist/serialize.js +1 -0
- package/dist/types/index.d.ts +187 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/clamp.d.ts +1 -0
- package/dist/utils/clamp.js +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/lerp.d.ts +1 -0
- package/dist/utils/lerp.js +1 -0
- package/dist/utils/parseColor.d.ts +6 -0
- package/dist/utils/parseColor.js +67 -0
- package/dist/utils/parseColor.test.d.ts +1 -0
- package/dist/utils/parseColor.test.js +51 -0
- package/dist/utils/smoothstep.d.ts +1 -0
- package/dist/utils/smoothstep.js +5 -0
- package/package.json +19 -12
- package/planning/phase-10-review.md +550 -0
- package/planning/phase-7-review.md +411 -0
- package/planning/phase-8-review.md +669 -0
- package/planning/phase-9-review.md +564 -0
- package/planning/roadmap-v0.3.md +284 -0
- package/planning/spec-serializer-v0.3.md +324 -0
- package/planning/spec-v0.3.md +305 -0
- package/src/cli/args.test.ts +28 -0
- package/src/cli/args.ts +66 -0
- package/src/cli/codegen/__snapshots__/tokens.test.ts.snap +87 -0
- package/src/cli/codegen/tokens.test.ts +61 -0
- package/src/cli/codegen/tokens.ts +191 -0
- package/src/cli/config.ts +71 -0
- package/src/cli/validate.test.ts +49 -0
- package/src/cli/validate.ts +38 -0
- package/src/cli.ts +183 -0
- package/src/contrast/apca.test.ts +20 -0
- package/src/contrast/apca.ts +26 -0
- package/src/contrast/index.ts +4 -0
- package/src/contrast/scoring.test.ts +188 -0
- package/src/contrast/scoring.ts +48 -0
- package/src/contrast/solver.test.ts +147 -0
- package/src/contrast/solver.ts +235 -0
- package/src/contrast/types.ts +20 -0
- package/src/contrast/utils.ts +28 -0
- package/src/contrast/wcag2.test.ts +21 -0
- package/src/contrast/wcag2.ts +24 -0
- package/src/core/createTheme.ts +78 -0
- package/src/core/dx-helpers.test.ts +82 -0
- package/src/core/index.ts +7 -0
- package/src/core/onSolid.test.ts +146 -0
- package/src/core/qa.v1.test.ts +149 -0
- package/src/core/resolve.test.ts +99 -0
- package/src/core/resolve.ts +11 -0
- package/src/core/resolveMany.ts +22 -0
- package/src/core/tokenRegistry.test.ts +153 -0
- package/src/core/tokenRegistry.ts +114 -0
- package/src/engine/applyOperators.ts +32 -0
- package/src/engine/context.ts +8 -0
- package/src/engine/gamut.test.ts +30 -0
- package/src/engine/gamut.ts +144 -0
- package/src/engine/generateScale.test.ts +46 -0
- package/src/engine/generateScale.ts +48 -0
- package/src/engine/index.ts +8 -0
- package/src/engine/normalize.test.ts +222 -0
- package/src/engine/normalize.ts +550 -0
- package/src/engine/onSolid.ts +178 -0
- package/src/engine/resolveBaseColor.test.ts +117 -0
- package/src/engine/resolveBaseColor.ts +203 -0
- package/src/export/__snapshots__/exportTheme.test.ts.snap +74 -0
- package/src/export/exportTheme.test.ts +144 -0
- package/src/export/exportTheme.ts +251 -0
- package/src/export/index.ts +1 -0
- package/src/export/serializeColor.test.ts +73 -0
- package/src/export/serializeColor.ts +1 -0
- package/src/export.ts +1 -0
- package/src/index.ts +3 -0
- package/src/operators/emphasis.test.ts +85 -0
- package/src/operators/emphasis.ts +132 -0
- package/src/operators/index.ts +3 -0
- package/src/operators/state.test.ts +66 -0
- package/src/operators/state.ts +122 -0
- package/src/operators/types.ts +14 -0
- package/src/operators/utils.ts +44 -0
- package/src/presets/curves.ts +168 -0
- package/src/presets/index.ts +2 -0
- package/src/presets/tokens/index.ts +3 -0
- package/src/presets/tokens/minimal-ui.ts +55 -0
- package/src/presets/tokens/modern-ui.ts +85 -0
- package/src/presets/tokens/presets.test.ts +46 -0
- package/src/presets/tokens/radixLike-ui.ts +79 -0
- package/src/serialize/index.ts +1 -0
- package/src/serialize/normalizeOutput.ts +63 -0
- package/src/serialize/serializeColor.ts +260 -0
- package/src/serialize/serializeResolved.test.ts +57 -0
- package/src/serialize.ts +1 -0
- package/src/types/index.ts +207 -0
- package/src/utils/clamp.ts +2 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/lerp.ts +1 -0
- package/src/utils/parseColor.test.ts +66 -0
- package/src/utils/parseColor.ts +87 -0
- package/src/utils/smoothstep.ts +6 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.json +15 -0
- package/dist/alpha/generateAlphaScale.d.ts +0 -5
- package/dist/alpha/generateAlphaScale.js +0 -34
- package/dist/contrast/onSolid.d.ts +0 -6
- package/dist/contrast/onSolid.js +0 -28
- package/dist/contrast/solveText.d.ts +0 -2
- package/dist/contrast/solveText.js +0 -31
- package/dist/createTheme.d.ts +0 -38
- package/dist/createTheme.js +0 -137
- package/dist/data/radixSeeds.d.ts +0 -3
- package/dist/data/radixSeeds.js +0 -34
- package/dist/diagnostics/analyzeScale.d.ts +0 -2
- package/dist/diagnostics/analyzeScale.js +0 -7
- package/dist/diagnostics/analyzeTheme.d.ts +0 -2
- package/dist/diagnostics/analyzeTheme.js +0 -35
- package/dist/diagnostics/warnings.d.ts +0 -2
- package/dist/diagnostics/warnings.js +0 -20
- package/dist/engine/curves.d.ts +0 -9
- package/dist/engine/curves.js +0 -48
- package/dist/engine/oklch.d.ts +0 -8
- package/dist/engine/oklch.js +0 -40
- package/dist/engine/templates.d.ts +0 -14
- package/dist/engine/templates.js +0 -45
- package/dist/exporters/selectColorMode.d.ts +0 -2
- package/dist/exporters/selectColorMode.js +0 -19
- package/dist/exporters/toCssVars.d.ts +0 -13
- package/dist/exporters/toCssVars.js +0 -108
- package/dist/exporters/toJson.d.ts +0 -3
- package/dist/exporters/toJson.js +0 -25
- package/dist/exporters/toReactNative.d.ts +0 -54
- package/dist/exporters/toReactNative.js +0 -33
- package/dist/exporters/toTailwind.d.ts +0 -17
- package/dist/exporters/toTailwind.js +0 -111
- package/dist/exporters/toTs.d.ts +0 -3
- package/dist/exporters/toTs.js +0 -43
- package/dist/generateScale.d.ts +0 -48
- package/dist/generateScale.js +0 -274
- package/dist/overlays/generateOverlayScale.d.ts +0 -2
- package/dist/overlays/generateOverlayScale.js +0 -34
- package/dist/text/generateTextScale.d.ts +0 -8
- package/dist/text/generateTextScale.js +0 -18
- package/dist/tokens/presetRadixLikeUi.d.ts +0 -5
- package/dist/tokens/presetRadixLikeUi.js +0 -55
- package/dist/types.d.ts +0 -69
- /package/dist/{types.js → cli/args.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,217 +1,127 @@
|
|
|
1
1
|
# Palette Kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Palette Kit is a **runtime-first color engine** for generating OKLCH-based palettes from semantic queries, with optional build-time tooling (serializer, exporters, CLI, codegen).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
5
|
+
## Install
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
npm install @clhaas/palette-kit
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
yarn add @clhaas/palette-kit
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
pnpm add @clhaas/palette-kit
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## What the library provides
|
|
22
|
-
|
|
23
|
-
- 12-step scale (light/dark) from a seed.
|
|
24
|
-
- Semantic tokens for UI (`radix-like-ui` preset).
|
|
25
|
-
- Alpha scales per palette slot (chromatic alpha).
|
|
26
|
-
- Overlay scales (black/white alpha).
|
|
27
|
-
- Deterministic text scales for light/dark backgrounds.
|
|
28
|
-
- Exporters for TS, JSON, CSS vars, Tailwind, and React Native.
|
|
29
|
-
- Auto anchor selection per mode (light/dark), overridable via `anchorStep`.
|
|
30
|
-
- Basic contrast and gamut diagnostics.
|
|
31
|
-
|
|
32
|
-
## Usage example
|
|
11
|
+
## Runtime quick start
|
|
33
12
|
|
|
34
13
|
```ts
|
|
35
14
|
import { createTheme } from "@clhaas/palette-kit";
|
|
36
15
|
|
|
37
16
|
const theme = createTheme({
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
success: { source: "seed", value: "#16a34a" },
|
|
42
|
-
warning: { source: "seed", value: "#f59e0b" },
|
|
43
|
-
danger: { source: "seed", value: "#ef4444" },
|
|
44
|
-
},
|
|
45
|
-
tokens: { preset: "radix-like-ui" },
|
|
46
|
-
text: {
|
|
47
|
-
darkBase: "#1C1C1E",
|
|
48
|
-
lightBase: "#F5F5F7",
|
|
17
|
+
seeds: {
|
|
18
|
+
light: { neutral: "#111827", accent: "#3d63dd" },
|
|
19
|
+
dark: { neutral: "#111827", accent: "#3d63dd" },
|
|
49
20
|
},
|
|
50
|
-
|
|
21
|
+
preset: "modern",
|
|
51
22
|
});
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Quick start
|
|
55
23
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const theme = createTheme({
|
|
62
|
-
neutral: { source: "seed", value: "#111827" },
|
|
63
|
-
accent: { source: "seed", value: "#3d63dd" },
|
|
24
|
+
const bg = theme.resolve({
|
|
25
|
+
role: "bg.app",
|
|
26
|
+
usage: "bg",
|
|
27
|
+
surface: "app",
|
|
28
|
+
context: "light",
|
|
64
29
|
});
|
|
65
30
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
:root {
|
|
73
|
-
/* paste the generated CSS vars here */
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
body {
|
|
77
|
-
background: var(--pk-bg-app);
|
|
78
|
-
color: var(--pk-text-primary);
|
|
79
|
-
}
|
|
31
|
+
const onSolidText = theme.onSolid({
|
|
32
|
+
bgRole: "bg.app",
|
|
33
|
+
usage: "text",
|
|
34
|
+
context: "light",
|
|
35
|
+
contrast: { model: "apca", targetLc: 75 },
|
|
36
|
+
});
|
|
80
37
|
```
|
|
81
38
|
|
|
82
|
-
##
|
|
83
|
-
|
|
84
|
-
1) Install:
|
|
39
|
+
## Serializer (public)
|
|
85
40
|
|
|
86
|
-
|
|
87
|
-
npm install @clhaas/palette-kit
|
|
88
|
-
```
|
|
41
|
+
Use the serializer to turn resolved OKLCH into CSS/RN-ready strings:
|
|
89
42
|
|
|
90
|
-
|
|
43
|
+
```ts
|
|
44
|
+
import { createTheme } from "@clhaas/palette-kit";
|
|
45
|
+
import { serializeResolved } from "@clhaas/palette-kit/serialize";
|
|
91
46
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
accent: { source: "seed", value: "#3d63dd" },
|
|
97
|
-
semantic: {
|
|
98
|
-
success: { source: "seed", value: "#16a34a" },
|
|
99
|
-
warning: { source: "seed", value: "#f59e0b" },
|
|
100
|
-
danger: { source: "seed", value: "#ef4444" },
|
|
101
|
-
},
|
|
102
|
-
tokens: { preset: "radix-like-ui" },
|
|
103
|
-
alpha: { enabled: true },
|
|
104
|
-
text: {
|
|
105
|
-
darkBase: "#1C1C1E",
|
|
106
|
-
lightBase: "#F5F5F7",
|
|
47
|
+
const theme = createTheme({
|
|
48
|
+
seeds: {
|
|
49
|
+
light: { neutral: "#111827", accent: "#3d63dd" },
|
|
50
|
+
dark: { neutral: "#111827", accent: "#3d63dd" },
|
|
107
51
|
},
|
|
108
|
-
|
|
109
|
-
};
|
|
110
|
-
```
|
|
52
|
+
});
|
|
111
53
|
|
|
112
|
-
|
|
54
|
+
const resolved = theme.resolve({ role: "bg.app", usage: "bg", surface: "app" });
|
|
55
|
+
const color = serializeResolved(resolved, { preferSpace: "srgb", srgbFormat: "hex" });
|
|
113
56
|
|
|
114
|
-
|
|
115
|
-
npx palette-kit generate --out src/theme.ts
|
|
57
|
+
console.log(color.value);
|
|
116
58
|
```
|
|
117
59
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```ts
|
|
121
|
-
import { toCssVars } from "@clhaas/palette-kit";
|
|
122
|
-
import { theme } from "./theme";
|
|
123
|
-
|
|
124
|
-
const css = toCssVars(theme, { prefix: "pk" });
|
|
125
|
-
// write the string into a .css file or inject it at build time
|
|
126
|
-
```
|
|
60
|
+
## Exporters (public, build-time)
|
|
127
61
|
|
|
128
|
-
|
|
62
|
+
Export deterministic CSS variables and JSON tokens:
|
|
129
63
|
|
|
130
64
|
```ts
|
|
131
|
-
import {
|
|
65
|
+
import { createTheme } from "@clhaas/palette-kit";
|
|
66
|
+
import { exportThemeCss, exportThemeJson } from "@clhaas/palette-kit/export";
|
|
132
67
|
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
68
|
+
const theme = createTheme({
|
|
69
|
+
seeds: {
|
|
70
|
+
light: { neutral: "#111827", accent: "#3d63dd" },
|
|
71
|
+
dark: { neutral: "#111827", accent: "#3d63dd" },
|
|
72
|
+
},
|
|
73
|
+
});
|
|
136
74
|
|
|
137
|
-
|
|
75
|
+
const tokens = {
|
|
76
|
+
"bg.app": { usage: "bg", surface: "app" },
|
|
77
|
+
"text.primary": { usage: "text", surface: "surface" },
|
|
78
|
+
};
|
|
138
79
|
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
const overlay = theme.overlay.black[9];
|
|
142
|
-
const textOnLight = theme.tokens.light["text.dark.primary"];
|
|
143
|
-
const textOnDark = theme.tokens.dark["text.light.primary"];
|
|
80
|
+
const { css } = exportThemeCss(theme, tokens, { includeSpaces: ["oklch", "p3"] });
|
|
81
|
+
const json = exportThemeJson(theme, tokens, { includeSpaces: ["srgb"] });
|
|
144
82
|
```
|
|
145
83
|
|
|
146
|
-
##
|
|
84
|
+
## CLI
|
|
147
85
|
|
|
148
|
-
|
|
86
|
+
- `palette-kit init` creates `palette.config.ts`
|
|
87
|
+
- `palette-kit build` writes `dist/palette/` artifacts (`tokens.css`, `tokens.json`, `tokens.ts`, `tokens.d.ts`)
|
|
149
88
|
|
|
150
|
-
|
|
151
|
-
theme.alpha?.light[5];
|
|
152
|
-
```
|
|
89
|
+
See `docs/CLI.md` for flags and config details.
|
|
153
90
|
|
|
154
|
-
|
|
91
|
+
## Docs
|
|
155
92
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
## React Native + Expo
|
|
93
|
+
- `docs/README.md`
|
|
94
|
+
- `docs/_api-surface.md`
|
|
95
|
+
- `docs/Exporters.md`
|
|
96
|
+
- `docs/CLI.md`
|
|
97
|
+
- `docs/Migration.md`
|
|
163
98
|
|
|
164
|
-
|
|
99
|
+
## Compatibility
|
|
165
100
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
101
|
+
- ESM package (`"type": "module"`).
|
|
102
|
+
- CJS is not supported in v0.3; use ESM or dynamic `import()` in CJS environments.
|
|
103
|
+
- Subpath imports:
|
|
104
|
+
- `@clhaas/palette-kit/serialize`
|
|
105
|
+
- `@clhaas/palette-kit/export`
|
|
106
|
+
- `@clhaas/palette-kit/cli`
|
|
107
|
+
- Tree-shaking: runtime imports (`@clhaas/palette-kit`) do not bundle build-time tools (exporters/CLI).
|
|
170
108
|
|
|
171
|
-
|
|
172
|
-
neutral: { source: "seed", value: "#111827" },
|
|
173
|
-
accent: { source: "seed", value: "#3d63dd" },
|
|
174
|
-
p3: true,
|
|
175
|
-
});
|
|
109
|
+
### CommonJS note
|
|
176
110
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
111
|
+
```js
|
|
112
|
+
// CJS workaround (dynamic import)
|
|
113
|
+
(async () => {
|
|
114
|
+
const { createTheme } = await import("@clhaas/palette-kit");
|
|
115
|
+
const theme = createTheme({
|
|
116
|
+
seeds: {
|
|
117
|
+
light: { neutral: "#111827", accent: "#3d63dd" },
|
|
118
|
+
dark: { neutral: "#111827", accent: "#3d63dd" },
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
console.log(theme);
|
|
122
|
+
})();
|
|
182
123
|
```
|
|
183
124
|
|
|
184
|
-
See `examples/expo` for a full example.
|
|
185
|
-
|
|
186
|
-
Note: React Native does not support `color(display-p3 ...)` strings as drop-in colors. The `p3` field is provided as data for platforms that can handle wide color via native APIs.
|
|
187
|
-
|
|
188
|
-
## Principles
|
|
189
|
-
|
|
190
|
-
- Tokens by intent, not by color.
|
|
191
|
-
- Fixed steps (1-12) for UI consistency.
|
|
192
|
-
- OKLCH generation, contrast resolved with APCA.
|
|
193
|
-
|
|
194
|
-
## Docs and plans
|
|
195
|
-
|
|
196
|
-
- `docs/README.md`
|
|
197
|
-
- `docs/concepts.md`
|
|
198
|
-
- `docs/api.md`
|
|
199
|
-
- `docs/tokens.md`
|
|
200
|
-
- `docs/contrast.md`
|
|
201
|
-
- `docs/alpha.md`
|
|
202
|
-
- `docs/text.md`
|
|
203
|
-
- `docs/overlays.md`
|
|
204
|
-
- `docs/Why.md`
|
|
205
|
-
- `docs/spec-implementation.md`
|
|
206
|
-
- `docs/plan-tests.md`
|
|
207
|
-
- `docs/plan-docs.md`
|
|
208
|
-
|
|
209
|
-
## Short roadmap
|
|
210
|
-
|
|
211
|
-
1) Generate scales from seeds (light/dark).
|
|
212
|
-
2) Tokens and basic exporters.
|
|
213
|
-
3) Contrast and alpha scale.
|
|
214
|
-
|
|
215
125
|
## License
|
|
216
126
|
|
|
217
|
-
MIT
|
|
127
|
+
MIT — see `LICENSE`.
|
package/biome.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
|
|
3
|
+
"formatter": {
|
|
4
|
+
"enabled": true,
|
|
5
|
+
"indentStyle": "space",
|
|
6
|
+
"indentWidth": 2,
|
|
7
|
+
"lineWidth": 100
|
|
8
|
+
},
|
|
9
|
+
"linter": {
|
|
10
|
+
"enabled": true,
|
|
11
|
+
"rules": {
|
|
12
|
+
"recommended": true
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": {
|
|
16
|
+
"ignoreUnknown": true,
|
|
17
|
+
"includes": [
|
|
18
|
+
"**/*.js",
|
|
19
|
+
"**/*.ts",
|
|
20
|
+
"**/*.tsx",
|
|
21
|
+
"**/*.css",
|
|
22
|
+
"**/*.scss",
|
|
23
|
+
"**/*.html",
|
|
24
|
+
"**/*.json",
|
|
25
|
+
"**/*.md",
|
|
26
|
+
"!**/supabase/functions",
|
|
27
|
+
"!**/node_modules",
|
|
28
|
+
"!**/dist",
|
|
29
|
+
"!**/build",
|
|
30
|
+
"!**/coverage",
|
|
31
|
+
"!**/ios",
|
|
32
|
+
"!**/android",
|
|
33
|
+
"!**/.git/",
|
|
34
|
+
"!**/.vscode",
|
|
35
|
+
"!**/*.d.ts",
|
|
36
|
+
"!**/*.spec.ts",
|
|
37
|
+
"!**/*.test.ts",
|
|
38
|
+
"!**/.github",
|
|
39
|
+
"!**/examples",
|
|
40
|
+
"!**/tests"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class CliUsageError extends Error {
|
|
2
|
+
name: string;
|
|
3
|
+
}
|
|
4
|
+
export declare const HELP_TEXT = "palette-kit <command>\n\nCommands:\n palette-kit init [--force] [--path <dir>]\n palette-kit build [--config <path>] [--outDir <dir>] [--report]\n\nOptions:\n -h, --help Show help\n -v, --version Show version\n";
|
|
5
|
+
export type ParsedArgs = {
|
|
6
|
+
command?: string;
|
|
7
|
+
help: boolean;
|
|
8
|
+
version: boolean;
|
|
9
|
+
flags: Record<string, string | boolean>;
|
|
10
|
+
};
|
|
11
|
+
export declare const COMMANDS: readonly ["init", "build"];
|
|
12
|
+
export declare const parseArgs: (argv: string[]) => ParsedArgs;
|
package/dist/cli/args.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export class CliUsageError extends Error {
|
|
2
|
+
name = "CliUsageError";
|
|
3
|
+
}
|
|
4
|
+
export const HELP_TEXT = `palette-kit <command>
|
|
5
|
+
|
|
6
|
+
Commands:
|
|
7
|
+
palette-kit init [--force] [--path <dir>]
|
|
8
|
+
palette-kit build [--config <path>] [--outDir <dir>] [--report]
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
-h, --help Show help
|
|
12
|
+
-v, --version Show version
|
|
13
|
+
`;
|
|
14
|
+
export const COMMANDS = ["init", "build"];
|
|
15
|
+
export const parseArgs = (argv) => {
|
|
16
|
+
const first = argv[0];
|
|
17
|
+
const command = first && !first.startsWith("-") ? first : undefined;
|
|
18
|
+
const rest = command ? argv.slice(1) : argv;
|
|
19
|
+
const flags = {};
|
|
20
|
+
let i = 0;
|
|
21
|
+
while (i < rest.length) {
|
|
22
|
+
const value = rest[i];
|
|
23
|
+
if (value === undefined)
|
|
24
|
+
break;
|
|
25
|
+
if (value === "-h" || value === "--help") {
|
|
26
|
+
flags.help = true;
|
|
27
|
+
i += 1;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (value === "-v" || value === "--version") {
|
|
31
|
+
flags.version = true;
|
|
32
|
+
i += 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (value.startsWith("--")) {
|
|
36
|
+
const key = value.slice(2);
|
|
37
|
+
const next = rest[i + 1];
|
|
38
|
+
if (next && !next.startsWith("--")) {
|
|
39
|
+
flags[key] = next;
|
|
40
|
+
i += 2;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
flags[key] = true;
|
|
44
|
+
i += 1;
|
|
45
|
+
}
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
throw new CliUsageError(`Unknown argument: ${value}`);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
command,
|
|
52
|
+
help: Boolean(flags.help),
|
|
53
|
+
version: Boolean(flags.version),
|
|
54
|
+
flags,
|
|
55
|
+
};
|
|
56
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { CliUsageError, parseArgs } from "./args.js";
|
|
3
|
+
describe("cli args", () => {
|
|
4
|
+
it("parses init command", () => {
|
|
5
|
+
const parsed = parseArgs(["init"]);
|
|
6
|
+
expect(parsed.command).toBe("init");
|
|
7
|
+
});
|
|
8
|
+
it("parses build command with flags", () => {
|
|
9
|
+
const parsed = parseArgs(["build", "--config", "custom.ts", "--outDir", "out", "--report"]);
|
|
10
|
+
expect(parsed.command).toBe("build");
|
|
11
|
+
expect(parsed.flags.config).toBe("custom.ts");
|
|
12
|
+
expect(parsed.flags.outDir).toBe("out");
|
|
13
|
+
expect(parsed.flags.report).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
it("recognizes help and version flags", () => {
|
|
16
|
+
expect(parseArgs(["--help"]).help).toBe(true);
|
|
17
|
+
expect(parseArgs(["--version"]).version).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
it("throws on unknown arguments", () => {
|
|
20
|
+
expect(() => parseArgs(["build", "wat"])).toThrow(CliUsageError);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -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,12 @@
|
|
|
1
|
+
import type { TokenRegistry } from "../../types/index.js";
|
|
2
|
+
export type GeneratedTokens = {
|
|
3
|
+
tokenNames: string[];
|
|
4
|
+
tokensTs: string;
|
|
5
|
+
tokensDts: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Generate `dist/palette/tokens.ts` and `dist/palette/tokens.d.ts` sources.
|
|
9
|
+
*
|
|
10
|
+
* Output is deterministic and derived from the token registry.
|
|
11
|
+
*/
|
|
12
|
+
export declare const generateTokenArtifacts: (registry: TokenRegistry) => GeneratedTokens;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
const RESERVED_WORDS = new Set([
|
|
2
|
+
"break",
|
|
3
|
+
"case",
|
|
4
|
+
"catch",
|
|
5
|
+
"class",
|
|
6
|
+
"const",
|
|
7
|
+
"continue",
|
|
8
|
+
"debugger",
|
|
9
|
+
"default",
|
|
10
|
+
"delete",
|
|
11
|
+
"do",
|
|
12
|
+
"else",
|
|
13
|
+
"export",
|
|
14
|
+
"extends",
|
|
15
|
+
"finally",
|
|
16
|
+
"for",
|
|
17
|
+
"function",
|
|
18
|
+
"if",
|
|
19
|
+
"import",
|
|
20
|
+
"in",
|
|
21
|
+
"instanceof",
|
|
22
|
+
"new",
|
|
23
|
+
"return",
|
|
24
|
+
"super",
|
|
25
|
+
"switch",
|
|
26
|
+
"this",
|
|
27
|
+
"throw",
|
|
28
|
+
"try",
|
|
29
|
+
"typeof",
|
|
30
|
+
"var",
|
|
31
|
+
"void",
|
|
32
|
+
"while",
|
|
33
|
+
"with",
|
|
34
|
+
"yield",
|
|
35
|
+
]);
|
|
36
|
+
const isValidIdentifier = (value) => {
|
|
37
|
+
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value))
|
|
38
|
+
return false;
|
|
39
|
+
return !RESERVED_WORDS.has(value);
|
|
40
|
+
};
|
|
41
|
+
const toPropertyKey = (key) => (isValidIdentifier(key) ? key : JSON.stringify(key));
|
|
42
|
+
const indentLines = (lines, spaces) => {
|
|
43
|
+
const prefix = " ".repeat(spaces);
|
|
44
|
+
return lines.map((line) => (line.length ? `${prefix}${line}` : line));
|
|
45
|
+
};
|
|
46
|
+
const escapeJsDoc = (value) => value.replace(/\*\//g, "*\\/");
|
|
47
|
+
const buildTokenJsDocLines = (tokenName, token) => {
|
|
48
|
+
const lines = [];
|
|
49
|
+
if (token.description?.trim()) {
|
|
50
|
+
lines.push(escapeJsDoc(token.description.trim()));
|
|
51
|
+
}
|
|
52
|
+
lines.push(`@token ${tokenName}`);
|
|
53
|
+
if (token.category?.trim()) {
|
|
54
|
+
lines.push(`@category ${escapeJsDoc(token.category.trim())}`);
|
|
55
|
+
}
|
|
56
|
+
const states = token.states ? Object.keys(token.states).sort() : [];
|
|
57
|
+
if (states.length > 0) {
|
|
58
|
+
lines.push(`@states ${states.join(", ")}`);
|
|
59
|
+
}
|
|
60
|
+
return ["/**", ...lines.map((line) => ` * ${line}`), " */"];
|
|
61
|
+
};
|
|
62
|
+
const buildTree = (registry) => {
|
|
63
|
+
const root = { children: new Map() };
|
|
64
|
+
const entries = Object.entries(registry.tokens).sort(([a], [b]) => a.localeCompare(b));
|
|
65
|
+
for (const [tokenName, token] of entries) {
|
|
66
|
+
const segments = tokenName.split(".").filter(Boolean);
|
|
67
|
+
if (segments.length === 0)
|
|
68
|
+
continue;
|
|
69
|
+
let node = root;
|
|
70
|
+
for (const segment of segments) {
|
|
71
|
+
let child = node.children.get(segment);
|
|
72
|
+
if (!child) {
|
|
73
|
+
child = { children: new Map() };
|
|
74
|
+
node.children.set(segment, child);
|
|
75
|
+
}
|
|
76
|
+
node = child;
|
|
77
|
+
}
|
|
78
|
+
node.token = token;
|
|
79
|
+
}
|
|
80
|
+
return root;
|
|
81
|
+
};
|
|
82
|
+
const renderTreeTs = (node, tokenNamePrefix) => {
|
|
83
|
+
const lines = ["{"];
|
|
84
|
+
const keys = [...node.children.keys()].sort((a, b) => a.localeCompare(b));
|
|
85
|
+
for (const key of keys) {
|
|
86
|
+
const child = node.children.get(key);
|
|
87
|
+
if (!child)
|
|
88
|
+
continue;
|
|
89
|
+
const fullTokenName = tokenNamePrefix ? `${tokenNamePrefix}.${key}` : key;
|
|
90
|
+
const propKey = toPropertyKey(key);
|
|
91
|
+
if (child.token && child.children.size === 0) {
|
|
92
|
+
lines.push(...buildTokenJsDocLines(fullTokenName, child.token));
|
|
93
|
+
lines.push(`${propKey}: "${fullTokenName}",`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const childLines = renderTreeTs(child, fullTokenName);
|
|
97
|
+
lines.push(`${propKey}: ${childLines[0]}`);
|
|
98
|
+
lines.push(...indentLines(childLines.slice(1), 2));
|
|
99
|
+
lines[lines.length - 1] = `${lines[lines.length - 1]},`;
|
|
100
|
+
}
|
|
101
|
+
lines.push("}");
|
|
102
|
+
return lines;
|
|
103
|
+
};
|
|
104
|
+
const renderTreeDts = (node, tokenNamePrefix) => {
|
|
105
|
+
const lines = ["{"];
|
|
106
|
+
const keys = [...node.children.keys()].sort((a, b) => a.localeCompare(b));
|
|
107
|
+
for (const key of keys) {
|
|
108
|
+
const child = node.children.get(key);
|
|
109
|
+
if (!child)
|
|
110
|
+
continue;
|
|
111
|
+
const fullTokenName = tokenNamePrefix ? `${tokenNamePrefix}.${key}` : key;
|
|
112
|
+
const propKey = toPropertyKey(key);
|
|
113
|
+
if (child.token && child.children.size === 0) {
|
|
114
|
+
lines.push(...buildTokenJsDocLines(fullTokenName, child.token));
|
|
115
|
+
lines.push(`${propKey}: "${fullTokenName}";`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const childLines = renderTreeDts(child, fullTokenName);
|
|
119
|
+
lines.push(`${propKey}: ${childLines[0]}`);
|
|
120
|
+
lines.push(...indentLines(childLines.slice(1), 2));
|
|
121
|
+
lines[lines.length - 1] = `${lines[lines.length - 1]};`;
|
|
122
|
+
}
|
|
123
|
+
lines.push("}");
|
|
124
|
+
return lines;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Generate `dist/palette/tokens.ts` and `dist/palette/tokens.d.ts` sources.
|
|
128
|
+
*
|
|
129
|
+
* Output is deterministic and derived from the token registry.
|
|
130
|
+
*/
|
|
131
|
+
export const generateTokenArtifacts = (registry) => {
|
|
132
|
+
const tokenNames = Object.keys(registry.tokens).sort((a, b) => a.localeCompare(b));
|
|
133
|
+
const tree = buildTree(registry);
|
|
134
|
+
const tokensObject = renderTreeTs(tree, "");
|
|
135
|
+
const tokensDtsObject = renderTreeDts(tree, "");
|
|
136
|
+
const tokensTs = `/* This file is generated by palette-kit build (Phase 7). */\n\nexport const tokens = ${tokensObject.join("\n")} as const;\n\nexport const tokenNames = ${JSON.stringify(tokenNames, null, 2)} as const;\n\nexport type TokenName = (typeof tokenNames)[number];\n\nexport type ColorRole = TokenName;\n`;
|
|
137
|
+
const tokensDts = `/* This file is generated by palette-kit build (Phase 7). */\n\nexport declare const tokens: ${tokensDtsObject.join("\n")};\n\nexport declare const tokenNames: readonly ${JSON.stringify(tokenNames, null, 2)};\n\nexport type TokenName = (typeof tokenNames)[number];\n\nexport type ColorRole = TokenName;\n`;
|
|
138
|
+
return { tokenNames, tokensTs, tokensDts };
|
|
139
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|