UNPKG

@nativescript/core

Version:

A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.

1,218 lines • 45.4 kB
import { unsetValue, CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty, isCssWideKeyword } from '../core/properties'; import { Style } from './style'; import { Color } from '../../color'; import { Font, parseFont, FontStyle, FontWeight, FontVariationSettings } from './font'; import { Background } from './background'; import { layout } from '../../utils'; import { Trace } from '../../trace'; import { CoreTypes } from '../../core-types'; import { parseBackground } from '../../css/parser'; import { LinearGradient } from './linear-gradient'; import { parseCSSShadow } from './css-shadow'; import { transformConverter } from './css-transform'; import { ClipPathFunction } from './clip-path-function'; function equalsCommon(a, b) { if (a == 'auto' || isCssWideKeyword(a)) { return b == 'auto' || isCssWideKeyword(b); } if (b == 'auto' || isCssWideKeyword(b)) { return false; } if (typeof a === 'number') { if (typeof b === 'number') { return a == b; } if (!b) { return false; } return b.unit == 'dip' && a == b.value; } if (typeof b === 'number') { return a ? a.unit == 'dip' && a.value == b : false; } if (!a || !b) { return false; } return a.value == b.value && a.unit == b.unit; } function convertToStringCommon(length) { if (length == 'auto' || isCssWideKeyword(length)) { return 'auto'; } if (typeof length === 'number') { return length.toString(); } let val = length.value; if (length.unit === '%') { val *= 100; } return val + length.unit; } function toDevicePixelsCommon(length, auto = Number.NaN, parentAvailableWidth = Number.NaN) { if (length == 'auto' || isCssWideKeyword(length)) { return auto; } if (typeof length === 'number') { return layout.round(layout.toDevicePixels(length)); } if (!length) { return auto; } switch (length.unit) { case 'px': return layout.round(length.value); case '%': return layout.round(parentAvailableWidth * length.value); case 'dip': default: return layout.round(layout.toDevicePixels(length.value)); } } export var PercentLength; (function (PercentLength) { function parse(fromValue) { if (fromValue == 'auto') { return 'auto'; } if (typeof fromValue === 'string') { let stringValue = fromValue.trim(); const percentIndex = stringValue.indexOf('%'); if (percentIndex !== -1) { let value; // if only % or % is not last we treat it as invalid value. if (percentIndex !== stringValue.length - 1 || percentIndex === 0) { value = Number.NaN; } else { // Normalize result to values between -1 and 1 value = parseFloat(stringValue.substring(0, stringValue.length - 1).trim()) / 100; } if (isNaN(value) || !isFinite(value)) { throw new Error(`Invalid value: ${fromValue}`); } return { unit: '%', value }; } else if (stringValue.indexOf('px') !== -1) { stringValue = stringValue.replace('px', '').trim(); const value = parseFloat(stringValue); if (isNaN(value) || !isFinite(value)) { throw new Error(`Invalid value: ${fromValue}`); } return { unit: 'px', value }; } else { const value = parseFloat(stringValue); if (isNaN(value) || !isFinite(value)) { throw new Error(`Invalid value: ${fromValue}`); } return value; } } else { return fromValue; } } PercentLength.parse = parse; PercentLength.equals = equalsCommon; PercentLength.toDevicePixels = toDevicePixelsCommon; PercentLength.convertToString = convertToStringCommon; })(PercentLength || (PercentLength = {})); export var FixedLength; (function (FixedLength) { function parse(fromValue) { if (typeof fromValue === 'string') { let stringValue = fromValue.trim(); if (stringValue.indexOf('px') !== -1) { stringValue = stringValue.replace('px', '').trim(); const value = parseFloat(stringValue); if (isNaN(value) || !isFinite(value)) { throw new Error(`Invalid value: ${stringValue}`); } return { unit: 'px', value }; } else { const value = parseFloat(stringValue); if (isNaN(value) || !isFinite(value)) { throw new Error(`Invalid value: ${stringValue}`); } return value; } } else { return fromValue; } } FixedLength.parse = parse; FixedLength.equals = equalsCommon; FixedLength.toDevicePixels = toDevicePixelsCommon; FixedLength.convertToString = convertToStringCommon; })(FixedLength || (FixedLength = {})); export var Length; (function (Length) { function parse(fromValue) { if (fromValue == 'auto') { return 'auto'; } return FixedLength.parse(fromValue); } Length.parse = parse; Length.equals = equalsCommon; Length.toDevicePixels = toDevicePixelsCommon; Length.convertToString = convertToStringCommon; })(Length || (Length = {})); function isNonNegativeFiniteNumber(value) { return isFinite(value) && !isNaN(value) && value >= 0; } function parseClipPath(value) { 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 = 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) { const arr = value.split(/[ ,]+/); let top; let right; let bottom; let left; 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) { if (value.indexOf('rgb') === 0 || value.indexOf('hsl') === 0) { return { top: value, right: value, bottom: value, left: value, }; } return parseShorthandPositioning(value); } function convertToBackgrounds(value) { 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; 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) { 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) { 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) { 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({ name: 'minWidth', cssName: 'min-width', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const view = target.viewRef.get(); if (view) { view.effectiveMinWidth = Length.toDevicePixels(newValue, 0); } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } }, valueConverter: Length.parse, }); minWidthProperty.register(Style); export const minHeightProperty = new CssProperty({ name: 'minHeight', cssName: 'min-height', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const view = target.viewRef.get(); if (view) { view.effectiveMinHeight = Length.toDevicePixels(newValue, 0); } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } }, valueConverter: Length.parse, }); minHeightProperty.register(Style); export const widthProperty = new CssAnimationProperty({ name: 'width', cssName: 'width', defaultValue: 'auto', equalityComparer: Length.equals, // TODO: CSSAnimationProperty was needed for keyframe (copying other impls), but `affectsLayout` does not exist // on the animation property, so fake it here. x_x valueChanged: (target, oldValue, newValue) => { if (global.isIOS) { const view = target.viewRef.get(); if (view) { view.requestLayout(); } } }, valueConverter: PercentLength.parse, }); widthProperty.register(Style); export const heightProperty = new CssAnimationProperty({ name: 'height', cssName: 'height', defaultValue: 'auto', equalityComparer: Length.equals, // TODO: CSSAnimationProperty was needed for keyframe (copying other impls), but `affectsLayout` does not exist // on the animation property, so fake it here. -_- valueChanged: (target, oldValue, newValue) => { if (global.isIOS) { const view = target.viewRef.get(); if (view) { view.requestLayout(); } } }, valueConverter: PercentLength.parse, }); heightProperty.register(Style); const marginProperty = new ShorthandProperty({ name: 'margin', cssName: 'margin', getter: function () { if (PercentLength.equals(this.marginTop, this.marginRight) && PercentLength.equals(this.marginTop, this.marginBottom) && PercentLength.equals(this.marginTop, this.marginLeft)) { return this.marginTop; } return `${PercentLength.convertToString(this.marginTop)} ${PercentLength.convertToString(this.marginRight)} ${PercentLength.convertToString(this.marginBottom)} ${PercentLength.convertToString(this.marginLeft)}`; }, converter: convertToMargins, }); marginProperty.register(Style); export const marginLeftProperty = new CssProperty({ name: 'marginLeft', cssName: 'margin-left', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueConverter: PercentLength.parse, }); marginLeftProperty.register(Style); export const marginRightProperty = new CssProperty({ name: 'marginRight', cssName: 'margin-right', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueConverter: PercentLength.parse, }); marginRightProperty.register(Style); export const marginTopProperty = new CssProperty({ name: 'marginTop', cssName: 'margin-top', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueConverter: PercentLength.parse, }); marginTopProperty.register(Style); export const marginBottomProperty = new CssProperty({ name: 'marginBottom', cssName: 'margin-bottom', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueConverter: PercentLength.parse, }); marginBottomProperty.register(Style); const paddingProperty = new ShorthandProperty({ name: 'padding', cssName: 'padding', getter: function () { if (Length.equals(this.paddingTop, this.paddingRight) && Length.equals(this.paddingTop, this.paddingBottom) && Length.equals(this.paddingTop, this.paddingLeft)) { return this.paddingTop; } return `${Length.convertToString(this.paddingTop)} ${Length.convertToString(this.paddingRight)} ${Length.convertToString(this.paddingBottom)} ${Length.convertToString(this.paddingLeft)}`; }, converter: convertToPaddings, }); paddingProperty.register(Style); export const paddingLeftProperty = new CssProperty({ name: 'paddingLeft', cssName: 'padding-left', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const view = target.viewRef.get(); if (view) { view.effectivePaddingLeft = Length.toDevicePixels(newValue, 0); } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } }, valueConverter: Length.parse, }); paddingLeftProperty.register(Style); export const paddingRightProperty = new CssProperty({ name: 'paddingRight', cssName: 'padding-right', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const view = target.viewRef.get(); if (view) { view.effectivePaddingRight = Length.toDevicePixels(newValue, 0); } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } }, valueConverter: Length.parse, }); paddingRightProperty.register(Style); export const paddingTopProperty = new CssProperty({ name: 'paddingTop', cssName: 'padding-top', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const view = target.viewRef.get(); if (view) { view.effectivePaddingTop = Length.toDevicePixels(newValue, 0); } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } }, valueConverter: Length.parse, }); paddingTopProperty.register(Style); export const paddingBottomProperty = new CssProperty({ name: 'paddingBottom', cssName: 'padding-bottom', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const view = target.viewRef.get(); if (view) { view.effectivePaddingBottom = Length.toDevicePixels(newValue, 0); } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } }, valueConverter: Length.parse, }); paddingBottomProperty.register(Style); export const horizontalAlignmentProperty = new CssProperty({ name: 'horizontalAlignment', cssName: 'horizontal-align', defaultValue: CoreTypes.HorizontalAlignment.stretch, affectsLayout: global.isIOS, valueConverter: CoreTypes.HorizontalAlignment.parse, }); horizontalAlignmentProperty.register(Style); export const verticalAlignmentProperty = new CssProperty({ name: 'verticalAlignment', cssName: 'vertical-align', defaultValue: CoreTypes.VerticalAlignmentText.stretch, affectsLayout: global.isIOS, valueConverter: CoreTypes.VerticalAlignmentText.parse, }); verticalAlignmentProperty.register(Style); export const rotateProperty = new CssAnimationProperty({ name: 'rotate', cssName: 'rotate', defaultValue: 0, valueConverter: parseFloat, }); rotateProperty.register(Style); export const rotateXProperty = new CssAnimationProperty({ name: 'rotateX', cssName: 'rotatex', defaultValue: 0, valueConverter: parseFloat, }); rotateXProperty.register(Style); export const rotateYProperty = new CssAnimationProperty({ name: 'rotateY', cssName: 'rotatey', defaultValue: 0, valueConverter: parseFloat, }); rotateYProperty.register(Style); export const perspectiveProperty = new CssAnimationProperty({ name: 'perspective', cssName: 'perspective', defaultValue: 1000, valueConverter: parseFloat, }); perspectiveProperty.register(Style); export const scaleXProperty = new CssAnimationProperty({ name: 'scaleX', cssName: 'scaleX', defaultValue: 1, valueConverter: parseFloat, }); scaleXProperty.register(Style); export const scaleYProperty = new CssAnimationProperty({ name: 'scaleY', cssName: 'scaleY', defaultValue: 1, valueConverter: parseFloat, }); scaleYProperty.register(Style); export const translateXProperty = new CssAnimationProperty({ name: 'translateX', cssName: 'translateX', defaultValue: 0, equalityComparer: FixedLength.equals, valueConverter: FixedLength.parse, }); translateXProperty.register(Style); export const translateYProperty = new CssAnimationProperty({ name: 'translateY', cssName: 'translateY', defaultValue: 0, equalityComparer: FixedLength.equals, valueConverter: FixedLength.parse, }); translateYProperty.register(Style); const transformProperty = new ShorthandProperty({ name: 'transform', cssName: 'transform', getter: function () { const scaleX = this.scaleX; const scaleY = this.scaleY; const translateX = this.translateX; const translateY = this.translateY; const rotate = this.rotate; const rotateX = this.rotateX; const rotateY = this.rotateY; let result = ''; if (translateX !== 0 || translateY !== 0) { result += `translate(${translateX}, ${translateY}) `; } if (scaleX !== 1 || scaleY !== 1) { result += `scale(${scaleX}, ${scaleY}) `; } if (rotateX !== 0 || rotateY !== 0 || rotate !== 0) { result += `rotate(${rotateX}, ${rotateY}, ${rotate}) `; result += `rotate (${rotate})`; } return result.trim(); }, converter: convertToTransform, }); transformProperty.register(Style); // Background properties. const backgroundProperty = new ShorthandProperty({ name: 'background', cssName: 'background', getter: function () { return `${this.backgroundColor} ${this.backgroundImage} ${this.backgroundRepeat} ${this.backgroundPosition}`; }, converter: convertToBackgrounds, }); backgroundProperty.register(Style); export const backgroundInternalProperty = new CssProperty({ name: 'backgroundInternal', cssName: '_backgroundInternal', defaultValue: Background.default, }); backgroundInternalProperty.register(Style); export const backgroundImageProperty = new CssProperty({ name: 'backgroundImage', cssName: 'background-image', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withImage(newValue); }, equalityComparer: (value1, value2) => { if (value1 instanceof LinearGradient && value2 instanceof LinearGradient) { return LinearGradient.equals(value1, value2); } else { return value1 === value2; } }, valueConverter: (value) => { if (typeof value === 'string') { const parsed = parseBackground(value); if (parsed) { value = typeof parsed.value.image === 'object' ? LinearGradient.parse(parsed.value.image) : value; } } return value; }, }); backgroundImageProperty.register(Style); export const backgroundColorProperty = new CssAnimationProperty({ name: 'backgroundColor', cssName: 'background-color', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withColor(newValue); }, equalityComparer: Color.equals, valueConverter: (value) => new Color(value), }); backgroundColorProperty.register(Style); export const backgroundRepeatProperty = new CssProperty({ name: 'backgroundRepeat', cssName: 'background-repeat', valueConverter: CoreTypes.BackgroundRepeat.parse, valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withRepeat(newValue); }, }); backgroundRepeatProperty.register(Style); export const backgroundSizeProperty = new CssProperty({ name: 'backgroundSize', cssName: 'background-size', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withSize(newValue); }, }); backgroundSizeProperty.register(Style); export const backgroundPositionProperty = new CssProperty({ name: 'backgroundPosition', cssName: 'background-position', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withPosition(newValue); }, }); backgroundPositionProperty.register(Style); // Border Color properties. const borderColorProperty = new ShorthandProperty({ name: 'borderColor', cssName: 'border-color', getter: function () { if (Color.equals(this.borderTopColor, this.borderRightColor) && Color.equals(this.borderTopColor, this.borderBottomColor) && Color.equals(this.borderTopColor, this.borderLeftColor)) { return this.borderTopColor; } else { return `${this.borderTopColor} ${this.borderRightColor} ${this.borderBottomColor} ${this.borderLeftColor}`; } }, converter: function (value) { if (typeof value === 'string') { const colors = parseBorderColorPositioning(value); return [ [borderTopColorProperty, new Color(colors.top)], [borderRightColorProperty, new Color(colors.right)], [borderBottomColorProperty, new Color(colors.bottom)], [borderLeftColorProperty, new Color(colors.left)], ]; } else { return [ [borderTopColorProperty, value], [borderRightColorProperty, value], [borderBottomColorProperty, value], [borderLeftColorProperty, value], ]; } }, }); borderColorProperty.register(Style); export const borderTopColorProperty = new CssProperty({ name: 'borderTopColor', cssName: 'border-top-color', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withBorderTopColor(newValue); }, equalityComparer: Color.equals, valueConverter: (value) => new Color(value), }); borderTopColorProperty.register(Style); export const borderRightColorProperty = new CssProperty({ name: 'borderRightColor', cssName: 'border-right-color', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withBorderRightColor(newValue); }, equalityComparer: Color.equals, valueConverter: (value) => new Color(value), }); borderRightColorProperty.register(Style); export const borderBottomColorProperty = new CssProperty({ name: 'borderBottomColor', cssName: 'border-bottom-color', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withBorderBottomColor(newValue); }, equalityComparer: Color.equals, valueConverter: (value) => new Color(value), }); borderBottomColorProperty.register(Style); export const borderLeftColorProperty = new CssProperty({ name: 'borderLeftColor', cssName: 'border-left-color', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withBorderLeftColor(newValue); }, equalityComparer: Color.equals, valueConverter: (value) => new Color(value), }); borderLeftColorProperty.register(Style); // Border Width properties. const borderWidthProperty = new ShorthandProperty({ name: 'borderWidth', cssName: 'border-width', getter: function () { if (Length.equals(this.borderTopWidth, this.borderRightWidth) && Length.equals(this.borderTopWidth, this.borderBottomWidth) && Length.equals(this.borderTopWidth, this.borderLeftWidth)) { return this.borderTopWidth; } else { return `${Length.convertToString(this.borderTopWidth)} ${Length.convertToString(this.borderRightWidth)} ${Length.convertToString(this.borderBottomWidth)} ${Length.convertToString(this.borderLeftWidth)}`; } }, converter: function (value) { if (typeof value === 'string' && value !== 'auto') { const borderWidths = parseShorthandPositioning(value); return [ [borderTopWidthProperty, Length.parse(borderWidths.top)], [borderRightWidthProperty, Length.parse(borderWidths.right)], [borderBottomWidthProperty, Length.parse(borderWidths.bottom)], [borderLeftWidthProperty, Length.parse(borderWidths.left)], ]; } else { return [ [borderTopWidthProperty, value], [borderRightWidthProperty, value], [borderBottomWidthProperty, value], [borderLeftWidthProperty, value], ]; } }, }); borderWidthProperty.register(Style); export const borderTopWidthProperty = new CssProperty({ name: 'borderTopWidth', cssName: 'border-top-width', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const value = Length.toDevicePixels(newValue, 0); if (!isNonNegativeFiniteNumber(value)) { throw new Error(`border-top-width should be Non-Negative Finite number. Value: ${value}`); } const view = target.viewRef.get(); if (view) { view.effectiveBorderTopWidth = value; } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } target.backgroundInternal = target.backgroundInternal.withBorderTopWidth(value); }, valueConverter: Length.parse, }); borderTopWidthProperty.register(Style); export const borderRightWidthProperty = new CssProperty({ name: 'borderRightWidth', cssName: 'border-right-width', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const value = Length.toDevicePixels(newValue, 0); if (!isNonNegativeFiniteNumber(value)) { throw new Error(`border-right-width should be Non-Negative Finite number. Value: ${value}`); } const view = target.viewRef.get(); if (view) { view.effectiveBorderRightWidth = value; } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } target.backgroundInternal = target.backgroundInternal.withBorderRightWidth(value); }, valueConverter: Length.parse, }); borderRightWidthProperty.register(Style); export const borderBottomWidthProperty = new CssProperty({ name: 'borderBottomWidth', cssName: 'border-bottom-width', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const value = Length.toDevicePixels(newValue, 0); if (!isNonNegativeFiniteNumber(value)) { throw new Error(`border-bottom-width should be Non-Negative Finite number. Value: ${value}`); } const view = target.viewRef.get(); if (view) { view.effectiveBorderBottomWidth = value; } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } target.backgroundInternal = target.backgroundInternal.withBorderBottomWidth(value); }, valueConverter: Length.parse, }); borderBottomWidthProperty.register(Style); export const borderLeftWidthProperty = new CssProperty({ name: 'borderLeftWidth', cssName: 'border-left-width', defaultValue: CoreTypes.zeroLength, affectsLayout: global.isIOS, equalityComparer: Length.equals, valueChanged: (target, oldValue, newValue) => { const value = Length.toDevicePixels(newValue, 0); if (!isNonNegativeFiniteNumber(value)) { throw new Error(`border-left-width should be Non-Negative Finite number. Value: ${value}`); } const view = target.viewRef.get(); if (view) { view.effectiveBorderLeftWidth = value; } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } target.backgroundInternal = target.backgroundInternal.withBorderLeftWidth(value); }, valueConverter: Length.parse, }); borderLeftWidthProperty.register(Style); // Border Radius properties. const borderRadiusProperty = new ShorthandProperty({ name: 'borderRadius', cssName: 'border-radius', getter: function () { if (Length.equals(this.borderTopLeftRadius, this.borderTopRightRadius) && Length.equals(this.borderTopLeftRadius, this.borderBottomRightRadius) && Length.equals(this.borderTopLeftRadius, this.borderBottomLeftRadius)) { return this.borderTopLeftRadius; } return `${Length.convertToString(this.borderTopLeftRadius)} ${Length.convertToString(this.borderTopRightRadius)} ${Length.convertToString(this.borderBottomRightRadius)} ${Length.convertToString(this.borderBottomLeftRadius)}`; }, converter: function (value) { if (typeof value === 'string') { const borderRadius = parseShorthandPositioning(value); return [ [borderTopLeftRadiusProperty, Length.parse(borderRadius.top)], [borderTopRightRadiusProperty, Length.parse(borderRadius.right)], [borderBottomRightRadiusProperty, Length.parse(borderRadius.bottom)], [borderBottomLeftRadiusProperty, Length.parse(borderRadius.left)], ]; } else { return [ [borderTopLeftRadiusProperty, value], [borderTopRightRadiusProperty, value], [borderBottomRightRadiusProperty, value], [borderBottomLeftRadiusProperty, value], ]; } }, }); borderRadiusProperty.register(Style); export const borderTopLeftRadiusProperty = new CssProperty({ name: 'borderTopLeftRadius', cssName: 'border-top-left-radius', defaultValue: 0, affectsLayout: global.isIOS, valueChanged: (target, oldValue, newValue) => { const value = Length.toDevicePixels(newValue, 0); if (!isNonNegativeFiniteNumber(value)) { throw new Error(`border-top-left-radius should be Non-Negative Finite number. Value: ${value}`); } target.backgroundInternal = target.backgroundInternal.withBorderTopLeftRadius(value); }, valueConverter: Length.parse, equalityComparer: Length.equals, }); borderTopLeftRadiusProperty.register(Style); export const borderTopRightRadiusProperty = new CssProperty({ name: 'borderTopRightRadius', cssName: 'border-top-right-radius', defaultValue: 0, affectsLayout: global.isIOS, valueChanged: (target, oldValue, newValue) => { const value = Length.toDevicePixels(newValue, 0); if (!isNonNegativeFiniteNumber(value)) { throw new Error(`border-top-right-radius should be Non-Negative Finite number. Value: ${value}`); } target.backgroundInternal = target.backgroundInternal.withBorderTopRightRadius(value); }, valueConverter: Length.parse, equalityComparer: Length.equals, }); borderTopRightRadiusProperty.register(Style); export const borderBottomRightRadiusProperty = new CssProperty({ name: 'borderBottomRightRadius', cssName: 'border-bottom-right-radius', defaultValue: 0, affectsLayout: global.isIOS, valueChanged: (target, oldValue, newValue) => { const value = Length.toDevicePixels(newValue, 0); if (!isNonNegativeFiniteNumber(value)) { throw new Error(`border-bottom-right-radius should be Non-Negative Finite number. Value: ${value}`); } target.backgroundInternal = target.backgroundInternal.withBorderBottomRightRadius(value); }, valueConverter: Length.parse, equalityComparer: Length.equals, }); borderBottomRightRadiusProperty.register(Style); export const borderBottomLeftRadiusProperty = new CssProperty({ name: 'borderBottomLeftRadius', cssName: 'border-bottom-left-radius', defaultValue: 0, affectsLayout: global.isIOS, valueChanged: (target, oldValue, newValue) => { const value = Length.toDevicePixels(newValue, 0); if (!isNonNegativeFiniteNumber(value)) { throw new Error(`border-bottom-left-radius should be Non-Negative Finite number. Value: ${value}`); } target.backgroundInternal = target.backgroundInternal.withBorderBottomLeftRadius(value); }, valueConverter: Length.parse, equalityComparer: Length.equals, }); borderBottomLeftRadiusProperty.register(Style); const boxShadowProperty = new CssProperty({ name: 'boxShadow', cssName: 'box-shadow', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withBoxShadow(newValue ? { inset: newValue.inset, offsetX: Length.toDevicePixels(newValue.offsetX, 0), offsetY: Length.toDevicePixels(newValue.offsetY, 0), blurRadius: Length.toDevicePixels(newValue.blurRadius, 0), spreadRadius: Length.toDevicePixels(newValue.spreadRadius, 0), color: newValue.color, } : null); }, valueConverter: (value) => { return parseCSSShadow(value); }, }); boxShadowProperty.register(Style); export const clipPathProperty = new CssProperty({ name: 'clipPath', cssName: 'clip-path', valueChanged: (target, oldValue, newValue) => { target.backgroundInternal = target.backgroundInternal.withClipPath(newValue); }, equalityComparer: (value1, value2) => { if (value1 instanceof ClipPathFunction && value2 instanceof ClipPathFunction) { return ClipPathFunction.equals(value1, value2); } return value1 === value2; }, valueConverter(value) { if (typeof value === 'string') { return parseClipPath(value); } return value; }, }); clipPathProperty.register(Style); export const zIndexProperty = new CssProperty({ name: 'zIndex', cssName: 'z-index', valueConverter: (value) => { const newValue = parseFloat(value); if (isNaN(newValue)) { throw new Error(`Invalid value: ${newValue}`); } return newValue; }, }); zIndexProperty.register(Style); export const opacityProperty = new CssAnimationProperty({ name: 'opacity', cssName: 'opacity', defaultValue: 1, valueConverter: (value) => { 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); export const colorProperty = new InheritedCssProperty({ name: 'color', cssName: 'color', equalityComparer: Color.equals, valueConverter: (v) => new Color(v), }); colorProperty.register(Style); export const fontInternalProperty = new CssProperty({ name: 'fontInternal', cssName: '_fontInternal', }); fontInternalProperty.register(Style); export const fontFamilyProperty = new InheritedCssProperty({ name: 'fontFamily', cssName: 'font-family', affectsLayout: global.isIOS, valueChanged: (target, oldValue, newValue) => { const currentFont = target.fontInternal || Font.default; if (currentFont.fontFamily !== newValue) { const newFont = currentFont.withFontFamily(newValue); target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont; } }, }); fontFamilyProperty.register(Style); export const fontScaleInternalProperty = new InheritedCssProperty({ name: 'fontScaleInternal', cssName: '_fontScaleInternal', defaultValue: 1.0, valueConverter: (v) => parseFloat(v), }); fontScaleInternalProperty.register(Style); export const fontSizeProperty = new InheritedCssProperty({ name: 'fontSize', cssName: 'font-size', affectsLayout: global.isIOS, valueChanged: (target, oldValue, newValue) => { if (target.viewRef['handleFontSize'] === true) { return; } const currentFont = target.fontInternal || Font.default; if (currentFont.fontSize !== newValue) { const newFont = currentFont.withFontSize(newValue); target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont; } }, valueConverter: (v) => parseFloat(v), }); fontSizeProperty.register(Style); export const fontStyleProperty = new InheritedCssProperty({ name: 'fontStyle', cssName: 'font-style', affectsLayout: global.isIOS, defaultValue: FontStyle.NORMAL, valueConverter: FontStyle.parse, valueChanged: (target, oldValue, newValue) => { const currentFont = target.fontInternal || Font.default; if (currentFont.fontStyle !== newValue) { const newFont = currentFont.withFontStyle(newValue); target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont; } }, }); fontStyleProperty.register(Style); export const fontWeightProperty = new InheritedCssProperty({ name: 'fontWeight', cssName: 'font-weight', affectsLayout: global.isIOS, defaultValue: FontWeight.NORMAL, valueConverter: FontWeight.parse, valueChanged: (target, oldValue, newValue) => { const currentFont = target.fontInternal || Font.default; if (currentFont.fontWeight !== newValue) { const newFont = currentFont.withFontWeight(newValue); target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont; } }, }); fontWeightProperty.register(Style); const fontProperty = new ShorthandProperty({ name: 'font', cssName: 'font', getter: function () { return `${this.fontStyle} ${this.fontWeight} ${this.fontSize} ${this.fontFamily}`; }, converter: function (value) { if (value === unsetValue) { return [ [fontStyleProperty, unsetValue], [fontWeightProperty, unsetValue], [fontSizeProperty, unsetValue], [fontFamilyProperty, unsetValue], ]; } else { const font = parseFont(value); const fontSize = parseFloat(font.fontSize); return [ [fontStyleProperty, font.fontStyle], [fontWeightProperty, font.fontWeight], [fontSizeProperty, fontSize], [fontFamilyProperty, font.fontFamily], ]; } }, }); fontProperty.register(Style); export const fontVariationSettingsProperty = new InheritedCssProperty({ name: 'fontVariationSettings', cssName: 'font-variation-settings', affectsLayout: global.isIOS, valueChanged: (target, oldValue, newValue) => { const currentFont = target.fontInternal || Font.default; if (currentFont.fontVariationSettings !== newValue) { const newFont = currentFont.withFontVariationSettings(newValue); target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont; } }, valueConverter: (value) => { return FontVariationSettings.parse(value); }, }); fontVariationSettingsProperty.register(Style); export const visibilityProperty = new CssProperty({ name: 'visibility', cssName: 'visibility', defaultValue: CoreTypes.Visibility.visible, affectsLayout: global.isIOS, valueConverter: CoreTypes.Visibility.parse, valueChanged: (target, oldValue, newValue) => { const view = target.viewRef.get(); if (view) { view.isCollapsed = newValue === CoreTypes.Visibility.collapse; } else { Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn); } }, }); visibilityProperty.register(Style); export const androidElevationProperty = new CssProperty({ name: 'androidElevation', cssName: 'android-elevation', valueConverter: parseFloat, }); androidElevationProperty.register(Style); export const androidDynamicElevationOffsetProperty = new CssProperty({ name: 'androidDynamicElevationOffset', cssName: 'android-dynamic-elevation-offset', valueConverter: parseFloat, }); androidDynamicElevationOffsetProperty.register(Style); //# sourceMappingURL=style-properties.js.map