diff --git a/.config/cspell.json b/.config/cspell.json index faafb94..e60c4e2 100644 --- a/.config/cspell.json +++ b/.config/cspell.json @@ -10,6 +10,7 @@ "xcworkspace" ], "words": [ + "colorjs", "prebuild" ] -} \ No newline at end of file +} diff --git a/package.json b/package.json index da54ce2..361fe63 100644 --- a/package.json +++ b/package.json @@ -111,6 +111,7 @@ "!**/__mocks__" ], "dependencies": { + "colorjs.io": "0.6.0-alpha.1", "comment-json": "^4.2.5", "debug": "^4.4.1" }, diff --git a/src/compiler/__tests__/compiler.test.tsx b/src/compiler/__tests__/compiler.test.tsx index 92c4473..aff9ca5 100644 --- a/src/compiler/__tests__/compiler.test.tsx +++ b/src/compiler/__tests__/compiler.test.tsx @@ -1,5 +1,18 @@ import { compile } from "../compiler"; +test("reads global CSS variables", () => { + const compiled = compile(` +@layer theme { + :root, :host { + --color-red-500: oklch(63.7% 0.237 25.331); + } +}`); + + expect(compiled).toStrictEqual({ + vr: [["color-red-500", ["#fb2c36"]]], + }); +}); + test.skip("test compiler", () => { const compiled = compile(` .test { diff --git a/src/compiler/add.ts b/src/compiler/add.ts index 49a5e66..eb169ef 100644 --- a/src/compiler/add.ts +++ b/src/compiler/add.ts @@ -2,6 +2,7 @@ import { isStyleDescriptorArray } from "../runtime/utils/style-value"; import type { CompilerCollection, + CompilerOptions, EasingFunction, StyleDeclaration, StyleDescriptor, @@ -17,6 +18,7 @@ export function buildAddFn( rule: StyleRule, collection: CompilerCollection, mapping: StyleRuleMapping, + options: CompilerOptions, ) { let staticDeclarations: Record | undefined; @@ -100,6 +102,7 @@ export function buildAddFn( if (property.startsWith("--")) { if ( + options.stripUnusedVariables && !property.startsWith("--__rn-css") && !collection.varUsageCount.has(property) ) { diff --git a/src/compiler/compiler.ts b/src/compiler/compiler.ts index fbc51b3..b5815d9 100644 --- a/src/compiler/compiler.ts +++ b/src/compiler/compiler.ts @@ -4,6 +4,7 @@ import { transform as lightningcss, type ContainerRule, type MediaQuery as CSSMediaQuery, + type CustomAtRules, type Declaration, type DeclarationBlock, type MediaRule, @@ -11,6 +12,7 @@ import { type Rule, type SelectorList, type TokenOrValue, + type Visitor, } from "lightningcss"; import { Specificity } from "../runtime/utils/specificity"; @@ -61,8 +63,9 @@ type ReactNativeAtRule = { */ export function compile( code: Buffer | string, - { logger = debug("react-native-css"), ...options }: CompilerOptions = {}, + options: CompilerOptions = {}, ): ReactNativeCssStyleSheet { + const { logger = debug("react-native-css") } = options; const features = Object.assign({}, options.features); logger(`Features ${JSON.stringify(features)}`); @@ -100,35 +103,44 @@ export function compile( } }; + const customAtRules: CustomAtRules = { + "react-native": { + body: "declaration-list", + }, + }; + + const visitor: Visitor = { + Rule(rule) { + if (isReactNativeAtRule(rule)) { + extractReactNativeOptions(rule, collection); + } + }, + StyleSheetExit(sheet) { + logger(`Found ${sheet.rules.length} rules to process`); + + for (const rule of sheet.rules) { + // Extract the style declarations and animations from the current rule + extractRule(rule, collection, {}, options); + // We have processed this rule, so now delete it from the AST + } + + logger(`Exiting lightningcss`); + }, + }; + + if (options.stripUnusedVariables) { + visitor.Declaration = (decl) => { + if (decl.property !== "unparsed" && decl.property !== "custom") return; + decl.value.value.forEach((varObj) => onVarUsage(varObj)); + return decl; + }; + } + // Use the lightningcss library to traverse the CSS AST and extract style declarations and animations lightningcss({ filename: "style.css", // This is ignored, but required code: typeof code === "string" ? new TextEncoder().encode(code) : code, - visitor: { - Declaration(decl) { - // Track variable usage, we remove any unused variables - if (decl.property !== "unparsed" && decl.property !== "custom") return; - decl.value.value.forEach((varObj) => onVarUsage(varObj)); - return decl; - }, - StyleSheetExit(sheet) { - logger(`Found ${sheet.rules.length} rules to process`); - - for (const rule of sheet.rules) { - // Extract the style declarations and animations from the current rule - extractRule(rule, collection); - // We have processed this rule, so now delete it from the AST - } - - logger(`Exiting lightningcss`); - }, - }, - customAtRules: { - "react-native": { - prelude: "+", - body: "declaration-list", - }, - }, + visitor, }); logger(`Found ${collection.rules.size} valid rules`); @@ -184,6 +196,7 @@ function extractRule( rule: ExtractableRules, collection: CompilerCollection, partialStyle: Partial = {}, + options: CompilerOptions, ) { // Check the rule's type to determine which extraction function to call switch (rule.type) { @@ -209,6 +222,7 @@ function extractRule( rule.value.declarations, collection, parseReactNativeStyleAtRule(rule.value.rules), + options, )) { setStyleForSelectorList( { ...partialStyle, ...style }, @@ -220,11 +234,33 @@ function extractRule( } break; } - case "custom": { - if (isReactNativeAtRule(rule)) { - extractReactNativeOptions(rule, collection); + case "layer-block": + for (const layerRule of rule.value.rules) { + extractRule(layerRule, collection, partialStyle, options); } - } + break; + case "custom": + case "font-face": + case "font-palette-values": + case "font-feature-values": + case "namespace": + case "layer-statement": + case "property": + case "view-transition": + case "ignored": + case "unknown": + case "import": + case "page": + case "supports": + case "counter-style": + case "moz-document": + case "nesting": + case "nested-declarations": + case "viewport": + case "custom-media": + case "scope": + case "starting-style": + break; } } @@ -377,7 +413,7 @@ function extractMedia(mediaRule: MediaRule, collection: CompilerCollection) { // Iterate over all rules in the mediaRule and extract their styles using the updated CompilerCollection for (const rule of mediaRule.rules) { - extractRule(rule, collection, { m }); + extractRule(rule, collection, { m }, options); } } @@ -405,7 +441,7 @@ function extractedContainer( query.n = containerRule.name; } - extractRule(rule, collection, { cq: [query] }); + extractRule(rule, collection, { cq: [query] }, options); } } @@ -564,6 +600,7 @@ function getExtractedStyles( declarationBlock: DeclarationBlock, collection: CompilerCollection, mapping: StyleRuleMapping = {}, + options: CompilerOptions, ): StyleRule[] { const extractedStyles = []; @@ -577,6 +614,7 @@ function getExtractedStyles( collection, specificity, mapping, + options, ), ); } @@ -592,6 +630,7 @@ function getExtractedStyles( collection, specificity, mapping, + options, ), ); } @@ -604,6 +643,7 @@ function declarationsToStyle( collection: CompilerCollection, specificity: SpecificityArray, mapping: StyleRuleMapping, + options: CompilerOptions, ): StyleRule { const extractedStyle: StyleRule = { s: [...specificity], @@ -617,7 +657,7 @@ function declarationsToStyle( // TODO }; - const addFn = buildAddFn(extractedStyle, collection, mapping); + const addFn = buildAddFn(extractedStyle, collection, mapping, options); for (const declaration of declarations) { parseDeclaration(declaration, parseDeclarationOptions, addFn, addWarning); diff --git a/src/compiler/compiler.types.ts b/src/compiler/compiler.types.ts index 731bb41..9de8f96 100644 --- a/src/compiler/compiler.types.ts +++ b/src/compiler/compiler.types.ts @@ -15,6 +15,8 @@ export interface CompilerOptions { stylesheetOrder?: number; features?: FeatureFlagRecord; logger?: (message: string) => void; + /** Strip unused variables declarations. Defaults: false */ + stripUnusedVariables?: boolean; /** @internal */ ignorePropertyWarningRegex?: (string | RegExp)[]; } diff --git a/src/compiler/declarations.ts b/src/compiler/declarations.ts index 78b6a67..31700e7 100644 --- a/src/compiler/declarations.ts +++ b/src/compiler/declarations.ts @@ -47,6 +47,8 @@ import type { VerticalAlign, } from "lightningcss"; +import Color from "colorjs.io"; + import { emVariableName } from "../runtime/native/styles/constants"; import { isStyleDescriptorArray } from "../runtime/utils/style-value"; import type { AddFn } from "./add"; @@ -228,6 +230,8 @@ export interface ParseDeclarationOptions { inlineRem?: number | false; features?: FeatureFlagRecord; allowAuto?: boolean; + hexColors?: boolean; + colorPrecision?: number; } export interface ParserOptions extends ParseDeclarationOptions { @@ -2011,58 +2015,139 @@ function parseColorOrAuto(color: ColorOrAuto, options: ParserOptions) { } } -function parseColor(color: CssColor, options: ParserOptions) { - if (typeof color === "string") { - // TODO: Could web system colors be mapped to native? +function parseColor(cssColor: CssColor, options: ParserOptions) { + if (typeof cssColor === "string") { + if (namedColors.has(cssColor)) { + return cssColor; + } return; } - switch (color.type) { - case "rgb": { - // Hex is smaller than rgb, so we convert it - const hexValues: string[] = [ - color.r.toString(16).padStart(2, "0"), - color.g.toString(16).padStart(2, "0"), - color.b.toString(16).padStart(2, "0"), - ]; + let color: Color | undefined; - if (color.alpha !== 1) { - hexValues.push( - Math.round(color.alpha * 255) - .toString(16) - .padStart(2, "0"), - ); - } - - return `#${hexValues.join("")}`; - } - case "hsl": - return `hsla(${color.h}, ${color.s}, ${color.l}, ${color.alpha})`; + switch (cssColor.type) { case "currentcolor": - options.addWarning("value", color.type); + options.addWarning("value", cssColor.type); return; case "light-dark": + // TODO: Handle light-dark colors + return; + case "rgb": { + color = new Color({ + space: "sRGB", + coords: [cssColor.r / 255, cssColor.g / 255, cssColor.b / 255], + alpha: cssColor.alpha, + }); + break; + } + case "hsl": + color = new Color({ + space: cssColor.type, + coords: [cssColor.h, cssColor.s, cssColor.l], + alpha: cssColor.alpha, + }); + break; + case "hwb": + color = new Color({ + space: cssColor.type, + coords: [cssColor.h, cssColor.w, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "lab": + color = new Color({ + space: cssColor.type, + coords: [cssColor.l, cssColor.a, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "lch": + color = new Color({ + space: cssColor.type, + coords: [cssColor.l, cssColor.c, cssColor.h], + alpha: cssColor.alpha, + }); + break; case "oklab": + color = new Color({ + space: cssColor.type, + coords: [cssColor.l, cssColor.a, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "oklch": + color = new Color({ + space: cssColor.type, + coords: [cssColor.l, cssColor.c, cssColor.h], + alpha: cssColor.alpha, + }); + break; case "srgb": + color = new Color({ + space: cssColor.type, + coords: [cssColor.r, cssColor.g, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "srgb-linear": + color = new Color({ + space: cssColor.type, + coords: [cssColor.r, cssColor.g, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "display-p3": + color = new Color({ + space: "p3", + coords: [cssColor.r, cssColor.g, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "a98-rgb": + color = new Color({ + space: "a98rgb", + coords: [cssColor.r, cssColor.g, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "prophoto-rgb": + color = new Color({ + space: "prophoto", + coords: [cssColor.r, cssColor.g, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "rec2020": + color = new Color({ + space: cssColor.type, + coords: [cssColor.r, cssColor.g, cssColor.b], + alpha: cssColor.alpha, + }); + break; case "xyz-d50": + color = new Color({ + space: cssColor.type, + coords: [cssColor.x, cssColor.y, cssColor.z], + alpha: cssColor.alpha, + }); + break; case "xyz-d65": - case "hwb": - options.addWarning("value", `Invalid color unit ${color.type}`); - return undefined; + color = new Color({ + space: cssColor.type, + coords: [cssColor.x, cssColor.y, cssColor.z], + alpha: cssColor.alpha, + }); + break; default: { - color satisfies never; + cssColor satisfies never; } } - return; + if (options.hexColors === false || options.colorPrecision) { + return color?.toString({ precision: options.colorPrecision ?? 3 }); + } else { + return color?.toString({ format: "hex" }); + } } function parseLengthPercentageOrAuto( @@ -3144,3 +3229,151 @@ function kebabCase(str: string) { } const runtimeShorthands = new Set(["animation", "text-shadow", "transform"]); + +const namedColors = new Set([ + "aliceblue", + "antiquewhite", + "aqua", + "aquamarine", + "azure", + "beige", + "bisque", + "black", + "blanchedalmond", + "blue", + "blueviolet", + "brown", + "burlywood", + "cadetblue", + "chartreuse", + "chocolate", + "coral", + "cornflowerblue", + "cornsilk", + "crimson", + "cyan", + "darkblue", + "darkcyan", + "darkgoldenrod", + "darkgray", + "darkgreen", + "darkgrey", + "darkkhaki", + "darkmagenta", + "darkolivegreen", + "darkorange", + "darkorchid", + "darkred", + "darksalmon", + "darkseagreen", + "darkslateblue", + "darkslategrey", + "darkturquoise", + "darkviolet", + "deeppink", + "deepskyblue", + "dimgray", + "dimgrey", + "dodgerblue", + "firebrick", + "floralwhite", + "forestgreen", + "fuchsia", + "gainsboro", + "ghostwhite", + "gold", + "goldenrod", + "gray", + "green", + "greenyellow", + "grey", + "honeydew", + "hotpink", + "indianred", + "indigo", + "ivory", + "khaki", + "lavender", + "lavenderblush", + "lawngreen", + "lemonchiffon", + "lightblue", + "lightcoral", + "lightcyan", + "lightgoldenrodyellow", + "lightgray", + "lightgreen", + "lightgrey", + "lightpink", + "lightsalmon", + "lightseagreen", + "lightskyblue", + "lightslategrey", + "lightsteelblue", + "lightyellow", + "lime", + "limegreen", + "linen", + "magenta", + "maroon", + "mediumaquamarine", + "mediumblue", + "mediumorchid", + "mediumpurple", + "mediumseagreen", + "mediumslateblue", + "mediumspringgreen", + "mediumturquoise", + "mediumvioletred", + "midnightblue", + "mintcream", + "mistyrose", + "moccasin", + "navajowhite", + "navy", + "oldlace", + "olive", + "olivedrab", + "orange", + "orangered", + "orchid", + "palegoldenrod", + "palegreen", + "paleturquoise", + "palevioletred", + "papayawhip", + "peachpuff", + "peru", + "pink", + "plum", + "powderblue", + "purple", + "rebeccapurple", + "red", + "rosybrown", + "royalblue", + "saddlebrown", + "salmon", + "sandybrown", + "seagreen", + "seashell", + "sienna", + "silver", + "skyblue", + "slateblue", + "slategray", + "snow", + "springgreen", + "steelblue", + "tan", + "teal", + "thistle", + "tomato", + "turquoise", + "violet", + "wheat", + "white", + "whitesmoke", + "yellow", + "yellowgreen", +]); diff --git a/src/runtime/native/__tests__/container-queries.test.tsx b/src/runtime/native/__tests__/container-queries.test.tsx index c6bbd43..a967b3d 100644 --- a/src/runtime/native/__tests__/container-queries.test.tsx +++ b/src/runtime/native/__tests__/container-queries.test.tsx @@ -36,7 +36,7 @@ test("container query width", () => { }); expect(child.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); fireEvent(parent, "layout", { @@ -49,7 +49,7 @@ test("container query width", () => { }); expect(child.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); screen.rerender( @@ -70,6 +70,6 @@ test("container query width", () => { expect(parent.props.style).toStrictEqual([{ width: 200 }, { width: 500 }]); expect(child.props.style).toStrictEqual({ - color: "#0000ff", + color: "#00f", }); }); diff --git a/src/runtime/native/__tests__/grouping.test.tsx b/src/runtime/native/__tests__/grouping.test.tsx index c2b88ca..2624b33 100644 --- a/src/runtime/native/__tests__/grouping.test.tsx +++ b/src/runtime/native/__tests__/grouping.test.tsx @@ -23,7 +23,7 @@ test("groups", () => { const component = getByTestId(childID); - expect(component.props.style).toStrictEqual({ color: "#ff0000" }); + expect(component.props.style).toStrictEqual({ color: "#f00" }); rerender( @@ -54,7 +54,7 @@ test("group - active", () => { fireEvent(parent, "pressIn"); - expect(child.props.style).toStrictEqual({ color: "#ff0000" }); + expect(child.props.style).toStrictEqual({ color: "#f00" }); }); test.skip("group - active (animated)", () => { @@ -111,7 +111,7 @@ test("group selector", () => { const child = screen.getByTestId(childID); - expect(child.props.style).toStrictEqual({ color: "#ff0000" }); + expect(child.props.style).toStrictEqual({ color: "#f00" }); rerender( diff --git a/src/runtime/native/__tests__/media-query.test.tsx b/src/runtime/native/__tests__/media-query.test.tsx index 5a9feae..c3abbbf 100644 --- a/src/runtime/native/__tests__/media-query.test.tsx +++ b/src/runtime/native/__tests__/media-query.test.tsx @@ -24,7 +24,7 @@ test("color scheme", () => { const component = screen.getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#0000ff", + color: "#00f", }); act(() => { @@ -32,7 +32,7 @@ test("color scheme", () => { }); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -48,7 +48,7 @@ test("width (plain)", () => { const component = screen.getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#0000ff", + color: "#00f", }); act(() => { @@ -59,7 +59,7 @@ test("width (plain)", () => { }); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -75,7 +75,7 @@ test("width (range)", () => { const component = screen.getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#0000ff", + color: "#00f", }); act(() => { @@ -86,7 +86,7 @@ test("width (range)", () => { }); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -102,7 +102,7 @@ test("min-width", () => { const component = screen.getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); act(() => { @@ -113,7 +113,7 @@ test("min-width", () => { }); expect(component.props.style).toStrictEqual({ - color: "#0000ff", + color: "#00f", }); }); @@ -129,7 +129,7 @@ test("max-width", () => { const component = screen.getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#0000ff", + color: "#00f", }); act(() => { @@ -140,7 +140,7 @@ test("max-width", () => { }); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -173,7 +173,7 @@ test("not all", () => { }); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -188,7 +188,7 @@ describe("resolution", () => { expect(PixelRatio.get()).toBe(2); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -202,7 +202,7 @@ describe("resolution", () => { expect(PixelRatio.get()).toBe(2); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); }); @@ -218,7 +218,7 @@ describe("min-resolution", () => { const component = screen.getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -231,7 +231,7 @@ describe("min-resolution", () => { const component = screen.getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); }); diff --git a/src/runtime/native/__tests__/pseudo-classes.test.tsx b/src/runtime/native/__tests__/pseudo-classes.test.tsx index fb38406..a41e9a2 100644 --- a/src/runtime/native/__tests__/pseudo-classes.test.tsx +++ b/src/runtime/native/__tests__/pseudo-classes.test.tsx @@ -24,7 +24,7 @@ test("hover", () => { onHoverIn: expect.any(Function), onHoverOut: expect.any(Function), style: { - color: "#0000ff", + color: "#00f", }, }); @@ -38,7 +38,7 @@ test("hover", () => { onHoverIn: expect.any(Function), onHoverOut: expect.any(Function), style: { - color: "#ff0000", + color: "#f00", }, }); act(() => { @@ -51,7 +51,7 @@ test("hover", () => { onHoverIn: expect.any(Function), onHoverOut: expect.any(Function), style: { - color: "#0000ff", + color: "#00f", }, }); }); diff --git a/src/runtime/native/__tests__/selector-prefix.test.tsx b/src/runtime/native/__tests__/selector-prefix.test.tsx index 0e9dbdc..a74cc79 100644 --- a/src/runtime/native/__tests__/selector-prefix.test.tsx +++ b/src/runtime/native/__tests__/selector-prefix.test.tsx @@ -11,7 +11,7 @@ test("type prefix", () => { ).getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -25,6 +25,6 @@ test("class prefix", () => { ).getByTestId(testID); expect(component.props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); diff --git a/src/runtime/native/__tests__/selectors.test.tsx b/src/runtime/native/__tests__/selectors.test.tsx index 475edfd..ab288b5 100644 --- a/src/runtime/native/__tests__/selectors.test.tsx +++ b/src/runtime/native/__tests__/selectors.test.tsx @@ -23,7 +23,7 @@ test(":is(.dark *)", () => { colorScheme.set("dark"); }); - expect(component.props.style).toStrictEqual({ color: "#ff0000" }); + expect(component.props.style).toStrictEqual({ color: "#f00" }); }); test(':root[class="dark"]', () => { @@ -50,7 +50,7 @@ test(':root[class="dark"]', () => { test(':root[class~="dark"]', () => { registerCSS(` - @react-native config { + @react-native { darkMode: dark; } diff --git a/src/runtime/native/__tests__/specificity.test.tsx b/src/runtime/native/__tests__/specificity.test.tsx index d601d88..22dd5b9 100644 --- a/src/runtime/native/__tests__/specificity.test.tsx +++ b/src/runtime/native/__tests__/specificity.test.tsx @@ -17,7 +17,7 @@ test("inline styles", () => { ).getByTestId(testID); expect(component.props.style).toStrictEqual([ - { backgroundColor: "#ff0000" }, + { backgroundColor: "#f00" }, { backgroundColor: "blue" }, ]); }); @@ -29,7 +29,7 @@ test("specificity order", () => { , ).getByTestId(testID); - expect(component.props.style).toStrictEqual({ color: "#0000ff" }); + expect(component.props.style).toStrictEqual({ color: "#00f" }); }); test("specificity modifiers", () => { @@ -42,7 +42,7 @@ test("specificity modifiers", () => { ).getByTestId(testID); expect(component.props.style).toStrictEqual( - { color: "#0000ff" }, // .blue + { color: "#00f" }, // .blue ); fireEvent(component, "hoverIn"); @@ -61,8 +61,8 @@ test("important - requires sorting", () => { ).getByTestId(testID); expect(component.props.style).toStrictEqual([ - { color: "#ff0000" }, - { color: "#0000ff" }, + { color: "#f00" }, + { color: "#00f" }, ]); }); @@ -81,7 +81,7 @@ test("important - inline", () => { expect(component.props.style).toStrictEqual([ { backgroundColor: "red" }, - { backgroundColor: "#0000ff" }, + { backgroundColor: "#00f" }, ]); }); @@ -97,15 +97,15 @@ test("important - modifiers", () => { ).getByTestId(testID); expect(component.props.style).toStrictEqual([ - { color: "#ff0000" }, - { color: "#0000ff" }, + { color: "#f00" }, + { color: "#00f" }, ]); fireEvent(component, "hoverIn"); expect(component.props.style).toStrictEqual([ { color: "#008000" }, - { color: "#0000ff" }, + { color: "#00f" }, ]); }); @@ -174,7 +174,7 @@ test("passThrough - inline important", () => { // Red wins because it is important and overrides the inline style expect(StyleSheet.flatten(component.props.style)).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); }); @@ -200,6 +200,6 @@ test("passThrough - inline important existing", () => { // Blue wins, because 'red' and 'blue' are both important, but 'blue' has a higher 'order' expect(StyleSheet.flatten(component.props.style)).toStrictEqual({ - color: "#0000ff", + color: "#00f", }); }); diff --git a/src/runtime/native/__tests__/style-updating.test.tsx b/src/runtime/native/__tests__/style-updating.test.tsx index 00e8287..2742a9c 100644 --- a/src/runtime/native/__tests__/style-updating.test.tsx +++ b/src/runtime/native/__tests__/style-updating.test.tsx @@ -17,7 +17,7 @@ test("should update styles", () => { render(); expect(screen.getByTestId(testID).props.style).toStrictEqual({ - color: "#ff0000", + color: "#f00", }); act(() => { @@ -29,6 +29,6 @@ test("should update styles", () => { }); expect(screen.getByTestId(testID).props.style).toStrictEqual({ - color: "#0000ff", + color: "#00f", }); }); diff --git a/yarn.lock b/yarn.lock index 1dbbcc9..0045b06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5138,6 +5138,13 @@ __metadata: languageName: node linkType: hard +"colorjs.io@npm:0.6.0-alpha.1": + version: 0.6.0-alpha.1 + resolution: "colorjs.io@npm:0.6.0-alpha.1" + checksum: 10c0/0bc58a65927d77fceade43fcdcaa512befadaa5fb38a4afb3ab632b38eea5d42d656c2bb32c3c604010eeb6e210f3801b0dc480d6b3ae26de6da8c3c55e09f11 + languageName: node + linkType: hard + "combined-stream@npm:^1.0.8": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" @@ -10872,6 +10879,7 @@ __metadata: "@types/react": "npm:^19.1.8" babel-plugin-tester: "npm:^12.0.0" babel-preset-expo: "npm:13.3.0-canary-20250713-8f814f8" + colorjs.io: "npm:0.6.0-alpha.1" comment-json: "npm:^4.2.5" commitlint: "npm:^19.8.1" debug: "npm:^4.4.1"