color-map 2.2.0 → 2.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/.claude-plugin/plugin.json +12 -0
- package/.codex-plugin/plugin.json +12 -0
- package/.cursor-plugin/plugin.json +12 -0
- package/CHANGELOG.md +94 -0
- package/README.md +71 -8
- package/bin/cli-CNBftDBE.js +6414 -0
- package/bin/color-map.js +9 -0
- package/bin/index.js +1 -0
- package/cjs/color/index.d.ts +5 -0
- package/cjs/color/index.js +52 -0
- package/cjs/color-wNrkrhC7.js +374 -0
- package/cjs/color-wNrkrhC7.js.map +1 -0
- package/cjs/contrast-XjF5Rwui.js +293 -0
- package/cjs/contrast-XjF5Rwui.js.map +1 -0
- package/cjs/gamut-CG1J2aat.d.ts +158 -0
- package/cjs/gamut-CG1J2aat.d.ts.map +1 -0
- package/cjs/index-BcEqCPHz.d.ts +137 -0
- package/cjs/index-BcEqCPHz.d.ts.map +1 -0
- package/cjs/index-CGKCqRqD.d.ts +111 -0
- package/cjs/index-CGKCqRqD.d.ts.map +1 -0
- package/cjs/index-Cv3iUUYE.d.ts +171 -0
- package/cjs/index-Cv3iUUYE.d.ts.map +1 -0
- package/cjs/index-Dw43Hj4v.d.ts +41 -0
- package/cjs/index-Dw43Hj4v.d.ts.map +1 -0
- package/cjs/index-Dy8UARqO.d.ts +72 -0
- package/cjs/index-Dy8UARqO.d.ts.map +1 -0
- package/cjs/index.d.ts +26 -36
- package/cjs/index.d.ts.map +1 -1
- package/cjs/index.js +83 -62
- package/cjs/index.js.map +1 -1
- package/cjs/legacy/index.d.ts +2 -0
- package/cjs/legacy/index.js +75 -0
- package/cjs/legacy/index.js.map +1 -0
- package/cjs/mix-Cs4owSbW.js +158 -0
- package/cjs/mix-Cs4owSbW.js.map +1 -0
- package/cjs/mix-DGlKoUw4.d.ts +31 -0
- package/cjs/mix-DGlKoUw4.d.ts.map +1 -0
- package/cjs/palette/index.d.ts +3 -0
- package/cjs/palette/index.js +8 -0
- package/cjs/palette-DyFV_KoJ.js +332 -0
- package/cjs/palette-DyFV_KoJ.js.map +1 -0
- package/cjs/parse-8mt2OMKf.js +1508 -0
- package/cjs/parse-8mt2OMKf.js.map +1 -0
- package/cjs/scale/index.d.ts +2 -0
- package/cjs/scale/index.js +11 -0
- package/cjs/scale-Cq9pXrc1.js +318 -0
- package/cjs/scale-Cq9pXrc1.js.map +1 -0
- package/cjs/semantic-CrEIo8tS.d.ts +52 -0
- package/cjs/semantic-CrEIo8tS.d.ts.map +1 -0
- package/cjs/serialize-C69DAmoE.d.ts +25 -0
- package/cjs/serialize-C69DAmoE.d.ts.map +1 -0
- package/cjs/serialize-Ci2X0cPN.js +103 -0
- package/cjs/serialize-Ci2X0cPN.js.map +1 -0
- package/cjs/tokens/index.d.ts +2 -0
- package/cjs/tokens/index.js +6 -0
- package/cjs/tokens-CzXxaMgM.js +168 -0
- package/cjs/tokens-CzXxaMgM.js.map +1 -0
- package/cjs/tone-BAhu-QzQ.js +118 -0
- package/cjs/tone-BAhu-QzQ.js.map +1 -0
- package/dist/color-map.es5.js.map +1 -1
- package/esm/color/a98-rgb.d.ts +7 -0
- package/esm/color/a98-rgb.d.ts.map +1 -0
- package/esm/color/a98-rgb.js +13 -0
- package/esm/color/a98-rgb.js.map +1 -0
- package/esm/color/argb.d.ts +6 -0
- package/esm/color/argb.d.ts.map +1 -0
- package/esm/color/argb.js +25 -0
- package/esm/color/argb.js.map +1 -0
- package/esm/color/calc.js +82 -0
- package/esm/color/calc.js.map +1 -0
- package/esm/color/compare.d.ts +20 -0
- package/esm/color/compare.d.ts.map +1 -0
- package/esm/color/compare.js +46 -0
- package/esm/color/compare.js.map +1 -0
- package/esm/color/contrast.d.ts +107 -0
- package/esm/color/contrast.d.ts.map +1 -0
- package/esm/color/contrast.js +242 -0
- package/esm/color/contrast.js.map +1 -0
- package/esm/color/convert.d.ts +9 -0
- package/esm/color/convert.d.ts.map +1 -0
- package/esm/color/convert.js +45 -0
- package/esm/color/convert.js.map +1 -0
- package/esm/color/display-p3-linear.d.ts +7 -0
- package/esm/color/display-p3-linear.d.ts.map +1 -0
- package/esm/color/display-p3-linear.js +12 -0
- package/esm/color/display-p3-linear.js.map +1 -0
- package/esm/color/display-p3.d.ts +7 -0
- package/esm/color/display-p3.d.ts.map +1 -0
- package/esm/color/display-p3.js +12 -0
- package/esm/color/display-p3.js.map +1 -0
- package/esm/color/expr.d.ts +43 -0
- package/esm/color/expr.d.ts.map +1 -0
- package/esm/color/expr.js +160 -0
- package/esm/color/expr.js.map +1 -0
- package/esm/color/gamut.d.ts +31 -0
- package/esm/color/gamut.d.ts.map +1 -0
- package/esm/color/gamut.js +210 -0
- package/esm/color/gamut.js.map +1 -0
- package/esm/color/hsl.d.ts +7 -0
- package/esm/color/hsl.d.ts.map +1 -0
- package/esm/color/hsl.js +67 -0
- package/esm/color/hsl.js.map +1 -0
- package/esm/color/hwb.d.ts +7 -0
- package/esm/color/hwb.d.ts.map +1 -0
- package/esm/color/hwb.js +40 -0
- package/esm/color/hwb.js.map +1 -0
- package/esm/color/index.d.ts +28 -0
- package/esm/color/index.js +27 -0
- package/esm/color/lab.d.ts +7 -0
- package/esm/color/lab.d.ts.map +1 -0
- package/esm/color/lab.js +33 -0
- package/esm/color/lab.js.map +1 -0
- package/esm/color/lch.d.ts +7 -0
- package/esm/color/lch.d.ts.map +1 -0
- package/esm/color/lch.js +11 -0
- package/esm/color/lch.js.map +1 -0
- package/esm/color/math.js +32 -0
- package/esm/color/math.js.map +1 -0
- package/esm/color/matrices.js +180 -0
- package/esm/color/matrices.js.map +1 -0
- package/esm/color/mix.d.ts +30 -0
- package/esm/color/mix.d.ts.map +1 -0
- package/esm/color/mix.js +152 -0
- package/esm/color/mix.js.map +1 -0
- package/esm/color/named.js +11 -0
- package/esm/color/named.js.map +1 -0
- package/esm/color/oklab.d.ts +7 -0
- package/esm/color/oklab.d.ts.map +1 -0
- package/esm/color/oklab.js +21 -0
- package/esm/color/oklab.js.map +1 -0
- package/esm/color/oklch.d.ts +7 -0
- package/esm/color/oklch.d.ts.map +1 -0
- package/esm/color/oklch.js +11 -0
- package/esm/color/oklch.js.map +1 -0
- package/esm/color/parse.d.ts +9 -0
- package/esm/color/parse.d.ts.map +1 -0
- package/esm/color/parse.js +452 -0
- package/esm/color/parse.js.map +1 -0
- package/esm/color/polar.js +27 -0
- package/esm/color/polar.js.map +1 -0
- package/esm/color/prophoto-rgb.d.ts +7 -0
- package/esm/color/prophoto-rgb.d.ts.map +1 -0
- package/esm/color/prophoto-rgb.js +18 -0
- package/esm/color/prophoto-rgb.js.map +1 -0
- package/esm/color/rec2020.d.ts +7 -0
- package/esm/color/rec2020.d.ts.map +1 -0
- package/esm/color/rec2020.js +13 -0
- package/esm/color/rec2020.js.map +1 -0
- package/esm/color/resolve.d.ts +18 -0
- package/esm/color/resolve.d.ts.map +1 -0
- package/esm/color/resolve.js +98 -0
- package/esm/color/resolve.js.map +1 -0
- package/esm/color/rgb.js +20 -0
- package/esm/color/rgb.js.map +1 -0
- package/esm/color/serialize.d.ts +24 -0
- package/esm/color/serialize.d.ts.map +1 -0
- package/esm/color/serialize.js +88 -0
- package/esm/color/serialize.js.map +1 -0
- package/esm/color/spaces.d.ts +6 -0
- package/esm/color/spaces.d.ts.map +1 -0
- package/esm/color/spaces.js +42 -0
- package/esm/color/spaces.js.map +1 -0
- package/esm/color/srgb-linear.d.ts +7 -0
- package/esm/color/srgb-linear.d.ts.map +1 -0
- package/esm/color/srgb-linear.js +12 -0
- package/esm/color/srgb-linear.js.map +1 -0
- package/esm/color/srgb.d.ts +7 -0
- package/esm/color/srgb.d.ts.map +1 -0
- package/esm/color/srgb.js +12 -0
- package/esm/color/srgb.js.map +1 -0
- package/esm/color/transfer.js +11 -0
- package/esm/color/transfer.js.map +1 -0
- package/esm/color/types.d.ts +23 -0
- package/esm/color/types.d.ts.map +1 -0
- package/esm/color/unknown-name.js +16 -0
- package/esm/color/unknown-name.js.map +1 -0
- package/esm/color/xyz-d50.d.ts +7 -0
- package/esm/color/xyz-d50.d.ts.map +1 -0
- package/esm/color/xyz-d50.js +15 -0
- package/esm/color/xyz-d50.js.map +1 -0
- package/esm/color/xyz-d65.d.ts +4 -0
- package/esm/color/xyz-d65.d.ts.map +1 -0
- package/esm/color/xyz-d65.js +10 -0
- package/esm/color/xyz-d65.js.map +1 -0
- package/esm/index.d.ts +63 -6
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +54 -5
- package/esm/index.js.map +1 -0
- package/esm/legacy/createColors.d.ts +9 -0
- package/esm/legacy/createColors.d.ts.map +1 -0
- package/esm/{createColors.js → legacy/createColors.js} +7 -2
- package/esm/legacy/createColors.js.map +1 -0
- package/esm/legacy/createColorsFromMap.d.ts +9 -0
- package/esm/legacy/createColorsFromMap.d.ts.map +1 -0
- package/esm/{createColorsFromMap.js → legacy/createColorsFromMap.js} +4 -2
- package/esm/legacy/createColorsFromMap.js.map +1 -0
- package/esm/legacy/index.d.ts +6 -0
- package/esm/legacy/index.js +5 -0
- package/esm/legacy/interfaces.d.ts +19 -0
- package/esm/legacy/interfaces.d.ts.map +1 -0
- package/esm/{rgbHex.d.ts → legacy/rgbHex.d.ts} +1 -4
- package/esm/legacy/rgbHex.d.ts.map +1 -0
- package/esm/{rgbHex.js → legacy/rgbHex.js} +1 -2
- package/esm/legacy/rgbHex.js.map +1 -0
- package/esm/legacy/rgbaString.d.ts +4 -0
- package/esm/{rgbaString.d.ts.map → legacy/rgbaString.d.ts.map} +1 -1
- package/esm/legacy/rgbaString.js +8 -0
- package/esm/legacy/rgbaString.js.map +1 -0
- package/esm/palette/dark.d.ts +23 -0
- package/esm/palette/dark.d.ts.map +1 -0
- package/esm/palette/dark.js +54 -0
- package/esm/palette/dark.js.map +1 -0
- package/esm/palette/harmony.d.ts +56 -0
- package/esm/palette/harmony.d.ts.map +1 -0
- package/esm/palette/harmony.js +115 -0
- package/esm/palette/harmony.js.map +1 -0
- package/esm/palette/index.d.ts +5 -0
- package/esm/palette/index.js +5 -0
- package/esm/palette/semantic.d.ts +53 -0
- package/esm/palette/semantic.d.ts.map +1 -0
- package/esm/palette/semantic.js +96 -0
- package/esm/palette/semantic.js.map +1 -0
- package/esm/palette/validate.d.ts +39 -0
- package/esm/palette/validate.d.ts.map +1 -0
- package/esm/palette/validate.js +56 -0
- package/esm/palette/validate.js.map +1 -0
- package/esm/scale/brand.d.ts +21 -0
- package/esm/scale/brand.d.ts.map +1 -0
- package/esm/scale/brand.js +63 -0
- package/esm/scale/brand.js.map +1 -0
- package/esm/scale/contrast-scale.d.ts +33 -0
- package/esm/scale/contrast-scale.d.ts.map +1 -0
- package/esm/scale/contrast-scale.js +26 -0
- package/esm/scale/contrast-scale.js.map +1 -0
- package/esm/scale/gradient.d.ts +38 -0
- package/esm/scale/gradient.d.ts.map +1 -0
- package/esm/scale/gradient.js +73 -0
- package/esm/scale/gradient.js.map +1 -0
- package/esm/scale/index.d.ts +6 -0
- package/esm/scale/index.js +6 -0
- package/esm/scale/scale.d.ts +31 -0
- package/esm/scale/scale.d.ts.map +1 -0
- package/esm/scale/scale.js +152 -0
- package/esm/scale/scale.js.map +1 -0
- package/esm/scale/tone.d.ts +25 -0
- package/esm/scale/tone.d.ts.map +1 -0
- package/esm/scale/tone.js +96 -0
- package/esm/scale/tone.js.map +1 -0
- package/esm/tokens/css.d.ts +18 -0
- package/esm/tokens/css.d.ts.map +1 -0
- package/esm/tokens/css.js +23 -0
- package/esm/tokens/css.js.map +1 -0
- package/esm/tokens/dtcg.d.ts +33 -0
- package/esm/tokens/dtcg.d.ts.map +1 -0
- package/esm/tokens/dtcg.js +42 -0
- package/esm/tokens/dtcg.js.map +1 -0
- package/esm/tokens/index.d.ts +5 -0
- package/esm/tokens/index.js +4 -0
- package/esm/tokens/tailwind.d.ts +19 -0
- package/esm/tokens/tailwind.d.ts.map +1 -0
- package/esm/tokens/tailwind.js +19 -0
- package/esm/tokens/tailwind.js.map +1 -0
- package/esm/tokens/tokens.d.ts +11 -0
- package/esm/tokens/tokens.d.ts.map +1 -0
- package/esm/tokens/tokens.js +77 -0
- package/esm/tokens/tokens.js.map +1 -0
- package/llms.txt +29 -0
- package/package.json +276 -64
- package/plugin.json +18 -0
- package/schemas/contrast.schema.json +24 -0
- package/schemas/convert.schema.json +60 -0
- package/schemas/export.schema.json +106 -0
- package/schemas/find-contrast.schema.json +51 -0
- package/schemas/harmony.schema.json +58 -0
- package/schemas/mix.schema.json +72 -0
- package/schemas/palette.schema.json +56 -0
- package/schemas/scale.schema.json +86 -0
- package/skills/color-map/SKILL.md +38 -0
- package/src/cli/bin.ts +11 -0
- package/src/cli/cli.ts +40 -0
- package/src/cli/commands/contrast.ts +36 -0
- package/src/cli/commands/convert.ts +37 -0
- package/src/cli/commands/export.ts +102 -0
- package/src/cli/commands/find-contrast.ts +37 -0
- package/src/cli/commands/harmony.ts +30 -0
- package/src/cli/commands/mix.ts +29 -0
- package/src/cli/commands/palette.ts +66 -0
- package/src/cli/commands/scale.ts +75 -0
- package/src/cli/index.ts +2 -0
- package/src/cli/schema-command.ts +31 -0
- package/src/cli/schemas.ts +86 -0
- package/src/cli/shared.ts +72 -0
- package/src/cli/testing.ts +27 -0
- package/src/color/a98-rgb.ts +11 -0
- package/src/color/argb.ts +21 -0
- package/src/color/calc.ts +84 -0
- package/src/color/compare.ts +53 -0
- package/src/color/contrast.ts +277 -0
- package/src/color/convert.ts +43 -0
- package/src/color/display-p3-linear.ts +9 -0
- package/src/color/display-p3.ts +9 -0
- package/src/color/expr.ts +158 -0
- package/src/color/gamut.ts +215 -0
- package/src/color/hsl.ts +57 -0
- package/src/color/hwb.ts +26 -0
- package/src/color/index.ts +43 -0
- package/src/color/lab.ts +29 -0
- package/src/color/lch.ts +8 -0
- package/src/color/math.ts +30 -0
- package/src/color/matrices.ts +91 -0
- package/src/color/mix.ts +158 -0
- package/src/color/named.ts +13 -0
- package/src/color/oklab.ts +19 -0
- package/src/color/oklch.ts +8 -0
- package/src/color/parse.ts +355 -0
- package/src/color/polar.ts +17 -0
- package/src/color/prophoto-rgb.ts +18 -0
- package/src/color/rec2020.ts +11 -0
- package/src/color/resolve.ts +87 -0
- package/src/color/rgb.ts +20 -0
- package/src/color/serialize.ts +96 -0
- package/src/color/spaces.ts +42 -0
- package/src/color/srgb-linear.ts +9 -0
- package/src/color/srgb.ts +9 -0
- package/src/color/test-utils.ts +10 -0
- package/src/color/transfer.ts +14 -0
- package/src/color/types.ts +41 -0
- package/src/color/unknown-name.ts +15 -0
- package/src/color/xyz-d50.ts +13 -0
- package/src/color/xyz-d65.ts +8 -0
- package/src/index.ts +37 -0
- package/{ts → src/legacy}/createColors.ts +6 -0
- package/{ts → src/legacy}/createColorsFromMap.ts +3 -0
- package/{ts → src/legacy}/interfaces.ts +4 -0
- package/{ts → src/legacy}/rgbaString.ts +1 -0
- package/src/palette/dark.ts +55 -0
- package/src/palette/harmony.ts +107 -0
- package/src/palette/index.ts +18 -0
- package/src/palette/semantic.ts +120 -0
- package/src/palette/validate.ts +82 -0
- package/src/scale/brand.ts +50 -0
- package/src/scale/contrast-scale.ts +48 -0
- package/src/scale/gradient.ts +91 -0
- package/src/scale/index.ts +5 -0
- package/src/scale/scale.ts +127 -0
- package/src/scale/tone.ts +69 -0
- package/src/tokens/css.ts +32 -0
- package/src/tokens/dtcg.ts +62 -0
- package/src/tokens/index.ts +11 -0
- package/src/tokens/tailwind.ts +24 -0
- package/src/tokens/tokens.ts +82 -0
- package/esm/createColors.d.ts +0 -6
- package/esm/createColors.d.ts.map +0 -1
- package/esm/createColors.js.map +0 -1
- package/esm/createColorsFromMap.d.ts +0 -9
- package/esm/createColorsFromMap.d.ts.map +0 -1
- package/esm/createColorsFromMap.js.map +0 -1
- package/esm/interfaces.d.ts +0 -18
- package/esm/interfaces.d.ts.map +0 -1
- package/esm/rgbHex.d.ts.map +0 -1
- package/esm/rgbHex.js.map +0 -1
- package/esm/rgbaString.d.ts +0 -6
- package/esm/rgbaString.js +0 -8
- package/esm/rgbaString.js.map +0 -1
- /package/{ts → src/legacy}/index.ts +0 -0
- /package/{ts → src/legacy}/rgbHex.ts +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://unpkg.com/color-map/schemas/harmony.schema.json",
|
|
4
|
+
"title": "color-map harmony",
|
|
5
|
+
"description": "The colors of a harmony scheme: the color rotated around the hue wheel",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"color": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "The base color",
|
|
11
|
+
"x-kind": "argument"
|
|
12
|
+
},
|
|
13
|
+
"scheme": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"enum": [
|
|
16
|
+
"complementary",
|
|
17
|
+
"split",
|
|
18
|
+
"analogous",
|
|
19
|
+
"triadic",
|
|
20
|
+
"tetradic"
|
|
21
|
+
],
|
|
22
|
+
"description": "The harmony scheme",
|
|
23
|
+
"default": "complementary",
|
|
24
|
+
"x-kind": "option"
|
|
25
|
+
},
|
|
26
|
+
"space": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"enum": [
|
|
29
|
+
"hsl",
|
|
30
|
+
"hwb",
|
|
31
|
+
"lch",
|
|
32
|
+
"oklch"
|
|
33
|
+
],
|
|
34
|
+
"description": "The space whose hue is rotated",
|
|
35
|
+
"default": "oklch",
|
|
36
|
+
"x-kind": "option"
|
|
37
|
+
},
|
|
38
|
+
"gamut": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"enum": [
|
|
41
|
+
"srgb",
|
|
42
|
+
"srgb-linear",
|
|
43
|
+
"display-p3",
|
|
44
|
+
"display-p3-linear",
|
|
45
|
+
"a98-rgb",
|
|
46
|
+
"prophoto-rgb",
|
|
47
|
+
"rec2020"
|
|
48
|
+
],
|
|
49
|
+
"description": "The gamut every color must fit",
|
|
50
|
+
"default": "srgb",
|
|
51
|
+
"x-kind": "option"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"required": [
|
|
55
|
+
"color"
|
|
56
|
+
],
|
|
57
|
+
"additionalProperties": false
|
|
58
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://unpkg.com/color-map/schemas/mix.schema.json",
|
|
4
|
+
"title": "color-map mix",
|
|
5
|
+
"description": "Mix two CSS colors, as color-mix() does",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"a": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "The first color",
|
|
11
|
+
"x-kind": "argument"
|
|
12
|
+
},
|
|
13
|
+
"b": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "The second color",
|
|
16
|
+
"x-kind": "argument"
|
|
17
|
+
},
|
|
18
|
+
"amount": {
|
|
19
|
+
"type": "number",
|
|
20
|
+
"minimum": 0,
|
|
21
|
+
"maximum": 1,
|
|
22
|
+
"description": "How far from a to b, 0 to 1",
|
|
23
|
+
"default": 0.5,
|
|
24
|
+
"x-kind": "option"
|
|
25
|
+
},
|
|
26
|
+
"in": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"enum": [
|
|
29
|
+
"srgb",
|
|
30
|
+
"srgb-linear",
|
|
31
|
+
"hsl",
|
|
32
|
+
"hwb",
|
|
33
|
+
"lab",
|
|
34
|
+
"lch",
|
|
35
|
+
"oklab",
|
|
36
|
+
"oklch",
|
|
37
|
+
"display-p3",
|
|
38
|
+
"display-p3-linear",
|
|
39
|
+
"a98-rgb",
|
|
40
|
+
"prophoto-rgb",
|
|
41
|
+
"rec2020",
|
|
42
|
+
"xyz-d50",
|
|
43
|
+
"xyz-d65"
|
|
44
|
+
],
|
|
45
|
+
"description": "The space to interpolate in",
|
|
46
|
+
"default": "oklab",
|
|
47
|
+
"x-kind": "option"
|
|
48
|
+
},
|
|
49
|
+
"hue": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"enum": [
|
|
52
|
+
"shorter",
|
|
53
|
+
"longer",
|
|
54
|
+
"increasing",
|
|
55
|
+
"decreasing"
|
|
56
|
+
],
|
|
57
|
+
"description": "How hues travel in a polar space",
|
|
58
|
+
"default": "shorter",
|
|
59
|
+
"x-kind": "option"
|
|
60
|
+
},
|
|
61
|
+
"full": {
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"description": "Show the complete output instead of truncating it",
|
|
64
|
+
"x-kind": "option"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"required": [
|
|
68
|
+
"a",
|
|
69
|
+
"b"
|
|
70
|
+
],
|
|
71
|
+
"additionalProperties": false
|
|
72
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://unpkg.com/color-map/schemas/palette.schema.json",
|
|
4
|
+
"title": "color-map palette",
|
|
5
|
+
"description": "A semantic palette from one brand color: primary, status colors, surface and outline, each with a text color and its WCAG 2 ratio",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"brand": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "The brand color",
|
|
11
|
+
"x-kind": "argument"
|
|
12
|
+
},
|
|
13
|
+
"mode": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"enum": [
|
|
16
|
+
"light",
|
|
17
|
+
"dark"
|
|
18
|
+
],
|
|
19
|
+
"description": "light or dark",
|
|
20
|
+
"default": "light",
|
|
21
|
+
"x-kind": "option"
|
|
22
|
+
},
|
|
23
|
+
"target": {
|
|
24
|
+
"type": "number",
|
|
25
|
+
"minimum": 1,
|
|
26
|
+
"maximum": 21,
|
|
27
|
+
"description": "The WCAG 2 ratio every text pair must reach",
|
|
28
|
+
"default": 4.5,
|
|
29
|
+
"x-kind": "option"
|
|
30
|
+
},
|
|
31
|
+
"gamut": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"enum": [
|
|
34
|
+
"srgb",
|
|
35
|
+
"srgb-linear",
|
|
36
|
+
"display-p3",
|
|
37
|
+
"display-p3-linear",
|
|
38
|
+
"a98-rgb",
|
|
39
|
+
"prophoto-rgb",
|
|
40
|
+
"rec2020"
|
|
41
|
+
],
|
|
42
|
+
"description": "The gamut every color must fit",
|
|
43
|
+
"default": "srgb",
|
|
44
|
+
"x-kind": "option"
|
|
45
|
+
},
|
|
46
|
+
"full": {
|
|
47
|
+
"type": "boolean",
|
|
48
|
+
"description": "Show the complete output instead of truncating it",
|
|
49
|
+
"x-kind": "option"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"required": [
|
|
53
|
+
"brand"
|
|
54
|
+
],
|
|
55
|
+
"additionalProperties": false
|
|
56
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://unpkg.com/color-map/schemas/scale.schema.json",
|
|
4
|
+
"title": "color-map scale",
|
|
5
|
+
"description": "Build a color scale from a seed color: a preset, a Radix-style brand scale, or contrast targets",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"seed": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "The color the scale is built around",
|
|
11
|
+
"x-kind": "argument"
|
|
12
|
+
},
|
|
13
|
+
"preset": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"enum": [
|
|
16
|
+
"tailwind-11",
|
|
17
|
+
"radix-12",
|
|
18
|
+
"tone-13",
|
|
19
|
+
"even"
|
|
20
|
+
],
|
|
21
|
+
"description": "The scale shape",
|
|
22
|
+
"default": "tailwind-11",
|
|
23
|
+
"x-kind": "option"
|
|
24
|
+
},
|
|
25
|
+
"steps": {
|
|
26
|
+
"type": "integer",
|
|
27
|
+
"minimum": 2,
|
|
28
|
+
"description": "Steps of an even scale; replaces --preset",
|
|
29
|
+
"x-kind": "option"
|
|
30
|
+
},
|
|
31
|
+
"brand": {
|
|
32
|
+
"type": "boolean",
|
|
33
|
+
"description": "Build a 12-step UI scale where the seed is step 9 exactly",
|
|
34
|
+
"x-kind": "option"
|
|
35
|
+
},
|
|
36
|
+
"mode": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"enum": [
|
|
39
|
+
"light",
|
|
40
|
+
"dark"
|
|
41
|
+
],
|
|
42
|
+
"description": "light or dark, for --brand",
|
|
43
|
+
"default": "light",
|
|
44
|
+
"x-kind": "option"
|
|
45
|
+
},
|
|
46
|
+
"background": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"description": "The background: page color for --brand, or what --targets are measured against",
|
|
49
|
+
"x-kind": "option"
|
|
50
|
+
},
|
|
51
|
+
"targets": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"items": {
|
|
54
|
+
"type": "number",
|
|
55
|
+
"minimum": 1,
|
|
56
|
+
"maximum": 21
|
|
57
|
+
},
|
|
58
|
+
"description": "Contrast ratios, one per step, such as 3,4.5,7: builds a contrast scale",
|
|
59
|
+
"x-kind": "option"
|
|
60
|
+
},
|
|
61
|
+
"gamut": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"enum": [
|
|
64
|
+
"srgb",
|
|
65
|
+
"srgb-linear",
|
|
66
|
+
"display-p3",
|
|
67
|
+
"display-p3-linear",
|
|
68
|
+
"a98-rgb",
|
|
69
|
+
"prophoto-rgb",
|
|
70
|
+
"rec2020"
|
|
71
|
+
],
|
|
72
|
+
"description": "The gamut every step must fit",
|
|
73
|
+
"default": "srgb",
|
|
74
|
+
"x-kind": "option"
|
|
75
|
+
},
|
|
76
|
+
"full": {
|
|
77
|
+
"type": "boolean",
|
|
78
|
+
"description": "Show the complete output instead of truncating it",
|
|
79
|
+
"x-kind": "option"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"required": [
|
|
83
|
+
"seed"
|
|
84
|
+
],
|
|
85
|
+
"additionalProperties": false
|
|
86
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: color-map
|
|
3
|
+
description: Build a design-system color palette, scale or token file with the color-map CLI. Use when asked to pick or generate colors from a brand color, make a semantic palette with passing contrast, convert or mix CSS colors, check WCAG contrast, or export colors as CSS variables, DTCG tokens or a Tailwind v4 theme.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# color-map
|
|
7
|
+
|
|
8
|
+
Drive the `color-map` command instead of writing color math by hand. Every result prints as TOON by default; add `--format json` for JSON. Run it with `npx color-map` when it is not installed.
|
|
9
|
+
|
|
10
|
+
## One prompt to a valid palette
|
|
11
|
+
|
|
12
|
+
1. Run `color-map palette '<brand color>' [--mode dark]`. The answer lists each role (`primary`, `primaryContainer`, `success`, `warning`, `danger`, `info`, `surface`, `surfaceVariant`, `outline`) with its background, text color and WCAG 2 ratio.
|
|
13
|
+
2. Read `failing` and `issues`. `failing: 0` and `issues: "none: ..."` mean every pair meets its target. If not, change `--target` or the brand color and run it again; do not edit hex values by hand.
|
|
14
|
+
3. Write the result with `color-map export '<brand color>' --source palette --to css|tailwind|dtcg`. The output is the file content: redirect it to a file.
|
|
15
|
+
4. Do both modes when the design has a dark theme: run steps 1 and 3 with `--mode dark`.
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
| Command | Use it to |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| `convert <color> --to <space> [--gamut <gamut>]` | change space; `--gamut` maps into a gamut instead of clipping |
|
|
22
|
+
| `mix <a> <b> [--amount 0.5] [--in oklab]` | blend as `color-mix()` does |
|
|
23
|
+
| `contrast <fg> <bg>` | WCAG 2 ratio with the AA and AAA verdicts |
|
|
24
|
+
| `find-contrast <bg> --target 4.5 [--hue H] [--chroma C]` | find a text color that reaches a ratio |
|
|
25
|
+
| `scale <seed> [--preset tailwind-11\|radix-12\|tone-13\|even] [--steps N] [--brand] [--targets R ...]` | a scale; `--brand` keeps the seed as step 9; `--targets` with `--background` builds a contrast scale |
|
|
26
|
+
| `palette <brand> [--mode] [--target]` | the semantic palette above |
|
|
27
|
+
| `harmony <color> --scheme complementary\|split\|analogous\|triadic\|tetradic` | related hues |
|
|
28
|
+
| `export [color] --to css\|tailwind\|dtcg [--source palette\|scale] [--tokens file.json]` | write tokens |
|
|
29
|
+
| `schema [command]` | print the JSON Schema of a command's options |
|
|
30
|
+
|
|
31
|
+
Colors are any CSS color: `#3b82f6`, `oklch(0.7 0.15 250)`, `color-mix(in oklab, red, blue)`. Add `--full` for every field. Run `color-map <command> --help` for one command.
|
|
32
|
+
|
|
33
|
+
## Rules
|
|
34
|
+
|
|
35
|
+
- Contrast is WCAG 2. There is no other contrast algorithm; do not look for an option for one.
|
|
36
|
+
- Pass colors as given; never round-trip them through hex when precision matters. Use `--to oklch` or `--format json`.
|
|
37
|
+
- A failed call exits 2 with a coded error (`invalid-color`, `unknown-option`, ...) on stdout. Fix the input named in the error and retry; retrying the same call cannot help.
|
|
38
|
+
- Nothing prompts, and an unknown flag fails instead of being ignored.
|
package/src/cli/bin.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs'
|
|
3
|
+
import { createApp } from './cli.js'
|
|
4
|
+
|
|
5
|
+
const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')) as { version: string }
|
|
6
|
+
|
|
7
|
+
createApp({ version })
|
|
8
|
+
.parse(process.argv)
|
|
9
|
+
.then((code) => {
|
|
10
|
+
if (typeof code === 'number') process.exitCode = code
|
|
11
|
+
})
|
package/src/cli/cli.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type cli as CliNamespace, cli } from 'clibuilder'
|
|
2
|
+
import { homeHeader, result } from 'clibuilder/axi'
|
|
3
|
+
import { contrast } from './commands/contrast.js'
|
|
4
|
+
import { convert } from './commands/convert.js'
|
|
5
|
+
import { exportCommand } from './commands/export.js'
|
|
6
|
+
import { findContrastCommand } from './commands/find-contrast.js'
|
|
7
|
+
import { harmony } from './commands/harmony.js'
|
|
8
|
+
import { mix } from './commands/mix.js'
|
|
9
|
+
import { palette } from './commands/palette.js'
|
|
10
|
+
import { scale } from './commands/scale.js'
|
|
11
|
+
import { schemaCommand } from './schema-command.js'
|
|
12
|
+
|
|
13
|
+
export const commands = [convert, mix, contrast, findContrastCommand, scale, palette, harmony, exportCommand] as const
|
|
14
|
+
|
|
15
|
+
const description = 'Color tools for agents: convert, mix, contrast, scale, palette and export'
|
|
16
|
+
|
|
17
|
+
/** The color-map CLI. Pass `streams` to capture its output. */
|
|
18
|
+
export function createApp(options: Pick<CliNamespace.Options, 'streams' | 'version'>) {
|
|
19
|
+
let app = cli({ name: 'color-map', description, version: options.version, streams: options.streams }).default({
|
|
20
|
+
description,
|
|
21
|
+
run() {
|
|
22
|
+
return result(
|
|
23
|
+
{
|
|
24
|
+
...homeHeader({ description }),
|
|
25
|
+
commands: [...commands.map((c) => c.name), 'schema'],
|
|
26
|
+
defaults: 'WCAG 2 contrast, sRGB gamut, TOON output (--format json for JSON)'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
help: [
|
|
30
|
+
"Run `color-map palette '#3b82f6'` for a semantic palette with every contrast pair checked",
|
|
31
|
+
"Run `color-map scale '#3b82f6'` for an 11-step scale",
|
|
32
|
+
'Run `color-map <command> --help` for one command'
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
for (const c of commands) app = app.command(c)
|
|
39
|
+
return app.command(schemaCommand(commands))
|
|
40
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type cli, command, t } from 'clibuilder'
|
|
2
|
+
import { result } from 'clibuilder/axi'
|
|
3
|
+
import { contrast as contrastOf, meets } from '../../color/index.js'
|
|
4
|
+
import { readColor, round } from '../shared.js'
|
|
5
|
+
|
|
6
|
+
const definition = command({
|
|
7
|
+
name: 'contrast',
|
|
8
|
+
description: 'WCAG 2 contrast ratio of a text color on a background, with the AA and AAA verdicts',
|
|
9
|
+
arguments: [
|
|
10
|
+
{ name: 'fg', description: 'The text (foreground) color', type: t.string() },
|
|
11
|
+
{ name: 'bg', description: 'The background color', type: t.string() }
|
|
12
|
+
],
|
|
13
|
+
run(args) {
|
|
14
|
+
const fg = readColor(args.fg, 'fg')
|
|
15
|
+
const bg = readColor(args.bg, 'bg')
|
|
16
|
+
const pass = (level: string) => meets(fg, bg, level)
|
|
17
|
+
const out = {
|
|
18
|
+
fg: args.fg,
|
|
19
|
+
bg: args.bg,
|
|
20
|
+
algorithm: 'wcag2',
|
|
21
|
+
ratio: round(contrastOf(fg, bg)),
|
|
22
|
+
AA: pass('AA'),
|
|
23
|
+
'AA-large': pass('AA-large'),
|
|
24
|
+
AAA: pass('AAA'),
|
|
25
|
+
'AAA-large': pass('AAA-large')
|
|
26
|
+
}
|
|
27
|
+
return result(out, {
|
|
28
|
+
help: out.AA
|
|
29
|
+
? undefined
|
|
30
|
+
: `Run \`color-map find-contrast '${args.bg}' --target 4.5\` for a text color that passes AA`
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
/** Typed as the plain command so its declaration does not name args-minus' internals. */
|
|
36
|
+
export const contrast: cli.Command = definition
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type cli, command, t } from 'clibuilder'
|
|
2
|
+
import { fullOption, result } from 'clibuilder/axi'
|
|
3
|
+
import { convert as convertColor, inGamut, toGamut } from '../../color/index.js'
|
|
4
|
+
import { describe, GAMUTS, readColor, SPACES } from '../shared.js'
|
|
5
|
+
|
|
6
|
+
const definition = command({
|
|
7
|
+
name: 'convert',
|
|
8
|
+
description: 'Convert a CSS color to another color space',
|
|
9
|
+
arguments: [
|
|
10
|
+
{ name: 'color', description: 'Any CSS color, such as "#3b82f6" or "oklch(0.7 0.15 250)"', type: t.string() }
|
|
11
|
+
],
|
|
12
|
+
options: {
|
|
13
|
+
to: { description: 'Target color space', type: t.enum([...SPACES]), default: 'srgb' },
|
|
14
|
+
gamut: {
|
|
15
|
+
description: 'Map the result into this gamut (CSS gamut mapping) when it falls outside',
|
|
16
|
+
type: t.enum([...GAMUTS]).optional()
|
|
17
|
+
},
|
|
18
|
+
full: fullOption
|
|
19
|
+
},
|
|
20
|
+
run(args) {
|
|
21
|
+
const input = readColor(args.color)
|
|
22
|
+
const converted = convertColor(input, args.to)
|
|
23
|
+
const mapped = args.gamut ? toGamut(converted, { gamut: args.gamut }) : converted
|
|
24
|
+
const out = {
|
|
25
|
+
input: args.color,
|
|
26
|
+
to: args.to,
|
|
27
|
+
...describe(mapped, args.full === true),
|
|
28
|
+
...(args.full ? { inSrgb: inGamut(mapped, 'srgb'), inDisplayP3: inGamut(mapped, 'display-p3') } : {})
|
|
29
|
+
}
|
|
30
|
+
return result(out, {
|
|
31
|
+
help: `Run \`color-map mix '${args.color}' '<other color>'\` to blend it with another color`
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
/** Typed as the plain command so its declaration does not name args-minus' internals. */
|
|
37
|
+
export const convert: cli.Command = definition
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { type cli, command, t } from 'clibuilder'
|
|
3
|
+
import { CliError, document, exitCodes, isCliError } from 'clibuilder/axi'
|
|
4
|
+
import type { ColorSpaceId } from '../../color/index.js'
|
|
5
|
+
import { semanticPalette } from '../../palette/index.js'
|
|
6
|
+
import { createScale } from '../../scale/index.js'
|
|
7
|
+
import { toCssVariables, toDtcg, toTailwindTheme } from '../../tokens/index.js'
|
|
8
|
+
import { EXPORT_SOURCES, EXPORT_TARGETS, MODES, readColor, SPACES } from '../shared.js'
|
|
9
|
+
|
|
10
|
+
function usage(code: string, message: string, help: string, details: CliError.Details = {}) {
|
|
11
|
+
return new CliError(message, { code, exitCode: exitCodes.usage, details, help })
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function readTokens(path: string): unknown {
|
|
15
|
+
let text: string
|
|
16
|
+
try {
|
|
17
|
+
text = readFileSync(path, 'utf8')
|
|
18
|
+
} catch {
|
|
19
|
+
throw usage(
|
|
20
|
+
'file-not-found',
|
|
21
|
+
`cannot read the token file "${path}"`,
|
|
22
|
+
'Pass a JSON file of CSS color strings, nested as you like',
|
|
23
|
+
{ path }
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(text)
|
|
28
|
+
} catch {
|
|
29
|
+
throw usage(
|
|
30
|
+
'invalid-json',
|
|
31
|
+
`"${path}" is not valid JSON`,
|
|
32
|
+
'Pass a JSON file of CSS color strings, nested as you like',
|
|
33
|
+
{ path }
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const definition = command({
|
|
39
|
+
name: 'export',
|
|
40
|
+
description: 'Write a palette, a scale or your own tokens as DTCG JSON, CSS variables or a Tailwind v4 theme',
|
|
41
|
+
arguments: [
|
|
42
|
+
{
|
|
43
|
+
name: 'color',
|
|
44
|
+
description: 'The brand color to build tokens from; leave out with --tokens',
|
|
45
|
+
type: t.string().optional()
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
options: {
|
|
49
|
+
to: { description: 'Output format', type: t.enum([...EXPORT_TARGETS]), default: 'css' },
|
|
50
|
+
source: { description: 'What to build from the color', type: t.enum([...EXPORT_SOURCES]), default: 'palette' },
|
|
51
|
+
mode: { description: 'light or dark, for --source palette', type: t.enum([...MODES]), default: 'light' },
|
|
52
|
+
tokens: {
|
|
53
|
+
description: 'A JSON file of CSS color strings, nested as you like, instead of a color',
|
|
54
|
+
type: t.string().optional()
|
|
55
|
+
},
|
|
56
|
+
space: { description: 'Convert every color to this space (css, tailwind)', type: t.enum([...SPACES]).optional() },
|
|
57
|
+
prefix: { description: 'Variable name prefix (css; tailwind uses --namespace)', type: t.string().optional() },
|
|
58
|
+
selector: { description: 'The CSS rule selector (css)', type: t.string().optional() },
|
|
59
|
+
namespace: { description: 'The Tailwind theme namespace (tailwind)', type: t.string().optional() },
|
|
60
|
+
inline: { description: 'Write @theme inline (tailwind)', type: t.boolean().optional() },
|
|
61
|
+
precision: { description: 'Decimal places in printed numbers', type: t.int({ min: 0, max: 10 }).optional() },
|
|
62
|
+
hex: { description: 'Add the hex fallback to DTCG values; --hex=false drops it', type: t.boolean().optional() }
|
|
63
|
+
},
|
|
64
|
+
run(args) {
|
|
65
|
+
if ((args.color === undefined) === (args.tokens === undefined))
|
|
66
|
+
throw usage(
|
|
67
|
+
'input-required',
|
|
68
|
+
'give exactly one of a color or --tokens <file>',
|
|
69
|
+
"Run `color-map export '#3b82f6' --to css`, or `color-map export --tokens tokens.json --to dtcg`"
|
|
70
|
+
)
|
|
71
|
+
try {
|
|
72
|
+
const space = args.space as ColorSpaceId | undefined
|
|
73
|
+
let tree: Parameters<typeof toDtcg>[0]
|
|
74
|
+
if (args.tokens !== undefined) tree = readTokens(args.tokens) as typeof tree
|
|
75
|
+
else {
|
|
76
|
+
const color = readColor(args.color as string)
|
|
77
|
+
tree =
|
|
78
|
+
args.source === 'scale'
|
|
79
|
+
? { primary: createScale({ seed: color }) }
|
|
80
|
+
: semanticPalette({ brand: color, mode: args.mode })
|
|
81
|
+
}
|
|
82
|
+
if (args.to === 'dtcg') return document(`${JSON.stringify(toDtcg(tree, { hex: args.hex }), null, 2)}\n`)
|
|
83
|
+
if (args.to === 'css')
|
|
84
|
+
return document(
|
|
85
|
+
toCssVariables(tree, { space, prefix: args.prefix, selector: args.selector, precision: args.precision })
|
|
86
|
+
)
|
|
87
|
+
return document(
|
|
88
|
+
toTailwindTheme(tree, { space, namespace: args.namespace, inline: args.inline, precision: args.precision })
|
|
89
|
+
)
|
|
90
|
+
} catch (e) {
|
|
91
|
+
if (isCliError(e)) throw e
|
|
92
|
+
throw usage(
|
|
93
|
+
'export-failed',
|
|
94
|
+
(e as Error).message,
|
|
95
|
+
'The tokens must be CSS color strings, color objects, or arrays and objects of them'
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
/** Typed as the plain command so its declaration does not name args-minus' internals. */
|
|
102
|
+
export const exportCommand: cli.Command = definition
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type cli, command, t } from 'clibuilder'
|
|
2
|
+
import { fullOption, result } from 'clibuilder/axi'
|
|
3
|
+
import { findContrast } from '../../color/index.js'
|
|
4
|
+
import { describe, readColor, round } from '../shared.js'
|
|
5
|
+
|
|
6
|
+
const definition = command({
|
|
7
|
+
name: 'find-contrast',
|
|
8
|
+
description: 'Find the color closest in lightness to a background that reaches a WCAG 2 contrast target',
|
|
9
|
+
arguments: [{ name: 'bg', description: 'The background color', type: t.string() }],
|
|
10
|
+
options: {
|
|
11
|
+
target: { description: 'The contrast ratio to reach, 1 to 21', type: t.number({ min: 1, max: 21 }), default: 4.5 },
|
|
12
|
+
hue: {
|
|
13
|
+
description: "OKLCH hue of the result in degrees (default: the background's hue)",
|
|
14
|
+
type: t.number().optional()
|
|
15
|
+
},
|
|
16
|
+
chroma: { description: 'OKLCH chroma of the result (default 0, a gray)', type: t.number({ min: 0 }).optional() },
|
|
17
|
+
direction: { description: 'Which way to look first', type: t.enum(['lighter', 'darker']).optional() },
|
|
18
|
+
full: fullOption
|
|
19
|
+
},
|
|
20
|
+
run(args) {
|
|
21
|
+
const found = findContrast(readColor(args.bg, 'bg'), args.target, {
|
|
22
|
+
hue: args.hue,
|
|
23
|
+
chroma: args.chroma,
|
|
24
|
+
direction: args.direction
|
|
25
|
+
})
|
|
26
|
+
return result({
|
|
27
|
+
bg: args.bg,
|
|
28
|
+
target: args.target,
|
|
29
|
+
...describe(found.color, args.full === true),
|
|
30
|
+
ratio: round(found.contrast),
|
|
31
|
+
met: found.met
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
/** Typed as the plain command so its declaration does not name args-minus' internals. */
|
|
37
|
+
export const findContrastCommand: cli.Command = definition
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type cli, command, t } from 'clibuilder'
|
|
2
|
+
import { result } from 'clibuilder/axi'
|
|
3
|
+
import { toCss, toHex } from '../../color/index.js'
|
|
4
|
+
import { harmony as harmonyOf } from '../../palette/index.js'
|
|
5
|
+
import { GAMUTS, POLAR_SPACES, readColor } from '../shared.js'
|
|
6
|
+
|
|
7
|
+
export const SCHEMES = ['complementary', 'split', 'analogous', 'triadic', 'tetradic'] as const
|
|
8
|
+
|
|
9
|
+
const definition = command({
|
|
10
|
+
name: 'harmony',
|
|
11
|
+
description: 'The colors of a harmony scheme: the color rotated around the hue wheel',
|
|
12
|
+
arguments: [{ name: 'color', description: 'The base color', type: t.string() }],
|
|
13
|
+
options: {
|
|
14
|
+
scheme: { description: 'The harmony scheme', type: t.enum([...SCHEMES]), default: 'complementary' },
|
|
15
|
+
space: { description: 'The space whose hue is rotated', type: t.enum([...POLAR_SPACES]), default: 'oklch' },
|
|
16
|
+
gamut: { description: 'The gamut every color must fit', type: t.enum([...GAMUTS]), default: 'srgb' }
|
|
17
|
+
},
|
|
18
|
+
run(args) {
|
|
19
|
+
const colors = harmonyOf(readColor(args.color), args.scheme, { space: args.space, gamut: args.gamut })
|
|
20
|
+
return result({
|
|
21
|
+
color: args.color,
|
|
22
|
+
scheme: args.scheme,
|
|
23
|
+
space: args.space,
|
|
24
|
+
colors: colors.map((c, i) => ({ index: i + 1, hex: toHex(c), css: toCss(c) }))
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
/** Typed as the plain command so its declaration does not name args-minus' internals. */
|
|
30
|
+
export const harmony: cli.Command = definition
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type cli, command, t } from 'clibuilder'
|
|
2
|
+
import { fullOption, result } from 'clibuilder/axi'
|
|
3
|
+
import { mix as mixColors } from '../../color/index.js'
|
|
4
|
+
import { describe, HUE_METHODS, readColor, SPACES } from '../shared.js'
|
|
5
|
+
|
|
6
|
+
const definition = command({
|
|
7
|
+
name: 'mix',
|
|
8
|
+
description: 'Mix two CSS colors, as color-mix() does',
|
|
9
|
+
arguments: [
|
|
10
|
+
{ name: 'a', description: 'The first color', type: t.string() },
|
|
11
|
+
{ name: 'b', description: 'The second color', type: t.string() }
|
|
12
|
+
],
|
|
13
|
+
options: {
|
|
14
|
+
amount: { description: 'How far from a to b, 0 to 1', type: t.number({ min: 0, max: 1 }), default: 0.5 },
|
|
15
|
+
in: { description: 'The space to interpolate in', type: t.enum([...SPACES]), default: 'oklab' },
|
|
16
|
+
hue: { description: 'How hues travel in a polar space', type: t.enum([...HUE_METHODS]), default: 'shorter' },
|
|
17
|
+
full: fullOption
|
|
18
|
+
},
|
|
19
|
+
run(args) {
|
|
20
|
+
const mixed = mixColors(readColor(args.a, 'a'), readColor(args.b, 'b'), args.amount, { in: args.in, hue: args.hue })
|
|
21
|
+
return result(
|
|
22
|
+
{ a: args.a, b: args.b, amount: args.amount, in: args.in, ...describe(mixed, args.full === true) },
|
|
23
|
+
{ help: `Run \`color-map contrast '${describe(mixed, false).hex}' '#ffffff'\` to check it against white` }
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
/** Typed as the plain command so its declaration does not name args-minus' internals. */
|
|
29
|
+
export const mix: cli.Command = definition
|