mirror of
				https://github.com/NativeScript/NativeScript.git
				synced 2025-11-04 21:06:45 +08:00 
			
		
		
		
	fix(core): box-shadow 'none' handling (#10405)
This commit is contained in:
		@ -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();
 | 
			
		||||
	});
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -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<CoreTypes.LengthType>;
 | 
			
		||||
	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,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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', () => {
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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<CoreTypes.LengthType>;
 | 
			
		||||
	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,
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								packages/core/utils/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								packages/core/utils/index.d.ts
									
									
									
									
										vendored
									
									
								
							@ -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<T extends Function = any>(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<T extends Function = any>(fn: T, delay?: number, options?: { leading?: boolean }): T;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Releases the reference to the wrapped native object
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user