@tokens-studio/tokenscript-schemas 0.0.11 → 0.0.13
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/dist/cli/index.cjs +31 -8
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +30 -8
- package/dist/cli/index.js.map +1 -1
- package/package.json +2 -1
- package/src/bundler/bundle-schema.ts +146 -0
- package/src/bundler/index.ts +151 -0
- package/src/bundler/schema-dependency-resolver.ts +299 -0
- package/src/bundler/selective-bundler.test.ts +94 -0
- package/src/bundler/selective-bundler.ts +159 -0
- package/src/bundler/types.ts +93 -0
- package/src/bundler/utils.ts +74 -0
- package/src/cli/commands/bundle.integration.test.ts +153 -0
- package/src/cli/commands/bundle.test.ts +57 -0
- package/src/cli/commands/bundle.ts +237 -0
- package/src/cli/commands/list.ts +109 -0
- package/src/cli/config-schema.ts +36 -0
- package/src/cli/index.ts +50 -0
- package/src/cli/output-generator.ts +63 -0
- package/src/downloader/index.ts +248 -0
- package/src/downloader/types.ts +48 -0
- package/src/index.ts +8 -0
- package/src/schemas/functions/adjust_chroma/adjust-chroma.tokenscript +27 -0
- package/src/schemas/functions/adjust_chroma/schema.json +48 -0
- package/src/schemas/functions/adjust_chroma/unit.test.ts +76 -0
- package/src/schemas/functions/adjust_hue/adjust-hue.tokenscript +32 -0
- package/src/schemas/functions/adjust_hue/schema.json +48 -0
- package/src/schemas/functions/adjust_hue/unit.test.ts +68 -0
- package/src/schemas/functions/adjust_lightness/adjust-lightness.tokenscript +31 -0
- package/src/schemas/functions/adjust_lightness/schema.json +48 -0
- package/src/schemas/functions/adjust_lightness/unit.test.ts +88 -0
- package/src/schemas/functions/adjust_to_contrast/adjust-to-contrast.tokenscript +131 -0
- package/src/schemas/functions/adjust_to_contrast/schema.json +56 -0
- package/src/schemas/functions/adjust_to_contrast/unit.test.ts +81 -0
- package/src/schemas/functions/alpha_blend/alpha-blend.tokenscript +46 -0
- package/src/schemas/functions/alpha_blend/schema.json +28 -0
- package/src/schemas/functions/alpha_blend/unit.test.ts +135 -0
- package/src/schemas/functions/alpha_scale/alpha-scale.tokenscript +38 -0
- package/src/schemas/functions/alpha_scale/schema.json +24 -0
- package/src/schemas/functions/alpha_scale/unit.test.ts +50 -0
- package/src/schemas/functions/analogous/analogous.tokenscript +47 -0
- package/src/schemas/functions/analogous/schema.json +28 -0
- package/src/schemas/functions/analogous/unit.test.ts +64 -0
- package/src/schemas/functions/apca_contrast/apca-contrast.tokenscript +129 -0
- package/src/schemas/functions/apca_contrast/schema.json +24 -0
- package/src/schemas/functions/apca_contrast/unit.test.ts +259 -0
- package/src/schemas/functions/are_similar/are-similar.tokenscript +24 -0
- package/src/schemas/functions/are_similar/schema.json +57 -0
- package/src/schemas/functions/are_similar/unit.test.ts +57 -0
- package/src/schemas/functions/auto_text_color/auto-text-color.tokenscript +41 -0
- package/src/schemas/functions/auto_text_color/schema.json +53 -0
- package/src/schemas/functions/auto_text_color/unit.test.ts +122 -0
- package/src/schemas/functions/best_contrast/best-contrast.tokenscript +66 -0
- package/src/schemas/functions/best_contrast/schema.json +24 -0
- package/src/schemas/functions/best_contrast/unit.test.ts +64 -0
- package/src/schemas/functions/chroma/chroma.tokenscript +12 -0
- package/src/schemas/functions/chroma/schema.json +44 -0
- package/src/schemas/functions/chroma/unit.test.ts +86 -0
- package/src/schemas/functions/clamp_chroma/clamp-chroma.tokenscript +21 -0
- package/src/schemas/functions/clamp_chroma/schema.json +52 -0
- package/src/schemas/functions/clamp_chroma/unit.test.ts +60 -0
- package/src/schemas/functions/clamp_lightness/clamp-lightness.tokenscript +21 -0
- package/src/schemas/functions/clamp_lightness/schema.json +52 -0
- package/src/schemas/functions/clamp_lightness/unit.test.ts +76 -0
- package/src/schemas/functions/clamp_to_gamut/clamp-to-gamut.tokenscript +41 -0
- package/src/schemas/functions/clamp_to_gamut/schema.json +20 -0
- package/src/schemas/functions/clamp_to_gamut/unit.test.ts +167 -0
- package/src/schemas/functions/complement/complement.tokenscript +21 -0
- package/src/schemas/functions/complement/schema.json +20 -0
- package/src/schemas/functions/complement/unit.test.ts +81 -0
- package/src/schemas/functions/contrast_ratio/contrast-ratio.tokenscript +36 -0
- package/src/schemas/functions/contrast_ratio/schema.json +24 -0
- package/src/schemas/functions/contrast_ratio/unit.test.ts +91 -0
- package/src/schemas/functions/cooler/cooler.tokenscript +45 -0
- package/src/schemas/functions/cooler/schema.json +43 -0
- package/src/schemas/functions/cooler/unit.test.ts +69 -0
- package/src/schemas/functions/darken/darken.tokenscript +37 -0
- package/src/schemas/functions/darken/schema.json +24 -0
- package/src/schemas/functions/darken/unit.test.ts +105 -0
- package/src/schemas/functions/delta_e_2000/delta-e-2000.tokenscript +184 -0
- package/src/schemas/functions/delta_e_2000/schema.json +36 -0
- package/src/schemas/functions/delta_e_2000/unit.test.ts +243 -0
- package/src/schemas/functions/delta_e_76/delta-e-76.tokenscript +45 -0
- package/src/schemas/functions/delta_e_76/schema.json +24 -0
- package/src/schemas/functions/delta_e_76/unit.test.ts +123 -0
- package/src/schemas/functions/delta_e_ok/delta-e-ok.tokenscript +43 -0
- package/src/schemas/functions/delta_e_ok/schema.json +24 -0
- package/src/schemas/functions/delta_e_ok/unit.test.ts +235 -0
- package/src/schemas/functions/desaturate/desaturate.tokenscript +32 -0
- package/src/schemas/functions/desaturate/schema.json +24 -0
- package/src/schemas/functions/desaturate/unit.test.ts +54 -0
- package/src/schemas/functions/distributed/distributed.tokenscript +54 -0
- package/src/schemas/functions/distributed/schema.json +32 -0
- package/src/schemas/functions/distributed/unit.test.ts +58 -0
- package/src/schemas/functions/diverging/diverging.tokenscript +58 -0
- package/src/schemas/functions/diverging/schema.json +32 -0
- package/src/schemas/functions/diverging/unit.test.ts +70 -0
- package/src/schemas/functions/grayscale/grayscale.tokenscript +17 -0
- package/src/schemas/functions/grayscale/schema.json +20 -0
- package/src/schemas/functions/grayscale/unit.test.ts +79 -0
- package/src/schemas/functions/harmonize/harmonize.tokenscript +61 -0
- package/src/schemas/functions/harmonize/schema.json +52 -0
- package/src/schemas/functions/harmonize/unit.test.ts +56 -0
- package/src/schemas/functions/hue/hue.tokenscript +12 -0
- package/src/schemas/functions/hue/schema.json +44 -0
- package/src/schemas/functions/hue/unit.test.ts +75 -0
- package/src/schemas/functions/hue_difference/hue-difference.tokenscript +42 -0
- package/src/schemas/functions/hue_difference/schema.json +24 -0
- package/src/schemas/functions/hue_difference/unit.test.ts +125 -0
- package/src/schemas/functions/in_gamut/in-gamut.tokenscript +51 -0
- package/src/schemas/functions/in_gamut/schema.json +24 -0
- package/src/schemas/functions/in_gamut/unit.test.ts +178 -0
- package/src/schemas/functions/interpolate/interpolate.tokenscript +61 -0
- package/src/schemas/functions/interpolate/schema.json +52 -0
- package/src/schemas/functions/interpolate/unit.test.ts +96 -0
- package/src/schemas/functions/invert/invert-initializer.tokenscript +29 -0
- package/src/schemas/functions/invert/schema.json +20 -0
- package/src/schemas/functions/invert/unit.test.ts +216 -0
- package/src/schemas/functions/is_cool/is-cool.tokenscript +41 -0
- package/src/schemas/functions/is_cool/schema.json +20 -0
- package/src/schemas/functions/is_cool/unit.test.ts +189 -0
- package/src/schemas/functions/is_dark/is-dark.tokenscript +16 -0
- package/src/schemas/functions/is_dark/schema.json +24 -0
- package/src/schemas/functions/is_dark/unit.test.ts +87 -0
- package/src/schemas/functions/is_light/is-light.tokenscript +16 -0
- package/src/schemas/functions/is_light/schema.json +24 -0
- package/src/schemas/functions/is_light/unit.test.ts +86 -0
- package/src/schemas/functions/is_neutral/is-neutral.tokenscript +16 -0
- package/src/schemas/functions/is_neutral/schema.json +53 -0
- package/src/schemas/functions/is_neutral/unit.test.ts +85 -0
- package/src/schemas/functions/is_warm/is-warm.tokenscript +62 -0
- package/src/schemas/functions/is_warm/schema.json +20 -0
- package/src/schemas/functions/is_warm/unit.test.ts +161 -0
- package/src/schemas/functions/lighten/lighten.tokenscript +37 -0
- package/src/schemas/functions/lighten/schema.json +24 -0
- package/src/schemas/functions/lighten/unit.test.ts +109 -0
- package/src/schemas/functions/lightness/lightness.tokenscript +12 -0
- package/src/schemas/functions/lightness/schema.json +49 -0
- package/src/schemas/functions/lightness/unit.test.ts +99 -0
- package/src/schemas/functions/luminance/luminance.tokenscript +16 -0
- package/src/schemas/functions/luminance/schema.json +20 -0
- package/src/schemas/functions/luminance/unit.test.ts +105 -0
- package/src/schemas/functions/meets_contrast/meets-contrast.tokenscript +49 -0
- package/src/schemas/functions/meets_contrast/schema.json +28 -0
- package/src/schemas/functions/meets_contrast/unit.test.ts +170 -0
- package/src/schemas/functions/mix/mix.tokenscript +47 -0
- package/src/schemas/functions/mix/schema.json +28 -0
- package/src/schemas/functions/mix/unit.test.ts +95 -0
- package/src/schemas/functions/monochromatic/monochromatic.tokenscript +72 -0
- package/src/schemas/functions/monochromatic/schema.json +24 -0
- package/src/schemas/functions/monochromatic/unit.test.ts +91 -0
- package/src/schemas/functions/muted/muted.tokenscript +25 -0
- package/src/schemas/functions/muted/schema.json +48 -0
- package/src/schemas/functions/muted/unit.test.ts +100 -0
- package/src/schemas/functions/neutral_variant/neutral-variant.tokenscript +23 -0
- package/src/schemas/functions/neutral_variant/schema.json +48 -0
- package/src/schemas/functions/neutral_variant/unit.test.ts +102 -0
- package/src/schemas/functions/relative_luminance/relative-luminance.tokenscript +15 -0
- package/src/schemas/functions/relative_luminance/schema.json +49 -0
- package/src/schemas/functions/relative_luminance/unit.test.ts +104 -0
- package/src/schemas/functions/rotate_hue/rotate-hue.tokenscript +20 -0
- package/src/schemas/functions/rotate_hue/schema.json +24 -0
- package/src/schemas/functions/rotate_hue/unit.test.ts +86 -0
- package/src/schemas/functions/saturate/saturate.tokenscript +33 -0
- package/src/schemas/functions/saturate/schema.json +24 -0
- package/src/schemas/functions/saturate/unit.test.ts +59 -0
- package/src/schemas/functions/scale_chroma/scale-chroma.tokenscript +22 -0
- package/src/schemas/functions/scale_chroma/schema.json +48 -0
- package/src/schemas/functions/scale_chroma/unit.test.ts +79 -0
- package/src/schemas/functions/scale_lightness/scale-lightness.tokenscript +23 -0
- package/src/schemas/functions/scale_lightness/schema.json +48 -0
- package/src/schemas/functions/scale_lightness/unit.test.ts +73 -0
- package/src/schemas/functions/sepia/schema.json +48 -0
- package/src/schemas/functions/sepia/sepia.tokenscript +54 -0
- package/src/schemas/functions/sepia/unit.test.ts +88 -0
- package/src/schemas/functions/set_chroma/schema.json +24 -0
- package/src/schemas/functions/set_chroma/set-chroma.tokenscript +18 -0
- package/src/schemas/functions/set_chroma/unit.test.ts +79 -0
- package/src/schemas/functions/set_hue/schema.json +24 -0
- package/src/schemas/functions/set_hue/set-hue.tokenscript +18 -0
- package/src/schemas/functions/set_hue/unit.test.ts +90 -0
- package/src/schemas/functions/set_lightness/schema.json +24 -0
- package/src/schemas/functions/set_lightness/set-lightness.tokenscript +18 -0
- package/src/schemas/functions/set_lightness/unit.test.ts +80 -0
- package/src/schemas/functions/shade_scale/schema.json +24 -0
- package/src/schemas/functions/shade_scale/shade-scale.tokenscript +61 -0
- package/src/schemas/functions/shade_scale/unit.test.ts +64 -0
- package/src/schemas/functions/split_complement/schema.json +24 -0
- package/src/schemas/functions/split_complement/split-complement.tokenscript +38 -0
- package/src/schemas/functions/split_complement/unit.test.ts +53 -0
- package/src/schemas/functions/steps/schema.json +28 -0
- package/src/schemas/functions/steps/steps.tokenscript +54 -0
- package/src/schemas/functions/steps/unit.test.ts +71 -0
- package/src/schemas/functions/tetradic/schema.json +20 -0
- package/src/schemas/functions/tetradic/tetradic.tokenscript +40 -0
- package/src/schemas/functions/tetradic/unit.test.ts +50 -0
- package/src/schemas/functions/tint_scale/schema.json +32 -0
- package/src/schemas/functions/tint_scale/tint-scale.tokenscript +71 -0
- package/src/schemas/functions/tint_scale/unit.test.ts +64 -0
- package/src/schemas/functions/to_gamut/schema.json +48 -0
- package/src/schemas/functions/to_gamut/to-gamut.tokenscript +96 -0
- package/src/schemas/functions/to_gamut/unit.test.ts +97 -0
- package/src/schemas/functions/triadic/schema.json +20 -0
- package/src/schemas/functions/triadic/triadic.tokenscript +33 -0
- package/src/schemas/functions/triadic/unit.test.ts +64 -0
- package/src/schemas/functions/vibrant/schema.json +48 -0
- package/src/schemas/functions/vibrant/unit.test.ts +55 -0
- package/src/schemas/functions/vibrant/vibrant.tokenscript +29 -0
- package/src/schemas/functions/warmer/schema.json +43 -0
- package/src/schemas/functions/warmer/unit.test.ts +69 -0
- package/src/schemas/functions/warmer/warmer.tokenscript +45 -0
- package/src/schemas/functions/wcag_level/schema.json +48 -0
- package/src/schemas/functions/wcag_level/unit.test.ts +75 -0
- package/src/schemas/functions/wcag_level/wcag-level.tokenscript +50 -0
- package/src/schemas/types/css-color/from-hsl-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-hwb-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-lab-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-lch-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-oklab-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-oklch-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-p3-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-rgb-color.tokenscript +15 -0
- package/src/schemas/types/css-color/from-srgb-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-srgb-linear-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-xyz-d50-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-xyz-d65-color.tokenscript +16 -0
- package/src/schemas/types/css-color/initializer.tokenscript +13 -0
- package/src/schemas/types/css-color/schema.json +148 -0
- package/src/schemas/types/css-color/unit.test.ts +402 -0
- package/src/schemas/types/hex-color/initializer.tokenscript +3 -0
- package/src/schemas/types/hex-color/schema.json +24 -0
- package/src/schemas/types/hex-color/unit.test.ts +123 -0
- package/src/schemas/types/hsl-color/from-srgb.tokenscript +87 -0
- package/src/schemas/types/hsl-color/initializer.tokenscript +16 -0
- package/src/schemas/types/hsl-color/schema.json +48 -0
- package/src/schemas/types/hsl-color/unit.test.ts +201 -0
- package/src/schemas/types/hsv-color/from-srgb.tokenscript +80 -0
- package/src/schemas/types/hsv-color/initializer.tokenscript +16 -0
- package/src/schemas/types/hsv-color/schema.json +48 -0
- package/src/schemas/types/hsv-color/unit.test.ts +162 -0
- package/src/schemas/types/hwb-color/from-hsv.tokenscript +31 -0
- package/src/schemas/types/hwb-color/initializer.tokenscript +16 -0
- package/src/schemas/types/hwb-color/schema.json +48 -0
- package/src/schemas/types/hwb-color/unit.test.ts +150 -0
- package/src/schemas/types/lab-color/from-xyz-d50.tokenscript +78 -0
- package/src/schemas/types/lab-color/initializer.tokenscript +16 -0
- package/src/schemas/types/lab-color/schema.json +48 -0
- package/src/schemas/types/lab-color/unit.test.ts +263 -0
- package/src/schemas/types/lch-color/from-lab.tokenscript +44 -0
- package/src/schemas/types/lch-color/initializer.tokenscript +16 -0
- package/src/schemas/types/lch-color/schema.json +48 -0
- package/src/schemas/types/lch-color/unit.test.ts +173 -0
- package/src/schemas/types/okhsl-color/from-oklab.tokenscript +410 -0
- package/src/schemas/types/okhsl-color/initializer.tokenscript +24 -0
- package/src/schemas/types/okhsl-color/schema.json +48 -0
- package/src/schemas/types/okhsl-color/unit.test.ts +514 -0
- package/src/schemas/types/okhsv-color/from-oklab.tokenscript +286 -0
- package/src/schemas/types/okhsv-color/initializer.tokenscript +24 -0
- package/src/schemas/types/okhsv-color/schema.json +48 -0
- package/src/schemas/types/okhsv-color/unit.test.ts +499 -0
- package/src/schemas/types/oklab-color/from-okhsl.tokenscript +195 -0
- package/src/schemas/types/oklab-color/from-okhsv.tokenscript +197 -0
- package/src/schemas/types/oklab-color/from-oklch.tokenscript +39 -0
- package/src/schemas/types/oklab-color/from-xyz-d65.tokenscript +43 -0
- package/src/schemas/types/oklab-color/initializer.tokenscript +16 -0
- package/src/schemas/types/oklab-color/schema.json +78 -0
- package/src/schemas/types/oklab-color/unit.test.ts +345 -0
- package/src/schemas/types/oklch-color/from-oklab.tokenscript +45 -0
- package/src/schemas/types/oklch-color/initializer.tokenscript +16 -0
- package/src/schemas/types/oklch-color/schema.json +48 -0
- package/src/schemas/types/oklch-color/unit.test.ts +267 -0
- package/src/schemas/types/p3-color/from-p3-linear.tokenscript +59 -0
- package/src/schemas/types/p3-color/initializer.tokenscript +16 -0
- package/src/schemas/types/p3-color/schema.json +48 -0
- package/src/schemas/types/p3-color/unit.test.ts +119 -0
- package/src/schemas/types/p3-linear-color/from-xyz-d65.tokenscript +47 -0
- package/src/schemas/types/p3-linear-color/initializer.tokenscript +16 -0
- package/src/schemas/types/p3-linear-color/schema.json +48 -0
- package/src/schemas/types/p3-linear-color/unit.test.ts +82 -0
- package/src/schemas/types/rgb-color/from-hex.tokenscript +43 -0
- package/src/schemas/types/rgb-color/initializer.tokenscript +16 -0
- package/src/schemas/types/rgb-color/schema.json +55 -0
- package/src/schemas/types/rgb-color/to-hex.tokenscript +42 -0
- package/src/schemas/types/rgb-color/unit.test.ts +302 -0
- package/src/schemas/types/srgb-color/from-hsl.tokenscript +106 -0
- package/src/schemas/types/srgb-color/from-linear.tokenscript +58 -0
- package/src/schemas/types/srgb-color/from-rgb.tokenscript +20 -0
- package/src/schemas/types/srgb-color/initializer.tokenscript +16 -0
- package/src/schemas/types/srgb-color/schema.json +68 -0
- package/src/schemas/types/srgb-color/unit.test.ts +303 -0
- package/src/schemas/types/srgb-linear-color/from-srgb.tokenscript +55 -0
- package/src/schemas/types/srgb-linear-color/from-xyz-d65.tokenscript +34 -0
- package/src/schemas/types/srgb-linear-color/initializer.tokenscript +13 -0
- package/src/schemas/types/srgb-linear-color/schema.json +58 -0
- package/src/schemas/types/srgb-linear-color/unit.test.ts +291 -0
- package/src/schemas/types/xyz-d50-color/from-xyz-d65.tokenscript +36 -0
- package/src/schemas/types/xyz-d50-color/initializer.tokenscript +16 -0
- package/src/schemas/types/xyz-d50-color/schema.json +48 -0
- package/src/schemas/types/xyz-d50-color/unit.test.ts +240 -0
- package/src/schemas/types/xyz-d65-color/from-linear-p3.tokenscript +47 -0
- package/src/schemas/types/xyz-d65-color/from-linear-srgb.tokenscript +38 -0
- package/src/schemas/types/xyz-d65-color/from-oklab.tokenscript +44 -0
- package/src/schemas/types/xyz-d65-color/initializer.tokenscript +16 -0
- package/src/schemas/types/xyz-d65-color/schema.json +68 -0
- package/src/schemas/types/xyz-d65-color/unit.test.ts +319 -0
- package/src/utils/schema-uri.ts +192 -0
- package/src/utils/type.ts +194 -0
|
@@ -0,0 +1,48 @@
|
|
|
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": ["/api/v1/core/srgb-color/0/", "/api/v1/core/oklch-color/0/"],
|
|
7
|
+
"schema": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"input": {
|
|
11
|
+
"type": "array",
|
|
12
|
+
"items": [
|
|
13
|
+
{
|
|
14
|
+
"description": "Color to map into gamut",
|
|
15
|
+
"type": "color"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"description": "Target gamut/space (default 'srgb')",
|
|
19
|
+
"type": "string"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"minItems": 1,
|
|
23
|
+
"maxItems": 2
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["input"]
|
|
27
|
+
},
|
|
28
|
+
"returns": {
|
|
29
|
+
"type": "color",
|
|
30
|
+
"description": "Color mapped into the target gamut"
|
|
31
|
+
},
|
|
32
|
+
"script": {
|
|
33
|
+
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
34
|
+
"script": "./to-gamut.tokenscript"
|
|
35
|
+
},
|
|
36
|
+
"examples": [
|
|
37
|
+
{
|
|
38
|
+
"description": "Map out-of-gamut P3 color to sRGB",
|
|
39
|
+
"input": ["oklch(0.8 0.3 150)", "srgb"],
|
|
40
|
+
"output": "Color with reduced chroma that fits sRGB"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"description": "In-gamut color returns unchanged",
|
|
44
|
+
"input": ["#ff0000"],
|
|
45
|
+
"output": "#ff0000"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// to_gamut: Perceptual gamut mapping (CSS Color Level 4 algorithm)
|
|
2
|
+
// Reference: CSS Color Level 4, Section 13.2 Gamut Mapping
|
|
3
|
+
// Reference: https://www.w3.org/TR/css-color-4/#gamut-mapping
|
|
4
|
+
//
|
|
5
|
+
// Maps out-of-gamut colors into sRGB while preserving perceptual
|
|
6
|
+
// intent. Uses OKLCH space with binary search on chroma:
|
|
7
|
+
// - Lightness and hue are preserved
|
|
8
|
+
// - Chroma is reduced until the color fits in gamut
|
|
9
|
+
//
|
|
10
|
+
// This is the CSS Gamut Mapping Algorithm (GMA) used by browsers.
|
|
11
|
+
|
|
12
|
+
variable input: List = {input};
|
|
13
|
+
variable color: Color.OKLCH = input.get(0).to.oklch();
|
|
14
|
+
|
|
15
|
+
// Target space (default sRGB) - currently only supports sRGB
|
|
16
|
+
variable target_space: String = "srgb";
|
|
17
|
+
if (input.length() > 1) [
|
|
18
|
+
target_space = input.get(1);
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// Constants
|
|
22
|
+
variable epsilon: Number = 0.0001;
|
|
23
|
+
variable neg_epsilon: Number = 0 - epsilon;
|
|
24
|
+
variable one_plus_eps: Number = 1 + epsilon;
|
|
25
|
+
|
|
26
|
+
// Check if already in gamut by converting and checking bounds
|
|
27
|
+
variable test_color: Color.SRGB = color.to.srgb();
|
|
28
|
+
variable in_gamut: Boolean = true;
|
|
29
|
+
|
|
30
|
+
// Check if sRGB values are in range [0, 1]
|
|
31
|
+
if (test_color.r < neg_epsilon) [ in_gamut = false; ];
|
|
32
|
+
if (test_color.r > one_plus_eps) [ in_gamut = false; ];
|
|
33
|
+
if (test_color.g < neg_epsilon) [ in_gamut = false; ];
|
|
34
|
+
if (test_color.g > one_plus_eps) [ in_gamut = false; ];
|
|
35
|
+
if (test_color.b < neg_epsilon) [ in_gamut = false; ];
|
|
36
|
+
if (test_color.b > one_plus_eps) [ in_gamut = false; ];
|
|
37
|
+
|
|
38
|
+
// If already in gamut, return clamped version
|
|
39
|
+
if (in_gamut) [
|
|
40
|
+
variable clamped: Color.SRGB;
|
|
41
|
+
clamped.r = min(1, max(0, test_color.r));
|
|
42
|
+
clamped.g = min(1, max(0, test_color.g));
|
|
43
|
+
clamped.b = min(1, max(0, test_color.b));
|
|
44
|
+
return clamped;
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
// Binary search: reduce chroma until in gamut
|
|
48
|
+
variable min_c: Number = 0;
|
|
49
|
+
variable max_c: Number = color.c;
|
|
50
|
+
variable current: Color.OKLCH;
|
|
51
|
+
current.l = color.l;
|
|
52
|
+
current.h = color.h;
|
|
53
|
+
|
|
54
|
+
variable iterations: Number = 0;
|
|
55
|
+
variable max_iterations: Number = 25;
|
|
56
|
+
|
|
57
|
+
while (max_c - min_c > epsilon) [
|
|
58
|
+
if (iterations >= max_iterations) [
|
|
59
|
+
max_c = min_c; // Force exit
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
variable mid_c: Number = (min_c + max_c) / 2;
|
|
63
|
+
current.c = mid_c;
|
|
64
|
+
|
|
65
|
+
variable test: Color.SRGB = current.to.srgb();
|
|
66
|
+
variable test_in_gamut: Boolean = true;
|
|
67
|
+
|
|
68
|
+
if (test.r < neg_epsilon) [ test_in_gamut = false; ];
|
|
69
|
+
if (test.r > one_plus_eps) [ test_in_gamut = false; ];
|
|
70
|
+
if (test.g < neg_epsilon) [ test_in_gamut = false; ];
|
|
71
|
+
if (test.g > one_plus_eps) [ test_in_gamut = false; ];
|
|
72
|
+
if (test.b < neg_epsilon) [ test_in_gamut = false; ];
|
|
73
|
+
if (test.b > one_plus_eps) [ test_in_gamut = false; ];
|
|
74
|
+
|
|
75
|
+
if (test_in_gamut) [
|
|
76
|
+
// We can try higher chroma
|
|
77
|
+
min_c = mid_c;
|
|
78
|
+
] else [
|
|
79
|
+
// Need to reduce chroma
|
|
80
|
+
max_c = mid_c;
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
iterations = iterations + 1;
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
// Use the last valid chroma
|
|
87
|
+
current.c = min_c;
|
|
88
|
+
variable result: Color.SRGB = current.to.srgb();
|
|
89
|
+
|
|
90
|
+
// Final clamp for any floating point errors
|
|
91
|
+
variable final_result: Color.SRGB;
|
|
92
|
+
final_result.r = min(1, max(0, result.r));
|
|
93
|
+
final_result.g = min(1, max(0, result.g));
|
|
94
|
+
final_result.b = min(1, max(0, result.b));
|
|
95
|
+
|
|
96
|
+
return final_result;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the to_gamut function
|
|
3
|
+
* Maps colors into sRGB gamut
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { executeWithSchema, getBundledSchema } from "@tests/helpers/schema-test-utils";
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
import type { FunctionSpecification } from "@/bundler/types";
|
|
9
|
+
|
|
10
|
+
describe("to_gamut function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("to_gamut", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("to_gamut");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("Function Execution", () => {
|
|
21
|
+
it("should return in-gamut color unchanged", async () => {
|
|
22
|
+
const result = await executeWithSchema(
|
|
23
|
+
"to_gamut",
|
|
24
|
+
"function",
|
|
25
|
+
`
|
|
26
|
+
variable red: Color.SRGB;
|
|
27
|
+
red.r = 1; red.g = 0; red.b = 0;
|
|
28
|
+
to_gamut(red)
|
|
29
|
+
`,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(result).toBeDefined();
|
|
33
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
34
|
+
expect(r).toBeCloseTo(1, 1);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should handle white", async () => {
|
|
38
|
+
const result = await executeWithSchema(
|
|
39
|
+
"to_gamut",
|
|
40
|
+
"function",
|
|
41
|
+
`
|
|
42
|
+
variable white: Color.SRGB;
|
|
43
|
+
white.r = 1; white.g = 1; white.b = 1;
|
|
44
|
+
to_gamut(white)
|
|
45
|
+
`,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(result).toBeDefined();
|
|
49
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
50
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
51
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
52
|
+
expect(r).toBeCloseTo(1, 1);
|
|
53
|
+
expect(g).toBeCloseTo(1, 1);
|
|
54
|
+
expect(b).toBeCloseTo(1, 1);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should handle black", async () => {
|
|
58
|
+
const result = await executeWithSchema(
|
|
59
|
+
"to_gamut",
|
|
60
|
+
"function",
|
|
61
|
+
`
|
|
62
|
+
variable black: Color.SRGB;
|
|
63
|
+
black.r = 0; black.g = 0; black.b = 0;
|
|
64
|
+
to_gamut(black)
|
|
65
|
+
`,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(result).toBeDefined();
|
|
69
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
70
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
71
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
72
|
+
expect(r).toBeCloseTo(0, 1);
|
|
73
|
+
expect(g).toBeCloseTo(0, 1);
|
|
74
|
+
expect(b).toBeCloseTo(0, 1);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should handle grayscale colors", async () => {
|
|
78
|
+
const result = await executeWithSchema(
|
|
79
|
+
"to_gamut",
|
|
80
|
+
"function",
|
|
81
|
+
`
|
|
82
|
+
variable gray: Color.SRGB;
|
|
83
|
+
gray.r = 0.5; gray.g = 0.5; gray.b = 0.5;
|
|
84
|
+
to_gamut(gray)
|
|
85
|
+
`,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(result).toBeDefined();
|
|
89
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
90
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
91
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
92
|
+
// Gray should remain gray
|
|
93
|
+
expect(Math.abs(r - g)).toBeLessThan(0.05);
|
|
94
|
+
expect(Math.abs(g - b)).toBeLessThan(0.05);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
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": "/api/v1/core/tokenscript/0/",
|
|
17
|
+
"script": "./triadic.tokenscript"
|
|
18
|
+
},
|
|
19
|
+
"requirements": ["/api/v1/core/oklch-color/0/", "/api/v1/core/srgb-color/0/"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Generate triadic colors (120° apart)
|
|
2
|
+
// Returns [base, base+120°, base+240°]
|
|
3
|
+
//
|
|
4
|
+
// Use case: Vibrant, balanced palettes
|
|
5
|
+
// Example: Red → Green → Blue
|
|
6
|
+
|
|
7
|
+
variable input: List = {input};
|
|
8
|
+
variable base: Color.OKLCH = input.get(0).to.oklch();
|
|
9
|
+
|
|
10
|
+
variable result: List;
|
|
11
|
+
|
|
12
|
+
// Base color
|
|
13
|
+
result = result, base.to.srgb();
|
|
14
|
+
|
|
15
|
+
// +120°
|
|
16
|
+
variable h2: Number = base.h + 120;
|
|
17
|
+
if (h2 >= 360) [ h2 = h2 - 360; ];
|
|
18
|
+
variable c2: Color.OKLCH;
|
|
19
|
+
c2.l = base.l; c2.c = base.c; c2.h = h2;
|
|
20
|
+
result = result, c2.to.srgb();
|
|
21
|
+
|
|
22
|
+
// +240°
|
|
23
|
+
variable h3: Number = base.h + 240;
|
|
24
|
+
if (h3 >= 360) [ h3 = h3 - 360; ];
|
|
25
|
+
variable c3: Color.OKLCH;
|
|
26
|
+
c3.l = base.l; c3.c = base.c; c3.h = h3;
|
|
27
|
+
result = result, c3.to.srgb();
|
|
28
|
+
|
|
29
|
+
return result;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Triadic function
|
|
3
|
+
* Generates triadic colors (120° apart on color wheel)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { executeWithSchema, getBundledSchema } from "@tests/helpers/schema-test-utils";
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
import type { FunctionSpecification } from "@/bundler/types";
|
|
9
|
+
|
|
10
|
+
describe("Triadic Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("triadic", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Triadic");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("triadic");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("Function Execution", () => {
|
|
22
|
+
it("should generate 3 colors", async () => {
|
|
23
|
+
const result = await executeWithSchema(
|
|
24
|
+
"triadic",
|
|
25
|
+
"function",
|
|
26
|
+
`
|
|
27
|
+
variable base: Color.SRGB;
|
|
28
|
+
base.r = 0.9; base.g = 0.2; base.b = 0.2;
|
|
29
|
+
triadic(base)
|
|
30
|
+
`,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect(result).toBeDefined();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should include the base color", async () => {
|
|
37
|
+
const result = await executeWithSchema(
|
|
38
|
+
"triadic",
|
|
39
|
+
"function",
|
|
40
|
+
`
|
|
41
|
+
variable blue: Color.SRGB;
|
|
42
|
+
blue.r = 0.2; blue.g = 0.3; blue.b = 0.9;
|
|
43
|
+
triadic(blue)
|
|
44
|
+
`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(result).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should preserve lightness across colors", async () => {
|
|
51
|
+
const result = await executeWithSchema(
|
|
52
|
+
"triadic",
|
|
53
|
+
"function",
|
|
54
|
+
`
|
|
55
|
+
variable mid: Color.SRGB;
|
|
56
|
+
mid.r = 0.6; mid.g = 0.5; mid.b = 0.4;
|
|
57
|
+
triadic(mid)
|
|
58
|
+
`,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(result).toBeDefined();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
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": ["/api/v1/core/srgb-color/0/", "/api/v1/core/oklch-color/0/"],
|
|
7
|
+
"schema": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"input": {
|
|
11
|
+
"type": "array",
|
|
12
|
+
"items": [
|
|
13
|
+
{
|
|
14
|
+
"description": "Color to make vibrant",
|
|
15
|
+
"type": "color"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"description": "Amount (0-1, default 0.5). Higher = more vibrant.",
|
|
19
|
+
"type": "number"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"minItems": 1,
|
|
23
|
+
"maxItems": 2
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["input"]
|
|
27
|
+
},
|
|
28
|
+
"returns": {
|
|
29
|
+
"type": "color",
|
|
30
|
+
"description": "More vibrant version of the color"
|
|
31
|
+
},
|
|
32
|
+
"script": {
|
|
33
|
+
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
34
|
+
"script": "./vibrant.tokenscript"
|
|
35
|
+
},
|
|
36
|
+
"examples": [
|
|
37
|
+
{
|
|
38
|
+
"description": "Make muted blue more vibrant",
|
|
39
|
+
"input": ["#6688aa"],
|
|
40
|
+
"output": "More saturated blue"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"description": "Full vibrancy",
|
|
44
|
+
"input": ["#808080", 1],
|
|
45
|
+
"output": "Still gray (no hue to enhance)"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the vibrant function
|
|
3
|
+
* Increases chroma toward maximum
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { executeWithSchema, getBundledSchema } from "@tests/helpers/schema-test-utils";
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
import type { FunctionSpecification } from "@/bundler/types";
|
|
9
|
+
|
|
10
|
+
describe("vibrant function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("vibrant", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("vibrant");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("Function Execution", () => {
|
|
21
|
+
it("should increase saturation of muted colors", async () => {
|
|
22
|
+
const result = await executeWithSchema(
|
|
23
|
+
"vibrant",
|
|
24
|
+
"function",
|
|
25
|
+
`
|
|
26
|
+
variable muted_blue: Color.SRGB;
|
|
27
|
+
muted_blue.r = 0.4; muted_blue.g = 0.5; muted_blue.b = 0.6;
|
|
28
|
+
vibrant(muted_blue).to.srgb()
|
|
29
|
+
`,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(result).toBeDefined();
|
|
33
|
+
expect((result as any).constructor.name).toBe("ColorSymbol");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should have minimal effect on already vibrant colors", async () => {
|
|
37
|
+
const result = await executeWithSchema(
|
|
38
|
+
"vibrant",
|
|
39
|
+
"function",
|
|
40
|
+
`
|
|
41
|
+
variable red: Color.SRGB;
|
|
42
|
+
red.r = 1; red.g = 0; red.b = 0;
|
|
43
|
+
vibrant(red, 0.5).to.srgb()
|
|
44
|
+
`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(result).toBeDefined();
|
|
48
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
49
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
50
|
+
// Should still be predominantly red
|
|
51
|
+
expect(r).toBeGreaterThan(0.7);
|
|
52
|
+
expect(g).toBeLessThan(0.5);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// vibrant: Increase chroma toward maximum colorfulness
|
|
2
|
+
// Preserves lightness and hue
|
|
3
|
+
// Amount controls how much to boost (0-1)
|
|
4
|
+
|
|
5
|
+
variable input: List = {input};
|
|
6
|
+
variable color: Color.OKLCH = input.get(0).to.oklch();
|
|
7
|
+
|
|
8
|
+
// Default amount
|
|
9
|
+
variable amount: Number = 0.5;
|
|
10
|
+
if (input.length() > 1) [
|
|
11
|
+
amount = input.get(1);
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
// Target maximum chroma for sRGB at this lightness (approximate)
|
|
15
|
+
// Real max varies by hue and lightness, but 0.3 is a reasonable target
|
|
16
|
+
variable max_chroma: Number = 0.3;
|
|
17
|
+
|
|
18
|
+
// Increase chroma toward max
|
|
19
|
+
variable current_c: Number = color.c;
|
|
20
|
+
variable new_c: Number = current_c + (max_chroma - current_c) * amount;
|
|
21
|
+
|
|
22
|
+
// Create result
|
|
23
|
+
variable result: Color.OKLCH;
|
|
24
|
+
result.l = color.l;
|
|
25
|
+
result.c = new_c;
|
|
26
|
+
result.h = color.h;
|
|
27
|
+
|
|
28
|
+
return result;
|
|
29
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
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": ["/api/v1/core/srgb-color/0/", "/api/v1/core/oklch-color/0/"],
|
|
7
|
+
"schema": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"properties": {
|
|
10
|
+
"input": {
|
|
11
|
+
"type": "array",
|
|
12
|
+
"items": [
|
|
13
|
+
{
|
|
14
|
+
"description": "Color to warm",
|
|
15
|
+
"type": "color"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"description": "Amount to shift (0-1), default 0.25",
|
|
19
|
+
"type": "number"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"minItems": 1,
|
|
23
|
+
"maxItems": 2
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["input"]
|
|
27
|
+
},
|
|
28
|
+
"returns": {
|
|
29
|
+
"type": "color",
|
|
30
|
+
"description": "Color shifted towards warm hues"
|
|
31
|
+
},
|
|
32
|
+
"script": {
|
|
33
|
+
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
34
|
+
"script": "./warmer.tokenscript"
|
|
35
|
+
},
|
|
36
|
+
"examples": [
|
|
37
|
+
{
|
|
38
|
+
"description": "Make blue warmer",
|
|
39
|
+
"input": ["#0000ff", 0.5],
|
|
40
|
+
"output": "Blue shifted towards purple/magenta"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the warmer function
|
|
3
|
+
* Shifts hue towards warm colors
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { executeWithSchema, getBundledSchema } from "@tests/helpers/schema-test-utils";
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
import type { FunctionSpecification } from "@/bundler/types";
|
|
9
|
+
|
|
10
|
+
describe("warmer function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("warmer", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("warmer");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("Function Execution", () => {
|
|
21
|
+
it("should shift blue towards warm (purple)", async () => {
|
|
22
|
+
const result = await executeWithSchema(
|
|
23
|
+
"warmer",
|
|
24
|
+
"function",
|
|
25
|
+
`
|
|
26
|
+
variable blue: Color.SRGB;
|
|
27
|
+
blue.r = 0; blue.g = 0; blue.b = 1;
|
|
28
|
+
warmer(blue, 0.5).to.srgb()
|
|
29
|
+
`,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(result).toBeDefined();
|
|
33
|
+
// Blue shifted warm should have more red
|
|
34
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
35
|
+
expect(r).toBeGreaterThan(0.1);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should shift green towards warm (yellow)", async () => {
|
|
39
|
+
const result = await executeWithSchema(
|
|
40
|
+
"warmer",
|
|
41
|
+
"function",
|
|
42
|
+
`
|
|
43
|
+
variable green: Color.SRGB;
|
|
44
|
+
green.r = 0; green.g = 1; green.b = 0;
|
|
45
|
+
warmer(green, 0.5).to.srgb()
|
|
46
|
+
`,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(result).toBeDefined();
|
|
50
|
+
// Green shifted warm should have more red
|
|
51
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
52
|
+
expect(r).toBeGreaterThan(0.1);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should use default amount if not provided", async () => {
|
|
56
|
+
const result = await executeWithSchema(
|
|
57
|
+
"warmer",
|
|
58
|
+
"function",
|
|
59
|
+
`
|
|
60
|
+
variable blue: Color.SRGB;
|
|
61
|
+
blue.r = 0; blue.g = 0; blue.b = 1;
|
|
62
|
+
warmer(blue).to.srgb()
|
|
63
|
+
`,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
expect(result).toBeDefined();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// warmer: Shift hue towards warm colors
|
|
2
|
+
//
|
|
3
|
+
// Warm colors are centered around orange (~60° in OKLCH).
|
|
4
|
+
// The function interpolates the hue towards this target via
|
|
5
|
+
// the shortest angular path on the hue wheel.
|
|
6
|
+
//
|
|
7
|
+
// Parameters:
|
|
8
|
+
// color - Input color
|
|
9
|
+
// amount - Shift amount (0 = no change, 1 = fully warm), default 0.25
|
|
10
|
+
//
|
|
11
|
+
// Preserves lightness and chroma.
|
|
12
|
+
|
|
13
|
+
variable input: List = {input};
|
|
14
|
+
variable color: Color.OKLCH = input.get(0).to.oklch();
|
|
15
|
+
variable amount: Number = 0.25;
|
|
16
|
+
|
|
17
|
+
if (input.length() > 1) [
|
|
18
|
+
amount = input.get(1);
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// Warm hue target (orange in OKLCH is around 60°)
|
|
22
|
+
variable warm_hue: Number = 60;
|
|
23
|
+
|
|
24
|
+
// Calculate shortest path hue difference
|
|
25
|
+
variable hue_diff: Number = warm_hue - color.h;
|
|
26
|
+
|
|
27
|
+
// Wrap to shortest path
|
|
28
|
+
if (hue_diff > 180) [ hue_diff = hue_diff - 360; ];
|
|
29
|
+
if (hue_diff < -180) [ hue_diff = hue_diff + 360; ];
|
|
30
|
+
|
|
31
|
+
// Apply interpolation
|
|
32
|
+
variable new_hue: Number = color.h + (hue_diff * amount);
|
|
33
|
+
|
|
34
|
+
// Normalize to 0-360
|
|
35
|
+
if (new_hue < 0) [ new_hue = new_hue + 360; ];
|
|
36
|
+
if (new_hue >= 360) [ new_hue = new_hue - 360; ];
|
|
37
|
+
|
|
38
|
+
// Create result
|
|
39
|
+
variable result: Color.OKLCH;
|
|
40
|
+
result.l = color.l;
|
|
41
|
+
result.c = color.c;
|
|
42
|
+
result.h = new_hue;
|
|
43
|
+
|
|
44
|
+
return result;
|
|
45
|
+
|