@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,61 @@
|
|
|
1
|
+
// Generate a design system shade scale (like Tailwind 50-900)
|
|
2
|
+
// Input color becomes the middle (500) shade
|
|
3
|
+
//
|
|
4
|
+
// Lightness distribution:
|
|
5
|
+
// 50: ~0.97 (very light)
|
|
6
|
+
// 100: ~0.93
|
|
7
|
+
// 200: ~0.87
|
|
8
|
+
// 300: ~0.78
|
|
9
|
+
// 400: ~0.67
|
|
10
|
+
// 500: input lightness (base)
|
|
11
|
+
// 600: ~0.52
|
|
12
|
+
// 700: ~0.42
|
|
13
|
+
// 800: ~0.32
|
|
14
|
+
// 900: ~0.22 (very dark)
|
|
15
|
+
//
|
|
16
|
+
// Chroma is scaled to avoid washed-out lights and muddy darks
|
|
17
|
+
|
|
18
|
+
variable input: List = {input};
|
|
19
|
+
variable base: Color.OKLCH = input.get(0).to.oklch();
|
|
20
|
+
|
|
21
|
+
variable count: Number = 10;
|
|
22
|
+
if (input.length() > 1) [
|
|
23
|
+
count = input.get(1);
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
// Target lightness values for standard 10-step scale
|
|
27
|
+
// These are perceptually optimized for OKLCH
|
|
28
|
+
variable lightness_targets: List = 0.97, 0.93, 0.87, 0.78, 0.67, 0.55, 0.45, 0.35, 0.27, 0.20;
|
|
29
|
+
|
|
30
|
+
variable base_h: Number = base.h;
|
|
31
|
+
variable base_c: Number = base.c;
|
|
32
|
+
|
|
33
|
+
variable result: List;
|
|
34
|
+
variable i: Number = 0;
|
|
35
|
+
variable target_l: Number = 0;
|
|
36
|
+
variable l_factor: Number = 0;
|
|
37
|
+
variable scaled_c: Number = 0;
|
|
38
|
+
variable shade: Color.OKLCH;
|
|
39
|
+
|
|
40
|
+
while (i < count) [
|
|
41
|
+
target_l = lightness_targets.get(i);
|
|
42
|
+
|
|
43
|
+
// Scale chroma based on lightness
|
|
44
|
+
// Chroma peaks in midtones, reduces at extremes
|
|
45
|
+
l_factor = 1 - abs(target_l - 0.55) * 1.2;
|
|
46
|
+
if (l_factor < 0.3) [ l_factor = 0.3; ];
|
|
47
|
+
if (l_factor > 1.2) [ l_factor = 1.2; ];
|
|
48
|
+
|
|
49
|
+
scaled_c = base_c * l_factor;
|
|
50
|
+
if (scaled_c > 0.4) [ scaled_c = 0.4; ];
|
|
51
|
+
|
|
52
|
+
shade.l = target_l;
|
|
53
|
+
shade.c = scaled_c;
|
|
54
|
+
shade.h = base_h;
|
|
55
|
+
|
|
56
|
+
result = result, shade.to.srgb();
|
|
57
|
+
i = i + 1;
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
return result;
|
|
61
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Shade Scale function
|
|
3
|
+
* Generates a design system shade scale (like Tailwind 50-900)
|
|
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("Shade Scale Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("shade_scale", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Shade Scale");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("shade_scale");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("Function Execution", () => {
|
|
22
|
+
it("should generate 10 shades by default", async () => {
|
|
23
|
+
const result = await executeWithSchema(
|
|
24
|
+
"shade_scale",
|
|
25
|
+
"function",
|
|
26
|
+
`
|
|
27
|
+
variable base: Color.SRGB;
|
|
28
|
+
base.r = 0.2; base.g = 0.5; base.b = 0.9;
|
|
29
|
+
shade_scale(base)
|
|
30
|
+
`,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect(result).toBeDefined();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should generate specified number of shades", async () => {
|
|
37
|
+
const result = await executeWithSchema(
|
|
38
|
+
"shade_scale",
|
|
39
|
+
"function",
|
|
40
|
+
`
|
|
41
|
+
variable base: Color.SRGB;
|
|
42
|
+
base.r = 0.9; base.g = 0.3; base.b = 0.4;
|
|
43
|
+
shade_scale(base, 5)
|
|
44
|
+
`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(result).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should preserve hue across shades", async () => {
|
|
51
|
+
const result = await executeWithSchema(
|
|
52
|
+
"shade_scale",
|
|
53
|
+
"function",
|
|
54
|
+
`
|
|
55
|
+
variable green: Color.SRGB;
|
|
56
|
+
green.r = 0.2; green.g = 0.7; green.b = 0.3;
|
|
57
|
+
shade_scale(green, 10)
|
|
58
|
+
`,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(result).toBeDefined();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
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": "/api/v1/core/tokenscript/0/",
|
|
21
|
+
"script": "./split-complement.tokenscript"
|
|
22
|
+
},
|
|
23
|
+
"requirements": ["/api/v1/core/oklch-color/0/", "/api/v1/core/srgb-color/0/"]
|
|
24
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Generate split-complementary colors
|
|
2
|
+
// Returns [base, complement-angle, complement+angle]
|
|
3
|
+
//
|
|
4
|
+
// Use case: Balanced contrast with more variety than complement
|
|
5
|
+
// Example: Blue → Orange-Red, Orange-Yellow (instead of just Orange)
|
|
6
|
+
|
|
7
|
+
variable input: List = {input};
|
|
8
|
+
variable base: Color.OKLCH = input.get(0).to.oklch();
|
|
9
|
+
|
|
10
|
+
variable angle: Number = 30;
|
|
11
|
+
if (input.length() > 1) [
|
|
12
|
+
angle = input.get(1);
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
variable complement_h: Number = base.h + 180;
|
|
16
|
+
if (complement_h >= 360) [ complement_h = complement_h - 360; ];
|
|
17
|
+
|
|
18
|
+
variable result: List;
|
|
19
|
+
|
|
20
|
+
// Base color
|
|
21
|
+
result = result, base.to.srgb();
|
|
22
|
+
|
|
23
|
+
// Complement - angle
|
|
24
|
+
variable h2: Number = complement_h - angle;
|
|
25
|
+
if (h2 < 0) [ h2 = h2 + 360; ];
|
|
26
|
+
variable c2: Color.OKLCH;
|
|
27
|
+
c2.l = base.l; c2.c = base.c; c2.h = h2;
|
|
28
|
+
result = result, c2.to.srgb();
|
|
29
|
+
|
|
30
|
+
// Complement + angle
|
|
31
|
+
variable h3: Number = complement_h + angle;
|
|
32
|
+
if (h3 >= 360) [ h3 = h3 - 360; ];
|
|
33
|
+
variable c3: Color.OKLCH;
|
|
34
|
+
c3.l = base.l; c3.c = base.c; c3.h = h3;
|
|
35
|
+
result = result, c3.to.srgb();
|
|
36
|
+
|
|
37
|
+
return result;
|
|
38
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Split Complement function
|
|
3
|
+
* Generates split complementary colors (150° and 210° from base)
|
|
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("Split Complement Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema(
|
|
14
|
+
"split_complement",
|
|
15
|
+
"function",
|
|
16
|
+
)) as FunctionSpecification;
|
|
17
|
+
|
|
18
|
+
expect(schema.name).toBe("Split Complement");
|
|
19
|
+
expect(schema.type).toBe("function");
|
|
20
|
+
expect(schema.keyword).toBe("split_complement");
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe("Function Execution", () => {
|
|
25
|
+
it("should generate 3 colors", async () => {
|
|
26
|
+
const result = await executeWithSchema(
|
|
27
|
+
"split_complement",
|
|
28
|
+
"function",
|
|
29
|
+
`
|
|
30
|
+
variable base: Color.SRGB;
|
|
31
|
+
base.r = 0.9; base.g = 0.5; base.b = 0.2;
|
|
32
|
+
split_complement(base)
|
|
33
|
+
`,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
expect(result).toBeDefined();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should include the base color", async () => {
|
|
40
|
+
const result = await executeWithSchema(
|
|
41
|
+
"split_complement",
|
|
42
|
+
"function",
|
|
43
|
+
`
|
|
44
|
+
variable purple: Color.SRGB;
|
|
45
|
+
purple.r = 0.6; purple.g = 0.2; purple.b = 0.8;
|
|
46
|
+
split_complement(purple)
|
|
47
|
+
`,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
expect(result).toBeDefined();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
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": "/api/v1/core/tokenscript/0/",
|
|
25
|
+
"script": "./steps.tokenscript"
|
|
26
|
+
},
|
|
27
|
+
"requirements": ["/api/v1/core/oklch-color/0/", "/api/v1/core/srgb-color/0/"]
|
|
28
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Generate gradient steps between two colors in OKLCH space
|
|
2
|
+
// Returns a List of colors from start to end (inclusive)
|
|
3
|
+
//
|
|
4
|
+
// Uses perceptually uniform interpolation with shortest hue path
|
|
5
|
+
|
|
6
|
+
variable input: List = {input};
|
|
7
|
+
variable color1: Color.OKLCH = input.get(0).to.oklch();
|
|
8
|
+
variable color2: Color.OKLCH = input.get(1).to.oklch();
|
|
9
|
+
|
|
10
|
+
// Default count is 5
|
|
11
|
+
variable count: Number = 5;
|
|
12
|
+
if (input.length() > 2) [
|
|
13
|
+
count = input.get(2);
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
// Calculate hue difference (shortest path)
|
|
17
|
+
variable h1: Number = color1.h;
|
|
18
|
+
variable h2: Number = color2.h;
|
|
19
|
+
variable h_diff: Number = h2 - h1;
|
|
20
|
+
if (h_diff > 180) [ h_diff = h_diff - 360; ];
|
|
21
|
+
if (h_diff < -180) [ h_diff = h_diff + 360; ];
|
|
22
|
+
|
|
23
|
+
// Generate steps
|
|
24
|
+
variable result: List;
|
|
25
|
+
variable i: Number = 0;
|
|
26
|
+
variable t: Number = 0;
|
|
27
|
+
variable step_l: Number = 0;
|
|
28
|
+
variable step_c: Number = 0;
|
|
29
|
+
variable step_h: Number = 0;
|
|
30
|
+
variable step_color: Color.OKLCH;
|
|
31
|
+
|
|
32
|
+
while (i < count) [
|
|
33
|
+
t = i / (count - 1);
|
|
34
|
+
|
|
35
|
+
// Interpolate each component
|
|
36
|
+
step_l = color1.l + (color2.l - color1.l) * t;
|
|
37
|
+
step_c = color1.c + (color2.c - color1.c) * t;
|
|
38
|
+
step_h = h1 + h_diff * t;
|
|
39
|
+
|
|
40
|
+
// Normalize hue
|
|
41
|
+
if (step_h < 0) [ step_h = step_h + 360; ];
|
|
42
|
+
if (step_h >= 360) [ step_h = step_h - 360; ];
|
|
43
|
+
|
|
44
|
+
// Create color and add to list
|
|
45
|
+
step_color.l = step_l;
|
|
46
|
+
step_color.c = step_c;
|
|
47
|
+
step_color.h = step_h;
|
|
48
|
+
|
|
49
|
+
result = result, step_color.to.srgb();
|
|
50
|
+
i = i + 1;
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
return result;
|
|
54
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Steps function
|
|
3
|
+
* Generates gradient stops between two colors in OKLCH space
|
|
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("Steps Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("steps", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Steps");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("steps");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("Function Execution", () => {
|
|
22
|
+
it("should generate 5 steps by default", async () => {
|
|
23
|
+
const result = await executeWithSchema(
|
|
24
|
+
"steps",
|
|
25
|
+
"function",
|
|
26
|
+
`
|
|
27
|
+
variable start: Color.SRGB;
|
|
28
|
+
start.r = 1; start.g = 0; start.b = 0;
|
|
29
|
+
variable end: Color.SRGB;
|
|
30
|
+
end.r = 0; end.g = 0; end.b = 1;
|
|
31
|
+
steps(start, end)
|
|
32
|
+
`,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Result should be a list
|
|
36
|
+
expect(result).toBeDefined();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should generate specified number of steps", async () => {
|
|
40
|
+
const result = await executeWithSchema(
|
|
41
|
+
"steps",
|
|
42
|
+
"function",
|
|
43
|
+
`
|
|
44
|
+
variable start: Color.SRGB;
|
|
45
|
+
start.r = 0; start.g = 0; start.b = 0;
|
|
46
|
+
variable end: Color.SRGB;
|
|
47
|
+
end.r = 1; end.g = 1; end.b = 1;
|
|
48
|
+
steps(start, end, 3)
|
|
49
|
+
`,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
expect(result).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should include start and end colors", async () => {
|
|
56
|
+
const result = await executeWithSchema(
|
|
57
|
+
"steps",
|
|
58
|
+
"function",
|
|
59
|
+
`
|
|
60
|
+
variable white: Color.SRGB;
|
|
61
|
+
white.r = 1; white.g = 1; white.b = 1;
|
|
62
|
+
variable black: Color.SRGB;
|
|
63
|
+
black.r = 0; black.g = 0; black.b = 0;
|
|
64
|
+
steps(white, black, 5)
|
|
65
|
+
`,
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(result).toBeDefined();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
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": "/api/v1/core/tokenscript/0/",
|
|
17
|
+
"script": "./tetradic.tokenscript"
|
|
18
|
+
},
|
|
19
|
+
"requirements": ["/api/v1/core/oklch-color/0/", "/api/v1/core/srgb-color/0/"]
|
|
20
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Generate tetradic (square) colors (90° apart)
|
|
2
|
+
// Returns [base, base+90°, base+180°, base+270°]
|
|
3
|
+
//
|
|
4
|
+
// Use case: Rich, complex palettes
|
|
5
|
+
// Contains two complementary pairs
|
|
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 (0°)
|
|
13
|
+
result = result, base.to.srgb();
|
|
14
|
+
|
|
15
|
+
// +90°
|
|
16
|
+
variable h2: Number = base.h + 90;
|
|
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
|
+
// +180° (complement)
|
|
23
|
+
variable h3: Number = base.h + 180;
|
|
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
|
+
// +270°
|
|
30
|
+
variable h4: Number = base.h + 270;
|
|
31
|
+
if (h4 >= 360) [ h4 = h4 - 360; ];
|
|
32
|
+
variable c4: Color.OKLCH;
|
|
33
|
+
c4.l = base.l; c4.c = base.c; c4.h = h4;
|
|
34
|
+
result = result, c4.to.srgb();
|
|
35
|
+
|
|
36
|
+
return result;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Tetradic function
|
|
3
|
+
* Generates tetradic colors (90° 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("Tetradic Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("tetradic", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Tetradic");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("tetradic");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("Function Execution", () => {
|
|
22
|
+
it("should generate 4 colors", async () => {
|
|
23
|
+
const result = await executeWithSchema(
|
|
24
|
+
"tetradic",
|
|
25
|
+
"function",
|
|
26
|
+
`
|
|
27
|
+
variable base: Color.SRGB;
|
|
28
|
+
base.r = 0.8; base.g = 0.2; base.b = 0.4;
|
|
29
|
+
tetradic(base)
|
|
30
|
+
`,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect(result).toBeDefined();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should include the base color", async () => {
|
|
37
|
+
const result = await executeWithSchema(
|
|
38
|
+
"tetradic",
|
|
39
|
+
"function",
|
|
40
|
+
`
|
|
41
|
+
variable green: Color.SRGB;
|
|
42
|
+
green.r = 0.2; green.g = 0.8; green.b = 0.3;
|
|
43
|
+
tetradic(green)
|
|
44
|
+
`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(result).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
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": "/api/v1/core/tokenscript/0/",
|
|
29
|
+
"script": "./tint-scale.tokenscript"
|
|
30
|
+
},
|
|
31
|
+
"requirements": ["/api/v1/core/oklch-color/0/", "/api/v1/core/srgb-color/0/"]
|
|
32
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Create a sequential tint scale from a base color
|
|
2
|
+
// Varies lightness while preserving hue and scaling chroma
|
|
3
|
+
//
|
|
4
|
+
// Ideal for: choropleth maps, intensity scales, single-hue heatmaps
|
|
5
|
+
// Chroma is scaled proportionally to maintain color harmony
|
|
6
|
+
|
|
7
|
+
variable input: List = {input};
|
|
8
|
+
variable base: Color.OKLCH = input.get(0).to.oklch();
|
|
9
|
+
|
|
10
|
+
// Default count is 9
|
|
11
|
+
variable count: Number = 9;
|
|
12
|
+
if (input.length() > 1) [
|
|
13
|
+
count = input.get(1);
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
// Default light_start is 0.95 (nearly white)
|
|
17
|
+
variable light_start: Number = 0.95;
|
|
18
|
+
if (input.length() > 2) [
|
|
19
|
+
light_start = input.get(2);
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
// Default light_end is 0.25 (dark)
|
|
23
|
+
variable light_end: Number = 0.25;
|
|
24
|
+
if (input.length() > 3) [
|
|
25
|
+
light_end = input.get(3);
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
// Base color properties
|
|
29
|
+
variable base_h: Number = base.h;
|
|
30
|
+
variable base_c: Number = base.c;
|
|
31
|
+
variable base_l: Number = base.l;
|
|
32
|
+
|
|
33
|
+
// Calculate chroma scaling factor (chroma decreases at extreme lightness)
|
|
34
|
+
variable max_c: Number = base_c * 1.2;
|
|
35
|
+
|
|
36
|
+
variable result: List;
|
|
37
|
+
variable i: Number = 0;
|
|
38
|
+
variable t: Number = 0;
|
|
39
|
+
variable step_l: Number = 0;
|
|
40
|
+
variable l_dist: Number = 0;
|
|
41
|
+
variable chroma_scale: Number = 0;
|
|
42
|
+
variable step_c: Number = 0;
|
|
43
|
+
variable color: Color.OKLCH;
|
|
44
|
+
|
|
45
|
+
while (i < count) [
|
|
46
|
+
t = i / (count - 1);
|
|
47
|
+
|
|
48
|
+
// Interpolate lightness
|
|
49
|
+
step_l = light_start + (light_end - light_start) * t;
|
|
50
|
+
|
|
51
|
+
// Scale chroma based on lightness distance from optimal (~0.6)
|
|
52
|
+
// Chroma is highest in midtones, lower at extremes
|
|
53
|
+
l_dist = step_l - 0.6;
|
|
54
|
+
if (l_dist < 0) [ l_dist = 0 - l_dist; ];
|
|
55
|
+
chroma_scale = 1 - l_dist * 1.5;
|
|
56
|
+
if (chroma_scale < 0.1) [ chroma_scale = 0.1; ];
|
|
57
|
+
step_c = max_c * chroma_scale;
|
|
58
|
+
|
|
59
|
+
// Clamp chroma
|
|
60
|
+
if (step_c > 0.4) [ step_c = 0.4; ];
|
|
61
|
+
|
|
62
|
+
color.l = step_l;
|
|
63
|
+
color.c = step_c;
|
|
64
|
+
color.h = base_h;
|
|
65
|
+
|
|
66
|
+
result = result, color.to.srgb();
|
|
67
|
+
i = i + 1;
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
return result;
|
|
71
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Tint Scale function
|
|
3
|
+
* Creates a sequential tint scale from a base 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("Tint Scale Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("tint_scale", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Tint Scale");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("tint_scale");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("Function Execution", () => {
|
|
22
|
+
it("should generate 9 tints by default", async () => {
|
|
23
|
+
const result = await executeWithSchema(
|
|
24
|
+
"tint_scale",
|
|
25
|
+
"function",
|
|
26
|
+
`
|
|
27
|
+
variable base: Color.SRGB;
|
|
28
|
+
base.r = 0.2; base.g = 0.5; base.b = 0.8;
|
|
29
|
+
tint_scale(base)
|
|
30
|
+
`,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect(result).toBeDefined();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should generate specified number of tints", async () => {
|
|
37
|
+
const result = await executeWithSchema(
|
|
38
|
+
"tint_scale",
|
|
39
|
+
"function",
|
|
40
|
+
`
|
|
41
|
+
variable base: Color.SRGB;
|
|
42
|
+
base.r = 0.6; base.g = 0.3; base.b = 0.7;
|
|
43
|
+
tint_scale(base, 5)
|
|
44
|
+
`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(result).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should preserve hue across scale", async () => {
|
|
51
|
+
const result = await executeWithSchema(
|
|
52
|
+
"tint_scale",
|
|
53
|
+
"function",
|
|
54
|
+
`
|
|
55
|
+
variable blue: Color.SRGB;
|
|
56
|
+
blue.r = 0.1; blue.g = 0.2; blue.b = 0.9;
|
|
57
|
+
tint_scale(blue, 3)
|
|
58
|
+
`,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(result).toBeDefined();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|