@tokens-studio/tokenscript-schemas 0.1.1 → 0.1.3

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 (105) hide show
  1. package/README.md +31 -7
  2. package/dist/cli/index.cjs +21 -35
  3. package/dist/cli/index.cjs.map +1 -1
  4. package/dist/cli/index.js +21 -35
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/index.cjs +19 -19
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +3 -3
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +19 -19
  11. package/dist/index.js.map +1 -1
  12. package/package.json +3 -3
  13. package/src/bundler/{bundle-schema.ts → build-schema.ts} +2 -2
  14. package/src/bundler/index.ts +25 -25
  15. package/src/bundler/schema-dependency-resolver.ts +3 -3
  16. package/src/bundler/selective-bundler.ts +3 -3
  17. package/src/cli/commands/bundle.test.ts +95 -1
  18. package/src/cli/commands/bundle.ts +11 -1
  19. package/src/cli/index.ts +1 -0
  20. package/src/cli/version-info.ts +16 -18
  21. package/bundled/functions/adjust_chroma.json +0 -60
  22. package/bundled/functions/adjust_hue.json +0 -60
  23. package/bundled/functions/adjust_lightness.json +0 -60
  24. package/bundled/functions/adjust_to_contrast.json +0 -67
  25. package/bundled/functions/alpha_blend.json +0 -31
  26. package/bundled/functions/alpha_scale.json +0 -27
  27. package/bundled/functions/analogous.json +0 -32
  28. package/bundled/functions/apca_contrast.json +0 -27
  29. package/bundled/functions/are_similar.json +0 -73
  30. package/bundled/functions/auto_text_color.json +0 -66
  31. package/bundled/functions/best_contrast.json +0 -28
  32. package/bundled/functions/chroma.json +0 -54
  33. package/bundled/functions/clamp_chroma.json +0 -66
  34. package/bundled/functions/clamp_lightness.json +0 -66
  35. package/bundled/functions/clamp_to_gamut.json +0 -23
  36. package/bundled/functions/complement.json +0 -24
  37. package/bundled/functions/contrast_ratio.json +0 -27
  38. package/bundled/functions/cooler.json +0 -52
  39. package/bundled/functions/darken.json +0 -28
  40. package/bundled/functions/delta_e_2000.json +0 -40
  41. package/bundled/functions/delta_e_76.json +0 -27
  42. package/bundled/functions/delta_e_ok.json +0 -27
  43. package/bundled/functions/desaturate.json +0 -28
  44. package/bundled/functions/distributed.json +0 -36
  45. package/bundled/functions/diverging.json +0 -36
  46. package/bundled/functions/grayscale.json +0 -24
  47. package/bundled/functions/harmonize.json +0 -65
  48. package/bundled/functions/hue.json +0 -54
  49. package/bundled/functions/hue_difference.json +0 -27
  50. package/bundled/functions/in_gamut.json +0 -27
  51. package/bundled/functions/interpolate.json +0 -66
  52. package/bundled/functions/invert.json +0 -23
  53. package/bundled/functions/is_cool.json +0 -23
  54. package/bundled/functions/is_dark.json +0 -27
  55. package/bundled/functions/is_light.json +0 -27
  56. package/bundled/functions/is_neutral.json +0 -65
  57. package/bundled/functions/is_warm.json +0 -23
  58. package/bundled/functions/lighten.json +0 -28
  59. package/bundled/functions/lightness.json +0 -61
  60. package/bundled/functions/luminance.json +0 -23
  61. package/bundled/functions/meets_contrast.json +0 -31
  62. package/bundled/functions/mix.json +0 -32
  63. package/bundled/functions/monochromatic.json +0 -28
  64. package/bundled/functions/muted.json +0 -59
  65. package/bundled/functions/neutral_variant.json +0 -59
  66. package/bundled/functions/relative_luminance.json +0 -61
  67. package/bundled/functions/rotate_hue.json +0 -28
  68. package/bundled/functions/saturate.json +0 -28
  69. package/bundled/functions/scale_chroma.json +0 -60
  70. package/bundled/functions/scale_lightness.json +0 -60
  71. package/bundled/functions/sepia.json +0 -59
  72. package/bundled/functions/set_chroma.json +0 -28
  73. package/bundled/functions/set_hue.json +0 -28
  74. package/bundled/functions/set_lightness.json +0 -28
  75. package/bundled/functions/shade_scale.json +0 -28
  76. package/bundled/functions/split_complement.json +0 -28
  77. package/bundled/functions/steps.json +0 -32
  78. package/bundled/functions/tetradic.json +0 -24
  79. package/bundled/functions/tint_scale.json +0 -36
  80. package/bundled/functions/to_gamut.json +0 -59
  81. package/bundled/functions/triadic.json +0 -24
  82. package/bundled/functions/vibrant.json +0 -59
  83. package/bundled/functions/warmer.json +0 -52
  84. package/bundled/functions/wcag_level.json +0 -60
  85. package/bundled/functions.json +0 -2624
  86. package/bundled/registry.json +0 -3833
  87. package/bundled/types/css-color.json +0 -151
  88. package/bundled/types/hex-color.json +0 -25
  89. package/bundled/types/hsl-color.json +0 -66
  90. package/bundled/types/hsv-color.json +0 -57
  91. package/bundled/types/hwb-color.json +0 -66
  92. package/bundled/types/lab-color.json +0 -57
  93. package/bundled/types/lch-color.json +0 -57
  94. package/bundled/types/okhsl-color.json +0 -57
  95. package/bundled/types/okhsv-color.json +0 -57
  96. package/bundled/types/oklab-color.json +0 -87
  97. package/bundled/types/oklch-color.json +0 -57
  98. package/bundled/types/p3-color.json +0 -57
  99. package/bundled/types/p3-linear-color.json +0 -57
  100. package/bundled/types/rgb-color.json +0 -73
  101. package/bundled/types/srgb-color.json +0 -77
  102. package/bundled/types/srgb-linear-color.json +0 -67
  103. package/bundled/types/xyz-d50-color.json +0 -57
  104. package/bundled/types/xyz-d65-color.json +0 -77
  105. package/bundled/types.json +0 -1207
