mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-14 18:12:09 +08:00
feat(core): style properties module improvements and organization (#10685)
This commit is contained in:

committed by
GitHub

parent
56af0b2f7e
commit
3a7206fc3b
@ -29,8 +29,9 @@ export namespace CoreTypes {
|
|||||||
export type LengthPxUnit = { readonly unit: 'px'; readonly value: px };
|
export type LengthPxUnit = { readonly unit: 'px'; readonly value: px };
|
||||||
export type LengthPercentUnit = { readonly unit: '%'; readonly value: percent };
|
export type LengthPercentUnit = { readonly unit: '%'; readonly value: percent };
|
||||||
|
|
||||||
export type LengthType = 'auto' | dip | LengthDipUnit | LengthPxUnit;
|
export type FixedLengthType = dip | LengthDipUnit | LengthPxUnit;
|
||||||
export type PercentLengthType = 'auto' | dip | LengthDipUnit | LengthPxUnit | LengthPercentUnit;
|
export type LengthType = 'auto' | FixedLengthType;
|
||||||
|
export type PercentLengthType = 'auto' | FixedLengthType | LengthPercentUnit;
|
||||||
|
|
||||||
export const zeroLength: LengthType = {
|
export const zeroLength: LengthType = {
|
||||||
value: 0,
|
value: 0,
|
||||||
|
@ -8,13 +8,19 @@ export type Transformation = {
|
|||||||
value: TransformationValue;
|
value: TransformationValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TransformationType = 'rotate' | 'translate' | 'translateX' | 'translateY' | 'scale' | 'scaleX' | 'scaleY';
|
export type TransformationType = 'rotate' | 'rotate3d' | 'rotateX' | 'rotateY' | 'translate' | 'translate3d' | 'translateX' | 'translateY' | 'scale' | 'scale3d' | 'scaleX' | 'scaleY';
|
||||||
|
|
||||||
export type TransformationValue = Pair | number;
|
export type TransformationValue = Point3D | Pair | number;
|
||||||
|
|
||||||
|
export interface Point3D {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
z: number;
|
||||||
|
}
|
||||||
|
|
||||||
export type TransformFunctionsInfo = {
|
export type TransformFunctionsInfo = {
|
||||||
translate: Pair;
|
translate: Pair;
|
||||||
rotate: number;
|
rotate: Point3D;
|
||||||
scale: Pair;
|
scale: Pair;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,7 +61,7 @@ export interface AnimationDefinition {
|
|||||||
scale?: Pair;
|
scale?: Pair;
|
||||||
height?: CoreTypes.PercentLengthType | string;
|
height?: CoreTypes.PercentLengthType | string;
|
||||||
width?: CoreTypes.PercentLengthType | string;
|
width?: CoreTypes.PercentLengthType | string;
|
||||||
rotate?: number;
|
rotate?: Point3D;
|
||||||
duration?: number;
|
duration?: number;
|
||||||
delay?: number;
|
delay?: number;
|
||||||
iterations?: number;
|
iterations?: number;
|
||||||
|
2
packages/core/ui/animation/index.d.ts
vendored
2
packages/core/ui/animation/index.d.ts
vendored
@ -83,7 +83,7 @@ export type Transformation = {
|
|||||||
/**
|
/**
|
||||||
* Defines possible css transformations
|
* Defines possible css transformations
|
||||||
*/
|
*/
|
||||||
export type TransformationType = 'rotate' | 'rotateX' | 'rotateY' | 'translate' | 'translateX' | 'translateY' | 'scale' | 'scaleX' | 'scaleY';
|
export type TransformationType = 'rotate' | 'rotate3d' | 'rotateX' | 'rotateY' | 'translate' | 'translate3d' | 'translateX' | 'translateY' | 'scale' | 'scale3d' | 'scaleX' | 'scaleY';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines possible css transformation values
|
* Defines possible css transformation values
|
||||||
|
@ -3,6 +3,7 @@ import { LinearGradient } from './linear-gradient';
|
|||||||
// Types.
|
// Types.
|
||||||
import { Color } from '../../color';
|
import { Color } from '../../color';
|
||||||
import { BoxShadow } from './box-shadow';
|
import { BoxShadow } from './box-shadow';
|
||||||
|
import { ClipPathFunction } from './clip-path-function';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flags used to hint the background handler if it has to clear a specific property
|
* Flags used to hint the background handler if it has to clear a specific property
|
||||||
@ -39,7 +40,7 @@ export class Background {
|
|||||||
public borderTopRightRadius = 0;
|
public borderTopRightRadius = 0;
|
||||||
public borderBottomLeftRadius = 0;
|
public borderBottomLeftRadius = 0;
|
||||||
public borderBottomRightRadius = 0;
|
public borderBottomRightRadius = 0;
|
||||||
public clipPath: string;
|
public clipPath: string | ClipPathFunction;
|
||||||
public boxShadow: BoxShadow;
|
public boxShadow: BoxShadow;
|
||||||
public clearFlags: number = BackgroundClearFlags.NONE;
|
public clearFlags: number = BackgroundClearFlags.NONE;
|
||||||
|
|
||||||
@ -192,7 +193,7 @@ export class Background {
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public withClipPath(value: string): Background {
|
public withClipPath(value: string | ClipPathFunction): Background {
|
||||||
const clone = this.clone();
|
const clone = this.clone();
|
||||||
clone.clipPath = value;
|
clone.clipPath = value;
|
||||||
|
|
||||||
@ -224,16 +225,23 @@ export class Background {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let imagesEqual = false;
|
let isImageEqual = false;
|
||||||
if (value1 instanceof LinearGradient && value2 instanceof LinearGradient) {
|
if (value1 instanceof LinearGradient && value2 instanceof LinearGradient) {
|
||||||
imagesEqual = LinearGradient.equals(value1, value2);
|
isImageEqual = LinearGradient.equals(value1, value2);
|
||||||
} else {
|
} else {
|
||||||
imagesEqual = value1.image === value2.image;
|
isImageEqual = value1.image === value2.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isClipPathEqual = false;
|
||||||
|
if (value1.clipPath instanceof ClipPathFunction && value2.clipPath instanceof ClipPathFunction) {
|
||||||
|
isClipPathEqual = ClipPathFunction.equals(value1.clipPath, value2.clipPath);
|
||||||
|
} else {
|
||||||
|
isClipPathEqual = value1.clipPath === value2.clipPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Color.equals(value1.color, value2.color) &&
|
Color.equals(value1.color, value2.color) &&
|
||||||
imagesEqual &&
|
isImageEqual &&
|
||||||
value1.position === value2.position &&
|
value1.position === value2.position &&
|
||||||
value1.repeat === value2.repeat &&
|
value1.repeat === value2.repeat &&
|
||||||
value1.size === value2.size &&
|
value1.size === value2.size &&
|
||||||
@ -249,7 +257,7 @@ export class Background {
|
|||||||
value1.borderTopRightRadius === value2.borderTopRightRadius &&
|
value1.borderTopRightRadius === value2.borderTopRightRadius &&
|
||||||
value1.borderBottomRightRadius === value2.borderBottomRightRadius &&
|
value1.borderBottomRightRadius === value2.borderBottomRightRadius &&
|
||||||
value1.borderBottomLeftRadius === value2.borderBottomLeftRadius &&
|
value1.borderBottomLeftRadius === value2.borderBottomLeftRadius &&
|
||||||
value1.clipPath === value2.clipPath
|
isClipPathEqual
|
||||||
// && value1.clearFlags === value2.clearFlags
|
// && value1.clearFlags === value2.clearFlags
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { View } from '../core/view';
|
import { View } from '../core/view';
|
||||||
import { LinearGradient } from './linear-gradient';
|
import { LinearGradient } from './linear-gradient';
|
||||||
|
import { ClipPathFunction } from './clip-path-function';
|
||||||
import { isDataURI, isFileOrResourcePath, RESOURCE_PREFIX, FILE_PREFIX } from '../../utils';
|
import { isDataURI, isFileOrResourcePath, RESOURCE_PREFIX, FILE_PREFIX } from '../../utils';
|
||||||
import { parse } from '../../css-value';
|
import { parse } from '../../css-value';
|
||||||
import { path, knownFolders } from '../../file-system';
|
import { path, knownFolders } from '../../file-system';
|
||||||
@ -92,7 +93,7 @@ export function refreshBorderDrawable(view: View, borderDrawable: org.nativescri
|
|||||||
background.borderBottomRightRadius,
|
background.borderBottomRightRadius,
|
||||||
background.borderBottomLeftRadius,
|
background.borderBottomLeftRadius,
|
||||||
|
|
||||||
background.clipPath,
|
background.clipPath instanceof ClipPathFunction ? background.clipPath.toString() : background.clipPath,
|
||||||
|
|
||||||
background.color ? background.color.android : 0,
|
background.color ? background.color.android : 0,
|
||||||
imageUri,
|
imageUri,
|
||||||
@ -103,7 +104,7 @@ export function refreshBorderDrawable(view: View, borderDrawable: org.nativescri
|
|||||||
background.position,
|
background.position,
|
||||||
backgroundPositionParsedCSSValues,
|
backgroundPositionParsedCSSValues,
|
||||||
background.size,
|
background.size,
|
||||||
backgroundSizeParsedCSSValues
|
backgroundSizeParsedCSSValues,
|
||||||
);
|
);
|
||||||
//console.log(`>>> ${borderDrawable.toDebugString()}`);
|
//console.log(`>>> ${borderDrawable.toDebugString()}`);
|
||||||
}
|
}
|
||||||
|
17
packages/core/ui/styling/background.d.ts
vendored
17
packages/core/ui/styling/background.d.ts
vendored
@ -1,7 +1,8 @@
|
|||||||
import { Color } from '../../color';
|
import { Color } from '../../color';
|
||||||
import { View } from '../core/view';
|
import { View } from '../core/view';
|
||||||
import { BackgroundRepeat } from '../../css/parser';
|
import { BackgroundRepeat } from '../../css/parser';
|
||||||
import { LinearGradient } from '../styling/linear-gradient';
|
import { LinearGradient } from './linear-gradient';
|
||||||
|
import { ClipPathFunction } from './clip-path-function';
|
||||||
import { BoxShadow } from './box-shadow';
|
import { BoxShadow } from './box-shadow';
|
||||||
import { Background as BackgroundDefinition } from './background-common';
|
import { Background as BackgroundDefinition } from './background-common';
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ export enum CacheMode {
|
|||||||
// public borderTopRightRadius: number;
|
// public borderTopRightRadius: number;
|
||||||
// public borderBottomRightRadius: number;
|
// public borderBottomRightRadius: number;
|
||||||
// public borderBottomLeftRadius: number;
|
// public borderBottomLeftRadius: number;
|
||||||
// public clipPath: string;
|
// public clipPath: string | ClipPathFunction;
|
||||||
// public boxShadow: string | BoxShadow;
|
// public boxShadow: string | BoxShadow;
|
||||||
// public clearFlags: number;
|
// public clearFlags: number;
|
||||||
|
|
||||||
@ -80,12 +81,12 @@ export namespace ios {
|
|||||||
export function drawBackgroundVisualEffects(view: View): void;
|
export function drawBackgroundVisualEffects(view: View): void;
|
||||||
export function clearBackgroundVisualEffects(view: View): void;
|
export function clearBackgroundVisualEffects(view: View): void;
|
||||||
export function createUIImageFromURI(view: View, imageURI: string, flip: boolean, callback: (image: any) => void): void;
|
export function createUIImageFromURI(view: View, imageURI: string, flip: boolean, callback: (image: any) => void): void;
|
||||||
export function generateClipPath(view: View, bounds: CGRect): any;
|
export function generateClipPath(view: View, bounds: any /* CGRect */): any;
|
||||||
export function generateShadowLayerPaths(view: View, bounds: CGRect): { maskPath: any; shadowPath: any };
|
export function generateShadowLayerPaths(view: View, bounds: any /* CGRect */): { maskPath: any; shadowPath: any };
|
||||||
export function getUniformBorderRadius(view: View, bounds: CGRect): number;
|
export function getUniformBorderRadius(view: View, bounds: any /* CGRect */): number;
|
||||||
export function generateNonUniformBorderInnerClipRoundedPath(view: View, bounds: CGRect): any;
|
export function generateNonUniformBorderInnerClipRoundedPath(view: View, bounds: any /* CGRect */): any;
|
||||||
export function generateNonUniformBorderOuterClipRoundedPath(view: View, bounds: CGRect): any;
|
export function generateNonUniformBorderOuterClipRoundedPath(view: View, bounds: any /* CGRect */): any;
|
||||||
export function generateNonUniformMultiColorBorderRoundedPaths(view: View, bounds: CGRect): Array<any>;
|
export function generateNonUniformMultiColorBorderRoundedPaths(view: View, bounds: any /* CGRect */): Array<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace ad {
|
export namespace ad {
|
||||||
|
@ -11,6 +11,7 @@ import { parse as cssParse } from '../../css-value/reworkcss-value.js';
|
|||||||
import { BoxShadow } from './box-shadow';
|
import { BoxShadow } from './box-shadow';
|
||||||
import { Length } from './style-properties';
|
import { Length } from './style-properties';
|
||||||
import { BackgroundClearFlags } from './background-common';
|
import { BackgroundClearFlags } from './background-common';
|
||||||
|
import { ClipPathFunction } from './clip-path-function';
|
||||||
|
|
||||||
export * from './background-common';
|
export * from './background-common';
|
||||||
|
|
||||||
@ -303,30 +304,28 @@ export namespace ios {
|
|||||||
let path: UIBezierPath;
|
let path: UIBezierPath;
|
||||||
const clipPath = background.clipPath;
|
const clipPath = background.clipPath;
|
||||||
|
|
||||||
const functionName: string = clipPath.substring(0, clipPath.indexOf('('));
|
if (clipPath instanceof ClipPathFunction) {
|
||||||
const value: string = clipPath.replace(`${functionName}(`, '').replace(')', '');
|
switch (clipPath.shape) {
|
||||||
|
|
||||||
switch (functionName) {
|
|
||||||
case 'rect':
|
case 'rect':
|
||||||
path = rectPath(value, position);
|
path = rectPath(clipPath.rule, position);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'inset':
|
case 'inset':
|
||||||
path = insetPath(value, position);
|
path = insetPath(clipPath.rule, position);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'circle':
|
case 'circle':
|
||||||
path = circlePath(value, position);
|
path = circlePath(clipPath.rule, position);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'ellipse':
|
case 'ellipse':
|
||||||
path = ellipsePath(value, position);
|
path = ellipsePath(clipPath.rule, position);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'polygon':
|
case 'polygon':
|
||||||
path = polygonPath(value, position);
|
path = polygonPath(clipPath.rule, position);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
path = null;
|
||||||
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
39
packages/core/ui/styling/clip-path-function.ts
Normal file
39
packages/core/ui/styling/clip-path-function.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
type ClipPathShape = 'rect' | 'circle' | 'ellipse' | 'polygon' | 'inset';
|
||||||
|
|
||||||
|
interface IClipPathFunction {
|
||||||
|
shape: ClipPathShape;
|
||||||
|
rule: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ClipPathFunction implements IClipPathFunction {
|
||||||
|
private readonly _shape: ClipPathShape;
|
||||||
|
private readonly _rule: string;
|
||||||
|
|
||||||
|
constructor(shape: ClipPathShape, rule: string) {
|
||||||
|
this._shape = shape;
|
||||||
|
this._rule = rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
get shape(): ClipPathShape {
|
||||||
|
return this._shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
get rule(): string {
|
||||||
|
return this._rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static equals(value1: ClipPathFunction, value2: ClipPathFunction): boolean {
|
||||||
|
return value1.shape === value2.shape && value1.rule === value2.rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(): IClipPathFunction {
|
||||||
|
return {
|
||||||
|
shape: this._shape,
|
||||||
|
rule: this._rule,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
return `${this._shape}(${this._rule})`;
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ import { CssAnimationProperty } from '../core/properties';
|
|||||||
import { KeyframeAnimationInfo, KeyframeDeclaration, KeyframeInfo, UnparsedKeyframe } from '../animation/keyframe-animation';
|
import { KeyframeAnimationInfo, KeyframeDeclaration, KeyframeInfo, UnparsedKeyframe } from '../animation/keyframe-animation';
|
||||||
import { timeConverter, animationTimingFunctionConverter } from '../styling/converters';
|
import { timeConverter, animationTimingFunctionConverter } from '../styling/converters';
|
||||||
|
|
||||||
import { transformConverter } from '../styling/style-properties';
|
import { transformConverter } from '../styling/css-transform';
|
||||||
import { cleanupImportantFlags } from './css-utils';
|
import { cleanupImportantFlags } from './css-utils';
|
||||||
|
|
||||||
const ANIMATION_PROPERTY_HANDLERS = Object.freeze({
|
const ANIMATION_PROPERTY_HANDLERS = Object.freeze({
|
||||||
|
133
packages/core/ui/styling/css-transform.ts
Normal file
133
packages/core/ui/styling/css-transform.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import { Pair, Transformation, TransformationType, TransformationValue, TransformFunctionsInfo } from '../animation';
|
||||||
|
import { radiansToDegrees } from '../../utils/number-utils';
|
||||||
|
import { decompose2DTransformMatrix, getTransformMatrix, matrixArrayToCssMatrix, multiplyAffine2d } from '../../matrix';
|
||||||
|
import { hasDuplicates } from '../../utils';
|
||||||
|
|
||||||
|
type TransformationStyleMap = {
|
||||||
|
[key: string]: (value: TransformationValue) => Transformation;
|
||||||
|
};
|
||||||
|
|
||||||
|
const IDENTITY_TRANSFORMATION = {
|
||||||
|
translate: { x: 0, y: 0 },
|
||||||
|
rotate: { x: 0, y: 0, z: 0 },
|
||||||
|
scale: { x: 1, y: 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const TRANSFORM_SPLITTER = new RegExp(/\s*(.+?)\((.*?)\)/g);
|
||||||
|
const TRANSFORMATIONS = Object.freeze<TransformationType[]>(['rotate', 'rotateX', 'rotateY', 'rotate3d', 'translate', 'translate3d', 'translateX', 'translateY', 'scale', 'scale3d', 'scaleX', 'scaleY']);
|
||||||
|
|
||||||
|
const STYLE_TRANSFORMATION_MAP: TransformationStyleMap = Object.freeze<TransformationStyleMap>({
|
||||||
|
scale: (value: number) => ({ property: 'scale', value }),
|
||||||
|
scale3d: (value: number) => ({ property: 'scale', value }),
|
||||||
|
scaleX: ({ x }: Pair) => ({
|
||||||
|
property: 'scale',
|
||||||
|
value: { x, y: IDENTITY_TRANSFORMATION.scale.y },
|
||||||
|
}),
|
||||||
|
scaleY: ({ y }: Pair) => ({
|
||||||
|
property: 'scale',
|
||||||
|
value: { y, x: IDENTITY_TRANSFORMATION.scale.x },
|
||||||
|
}),
|
||||||
|
translate: (value) => ({ property: 'translate', value }),
|
||||||
|
translate3d: (value) => ({ property: 'translate', value }),
|
||||||
|
translateX: ({ x }: Pair) => ({
|
||||||
|
property: 'translate',
|
||||||
|
value: { x, y: IDENTITY_TRANSFORMATION.translate.y },
|
||||||
|
}),
|
||||||
|
translateY: ({ y }: Pair) => ({
|
||||||
|
property: 'translate',
|
||||||
|
value: { y, x: IDENTITY_TRANSFORMATION.translate.x },
|
||||||
|
}),
|
||||||
|
|
||||||
|
rotate3d: (value) => ({ property: 'rotate', value }),
|
||||||
|
rotateX: (x: number) => ({
|
||||||
|
property: 'rotate',
|
||||||
|
value: {
|
||||||
|
x,
|
||||||
|
y: IDENTITY_TRANSFORMATION.rotate.y,
|
||||||
|
z: IDENTITY_TRANSFORMATION.rotate.z,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
rotateY: (y: number) => ({
|
||||||
|
property: 'rotate',
|
||||||
|
value: {
|
||||||
|
x: IDENTITY_TRANSFORMATION.rotate.x,
|
||||||
|
y,
|
||||||
|
z: IDENTITY_TRANSFORMATION.rotate.z,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
rotate: (z: number) => ({
|
||||||
|
property: 'rotate',
|
||||||
|
value: {
|
||||||
|
x: IDENTITY_TRANSFORMATION.rotate.x,
|
||||||
|
y: IDENTITY_TRANSFORMATION.rotate.y,
|
||||||
|
z,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export function transformConverter(text: string): TransformFunctionsInfo {
|
||||||
|
const transformations = parseTransformString(text);
|
||||||
|
|
||||||
|
if (text === 'none' || text === '' || !transformations.length) {
|
||||||
|
return IDENTITY_TRANSFORMATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
const usedTransforms = transformations.map((t) => t.property);
|
||||||
|
if (!hasDuplicates(usedTransforms)) {
|
||||||
|
const fullTransformations = { ...IDENTITY_TRANSFORMATION };
|
||||||
|
transformations.forEach((transform) => {
|
||||||
|
fullTransformations[transform.property] = transform.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return fullTransformations;
|
||||||
|
}
|
||||||
|
|
||||||
|
const affineMatrix = transformations.map(getTransformMatrix).reduce(multiplyAffine2d);
|
||||||
|
const cssMatrix = matrixArrayToCssMatrix(affineMatrix);
|
||||||
|
|
||||||
|
return decompose2DTransformMatrix(cssMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTransformType(propertyName: string): propertyName is TransformationType {
|
||||||
|
return (TRANSFORMATIONS as string[]).indexOf(propertyName) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// using general regex and manually checking the matched
|
||||||
|
// properties is faster than using more specific regex
|
||||||
|
// https://jsperf.com/cssparse
|
||||||
|
function parseTransformString(text: string): Transformation[] {
|
||||||
|
const matches: Transformation[] = [];
|
||||||
|
let match: RegExpExecArray;
|
||||||
|
|
||||||
|
while ((match = TRANSFORM_SPLITTER.exec(text)) !== null) {
|
||||||
|
const property = match[1];
|
||||||
|
|
||||||
|
if (isTransformType(property)) {
|
||||||
|
const value = convertTransformValue(property, match[2]);
|
||||||
|
matches.push(STYLE_TRANSFORMATION_MAP[property](value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertTransformValue(property: TransformationType, rawValue: string): TransformationValue {
|
||||||
|
const values = rawValue.split(',').map(parseFloat);
|
||||||
|
const x = values[0];
|
||||||
|
|
||||||
|
let y = values[1];
|
||||||
|
let z = values[2];
|
||||||
|
|
||||||
|
if (property === 'translate') {
|
||||||
|
y ??= IDENTITY_TRANSFORMATION.translate.y;
|
||||||
|
} else {
|
||||||
|
y ??= x;
|
||||||
|
z ??= y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property === 'rotate' || property === 'rotateX' || property === 'rotateY') {
|
||||||
|
return rawValue.slice(-3) === 'rad' ? radiansToDegrees(x) : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { x, y, z };
|
||||||
|
}
|
24
packages/core/ui/styling/style-properties.d.ts
vendored
24
packages/core/ui/styling/style-properties.d.ts
vendored
@ -1,17 +1,29 @@
|
|||||||
import { TransformFunctionsInfo } from '../animation';
|
|
||||||
import { CoreTypes } from '../../core-types';
|
import { CoreTypes } from '../../core-types';
|
||||||
import { Color } from '../../color';
|
import { Color } from '../../color';
|
||||||
import { CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty } from '../core/properties';
|
import { CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty } from '../core/properties';
|
||||||
import { Style } from './style';
|
import { Style } from './style';
|
||||||
import { Font, FontStyleType, FontWeightType, FontVariationSettingsType } from './font';
|
import { Font, FontStyleType, FontWeightType, FontVariationSettingsType } from './font';
|
||||||
import { Background } from './background';
|
import { Background } from './background';
|
||||||
|
import { ClipPathFunction } from './clip-path-function';
|
||||||
|
import { LinearGradient } from './linear-gradient';
|
||||||
|
|
||||||
|
export namespace FixedLength {
|
||||||
|
export function parse(text: string): CoreTypes.FixedLengthType;
|
||||||
|
export function equals(a: CoreTypes.FixedLengthType, b: CoreTypes.FixedLengthType): boolean;
|
||||||
|
/**
|
||||||
|
* Converts FixedLengthType unit to device pixels.
|
||||||
|
* @param length The FixedLengthType to convert.
|
||||||
|
*/
|
||||||
|
export function toDevicePixels(length: CoreTypes.FixedLengthType): number;
|
||||||
|
export function convertToString(length: CoreTypes.FixedLengthType): string;
|
||||||
|
}
|
||||||
|
|
||||||
export namespace Length {
|
export namespace Length {
|
||||||
export function parse(text: string): CoreTypes.LengthType;
|
export function parse(text: string): CoreTypes.LengthType;
|
||||||
export function equals(a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean;
|
export function equals(a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean;
|
||||||
/**
|
/**
|
||||||
* Converts Length unit to device pixels.
|
* Converts LengthType unit to device pixels.
|
||||||
* @param length The Length to convert.
|
* @param length The LengthType to convert.
|
||||||
* @param auto Value to use for conversion of "auto". By default is Math.NaN.
|
* @param auto Value to use for conversion of "auto". By default is Math.NaN.
|
||||||
*/
|
*/
|
||||||
export function toDevicePixels(length: CoreTypes.LengthType, auto?: number): number;
|
export function toDevicePixels(length: CoreTypes.LengthType, auto?: number): number;
|
||||||
@ -39,14 +51,12 @@ export const scaleYProperty: CssAnimationProperty<Style, number>;
|
|||||||
export const translateXProperty: CssAnimationProperty<Style, CoreTypes.dip>;
|
export const translateXProperty: CssAnimationProperty<Style, CoreTypes.dip>;
|
||||||
export const translateYProperty: CssAnimationProperty<Style, CoreTypes.dip>;
|
export const translateYProperty: CssAnimationProperty<Style, CoreTypes.dip>;
|
||||||
|
|
||||||
export function transformConverter(text: string): TransformFunctionsInfo;
|
export const clipPathProperty: CssProperty<Style, string | ClipPathFunction>;
|
||||||
|
|
||||||
export const clipPathProperty: CssProperty<Style, string>;
|
|
||||||
export const colorProperty: InheritedCssProperty<Style, Color>;
|
export const colorProperty: InheritedCssProperty<Style, Color>;
|
||||||
|
|
||||||
export const backgroundProperty: ShorthandProperty<Style, string>;
|
export const backgroundProperty: ShorthandProperty<Style, string>;
|
||||||
export const backgroundColorProperty: CssAnimationProperty<Style, Color>;
|
export const backgroundColorProperty: CssAnimationProperty<Style, Color>;
|
||||||
export const backgroundImageProperty: CssProperty<Style, string>;
|
export const backgroundImageProperty: CssProperty<Style, string | LinearGradient>;
|
||||||
export const backgroundRepeatProperty: CssProperty<Style, CoreTypes.BackgroundRepeatType>;
|
export const backgroundRepeatProperty: CssProperty<Style, CoreTypes.BackgroundRepeatType>;
|
||||||
export const backgroundSizeProperty: CssProperty<Style, string>;
|
export const backgroundSizeProperty: CssProperty<Style, string>;
|
||||||
export const backgroundPositionProperty: CssProperty<Style, string>;
|
export const backgroundPositionProperty: CssProperty<Style, string>;
|
||||||
|
@ -1,59 +1,59 @@
|
|||||||
// Types
|
|
||||||
import { unsetValue, CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty } from '../core/properties';
|
import { unsetValue, CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty } from '../core/properties';
|
||||||
import { Style } from './style';
|
import { Style } from './style';
|
||||||
import { Transformation, TransformationValue, TransformFunctionsInfo } from '../animation';
|
|
||||||
|
|
||||||
import { Color } from '../../color';
|
import { Color } from '../../color';
|
||||||
import { Font, parseFont, FontStyle, FontStyleType, FontWeight, FontWeightType, FontVariationSettings, FontVariationSettingsType } from './font';
|
import { Font, parseFont, FontStyle, FontStyleType, FontWeight, FontWeightType, FontVariationSettings, FontVariationSettingsType } from './font';
|
||||||
import { Background } from './background';
|
import { Background } from './background';
|
||||||
import { layout, hasDuplicates } from '../../utils';
|
import { layout } from '../../utils';
|
||||||
|
|
||||||
import { radiansToDegrees } from '../../utils/number-utils';
|
|
||||||
|
|
||||||
import { decompose2DTransformMatrix, getTransformMatrix, matrixArrayToCssMatrix, multiplyAffine2d } from '../../matrix';
|
|
||||||
import { Trace } from '../../trace';
|
import { Trace } from '../../trace';
|
||||||
import { CoreTypes } from '../../core-types';
|
import { CoreTypes } from '../../core-types';
|
||||||
|
|
||||||
import { parseBackground } from '../../css/parser';
|
import { parseBackground } from '../../css/parser';
|
||||||
import { LinearGradient } from './linear-gradient';
|
import { LinearGradient } from './linear-gradient';
|
||||||
import { parseCSSShadow, ShadowCSSValues } from './css-shadow';
|
import { parseCSSShadow, ShadowCSSValues } from './css-shadow';
|
||||||
|
import { transformConverter } from './css-transform';
|
||||||
|
import { ClipPathFunction } from './clip-path-function';
|
||||||
|
|
||||||
|
interface ShorthandPositioning {
|
||||||
|
top: string;
|
||||||
|
right: string;
|
||||||
|
bottom: string;
|
||||||
|
left: string;
|
||||||
|
}
|
||||||
|
|
||||||
function equalsCommon(a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean;
|
function equalsCommon(a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean;
|
||||||
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean;
|
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean;
|
||||||
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean {
|
function equalsCommon(a: CoreTypes.PercentLengthType, b: CoreTypes.PercentLengthType): boolean {
|
||||||
if (a == 'auto') {
|
if (a == 'auto') {
|
||||||
// tslint:disable-line
|
return b == 'auto';
|
||||||
return b == 'auto'; // tslint:disable-line
|
|
||||||
}
|
}
|
||||||
if (typeof a === 'number') {
|
|
||||||
if (b == 'auto') {
|
if (b == 'auto') {
|
||||||
// tslint:disable-line
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof a === 'number') {
|
||||||
if (typeof b === 'number') {
|
if (typeof b === 'number') {
|
||||||
return a == b; // tslint:disable-line
|
return a == b;
|
||||||
}
|
}
|
||||||
if (!b) {
|
if (!b) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return b.unit == 'dip' && a == b.value; // tslint:disable-line
|
return b.unit == 'dip' && a == b.value;
|
||||||
}
|
|
||||||
if (b == 'auto') {
|
|
||||||
// tslint:disable-line
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof b === 'number') {
|
if (typeof b === 'number') {
|
||||||
return a ? a.unit == 'dip' && a.value == b : false; // tslint:disable-line
|
return a ? a.unit == 'dip' && a.value == b : false;
|
||||||
}
|
}
|
||||||
if (!a || !b) {
|
if (!a || !b) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return a.value == b.value && a.unit == b.unit; // tslint:disable-line
|
return a.value == b.value && a.unit == b.unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertToStringCommon(length: CoreTypes.LengthType | CoreTypes.PercentLengthType): string {
|
function convertToStringCommon(length: CoreTypes.LengthType | CoreTypes.PercentLengthType): string {
|
||||||
if (length == 'auto') {
|
if (length == 'auto') {
|
||||||
// tslint:disable-line
|
|
||||||
return 'auto';
|
return 'auto';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,6 @@ function convertToStringCommon(length: CoreTypes.LengthType | CoreTypes.PercentL
|
|||||||
|
|
||||||
function toDevicePixelsCommon(length: CoreTypes.PercentLengthType, auto: number = Number.NaN, parentAvailableWidth: number = Number.NaN): number {
|
function toDevicePixelsCommon(length: CoreTypes.PercentLengthType, auto: number = Number.NaN, parentAvailableWidth: number = Number.NaN): number {
|
||||||
if (length == 'auto') {
|
if (length == 'auto') {
|
||||||
// tslint:disable-line
|
|
||||||
return auto;
|
return auto;
|
||||||
}
|
}
|
||||||
if (typeof length === 'number') {
|
if (typeof length === 'number') {
|
||||||
@ -94,9 +93,9 @@ function toDevicePixelsCommon(length: CoreTypes.PercentLengthType, auto: number
|
|||||||
export namespace PercentLength {
|
export namespace PercentLength {
|
||||||
export function parse(fromValue: string | CoreTypes.LengthType): CoreTypes.PercentLengthType {
|
export function parse(fromValue: string | CoreTypes.LengthType): CoreTypes.PercentLengthType {
|
||||||
if (fromValue == 'auto') {
|
if (fromValue == 'auto') {
|
||||||
// tslint:disable-line
|
|
||||||
return 'auto';
|
return 'auto';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof fromValue === 'string') {
|
if (typeof fromValue === 'string') {
|
||||||
let stringValue = fromValue.trim();
|
let stringValue = fromValue.trim();
|
||||||
const percentIndex = stringValue.indexOf('%');
|
const percentIndex = stringValue.indexOf('%');
|
||||||
@ -147,12 +146,8 @@ export namespace PercentLength {
|
|||||||
} = convertToStringCommon;
|
} = convertToStringCommon;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace Length {
|
export namespace FixedLength {
|
||||||
export function parse(fromValue: string | CoreTypes.LengthType): CoreTypes.LengthType {
|
export function parse(fromValue: string | CoreTypes.FixedLengthType): CoreTypes.FixedLengthType {
|
||||||
if (fromValue == 'auto') {
|
|
||||||
// tslint:disable-line
|
|
||||||
return 'auto';
|
|
||||||
}
|
|
||||||
if (typeof fromValue === 'string') {
|
if (typeof fromValue === 'string') {
|
||||||
let stringValue = fromValue.trim();
|
let stringValue = fromValue.trim();
|
||||||
if (stringValue.indexOf('px') !== -1) {
|
if (stringValue.indexOf('px') !== -1) {
|
||||||
@ -175,6 +170,23 @@ export namespace Length {
|
|||||||
return fromValue;
|
return fromValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export const equals: { (a: CoreTypes.FixedLengthType, b: CoreTypes.FixedLengthType): boolean } = equalsCommon;
|
||||||
|
export const toDevicePixels: {
|
||||||
|
(length: CoreTypes.FixedLengthType): number;
|
||||||
|
} = toDevicePixelsCommon;
|
||||||
|
export const convertToString: {
|
||||||
|
(length: CoreTypes.FixedLengthType): string;
|
||||||
|
} = convertToStringCommon;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace Length {
|
||||||
|
export function parse(fromValue: string | CoreTypes.LengthType): CoreTypes.LengthType {
|
||||||
|
if (fromValue == 'auto') {
|
||||||
|
return 'auto';
|
||||||
|
}
|
||||||
|
|
||||||
|
return FixedLength.parse(fromValue);
|
||||||
|
}
|
||||||
export const equals: { (a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean } = equalsCommon;
|
export const equals: { (a: CoreTypes.LengthType, b: CoreTypes.LengthType): boolean } = equalsCommon;
|
||||||
export const toDevicePixels: {
|
export const toDevicePixels: {
|
||||||
(length: CoreTypes.LengthType, auto?: number): number;
|
(length: CoreTypes.LengthType, auto?: number): number;
|
||||||
@ -184,6 +196,185 @@ export namespace Length {
|
|||||||
} = convertToStringCommon;
|
} = convertToStringCommon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isNonNegativeFiniteNumber(value: number): boolean {
|
||||||
|
return isFinite(value) && !isNaN(value) && value >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseClipPath(value: string): string | ClipPathFunction {
|
||||||
|
const functionStartIndex = value.indexOf('(');
|
||||||
|
|
||||||
|
if (functionStartIndex > -1) {
|
||||||
|
const functionName = value.substring(0, functionStartIndex).trim();
|
||||||
|
|
||||||
|
switch (functionName) {
|
||||||
|
case 'rect':
|
||||||
|
case 'circle':
|
||||||
|
case 'ellipse':
|
||||||
|
case 'polygon':
|
||||||
|
case 'inset': {
|
||||||
|
const rule: string = value.replace(`${functionName}(`, '').replace(')', '');
|
||||||
|
return new ClipPathFunction(functionName, rule);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new Error(`Clip-path function ${functionName} is not valid.`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value === 'none') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only shape functions and none are supported for now
|
||||||
|
throw new Error(`Clip-path value ${value} is not valid.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseShorthandPositioning(value: string): ShorthandPositioning {
|
||||||
|
const arr = value.split(/[ ,]+/);
|
||||||
|
|
||||||
|
let top: string;
|
||||||
|
let right: string;
|
||||||
|
let bottom: string;
|
||||||
|
let left: string;
|
||||||
|
|
||||||
|
if (arr.length === 1) {
|
||||||
|
top = arr[0];
|
||||||
|
right = arr[0];
|
||||||
|
bottom = arr[0];
|
||||||
|
left = arr[0];
|
||||||
|
} else if (arr.length === 2) {
|
||||||
|
top = arr[0];
|
||||||
|
bottom = arr[0];
|
||||||
|
right = arr[1];
|
||||||
|
left = arr[1];
|
||||||
|
} else if (arr.length === 3) {
|
||||||
|
top = arr[0];
|
||||||
|
right = arr[1];
|
||||||
|
left = arr[1];
|
||||||
|
bottom = arr[2];
|
||||||
|
} else if (arr.length === 4) {
|
||||||
|
top = arr[0];
|
||||||
|
right = arr[1];
|
||||||
|
bottom = arr[2];
|
||||||
|
left = arr[3];
|
||||||
|
} else {
|
||||||
|
throw new Error('Expected 1, 2, 3 or 4 parameters. Actual: ' + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
top: top,
|
||||||
|
right: right,
|
||||||
|
bottom: bottom,
|
||||||
|
left: left,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseBorderColorPositioning(value: string): ShorthandPositioning {
|
||||||
|
if (value.indexOf('rgb') === 0 || value.indexOf('hsl') === 0) {
|
||||||
|
return {
|
||||||
|
top: value,
|
||||||
|
right: value,
|
||||||
|
bottom: value,
|
||||||
|
left: value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseShorthandPositioning(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertToBackgrounds(value: string): [CssProperty<any, any> | CssAnimationProperty<any, any>, any][] {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const backgrounds = parseBackground(value).value;
|
||||||
|
let backgroundColor = unsetValue;
|
||||||
|
if (backgrounds.color) {
|
||||||
|
backgroundColor = backgrounds.color instanceof Color ? backgrounds.color : new Color(backgrounds.color);
|
||||||
|
}
|
||||||
|
|
||||||
|
let backgroundImage: string | LinearGradient;
|
||||||
|
if (typeof backgrounds.image === 'object' && backgrounds.image) {
|
||||||
|
backgroundImage = LinearGradient.parse(backgrounds.image);
|
||||||
|
} else {
|
||||||
|
backgroundImage = backgrounds.image || unsetValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const backgroundRepeat = backgrounds.repeat || unsetValue;
|
||||||
|
const backgroundPosition = backgrounds.position ? backgrounds.position.text : unsetValue;
|
||||||
|
|
||||||
|
return [
|
||||||
|
[backgroundColorProperty, backgroundColor],
|
||||||
|
[backgroundImageProperty, backgroundImage],
|
||||||
|
[backgroundRepeatProperty, backgroundRepeat],
|
||||||
|
[backgroundPositionProperty, backgroundPosition],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
[backgroundColorProperty, unsetValue],
|
||||||
|
[backgroundImageProperty, unsetValue],
|
||||||
|
[backgroundRepeatProperty, unsetValue],
|
||||||
|
[backgroundPositionProperty, unsetValue],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertToMargins(value: string | CoreTypes.PercentLengthType): [CssProperty<Style, CoreTypes.PercentLengthType>, CoreTypes.PercentLengthType][] {
|
||||||
|
if (typeof value === 'string' && value !== 'auto') {
|
||||||
|
const thickness = parseShorthandPositioning(value);
|
||||||
|
|
||||||
|
return [
|
||||||
|
[marginTopProperty, PercentLength.parse(thickness.top)],
|
||||||
|
[marginRightProperty, PercentLength.parse(thickness.right)],
|
||||||
|
[marginBottomProperty, PercentLength.parse(thickness.bottom)],
|
||||||
|
[marginLeftProperty, PercentLength.parse(thickness.left)],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
[marginTopProperty, value],
|
||||||
|
[marginRightProperty, value],
|
||||||
|
[marginBottomProperty, value],
|
||||||
|
[marginLeftProperty, value],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertToPaddings(value: string | CoreTypes.LengthType): [CssProperty<Style, CoreTypes.LengthType>, CoreTypes.LengthType][] {
|
||||||
|
if (typeof value === 'string' && value !== 'auto') {
|
||||||
|
const thickness = parseShorthandPositioning(value);
|
||||||
|
|
||||||
|
return [
|
||||||
|
[paddingTopProperty, Length.parse(thickness.top)],
|
||||||
|
[paddingRightProperty, Length.parse(thickness.right)],
|
||||||
|
[paddingBottomProperty, Length.parse(thickness.bottom)],
|
||||||
|
[paddingLeftProperty, Length.parse(thickness.left)],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
[paddingTopProperty, value],
|
||||||
|
[paddingRightProperty, value],
|
||||||
|
[paddingBottomProperty, value],
|
||||||
|
[paddingLeftProperty, value],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertToTransform(value: string): [CssAnimationProperty<any, any>, any][] {
|
||||||
|
if (value === unsetValue) {
|
||||||
|
value = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
const { translate, rotate, scale } = transformConverter(value);
|
||||||
|
|
||||||
|
return [
|
||||||
|
[translateXProperty, translate.x],
|
||||||
|
[translateYProperty, translate.y],
|
||||||
|
|
||||||
|
[scaleXProperty, scale.x],
|
||||||
|
[scaleYProperty, scale.y],
|
||||||
|
|
||||||
|
[rotateProperty, rotate.z],
|
||||||
|
[rotateXProperty, rotate.x],
|
||||||
|
[rotateYProperty, rotate.y],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
export const minWidthProperty = new CssProperty<Style, CoreTypes.LengthType>({
|
export const minWidthProperty = new CssProperty<Style, CoreTypes.LengthType>({
|
||||||
name: 'minWidth',
|
name: 'minWidth',
|
||||||
cssName: 'min-width',
|
cssName: 'min-width',
|
||||||
@ -416,97 +607,6 @@ export const verticalAlignmentProperty = new CssProperty<Style, CoreTypes.Vertic
|
|||||||
});
|
});
|
||||||
verticalAlignmentProperty.register(Style);
|
verticalAlignmentProperty.register(Style);
|
||||||
|
|
||||||
interface Thickness {
|
|
||||||
top: string;
|
|
||||||
right: string;
|
|
||||||
bottom: string;
|
|
||||||
left: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseThickness(value: string): Thickness {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
const arr = value.split(/[ ,]+/);
|
|
||||||
|
|
||||||
let top: string;
|
|
||||||
let right: string;
|
|
||||||
let bottom: string;
|
|
||||||
let left: string;
|
|
||||||
|
|
||||||
if (arr.length === 1) {
|
|
||||||
top = arr[0];
|
|
||||||
right = arr[0];
|
|
||||||
bottom = arr[0];
|
|
||||||
left = arr[0];
|
|
||||||
} else if (arr.length === 2) {
|
|
||||||
top = arr[0];
|
|
||||||
bottom = arr[0];
|
|
||||||
right = arr[1];
|
|
||||||
left = arr[1];
|
|
||||||
} else if (arr.length === 3) {
|
|
||||||
top = arr[0];
|
|
||||||
right = arr[1];
|
|
||||||
left = arr[1];
|
|
||||||
bottom = arr[2];
|
|
||||||
} else if (arr.length === 4) {
|
|
||||||
top = arr[0];
|
|
||||||
right = arr[1];
|
|
||||||
bottom = arr[2];
|
|
||||||
left = arr[3];
|
|
||||||
} else {
|
|
||||||
throw new Error('Expected 1, 2, 3 or 4 parameters. Actual: ' + value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
top: top,
|
|
||||||
right: right,
|
|
||||||
bottom: bottom,
|
|
||||||
left: left,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertToMargins(this: void, value: string | CoreTypes.PercentLengthType): [CssProperty<any, any>, any][] {
|
|
||||||
if (typeof value === 'string' && value !== 'auto') {
|
|
||||||
const thickness = parseThickness(value);
|
|
||||||
|
|
||||||
return [
|
|
||||||
[marginTopProperty, PercentLength.parse(thickness.top)],
|
|
||||||
[marginRightProperty, PercentLength.parse(thickness.right)],
|
|
||||||
[marginBottomProperty, PercentLength.parse(thickness.bottom)],
|
|
||||||
[marginLeftProperty, PercentLength.parse(thickness.left)],
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
[marginTopProperty, value],
|
|
||||||
[marginRightProperty, value],
|
|
||||||
[marginBottomProperty, value],
|
|
||||||
[marginLeftProperty, value],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertToPaddings(this: void, value: string | CoreTypes.LengthType): [CssProperty<any, any>, any][] {
|
|
||||||
if (typeof value === 'string' && value !== 'auto') {
|
|
||||||
const thickness = parseThickness(value);
|
|
||||||
|
|
||||||
return [
|
|
||||||
[paddingTopProperty, Length.parse(thickness.top)],
|
|
||||||
[paddingRightProperty, Length.parse(thickness.right)],
|
|
||||||
[paddingBottomProperty, Length.parse(thickness.bottom)],
|
|
||||||
[paddingLeftProperty, Length.parse(thickness.left)],
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
[paddingTopProperty, value],
|
|
||||||
[paddingRightProperty, value],
|
|
||||||
[paddingBottomProperty, value],
|
|
||||||
[paddingLeftProperty, value],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const rotateProperty = new CssAnimationProperty<Style, number>({
|
export const rotateProperty = new CssAnimationProperty<Style, number>({
|
||||||
name: 'rotate',
|
name: 'rotate',
|
||||||
cssName: 'rotate',
|
cssName: 'rotate',
|
||||||
@ -555,27 +655,21 @@ export const scaleYProperty = new CssAnimationProperty<Style, number>({
|
|||||||
});
|
});
|
||||||
scaleYProperty.register(Style);
|
scaleYProperty.register(Style);
|
||||||
|
|
||||||
function parseDIPs(value: string): CoreTypes.dip {
|
export const translateXProperty = new CssAnimationProperty<Style, CoreTypes.FixedLengthType>({
|
||||||
if (value.indexOf('px') !== -1) {
|
|
||||||
return layout.toDeviceIndependentPixels(parseFloat(value.replace('px', '').trim()));
|
|
||||||
} else {
|
|
||||||
return parseFloat(value.replace('dip', '').trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const translateXProperty = new CssAnimationProperty<Style, CoreTypes.dip>({
|
|
||||||
name: 'translateX',
|
name: 'translateX',
|
||||||
cssName: 'translateX',
|
cssName: 'translateX',
|
||||||
defaultValue: 0,
|
defaultValue: 0,
|
||||||
valueConverter: parseDIPs,
|
equalityComparer: FixedLength.equals,
|
||||||
|
valueConverter: FixedLength.parse,
|
||||||
});
|
});
|
||||||
translateXProperty.register(Style);
|
translateXProperty.register(Style);
|
||||||
|
|
||||||
export const translateYProperty = new CssAnimationProperty<Style, CoreTypes.dip>({
|
export const translateYProperty = new CssAnimationProperty<Style, CoreTypes.FixedLengthType>({
|
||||||
name: 'translateY',
|
name: 'translateY',
|
||||||
cssName: 'translateY',
|
cssName: 'translateY',
|
||||||
defaultValue: 0,
|
defaultValue: 0,
|
||||||
valueConverter: parseDIPs,
|
equalityComparer: FixedLength.equals,
|
||||||
|
valueConverter: FixedLength.parse,
|
||||||
});
|
});
|
||||||
translateYProperty.register(Style);
|
translateYProperty.register(Style);
|
||||||
|
|
||||||
@ -608,148 +702,6 @@ const transformProperty = new ShorthandProperty<Style, string>({
|
|||||||
});
|
});
|
||||||
transformProperty.register(Style);
|
transformProperty.register(Style);
|
||||||
|
|
||||||
const IDENTITY_TRANSFORMATION = {
|
|
||||||
translate: { x: 0, y: 0 },
|
|
||||||
rotate: { x: 0, y: 0, z: 0 },
|
|
||||||
scale: { x: 1, y: 1 },
|
|
||||||
};
|
|
||||||
|
|
||||||
const TRANSFORM_SPLITTER = new RegExp(/\s*(.+?)\((.*?)\)/g);
|
|
||||||
const TRANSFORMATIONS = Object.freeze(['rotate', 'rotateX', 'rotateY', 'rotate3d', 'translate', 'translate3d', 'translateX', 'translateY', 'scale', 'scale3d', 'scaleX', 'scaleY']);
|
|
||||||
|
|
||||||
const STYLE_TRANSFORMATION_MAP = Object.freeze({
|
|
||||||
scale: (value) => ({ property: 'scale', value }),
|
|
||||||
scale3d: (value) => ({ property: 'scale', value }),
|
|
||||||
scaleX: ({ x }) => ({
|
|
||||||
property: 'scale',
|
|
||||||
value: { x, y: IDENTITY_TRANSFORMATION.scale.y },
|
|
||||||
}),
|
|
||||||
scaleY: ({ y }) => ({
|
|
||||||
property: 'scale',
|
|
||||||
value: { y, x: IDENTITY_TRANSFORMATION.scale.x },
|
|
||||||
}),
|
|
||||||
|
|
||||||
translate: (value) => ({ property: 'translate', value }),
|
|
||||||
translate3d: (value) => ({ property: 'translate', value }),
|
|
||||||
translateX: ({ x }) => ({
|
|
||||||
property: 'translate',
|
|
||||||
value: { x, y: IDENTITY_TRANSFORMATION.translate.y },
|
|
||||||
}),
|
|
||||||
translateY: ({ y }) => ({
|
|
||||||
property: 'translate',
|
|
||||||
value: { y, x: IDENTITY_TRANSFORMATION.translate.x },
|
|
||||||
}),
|
|
||||||
|
|
||||||
rotate3d: (value) => ({ property: 'rotate', value }),
|
|
||||||
rotateX: (x) => ({
|
|
||||||
property: 'rotate',
|
|
||||||
value: {
|
|
||||||
x,
|
|
||||||
y: IDENTITY_TRANSFORMATION.rotate.y,
|
|
||||||
z: IDENTITY_TRANSFORMATION.rotate.z,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
rotateY: (y) => ({
|
|
||||||
property: 'rotate',
|
|
||||||
value: {
|
|
||||||
x: IDENTITY_TRANSFORMATION.rotate.x,
|
|
||||||
y,
|
|
||||||
z: IDENTITY_TRANSFORMATION.rotate.z,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
rotate: (z) => ({
|
|
||||||
property: 'rotate',
|
|
||||||
value: {
|
|
||||||
x: IDENTITY_TRANSFORMATION.rotate.x,
|
|
||||||
y: IDENTITY_TRANSFORMATION.rotate.y,
|
|
||||||
z,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
function convertToTransform(value: string): [CssProperty<any, any>, any][] {
|
|
||||||
if (value === unsetValue) {
|
|
||||||
value = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
const { translate, rotate, scale } = transformConverter(value);
|
|
||||||
|
|
||||||
return [
|
|
||||||
[<any>translateXProperty, translate.x],
|
|
||||||
[<any>translateYProperty, translate.y],
|
|
||||||
|
|
||||||
[<any>scaleXProperty, scale.x],
|
|
||||||
[<any>scaleYProperty, scale.y],
|
|
||||||
|
|
||||||
[<any>rotateProperty, rotate.z],
|
|
||||||
[<any>rotateXProperty, rotate.x],
|
|
||||||
[<any>rotateYProperty, rotate.y],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function transformConverter(text: string): TransformFunctionsInfo {
|
|
||||||
const transformations = parseTransformString(text);
|
|
||||||
|
|
||||||
if (text === 'none' || text === '' || !transformations.length) {
|
|
||||||
return IDENTITY_TRANSFORMATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
const usedTransforms = transformations.map((t) => t.property);
|
|
||||||
if (!hasDuplicates(usedTransforms)) {
|
|
||||||
const fullTransformations = { ...IDENTITY_TRANSFORMATION };
|
|
||||||
transformations.forEach((transform) => {
|
|
||||||
fullTransformations[transform.property] = transform.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
return fullTransformations;
|
|
||||||
}
|
|
||||||
|
|
||||||
const affineMatrix = transformations.map(getTransformMatrix).reduce(multiplyAffine2d);
|
|
||||||
const cssMatrix = matrixArrayToCssMatrix(affineMatrix);
|
|
||||||
|
|
||||||
return decompose2DTransformMatrix(cssMatrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
// using general regex and manually checking the matched
|
|
||||||
// properties is faster than using more specific regex
|
|
||||||
// https://jsperf.com/cssparse
|
|
||||||
function parseTransformString(text: string): Transformation[] {
|
|
||||||
const matches: Transformation[] = [];
|
|
||||||
let match;
|
|
||||||
|
|
||||||
while ((match = TRANSFORM_SPLITTER.exec(text)) !== null) {
|
|
||||||
const property = match[1];
|
|
||||||
const value = convertTransformValue(property, match[2]);
|
|
||||||
|
|
||||||
if (TRANSFORMATIONS.indexOf(property) !== -1) {
|
|
||||||
matches.push(normalizeTransformation({ property, value }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return matches;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeTransformation({ property, value }: Transformation): Transformation {
|
|
||||||
return <any>STYLE_TRANSFORMATION_MAP[property](value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertTransformValue(property: string, stringValue: string): TransformationValue {
|
|
||||||
// eslint-disable-next-line prefer-const
|
|
||||||
let [x, y, z] = stringValue.split(',').map(parseFloat);
|
|
||||||
if (property === 'translate') {
|
|
||||||
y ??= IDENTITY_TRANSFORMATION.translate.y;
|
|
||||||
} else {
|
|
||||||
y ??= x;
|
|
||||||
z ??= y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (property === 'rotate' || property === 'rotateX' || property === 'rotateY') {
|
|
||||||
return stringValue.slice(-3) === 'rad' ? radiansToDegrees(x) : x;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { x, y, z };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Background properties.
|
// Background properties.
|
||||||
const backgroundProperty = new ShorthandProperty<Style, string | Color>({
|
const backgroundProperty = new ShorthandProperty<Style, string | Color>({
|
||||||
name: 'background',
|
name: 'background',
|
||||||
@ -768,7 +720,6 @@ export const backgroundInternalProperty = new CssProperty<Style, Background>({
|
|||||||
});
|
});
|
||||||
backgroundInternalProperty.register(Style);
|
backgroundInternalProperty.register(Style);
|
||||||
|
|
||||||
// const pattern: RegExp = /url\(('|")(.*?)\1\)/;
|
|
||||||
export const backgroundImageProperty = new CssProperty<Style, string | LinearGradient>({
|
export const backgroundImageProperty = new CssProperty<Style, string | LinearGradient>({
|
||||||
name: 'backgroundImage',
|
name: 'backgroundImage',
|
||||||
cssName: 'background-image',
|
cssName: 'background-image',
|
||||||
@ -834,91 +785,6 @@ export const backgroundPositionProperty = new CssProperty<Style, string>({
|
|||||||
});
|
});
|
||||||
backgroundPositionProperty.register(Style);
|
backgroundPositionProperty.register(Style);
|
||||||
|
|
||||||
function convertToBackgrounds(this: void, value: string): [CssProperty<any, any>, any][] {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
const backgrounds = parseBackground(value).value;
|
|
||||||
let backgroundColor = unsetValue;
|
|
||||||
if (backgrounds.color) {
|
|
||||||
backgroundColor = backgrounds.color instanceof Color ? backgrounds.color : new Color(backgrounds.color);
|
|
||||||
}
|
|
||||||
|
|
||||||
let backgroundImage: string | LinearGradient;
|
|
||||||
if (typeof backgrounds.image === 'object' && backgrounds.image) {
|
|
||||||
backgroundImage = LinearGradient.parse(backgrounds.image);
|
|
||||||
} else {
|
|
||||||
backgroundImage = backgrounds.image || unsetValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const backgroundRepeat = backgrounds.repeat || unsetValue;
|
|
||||||
const backgroundPosition = backgrounds.position ? backgrounds.position.text : unsetValue;
|
|
||||||
|
|
||||||
return [
|
|
||||||
[<any>backgroundColorProperty, backgroundColor],
|
|
||||||
[backgroundImageProperty, backgroundImage],
|
|
||||||
[backgroundRepeatProperty, backgroundRepeat],
|
|
||||||
[backgroundPositionProperty, backgroundPosition],
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
[<any>backgroundColorProperty, unsetValue],
|
|
||||||
[backgroundImageProperty, unsetValue],
|
|
||||||
[backgroundRepeatProperty, unsetValue],
|
|
||||||
[backgroundPositionProperty, unsetValue],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseBorderColor(value: string): { top: Color; right: Color; bottom: Color; left: Color } {
|
|
||||||
const result: { top: Color; right: Color; bottom: Color; left: Color } = {
|
|
||||||
top: undefined,
|
|
||||||
right: undefined,
|
|
||||||
bottom: undefined,
|
|
||||||
left: undefined,
|
|
||||||
};
|
|
||||||
if (value.indexOf('rgb') === 0 || value.indexOf('hsl') === 0) {
|
|
||||||
result.top = result.right = result.bottom = result.left = new Color(value);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const arr = value.split(/[ ,]+/);
|
|
||||||
if (arr.length === 1) {
|
|
||||||
const arr0 = new Color(arr[0]);
|
|
||||||
result.top = arr0;
|
|
||||||
result.right = arr0;
|
|
||||||
result.bottom = arr0;
|
|
||||||
result.left = arr0;
|
|
||||||
} else if (arr.length === 2) {
|
|
||||||
const arr0 = new Color(arr[0]);
|
|
||||||
const arr1 = new Color(arr[1]);
|
|
||||||
result.top = arr0;
|
|
||||||
result.right = arr1;
|
|
||||||
result.bottom = arr0;
|
|
||||||
result.left = arr1;
|
|
||||||
} else if (arr.length === 3) {
|
|
||||||
const arr0 = new Color(arr[0]);
|
|
||||||
const arr1 = new Color(arr[1]);
|
|
||||||
const arr2 = new Color(arr[2]);
|
|
||||||
result.top = arr0;
|
|
||||||
result.right = arr1;
|
|
||||||
result.bottom = arr2;
|
|
||||||
result.left = arr1;
|
|
||||||
} else if (arr.length === 4) {
|
|
||||||
const arr0 = new Color(arr[0]);
|
|
||||||
const arr1 = new Color(arr[1]);
|
|
||||||
const arr2 = new Color(arr[2]);
|
|
||||||
const arr3 = new Color(arr[3]);
|
|
||||||
result.top = arr0;
|
|
||||||
result.right = arr1;
|
|
||||||
result.bottom = arr2;
|
|
||||||
result.left = arr3;
|
|
||||||
} else {
|
|
||||||
throw new Error(`Expected 1, 2, 3 or 4 parameters. Actual: ${value}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Border Color properties.
|
// Border Color properties.
|
||||||
const borderColorProperty = new ShorthandProperty<Style, string | Color>({
|
const borderColorProperty = new ShorthandProperty<Style, string | Color>({
|
||||||
name: 'borderColor',
|
name: 'borderColor',
|
||||||
@ -932,13 +798,13 @@ const borderColorProperty = new ShorthandProperty<Style, string | Color>({
|
|||||||
},
|
},
|
||||||
converter: function (value) {
|
converter: function (value) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
const fourColors = parseBorderColor(value);
|
const colors = parseBorderColorPositioning(value);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[borderTopColorProperty, fourColors.top],
|
[borderTopColorProperty, new Color(colors.top)],
|
||||||
[borderRightColorProperty, fourColors.right],
|
[borderRightColorProperty, new Color(colors.right)],
|
||||||
[borderBottomColorProperty, fourColors.bottom],
|
[borderBottomColorProperty, new Color(colors.bottom)],
|
||||||
[borderLeftColorProperty, fourColors.left],
|
[borderLeftColorProperty, new Color(colors.left)],
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
return [
|
return [
|
||||||
@ -1009,13 +875,13 @@ const borderWidthProperty = new ShorthandProperty<Style, string | CoreTypes.Leng
|
|||||||
},
|
},
|
||||||
converter: function (value) {
|
converter: function (value) {
|
||||||
if (typeof value === 'string' && value !== 'auto') {
|
if (typeof value === 'string' && value !== 'auto') {
|
||||||
const borderWidths = parseThickness(value);
|
const borderWidths = parseShorthandPositioning(value);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[borderTopWidthProperty, borderWidths.top],
|
[borderTopWidthProperty, Length.parse(borderWidths.top)],
|
||||||
[borderRightWidthProperty, borderWidths.right],
|
[borderRightWidthProperty, Length.parse(borderWidths.right)],
|
||||||
[borderBottomWidthProperty, borderWidths.bottom],
|
[borderBottomWidthProperty, Length.parse(borderWidths.bottom)],
|
||||||
[borderLeftWidthProperty, borderWidths.left],
|
[borderLeftWidthProperty, Length.parse(borderWidths.left)],
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
return [
|
return [
|
||||||
@ -1138,13 +1004,13 @@ const borderRadiusProperty = new ShorthandProperty<Style, string | CoreTypes.Len
|
|||||||
},
|
},
|
||||||
converter: function (value) {
|
converter: function (value) {
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
const borderRadius = parseThickness(value);
|
const borderRadius = parseShorthandPositioning(value);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[borderTopLeftRadiusProperty, borderRadius.top],
|
[borderTopLeftRadiusProperty, Length.parse(borderRadius.top)],
|
||||||
[borderTopRightRadiusProperty, borderRadius.right],
|
[borderTopRightRadiusProperty, Length.parse(borderRadius.right)],
|
||||||
[borderBottomRightRadiusProperty, borderRadius.bottom],
|
[borderBottomRightRadiusProperty, Length.parse(borderRadius.bottom)],
|
||||||
[borderBottomLeftRadiusProperty, borderRadius.left],
|
[borderBottomLeftRadiusProperty, Length.parse(borderRadius.left)],
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
return [
|
return [
|
||||||
@ -1249,63 +1115,54 @@ const boxShadowProperty = new CssProperty<Style, ShadowCSSValues>({
|
|||||||
});
|
});
|
||||||
boxShadowProperty.register(Style);
|
boxShadowProperty.register(Style);
|
||||||
|
|
||||||
function isNonNegativeFiniteNumber(value: number): boolean {
|
export const clipPathProperty = new CssProperty<Style, string | ClipPathFunction>({
|
||||||
return isFinite(value) && !isNaN(value) && value >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const supportedPaths = ['rect', 'circle', 'ellipse', 'polygon', 'inset'];
|
|
||||||
function isClipPathValid(value: string): boolean {
|
|
||||||
if (!value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const functionName = value.substring(0, value.indexOf('(')).trim();
|
|
||||||
|
|
||||||
return supportedPaths.indexOf(functionName) !== -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const clipPathProperty = new CssProperty<Style, string>({
|
|
||||||
name: 'clipPath',
|
name: 'clipPath',
|
||||||
cssName: 'clip-path',
|
cssName: 'clip-path',
|
||||||
valueChanged: (target, oldValue, newValue) => {
|
valueChanged: (target, oldValue, newValue) => {
|
||||||
if (!isClipPathValid(newValue)) {
|
target.backgroundInternal = target.backgroundInternal.withClipPath(newValue);
|
||||||
throw new Error('clip-path is not valid.');
|
},
|
||||||
|
equalityComparer: (value1, value2) => {
|
||||||
|
if (value1 instanceof ClipPathFunction && value2 instanceof ClipPathFunction) {
|
||||||
|
return ClipPathFunction.equals(value1, value2);
|
||||||
|
}
|
||||||
|
return value1 === value2;
|
||||||
|
},
|
||||||
|
valueConverter(value: string | ClipPathFunction) {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return parseClipPath(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
target.backgroundInternal = target.backgroundInternal.withClipPath(newValue);
|
return value;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
clipPathProperty.register(Style);
|
clipPathProperty.register(Style);
|
||||||
|
|
||||||
function isFloatValueConverter(value: string): number {
|
export const zIndexProperty = new CssProperty<Style, number>({
|
||||||
|
name: 'zIndex',
|
||||||
|
cssName: 'z-index',
|
||||||
|
valueConverter: (value: string): number => {
|
||||||
const newValue = parseFloat(value);
|
const newValue = parseFloat(value);
|
||||||
if (isNaN(newValue)) {
|
if (isNaN(newValue)) {
|
||||||
throw new Error(`Invalid value: ${newValue}`);
|
throw new Error(`Invalid value: ${newValue}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
},
|
||||||
|
|
||||||
export const zIndexProperty = new CssProperty<Style, number>({
|
|
||||||
name: 'zIndex',
|
|
||||||
cssName: 'z-index',
|
|
||||||
valueConverter: isFloatValueConverter,
|
|
||||||
});
|
});
|
||||||
zIndexProperty.register(Style);
|
zIndexProperty.register(Style);
|
||||||
|
|
||||||
function opacityConverter(value: any): number {
|
|
||||||
const newValue = parseFloat(value);
|
|
||||||
if (!isNaN(newValue) && 0 <= newValue && newValue <= 1) {
|
|
||||||
return newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`Opacity should be between [0, 1]. Value: ${newValue}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const opacityProperty = new CssAnimationProperty<Style, number>({
|
export const opacityProperty = new CssAnimationProperty<Style, number>({
|
||||||
name: 'opacity',
|
name: 'opacity',
|
||||||
cssName: 'opacity',
|
cssName: 'opacity',
|
||||||
defaultValue: 1,
|
defaultValue: 1,
|
||||||
valueConverter: opacityConverter,
|
valueConverter: (value: string): number => {
|
||||||
|
const newValue = parseFloat(value);
|
||||||
|
if (!isNonNegativeFiniteNumber(newValue) || newValue > 1) {
|
||||||
|
throw new Error(`Opacity should be between [0, 1]. Value: ${newValue}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newValue;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
opacityProperty.register(Style);
|
opacityProperty.register(Style);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import { CoreTypes } from '../../../core-types';
|
|||||||
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState } from '../../../accessibility/accessibility-types';
|
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState } from '../../../accessibility/accessibility-types';
|
||||||
import { ShadowCSSValues } from '../css-shadow';
|
import { ShadowCSSValues } from '../css-shadow';
|
||||||
import { StrokeCSSValues } from '../css-stroke';
|
import { StrokeCSSValues } from '../css-stroke';
|
||||||
|
import { ClipPathFunction } from '../clip-path-function';
|
||||||
|
|
||||||
export interface CommonLayoutParams {
|
export interface CommonLayoutParams {
|
||||||
width: number;
|
width: number;
|
||||||
@ -122,7 +123,7 @@ export class Style extends Observable implements StyleDefinition {
|
|||||||
public translateX: CoreTypes.dip;
|
public translateX: CoreTypes.dip;
|
||||||
public translateY: CoreTypes.dip;
|
public translateY: CoreTypes.dip;
|
||||||
|
|
||||||
public clipPath: string;
|
public clipPath: string | ClipPathFunction;
|
||||||
public color: Color;
|
public color: Color;
|
||||||
public tintColor: Color;
|
public tintColor: Color;
|
||||||
public placeholderColor: Color;
|
public placeholderColor: Color;
|
||||||
|
Reference in New Issue
Block a user