mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-02 19:12:40 +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