UNPKG

49.8 kBJavaScriptView Raw
1// Types
2import { unsetValue, CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty } from '../core/properties';
3import { Style } from './style';
4import { Color } from '../../color';
5import { Font, parseFont, FontStyle, FontWeight, FontVariationSettings } from './font';
6import { Background } from './background';
7import { layout, hasDuplicates } from '../../utils';
8import { radiansToDegrees } from '../../utils/number-utils';
9import { decompose2DTransformMatrix, getTransformMatrix, matrixArrayToCssMatrix, multiplyAffine2d } from '../../matrix';
10import { Trace } from '../../trace';
11import { CoreTypes } from '../../core-types';
12import { parseBackground } from '../../css/parser';
13import { LinearGradient } from './linear-gradient';
14import { parseCSSShadow } from './css-shadow';
15function equalsCommon(a, b) {
16 if (a == 'auto') {
17 // tslint:disable-line
18 return b == 'auto'; // tslint:disable-line
19 }
20 if (typeof a === 'number') {
21 if (b == 'auto') {
22 // tslint:disable-line
23 return false;
24 }
25 if (typeof b === 'number') {
26 return a == b; // tslint:disable-line
27 }
28 if (!b) {
29 return false;
30 }
31 return b.unit == 'dip' && a == b.value; // tslint:disable-line
32 }
33 if (b == 'auto') {
34 // tslint:disable-line
35 return false;
36 }
37 if (typeof b === 'number') {
38 return a ? a.unit == 'dip' && a.value == b : false; // tslint:disable-line
39 }
40 if (!a || !b) {
41 return false;
42 }
43 return a.value == b.value && a.unit == b.unit; // tslint:disable-line
44}
45function convertToStringCommon(length) {
46 if (length == 'auto') {
47 // tslint:disable-line
48 return 'auto';
49 }
50 if (typeof length === 'number') {
51 return length.toString();
52 }
53 let val = length.value;
54 if (length.unit === '%') {
55 val *= 100;
56 }
57 return val + length.unit;
58}
59function toDevicePixelsCommon(length, auto = Number.NaN, parentAvailableWidth = Number.NaN) {
60 if (length == 'auto') {
61 // tslint:disable-line
62 return auto;
63 }
64 if (typeof length === 'number') {
65 return layout.round(layout.toDevicePixels(length));
66 }
67 if (!length) {
68 return auto;
69 }
70 switch (length.unit) {
71 case 'px':
72 return layout.round(length.value);
73 case '%':
74 return layout.round(parentAvailableWidth * length.value);
75 case 'dip':
76 default:
77 return layout.round(layout.toDevicePixels(length.value));
78 }
79}
80export var PercentLength;
81(function (PercentLength) {
82 function parse(fromValue) {
83 if (fromValue == 'auto') {
84 // tslint:disable-line
85 return 'auto';
86 }
87 if (typeof fromValue === 'string') {
88 let stringValue = fromValue.trim();
89 const percentIndex = stringValue.indexOf('%');
90 if (percentIndex !== -1) {
91 let value;
92 // if only % or % is not last we treat it as invalid value.
93 if (percentIndex !== stringValue.length - 1 || percentIndex === 0) {
94 value = Number.NaN;
95 }
96 else {
97 // Normalize result to values between -1 and 1
98 value = parseFloat(stringValue.substring(0, stringValue.length - 1).trim()) / 100;
99 }
100 if (isNaN(value) || !isFinite(value)) {
101 throw new Error(`Invalid value: ${fromValue}`);
102 }
103 return { unit: '%', value };
104 }
105 else if (stringValue.indexOf('px') !== -1) {
106 stringValue = stringValue.replace('px', '').trim();
107 const value = parseFloat(stringValue);
108 if (isNaN(value) || !isFinite(value)) {
109 throw new Error(`Invalid value: ${fromValue}`);
110 }
111 return { unit: 'px', value };
112 }
113 else {
114 const value = parseFloat(stringValue);
115 if (isNaN(value) || !isFinite(value)) {
116 throw new Error(`Invalid value: ${fromValue}`);
117 }
118 return value;
119 }
120 }
121 else {
122 return fromValue;
123 }
124 }
125 PercentLength.parse = parse;
126 PercentLength.equals = equalsCommon;
127 PercentLength.toDevicePixels = toDevicePixelsCommon;
128 PercentLength.convertToString = convertToStringCommon;
129})(PercentLength || (PercentLength = {}));
130export var Length;
131(function (Length) {
132 function parse(fromValue) {
133 if (fromValue == 'auto') {
134 // tslint:disable-line
135 return 'auto';
136 }
137 if (typeof fromValue === 'string') {
138 let stringValue = fromValue.trim();
139 if (stringValue.indexOf('px') !== -1) {
140 stringValue = stringValue.replace('px', '').trim();
141 const value = parseFloat(stringValue);
142 if (isNaN(value) || !isFinite(value)) {
143 throw new Error(`Invalid value: ${stringValue}`);
144 }
145 return { unit: 'px', value };
146 }
147 else {
148 const value = parseFloat(stringValue);
149 if (isNaN(value) || !isFinite(value)) {
150 throw new Error(`Invalid value: ${stringValue}`);
151 }
152 return value;
153 }
154 }
155 else {
156 return fromValue;
157 }
158 }
159 Length.parse = parse;
160 Length.equals = equalsCommon;
161 Length.toDevicePixels = toDevicePixelsCommon;
162 Length.convertToString = convertToStringCommon;
163})(Length || (Length = {}));
164export const minWidthProperty = new CssProperty({
165 name: 'minWidth',
166 cssName: 'min-width',
167 defaultValue: CoreTypes.zeroLength,
168 affectsLayout: global.isIOS,
169 equalityComparer: Length.equals,
170 valueChanged: (target, oldValue, newValue) => {
171 const view = target.viewRef.get();
172 if (view) {
173 view.effectiveMinWidth = Length.toDevicePixels(newValue, 0);
174 }
175 else {
176 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
177 }
178 },
179 valueConverter: Length.parse,
180});
181minWidthProperty.register(Style);
182export const minHeightProperty = new CssProperty({
183 name: 'minHeight',
184 cssName: 'min-height',
185 defaultValue: CoreTypes.zeroLength,
186 affectsLayout: global.isIOS,
187 equalityComparer: Length.equals,
188 valueChanged: (target, oldValue, newValue) => {
189 const view = target.viewRef.get();
190 if (view) {
191 view.effectiveMinHeight = Length.toDevicePixels(newValue, 0);
192 }
193 else {
194 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
195 }
196 },
197 valueConverter: Length.parse,
198});
199minHeightProperty.register(Style);
200export const widthProperty = new CssAnimationProperty({
201 name: 'width',
202 cssName: 'width',
203 defaultValue: 'auto',
204 equalityComparer: Length.equals,
205 // TODO: CSSAnimationProperty was needed for keyframe (copying other impls), but `affectsLayout` does not exist
206 // on the animation property, so fake it here. x_x
207 valueChanged: (target, oldValue, newValue) => {
208 if (global.isIOS) {
209 const view = target.viewRef.get();
210 if (view) {
211 view.requestLayout();
212 }
213 }
214 },
215 valueConverter: PercentLength.parse,
216});
217widthProperty.register(Style);
218export const heightProperty = new CssAnimationProperty({
219 name: 'height',
220 cssName: 'height',
221 defaultValue: 'auto',
222 equalityComparer: Length.equals,
223 // TODO: CSSAnimationProperty was needed for keyframe (copying other impls), but `affectsLayout` does not exist
224 // on the animation property, so fake it here. -_-
225 valueChanged: (target, oldValue, newValue) => {
226 if (global.isIOS) {
227 const view = target.viewRef.get();
228 if (view) {
229 view.requestLayout();
230 }
231 }
232 },
233 valueConverter: PercentLength.parse,
234});
235heightProperty.register(Style);
236const marginProperty = new ShorthandProperty({
237 name: 'margin',
238 cssName: 'margin',
239 getter: function () {
240 if (PercentLength.equals(this.marginTop, this.marginRight) && PercentLength.equals(this.marginTop, this.marginBottom) && PercentLength.equals(this.marginTop, this.marginLeft)) {
241 return this.marginTop;
242 }
243 return `${PercentLength.convertToString(this.marginTop)} ${PercentLength.convertToString(this.marginRight)} ${PercentLength.convertToString(this.marginBottom)} ${PercentLength.convertToString(this.marginLeft)}`;
244 },
245 converter: convertToMargins,
246});
247marginProperty.register(Style);
248export const marginLeftProperty = new CssProperty({
249 name: 'marginLeft',
250 cssName: 'margin-left',
251 defaultValue: CoreTypes.zeroLength,
252 affectsLayout: global.isIOS,
253 equalityComparer: Length.equals,
254 valueConverter: PercentLength.parse,
255});
256marginLeftProperty.register(Style);
257export const marginRightProperty = new CssProperty({
258 name: 'marginRight',
259 cssName: 'margin-right',
260 defaultValue: CoreTypes.zeroLength,
261 affectsLayout: global.isIOS,
262 equalityComparer: Length.equals,
263 valueConverter: PercentLength.parse,
264});
265marginRightProperty.register(Style);
266export const marginTopProperty = new CssProperty({
267 name: 'marginTop',
268 cssName: 'margin-top',
269 defaultValue: CoreTypes.zeroLength,
270 affectsLayout: global.isIOS,
271 equalityComparer: Length.equals,
272 valueConverter: PercentLength.parse,
273});
274marginTopProperty.register(Style);
275export const marginBottomProperty = new CssProperty({
276 name: 'marginBottom',
277 cssName: 'margin-bottom',
278 defaultValue: CoreTypes.zeroLength,
279 affectsLayout: global.isIOS,
280 equalityComparer: Length.equals,
281 valueConverter: PercentLength.parse,
282});
283marginBottomProperty.register(Style);
284const paddingProperty = new ShorthandProperty({
285 name: 'padding',
286 cssName: 'padding',
287 getter: function () {
288 if (Length.equals(this.paddingTop, this.paddingRight) && Length.equals(this.paddingTop, this.paddingBottom) && Length.equals(this.paddingTop, this.paddingLeft)) {
289 return this.paddingTop;
290 }
291 return `${Length.convertToString(this.paddingTop)} ${Length.convertToString(this.paddingRight)} ${Length.convertToString(this.paddingBottom)} ${Length.convertToString(this.paddingLeft)}`;
292 },
293 converter: convertToPaddings,
294});
295paddingProperty.register(Style);
296export const paddingLeftProperty = new CssProperty({
297 name: 'paddingLeft',
298 cssName: 'padding-left',
299 defaultValue: CoreTypes.zeroLength,
300 affectsLayout: global.isIOS,
301 equalityComparer: Length.equals,
302 valueChanged: (target, oldValue, newValue) => {
303 const view = target.viewRef.get();
304 if (view) {
305 view.effectivePaddingLeft = Length.toDevicePixels(newValue, 0);
306 }
307 else {
308 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
309 }
310 },
311 valueConverter: Length.parse,
312});
313paddingLeftProperty.register(Style);
314export const paddingRightProperty = new CssProperty({
315 name: 'paddingRight',
316 cssName: 'padding-right',
317 defaultValue: CoreTypes.zeroLength,
318 affectsLayout: global.isIOS,
319 equalityComparer: Length.equals,
320 valueChanged: (target, oldValue, newValue) => {
321 const view = target.viewRef.get();
322 if (view) {
323 view.effectivePaddingRight = Length.toDevicePixels(newValue, 0);
324 }
325 else {
326 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
327 }
328 },
329 valueConverter: Length.parse,
330});
331paddingRightProperty.register(Style);
332export const paddingTopProperty = new CssProperty({
333 name: 'paddingTop',
334 cssName: 'padding-top',
335 defaultValue: CoreTypes.zeroLength,
336 affectsLayout: global.isIOS,
337 equalityComparer: Length.equals,
338 valueChanged: (target, oldValue, newValue) => {
339 const view = target.viewRef.get();
340 if (view) {
341 view.effectivePaddingTop = Length.toDevicePixels(newValue, 0);
342 }
343 else {
344 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
345 }
346 },
347 valueConverter: Length.parse,
348});
349paddingTopProperty.register(Style);
350export const paddingBottomProperty = new CssProperty({
351 name: 'paddingBottom',
352 cssName: 'padding-bottom',
353 defaultValue: CoreTypes.zeroLength,
354 affectsLayout: global.isIOS,
355 equalityComparer: Length.equals,
356 valueChanged: (target, oldValue, newValue) => {
357 const view = target.viewRef.get();
358 if (view) {
359 view.effectivePaddingBottom = Length.toDevicePixels(newValue, 0);
360 }
361 else {
362 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
363 }
364 },
365 valueConverter: Length.parse,
366});
367paddingBottomProperty.register(Style);
368export const horizontalAlignmentProperty = new CssProperty({
369 name: 'horizontalAlignment',
370 cssName: 'horizontal-align',
371 defaultValue: CoreTypes.HorizontalAlignment.stretch,
372 affectsLayout: global.isIOS,
373 valueConverter: CoreTypes.HorizontalAlignment.parse,
374});
375horizontalAlignmentProperty.register(Style);
376export const verticalAlignmentProperty = new CssProperty({
377 name: 'verticalAlignment',
378 cssName: 'vertical-align',
379 defaultValue: CoreTypes.VerticalAlignmentText.stretch,
380 affectsLayout: global.isIOS,
381 valueConverter: CoreTypes.VerticalAlignmentText.parse,
382});
383verticalAlignmentProperty.register(Style);
384function parseThickness(value) {
385 if (typeof value === 'string') {
386 const arr = value.split(/[ ,]+/);
387 let top;
388 let right;
389 let bottom;
390 let left;
391 if (arr.length === 1) {
392 top = arr[0];
393 right = arr[0];
394 bottom = arr[0];
395 left = arr[0];
396 }
397 else if (arr.length === 2) {
398 top = arr[0];
399 bottom = arr[0];
400 right = arr[1];
401 left = arr[1];
402 }
403 else if (arr.length === 3) {
404 top = arr[0];
405 right = arr[1];
406 left = arr[1];
407 bottom = arr[2];
408 }
409 else if (arr.length === 4) {
410 top = arr[0];
411 right = arr[1];
412 bottom = arr[2];
413 left = arr[3];
414 }
415 else {
416 throw new Error('Expected 1, 2, 3 or 4 parameters. Actual: ' + value);
417 }
418 return {
419 top: top,
420 right: right,
421 bottom: bottom,
422 left: left,
423 };
424 }
425 else {
426 return value;
427 }
428}
429function convertToMargins(value) {
430 if (typeof value === 'string' && value !== 'auto') {
431 const thickness = parseThickness(value);
432 return [
433 [marginTopProperty, PercentLength.parse(thickness.top)],
434 [marginRightProperty, PercentLength.parse(thickness.right)],
435 [marginBottomProperty, PercentLength.parse(thickness.bottom)],
436 [marginLeftProperty, PercentLength.parse(thickness.left)],
437 ];
438 }
439 else {
440 return [
441 [marginTopProperty, value],
442 [marginRightProperty, value],
443 [marginBottomProperty, value],
444 [marginLeftProperty, value],
445 ];
446 }
447}
448function convertToPaddings(value) {
449 if (typeof value === 'string' && value !== 'auto') {
450 const thickness = parseThickness(value);
451 return [
452 [paddingTopProperty, Length.parse(thickness.top)],
453 [paddingRightProperty, Length.parse(thickness.right)],
454 [paddingBottomProperty, Length.parse(thickness.bottom)],
455 [paddingLeftProperty, Length.parse(thickness.left)],
456 ];
457 }
458 else {
459 return [
460 [paddingTopProperty, value],
461 [paddingRightProperty, value],
462 [paddingBottomProperty, value],
463 [paddingLeftProperty, value],
464 ];
465 }
466}
467export const rotateProperty = new CssAnimationProperty({
468 name: 'rotate',
469 cssName: 'rotate',
470 defaultValue: 0,
471 valueConverter: parseFloat,
472});
473rotateProperty.register(Style);
474export const rotateXProperty = new CssAnimationProperty({
475 name: 'rotateX',
476 cssName: 'rotatex',
477 defaultValue: 0,
478 valueConverter: parseFloat,
479});
480rotateXProperty.register(Style);
481export const rotateYProperty = new CssAnimationProperty({
482 name: 'rotateY',
483 cssName: 'rotatey',
484 defaultValue: 0,
485 valueConverter: parseFloat,
486});
487rotateYProperty.register(Style);
488export const perspectiveProperty = new CssAnimationProperty({
489 name: 'perspective',
490 cssName: 'perspective',
491 defaultValue: 1000,
492 valueConverter: parseFloat,
493});
494perspectiveProperty.register(Style);
495export const scaleXProperty = new CssAnimationProperty({
496 name: 'scaleX',
497 cssName: 'scaleX',
498 defaultValue: 1,
499 valueConverter: parseFloat,
500});
501scaleXProperty.register(Style);
502export const scaleYProperty = new CssAnimationProperty({
503 name: 'scaleY',
504 cssName: 'scaleY',
505 defaultValue: 1,
506 valueConverter: parseFloat,
507});
508scaleYProperty.register(Style);
509function parseDIPs(value) {
510 if (value.indexOf('px') !== -1) {
511 return layout.toDeviceIndependentPixels(parseFloat(value.replace('px', '').trim()));
512 }
513 else {
514 return parseFloat(value.replace('dip', '').trim());
515 }
516}
517export const translateXProperty = new CssAnimationProperty({
518 name: 'translateX',
519 cssName: 'translateX',
520 defaultValue: 0,
521 valueConverter: parseDIPs,
522});
523translateXProperty.register(Style);
524export const translateYProperty = new CssAnimationProperty({
525 name: 'translateY',
526 cssName: 'translateY',
527 defaultValue: 0,
528 valueConverter: parseDIPs,
529});
530translateYProperty.register(Style);
531const transformProperty = new ShorthandProperty({
532 name: 'transform',
533 cssName: 'transform',
534 getter: function () {
535 const scaleX = this.scaleX;
536 const scaleY = this.scaleY;
537 const translateX = this.translateX;
538 const translateY = this.translateY;
539 const rotate = this.rotate;
540 const rotateX = this.rotateX;
541 const rotateY = this.rotateY;
542 let result = '';
543 if (translateX !== 0 || translateY !== 0) {
544 result += `translate(${translateX}, ${translateY}) `;
545 }
546 if (scaleX !== 1 || scaleY !== 1) {
547 result += `scale(${scaleX}, ${scaleY}) `;
548 }
549 if (rotateX !== 0 || rotateY !== 0 || rotate !== 0) {
550 result += `rotate(${rotateX}, ${rotateY}, ${rotate}) `;
551 result += `rotate (${rotate})`;
552 }
553 return result.trim();
554 },
555 converter: convertToTransform,
556});
557transformProperty.register(Style);
558const IDENTITY_TRANSFORMATION = {
559 translate: { x: 0, y: 0 },
560 rotate: { x: 0, y: 0, z: 0 },
561 scale: { x: 1, y: 1 },
562};
563const TRANSFORM_SPLITTER = new RegExp(/\s*(.+?)\((.*?)\)/g);
564const TRANSFORMATIONS = Object.freeze(['rotate', 'rotateX', 'rotateY', 'rotate3d', 'translate', 'translate3d', 'translateX', 'translateY', 'scale', 'scale3d', 'scaleX', 'scaleY']);
565const STYLE_TRANSFORMATION_MAP = Object.freeze({
566 scale: (value) => ({ property: 'scale', value }),
567 scale3d: (value) => ({ property: 'scale', value }),
568 scaleX: ({ x }) => ({
569 property: 'scale',
570 value: { x, y: IDENTITY_TRANSFORMATION.scale.y },
571 }),
572 scaleY: ({ y }) => ({
573 property: 'scale',
574 value: { y, x: IDENTITY_TRANSFORMATION.scale.x },
575 }),
576 translate: (value) => ({ property: 'translate', value }),
577 translate3d: (value) => ({ property: 'translate', value }),
578 translateX: ({ x }) => ({
579 property: 'translate',
580 value: { x, y: IDENTITY_TRANSFORMATION.translate.y },
581 }),
582 translateY: ({ y }) => ({
583 property: 'translate',
584 value: { y, x: IDENTITY_TRANSFORMATION.translate.x },
585 }),
586 rotate3d: (value) => ({ property: 'rotate', value }),
587 rotateX: (x) => ({
588 property: 'rotate',
589 value: {
590 x,
591 y: IDENTITY_TRANSFORMATION.rotate.y,
592 z: IDENTITY_TRANSFORMATION.rotate.z,
593 },
594 }),
595 rotateY: (y) => ({
596 property: 'rotate',
597 value: {
598 x: IDENTITY_TRANSFORMATION.rotate.x,
599 y,
600 z: IDENTITY_TRANSFORMATION.rotate.z,
601 },
602 }),
603 rotate: (z) => ({
604 property: 'rotate',
605 value: {
606 x: IDENTITY_TRANSFORMATION.rotate.x,
607 y: IDENTITY_TRANSFORMATION.rotate.y,
608 z,
609 },
610 }),
611});
612function convertToTransform(value) {
613 if (value === unsetValue) {
614 value = 'none';
615 }
616 const { translate, rotate, scale } = transformConverter(value);
617 return [
618 [translateXProperty, translate.x],
619 [translateYProperty, translate.y],
620 [scaleXProperty, scale.x],
621 [scaleYProperty, scale.y],
622 [rotateProperty, rotate.z],
623 [rotateXProperty, rotate.x],
624 [rotateYProperty, rotate.y],
625 ];
626}
627export function transformConverter(text) {
628 const transformations = parseTransformString(text);
629 if (text === 'none' || text === '' || !transformations.length) {
630 return IDENTITY_TRANSFORMATION;
631 }
632 const usedTransforms = transformations.map((t) => t.property);
633 if (!hasDuplicates(usedTransforms)) {
634 const fullTransformations = { ...IDENTITY_TRANSFORMATION };
635 transformations.forEach((transform) => {
636 fullTransformations[transform.property] = transform.value;
637 });
638 return fullTransformations;
639 }
640 const affineMatrix = transformations.map(getTransformMatrix).reduce(multiplyAffine2d);
641 const cssMatrix = matrixArrayToCssMatrix(affineMatrix);
642 return decompose2DTransformMatrix(cssMatrix);
643}
644// using general regex and manually checking the matched
645// properties is faster than using more specific regex
646// https://jsperf.com/cssparse
647function parseTransformString(text) {
648 const matches = [];
649 let match;
650 while ((match = TRANSFORM_SPLITTER.exec(text)) !== null) {
651 const property = match[1];
652 const value = convertTransformValue(property, match[2]);
653 if (TRANSFORMATIONS.indexOf(property) !== -1) {
654 matches.push(normalizeTransformation({ property, value }));
655 }
656 }
657 return matches;
658}
659function normalizeTransformation({ property, value }) {
660 return STYLE_TRANSFORMATION_MAP[property](value);
661}
662function convertTransformValue(property, stringValue) {
663 /* eslint-disable prefer-const */
664 let [x, y, z] = stringValue.split(',').map(parseFloat);
665 if (property === 'translate') {
666 y ?? (y = IDENTITY_TRANSFORMATION.translate.y);
667 }
668 else {
669 y ?? (y = x);
670 z ?? (z = y);
671 }
672 if (property === 'rotate' || property === 'rotateX' || property === 'rotateY') {
673 return stringValue.slice(-3) === 'rad' ? radiansToDegrees(x) : x;
674 }
675 return { x, y, z };
676}
677// Background properties.
678const backgroundProperty = new ShorthandProperty({
679 name: 'background',
680 cssName: 'background',
681 getter: function () {
682 return `${this.backgroundColor} ${this.backgroundImage} ${this.backgroundRepeat} ${this.backgroundPosition}`;
683 },
684 converter: convertToBackgrounds,
685});
686backgroundProperty.register(Style);
687export const backgroundInternalProperty = new CssProperty({
688 name: 'backgroundInternal',
689 cssName: '_backgroundInternal',
690 defaultValue: Background.default,
691});
692backgroundInternalProperty.register(Style);
693// const pattern: RegExp = /url\(('|")(.*?)\1\)/;
694export const backgroundImageProperty = new CssProperty({
695 name: 'backgroundImage',
696 cssName: 'background-image',
697 valueChanged: (target, oldValue, newValue) => {
698 target.backgroundInternal = target.backgroundInternal.withImage(newValue);
699 },
700 equalityComparer: (value1, value2) => {
701 if (value1 instanceof LinearGradient && value2 instanceof LinearGradient) {
702 return LinearGradient.equals(value1, value2);
703 }
704 else {
705 return value1 === value2;
706 }
707 },
708 valueConverter: (value) => {
709 if (typeof value === 'string') {
710 const parsed = parseBackground(value);
711 if (parsed) {
712 value = typeof parsed.value.image === 'object' ? LinearGradient.parse(parsed.value.image) : value;
713 }
714 }
715 return value;
716 },
717});
718backgroundImageProperty.register(Style);
719export const backgroundColorProperty = new CssAnimationProperty({
720 name: 'backgroundColor',
721 cssName: 'background-color',
722 valueChanged: (target, oldValue, newValue) => {
723 target.backgroundInternal = target.backgroundInternal.withColor(newValue);
724 },
725 equalityComparer: Color.equals,
726 valueConverter: (value) => new Color(value),
727});
728backgroundColorProperty.register(Style);
729export const backgroundRepeatProperty = new CssProperty({
730 name: 'backgroundRepeat',
731 cssName: 'background-repeat',
732 valueConverter: CoreTypes.BackgroundRepeat.parse,
733 valueChanged: (target, oldValue, newValue) => {
734 target.backgroundInternal = target.backgroundInternal.withRepeat(newValue);
735 },
736});
737backgroundRepeatProperty.register(Style);
738export const backgroundSizeProperty = new CssProperty({
739 name: 'backgroundSize',
740 cssName: 'background-size',
741 valueChanged: (target, oldValue, newValue) => {
742 target.backgroundInternal = target.backgroundInternal.withSize(newValue);
743 },
744});
745backgroundSizeProperty.register(Style);
746export const backgroundPositionProperty = new CssProperty({
747 name: 'backgroundPosition',
748 cssName: 'background-position',
749 valueChanged: (target, oldValue, newValue) => {
750 target.backgroundInternal = target.backgroundInternal.withPosition(newValue);
751 },
752});
753backgroundPositionProperty.register(Style);
754function convertToBackgrounds(value) {
755 if (typeof value === 'string') {
756 const backgrounds = parseBackground(value).value;
757 let backgroundColor = unsetValue;
758 if (backgrounds.color) {
759 backgroundColor = backgrounds.color instanceof Color ? backgrounds.color : new Color(backgrounds.color);
760 }
761 let backgroundImage;
762 if (typeof backgrounds.image === 'object' && backgrounds.image) {
763 backgroundImage = LinearGradient.parse(backgrounds.image);
764 }
765 else {
766 backgroundImage = backgrounds.image || unsetValue;
767 }
768 const backgroundRepeat = backgrounds.repeat || unsetValue;
769 const backgroundPosition = backgrounds.position ? backgrounds.position.text : unsetValue;
770 return [
771 [backgroundColorProperty, backgroundColor],
772 [backgroundImageProperty, backgroundImage],
773 [backgroundRepeatProperty, backgroundRepeat],
774 [backgroundPositionProperty, backgroundPosition],
775 ];
776 }
777 else {
778 return [
779 [backgroundColorProperty, unsetValue],
780 [backgroundImageProperty, unsetValue],
781 [backgroundRepeatProperty, unsetValue],
782 [backgroundPositionProperty, unsetValue],
783 ];
784 }
785}
786function parseBorderColor(value) {
787 const result = {
788 top: undefined,
789 right: undefined,
790 bottom: undefined,
791 left: undefined,
792 };
793 if (value.indexOf('rgb') === 0 || value.indexOf('hsl') === 0) {
794 result.top = result.right = result.bottom = result.left = new Color(value);
795 return result;
796 }
797 const arr = value.split(/[ ,]+/);
798 if (arr.length === 1) {
799 const arr0 = new Color(arr[0]);
800 result.top = arr0;
801 result.right = arr0;
802 result.bottom = arr0;
803 result.left = arr0;
804 }
805 else if (arr.length === 2) {
806 const arr0 = new Color(arr[0]);
807 const arr1 = new Color(arr[1]);
808 result.top = arr0;
809 result.right = arr1;
810 result.bottom = arr0;
811 result.left = arr1;
812 }
813 else if (arr.length === 3) {
814 const arr0 = new Color(arr[0]);
815 const arr1 = new Color(arr[1]);
816 const arr2 = new Color(arr[2]);
817 result.top = arr0;
818 result.right = arr1;
819 result.bottom = arr2;
820 result.left = arr1;
821 }
822 else if (arr.length === 4) {
823 const arr0 = new Color(arr[0]);
824 const arr1 = new Color(arr[1]);
825 const arr2 = new Color(arr[2]);
826 const arr3 = new Color(arr[3]);
827 result.top = arr0;
828 result.right = arr1;
829 result.bottom = arr2;
830 result.left = arr3;
831 }
832 else {
833 throw new Error(`Expected 1, 2, 3 or 4 parameters. Actual: ${value}`);
834 }
835 return result;
836}
837// Border Color properties.
838const borderColorProperty = new ShorthandProperty({
839 name: 'borderColor',
840 cssName: 'border-color',
841 getter: function () {
842 if (Color.equals(this.borderTopColor, this.borderRightColor) && Color.equals(this.borderTopColor, this.borderBottomColor) && Color.equals(this.borderTopColor, this.borderLeftColor)) {
843 return this.borderTopColor;
844 }
845 else {
846 return `${this.borderTopColor} ${this.borderRightColor} ${this.borderBottomColor} ${this.borderLeftColor}`;
847 }
848 },
849 converter: function (value) {
850 if (typeof value === 'string') {
851 const fourColors = parseBorderColor(value);
852 return [
853 [borderTopColorProperty, fourColors.top],
854 [borderRightColorProperty, fourColors.right],
855 [borderBottomColorProperty, fourColors.bottom],
856 [borderLeftColorProperty, fourColors.left],
857 ];
858 }
859 else {
860 return [
861 [borderTopColorProperty, value],
862 [borderRightColorProperty, value],
863 [borderBottomColorProperty, value],
864 [borderLeftColorProperty, value],
865 ];
866 }
867 },
868});
869borderColorProperty.register(Style);
870export const borderTopColorProperty = new CssProperty({
871 name: 'borderTopColor',
872 cssName: 'border-top-color',
873 valueChanged: (target, oldValue, newValue) => {
874 target.backgroundInternal = target.backgroundInternal.withBorderTopColor(newValue);
875 },
876 equalityComparer: Color.equals,
877 valueConverter: (value) => new Color(value),
878});
879borderTopColorProperty.register(Style);
880export const borderRightColorProperty = new CssProperty({
881 name: 'borderRightColor',
882 cssName: 'border-right-color',
883 valueChanged: (target, oldValue, newValue) => {
884 target.backgroundInternal = target.backgroundInternal.withBorderRightColor(newValue);
885 },
886 equalityComparer: Color.equals,
887 valueConverter: (value) => new Color(value),
888});
889borderRightColorProperty.register(Style);
890export const borderBottomColorProperty = new CssProperty({
891 name: 'borderBottomColor',
892 cssName: 'border-bottom-color',
893 valueChanged: (target, oldValue, newValue) => {
894 target.backgroundInternal = target.backgroundInternal.withBorderBottomColor(newValue);
895 },
896 equalityComparer: Color.equals,
897 valueConverter: (value) => new Color(value),
898});
899borderBottomColorProperty.register(Style);
900export const borderLeftColorProperty = new CssProperty({
901 name: 'borderLeftColor',
902 cssName: 'border-left-color',
903 valueChanged: (target, oldValue, newValue) => {
904 target.backgroundInternal = target.backgroundInternal.withBorderLeftColor(newValue);
905 },
906 equalityComparer: Color.equals,
907 valueConverter: (value) => new Color(value),
908});
909borderLeftColorProperty.register(Style);
910// Border Width properties.
911const borderWidthProperty = new ShorthandProperty({
912 name: 'borderWidth',
913 cssName: 'border-width',
914 getter: function () {
915 if (Length.equals(this.borderTopWidth, this.borderRightWidth) && Length.equals(this.borderTopWidth, this.borderBottomWidth) && Length.equals(this.borderTopWidth, this.borderLeftWidth)) {
916 return this.borderTopWidth;
917 }
918 else {
919 return `${Length.convertToString(this.borderTopWidth)} ${Length.convertToString(this.borderRightWidth)} ${Length.convertToString(this.borderBottomWidth)} ${Length.convertToString(this.borderLeftWidth)}`;
920 }
921 },
922 converter: function (value) {
923 if (typeof value === 'string' && value !== 'auto') {
924 const borderWidths = parseThickness(value);
925 return [
926 [borderTopWidthProperty, borderWidths.top],
927 [borderRightWidthProperty, borderWidths.right],
928 [borderBottomWidthProperty, borderWidths.bottom],
929 [borderLeftWidthProperty, borderWidths.left],
930 ];
931 }
932 else {
933 return [
934 [borderTopWidthProperty, value],
935 [borderRightWidthProperty, value],
936 [borderBottomWidthProperty, value],
937 [borderLeftWidthProperty, value],
938 ];
939 }
940 },
941});
942borderWidthProperty.register(Style);
943export const borderTopWidthProperty = new CssProperty({
944 name: 'borderTopWidth',
945 cssName: 'border-top-width',
946 defaultValue: CoreTypes.zeroLength,
947 affectsLayout: global.isIOS,
948 equalityComparer: Length.equals,
949 valueChanged: (target, oldValue, newValue) => {
950 const value = Length.toDevicePixels(newValue, 0);
951 if (!isNonNegativeFiniteNumber(value)) {
952 throw new Error(`border-top-width should be Non-Negative Finite number. Value: ${value}`);
953 }
954 const view = target.viewRef.get();
955 if (view) {
956 view.effectiveBorderTopWidth = value;
957 }
958 else {
959 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
960 }
961 target.backgroundInternal = target.backgroundInternal.withBorderTopWidth(value);
962 },
963 valueConverter: Length.parse,
964});
965borderTopWidthProperty.register(Style);
966export const borderRightWidthProperty = new CssProperty({
967 name: 'borderRightWidth',
968 cssName: 'border-right-width',
969 defaultValue: CoreTypes.zeroLength,
970 affectsLayout: global.isIOS,
971 equalityComparer: Length.equals,
972 valueChanged: (target, oldValue, newValue) => {
973 const value = Length.toDevicePixels(newValue, 0);
974 if (!isNonNegativeFiniteNumber(value)) {
975 throw new Error(`border-right-width should be Non-Negative Finite number. Value: ${value}`);
976 }
977 const view = target.viewRef.get();
978 if (view) {
979 view.effectiveBorderRightWidth = value;
980 }
981 else {
982 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
983 }
984 target.backgroundInternal = target.backgroundInternal.withBorderRightWidth(value);
985 },
986 valueConverter: Length.parse,
987});
988borderRightWidthProperty.register(Style);
989export const borderBottomWidthProperty = new CssProperty({
990 name: 'borderBottomWidth',
991 cssName: 'border-bottom-width',
992 defaultValue: CoreTypes.zeroLength,
993 affectsLayout: global.isIOS,
994 equalityComparer: Length.equals,
995 valueChanged: (target, oldValue, newValue) => {
996 const value = Length.toDevicePixels(newValue, 0);
997 if (!isNonNegativeFiniteNumber(value)) {
998 throw new Error(`border-bottom-width should be Non-Negative Finite number. Value: ${value}`);
999 }
1000 const view = target.viewRef.get();
1001 if (view) {
1002 view.effectiveBorderBottomWidth = value;
1003 }
1004 else {
1005 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
1006 }
1007 target.backgroundInternal = target.backgroundInternal.withBorderBottomWidth(value);
1008 },
1009 valueConverter: Length.parse,
1010});
1011borderBottomWidthProperty.register(Style);
1012export const borderLeftWidthProperty = new CssProperty({
1013 name: 'borderLeftWidth',
1014 cssName: 'border-left-width',
1015 defaultValue: CoreTypes.zeroLength,
1016 affectsLayout: global.isIOS,
1017 equalityComparer: Length.equals,
1018 valueChanged: (target, oldValue, newValue) => {
1019 const value = Length.toDevicePixels(newValue, 0);
1020 if (!isNonNegativeFiniteNumber(value)) {
1021 throw new Error(`border-left-width should be Non-Negative Finite number. Value: ${value}`);
1022 }
1023 const view = target.viewRef.get();
1024 if (view) {
1025 view.effectiveBorderLeftWidth = value;
1026 }
1027 else {
1028 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
1029 }
1030 target.backgroundInternal = target.backgroundInternal.withBorderLeftWidth(value);
1031 },
1032 valueConverter: Length.parse,
1033});
1034borderLeftWidthProperty.register(Style);
1035// Border Radius properties.
1036const borderRadiusProperty = new ShorthandProperty({
1037 name: 'borderRadius',
1038 cssName: 'border-radius',
1039 getter: function () {
1040 if (Length.equals(this.borderTopLeftRadius, this.borderTopRightRadius) && Length.equals(this.borderTopLeftRadius, this.borderBottomRightRadius) && Length.equals(this.borderTopLeftRadius, this.borderBottomLeftRadius)) {
1041 return this.borderTopLeftRadius;
1042 }
1043 return `${Length.convertToString(this.borderTopLeftRadius)} ${Length.convertToString(this.borderTopRightRadius)} ${Length.convertToString(this.borderBottomRightRadius)} ${Length.convertToString(this.borderBottomLeftRadius)}`;
1044 },
1045 converter: function (value) {
1046 if (typeof value === 'string') {
1047 const borderRadius = parseThickness(value);
1048 return [
1049 [borderTopLeftRadiusProperty, borderRadius.top],
1050 [borderTopRightRadiusProperty, borderRadius.right],
1051 [borderBottomRightRadiusProperty, borderRadius.bottom],
1052 [borderBottomLeftRadiusProperty, borderRadius.left],
1053 ];
1054 }
1055 else {
1056 return [
1057 [borderTopLeftRadiusProperty, value],
1058 [borderTopRightRadiusProperty, value],
1059 [borderBottomRightRadiusProperty, value],
1060 [borderBottomLeftRadiusProperty, value],
1061 ];
1062 }
1063 },
1064});
1065borderRadiusProperty.register(Style);
1066export const borderTopLeftRadiusProperty = new CssProperty({
1067 name: 'borderTopLeftRadius',
1068 cssName: 'border-top-left-radius',
1069 defaultValue: 0,
1070 affectsLayout: global.isIOS,
1071 valueChanged: (target, oldValue, newValue) => {
1072 const value = Length.toDevicePixels(newValue, 0);
1073 if (!isNonNegativeFiniteNumber(value)) {
1074 throw new Error(`border-top-left-radius should be Non-Negative Finite number. Value: ${value}`);
1075 }
1076 target.backgroundInternal = target.backgroundInternal.withBorderTopLeftRadius(value);
1077 },
1078 valueConverter: Length.parse,
1079 equalityComparer: Length.equals,
1080});
1081borderTopLeftRadiusProperty.register(Style);
1082export const borderTopRightRadiusProperty = new CssProperty({
1083 name: 'borderTopRightRadius',
1084 cssName: 'border-top-right-radius',
1085 defaultValue: 0,
1086 affectsLayout: global.isIOS,
1087 valueChanged: (target, oldValue, newValue) => {
1088 const value = Length.toDevicePixels(newValue, 0);
1089 if (!isNonNegativeFiniteNumber(value)) {
1090 throw new Error(`border-top-right-radius should be Non-Negative Finite number. Value: ${value}`);
1091 }
1092 target.backgroundInternal = target.backgroundInternal.withBorderTopRightRadius(value);
1093 },
1094 valueConverter: Length.parse,
1095 equalityComparer: Length.equals,
1096});
1097borderTopRightRadiusProperty.register(Style);
1098export const borderBottomRightRadiusProperty = new CssProperty({
1099 name: 'borderBottomRightRadius',
1100 cssName: 'border-bottom-right-radius',
1101 defaultValue: 0,
1102 affectsLayout: global.isIOS,
1103 valueChanged: (target, oldValue, newValue) => {
1104 const value = Length.toDevicePixels(newValue, 0);
1105 if (!isNonNegativeFiniteNumber(value)) {
1106 throw new Error(`border-bottom-right-radius should be Non-Negative Finite number. Value: ${value}`);
1107 }
1108 target.backgroundInternal = target.backgroundInternal.withBorderBottomRightRadius(value);
1109 },
1110 valueConverter: Length.parse,
1111 equalityComparer: Length.equals,
1112});
1113borderBottomRightRadiusProperty.register(Style);
1114export const borderBottomLeftRadiusProperty = new CssProperty({
1115 name: 'borderBottomLeftRadius',
1116 cssName: 'border-bottom-left-radius',
1117 defaultValue: 0,
1118 affectsLayout: global.isIOS,
1119 valueChanged: (target, oldValue, newValue) => {
1120 const value = Length.toDevicePixels(newValue, 0);
1121 if (!isNonNegativeFiniteNumber(value)) {
1122 throw new Error(`border-bottom-left-radius should be Non-Negative Finite number. Value: ${value}`);
1123 }
1124 target.backgroundInternal = target.backgroundInternal.withBorderBottomLeftRadius(value);
1125 },
1126 valueConverter: Length.parse,
1127 equalityComparer: Length.equals,
1128});
1129borderBottomLeftRadiusProperty.register(Style);
1130const boxShadowProperty = new CssProperty({
1131 name: 'boxShadow',
1132 cssName: 'box-shadow',
1133 valueChanged: (target, oldValue, newValue) => {
1134 target.backgroundInternal = target.backgroundInternal.withBoxShadow(newValue
1135 ? {
1136 inset: newValue.inset,
1137 offsetX: Length.toDevicePixels(newValue.offsetX, 0),
1138 offsetY: Length.toDevicePixels(newValue.offsetY, 0),
1139 blurRadius: Length.toDevicePixels(newValue.blurRadius, 0),
1140 spreadRadius: Length.toDevicePixels(newValue.spreadRadius, 0),
1141 color: newValue.color,
1142 }
1143 : null);
1144 },
1145 valueConverter: (value) => {
1146 return parseCSSShadow(value);
1147 },
1148});
1149boxShadowProperty.register(Style);
1150function isNonNegativeFiniteNumber(value) {
1151 return isFinite(value) && !isNaN(value) && value >= 0;
1152}
1153const supportedPaths = ['rect', 'circle', 'ellipse', 'polygon', 'inset'];
1154function isClipPathValid(value) {
1155 if (!value) {
1156 return true;
1157 }
1158 const functionName = value.substring(0, value.indexOf('(')).trim();
1159 return supportedPaths.indexOf(functionName) !== -1;
1160}
1161export const clipPathProperty = new CssProperty({
1162 name: 'clipPath',
1163 cssName: 'clip-path',
1164 valueChanged: (target, oldValue, newValue) => {
1165 if (!isClipPathValid(newValue)) {
1166 throw new Error('clip-path is not valid.');
1167 }
1168 target.backgroundInternal = target.backgroundInternal.withClipPath(newValue);
1169 },
1170});
1171clipPathProperty.register(Style);
1172function isFloatValueConverter(value) {
1173 const newValue = parseFloat(value);
1174 if (isNaN(newValue)) {
1175 throw new Error(`Invalid value: ${newValue}`);
1176 }
1177 return newValue;
1178}
1179export const zIndexProperty = new CssProperty({
1180 name: 'zIndex',
1181 cssName: 'z-index',
1182 valueConverter: isFloatValueConverter,
1183});
1184zIndexProperty.register(Style);
1185function opacityConverter(value) {
1186 const newValue = parseFloat(value);
1187 if (!isNaN(newValue) && 0 <= newValue && newValue <= 1) {
1188 return newValue;
1189 }
1190 throw new Error(`Opacity should be between [0, 1]. Value: ${newValue}`);
1191}
1192export const opacityProperty = new CssAnimationProperty({
1193 name: 'opacity',
1194 cssName: 'opacity',
1195 defaultValue: 1,
1196 valueConverter: opacityConverter,
1197});
1198opacityProperty.register(Style);
1199export const colorProperty = new InheritedCssProperty({
1200 name: 'color',
1201 cssName: 'color',
1202 equalityComparer: Color.equals,
1203 valueConverter: (v) => new Color(v),
1204});
1205colorProperty.register(Style);
1206export const fontInternalProperty = new CssProperty({
1207 name: 'fontInternal',
1208 cssName: '_fontInternal',
1209});
1210fontInternalProperty.register(Style);
1211export const fontFamilyProperty = new InheritedCssProperty({
1212 name: 'fontFamily',
1213 cssName: 'font-family',
1214 affectsLayout: global.isIOS,
1215 valueChanged: (target, oldValue, newValue) => {
1216 const currentFont = target.fontInternal || Font.default;
1217 if (currentFont.fontFamily !== newValue) {
1218 const newFont = currentFont.withFontFamily(newValue);
1219 target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont;
1220 }
1221 },
1222});
1223fontFamilyProperty.register(Style);
1224export const fontScaleInternalProperty = new InheritedCssProperty({
1225 name: 'fontScaleInternal',
1226 cssName: '_fontScaleInternal',
1227 defaultValue: 1.0,
1228 valueConverter: (v) => parseFloat(v),
1229});
1230fontScaleInternalProperty.register(Style);
1231export const fontSizeProperty = new InheritedCssProperty({
1232 name: 'fontSize',
1233 cssName: 'font-size',
1234 affectsLayout: global.isIOS,
1235 valueChanged: (target, oldValue, newValue) => {
1236 if (target.viewRef['handleFontSize'] === true) {
1237 return;
1238 }
1239 const currentFont = target.fontInternal || Font.default;
1240 if (currentFont.fontSize !== newValue) {
1241 const newFont = currentFont.withFontSize(newValue);
1242 target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont;
1243 }
1244 },
1245 valueConverter: (v) => parseFloat(v),
1246});
1247fontSizeProperty.register(Style);
1248export const fontStyleProperty = new InheritedCssProperty({
1249 name: 'fontStyle',
1250 cssName: 'font-style',
1251 affectsLayout: global.isIOS,
1252 defaultValue: FontStyle.NORMAL,
1253 valueConverter: FontStyle.parse,
1254 valueChanged: (target, oldValue, newValue) => {
1255 const currentFont = target.fontInternal || Font.default;
1256 if (currentFont.fontStyle !== newValue) {
1257 const newFont = currentFont.withFontStyle(newValue);
1258 target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont;
1259 }
1260 },
1261});
1262fontStyleProperty.register(Style);
1263export const fontWeightProperty = new InheritedCssProperty({
1264 name: 'fontWeight',
1265 cssName: 'font-weight',
1266 affectsLayout: global.isIOS,
1267 defaultValue: FontWeight.NORMAL,
1268 valueConverter: FontWeight.parse,
1269 valueChanged: (target, oldValue, newValue) => {
1270 const currentFont = target.fontInternal || Font.default;
1271 if (currentFont.fontWeight !== newValue) {
1272 const newFont = currentFont.withFontWeight(newValue);
1273 target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont;
1274 }
1275 },
1276});
1277fontWeightProperty.register(Style);
1278const fontProperty = new ShorthandProperty({
1279 name: 'font',
1280 cssName: 'font',
1281 getter: function () {
1282 return `${this.fontStyle} ${this.fontWeight} ${this.fontSize} ${this.fontFamily}`;
1283 },
1284 converter: function (value) {
1285 if (value === unsetValue) {
1286 return [
1287 [fontStyleProperty, unsetValue],
1288 [fontWeightProperty, unsetValue],
1289 [fontSizeProperty, unsetValue],
1290 [fontFamilyProperty, unsetValue],
1291 ];
1292 }
1293 else {
1294 const font = parseFont(value);
1295 const fontSize = parseFloat(font.fontSize);
1296 return [
1297 [fontStyleProperty, font.fontStyle],
1298 [fontWeightProperty, font.fontWeight],
1299 [fontSizeProperty, fontSize],
1300 [fontFamilyProperty, font.fontFamily],
1301 ];
1302 }
1303 },
1304});
1305fontProperty.register(Style);
1306export const fontVariationSettingsProperty = new InheritedCssProperty({
1307 name: 'fontVariationSettings',
1308 cssName: 'font-variation-settings',
1309 affectsLayout: global.isIOS,
1310 valueChanged: (target, oldValue, newValue) => {
1311 const currentFont = target.fontInternal || Font.default;
1312 if (currentFont.fontVariationSettings !== newValue) {
1313 const newFont = currentFont.withFontVariationSettings(newValue);
1314 target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont;
1315 }
1316 },
1317 valueConverter: (value) => {
1318 return FontVariationSettings.parse(value);
1319 },
1320});
1321fontVariationSettingsProperty.register(Style);
1322export const visibilityProperty = new CssProperty({
1323 name: 'visibility',
1324 cssName: 'visibility',
1325 defaultValue: CoreTypes.Visibility.visible,
1326 affectsLayout: global.isIOS,
1327 valueConverter: CoreTypes.Visibility.parse,
1328 valueChanged: (target, oldValue, newValue) => {
1329 const view = target.viewRef.get();
1330 if (view) {
1331 view.isCollapsed = newValue === CoreTypes.Visibility.collapse;
1332 }
1333 else {
1334 Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
1335 }
1336 },
1337});
1338visibilityProperty.register(Style);
1339export const androidElevationProperty = new CssProperty({
1340 name: 'androidElevation',
1341 cssName: 'android-elevation',
1342 valueConverter: parseFloat,
1343});
1344androidElevationProperty.register(Style);
1345export const androidDynamicElevationOffsetProperty = new CssProperty({
1346 name: 'androidDynamicElevationOffset',
1347 cssName: 'android-dynamic-elevation-offset',
1348 valueConverter: parseFloat,
1349});
1350androidDynamicElevationOffsetProperty.register(Style);
1351//# sourceMappingURL=style-properties.js.map
\No newline at end of file