diff --git a/packages/core/ui/styling/css-shadow.spec.ts b/packages/core/ui/styling/css-shadow.spec.ts index 0d7624f7f..b8c0eb844 100644 --- a/packages/core/ui/styling/css-shadow.spec.ts +++ b/packages/core/ui/styling/css-shadow.spec.ts @@ -7,11 +7,11 @@ describe('css-shadow', () => { it('empty', () => { const shadow = parseCSSShadow(''); expect(shadow.inset).toBe(false); - expect(shadow.offsetX).toBe(CoreTypes.zeroLength); + expect(shadow.offsetX).toBeUndefined(); expect(shadow.offsetY).toBeUndefined(); expect(shadow.blurRadius).toBeUndefined(); expect(shadow.spreadRadius).toBeUndefined(); - expect(shadow.color).toEqual(new Color('black')); + expect(shadow.color).toBeUndefined(); }); it('1px 1px 2px black', () => { @@ -134,4 +134,14 @@ describe('css-shadow', () => { expect(shadow.spreadRadius).toBeUndefined(); expect(shadow.color).toEqual(new Color('#333')); }); + + it('none', () => { + const shadow = parseCSSShadow('none'); + expect(shadow.inset).toBe(false); + expect(shadow.offsetX).toBeUndefined(); + expect(shadow.offsetY).toBeUndefined(); + expect(shadow.blurRadius).toBeUndefined(); + expect(shadow.spreadRadius).toBeUndefined(); + expect(shadow.color).toBeUndefined(); + }); }); diff --git a/packages/core/ui/styling/css-shadow.ts b/packages/core/ui/styling/css-shadow.ts index 598e953d6..292d141b7 100644 --- a/packages/core/ui/styling/css-shadow.ts +++ b/packages/core/ui/styling/css-shadow.ts @@ -1,6 +1,6 @@ -import { CoreTypes } from '../../core-types'; import { Color } from '../../color'; -import { Length } from './style-properties'; +import { CoreTypes } from '../../core-types'; +import { parseCSSShorthand } from './css-utils'; export interface ShadowCSSValues { inset: boolean; @@ -11,57 +11,6 @@ export interface ShadowCSSValues { color: Color; } -/** - * Matches whitespace except if the whitespace is contained in parenthesis - ex. rgb(a), hsl color. - */ -const PARTS_RE = /\s(?![^(]*\))/; - -/** - * Matches a Length value with or without a unit - */ -const LENGTH_RE = /^-?[0-9]+[a-zA-Z%]*?$/; - -/** - * Checks if the value is a Length or 0 - */ -const isLength = (v) => v === '0' || LENGTH_RE.test(v); - -export function parseCSSShorthand(value: string): { - values: Array; - color: string; - inset: boolean; -} { - const parts = value.trim().split(PARTS_RE); - const inset = parts.includes('inset'); - const first = parts[0]; - const last = parts[parts.length - 1]; - - if (first === 'none') { - return null; - } - - let color = 'black'; - if (first && !isLength(first) && first !== 'inset') { - color = first; - } else if (last && !isLength(last)) { - color = last; - } - const values = parts - .filter((n) => n !== 'inset') - .filter((n) => n !== color) - .map((val) => { - try { - return Length.parse(val); - } catch (err) { - return CoreTypes.zeroLength; - } - }); - return { - inset, - color, - values, - }; -} /** * Parse a string into ShadowCSSValues * Supports any valid css box/text shadow combination. @@ -80,6 +29,6 @@ export function parseCSSShadow(value: string): ShadowCSSValues { offsetY: offsetY, blurRadius: blurRadius, spreadRadius: spreadRadius, - color: new Color(data.color), + color: data.color ? new Color(data.color) : undefined, }; } diff --git a/packages/core/ui/styling/css-stroke.spec.ts b/packages/core/ui/styling/css-stroke.spec.ts index 60122fc7d..715b23012 100644 --- a/packages/core/ui/styling/css-stroke.spec.ts +++ b/packages/core/ui/styling/css-stroke.spec.ts @@ -6,8 +6,8 @@ import { Color } from '../../color'; describe('css-text-stroke', () => { it('empty', () => { const stroke = parseCSSStroke(''); - expect(stroke.width).toBe(CoreTypes.zeroLength); - expect(stroke.color).toEqual(new Color('black')); + expect(stroke.width).toBeUndefined(); + expect(stroke.color).toBeUndefined(); }); it('1px navy', () => { diff --git a/packages/core/ui/styling/css-stroke.ts b/packages/core/ui/styling/css-stroke.ts index 213d30ff6..03e1a39a0 100644 --- a/packages/core/ui/styling/css-stroke.ts +++ b/packages/core/ui/styling/css-stroke.ts @@ -1,6 +1,6 @@ import { CoreTypes } from '../../core-types'; import { Color } from '../../color'; -import { parseCSSShorthand } from './css-shadow'; +import { parseCSSShorthand } from './css-utils'; export interface StrokeCSSValues { width: CoreTypes.LengthType; @@ -18,6 +18,6 @@ export function parseCSSStroke(value: string): StrokeCSSValues { return { width, - color: new Color(data.color), + color: data.color ? new Color(data.color) : undefined, }; } diff --git a/packages/core/ui/styling/css-utils.ts b/packages/core/ui/styling/css-utils.ts index 4d61b2a62..c4ac96dee 100644 --- a/packages/core/ui/styling/css-utils.ts +++ b/packages/core/ui/styling/css-utils.ts @@ -1,4 +1,6 @@ import { Trace } from '../../trace'; +import { CoreTypes } from '../../core-types'; +import { Length } from './style-properties'; export function cleanupImportantFlags(value: string, propertyName: string) { const index = value?.indexOf('!important'); @@ -10,3 +12,60 @@ export function cleanupImportantFlags(value: string, propertyName: string) { } return value; } + +/** + * Matches whitespace except if the whitespace is contained in parenthesis - ex. rgb(a), hsl color. + */ +const PARTS_RE = /\s(?![^(]*\))/; + +/** + * Matches a Length value with or without a unit + */ +const LENGTH_RE = /^-?[0-9]+[a-zA-Z%]*?$/; + +/** + * Checks if the value is a Length or 0 + */ +const isLength = (v) => v === '0' || LENGTH_RE.test(v); + +export function parseCSSShorthand(value: string): { + values: Array; + color: string; + inset: boolean; +} { + const parts = value.trim().split(PARTS_RE); + const first = parts[0]; + + if (['', 'none'].includes(first)) { + return { + inset: false, + color: undefined, + values: [], + }; + } else { + const inset = parts.includes('inset'); + const last = parts[parts.length - 1]; + let color = 'black'; + if (first && !isLength(first) && first !== 'inset') { + color = first; + } else if (last && !isLength(last)) { + color = last; + } + + const values = parts + .filter((n) => n !== 'inset') + .filter((n) => n !== color) + .map((val) => { + try { + return Length.parse(val); + } catch (err) { + return CoreTypes.zeroLength; + } + }); + return { + inset, + color, + values, + }; + } +} diff --git a/packages/core/utils/index.d.ts b/packages/core/utils/index.d.ts index 38d273302..c551cbdcf 100644 --- a/packages/core/utils/index.d.ts +++ b/packages/core/utils/index.d.ts @@ -38,14 +38,14 @@ export function queueGC(delay?: number, useThrottle?: boolean); * @param fn Function to throttle * @param delay Customize the delay (default is 300ms) */ -export function throttle(fn: any, delay?: number); +export function throttle(fn: T, delay?: number): T; /** * A simple debounce utility * @param fn Function to debounce * @param delay Customize the delay (default is 300ms) */ -export function debounce(fn: any, delay?: number, options?: { leading?: boolean }); +export function debounce(fn: T, delay?: number, options?: { leading?: boolean }): T; /** * Releases the reference to the wrapped native object