@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,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Mix function
|
|
3
|
+
* Interpolates 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("Mix Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("mix", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Mix");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("mix");
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe("Function Execution", () => {
|
|
22
|
+
it("should mix red and blue at 50%", async () => {
|
|
23
|
+
const result = await executeWithSchema(
|
|
24
|
+
"mix",
|
|
25
|
+
"function",
|
|
26
|
+
`
|
|
27
|
+
variable red: Color.SRGB;
|
|
28
|
+
red.r = 1; red.g = 0; red.b = 0;
|
|
29
|
+
variable blue: Color.SRGB;
|
|
30
|
+
blue.r = 0; blue.g = 0; blue.b = 1;
|
|
31
|
+
mix(red, blue, 0.5).to.srgb()
|
|
32
|
+
`,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
36
|
+
const r = (result as any).value.r.value;
|
|
37
|
+
const b = (result as any).value.b.value;
|
|
38
|
+
// Should have both red and blue components
|
|
39
|
+
expect(r).toBeGreaterThan(0.2);
|
|
40
|
+
expect(b).toBeGreaterThan(0.2);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should return first color at 0%", async () => {
|
|
44
|
+
const result = await executeWithSchema(
|
|
45
|
+
"mix",
|
|
46
|
+
"function",
|
|
47
|
+
`
|
|
48
|
+
variable white: Color.SRGB;
|
|
49
|
+
white.r = 1; white.g = 1; white.b = 1;
|
|
50
|
+
variable black: Color.SRGB;
|
|
51
|
+
black.r = 0; black.g = 0; black.b = 0;
|
|
52
|
+
mix(white, black, 0).to.srgb()
|
|
53
|
+
`,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
57
|
+
const r = (result as any).value.r.value;
|
|
58
|
+
expect(r).toBeCloseTo(1, 1);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should return second color at 100%", async () => {
|
|
62
|
+
const result = await executeWithSchema(
|
|
63
|
+
"mix",
|
|
64
|
+
"function",
|
|
65
|
+
`
|
|
66
|
+
variable white: Color.SRGB;
|
|
67
|
+
white.r = 1; white.g = 1; white.b = 1;
|
|
68
|
+
variable black: Color.SRGB;
|
|
69
|
+
black.r = 0; black.g = 0; black.b = 0;
|
|
70
|
+
mix(white, black, 1).to.srgb()
|
|
71
|
+
`,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
75
|
+
const r = (result as any).value.r.value;
|
|
76
|
+
expect(r).toBeCloseTo(0, 1);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("should default to 50% mix", async () => {
|
|
80
|
+
const result = await executeWithSchema(
|
|
81
|
+
"mix",
|
|
82
|
+
"function",
|
|
83
|
+
`
|
|
84
|
+
variable c1: Color.SRGB;
|
|
85
|
+
c1.r = 0.8; c1.g = 0.2; c1.b = 0.2;
|
|
86
|
+
variable c2: Color.SRGB;
|
|
87
|
+
c2.r = 0.2; c2.g = 0.8; c2.b = 0.2;
|
|
88
|
+
mix(c1, c2).to.srgb()
|
|
89
|
+
`,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Monochromatic Color Palette
|
|
2
|
+
// Generates variations of a single hue with different lightness
|
|
3
|
+
//
|
|
4
|
+
// A monochromatic scheme uses:
|
|
5
|
+
// - Same hue throughout
|
|
6
|
+
// - Varying lightness (from light tints to dark shades)
|
|
7
|
+
// - Varying chroma (reduced at extremes for natural appearance)
|
|
8
|
+
//
|
|
9
|
+
// This creates harmonious, cohesive palettes ideal for:
|
|
10
|
+
// - UI background/foreground variations
|
|
11
|
+
// - Data visualization with single-variable emphasis
|
|
12
|
+
// - Brand color systems
|
|
13
|
+
|
|
14
|
+
variable input: List = {input};
|
|
15
|
+
variable base: Color.OKLCH = input.get(0).to.oklch();
|
|
16
|
+
|
|
17
|
+
// Default count is 5
|
|
18
|
+
variable count: Number = 5;
|
|
19
|
+
if (input.length() > 1) [
|
|
20
|
+
count = input.get(1);
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// Preserve the hue
|
|
24
|
+
variable base_h: Number = base.h;
|
|
25
|
+
variable base_c: Number = base.c;
|
|
26
|
+
|
|
27
|
+
// Define lightness range (from light to dark)
|
|
28
|
+
variable light_start: Number = 0.9;
|
|
29
|
+
variable light_end: Number = 0.3;
|
|
30
|
+
|
|
31
|
+
variable result: List;
|
|
32
|
+
variable i: Number = 0;
|
|
33
|
+
variable t: Number = 0;
|
|
34
|
+
variable step_l: Number = 0;
|
|
35
|
+
variable l_factor: Number = 0;
|
|
36
|
+
variable step_c: Number = 0;
|
|
37
|
+
variable color: Color.OKLCH;
|
|
38
|
+
|
|
39
|
+
while (i < count) [
|
|
40
|
+
// Calculate interpolation factor
|
|
41
|
+
if (count > 1) [
|
|
42
|
+
t = i / (count - 1);
|
|
43
|
+
] else [
|
|
44
|
+
t = 0.5;
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
// Interpolate lightness
|
|
48
|
+
step_l = light_start + (light_end - light_start) * t;
|
|
49
|
+
|
|
50
|
+
// Scale chroma - reduce at extremes for natural appearance
|
|
51
|
+
// Peak chroma around middle lightness (0.6)
|
|
52
|
+
l_factor = step_l - 0.6;
|
|
53
|
+
if (l_factor < 0) [ l_factor = 0 - l_factor; ];
|
|
54
|
+
l_factor = 1 - l_factor * 1.5;
|
|
55
|
+
if (l_factor < 0.3) [ l_factor = 0.3; ];
|
|
56
|
+
if (l_factor > 1) [ l_factor = 1; ];
|
|
57
|
+
|
|
58
|
+
step_c = base_c * l_factor;
|
|
59
|
+
|
|
60
|
+
// Clamp chroma to avoid out-of-gamut
|
|
61
|
+
if (step_c > 0.35) [ step_c = 0.35; ];
|
|
62
|
+
|
|
63
|
+
color.l = step_l;
|
|
64
|
+
color.c = step_c;
|
|
65
|
+
color.h = base_h;
|
|
66
|
+
|
|
67
|
+
result = result, color.to.srgb();
|
|
68
|
+
i = i + 1;
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Monochromatic",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Generates a monochromatic color palette - variations of a single hue with different lightness and chroma. Useful for creating cohesive single-color schemes. Preserves hue, varies lightness from light to dark.",
|
|
5
|
+
"keyword": "monochromatic",
|
|
6
|
+
"input": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"color": {
|
|
10
|
+
"type": "color",
|
|
11
|
+
"description": "Base color"
|
|
12
|
+
},
|
|
13
|
+
"count": {
|
|
14
|
+
"type": "number",
|
|
15
|
+
"description": "Number of colors to generate (default: 5)"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"script": {
|
|
20
|
+
"type": "/api/v1/core/tokenscript/0/",
|
|
21
|
+
"script": "./monochromatic.tokenscript"
|
|
22
|
+
},
|
|
23
|
+
"requirements": ["/api/v1/core/oklch-color/0/", "/api/v1/core/srgb-color/0/"]
|
|
24
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { executeWithSchema } from "@tests/helpers/schema-test-utils";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
describe("Monochromatic Function", () => {
|
|
5
|
+
describe("Schema Definition", () => {
|
|
6
|
+
it("should have correct schema structure", async () => {
|
|
7
|
+
const { getBundledSchema } = await import("@tests/helpers/schema-test-utils");
|
|
8
|
+
const schema = await getBundledSchema("monochromatic", "function");
|
|
9
|
+
|
|
10
|
+
expect(schema.name).toBe("Monochromatic");
|
|
11
|
+
expect(schema.type).toBe("function");
|
|
12
|
+
expect((schema as any).keyword).toBe("monochromatic");
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe("Basic Generation", () => {
|
|
17
|
+
it("should generate colors with default count", async () => {
|
|
18
|
+
const result = await executeWithSchema(
|
|
19
|
+
"monochromatic",
|
|
20
|
+
"function",
|
|
21
|
+
`
|
|
22
|
+
variable c: Color.SRGB;
|
|
23
|
+
c.r = 0.2; c.g = 0.4; c.b = 0.8;
|
|
24
|
+
monochromatic(c)
|
|
25
|
+
`,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
expect(result).toBeDefined();
|
|
29
|
+
expect(result.value).toBeDefined();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should generate colors with specified count", async () => {
|
|
33
|
+
const result = await executeWithSchema(
|
|
34
|
+
"monochromatic",
|
|
35
|
+
"function",
|
|
36
|
+
`
|
|
37
|
+
variable c: Color.SRGB;
|
|
38
|
+
c.r = 0.8; c.g = 0.2; c.b = 0.4;
|
|
39
|
+
monochromatic(c, 7)
|
|
40
|
+
`,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
expect(result).toBeDefined();
|
|
44
|
+
expect(result.value).toBeDefined();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe("Different Base Colors", () => {
|
|
49
|
+
it("should work with red base", async () => {
|
|
50
|
+
const result = await executeWithSchema(
|
|
51
|
+
"monochromatic",
|
|
52
|
+
"function",
|
|
53
|
+
`
|
|
54
|
+
variable c: Color.SRGB;
|
|
55
|
+
c.r = 1; c.g = 0; c.b = 0;
|
|
56
|
+
monochromatic(c, 5)
|
|
57
|
+
`,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
expect(result).toBeDefined();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("should work with blue base", async () => {
|
|
64
|
+
const result = await executeWithSchema(
|
|
65
|
+
"monochromatic",
|
|
66
|
+
"function",
|
|
67
|
+
`
|
|
68
|
+
variable c: Color.SRGB;
|
|
69
|
+
c.r = 0; c.g = 0; c.b = 1;
|
|
70
|
+
monochromatic(c, 5)
|
|
71
|
+
`,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
expect(result).toBeDefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should work with green base", async () => {
|
|
78
|
+
const result = await executeWithSchema(
|
|
79
|
+
"monochromatic",
|
|
80
|
+
"function",
|
|
81
|
+
`
|
|
82
|
+
variable c: Color.SRGB;
|
|
83
|
+
c.r = 0; c.g = 0.8; c.b = 0.2;
|
|
84
|
+
monochromatic(c, 5)
|
|
85
|
+
`,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(result).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// muted: Decrease chroma toward neutral (gray)
|
|
2
|
+
// Preserves lightness and hue
|
|
3
|
+
// Amount controls how much to reduce (0-1, 1 = fully gray)
|
|
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
|
+
// Move chroma toward 0 by the specified amount
|
|
15
|
+
variable current_c: Number = color.c;
|
|
16
|
+
variable new_c: Number = current_c * (1 - amount);
|
|
17
|
+
|
|
18
|
+
// Create result
|
|
19
|
+
variable result: Color.OKLCH;
|
|
20
|
+
result.l = color.l;
|
|
21
|
+
result.c = new_c;
|
|
22
|
+
result.h = color.h;
|
|
23
|
+
|
|
24
|
+
return result;
|
|
25
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "muted",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Decreases a color's chroma toward neutral (gray). Preserves lightness and hue while reducing colorfulness. The optional amount parameter controls the intensity (0-1, default 0.5). Uses OKLCH for perceptually uniform chroma adjustment. Useful for creating subtle backgrounds, disabled states, or calming variations of vibrant colors.",
|
|
5
|
+
"keyword": "muted",
|
|
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 mute",
|
|
15
|
+
"type": "color"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"description": "Amount (0-1, default 0.5). Higher = more muted.",
|
|
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 muted version of the color"
|
|
31
|
+
},
|
|
32
|
+
"script": {
|
|
33
|
+
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
34
|
+
"script": "./muted.tokenscript"
|
|
35
|
+
},
|
|
36
|
+
"examples": [
|
|
37
|
+
{
|
|
38
|
+
"description": "Mute vibrant red",
|
|
39
|
+
"input": ["#ff0000"],
|
|
40
|
+
"output": "Desaturated red"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"description": "Fully muted becomes gray",
|
|
44
|
+
"input": ["#ff0000", 1],
|
|
45
|
+
"output": "Gray with same lightness as red"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the muted function
|
|
3
|
+
* Decreases chroma toward neutral
|
|
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("muted function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("muted", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("muted");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("Function Execution", () => {
|
|
21
|
+
it("should decrease saturation of vibrant colors", async () => {
|
|
22
|
+
const result = await executeWithSchema(
|
|
23
|
+
"muted",
|
|
24
|
+
"function",
|
|
25
|
+
`
|
|
26
|
+
variable red: Color.SRGB;
|
|
27
|
+
red.r = 1; red.g = 0; red.b = 0;
|
|
28
|
+
muted(red).to.srgb()
|
|
29
|
+
`,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
expect(result).toBeDefined();
|
|
33
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
34
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
35
|
+
// Muted red should have less extreme channel differences
|
|
36
|
+
expect(r - g).toBeLessThan(0.9);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should produce gray with amount 1", async () => {
|
|
40
|
+
const result = await executeWithSchema(
|
|
41
|
+
"muted",
|
|
42
|
+
"function",
|
|
43
|
+
`
|
|
44
|
+
variable red: Color.SRGB;
|
|
45
|
+
red.r = 1; red.g = 0; red.b = 0;
|
|
46
|
+
muted(red, 1).to.srgb()
|
|
47
|
+
`,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
expect(result).toBeDefined();
|
|
51
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
52
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
53
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
54
|
+
// Should be gray
|
|
55
|
+
expect(Math.abs(r - g)).toBeLessThan(0.05);
|
|
56
|
+
expect(Math.abs(g - b)).toBeLessThan(0.05);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should have no effect with amount 0", async () => {
|
|
60
|
+
const result = await executeWithSchema(
|
|
61
|
+
"muted",
|
|
62
|
+
"function",
|
|
63
|
+
`
|
|
64
|
+
variable red: Color.SRGB;
|
|
65
|
+
red.r = 1; red.g = 0; red.b = 0;
|
|
66
|
+
muted(red, 0).to.srgb()
|
|
67
|
+
`,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
expect(result).toBeDefined();
|
|
71
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
72
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
73
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
74
|
+
// Should remain red
|
|
75
|
+
expect(r).toBeCloseTo(1, 1);
|
|
76
|
+
expect(g).toBeCloseTo(0, 1);
|
|
77
|
+
expect(b).toBeCloseTo(0, 1);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("should preserve gray (already muted)", async () => {
|
|
81
|
+
const result = await executeWithSchema(
|
|
82
|
+
"muted",
|
|
83
|
+
"function",
|
|
84
|
+
`
|
|
85
|
+
variable gray: Color.SRGB;
|
|
86
|
+
gray.r = 0.5; gray.g = 0.5; gray.b = 0.5;
|
|
87
|
+
muted(gray).to.srgb()
|
|
88
|
+
`,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
expect(result).toBeDefined();
|
|
92
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
93
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
94
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
95
|
+
// Gray should stay gray
|
|
96
|
+
expect(Math.abs(r - g)).toBeLessThan(0.05);
|
|
97
|
+
expect(Math.abs(g - b)).toBeLessThan(0.05);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// neutral_variant: Create gray version of color preserving lightness
|
|
2
|
+
// Optionally retain some chroma for subtle tinting
|
|
3
|
+
|
|
4
|
+
variable input: List = {input};
|
|
5
|
+
variable color: Color.OKLCH = input.get(0).to.oklch();
|
|
6
|
+
|
|
7
|
+
// Default to pure gray (0 chroma retention)
|
|
8
|
+
variable retention: Number = 0;
|
|
9
|
+
if (input.length() > 1) [
|
|
10
|
+
retention = input.get(1);
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
// Calculate retained chroma
|
|
14
|
+
variable new_c: Number = color.c * retention;
|
|
15
|
+
|
|
16
|
+
// Create result
|
|
17
|
+
variable result: Color.OKLCH;
|
|
18
|
+
result.l = color.l;
|
|
19
|
+
result.c = new_c;
|
|
20
|
+
result.h = color.h; // Hue preserved for subtle tinting
|
|
21
|
+
|
|
22
|
+
return result;
|
|
23
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "neutral_variant",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Creates a neutral (gray) variant of a color while preserving its lightness. Optionally retains a hint of the original hue. Useful for creating subtle backgrounds, disabled states, or neutral UI elements that relate to a brand color. Uses OKLCH for accurate lightness preservation.",
|
|
5
|
+
"keyword": "neutral_variant",
|
|
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": "Source color",
|
|
15
|
+
"type": "color"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"description": "Optional chroma retention (0-1, default 0 for pure gray)",
|
|
19
|
+
"type": "number"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"minItems": 1,
|
|
23
|
+
"maxItems": 2
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["input"]
|
|
27
|
+
},
|
|
28
|
+
"returns": {
|
|
29
|
+
"type": "color",
|
|
30
|
+
"description": "Neutral variant with same lightness"
|
|
31
|
+
},
|
|
32
|
+
"script": {
|
|
33
|
+
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
|
|
34
|
+
"script": "./neutral-variant.tokenscript"
|
|
35
|
+
},
|
|
36
|
+
"examples": [
|
|
37
|
+
{
|
|
38
|
+
"description": "Pure gray from blue",
|
|
39
|
+
"input": ["#0066cc"],
|
|
40
|
+
"output": "Gray with same lightness as blue"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"description": "Slightly tinted gray",
|
|
44
|
+
"input": ["#ff0000", 0.02],
|
|
45
|
+
"output": "Very subtle warm gray"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the neutral_variant function
|
|
3
|
+
* Creates a gray version of a color preserving lightness
|
|
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("neutral_variant function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema(
|
|
14
|
+
"neutral_variant",
|
|
15
|
+
"function",
|
|
16
|
+
)) as FunctionSpecification;
|
|
17
|
+
|
|
18
|
+
expect(schema.name).toBe("neutral_variant");
|
|
19
|
+
expect(schema.type).toBe("function");
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("Function Execution", () => {
|
|
24
|
+
it("should produce pure gray with default retention", async () => {
|
|
25
|
+
const result = await executeWithSchema(
|
|
26
|
+
"neutral_variant",
|
|
27
|
+
"function",
|
|
28
|
+
`
|
|
29
|
+
variable blue: Color.SRGB;
|
|
30
|
+
blue.r = 0; blue.g = 0.4; blue.b = 0.8;
|
|
31
|
+
neutral_variant(blue).to.srgb()
|
|
32
|
+
`,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
expect(result).toBeDefined();
|
|
36
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
37
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
38
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
39
|
+
// Should be gray
|
|
40
|
+
expect(Math.abs(r - g)).toBeLessThan(0.05);
|
|
41
|
+
expect(Math.abs(g - b)).toBeLessThan(0.05);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should retain some color with retention > 0", async () => {
|
|
45
|
+
const result = await executeWithSchema(
|
|
46
|
+
"neutral_variant",
|
|
47
|
+
"function",
|
|
48
|
+
`
|
|
49
|
+
variable red: Color.SRGB;
|
|
50
|
+
red.r = 1; red.g = 0; red.b = 0;
|
|
51
|
+
neutral_variant(red, 0.5).to.srgb()
|
|
52
|
+
`,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
expect(result).toBeDefined();
|
|
56
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
57
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
58
|
+
// Should still have some red tint
|
|
59
|
+
expect(r).toBeGreaterThan(g);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should handle white (already neutral)", async () => {
|
|
63
|
+
const result = await executeWithSchema(
|
|
64
|
+
"neutral_variant",
|
|
65
|
+
"function",
|
|
66
|
+
`
|
|
67
|
+
variable white: Color.SRGB;
|
|
68
|
+
white.r = 1; white.g = 1; white.b = 1;
|
|
69
|
+
neutral_variant(white).to.srgb()
|
|
70
|
+
`,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
expect(result).toBeDefined();
|
|
74
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
75
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
76
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
77
|
+
expect(r).toBeCloseTo(1, 1);
|
|
78
|
+
expect(g).toBeCloseTo(1, 1);
|
|
79
|
+
expect(b).toBeCloseTo(1, 1);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should handle black (already neutral)", async () => {
|
|
83
|
+
const result = await executeWithSchema(
|
|
84
|
+
"neutral_variant",
|
|
85
|
+
"function",
|
|
86
|
+
`
|
|
87
|
+
variable black: Color.SRGB;
|
|
88
|
+
black.r = 0; black.g = 0; black.b = 0;
|
|
89
|
+
neutral_variant(black).to.srgb()
|
|
90
|
+
`,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
expect(result).toBeDefined();
|
|
94
|
+
const r = (result as any).value?.r?.value ?? (result as any).value?.r;
|
|
95
|
+
const g = (result as any).value?.g?.value ?? (result as any).value?.g;
|
|
96
|
+
const b = (result as any).value?.b?.value ?? (result as any).value?.b;
|
|
97
|
+
expect(r).toBeCloseTo(0, 1);
|
|
98
|
+
expect(g).toBeCloseTo(0, 1);
|
|
99
|
+
expect(b).toBeCloseTo(0, 1);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// relative_luminance: Get WCAG 2.1 relative luminance
|
|
2
|
+
// Reference: WCAG 2.1 Definition of Relative Luminance
|
|
3
|
+
// Reference: https://www.w3.org/TR/WCAG21/#dfn-relative-luminance
|
|
4
|
+
//
|
|
5
|
+
// Returns the Y component from CIE XYZ D65, which is the
|
|
6
|
+
// relative luminance as defined by WCAG. Range is [0, 1]
|
|
7
|
+
// where 0 = black and 1 = reference white.
|
|
8
|
+
//
|
|
9
|
+
// This value is used in WCAG contrast ratio calculations.
|
|
10
|
+
|
|
11
|
+
variable input: List = {input};
|
|
12
|
+
variable color: Color.XYZD65 = input.get(0).to.xyzd65();
|
|
13
|
+
|
|
14
|
+
return color.y;
|
|
15
|
+
|