@@ -1,28 +0,0 @@
1
- {
2
- "name": "Set Hue",
3
- "type": "function",
4
- "description": "Sets a color's hue to a specific angle in OKLCH space. Preserves lightness and chroma.",
5
- "keyword": "set_hue",
6
- "input": {
7
- "type": "object",
8
- "properties": {
9
- "color": {
10
- "type": "color",
11
- "description": "The color to modify"
12
- },
13
- "hue": {
14
- "type": "number",
15
- "description": "Target hue angle (0-360)"
16
- }
17
- }
18
- },
19
- "script": {
20
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
21
- "script": "// Set a color's hue to a specific angle\n// Preserves lightness and chroma\n\nvariable input: List = {input};\nvariable color: Color.OKLCH = input.get(0).to.oklch();\nvariable target_h: Number = input.get(1);\n\n// Normalize to 0-360\nwhile (target_h >= 360) [ target_h = target_h - 360; ];\nwhile (target_h < 0) [ target_h = target_h + 360; ];\n\nvariable result: Color.OKLCH;\nresult.l = color.l;\nresult.c = color.c;\nresult.h = target_h;\n\nreturn result;"
22
- },
23
- "requirements": [
24
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
25
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/"
26
- ],
27
- "slug": "set_hue"
28
- }
@@ -1,28 +0,0 @@
1
- {
2
- "name": "Set Lightness",
3
- "type": "function",
4
- "description": "Sets a color's lightness to a specific value in OKLCH space. Preserves hue and chroma.",
5
- "keyword": "set_lightness",
6
- "input": {
7
- "type": "object",
8
- "properties": {
9
- "color": {
10
- "type": "color",
11
- "description": "The color to modify"
12
- },
13
- "lightness": {
14
- "type": "number",
15
- "description": "Target lightness (0-1)"
16
- }
17
- }
18
- },
19
- "script": {
20
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
21
- "script": "// Set a color's lightness to a specific value\n// Preserves hue and chroma\n\nvariable input: List = {input};\nvariable color: Color.OKLCH = input.get(0).to.oklch();\nvariable target_l: Number = input.get(1);\n\n// Clamp to valid range\nif (target_l < 0) [ target_l = 0; ];\nif (target_l > 1) [ target_l = 1; ];\n\nvariable result: Color.OKLCH;\nresult.l = target_l;\nresult.c = color.c;\nresult.h = color.h;\n\nreturn result;"
22
- },
23
- "requirements": [
24
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
25
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/"
26
- ],
27
- "slug": "set_lightness"
28
- }
@@ -1,28 +0,0 @@
1
- {
2
- "name": "Shade Scale",
3
- "type": "function",
4
- "description": "Generates a Tailwind/Material-style shade scale from 50 (lightest) to 900 (darkest). The input color becomes the 500 (middle) value. Perfect for design system color tokens.",
5
- "keyword": "shade_scale",
6
- "input": {
7
- "type": "object",
8
- "properties": {
9
- "color": {
10
- "type": "color",
11
- "description": "Base color (becomes the 500 shade)"
12
- },
13
- "count": {
14
- "type": "number",
15
- "description": "Number of shades. Default is 10 (50-900)"
16
- }
17
- }
18
- },
19
- "script": {
20
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
21
- "script": "// Generate a design system shade scale (like Tailwind 50-900)\n// Input color becomes the middle (500) shade\n//\n// Lightness distribution:\n// 50: ~0.97 (very light)\n// 100: ~0.93\n// 200: ~0.87\n// 300: ~0.78\n// 400: ~0.67\n// 500: input lightness (base)\n// 600: ~0.52\n// 700: ~0.42\n// 800: ~0.32\n// 900: ~0.22 (very dark)\n//\n// Chroma is scaled to avoid washed-out lights and muddy darks\n\nvariable input: List = {input};\nvariable base: Color.OKLCH = input.get(0).to.oklch();\n\nvariable count: Number = 10;\nif (input.length() > 1) [\n count = input.get(1);\n];\n\n// Target lightness values for standard 10-step scale\n// These are perceptually optimized for OKLCH\nvariable lightness_targets: List = 0.97, 0.93, 0.87, 0.78, 0.67, 0.55, 0.45, 0.35, 0.27, 0.20;\n\nvariable base_h: Number = base.h;\nvariable base_c: Number = base.c;\n\nvariable result: List;\nvariable i: Number = 0;\nvariable target_l: Number = 0;\nvariable l_factor: Number = 0;\nvariable scaled_c: Number = 0;\nvariable shade: Color.OKLCH;\n\nwhile (i < count) [\n target_l = lightness_targets.get(i);\n \n // Scale chroma based on lightness\n // Chroma peaks in midtones, reduces at extremes\n l_factor = 1 - abs(target_l - 0.55) * 1.2;\n if (l_factor < 0.3) [ l_factor = 0.3; ];\n if (l_factor > 1.2) [ l_factor = 1.2; ];\n \n scaled_c = base_c * l_factor;\n if (scaled_c > 0.4) [ scaled_c = 0.4; ];\n \n shade.l = target_l;\n shade.c = scaled_c;\n shade.h = base_h;\n \n result = result, shade.to.srgb();\n i = i + 1;\n];\n\nreturn result;"
22
- },
23
- "requirements": [
24
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
25
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/"
26
- ],
27
- "slug": "shade_scale"
28
- }
@@ -1,28 +0,0 @@
1
- {
2
- "name": "Split Complement",
3
- "type": "function",
4
- "description": "Generates split-complementary colors - base color plus two colors adjacent to its complement. More nuanced than direct complement, less tension than triadic.",
5
- "keyword": "split_complement",
6
- "input": {
7
- "type": "object",
8
- "properties": {
9
- "color": {
10
- "type": "color",
11
- "description": "Base color"
12
- },
13
- "angle": {
14
- "type": "number",
15
- "description": "Degrees from complement for split colors. Default is 30"
16
- }
17
- }
18
- },
19
- "script": {
20
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
21
- "script": "// Generate split-complementary colors\n// Returns [base, complement-angle, complement+angle]\n//\n// Use case: Balanced contrast with more variety than complement\n// Example: Blue → Orange-Red, Orange-Yellow (instead of just Orange)\n\nvariable input: List = {input};\nvariable base: Color.OKLCH = input.get(0).to.oklch();\n\nvariable angle: Number = 30;\nif (input.length() > 1) [\n angle = input.get(1);\n];\n\nvariable complement_h: Number = base.h + 180;\nif (complement_h >= 360) [ complement_h = complement_h - 360; ];\n\nvariable result: List;\n\n// Base color\nresult = result, base.to.srgb();\n\n// Complement - angle\nvariable h2: Number = complement_h - angle;\nif (h2 < 0) [ h2 = h2 + 360; ];\nvariable c2: Color.OKLCH;\nc2.l = base.l; c2.c = base.c; c2.h = h2;\nresult = result, c2.to.srgb();\n\n// Complement + angle\nvariable h3: Number = complement_h + angle;\nif (h3 >= 360) [ h3 = h3 - 360; ];\nvariable c3: Color.OKLCH;\nc3.l = base.l; c3.c = base.c; c3.h = h3;\nresult = result, c3.to.srgb();\n\nreturn result;"
22
- },
23
- "requirements": [
24
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
25
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/"
26
- ],
27
- "slug": "split_complement"
28
- }
@@ -1,32 +0,0 @@
1
- {
2
- "name": "Steps",
3
- "type": "function",
4
- "description": "Generates a list of colors interpolated between two colors in OKLCH space. Perfect for gradient stops.",
5
- "keyword": "steps",
6
- "input": {
7
- "type": "object",
8
- "properties": {
9
- "color1": {
10
- "type": "color",
11
- "description": "Start color"
12
- },
13
- "color2": {
14
- "type": "color",
15
- "description": "End color"
16
- },
17
- "count": {
18
- "type": "number",
19
- "description": "Number of steps (including start and end). Default is 5"
20
- }
21
- }
22
- },
23
- "script": {
24
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
25
- "script": "// Generate gradient steps between two colors in OKLCH space\n// Returns a List of colors from start to end (inclusive)\n//\n// Uses perceptually uniform interpolation with shortest hue path\n\nvariable input: List = {input};\nvariable color1: Color.OKLCH = input.get(0).to.oklch();\nvariable color2: Color.OKLCH = input.get(1).to.oklch();\n\n// Default count is 5\nvariable count: Number = 5;\nif (input.length() > 2) [\n count = input.get(2);\n];\n\n// Calculate hue difference (shortest path)\nvariable h1: Number = color1.h;\nvariable h2: Number = color2.h;\nvariable h_diff: Number = h2 - h1;\nif (h_diff > 180) [ h_diff = h_diff - 360; ];\nif (h_diff < -180) [ h_diff = h_diff + 360; ];\n\n// Generate steps\nvariable result: List;\nvariable i: Number = 0;\nvariable t: Number = 0;\nvariable step_l: Number = 0;\nvariable step_c: Number = 0;\nvariable step_h: Number = 0;\nvariable step_color: Color.OKLCH;\n\nwhile (i < count) [\n t = i / (count - 1);\n \n // Interpolate each component\n step_l = color1.l + (color2.l - color1.l) * t;\n step_c = color1.c + (color2.c - color1.c) * t;\n step_h = h1 + h_diff * t;\n \n // Normalize hue\n if (step_h < 0) [ step_h = step_h + 360; ];\n if (step_h >= 360) [ step_h = step_h - 360; ];\n \n // Create color and add to list\n step_color.l = step_l;\n step_color.c = step_c;\n step_color.h = step_h;\n \n result = result, step_color.to.srgb();\n i = i + 1;\n];\n\nreturn result;"
26
- },
27
- "requirements": [
28
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
29
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/"
30
- ],
31
- "slug": "steps"
32
- }
@@ -1,24 +0,0 @@
1
- {
2
- "name": "Tetradic",
3
- "type": "function",
4
- "description": "Generates tetradic (square) colors - four hues equally spaced 90° apart. Creates rich, complex palettes with two complementary pairs.",
5
- "keyword": "tetradic",
6
- "input": {
7
- "type": "object",
8
- "properties": {
9
- "color": {
10
- "type": "color",
11
- "description": "Base color"
12
- }
13
- }
14
- },
15
- "script": {
16
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
17
- "script": "// Generate tetradic (square) colors (90° apart)\n// Returns [base, base+90°, base+180°, base+270°]\n//\n// Use case: Rich, complex palettes\n// Contains two complementary pairs\n\nvariable input: List = {input};\nvariable base: Color.OKLCH = input.get(0).to.oklch();\n\nvariable result: List;\n\n// Base color (0°)\nresult = result, base.to.srgb();\n\n// +90°\nvariable h2: Number = base.h + 90;\nif (h2 >= 360) [ h2 = h2 - 360; ];\nvariable c2: Color.OKLCH;\nc2.l = base.l; c2.c = base.c; c2.h = h2;\nresult = result, c2.to.srgb();\n\n// +180° (complement)\nvariable h3: Number = base.h + 180;\nif (h3 >= 360) [ h3 = h3 - 360; ];\nvariable c3: Color.OKLCH;\nc3.l = base.l; c3.c = base.c; c3.h = h3;\nresult = result, c3.to.srgb();\n\n// +270°\nvariable h4: Number = base.h + 270;\nif (h4 >= 360) [ h4 = h4 - 360; ];\nvariable c4: Color.OKLCH;\nc4.l = base.l; c4.c = base.c; c4.h = h4;\nresult = result, c4.to.srgb();\n\nreturn result;"
18
- },
19
- "requirements": [
20
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
21
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/"
22
- ],
23
- "slug": "tetradic"
24
- }
@@ -1,36 +0,0 @@
1
- {
2
- "name": "Tint Scale",
3
- "type": "function",
4
- "description": "Creates a sequential scale of tints from a base color. Varies lightness while preserving hue and adjusting chroma proportionally. Perfect for sequential/quantitative data visualization.",
5
- "keyword": "tint_scale",
6
- "input": {
7
- "type": "object",
8
- "properties": {
9
- "color": {
10
- "type": "color",
11
- "description": "Base color for the scale"
12
- },
13
- "count": {
14
- "type": "number",
15
- "description": "Number of tints to generate. Default is 9"
16
- },
17
- "light_start": {
18
- "type": "number",
19
- "description": "Lightness of lightest tint (0-1). Default is 0.95"
20
- },
21
- "light_end": {
22
- "type": "number",
23
- "description": "Lightness of darkest tint (0-1). Default is 0.25"
24
- }
25
- }
26
- },
27
- "script": {
28
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
29
- "script": "// Create a sequential tint scale from a base color\n// Varies lightness while preserving hue and scaling chroma\n//\n// Ideal for: choropleth maps, intensity scales, single-hue heatmaps\n// Chroma is scaled proportionally to maintain color harmony\n\nvariable input: List = {input};\nvariable base: Color.OKLCH = input.get(0).to.oklch();\n\n// Default count is 9\nvariable count: Number = 9;\nif (input.length() > 1) [\n count = input.get(1);\n];\n\n// Default light_start is 0.95 (nearly white)\nvariable light_start: Number = 0.95;\nif (input.length() > 2) [\n light_start = input.get(2);\n];\n\n// Default light_end is 0.25 (dark)\nvariable light_end: Number = 0.25;\nif (input.length() > 3) [\n light_end = input.get(3);\n];\n\n// Base color properties\nvariable base_h: Number = base.h;\nvariable base_c: Number = base.c;\nvariable base_l: Number = base.l;\n\n// Calculate chroma scaling factor (chroma decreases at extreme lightness)\nvariable max_c: Number = base_c * 1.2;\n\nvariable result: List;\nvariable i: Number = 0;\nvariable t: Number = 0;\nvariable step_l: Number = 0;\nvariable l_dist: Number = 0;\nvariable chroma_scale: Number = 0;\nvariable step_c: Number = 0;\nvariable color: Color.OKLCH;\n\nwhile (i < count) [\n t = i / (count - 1);\n \n // Interpolate lightness\n step_l = light_start + (light_end - light_start) * t;\n \n // Scale chroma based on lightness distance from optimal (~0.6)\n // Chroma is highest in midtones, lower at extremes\n l_dist = step_l - 0.6;\n if (l_dist < 0) [ l_dist = 0 - l_dist; ];\n chroma_scale = 1 - l_dist * 1.5;\n if (chroma_scale < 0.1) [ chroma_scale = 0.1; ];\n step_c = max_c * chroma_scale;\n \n // Clamp chroma\n if (step_c > 0.4) [ step_c = 0.4; ];\n \n color.l = step_l;\n color.c = step_c;\n color.h = base_h;\n \n result = result, color.to.srgb();\n i = i + 1;\n];\n\nreturn result;"
30
- },
31
- "requirements": [
32
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
33
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/"
34
- ],
35
- "slug": "tint_scale"
36
- }
@@ -1,59 +0,0 @@
1
- {
2
- "name": "to_gamut",
3
- "type": "function",
4
- "description": "Maps a color into a target gamut using the CSS Color Level 4 gamut mapping algorithm. This preserves the perceptual lightness and hue while reducing chroma until the color fits within the target color space. Uses OKLCH for perceptually uniform mapping and binary search with Delta E OK for convergence. Essential for wide-gamut to sRGB conversion in design systems.",
5
- "keyword": "to_gamut",
6
- "requirements": [
7
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/",
8
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/"
9
- ],
10
- "schema": {
11
- "type": "object",
12
- "properties": {
13
- "input": {
14
- "type": "array",
15
- "items": [
16
- {
17
- "description": "Color to map into gamut",
18
- "type": "color"
19
- },
20
- {
21
- "description": "Target gamut/space (default 'srgb')",
22
- "type": "string"
23
- }
24
- ],
25
- "minItems": 1,
26
- "maxItems": 2
27
- }
28
- },
29
- "required": [
30
- "input"
31
- ]
32
- },
33
- "returns": {
34
- "type": "color",
35
- "description": "Color mapped into the target gamut"
36
- },
37
- "script": {
38
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
39
- "script": "// to_gamut: Perceptual gamut mapping (CSS Color Level 4 algorithm)\n// Reference: CSS Color Level 4, Section 13.2 Gamut Mapping\n// Reference: https://www.w3.org/TR/css-color-4/#gamut-mapping\n//\n// Maps out-of-gamut colors into sRGB while preserving perceptual\n// intent. Uses OKLCH space with binary search on chroma:\n// - Lightness and hue are preserved\n// - Chroma is reduced until the color fits in gamut\n//\n// This is the CSS Gamut Mapping Algorithm (GMA) used by browsers.\n\nvariable input: List = {input};\nvariable color: Color.OKLCH = input.get(0).to.oklch();\n\n// Target space (default sRGB) - currently only supports sRGB\nvariable target_space: String = \"srgb\";\nif (input.length() > 1) [\n target_space = input.get(1);\n];\n\n// Constants\nvariable epsilon: Number = 0.0001;\nvariable neg_epsilon: Number = 0 - epsilon;\nvariable one_plus_eps: Number = 1 + epsilon;\n\n// Check if already in gamut by converting and checking bounds\nvariable test_color: Color.SRGB = color.to.srgb();\nvariable in_gamut: Boolean = true;\n\n// Check if sRGB values are in range [0, 1]\nif (test_color.r < neg_epsilon) [ in_gamut = false; ];\nif (test_color.r > one_plus_eps) [ in_gamut = false; ];\nif (test_color.g < neg_epsilon) [ in_gamut = false; ];\nif (test_color.g > one_plus_eps) [ in_gamut = false; ];\nif (test_color.b < neg_epsilon) [ in_gamut = false; ];\nif (test_color.b > one_plus_eps) [ in_gamut = false; ];\n\n// If already in gamut, return clamped version\nif (in_gamut) [\n variable clamped: Color.SRGB;\n clamped.r = min(1, max(0, test_color.r));\n clamped.g = min(1, max(0, test_color.g));\n clamped.b = min(1, max(0, test_color.b));\n return clamped;\n];\n\n// Binary search: reduce chroma until in gamut\nvariable min_c: Number = 0;\nvariable max_c: Number = color.c;\nvariable current: Color.OKLCH;\ncurrent.l = color.l;\ncurrent.h = color.h;\n\nvariable iterations: Number = 0;\nvariable max_iterations: Number = 25;\n\nwhile (max_c - min_c > epsilon) [\n if (iterations >= max_iterations) [\n max_c = min_c; // Force exit\n ];\n \n variable mid_c: Number = (min_c + max_c) / 2;\n current.c = mid_c;\n \n variable test: Color.SRGB = current.to.srgb();\n variable test_in_gamut: Boolean = true;\n \n if (test.r < neg_epsilon) [ test_in_gamut = false; ];\n if (test.r > one_plus_eps) [ test_in_gamut = false; ];\n if (test.g < neg_epsilon) [ test_in_gamut = false; ];\n if (test.g > one_plus_eps) [ test_in_gamut = false; ];\n if (test.b < neg_epsilon) [ test_in_gamut = false; ];\n if (test.b > one_plus_eps) [ test_in_gamut = false; ];\n \n if (test_in_gamut) [\n // We can try higher chroma\n min_c = mid_c;\n ] else [\n // Need to reduce chroma\n max_c = mid_c;\n ];\n \n iterations = iterations + 1;\n];\n\n// Use the last valid chroma\ncurrent.c = min_c;\nvariable result: Color.SRGB = current.to.srgb();\n\n// Final clamp for any floating point errors\nvariable final_result: Color.SRGB;\nfinal_result.r = min(1, max(0, result.r));\nfinal_result.g = min(1, max(0, result.g));\nfinal_result.b = min(1, max(0, result.b));\n\nreturn final_result;"
40
- },
41
- "examples": [
42
- {
43
- "description": "Map out-of-gamut P3 color to sRGB",
44
- "input": [
45
- "oklch(0.8 0.3 150)",
46
- "srgb"
47
- ],
48
- "output": "Color with reduced chroma that fits sRGB"
49
- },
50
- {
51
- "description": "In-gamut color returns unchanged",
52
- "input": [
53
- "#ff0000"
54
- ],
55
- "output": "#ff0000"
56
- }
57
- ],
58
- "slug": "to_gamut"
59
- }
@@ -1,24 +0,0 @@
1
- {
2
- "name": "Triadic",
3
- "type": "function",
4
- "description": "Generates triadic colors - three hues equally spaced 120° apart on the color wheel. Creates vibrant, balanced palettes with high contrast.",
5
- "keyword": "triadic",
6
- "input": {
7
- "type": "object",
8
- "properties": {
9
- "color": {
10
- "type": "color",
11
- "description": "Base color"
12
- }
13
- }
14
- },
15
- "script": {
16
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
17
- "script": "// Generate triadic colors (120° apart)\n// Returns [base, base+120°, base+240°]\n//\n// Use case: Vibrant, balanced palettes\n// Example: Red → Green → Blue\n\nvariable input: List = {input};\nvariable base: Color.OKLCH = input.get(0).to.oklch();\n\nvariable result: List;\n\n// Base color\nresult = result, base.to.srgb();\n\n// +120°\nvariable h2: Number = base.h + 120;\nif (h2 >= 360) [ h2 = h2 - 360; ];\nvariable c2: Color.OKLCH;\nc2.l = base.l; c2.c = base.c; c2.h = h2;\nresult = result, c2.to.srgb();\n\n// +240°\nvariable h3: Number = base.h + 240;\nif (h3 >= 360) [ h3 = h3 - 360; ];\nvariable c3: Color.OKLCH;\nc3.l = base.l; c3.c = base.c; c3.h = h3;\nresult = result, c3.to.srgb();\n\nreturn result;"
18
- },
19
- "requirements": [
20
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
21
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/"
22
- ],
23
- "slug": "triadic"
24
- }
@@ -1,59 +0,0 @@
1
- {
2
- "name": "vibrant",
3
- "type": "function",
4
- "description": "Increases a color's chroma toward a vibrant level. Preserves lightness and hue while boosting colorfulness. The optional amount parameter controls the intensity (0-1, default 0.5). Uses OKLCH for perceptually uniform chroma adjustment. Useful for creating attention-grabbing accents or active states from muted base colors.",
5
- "keyword": "vibrant",
6
- "requirements": [
7
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/",
8
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/"
9
- ],
10
- "schema": {
11
- "type": "object",
12
- "properties": {
13
- "input": {
14
- "type": "array",
15
- "items": [
16
- {
17
- "description": "Color to make vibrant",
18
- "type": "color"
19
- },
20
- {
21
- "description": "Amount (0-1, default 0.5). Higher = more vibrant.",
22
- "type": "number"
23
- }
24
- ],
25
- "minItems": 1,
26
- "maxItems": 2
27
- }
28
- },
29
- "required": [
30
- "input"
31
- ]
32
- },
33
- "returns": {
34
- "type": "color",
35
- "description": "More vibrant version of the color"
36
- },
37
- "script": {
38
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
39
- "script": "// vibrant: Increase chroma toward maximum colorfulness\n// Preserves lightness and hue\n// Amount controls how much to boost (0-1)\n\nvariable input: List = {input};\nvariable color: Color.OKLCH = input.get(0).to.oklch();\n\n// Default amount\nvariable amount: Number = 0.5;\nif (input.length() > 1) [\n amount = input.get(1);\n];\n\n// Target maximum chroma for sRGB at this lightness (approximate)\n// Real max varies by hue and lightness, but 0.3 is a reasonable target\nvariable max_chroma: Number = 0.3;\n\n// Increase chroma toward max\nvariable current_c: Number = color.c;\nvariable new_c: Number = current_c + (max_chroma - current_c) * amount;\n\n// Create result\nvariable result: Color.OKLCH;\nresult.l = color.l;\nresult.c = new_c;\nresult.h = color.h;\n\nreturn result;"
40
- },
41
- "examples": [
42
- {
43
- "description": "Make muted blue more vibrant",
44
- "input": [
45
- "#6688aa"
46
- ],
47
- "output": "More saturated blue"
48
- },
49
- {
50
- "description": "Full vibrancy",
51
- "input": [
52
- "#808080",
53
- 1
54
- ],
55
- "output": "Still gray (no hue to enhance)"
56
- }
57
- ],
58
- "slug": "vibrant"
59
- }
@@ -1,52 +0,0 @@
1
- {
2
- "name": "warmer",
3
- "type": "function",
4
- "description": "Shifts a color's hue towards warm colors (orange, ~60° in OKLCH). The amount parameter controls how much to shift, from 0 (no change) to 1 (fully warm). Preserves lightness and chroma.",
5
- "keyword": "warmer",
6
- "requirements": [
7
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/",
8
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/"
9
- ],
10
- "schema": {
11
- "type": "object",
12
- "properties": {
13
- "input": {
14
- "type": "array",
15
- "items": [
16
- {
17
- "description": "Color to warm",
18
- "type": "color"
19
- },
20
- {
21
- "description": "Amount to shift (0-1), default 0.25",
22
- "type": "number"
23
- }
24
- ],
25
- "minItems": 1,
26
- "maxItems": 2
27
- }
28
- },
29
- "required": [
30
- "input"
31
- ]
32
- },
33
- "returns": {
34
- "type": "color",
35
- "description": "Color shifted towards warm hues"
36
- },
37
- "script": {
38
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
39
- "script": "// warmer: Shift hue towards warm colors\n//\n// Warm colors are centered around orange (~60° in OKLCH).\n// The function interpolates the hue towards this target via\n// the shortest angular path on the hue wheel.\n//\n// Parameters:\n// color - Input color\n// amount - Shift amount (0 = no change, 1 = fully warm), default 0.25\n//\n// Preserves lightness and chroma.\n\nvariable input: List = {input};\nvariable color: Color.OKLCH = input.get(0).to.oklch();\nvariable amount: Number = 0.25;\n\nif (input.length() > 1) [\n amount = input.get(1);\n];\n\n// Warm hue target (orange in OKLCH is around 60°)\nvariable warm_hue: Number = 60;\n\n// Calculate shortest path hue difference\nvariable hue_diff: Number = warm_hue - color.h;\n\n// Wrap to shortest path\nif (hue_diff > 180) [ hue_diff = hue_diff - 360; ];\nif (hue_diff < -180) [ hue_diff = hue_diff + 360; ];\n\n// Apply interpolation\nvariable new_hue: Number = color.h + (hue_diff * amount);\n\n// Normalize to 0-360\nif (new_hue < 0) [ new_hue = new_hue + 360; ];\nif (new_hue >= 360) [ new_hue = new_hue - 360; ];\n\n// Create result\nvariable result: Color.OKLCH;\nresult.l = color.l;\nresult.c = color.c;\nresult.h = new_hue;\n\nreturn result;"
40
- },
41
- "examples": [
42
- {
43
- "description": "Make blue warmer",
44
- "input": [
45
- "#0000ff",
46
- 0.5
47
- ],
48
- "output": "Blue shifted towards purple/magenta"
49
- }
50
- ],
51
- "slug": "warmer"
52
- }
@@ -1,60 +0,0 @@
1
- {
2
- "name": "wcag_level",
3
- "type": "function",
4
- "description": "Returns the WCAG 2.1 compliance level for a foreground/background color pair. Returns 'AAA' (ratio >= 7:1), 'AA' (ratio >= 4.5:1), 'AA-large' (ratio >= 3:1), or 'fail' (ratio < 3:1). Based on W3C WCAG 2.1 Success Criteria 1.4.3 and 1.4.6.",
5
- "keyword": "wcag_level",
6
- "requirements": [
7
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/",
8
- "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/xyz-d65-color/0/"
9
- ],
10
- "schema": {
11
- "type": "object",
12
- "properties": {
13
- "input": {
14
- "type": "array",
15
- "items": [
16
- {
17
- "description": "Foreground color (text)",
18
- "type": "color"
19
- },
20
- {
21
- "description": "Background color",
22
- "type": "color"
23
- }
24
- ],
25
- "minItems": 2,
26
- "maxItems": 2
27
- }
28
- },
29
- "required": [
30
- "input"
31
- ]
32
- },
33
- "returns": {
34
- "type": "string",
35
- "description": "WCAG level: 'AAA', 'AA', 'AA-large', or 'fail'"
36
- },
37
- "script": {
38
- "type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
39
- "script": "// wcag_level: Determine WCAG 2.1 compliance level for a color pair\n// Reference: WCAG 2.1 Success Criterion 1.4.3 (Contrast Minimum)\n// Reference: WCAG 2.1 Success Criterion 1.4.6 (Contrast Enhanced)\n// Reference: https://www.w3.org/TR/WCAG21/#contrast-minimum\n//\n// Returns one of:\n// \"AAA\" - Ratio >= 7:1 (enhanced contrast for normal text)\n// \"AA\" - Ratio >= 4.5:1 (minimum for normal text)\n// \"AA-large\" - Ratio >= 3:1 (minimum for large text: 18pt or 14pt bold)\n// \"fail\" - Ratio < 3:1 (does not meet any criterion)\n\nvariable input: List = {input};\nvariable fg_xyz: Color.XYZD65 = input.get(0).to.xyzd65();\nvariable bg_xyz: Color.XYZD65 = input.get(1).to.xyzd65();\n\nvariable l1: Number = fg_xyz.y;\nvariable l2: Number = bg_xyz.y;\n\n// Ensure l1 is the lighter of the two\nif (l2 > l1) [\n variable temp: Number = l1;\n l1 = l2;\n l2 = temp;\n];\n\n// Calculate contrast ratio per WCAG formula\n// Ratio = (L1 + 0.05) / (L2 + 0.05)\nvariable ratio: Number = (l1 + 0.05) / (l2 + 0.05);\n\n// Determine WCAG level\n// AAA: ratio >= 7:1 (enhanced contrast)\n// AA: ratio >= 4.5:1 (minimum for normal text)\n// AA-large: ratio >= 3:1 (minimum for large text, 18pt+ or 14pt+ bold)\n// fail: ratio < 3:1\n\nvariable result: String = \"fail\";\n\nif (ratio >= 7) [\n result = \"AAA\";\n] else [\n if (ratio >= 4.5) [\n result = \"AA\";\n ] else [\n if (ratio >= 3) [\n result = \"AA-large\";\n ];\n ];\n];\n\nreturn result;"
40
- },
41
- "examples": [
42
- {
43
- "description": "Black on white passes AAA",
44
- "input": [
45
- "#000000",
46
- "#ffffff"
47
- ],
48
- "output": "AAA"
49
- },
50
- {
51
- "description": "Gray on white may only pass AA-large",
52
- "input": [
53
- "#767676",
54
- "#ffffff"
55
- ],
56
- "output": "AA"
57
- }
58
- ],
59
- "slug": "wcag_level"
60
- }