@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,58 @@
|
|
|
1
|
+
// Create a diverging color palette for data visualization
|
|
2
|
+
// Goes: color1 → neutral → color2
|
|
3
|
+
//
|
|
4
|
+
// Ideal for: heatmaps, correlation matrices, deviation from mean
|
|
5
|
+
// Example: blue → white → red for temperature anomalies
|
|
6
|
+
|
|
7
|
+
variable input: List = {input};
|
|
8
|
+
variable color1: Color.OKLCH = input.get(0).to.oklch();
|
|
9
|
+
variable color2: Color.OKLCH = input.get(1).to.oklch();
|
|
10
|
+
|
|
11
|
+
// Default count is 9 (gives clear midpoint at index 4)
|
|
12
|
+
variable count: Number = 9;
|
|
13
|
+
if (input.length() > 2) [
|
|
14
|
+
count = input.get(2);
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
// Default neutral lightness is 0.95 (near white)
|
|
18
|
+
variable neutral_l: Number = 0.95;
|
|
19
|
+
if (input.length() > 3) [
|
|
20
|
+
neutral_l = input.get(3);
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// Calculate midpoint index
|
|
24
|
+
variable mid: Number = (count - 1) / 2;
|
|
25
|
+
|
|
26
|
+
variable result: List;
|
|
27
|
+
variable i: Number = 0;
|
|
28
|
+
variable t: Number = 0;
|
|
29
|
+
variable step_color: Color.OKLCH;
|
|
30
|
+
|
|
31
|
+
while (i < count) [
|
|
32
|
+
if (i < mid) [
|
|
33
|
+
// First half: color1 → neutral
|
|
34
|
+
t = i / mid;
|
|
35
|
+
step_color.l = color1.l + (neutral_l - color1.l) * t;
|
|
36
|
+
step_color.c = color1.c * (1 - t);
|
|
37
|
+
step_color.h = color1.h;
|
|
38
|
+
] else [
|
|
39
|
+
if (i == mid) [
|
|
40
|
+
// Midpoint: neutral (achromatic)
|
|
41
|
+
step_color.l = neutral_l;
|
|
42
|
+
step_color.c = 0;
|
|
43
|
+
step_color.h = 0;
|
|
44
|
+
] else [
|
|
45
|
+
// Second half: neutral → color2
|
|
46
|
+
t = (i - mid) / mid;
|
|
47
|
+
step_color.l = neutral_l + (color2.l - neutral_l) * t;
|
|
48
|
+
step_color.c = color2.c * t;
|
|
49
|
+
step_color.h = color2.h;
|
|
50
|
+
];
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
result = result, step_color.to.srgb();
|
|
54
|
+
i = i + 1;
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
return result;
|
|
58
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Diverging",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Creates a diverging color palette for heatmaps. Goes from color1 through a neutral midpoint to color2. Perfect for data that diverges from a center value (e.g., -1 to 0 to +1).",
|
|
5
|
+
"keyword": "diverging",
|
|
6
|
+
"input": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"color1": {
|
|
10
|
+
"type": "color",
|
|
11
|
+
"description": "Color for negative/low end (e.g., blue)"
|
|
12
|
+
},
|
|
13
|
+
"color2": {
|
|
14
|
+
"type": "color",
|
|
15
|
+
"description": "Color for positive/high end (e.g., red)"
|
|
16
|
+
},
|
|
17
|
+
"count": {
|
|
18
|
+
"type": "number",
|
|
19
|
+
"description": "Number of steps (should be odd for clear midpoint). Default is 9"
|
|
20
|
+
},
|
|
21
|
+
"neutral": {
|
|
22
|
+
"type": "number",
|
|
23
|
+
"description": "Lightness of neutral midpoint (0-1). Default is 0.95 (near white)"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"script": {
|
|
28
|
+
"type": "/api/v1/core/tokenscript/0/",
|
|
29
|
+
"script": "./diverging.tokenscript"
|
|
30
|
+
},
|
|
31
|
+
"requirements": ["/api/v1/core/oklch-color/0/", "/api/v1/core/srgb-color/0/"]
|
|
32
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Diverging function
|
|
3
|
+
* Creates a diverging color palette for data visualization
|
|
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("Diverging Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("diverging", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Diverging");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("diverging");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("Function Execution", () => {
|
|
22
|
+
it("should generate 9 steps by default", async () => {
|
|
23
|
+
const result = await executeWithSchema(
|
|
24
|
+
"diverging",
|
|
25
|
+
"function",
|
|
26
|
+
`
|
|
27
|
+
variable cold: Color.SRGB;
|
|
28
|
+
cold.r = 0.2; cold.g = 0.4; cold.b = 0.8;
|
|
29
|
+
variable hot: Color.SRGB;
|
|
30
|
+
hot.r = 0.8; hot.g = 0.2; hot.b = 0.2;
|
|
31
|
+
diverging(cold, hot)
|
|
32
|
+
`,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
expect(result).toBeDefined();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should generate specified number of steps", async () => {
|
|
39
|
+
const result = await executeWithSchema(
|
|
40
|
+
"diverging",
|
|
41
|
+
"function",
|
|
42
|
+
`
|
|
43
|
+
variable blue: Color.SRGB;
|
|
44
|
+
blue.r = 0; blue.g = 0.3; blue.b = 0.7;
|
|
45
|
+
variable red: Color.SRGB;
|
|
46
|
+
red.r = 0.7; red.g = 0.1; red.b = 0.1;
|
|
47
|
+
diverging(blue, red, 5)
|
|
48
|
+
`,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect(result).toBeDefined();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should have neutral midpoint", async () => {
|
|
55
|
+
const result = await executeWithSchema(
|
|
56
|
+
"diverging",
|
|
57
|
+
"function",
|
|
58
|
+
`
|
|
59
|
+
variable neg: Color.SRGB;
|
|
60
|
+
neg.r = 0; neg.g = 0.5; neg.b = 0.8;
|
|
61
|
+
variable pos: Color.SRGB;
|
|
62
|
+
pos.r = 0.9; pos.g = 0.4; pos.b = 0;
|
|
63
|
+
diverging(neg, pos, 9)
|
|
64
|
+
`,
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
expect(result).toBeDefined();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Convert a color to grayscale by setting OKLCH chroma to 0
|
|
2
|
+
// This preserves perceptual lightness (unlike simple RGB averaging)
|
|
3
|
+
|
|
4
|
+
variable input: List = {input};
|
|
5
|
+
variable color: Color.OKLCH = input.get(0).to.oklch();
|
|
6
|
+
|
|
7
|
+
// Create grayscale by removing chroma
|
|
8
|
+
variable result: Color.OKLCH;
|
|
9
|
+
result.l = color.l;
|
|
10
|
+
result.c = 0;
|
|
11
|
+
result.h = 0;
|
|
12
|
+
|
|
13
|
+
return result;
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Grayscale",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Converts a color to grayscale by removing all chroma in OKLCH space. Preserves perceptual lightness.",
|
|
5
|
+
"keyword": "grayscale",
|
|
6
|
+
"input": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"color": {
|
|
10
|
+
"type": "color",
|
|
11
|
+
"description": "The color to convert to grayscale"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"script": {
|
|
16
|
+
"type": "/api/v1/core/tokenscript/0/",
|
|
17
|
+
"script": "./grayscale.tokenscript"
|
|
18
|
+
},
|
|
19
|
+
"requirements": ["/api/v1/core/oklch-color/0/", "/api/v1/core/srgb-color/0/"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Grayscale function
|
|
3
|
+
* Converts color to grayscale by setting OKLCH chroma to 0
|
|
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("Grayscale Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("grayscale", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Grayscale");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("grayscale");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("Function Execution", () => {
|
|
22
|
+
it("should convert colored to grayscale", async () => {
|
|
23
|
+
const result = await executeWithSchema(
|
|
24
|
+
"grayscale",
|
|
25
|
+
"function",
|
|
26
|
+
`
|
|
27
|
+
variable red: Color.SRGB;
|
|
28
|
+
red.r = 0.8; red.g = 0.2; red.b = 0.2;
|
|
29
|
+
grayscale(red).to.srgb()
|
|
30
|
+
`,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
34
|
+
const r = (result as any).value.r.value;
|
|
35
|
+
const g = (result as any).value.g.value;
|
|
36
|
+
const b = (result as any).value.b.value;
|
|
37
|
+
// All channels should be approximately equal (gray)
|
|
38
|
+
expect(Math.abs(r - g)).toBeLessThan(0.05);
|
|
39
|
+
expect(Math.abs(g - b)).toBeLessThan(0.05);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should preserve lightness", async () => {
|
|
43
|
+
const result = await executeWithSchema(
|
|
44
|
+
"grayscale",
|
|
45
|
+
"function",
|
|
46
|
+
`
|
|
47
|
+
variable bright: Color.SRGB;
|
|
48
|
+
bright.r = 0.9; bright.g = 0.9; bright.b = 0.3;
|
|
49
|
+
grayscale(bright).to.srgb()
|
|
50
|
+
`,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
54
|
+
const r = (result as any).value.r.value;
|
|
55
|
+
// Should still be relatively bright
|
|
56
|
+
expect(r).toBeGreaterThan(0.5);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should handle already gray colors", async () => {
|
|
60
|
+
const result = await executeWithSchema(
|
|
61
|
+
"grayscale",
|
|
62
|
+
"function",
|
|
63
|
+
`
|
|
64
|
+
variable gray: Color.SRGB;
|
|
65
|
+
gray.r = 0.5; gray.g = 0.5; gray.b = 0.5;
|
|
66
|
+
grayscale(gray).to.srgb()
|
|
67
|
+
`,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
71
|
+
const r = (result as any).value.r.value;
|
|
72
|
+
const g = (result as any).value.g.value;
|
|
73
|
+
const b = (result as any).value.b.value;
|
|
74
|
+
expect(r).toBeCloseTo(0.5, 1);
|
|
75
|
+
expect(g).toBeCloseTo(0.5, 1);
|
|
76
|
+
expect(b).toBeCloseTo(0.5, 1);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// harmonize: Shift hue towards a source color for visual harmony
|
|
2
|
+
// Reference: Material Design 3 Color System
|
|
3
|
+
// Reference: https://m3.material.io/styles/color/dynamic-color
|
|
4
|
+
//
|
|
5
|
+
// Shifts the input color's hue towards a source color by a specified
|
|
6
|
+
// amount, creating a harmonized palette. Uses OKLCH for perceptually
|
|
7
|
+
// uniform hue interpolation via the shortest angular path.
|
|
8
|
+
//
|
|
9
|
+
// Parameters:
|
|
10
|
+
// color - Color to harmonize
|
|
11
|
+
// source - Target hue source
|
|
12
|
+
// amount - Shift amount (0 = no change, 1 = match source), default 0.5
|
|
13
|
+
//
|
|
14
|
+
// Input: Any color space (converted to OKLCH internally)
|
|
15
|
+
// Output: OKLCH (working space)
|
|
16
|
+
// To get sRGB: harmonize(color, source, 0.5).to.srgb()
|
|
17
|
+
|
|
18
|
+
variable input: List = {input};
|
|
19
|
+
variable color: Color.OKLCH = input.get(0).to.oklch();
|
|
20
|
+
variable source: Color.OKLCH = input.get(1).to.oklch();
|
|
21
|
+
|
|
22
|
+
// Default harmonization amount (0.5 = 50% shift)
|
|
23
|
+
variable amount: Number = 0.5;
|
|
24
|
+
if (input.length() > 2) [
|
|
25
|
+
amount = input.get(2);
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
// Get hues
|
|
29
|
+
variable color_hue: Number = color.h;
|
|
30
|
+
variable source_hue: Number = source.h;
|
|
31
|
+
|
|
32
|
+
// Calculate shortest path around the hue circle
|
|
33
|
+
variable diff: Number = source_hue - color_hue;
|
|
34
|
+
|
|
35
|
+
// Normalize to -180 to 180 range for shortest path
|
|
36
|
+
if (diff > 180) [
|
|
37
|
+
diff = diff - 360;
|
|
38
|
+
];
|
|
39
|
+
if (diff < -180) [
|
|
40
|
+
diff = diff + 360;
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
// Apply harmonization: shift hue by amount * difference
|
|
44
|
+
variable new_hue: Number = color_hue + (diff * amount);
|
|
45
|
+
|
|
46
|
+
// Normalize hue to 0-360
|
|
47
|
+
if (new_hue < 0) [
|
|
48
|
+
new_hue = new_hue + 360;
|
|
49
|
+
];
|
|
50
|
+
if (new_hue >= 360) [
|
|
51
|
+
new_hue = new_hue - 360;
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
// Create result with shifted hue, preserving lightness and chroma
|
|
55
|
+
variable result: Color.OKLCH;
|
|
56
|
+
result.l = color.l;
|
|
57
|
+
result.c = color.c;
|
|
58
|
+
result.h = new_hue;
|
|
59
|
+
|
|
60
|
+
return result;
|
|
61
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "harmonize",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Harmonizes a color by shifting its hue toward a source color. Inspired by Material Design 3's color harmonization algorithm. This creates visual cohesion in design systems by making colors feel related while preserving their identity. The amount parameter controls how much the hue shifts (0 = no change, 1 = full shift to source hue).",
|
|
5
|
+
"keyword": "harmonize",
|
|
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 harmonize",
|
|
15
|
+
"type": "color"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"description": "Source color (hue target)",
|
|
19
|
+
"type": "color"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"description": "Amount of harmonization (0-1, default 0.5)",
|
|
23
|
+
"type": "number"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"minItems": 2,
|
|
27
|
+
"maxItems": 3
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": ["input"]
|
|
31
|
+
},
|
|
32
|
+
"returns": {
|
|
33
|
+
"type": "color",
|
|
34
|
+
"description": "Harmonized color with hue shifted toward source"
|
|
35
|
+
},
|
|
36
|
+
"script": {
|
|
37
|
+
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
38
|
+
"script": "./harmonize.tokenscript"
|
|
39
|
+
},
|
|
40
|
+
"examples": [
|
|
41
|
+
{
|
|
42
|
+
"description": "Harmonize red toward blue",
|
|
43
|
+
"input": ["#ff0000", "#0000ff", 0.3],
|
|
44
|
+
"output": "Color with hue shifted toward blue"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"description": "Harmonize green toward brand color",
|
|
48
|
+
"input": ["#00ff00", "#6750a4"],
|
|
49
|
+
"output": "Green shifted toward purple brand"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the harmonize function
|
|
3
|
+
* Shifts a color's hue toward a source color
|
|
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("harmonize function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("harmonize", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("harmonize");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("Function Execution", () => {
|
|
21
|
+
it("should shift hue toward source color", async () => {
|
|
22
|
+
const result = await executeWithSchema(
|
|
23
|
+
"harmonize",
|
|
24
|
+
"function",
|
|
25
|
+
`
|
|
26
|
+
variable color: Color.SRGB;
|
|
27
|
+
color.r = 1; color.g = 0; color.b = 0;
|
|
28
|
+
variable source: Color.SRGB;
|
|
29
|
+
source.r = 0; source.g = 0; source.b = 1;
|
|
30
|
+
harmonize(color, source, 0.5).to.srgb()
|
|
31
|
+
`,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(result).toBeDefined();
|
|
35
|
+
expect((result as any).constructor.name).toBe("ColorSymbol");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should return original color with amount 0", async () => {
|
|
39
|
+
const result = await executeWithSchema(
|
|
40
|
+
"harmonize",
|
|
41
|
+
"function",
|
|
42
|
+
`
|
|
43
|
+
variable color: Color.SRGB;
|
|
44
|
+
color.r = 1; color.g = 0; color.b = 0;
|
|
45
|
+
variable source: Color.SRGB;
|
|
46
|
+
source.r = 0; source.g = 0; source.b = 1;
|
|
47
|
+
harmonize(color, source, 0).to.srgb()
|
|
48
|
+
`,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect(result).toBeDefined();
|
|
52
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
53
|
+
expect(r).toBeCloseTo(1, 1);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// hue: Extract hue angle from a color
|
|
2
|
+
// Reference: OKLCH Color Space (Björn Ottosson)
|
|
3
|
+
// Reference: https://bottosson.github.io/posts/oklab/
|
|
4
|
+
//
|
|
5
|
+
// Returns the H component from OKLCH, representing the
|
|
6
|
+
// perceptually uniform hue angle. Range: 0-360 degrees.
|
|
7
|
+
|
|
8
|
+
variable input: List = {input};
|
|
9
|
+
variable color: Color.OKLCH = input.get(0).to.oklch();
|
|
10
|
+
|
|
11
|
+
return color.h;
|
|
12
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hue",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Extracts the hue angle from any color using OKLCH. Returns a value from 0 to 360 degrees representing the color's position on the hue wheel. Hue in OKLCH is perceptually uniform, meaning equal angular steps produce equally perceived hue changes. Essential for color harmony calculations and palette generation.",
|
|
5
|
+
"keyword": "hue",
|
|
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 extract hue from",
|
|
15
|
+
"type": "color"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"minItems": 1,
|
|
19
|
+
"maxItems": 1
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"required": ["input"]
|
|
23
|
+
},
|
|
24
|
+
"returns": {
|
|
25
|
+
"type": "number",
|
|
26
|
+
"description": "Hue angle (0-360 degrees)"
|
|
27
|
+
},
|
|
28
|
+
"script": {
|
|
29
|
+
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
30
|
+
"script": "./hue.tokenscript"
|
|
31
|
+
},
|
|
32
|
+
"examples": [
|
|
33
|
+
{
|
|
34
|
+
"description": "Red has hue around 30° in OKLCH",
|
|
35
|
+
"input": ["#ff0000"],
|
|
36
|
+
"output": 29
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"description": "Cyan has hue around 195°",
|
|
40
|
+
"input": ["#00ffff"],
|
|
41
|
+
"output": 195
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the hue function
|
|
3
|
+
* Extracts hue angle from a color
|
|
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("hue function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("hue", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("hue");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("Function Execution", () => {
|
|
21
|
+
it("should return hue for red (~30° in OKLCH)", async () => {
|
|
22
|
+
const result = await executeWithSchema(
|
|
23
|
+
"hue",
|
|
24
|
+
"function",
|
|
25
|
+
`
|
|
26
|
+
variable red: Color.SRGB;
|
|
27
|
+
red.r = 1; red.g = 0; red.b = 0;
|
|
28
|
+
hue(red)
|
|
29
|
+
`,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(result).toBeDefined();
|
|
33
|
+
const h = (result as any).value ?? result;
|
|
34
|
+
// Red in OKLCH has hue around 29-30°
|
|
35
|
+
expect(h).toBeGreaterThan(20);
|
|
36
|
+
expect(h).toBeLessThan(40);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should return hue for green (~142° in OKLCH)", async () => {
|
|
40
|
+
const result = await executeWithSchema(
|
|
41
|
+
"hue",
|
|
42
|
+
"function",
|
|
43
|
+
`
|
|
44
|
+
variable green: Color.SRGB;
|
|
45
|
+
green.r = 0; green.g = 1; green.b = 0;
|
|
46
|
+
hue(green)
|
|
47
|
+
`,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
expect(result).toBeDefined();
|
|
51
|
+
const h = (result as any).value ?? result;
|
|
52
|
+
// Green in OKLCH has hue around 142°
|
|
53
|
+
expect(h).toBeGreaterThan(130);
|
|
54
|
+
expect(h).toBeLessThan(160);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should return hue for blue (~264° in OKLCH)", async () => {
|
|
58
|
+
const result = await executeWithSchema(
|
|
59
|
+
"hue",
|
|
60
|
+
"function",
|
|
61
|
+
`
|
|
62
|
+
variable blue: Color.SRGB;
|
|
63
|
+
blue.r = 0; blue.g = 0; blue.b = 1;
|
|
64
|
+
hue(blue)
|
|
65
|
+
`,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(result).toBeDefined();
|
|
69
|
+
const h = (result as any).value ?? result;
|
|
70
|
+
// Blue in OKLCH has hue around 264°
|
|
71
|
+
expect(h).toBeGreaterThan(250);
|
|
72
|
+
expect(h).toBeLessThan(280);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Hue Difference
|
|
2
|
+
// Calculates angular hue difference using shortest path
|
|
3
|
+
//
|
|
4
|
+
// The hue circle wraps at 360°, so we need to find
|
|
5
|
+
// the shortest angular distance between two hues.
|
|
6
|
+
//
|
|
7
|
+
// Examples:
|
|
8
|
+
// hue_diff(350°, 10°) = 20° (not 340°)
|
|
9
|
+
// hue_diff(0°, 180°) = 180° (maximum difference)
|
|
10
|
+
// hue_diff(90°, 90°) = 0° (same hue)
|
|
11
|
+
//
|
|
12
|
+
// Returns value in range [0, 180]
|
|
13
|
+
|
|
14
|
+
variable input: List = {input};
|
|
15
|
+
variable color1: Color.OKLCH = input.get(0).to.oklch();
|
|
16
|
+
variable color2: Color.OKLCH = input.get(1).to.oklch();
|
|
17
|
+
|
|
18
|
+
// Get hue values
|
|
19
|
+
variable h1: Number = color1.h;
|
|
20
|
+
variable h2: Number = color2.h;
|
|
21
|
+
|
|
22
|
+
// Normalize to 0-360
|
|
23
|
+
if (h1 < 0) [ h1 = h1 + 360; ];
|
|
24
|
+
if (h1 >= 360) [ h1 = h1 - 360; ];
|
|
25
|
+
if (h2 < 0) [ h2 = h2 + 360; ];
|
|
26
|
+
if (h2 >= 360) [ h2 = h2 - 360; ];
|
|
27
|
+
|
|
28
|
+
// Calculate raw difference
|
|
29
|
+
variable diff: Number = h1 - h2;
|
|
30
|
+
|
|
31
|
+
// Make positive
|
|
32
|
+
if (diff < 0) [
|
|
33
|
+
diff = 0 - diff;
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
// Take shortest path around circle
|
|
37
|
+
if (diff > 180) [
|
|
38
|
+
diff = 360 - diff;
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
return diff;
|
|
42
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Hue Difference",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Calculates the angular difference between two color hues. Returns the shortest path around the hue circle (0-180°). Useful for determining how different two colors are in terms of hue alone, ignoring lightness and chroma.",
|
|
5
|
+
"keyword": "hue_difference",
|
|
6
|
+
"input": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"color1": {
|
|
10
|
+
"type": "color",
|
|
11
|
+
"description": "First color"
|
|
12
|
+
},
|
|
13
|
+
"color2": {
|
|
14
|
+
"type": "color",
|
|
15
|
+
"description": "Second color"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"script": {
|
|
20
|
+
"type": "/api/v1/core/tokenscript/0/",
|
|
21
|
+
"script": "./hue-difference.tokenscript"
|
|
22
|
+
},
|
|
23
|
+
"requirements": ["/api/v1/core/oklch-color/0/"]
|
|
24
|
+
}
|