@octane-xplat/patches 0.0.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +8 -1
- package/package.json +16 -10
- package/patches/@nativescript-community__octane@0.2.4.patch +25 -0
- package/patches/@nativescript-community__vite-octane@0.2.1.patch +41 -0
- package/patches/@nativescript__core@9.1.2.patch +1415 -0
- package/patches/@nativescript__core@9.1.3-next.2.patch +428 -0
- package/patches/@nativescript__types@9.0.0.patch +93 -0
- package/patches/@nativescript__vite@8.0.13.patch +233 -0
- package/patches/@nativescript__vite@8.0.17.patch +220 -0
- package/patches/@octanejs__tiptap@0.0.51.patch +78 -0
- package/patches/@tsrx__typescript-plugin@0.4.11.patch +11 -0
- package/patches/css@3.0.0.patch +52 -0
- package/patches/linkifyjs@4.3.3.patch +73 -0
- package/patches/octane@0.6.3.patch +1307 -0
- package/index.d.ts +0 -1
- package/index.js +0 -2
|
@@ -0,0 +1,1415 @@
|
|
|
1
|
+
diff --git a/css/css-tree-parser.js b/css/css-tree-parser.js
|
|
2
|
+
index 0c13e7e67a8eb306248d738bb73189b772b4a409..7ce38a9ba8f1f9aef709136b46f8e5b2435ba714 100644
|
|
3
|
+
--- a/css/css-tree-parser.js
|
|
4
|
+
+++ b/css/css-tree-parser.js
|
|
5
|
+
@@ -66,6 +66,10 @@ function transformAst(node, css, type = null) {
|
|
6
|
+
atrule.keyframes = transformAst(node.block, css, 'keyframe');
|
|
7
|
+
atrule.vendor = undefined;
|
|
8
|
+
}
|
|
9
|
+
+ else if (node.name === 'layer') {
|
|
10
|
+
+ atrule.layer = node.prelude ? node.prelude.value.trim() : '';
|
|
11
|
+
+ atrule.rules = transformAst(node.block, css);
|
|
12
|
+
+ }
|
|
13
|
+
else {
|
|
14
|
+
atrule.rules = transformAst(node.block, css);
|
|
15
|
+
}
|
|
16
|
+
diff --git a/css/reworkcss.d.ts b/css/reworkcss.d.ts
|
|
17
|
+
index 3ac4f618f307864cb95b70cd01f4ecdc42c9d9e4..1906ed1457de195a799c9e938136f078e7ed6307 100644
|
|
18
|
+
--- a/css/reworkcss.d.ts
|
|
19
|
+
+++ b/css/reworkcss.d.ts
|
|
20
|
+
@@ -10,7 +10,7 @@ export interface Position {
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface Node {
|
|
24
|
+
- type: 'rule' | 'keyframes' | 'declaration' | 'import' | 'media';
|
|
25
|
+
+ type: 'rule' | 'keyframes' | 'declaration' | 'import' | 'media' | 'layer';
|
|
26
|
+
position: Position;
|
|
27
|
+
}
|
|
28
|
+
export interface Declaration extends Node {
|
|
29
|
+
@@ -21,7 +21,7 @@ export interface Rule extends Node {
|
|
30
|
+
selectors: string[];
|
|
31
|
+
declarations: Declaration[];
|
|
32
|
+
}
|
|
33
|
+
-export type AtRule = KeyFrames | Media;
|
|
34
|
+
+export type AtRule = KeyFrames | Media | Layer;
|
|
35
|
+
export interface Keyframes extends Rule {
|
|
36
|
+
name: string;
|
|
37
|
+
vendor?: string;
|
|
38
|
+
@@ -35,6 +35,11 @@ export interface Media extends Node {
|
|
39
|
+
media: string;
|
|
40
|
+
rules: Array<Rule | AtRule>;
|
|
41
|
+
}
|
|
42
|
+
+export interface Layer extends Node {
|
|
43
|
+
+ /** Layer-name prelude — '' for an anonymous block. Statement form (`@layer a, b;`) leaves rules undefined. */
|
|
44
|
+
+ layer: string;
|
|
45
|
+
+ rules?: Array<Rule | AtRule>;
|
|
46
|
+
+}
|
|
47
|
+
export interface StyleSheet {
|
|
48
|
+
rules: Rule[];
|
|
49
|
+
}
|
|
50
|
+
diff --git a/ui/animation/animation-common.js b/ui/animation/animation-common.js
|
|
51
|
+
index d67e3c208de1a37d07aa3ee97f7f64e58ca1c1c4..60415ea6c023212727d090d724793b4ff5cf3b93 100644
|
|
52
|
+
--- a/ui/animation/animation-common.js
|
|
53
|
+
+++ b/ui/animation/animation-common.js
|
|
54
|
+
@@ -106,10 +106,26 @@ export class AnimationBase {
|
|
55
|
+
console.error(`Property ${item} must be valid number. Value: ${value}`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
- else if ((item === Properties.scale || item === Properties.translate) && (typeof value.x !== 'number' || typeof value.y !== 'number')) {
|
|
59
|
+
+ else if (item === Properties.scale && (typeof value.x !== 'number' || typeof value.y !== 'number')) {
|
|
60
|
+
console.error(`Property ${item} must be valid Pair. Value: ${value}`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
+ else if (item === Properties.translate) {
|
|
64
|
+
+ // Coerce input into PercentLength values so that percentage
|
|
65
|
+
+ // translates (e.g. from keyframe transforms) are preserved.
|
|
66
|
+
+ try {
|
|
67
|
+
+ const x = PercentLength.parse(value.x);
|
|
68
|
+
+ const y = PercentLength.parse(value.y);
|
|
69
|
+
+ if (!isValidTranslateValue(x) || !isValidTranslateValue(y)) {
|
|
70
|
+
+ throw new Error();
|
|
71
|
+
+ }
|
|
72
|
+
+ animationDefinition[item] = { x, y };
|
|
73
|
+
+ }
|
|
74
|
+
+ catch {
|
|
75
|
+
+ console.error(`Property ${item} must be valid Pair. Value: ${value}`);
|
|
76
|
+
+ return;
|
|
77
|
+
+ }
|
|
78
|
+
+ }
|
|
79
|
+
else if (item === Properties.backgroundColor && !Color.isValid(animationDefinition.backgroundColor)) {
|
|
80
|
+
console.error(`Property ${item} must be valid color. Value: ${value}`);
|
|
81
|
+
return;
|
|
82
|
+
@@ -236,4 +252,13 @@ export class AnimationBase {
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
+function isValidTranslateValue(value) {
|
|
87
|
+
+ if (typeof value === 'number') {
|
|
88
|
+
+ return true;
|
|
89
|
+
+ }
|
|
90
|
+
+ if (!value || typeof value !== 'object') {
|
|
91
|
+
+ return false;
|
|
92
|
+
+ }
|
|
93
|
+
+ return (value.unit === 'px' || value.unit === 'dip' || value.unit === '%') && typeof value.value === 'number';
|
|
94
|
+
+}
|
|
95
|
+
//# sourceMappingURL=animation-common.js.map
|
|
96
|
+
|
|
97
|
+
diff --git a/ui/animation/animation-shared.d.ts b/ui/animation/animation-shared.d.ts
|
|
98
|
+
index 4d5239dc6d6d4dd4d22e34f68b9a2c246fb2f16a..eb216e70300d7a186d40b20d27860a17eb6815f4 100644
|
|
99
|
+
--- a/ui/animation/animation-shared.d.ts
|
|
100
|
+
+++ b/ui/animation/animation-shared.d.ts
|
|
101
|
+
@@ -6,17 +6,21 @@ export type Transformation = {
|
|
102
|
+
value: TransformationValue;
|
|
103
|
+
};
|
|
104
|
+
export type TransformationType = 'rotate' | 'rotate3d' | 'rotateX' | 'rotateY' | 'translate' | 'translate3d' | 'translateX' | 'translateY' | 'scale' | 'scale3d' | 'scaleX' | 'scaleY';
|
|
105
|
+
-export type TransformationValue = Point3D | Pair | number;
|
|
106
|
+
+export type TransformationValue = Point3D | Pair | TranslatePair | number;
|
|
107
|
+
export interface Point3D {
|
|
108
|
+
x: number;
|
|
109
|
+
y: number;
|
|
110
|
+
z: number;
|
|
111
|
+
}
|
|
112
|
+
export type TransformFunctionsInfo = {
|
|
113
|
+
- translate: Pair;
|
|
114
|
+
+ translate: TranslatePair;
|
|
115
|
+
rotate: Point3D;
|
|
116
|
+
scale: Pair;
|
|
117
|
+
};
|
|
118
|
+
+export interface TranslatePair {
|
|
119
|
+
+ x: CoreTypes.PercentLengthType;
|
|
120
|
+
+ y: CoreTypes.PercentLengthType;
|
|
121
|
+
+}
|
|
122
|
+
export interface Pair {
|
|
123
|
+
x: number;
|
|
124
|
+
y: number;
|
|
125
|
+
@@ -29,10 +33,7 @@ export interface AnimationDefinition {
|
|
126
|
+
target?: View;
|
|
127
|
+
opacity?: number;
|
|
128
|
+
backgroundColor?: Color | any;
|
|
129
|
+
- translate?: Pair | {
|
|
130
|
+
- x: number;
|
|
131
|
+
- y: number;
|
|
132
|
+
- };
|
|
133
|
+
+ translate?: TranslatePair;
|
|
134
|
+
scale?: Pair | {
|
|
135
|
+
x: number;
|
|
136
|
+
y: number;
|
|
137
|
+
diff --git a/ui/animation/index.android.js b/ui/animation/index.android.js
|
|
138
|
+
index a9328887ae7ad20eadc75f46d9829ce4d3716b6f..55d0cad961eb9b4e47b007f4a2de7424a98aa890 100644
|
|
139
|
+
--- a/ui/animation/index.android.js
|
|
140
|
+
+++ b/ui/animation/index.android.js
|
|
141
|
+
@@ -304,7 +304,7 @@ export class Animation extends AnimationBase {
|
|
142
|
+
propertyAnimation.target[translateYProperty.setNative](propertyAnimation.target.style.translateY);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
- animators.push(createAnimationSet([createObjectAnimator(nativeView, 'translationX', propertyAnimation.value.x * density), createObjectAnimator(nativeView, 'translationY', propertyAnimation.value.y * density)], propertyAnimation.iterations));
|
|
146
|
+
+ animators.push(createAnimationSet([createObjectAnimator(nativeView, 'translationX', PercentLength.toDevicePixels(propertyAnimation.value.x, 0, nativeView.getWidth())), createObjectAnimator(nativeView, 'translationY', PercentLength.toDevicePixels(propertyAnimation.value.y, 0, nativeView.getHeight()))], propertyAnimation.iterations));
|
|
147
|
+
break;
|
|
148
|
+
case Properties.scale:
|
|
149
|
+
scaleXProperty._initDefaultNativeValue(style);
|
|
150
|
+
diff --git a/ui/animation/index.d.ts b/ui/animation/index.d.ts
|
|
151
|
+
index 24292e7aa38a0e915e19843551121d336d39d477..47307b90625d2dc09b3ca00b91882d7d8e542864 100644
|
|
152
|
+
--- a/ui/animation/index.d.ts
|
|
153
|
+
+++ b/ui/animation/index.d.ts
|
|
154
|
+
@@ -1,4 +1,4 @@
|
|
155
|
+
-export type { Pair, Transformation, TransformationType, TransformationValue, TransformFunctionsInfo, Point3D, AnimationPromise, Cancelable } from './animation-types';
|
|
156
|
+
+export type { Pair, TranslatePair, Transformation, TransformationType, TransformationValue, TransformFunctionsInfo, Point3D, AnimationPromise, Cancelable } from './animation-types';
|
|
157
|
+
export { KeyframeAnimation, KeyframeAnimationInfo, KeyframeDeclaration, KeyframeInfo } from './keyframe-animation';
|
|
158
|
+
import type { AnimationDefinition, AnimationPromise } from './animation-types';
|
|
159
|
+
|
|
160
|
+
diff --git a/ui/animation/index.ios.js b/ui/animation/index.ios.js
|
|
161
|
+
index 25f3c19349a389341676963351b6315f9181c1fc..f2d0eeb42ac12daa0fa4dd5ce1c704103501a736 100644
|
|
162
|
+
--- a/ui/animation/index.ios.js
|
|
163
|
+
+++ b/ui/animation/index.ios.js
|
|
164
|
+
@@ -3,6 +3,7 @@ import { AnimationBase, Properties } from './animation-common';
|
|
165
|
+
import { CubicBezierAnimationCurve } from '../../core-types/animation-types';
|
|
166
|
+
import { Trace } from '../../trace';
|
|
167
|
+
import { opacityProperty, backgroundColorProperty, rotateProperty, rotateXProperty, rotateYProperty, translateXProperty, translateYProperty, scaleXProperty, scaleYProperty, heightProperty, widthProperty } from '../styling/style-properties';
|
|
168
|
+
+import { resolveTranslate } from '../styling/css-transform';
|
|
169
|
+
import { PercentLength } from '../styling/length-shared';
|
|
170
|
+
import { ios as iosBackground } from '../styling/background';
|
|
171
|
+
import { ios as iosViewUtils } from '../utils';
|
|
172
|
+
@@ -329,7 +330,8 @@ export class Animation extends AnimationBase {
|
|
173
|
+
};
|
|
174
|
+
propertyNameToAnimate = 'transform';
|
|
175
|
+
fromValue = NSValue.valueWithCATransform3D(nativeView.layer.transform);
|
|
176
|
+
- toValue = NSValue.valueWithCATransform3D(CATransform3DTranslate(nativeView.layer.transform, toValue.x, toValue.y, 0));
|
|
177
|
+
+ const bounds = nativeView.bounds.size;
|
|
178
|
+
+ toValue = NSValue.valueWithCATransform3D(CATransform3DTranslate(nativeView.layer.transform, resolveTranslate(toValue.x, bounds.width), resolveTranslate(toValue.y, bounds.height), 0));
|
|
179
|
+
break;
|
|
180
|
+
case Properties.scale:
|
|
181
|
+
if (toValue.x === 0) {
|
|
182
|
+
@@ -583,8 +585,9 @@ export class Animation extends AnimationBase {
|
|
183
|
+
const value = animation.value;
|
|
184
|
+
let result = CATransform3DIdentity;
|
|
185
|
+
if (value[Properties.translate] !== undefined) {
|
|
186
|
+
- const x = value[Properties.translate].x;
|
|
187
|
+
- const y = value[Properties.translate].y;
|
|
188
|
+
+ const bounds = animation.target.nativeViewProtected ? animation.target.nativeViewProtected.bounds.size : { width: 0, height: 0 };
|
|
189
|
+
+ const x = resolveTranslate(value[Properties.translate].x, bounds.width);
|
|
190
|
+
+ const y = resolveTranslate(value[Properties.translate].y, bounds.height);
|
|
191
|
+
result = CATransform3DTranslate(result, x, y, 0);
|
|
192
|
+
}
|
|
193
|
+
if (value[Properties.scale] !== undefined) {
|
|
194
|
+
@@ -793,7 +796,8 @@ function calculateTransform(view) {
|
|
195
|
+
if (view.rotateX || view.rotateY) {
|
|
196
|
+
expectedTransform.m34 = -1 / perspective;
|
|
197
|
+
}
|
|
198
|
+
- expectedTransform = CATransform3DTranslate(expectedTransform, view.translateX, view.translateY, 0);
|
|
199
|
+
+ const bounds = view.nativeViewProtected ? view.nativeViewProtected.bounds.size : { width: 0, height: 0 };
|
|
200
|
+
+ expectedTransform = CATransform3DTranslate(expectedTransform, resolveTranslate(view.translateX, bounds.width), resolveTranslate(view.translateY, bounds.height), 0);
|
|
201
|
+
expectedTransform = iosHelper.applyRotateTransform(expectedTransform, view.rotateX, view.rotateY, view.rotate);
|
|
202
|
+
expectedTransform = CATransform3DScale(expectedTransform, scaleX, scaleY, 1);
|
|
203
|
+
return expectedTransform;
|
|
204
|
+
diff --git a/ui/animation/keyframe-animation.d.ts b/ui/animation/keyframe-animation.d.ts
|
|
205
|
+
index 3be12d5c382176ca302bc318f8d24e0434e00f51..7e34c4329780fb0cc623dbf28934b17610d427c6 100644
|
|
206
|
+
--- a/ui/animation/keyframe-animation.d.ts
|
|
207
|
+
+++ b/ui/animation/keyframe-animation.d.ts
|
|
208
|
+
@@ -38,8 +38,8 @@ interface Keyframe {
|
|
209
|
+
y: number;
|
|
210
|
+
};
|
|
211
|
+
translate?: {
|
|
212
|
+
- x: number;
|
|
213
|
+
- y: number;
|
|
214
|
+
+ x: CoreTypes.PercentLengthType;
|
|
215
|
+
+ y: CoreTypes.PercentLengthType;
|
|
216
|
+
};
|
|
217
|
+
rotate?: {
|
|
218
|
+
x: number;
|
|
219
|
+
diff --git a/ui/core/view/index.android.d.ts b/ui/core/view/index.android.d.ts
|
|
220
|
+
index d540ec1993b7745ac600bc1bb542779024d1bcfa..867345daa6f5a8ded5f3a0ae0655562a3581870e 100644
|
|
221
|
+
--- a/ui/core/view/index.android.d.ts
|
|
222
|
+
+++ b/ui/core/view/index.android.d.ts
|
|
223
|
+
@@ -58,8 +58,8 @@ export declare class View extends ViewCommon {
|
|
224
|
+
[perspectiveProperty.setNative]: (value: number) => void;
|
|
225
|
+
[scaleXProperty.setNative]: (value: number) => void;
|
|
226
|
+
[scaleYProperty.setNative]: (value: number) => void;
|
|
227
|
+
- [translateXProperty.setNative]: (value: CoreTypes.dip) => void;
|
|
228
|
+
- [translateYProperty.setNative]: (value: CoreTypes.dip) => void;
|
|
229
|
+
+ [translateXProperty.setNative]: (value: CoreTypes.PercentLengthType) => void;
|
|
230
|
+
+ [translateYProperty.setNative]: (value: CoreTypes.PercentLengthType) => void;
|
|
231
|
+
[zIndexProperty.getDefault]: () => number;
|
|
232
|
+
[zIndexProperty.setNative]: (value: number) => void;
|
|
233
|
+
[backgroundInternalProperty.getDefault]: () => android.graphics.drawable.Drawable;
|
|
234
|
+
diff --git a/ui/core/view/index.android.js b/ui/core/view/index.android.js
|
|
235
|
+
index b17d5f174ff636be2ac5a18ad06e7986a177f3bc..50bd1c764244d3cb8d7fd5ad8ae7bbcd234c152e 100644
|
|
236
|
+
--- a/ui/core/view/index.android.js
|
|
237
|
+
+++ b/ui/core/view/index.android.js
|
|
238
|
+
@@ -6,6 +6,8 @@ import { Trace } from '../../../trace';
|
|
239
|
+
import { hiddenProperty } from '../view-base';
|
|
240
|
+
import { isCssWideKeyword } from '../properties/property-shared';
|
|
241
|
+
import { perspectiveProperty, visibilityProperty, opacityProperty, horizontalAlignmentProperty, verticalAlignmentProperty, minWidthProperty, minHeightProperty, maxWidthProperty, maxHeightProperty, widthProperty, heightProperty, marginLeftProperty, marginTopProperty, marginRightProperty, marginBottomProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, androidElevationProperty, androidDynamicElevationOffsetProperty } from '../../styling/style-properties';
|
|
242
|
+
+import { isPercentTranslate } from '../../styling/css-transform';
|
|
243
|
+
+import { PercentLength } from '../../styling/length-shared';
|
|
244
|
+
import { CoreTypes } from '../../../core-types';
|
|
245
|
+
import { Background, refreshBorderDrawable } from '../../styling/background';
|
|
246
|
+
import { profile } from '../../../profiling';
|
|
247
|
+
@@ -694,8 +696,16 @@ export class View extends ViewCommon {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
layoutNativeView(left, top, right, bottom) {
|
|
251
|
+
- if (this.nativeViewProtected) {
|
|
252
|
+
- this.nativeViewProtected.layout(left, top, right, bottom);
|
|
253
|
+
+ const nativeView = this.nativeViewProtected;
|
|
254
|
+
+ if (nativeView) {
|
|
255
|
+
+ nativeView.layout(left, top, right, bottom);
|
|
256
|
+
+ // Percentage translates are resolved against the view's own size.
|
|
257
|
+
+ if (isPercentTranslate(this.translateX)) {
|
|
258
|
+
+ org.nativescript.widgets.ViewHelper.setTranslateX(nativeView, PercentLength.toDevicePixels(this.translateX, 0, nativeView.getWidth()));
|
|
259
|
+
+ }
|
|
260
|
+
+ if (isPercentTranslate(this.translateY)) {
|
|
261
|
+
+ org.nativescript.widgets.ViewHelper.setTranslateY(nativeView, PercentLength.toDevicePixels(this.translateY, 0, nativeView.getHeight()));
|
|
262
|
+
+ }
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
requestLayout() {
|
|
266
|
+
@@ -1272,10 +1282,10 @@ export class View extends ViewCommon {
|
|
267
|
+
org.nativescript.widgets.ViewHelper.setScaleY(this.nativeViewProtected, float(value));
|
|
268
|
+
}
|
|
269
|
+
[translateXProperty.setNative](value) {
|
|
270
|
+
- org.nativescript.widgets.ViewHelper.setTranslateX(this.nativeViewProtected, layout.toDevicePixels(value));
|
|
271
|
+
+ org.nativescript.widgets.ViewHelper.setTranslateX(this.nativeViewProtected, PercentLength.toDevicePixels(value, 0, this.nativeViewProtected ? this.nativeViewProtected.getWidth() : 0));
|
|
272
|
+
}
|
|
273
|
+
[translateYProperty.setNative](value) {
|
|
274
|
+
- org.nativescript.widgets.ViewHelper.setTranslateY(this.nativeViewProtected, layout.toDevicePixels(value));
|
|
275
|
+
+ org.nativescript.widgets.ViewHelper.setTranslateY(this.nativeViewProtected, PercentLength.toDevicePixels(value, 0, this.nativeViewProtected ? this.nativeViewProtected.getHeight() : 0));
|
|
276
|
+
}
|
|
277
|
+
[zIndexProperty.getDefault]() {
|
|
278
|
+
return 0;
|
|
279
|
+
diff --git a/ui/core/view/index.d.ts b/ui/core/view/index.d.ts
|
|
280
|
+
index f5cc0e283779eb9049932b99fd9c8285526c05f9..af4b295ebed3886b31c0678b2d6e5103ad470ae1 100644
|
|
281
|
+
--- a/ui/core/view/index.d.ts
|
|
282
|
+
+++ b/ui/core/view/index.d.ts
|
|
283
|
+
@@ -549,18 +549,20 @@ export abstract class View extends ViewCommon {
|
|
284
|
+
perspective: number;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
- * Gets or sets the translateX affine transform of the view in device independent pixels.
|
|
288
|
+
+ * Gets or sets the translateX affine transform of the view.
|
|
289
|
+
+ * Percentages are resolved against the view's own width.
|
|
290
|
+
*
|
|
291
|
+
* @nsProperty
|
|
292
|
+
*/
|
|
293
|
+
- translateX: CoreTypes.dip;
|
|
294
|
+
+ translateX: CoreTypes.PercentLengthType;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
- * Gets or sets the translateY affine transform of the view in device independent pixels.
|
|
298
|
+
+ * Gets or sets the translateY affine transform of the view.
|
|
299
|
+
+ * Percentages are resolved against the view's own height.
|
|
300
|
+
*
|
|
301
|
+
* @nsProperty
|
|
302
|
+
*/
|
|
303
|
+
- translateY: CoreTypes.dip;
|
|
304
|
+
+ translateY: CoreTypes.PercentLengthType;
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Gets or sets the scaleX affine transform of the view.
|
|
308
|
+
diff --git a/ui/core/view/index.ios.d.ts b/ui/core/view/index.ios.d.ts
|
|
309
|
+
index a63b36db5e1be012ba5595fa54e624a9bc13d196..9b19fbc49efbb93e6e185e0f1abab36992029377 100644
|
|
310
|
+
--- a/ui/core/view/index.ios.d.ts
|
|
311
|
+
+++ b/ui/core/view/index.ios.d.ts
|
|
312
|
+
@@ -51,9 +51,9 @@ export declare class View extends ViewCommon {
|
|
313
|
+
[scaleYProperty.getDefault]: () => number;
|
|
314
|
+
[scaleYProperty.setNative]: (value: number) => void;
|
|
315
|
+
[translateXProperty.getDefault]: () => CoreTypes.dip;
|
|
316
|
+
- [translateXProperty.setNative]: (value: CoreTypes.dip) => void;
|
|
317
|
+
+ [translateXProperty.setNative]: (value: CoreTypes.PercentLengthType) => void;
|
|
318
|
+
[translateYProperty.getDefault]: () => CoreTypes.dip;
|
|
319
|
+
- [translateYProperty.setNative]: (value: CoreTypes.dip) => void;
|
|
320
|
+
+ [translateYProperty.setNative]: (value: CoreTypes.PercentLengthType) => void;
|
|
321
|
+
[zIndexProperty.getDefault]: () => number;
|
|
322
|
+
[zIndexProperty.setNative]: (value: number) => void;
|
|
323
|
+
[backgroundInternalProperty.getDefault]: () => UIColor;
|
|
324
|
+
diff --git a/ui/core/view/index.ios.js b/ui/core/view/index.ios.js
|
|
325
|
+
index 9a2ed977caa7e80dd03ae2738620bbeb7972d236..c55989f928aaf9582f82d9a8f5f5a6d8c9679ac1 100644
|
|
326
|
+
--- a/ui/core/view/index.ios.js
|
|
327
|
+
+++ b/ui/core/view/index.ios.js
|
|
328
|
+
@@ -8,6 +8,7 @@ import { SDK_VERSION, supportsGlass } from '../../../utils/constants';
|
|
329
|
+
import { IOSHelper } from './view-helper';
|
|
330
|
+
import { ios as iosBackground } from '../../styling/background';
|
|
331
|
+
import { perspectiveProperty, visibilityProperty, opacityProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, directionProperty } from '../../styling/style-properties';
|
|
332
|
+
+import { isPercentTranslate, resolveTranslate } from '../../styling/css-transform';
|
|
333
|
+
import { profile } from '../../../profiling';
|
|
334
|
+
import { accessibilityEnabledProperty, accessibilityHiddenProperty, accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityLanguageProperty, accessibilityLiveRegionProperty, accessibilityMediaSessionProperty, accessibilityRoleProperty, accessibilityStateProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties';
|
|
335
|
+
import { IOSPostAccessibilityNotificationType } from '../../../accessibility';
|
|
336
|
+
@@ -332,6 +333,10 @@ export class View extends ViewCommon {
|
|
337
|
+
if (this._nativeBackgroundState === 'invalid' || (this._nativeBackgroundState === 'drawn' && backgroundDependsOnSize)) {
|
|
338
|
+
this._redrawNativeBackground(background);
|
|
339
|
+
}
|
|
340
|
+
+ // Percentage translates are resolved against the view's own size.
|
|
341
|
+
+ if (isPercentTranslate(this.translateX) || isPercentTranslate(this.translateY)) {
|
|
342
|
+
+ this.updateNativeTransform();
|
|
343
|
+
+ }
|
|
344
|
+
}
|
|
345
|
+
updateNativeTransform() {
|
|
346
|
+
const scaleX = this.scaleX || 1e-6;
|
|
347
|
+
@@ -343,7 +348,8 @@ export class View extends ViewCommon {
|
|
348
|
+
if (this.rotateX || this.rotateY) {
|
|
349
|
+
transform.m34 = -1 / perspective;
|
|
350
|
+
}
|
|
351
|
+
- transform = CATransform3DTranslate(transform, this.translateX, this.translateY, 0);
|
|
352
|
+
+ const bounds = nativeView.bounds.size;
|
|
353
|
+
+ transform = CATransform3DTranslate(transform, resolveTranslate(this.translateX, bounds.width), resolveTranslate(this.translateY, bounds.height), 0);
|
|
354
|
+
transform = iosUtils.applyRotateTransform(transform, this.rotateX, this.rotateY, this.rotate);
|
|
355
|
+
transform = CATransform3DScale(transform, scaleX, scaleY, 1);
|
|
356
|
+
if (!CATransform3DEqualToTransform(this.nativeViewProtected.layer.transform, transform)) {
|
|
357
|
+
diff --git a/ui/core/view/view-common.d.ts b/ui/core/view/view-common.d.ts
|
|
358
|
+
index e08bd0515f328334feb43be5c0a608099cc7efd3..5ab1064575441d664a6854f15d92b79d6bd122de 100644
|
|
359
|
+
--- a/ui/core/view/view-common.d.ts
|
|
360
|
+
+++ b/ui/core/view/view-common.d.ts
|
|
361
|
+
@@ -228,10 +228,10 @@ export declare abstract class ViewCommon extends ViewBase {
|
|
362
|
+
set perspective(value: number);
|
|
363
|
+
get textTransform(): CoreTypes.TextTransformType;
|
|
364
|
+
set textTransform(value: CoreTypes.TextTransformType);
|
|
365
|
+
- get translateX(): CoreTypes.dip;
|
|
366
|
+
- set translateX(value: CoreTypes.dip);
|
|
367
|
+
- get translateY(): CoreTypes.dip;
|
|
368
|
+
- set translateY(value: CoreTypes.dip);
|
|
369
|
+
+ get translateX(): CoreTypes.PercentLengthType;
|
|
370
|
+
+ set translateX(value: CoreTypes.PercentLengthType);
|
|
371
|
+
+ get translateY(): CoreTypes.PercentLengthType;
|
|
372
|
+
+ set translateY(value: CoreTypes.PercentLengthType);
|
|
373
|
+
get scaleX(): number;
|
|
374
|
+
set scaleX(value: number);
|
|
375
|
+
get scaleY(): number;
|
|
376
|
+
diff --git a/ui/core/view-base/index.d.ts b/ui/core/view-base/index.d.ts
|
|
377
|
+
index e60308ab6e5bdfd05f9ed4173933496b96e23e33..1aee75a717bc61eed76ed2882517ed33fef5c570 100644
|
|
378
|
+
--- a/ui/core/view-base/index.d.ts
|
|
379
|
+
+++ b/ui/core/view-base/index.d.ts
|
|
380
|
+
@@ -497,6 +497,12 @@ export declare abstract class ViewBase extends Observable {
|
|
381
|
+
* @param view to unload.
|
|
382
|
+
*/
|
|
383
|
+
unloadView(view: ViewBase): void;
|
|
384
|
+
+ /**
|
|
385
|
+
+ * Whether a child is the one currently shown. Containers that keep several children
|
|
386
|
+
+ * alive but show one at a time (a TabView's items) override it for the hidden ones.
|
|
387
|
+
+ * @param child A direct child of this view.
|
|
388
|
+
+ */
|
|
389
|
+
+ _isChildPresented(child: ViewBase): boolean;
|
|
390
|
+
/**
|
|
391
|
+
* Core logic for removing a child view from this instance. Used by the framework to handle lifecycle events more centralized. Do not use outside the UI Stack implementation.
|
|
392
|
+
*/
|
|
393
|
+
diff --git a/ui/core/view-base/index.js b/ui/core/view-base/index.js
|
|
394
|
+
index 0c25671db43f74551878c67a38a0b276e10880d4..524dfd7892bae5d8484dd86ae7153a95b8d1a6e3 100644
|
|
395
|
+
--- a/ui/core/view-base/index.js
|
|
396
|
+
+++ b/ui/core/view-base/index.js
|
|
397
|
+
@@ -633,6 +633,14 @@ export class ViewBase extends Observable {
|
|
398
|
+
view.callUnloaded();
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
+ /**
|
|
402
|
+
+ * Whether a child is the one currently shown. Containers that keep several children
|
|
403
|
+
+ * alive but show one at a time (a TabView's items) override it for the hidden ones.
|
|
404
|
+
+ * @param child A direct child of this view.
|
|
405
|
+
+ */
|
|
406
|
+
+ _isChildPresented(child) {
|
|
407
|
+
+ return true;
|
|
408
|
+
+ }
|
|
409
|
+
/**
|
|
410
|
+
* Core logic for removing a child view from this instance. Used by the framework to handle lifecycle events more centralized. Do not use outside the UI Stack implementation.
|
|
411
|
+
*/
|
|
412
|
+
diff --git a/ui/frame/frame-common.js b/ui/frame/frame-common.js
|
|
413
|
+
index f678538745fbc3b3fd78edf46ea702d8cc4e641b..28b261eafd9560a656a5549e4f718b77016af437 100644
|
|
414
|
+
--- a/ui/frame/frame-common.js
|
|
415
|
+
+++ b/ui/frame/frame-common.js
|
|
416
|
+
@@ -3,7 +3,7 @@ import { NavigationType } from './frame-interfaces';
|
|
417
|
+
import { CustomLayoutView, CSSType } from '../core/view';
|
|
418
|
+
import { Property } from '../core/properties';
|
|
419
|
+
import { Trace } from '../../trace';
|
|
420
|
+
-import { frameStack, topmost as frameStackTopmost, _pushInFrameStack, _popFromFrameStack, _removeFromFrameStack, _isFrameStackEmpty } from './frame-stack';
|
|
421
|
+
+import { frameStack, topmost as frameStackTopmost, _pushInFrameStack, _insertAtFrameStackBottom, _popFromFrameStack, _removeFromFrameStack, _isFrameStackEmpty } from './frame-stack';
|
|
422
|
+
import { viewMatchesModuleContext } from '../core/view/view-common';
|
|
423
|
+
import { getAncestor } from '../core/view-base';
|
|
424
|
+
import { Builder } from '../builder';
|
|
425
|
+
@@ -12,6 +12,19 @@ import { profile } from '../../profiling';
|
|
426
|
+
import { FRAME_SYMBOL } from './frame-helpers';
|
|
427
|
+
import { SharedTransition } from '../transition/shared-transition';
|
|
428
|
+
export { NavigationType } from './frame-interfaces';
|
|
429
|
+
+/**
|
|
430
|
+
+ * A view is presented while every ancestor shows the child leading to it; a frame in an
|
|
431
|
+
+ * unselected tab is loaded on Android but must never outrank the tab that is shown.
|
|
432
|
+
+ */
|
|
433
|
+
+function isPresented(view) {
|
|
434
|
+
+ while (view.parent) {
|
|
435
|
+
+ if (!view.parent._isChildPresented(view)) {
|
|
436
|
+
+ return false;
|
|
437
|
+
+ }
|
|
438
|
+
+ view = view.parent;
|
|
439
|
+
+ }
|
|
440
|
+
+ return true;
|
|
441
|
+
+}
|
|
442
|
+
function buildEntryFromArgs(arg) {
|
|
443
|
+
let entry;
|
|
444
|
+
if (typeof arg === 'string') {
|
|
445
|
+
@@ -466,7 +479,12 @@ let FrameBase = FrameBase_1 = class FrameBase extends CustomLayoutView {
|
|
446
|
+
return _isFrameStackEmpty();
|
|
447
|
+
}
|
|
448
|
+
_pushInFrameStack() {
|
|
449
|
+
- _pushInFrameStack(this);
|
|
450
|
+
+ if (isPresented(this)) {
|
|
451
|
+
+ _pushInFrameStack(this);
|
|
452
|
+
+ }
|
|
453
|
+
+ else {
|
|
454
|
+
+ _insertAtFrameStackBottom(this);
|
|
455
|
+
+ }
|
|
456
|
+
}
|
|
457
|
+
_popFromFrameStack() {
|
|
458
|
+
_popFromFrameStack(this);
|
|
459
|
+
diff --git a/ui/frame/frame-stack.d.ts b/ui/frame/frame-stack.d.ts
|
|
460
|
+
index 8387e6202380ec502adbc577c8de73e354ced9a9..0c874161af12d69ea4ced8f43d3e8a4d92032dcd 100644
|
|
461
|
+
--- a/ui/frame/frame-stack.d.ts
|
|
462
|
+
+++ b/ui/frame/frame-stack.d.ts
|
|
463
|
+
@@ -19,5 +19,6 @@ export declare function topmostForWindow(window: WindowBase): FrameBase | undefi
|
|
464
|
+
export declare function topmost(window?: WindowBase): FrameBase;
|
|
465
|
+
export declare function _isFrameStackEmpty(): boolean;
|
|
466
|
+
export declare function _pushInFrameStack(frame: FrameBase): void;
|
|
467
|
+
+export declare function _insertAtFrameStackBottom(frame: FrameBase): void;
|
|
468
|
+
export declare function _popFromFrameStack(frame: FrameBase): void;
|
|
469
|
+
export declare function _removeFromFrameStack(frame: FrameBase): void;
|
|
470
|
+
diff --git a/ui/frame/frame-stack.js b/ui/frame/frame-stack.js
|
|
471
|
+
index 9ded225f53e4c4af92166a3e019671a1a65a2db2..9a9f5d5f9f891c9bcf6035b0345f4bb21c72831c 100644
|
|
472
|
+
--- a/ui/frame/frame-stack.js
|
|
473
|
+
+++ b/ui/frame/frame-stack.js
|
|
474
|
+
@@ -46,6 +46,17 @@ export function _pushInFrameStack(frame) {
|
|
475
|
+
frameStack.push(frame);
|
|
476
|
+
frame._isInFrameStack = true;
|
|
477
|
+
}
|
|
478
|
+
+/**
|
|
479
|
+
+ * Keeps a frame in the stack without making it topmost: the frame stays findable by id,
|
|
480
|
+
+ * while every frame that is actually shown outranks it.
|
|
481
|
+
+ */
|
|
482
|
+
+export function _insertAtFrameStackBottom(frame) {
|
|
483
|
+
+ if (frame._isInFrameStack) {
|
|
484
|
+
+ return;
|
|
485
|
+
+ }
|
|
486
|
+
+ frameStack.unshift(frame);
|
|
487
|
+
+ frame._isInFrameStack = true;
|
|
488
|
+
+}
|
|
489
|
+
export function _popFromFrameStack(frame) {
|
|
490
|
+
if (!frame._isInFrameStack) {
|
|
491
|
+
return;
|
|
492
|
+
diff --git a/ui/index.d.ts b/ui/index.d.ts
|
|
493
|
+
index ef5209d97b83fadf0da672fc2677faa1d56199b6..b2eac9a30234e05ca859c0f664b77ca40f06793c 100644
|
|
494
|
+
--- a/ui/index.d.ts
|
|
495
|
+
+++ b/ui/index.d.ts
|
|
496
|
+
@@ -2,7 +2,7 @@ export { ActionBar, ActionItem, ActionItems, NavigationButton } from './action-b
|
|
497
|
+
export { ActivityIndicator } from './activity-indicator';
|
|
498
|
+
export { Animation, _resolveAnimationCurve } from './animation';
|
|
499
|
+
export { KeyframeAnimation, KeyframeAnimationInfo, KeyframeDeclaration, KeyframeInfo } from './animation/keyframe-animation';
|
|
500
|
+
-export type { AnimationDefinition, Pair, Transformation, TransformationType, TransformationValue, TransformFunctionsInfo, Point3D, AnimationPromise, Cancelable } from './animation/animation-types';
|
|
501
|
+
+export type { AnimationDefinition, Pair, TranslatePair, Transformation, TransformationType, TransformationValue, TransformFunctionsInfo, Point3D, AnimationPromise, Cancelable } from './animation/animation-types';
|
|
502
|
+
export * from './animation/animation-shared';
|
|
503
|
+
export { Builder } from './builder';
|
|
504
|
+
export type { LoadOptions } from './builder';
|
|
505
|
+
diff --git a/ui/layouts/flexbox-layout/flexbox-layout-common.js b/ui/layouts/flexbox-layout/flexbox-layout-common.js
|
|
506
|
+
index 54a037138b909446c71da47eb1cd682d5286fb18..64fa8712dae8260998f88eb26b053f5f48002c9e 100644
|
|
507
|
+
--- a/ui/layouts/flexbox-layout/flexbox-layout-common.js
|
|
508
|
+
+++ b/ui/layouts/flexbox-layout/flexbox-layout-common.js
|
|
509
|
+
@@ -193,7 +193,21 @@ let FlexboxLayoutBase = class FlexboxLayoutBase extends LayoutBase {
|
|
510
|
+
validateArgs(view).style.alignSelf = align;
|
|
511
|
+
}
|
|
512
|
+
static getAlignSelf(view) {
|
|
513
|
+
- return validateArgs(view).style.alignSelf;
|
|
514
|
+
+ const style = validateArgs(view).style;
|
|
515
|
+
+ const alignSelf = style.alignSelf;
|
|
516
|
+
+ if (alignSelf !== 'auto' && alignSelf !== 'stretch') {
|
|
517
|
+
+ return alignSelf;
|
|
518
|
+
+ }
|
|
519
|
+
+ const parent = view.parent;
|
|
520
|
+
+ if (!(parent instanceof FlexboxLayoutBase)) {
|
|
521
|
+
+ return alignSelf;
|
|
522
|
+
+ }
|
|
523
|
+
+ if (alignSelf === 'auto' && parent.alignItems !== 'stretch') {
|
|
524
|
+
+ return alignSelf;
|
|
525
|
+
+ }
|
|
526
|
+
+ const isRow = parent.flexDirection === 'row' || parent.flexDirection === 'row-reverse';
|
|
527
|
+
+ const crossSize = isRow ? style.height : style.width;
|
|
528
|
+
+ return crossSize == null || crossSize === 'auto' ? alignSelf : 'flex-start';
|
|
529
|
+
}
|
|
530
|
+
static setFlexWrapBefore(view, wrap) {
|
|
531
|
+
validateArgs(view).style.flexWrapBefore = wrap;
|
|
532
|
+
diff --git a/ui/layouts/flexbox-layout/index.android.js b/ui/layouts/flexbox-layout/index.android.js
|
|
533
|
+
index ed354fddfe1caf982e73b603798cb8f5bf0d3501..7191092e40ba07c3dc3e6555059dbda028418d9c 100644
|
|
534
|
+
--- a/ui/layouts/flexbox-layout/index.android.js
|
|
535
|
+
+++ b/ui/layouts/flexbox-layout/index.android.js
|
|
536
|
+
@@ -1,7 +1,7 @@
|
|
537
|
+
import { FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent, FlexboxLayoutBase, orderProperty, flexGrowProperty, flexShrinkProperty, flexWrapBeforeProperty, alignSelfProperty, AlignSelf, flexDirectionProperty, flexWrapProperty, justifyContentProperty, alignItemsProperty, alignContentProperty } from './flexbox-layout-common';
|
|
538
|
+
import { View } from '../../core/view';
|
|
539
|
+
import { Length } from '../../styling/length-shared';
|
|
540
|
+
-import { columnGapProperty, rowGapProperty } from '../../styling/style-properties';
|
|
541
|
+
+import { columnGapProperty, rowGapProperty, widthProperty, heightProperty } from '../../styling/style-properties';
|
|
542
|
+
export * from './flexbox-layout-common';
|
|
543
|
+
let widgetFlexboxLayout;
|
|
544
|
+
let widgetLayoutParams;
|
|
545
|
+
@@ -27,6 +27,25 @@ View.prototype[flexGrowProperty.setNative] = makeNativeSetter((lp, value) => (lp
|
|
546
|
+
View.prototype[flexShrinkProperty.setNative] = makeNativeSetter((lp, value) => (lp.flexShrink = value));
|
|
547
|
+
View.prototype[flexWrapBeforeProperty.setNative] = makeNativeSetter((lp, value) => (lp.wrapBefore = value));
|
|
548
|
+
View.prototype[alignSelfProperty.setNative] = makeNativeSetter((lp, value) => (lp.alignSelf = alignSelfMap[value]));
|
|
549
|
+
+function refreshFlexboxParent(child) {
|
|
550
|
+
+ const parent = child.parent;
|
|
551
|
+
+ if (parent instanceof FlexboxLayoutBase) {
|
|
552
|
+
+ parent._updateNativeLayoutParams(child);
|
|
553
|
+
+ }
|
|
554
|
+
+}
|
|
555
|
+
+function wrapChildLayoutProperty(property) {
|
|
556
|
+
+ const setter = View.prototype[property.setNative];
|
|
557
|
+
+ if (typeof setter !== 'function') {
|
|
558
|
+
+ return;
|
|
559
|
+
+ }
|
|
560
|
+
+ View.prototype[property.setNative] = function (value) {
|
|
561
|
+
+ setter.call(this, value);
|
|
562
|
+
+ refreshFlexboxParent(this);
|
|
563
|
+
+ };
|
|
564
|
+
+}
|
|
565
|
+
+wrapChildLayoutProperty(widthProperty);
|
|
566
|
+
+wrapChildLayoutProperty(heightProperty);
|
|
567
|
+
+wrapChildLayoutProperty(alignSelfProperty);
|
|
568
|
+
const flexDirectionMap = {
|
|
569
|
+
[FlexDirection.ROW]: 0, //FlexboxLayoutWidget.FLEX_DIRECTION_ROW,
|
|
570
|
+
[FlexDirection.ROW_REVERSE]: 1, //FlexboxLayoutWidget.FLEX_DIRECTION_ROW_REVERSE,
|
|
571
|
+
@@ -85,6 +104,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
|
|
572
|
+
}
|
|
573
|
+
[flexDirectionProperty.setNative](flexDirection) {
|
|
574
|
+
this.nativeViewProtected.setFlexDirection(flexDirectionMap[flexDirection]);
|
|
575
|
+
+ this.eachLayoutChild((child) => this._updateNativeLayoutParams(child));
|
|
576
|
+
}
|
|
577
|
+
[flexWrapProperty.getDefault]() {
|
|
578
|
+
return flexWrapProperty.defaultValue;
|
|
579
|
+
@@ -103,6 +123,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
|
|
580
|
+
}
|
|
581
|
+
[alignItemsProperty.setNative](alignItems) {
|
|
582
|
+
this.nativeViewProtected.setAlignItems(alignItemsMap[alignItems]);
|
|
583
|
+
+ this.eachLayoutChild((child) => this._updateNativeLayoutParams(child));
|
|
584
|
+
}
|
|
585
|
+
[alignContentProperty.getDefault]() {
|
|
586
|
+
return alignContentProperty.defaultValue;
|
|
587
|
+
@@ -136,7 +157,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
|
|
588
|
+
lp.flexGrow = style.flexGrow;
|
|
589
|
+
lp.flexShrink = style.flexShrink;
|
|
590
|
+
lp.wrapBefore = style.flexWrapBefore;
|
|
591
|
+
- lp.alignSelf = alignSelfMap[style.alignSelf];
|
|
592
|
+
+ lp.alignSelf = alignSelfMap[FlexboxLayoutBase.getAlignSelf(child)];
|
|
593
|
+
child.nativeViewProtected.setLayoutParams(lp);
|
|
594
|
+
}
|
|
595
|
+
_setChildMinWidthNative(child, value) {
|
|
596
|
+
diff --git a/ui/layouts/flexbox-layout/index.ios.js b/ui/layouts/flexbox-layout/index.ios.js
|
|
597
|
+
index d391d4213240cab9a5088f9d7937fab17e7c7e54..112a3dc9ca31471c7cbceb94f6ee22bc86181955 100644
|
|
598
|
+
--- a/ui/layouts/flexbox-layout/index.ios.js
|
|
599
|
+
+++ b/ui/layouts/flexbox-layout/index.ios.js
|
|
600
|
+
@@ -222,8 +222,8 @@ export class FlexboxLayout extends FlexboxLayoutBase {
|
|
601
|
+
if (FlexBasisPercent.DEFAULT /*lp.flexBasisPercent*/ !== FlexBasisPercent.DEFAULT && widthMode === EXACTLY) {
|
|
602
|
+
childWidth = Math.round(widthSize * FlexBasisPercent.DEFAULT /*lp.flexBasisPercent*/);
|
|
603
|
+
}
|
|
604
|
+
- const childWidthMeasureSpec = FlexboxLayout.getChildMeasureSpec(widthMeasureSpec, lp.effectivePaddingLeft + lp.effectivePaddingRight + lp.effectiveMarginLeft + lp.effectiveMarginRight, childWidth < 0 ? WRAP_CONTENT : childWidth);
|
|
605
|
+
- const childHeightMeasureSpec = FlexboxLayout.getChildMeasureSpec(heightMeasureSpec, lp.effectivePaddingTop + lp.effectivePaddingBottom + lp.effectiveMarginTop + lp.effectiveMarginBottom, lp.effectiveHeight < 0 ? WRAP_CONTENT : lp.effectiveHeight);
|
|
606
|
+
+ const childWidthMeasureSpec = FlexboxLayout.getChildMeasureSpec(widthMeasureSpec, this.effectivePaddingLeft + this.effectivePaddingRight + lp.effectiveMarginLeft + lp.effectiveMarginRight, childWidth < 0 ? WRAP_CONTENT : childWidth);
|
|
607
|
+
+ const childHeightMeasureSpec = FlexboxLayout.getChildMeasureSpec(heightMeasureSpec, this.effectivePaddingTop + this.effectivePaddingBottom + lp.effectiveMarginTop + lp.effectiveMarginBottom, lp.effectiveHeight < 0 ? WRAP_CONTENT : lp.effectiveHeight);
|
|
608
|
+
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
|
|
609
|
+
this._checkSizeConstraints(child);
|
|
610
|
+
childState = View.combineMeasuredStates(childState, child.getMeasuredState());
|
|
611
|
+
@@ -547,7 +547,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
|
|
612
|
+
// might result in increased height e.g. text that could be shown on one line for larger
|
|
613
|
+
// width needs to be wrapped in two when width is reduced.
|
|
614
|
+
// As a result we cannot unconditionally measure with EXACTLY the current measured height
|
|
615
|
+
- const childHeightMeasureSpec = FlexboxLayout.getChildMeasureSpec(this._currentHeightMeasureSpec, lp.effectivePaddingTop + lp.effectivePaddingBottom + lp.effectiveMarginTop + lp.effectiveMarginBottom, lp.effectiveHeight < 0 ? WRAP_CONTENT : lp.effectiveHeight);
|
|
616
|
+
+ const childHeightMeasureSpec = FlexboxLayout.getChildMeasureSpec(this._currentHeightMeasureSpec, this.effectivePaddingTop + this.effectivePaddingBottom + lp.effectiveMarginTop + lp.effectiveMarginBottom, lp.effectiveHeight < 0 ? WRAP_CONTENT : lp.effectiveHeight);
|
|
617
|
+
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
|
|
618
|
+
child.effectiveMinWidth = minWidth;
|
|
619
|
+
// make sure crossSize is up-to-date as child calculated height might have increased
|
|
620
|
+
@@ -758,7 +758,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
|
|
621
|
+
let newHeight = crossSize - view.effectiveMarginTop - view.effectiveMarginBottom;
|
|
622
|
+
newHeight = Math.max(newHeight, 0);
|
|
623
|
+
const originalMeasuredWidth = view.getMeasuredWidth();
|
|
624
|
+
- let childWidthMeasureSpec = FlexboxLayout.getChildMeasureSpec(this._currentWidthMeasureSpec, view.effectivePaddingLeft + view.effectivePaddingRight + view.effectiveMarginLeft + view.effectiveMarginRight, view.effectiveWidth < 0 ? WRAP_CONTENT : Math.min(view.effectiveWidth, originalMeasuredWidth));
|
|
625
|
+
+ let childWidthMeasureSpec = FlexboxLayout.getChildMeasureSpec(this._currentWidthMeasureSpec, this.effectivePaddingLeft + this.effectivePaddingRight + view.effectiveMarginLeft + view.effectiveMarginRight, view.effectiveWidth < 0 ? WRAP_CONTENT : Math.min(view.effectiveWidth, originalMeasuredWidth));
|
|
626
|
+
view.measure(childWidthMeasureSpec, makeMeasureSpec(newHeight, EXACTLY));
|
|
627
|
+
if (originalMeasuredWidth > view.getMeasuredWidth()) {
|
|
628
|
+
childWidthMeasureSpec = makeMeasureSpec(originalMeasuredWidth, EXACTLY);
|
|
629
|
+
diff --git a/ui/layouts/liquid-glass-container/index.ios.js b/ui/layouts/liquid-glass-container/index.ios.js
|
|
630
|
+
index f72d4a1f66520c71f4830abcb6f908ef04d00ad6..78e97694657babd46fd4900db2dda0b7906ab25c 100644
|
|
631
|
+
--- a/ui/layouts/liquid-glass-container/index.ios.js
|
|
632
|
+
+++ b/ui/layouts/liquid-glass-container/index.ios.js
|
|
633
|
+
@@ -1,5 +1,6 @@
|
|
634
|
+
import { supportsGlass } from '../../../utils/constants';
|
|
635
|
+
import { iosGlassEffectProperty } from '../../core/view';
|
|
636
|
+
+import { resolveTranslate } from '../../styling/css-transform';
|
|
637
|
+
import { LiquidGlassContainerCommon } from './liquid-glass-container-common';
|
|
638
|
+
import { toUIGlassStyle } from '../liquid-glass';
|
|
639
|
+
export class LiquidGlassContainer extends LiquidGlassContainerCommon {
|
|
640
|
+
@@ -123,13 +124,14 @@ export class LiquidGlassContainer extends LiquidGlassContainerCommon {
|
|
641
|
+
const child = this.getChildAt(i);
|
|
642
|
+
if (!child)
|
|
643
|
+
continue;
|
|
644
|
+
- const tx = child.translateX || 0;
|
|
645
|
+
- const ty = child.translateY || 0;
|
|
646
|
+
- if (!tx && !ty)
|
|
647
|
+
- continue;
|
|
648
|
+
const native = child.nativeViewProtected;
|
|
649
|
+
if (!native)
|
|
650
|
+
continue;
|
|
651
|
+
+ const bounds = native.bounds.size;
|
|
652
|
+
+ const tx = resolveTranslate(child.translateX, bounds.width);
|
|
653
|
+
+ const ty = resolveTranslate(child.translateY, bounds.height);
|
|
654
|
+
+ if (!tx && !ty)
|
|
655
|
+
+ continue;
|
|
656
|
+
// Skip if the child is still animating (unless forced)
|
|
657
|
+
if (!force) {
|
|
658
|
+
const keys = native.layer.animationKeys ? native.layer.animationKeys() : null;
|
|
659
|
+
diff --git a/ui/styling/background.ios.js b/ui/styling/background.ios.js
|
|
660
|
+
index ed4b6883680229ffd1aa92a7bbcba2d36f1efebc..3882cad9a8d17fb5b8a80a4795b0161bc2f82e28 100644
|
|
661
|
+
--- a/ui/styling/background.ios.js
|
|
662
|
+
+++ b/ui/styling/background.ios.js
|
|
663
|
+
@@ -197,8 +197,8 @@ export var ios;
|
|
664
|
+
bottomLeft: cappedRadius + spreadRadius,
|
|
665
|
+
bottomRight: cappedRadius + spreadRadius,
|
|
666
|
+
};
|
|
667
|
+
- innerPath = generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadii);
|
|
668
|
+
- shadowPath = generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadiiWithSpread, spreadRadius);
|
|
669
|
+
+ innerPath = generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadii, 0, background.cornerShape === CoreTypes.CornerShape.squircle);
|
|
670
|
+
+ shadowPath = generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadiiWithSpread, spreadRadius, background.cornerShape === CoreTypes.CornerShape.squircle);
|
|
671
|
+
}
|
|
672
|
+
else {
|
|
673
|
+
const outerTopLeftRadius = layout.toDeviceIndependentPixels(background.borderTopLeftRadius);
|
|
674
|
+
@@ -223,8 +223,8 @@ export var ios;
|
|
675
|
+
bottomLeft: cappedOuterRadii.bottomLeft > 0 ? cappedOuterRadii.bottomLeft + spreadRadius : cappedOuterRadii.bottomLeft,
|
|
676
|
+
bottomRight: cappedOuterRadii.bottomRight > 0 ? cappedOuterRadii.bottomRight + spreadRadius : cappedOuterRadii.bottomRight,
|
|
677
|
+
};
|
|
678
|
+
- innerPath = generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadii);
|
|
679
|
+
- shadowPath = generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadiiWithSpread, spreadRadius);
|
|
680
|
+
+ innerPath = generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadii, 0, background.cornerShape === CoreTypes.CornerShape.squircle);
|
|
681
|
+
+ shadowPath = generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadiiWithSpread, spreadRadius, background.cornerShape === CoreTypes.CornerShape.squircle);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
@@ -292,7 +292,7 @@ export var ios;
|
|
686
|
+
function generateNonUniformBorderOuterClipRoundedPath(view, bounds) {
|
|
687
|
+
const background = view.style.backgroundInternal;
|
|
688
|
+
const cappedOuterRadii = calculateNonUniformBorderCappedRadii(bounds, background);
|
|
689
|
+
- return generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadii);
|
|
690
|
+
+ return generateNonUniformBorderOuterClipPath(bounds, cappedOuterRadii, 0, background.cornerShape === CoreTypes.CornerShape.squircle);
|
|
691
|
+
}
|
|
692
|
+
ios.generateNonUniformBorderOuterClipRoundedPath = generateNonUniformBorderOuterClipRoundedPath;
|
|
693
|
+
function generateNonUniformMultiColorBorderRoundedPaths(view, bounds) {
|
|
694
|
+
@@ -626,7 +626,7 @@ function drawNonUniformBorders(nativeView, background) {
|
|
695
|
+
layer.cornerRadius = 0;
|
|
696
|
+
const cappedOuterRadii = calculateNonUniformBorderCappedRadii(layerBounds, background);
|
|
697
|
+
if (nativeView.maskType === iosViewUtils.LayerMask.BORDER && layer.mask instanceof CAShapeLayer) {
|
|
698
|
+
- layer.mask.path = generateNonUniformBorderOuterClipPath(layerBounds, cappedOuterRadii);
|
|
699
|
+
+ layer.mask.path = generateNonUniformBorderOuterClipPath(layerBounds, cappedOuterRadii, 0, background.cornerShape === CoreTypes.CornerShape.squircle);
|
|
700
|
+
}
|
|
701
|
+
if (background.hasBorderWidth()) {
|
|
702
|
+
if (!nativeView.hasNonUniformBorder) {
|
|
703
|
+
@@ -694,15 +694,57 @@ function calculateInnerBorderClipRadius(radius, insetX, insetY) {
|
|
704
|
+
maxRadius: innerMaxRadius,
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
+// Squircle corner curve — superellipse |x|^n + |y|^n = r^n with n=4, the
|
|
708
|
+
+// approximation of Apple's "continuous" corner that CSS `corner-shape:
|
|
709
|
+
+// squircle` specifies. Sampled as a short polyline per corner (the mask is
|
|
710
|
+
+// rasterized once per bounds change, so segment count doesn't matter at
|
|
711
|
+
+// screen scale).
|
|
712
|
+
+const SQUIRCLE_EXPONENT = 4;
|
|
713
|
+
+const SQUIRCLE_CORNER_STEPS = 12;
|
|
714
|
+
+/**
|
|
715
|
+
+ * Appends a straight line to the incoming tangent point, then a squircle
|
|
716
|
+
+ * quarter arc to the exit tangent — same semantics as CGPathAddArcToPoint.
|
|
717
|
+
+ *
|
|
718
|
+
+ * @param path
|
|
719
|
+
+ * @param t1x/t1y tangent point on the incoming edge
|
|
720
|
+
+ * @param t2x/t2y tangent point on the outgoing edge
|
|
721
|
+
+ * @param vx/vy corner vertex where the two edges would meet
|
|
722
|
+
+ */
|
|
723
|
+
+function addSquircleArcToPoint(path, t1x, t1y, t2x, t2y, vx, vy) {
|
|
724
|
+
+ CGPathAddLineToPoint(path, null, t1x, t1y);
|
|
725
|
+
+ // The corner-box corner opposite the vertex is the arc's center.
|
|
726
|
+
+ const cx = t1x + t2x - vx;
|
|
727
|
+
+ const cy = t1y + t2y - vy;
|
|
728
|
+
+ const e = 2 / SQUIRCLE_EXPONENT;
|
|
729
|
+
+ // t1 sits on a horizontal edge when its offset from the center is
|
|
730
|
+
+ // vertical; parametrize θ: 0 → π/2 so the polyline always runs t1 → t2.
|
|
731
|
+
+ if (Math.abs(t1y - cy) >= Math.abs(t1x - cx)) {
|
|
732
|
+
+ const ax = t2x - cx;
|
|
733
|
+
+ const ay = t1y - cy;
|
|
734
|
+
+ for (let i = 1; i <= SQUIRCLE_CORNER_STEPS; i++) {
|
|
735
|
+
+ const a = (i / SQUIRCLE_CORNER_STEPS) * (Math.PI / 2);
|
|
736
|
+
+ CGPathAddLineToPoint(path, null, cx + ax * Math.pow(Math.sin(a), e), cy + ay * Math.pow(Math.cos(a), e));
|
|
737
|
+
+ }
|
|
738
|
+
+ }
|
|
739
|
+
+ else {
|
|
740
|
+
+ const ax = t1x - cx;
|
|
741
|
+
+ const ay = t2y - cy;
|
|
742
|
+
+ for (let i = 1; i <= SQUIRCLE_CORNER_STEPS; i++) {
|
|
743
|
+
+ const a = (i / SQUIRCLE_CORNER_STEPS) * (Math.PI / 2);
|
|
744
|
+
+ CGPathAddLineToPoint(path, null, cx + ax * Math.pow(Math.cos(a), e), cy + ay * Math.pow(Math.sin(a), e));
|
|
745
|
+
+ }
|
|
746
|
+
+ }
|
|
747
|
+
+}
|
|
748
|
+
/**
|
|
749
|
+
* Generates a path that represents the rounded view area.
|
|
750
|
+
*
|
|
751
|
+
* @param bounds
|
|
752
|
+
* @param cappedRadii
|
|
753
|
+
* @param offset
|
|
754
|
+
+ * @param squircle draw corner arcs as squircles instead of circular arcs
|
|
755
|
+
* @returns
|
|
756
|
+
*/
|
|
757
|
+
-function generateNonUniformBorderOuterClipPath(bounds, cappedRadii, offset = 0) {
|
|
758
|
+
+function generateNonUniformBorderOuterClipPath(bounds, cappedRadii, offset = 0, squircle = false) {
|
|
759
|
+
const { width, height } = bounds.size;
|
|
760
|
+
const { x, y } = bounds.origin;
|
|
761
|
+
const left = x - offset;
|
|
762
|
+
@@ -711,10 +753,18 @@ function generateNonUniformBorderOuterClipPath(bounds, cappedRadii, offset = 0)
|
|
763
|
+
const bottom = y + height + offset;
|
|
764
|
+
const clipPath = CGPathCreateMutable();
|
|
765
|
+
CGPathMoveToPoint(clipPath, null, left + cappedRadii.topLeft, top);
|
|
766
|
+
- CGPathAddArcToPoint(clipPath, null, right, top, right, top + cappedRadii.topRight, cappedRadii.topRight);
|
|
767
|
+
- CGPathAddArcToPoint(clipPath, null, right, bottom, right - cappedRadii.bottomRight, bottom, cappedRadii.bottomRight);
|
|
768
|
+
- CGPathAddArcToPoint(clipPath, null, left, bottom, left, bottom - cappedRadii.bottomLeft, cappedRadii.bottomLeft);
|
|
769
|
+
- CGPathAddArcToPoint(clipPath, null, left, top, left + cappedRadii.topLeft, top, cappedRadii.topLeft);
|
|
770
|
+
+ if (squircle) {
|
|
771
|
+
+ addSquircleArcToPoint(clipPath, right - cappedRadii.topRight, top, right, top + cappedRadii.topRight, right, top);
|
|
772
|
+
+ addSquircleArcToPoint(clipPath, right, bottom - cappedRadii.bottomRight, right - cappedRadii.bottomRight, bottom, right, bottom);
|
|
773
|
+
+ addSquircleArcToPoint(clipPath, left + cappedRadii.bottomLeft, bottom, left, bottom - cappedRadii.bottomLeft, left, bottom);
|
|
774
|
+
+ addSquircleArcToPoint(clipPath, left, top + cappedRadii.topLeft, left + cappedRadii.topLeft, top, left, top);
|
|
775
|
+
+ }
|
|
776
|
+
+ else {
|
|
777
|
+
+ CGPathAddArcToPoint(clipPath, null, right, top, right, top + cappedRadii.topRight, cappedRadii.topRight);
|
|
778
|
+
+ CGPathAddArcToPoint(clipPath, null, right, bottom, right - cappedRadii.bottomRight, bottom, cappedRadii.bottomRight);
|
|
779
|
+
+ CGPathAddArcToPoint(clipPath, null, left, bottom, left, bottom - cappedRadii.bottomLeft, cappedRadii.bottomLeft);
|
|
780
|
+
+ CGPathAddArcToPoint(clipPath, null, left, top, left + cappedRadii.topLeft, top, cappedRadii.topLeft);
|
|
781
|
+
+ }
|
|
782
|
+
CGPathCloseSubpath(clipPath);
|
|
783
|
+
return clipPath;
|
|
784
|
+
}
|
|
785
|
+
@@ -747,6 +797,7 @@ function generateNonUniformBorderInnerClipPath(bounds, background, cappedOuterRa
|
|
786
|
+
const cappedBorderLeftWidth = borderLeftWidth && borderLeftWidth * Math.min(1, width / borderHWidth);
|
|
787
|
+
const clipPath = CGPathCreateMutable();
|
|
788
|
+
CGPathAddRect(clipPath, null, CGRectMake(x, y, width, height));
|
|
789
|
+
+ const squircle = background.cornerShape === CoreTypes.CornerShape.squircle;
|
|
790
|
+
// Inner clip paths
|
|
791
|
+
if (cappedBorderTopWidth > 0 || cappedBorderLeftWidth > 0) {
|
|
792
|
+
CGPathMoveToPoint(clipPath, null, position.left + cappedOuterRadii.topLeft, position.top + cappedBorderTopWidth);
|
|
793
|
+
@@ -756,32 +807,52 @@ function generateNonUniformBorderInnerClipPath(bounds, background, cappedOuterRa
|
|
794
|
+
}
|
|
795
|
+
if (cappedBorderTopWidth > 0 || cappedBorderRightWidth > 0) {
|
|
796
|
+
const { xRadius, yRadius, maxRadius } = calculateInnerBorderClipRadius(cappedOuterRadii.topRight, cappedBorderRightWidth, cappedBorderTopWidth);
|
|
797
|
+
- const innerTopRightTransform = CGAffineTransformMake(maxRadius && xRadius / maxRadius, 0, 0, maxRadius && yRadius / maxRadius, position.right - cappedBorderRightWidth - xRadius, position.top + cappedBorderTopWidth + yRadius);
|
|
798
|
+
- CGPathAddArc(clipPath, innerTopRightTransform, 0, 0, maxRadius, (Math.PI * 3) / 2, 0, false);
|
|
799
|
+
+ if (squircle) {
|
|
800
|
+
+ addSquircleArcToPoint(clipPath, position.right - cappedBorderRightWidth - xRadius, position.top + cappedBorderTopWidth, position.right - cappedBorderRightWidth, position.top + cappedBorderTopWidth + yRadius, position.right - cappedBorderRightWidth, position.top + cappedBorderTopWidth);
|
|
801
|
+
+ }
|
|
802
|
+
+ else {
|
|
803
|
+
+ const innerTopRightTransform = CGAffineTransformMake(maxRadius && xRadius / maxRadius, 0, 0, maxRadius && yRadius / maxRadius, position.right - cappedBorderRightWidth - xRadius, position.top + cappedBorderTopWidth + yRadius);
|
|
804
|
+
+ CGPathAddArc(clipPath, innerTopRightTransform, 0, 0, maxRadius, (Math.PI * 3) / 2, 0, false);
|
|
805
|
+
+ }
|
|
806
|
+
}
|
|
807
|
+
else {
|
|
808
|
+
CGPathAddLineToPoint(clipPath, null, position.right, position.top);
|
|
809
|
+
}
|
|
810
|
+
if (cappedBorderBottomWidth > 0 || cappedBorderRightWidth > 0) {
|
|
811
|
+
const { xRadius, yRadius, maxRadius } = calculateInnerBorderClipRadius(cappedOuterRadii.bottomRight, cappedBorderRightWidth, cappedBorderBottomWidth);
|
|
812
|
+
- const innerBottomRightTransform = CGAffineTransformMake(maxRadius && xRadius / maxRadius, 0, 0, maxRadius && yRadius / maxRadius, position.right - cappedBorderRightWidth - xRadius, position.bottom - cappedBorderBottomWidth - yRadius);
|
|
813
|
+
- CGPathAddArc(clipPath, innerBottomRightTransform, 0, 0, maxRadius, 0, Math.PI / 2, false);
|
|
814
|
+
+ if (squircle) {
|
|
815
|
+
+ addSquircleArcToPoint(clipPath, position.right - cappedBorderRightWidth, position.bottom - cappedBorderBottomWidth - yRadius, position.right - cappedBorderRightWidth - xRadius, position.bottom - cappedBorderBottomWidth, position.right - cappedBorderRightWidth, position.bottom - cappedBorderBottomWidth);
|
|
816
|
+
+ }
|
|
817
|
+
+ else {
|
|
818
|
+
+ const innerBottomRightTransform = CGAffineTransformMake(maxRadius && xRadius / maxRadius, 0, 0, maxRadius && yRadius / maxRadius, position.right - cappedBorderRightWidth - xRadius, position.bottom - cappedBorderBottomWidth - yRadius);
|
|
819
|
+
+ CGPathAddArc(clipPath, innerBottomRightTransform, 0, 0, maxRadius, 0, Math.PI / 2, false);
|
|
820
|
+
+ }
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
CGPathAddLineToPoint(clipPath, null, position.right, position.bottom);
|
|
824
|
+
}
|
|
825
|
+
if (cappedBorderBottomWidth > 0 || cappedBorderLeftWidth > 0) {
|
|
826
|
+
const { xRadius, yRadius, maxRadius } = calculateInnerBorderClipRadius(cappedOuterRadii.bottomLeft, cappedBorderLeftWidth, cappedBorderBottomWidth);
|
|
827
|
+
- const innerBottomLeftTransform = CGAffineTransformMake(maxRadius && xRadius / maxRadius, 0, 0, maxRadius && yRadius / maxRadius, position.left + cappedBorderLeftWidth + xRadius, position.bottom - cappedBorderBottomWidth - yRadius);
|
|
828
|
+
- CGPathAddArc(clipPath, innerBottomLeftTransform, 0, 0, maxRadius, Math.PI / 2, Math.PI, false);
|
|
829
|
+
+ if (squircle) {
|
|
830
|
+
+ addSquircleArcToPoint(clipPath, position.left + cappedBorderLeftWidth + xRadius, position.bottom - cappedBorderBottomWidth, position.left + cappedBorderLeftWidth, position.bottom - cappedBorderBottomWidth - yRadius, position.left + cappedBorderLeftWidth, position.bottom - cappedBorderBottomWidth);
|
|
831
|
+
+ }
|
|
832
|
+
+ else {
|
|
833
|
+
+ const innerBottomLeftTransform = CGAffineTransformMake(maxRadius && xRadius / maxRadius, 0, 0, maxRadius && yRadius / maxRadius, position.left + cappedBorderLeftWidth + xRadius, position.bottom - cappedBorderBottomWidth - yRadius);
|
|
834
|
+
+ CGPathAddArc(clipPath, innerBottomLeftTransform, 0, 0, maxRadius, Math.PI / 2, Math.PI, false);
|
|
835
|
+
+ }
|
|
836
|
+
}
|
|
837
|
+
else {
|
|
838
|
+
CGPathAddLineToPoint(clipPath, null, position.left, position.bottom);
|
|
839
|
+
}
|
|
840
|
+
if (cappedBorderTopWidth > 0 || cappedBorderLeftWidth > 0) {
|
|
841
|
+
const { xRadius, yRadius, maxRadius } = calculateInnerBorderClipRadius(cappedOuterRadii.topLeft, cappedBorderLeftWidth, cappedBorderTopWidth);
|
|
842
|
+
- const innerTopLeftTransform = CGAffineTransformMake(maxRadius && xRadius / maxRadius, 0, 0, maxRadius && yRadius / maxRadius, position.left + cappedBorderLeftWidth + xRadius, position.top + cappedBorderTopWidth + yRadius);
|
|
843
|
+
- CGPathAddArc(clipPath, innerTopLeftTransform, 0, 0, maxRadius, Math.PI, (Math.PI * 3) / 2, false);
|
|
844
|
+
+ if (squircle) {
|
|
845
|
+
+ addSquircleArcToPoint(clipPath, position.left + cappedBorderLeftWidth, position.top + cappedBorderTopWidth + yRadius, position.left + cappedBorderLeftWidth + xRadius, position.top + cappedBorderTopWidth, position.left + cappedBorderLeftWidth, position.top + cappedBorderTopWidth);
|
|
846
|
+
+ }
|
|
847
|
+
+ else {
|
|
848
|
+
+ const innerTopLeftTransform = CGAffineTransformMake(maxRadius && xRadius / maxRadius, 0, 0, maxRadius && yRadius / maxRadius, position.left + cappedBorderLeftWidth + xRadius, position.top + cappedBorderTopWidth + yRadius);
|
|
849
|
+
+ CGPathAddArc(clipPath, innerTopLeftTransform, 0, 0, maxRadius, Math.PI, (Math.PI * 3) / 2, false);
|
|
850
|
+
+ }
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
CGPathAddLineToPoint(clipPath, null, position.left, position.top);
|
|
854
|
+
diff --git a/ui/styling/css-selector.d.ts b/ui/styling/css-selector.d.ts
|
|
855
|
+
index 734d886877b867e69b36fd75785b0a4372008f0f..d90f0e4fcf0f136bf4e9b10f9b08cc14f9b73e32 100644
|
|
856
|
+
--- a/ui/styling/css-selector.d.ts
|
|
857
|
+
+++ b/ui/styling/css-selector.d.ts
|
|
858
|
+
@@ -222,6 +222,8 @@ export declare class RuleSet {
|
|
859
|
+
mediaQueryString: string | string[];
|
|
860
|
+
tag?: string | number;
|
|
861
|
+
scopedTag?: string;
|
|
862
|
+
+ /** Cascade-layer rank per nesting depth; undefined/shortest path sorts after every layer (unlayered styles win). */
|
|
863
|
+
+ layerPath?: number[];
|
|
864
|
+
constructor(selectors: SelectorCore[], declarations: Declaration[]);
|
|
865
|
+
toString(): string;
|
|
866
|
+
lookupSort(sorter: LookupSorter): void;
|
|
867
|
+
diff --git a/ui/styling/css-selector.js b/ui/styling/css-selector.js
|
|
868
|
+
index 702ca508f27ace527938860dfe4b13dbcbb93c2f..b6fa55a9570d4ed0714f053301bbe69efbd6900c 100644
|
|
869
|
+
--- a/ui/styling/css-selector.js
|
|
870
|
+
+++ b/ui/styling/css-selector.js
|
|
871
|
+
@@ -1081,9 +1081,27 @@ export class StyleSheetSelectorScope extends SelectorScope {
|
|
872
|
+
return matchSelectorCandidates(node, this.collectCandidates(node));
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
-/** Cascade order: specificity, then source order - (tier, position) across stylesheets. */
|
|
876
|
+
+/**
|
|
877
|
+
+ * Cascade layers order before specificity: rules in an earlier-declared layer lose
|
|
878
|
+
+ * to rules in a later-declared layer regardless of specificity, and unlayered
|
|
879
|
+
+ * rules (absent rank at a depth) beat every layered rule.
|
|
880
|
+
+ */
|
|
881
|
+
+function compareLayerPaths(a, b) {
|
|
882
|
+
+ const aLength = a?.length ?? 0;
|
|
883
|
+
+ const bLength = b?.length ?? 0;
|
|
884
|
+
+ const length = Math.max(aLength, bLength);
|
|
885
|
+
+ for (let i = 0; i < length; i++) {
|
|
886
|
+
+ const rankA = i < aLength ? a[i] : Number.POSITIVE_INFINITY;
|
|
887
|
+
+ const rankB = i < bLength ? b[i] : Number.POSITIVE_INFINITY;
|
|
888
|
+
+ if (rankA !== rankB) {
|
|
889
|
+
+ return rankA - rankB;
|
|
890
|
+
+ }
|
|
891
|
+
+ }
|
|
892
|
+
+ return 0;
|
|
893
|
+
+}
|
|
894
|
+
+/** Cascade order: cascade layer, then specificity, then source order - (tier, position) across stylesheets. */
|
|
895
|
+
function compareSelectors(a, b) {
|
|
896
|
+
- return a.specificity - b.specificity || a.tier - b.tier || a.pos - b.pos;
|
|
897
|
+
+ return compareLayerPaths(a.ruleset?.layerPath, b.ruleset?.layerPath) || a.specificity - b.specificity || a.tier - b.tier || a.pos - b.pos;
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* Resolve collected candidates against a node, compacting the array in place.
|
|
901
|
+
diff --git a/ui/styling/css-transform.d.ts b/ui/styling/css-transform.d.ts
|
|
902
|
+
index bf6a93847dc04ddf6d91a7912b033ab2ba93659e..b9a1e13824ec36c871c72acc53bdf3ff2de70180 100644
|
|
903
|
+
--- a/ui/styling/css-transform.d.ts
|
|
904
|
+
+++ b/ui/styling/css-transform.d.ts
|
|
905
|
+
@@ -1,2 +1,5 @@
|
|
906
|
+
import { TransformFunctionsInfo } from '../animation/animation-types';
|
|
907
|
+
+import type { CoreTypes } from '../../core-types';
|
|
908
|
+
export declare function transformConverter(text: string): TransformFunctionsInfo;
|
|
909
|
+
+export declare function isPercentTranslate(value: CoreTypes.PercentLengthType): boolean;
|
|
910
|
+
+export declare function resolveTranslate(value: CoreTypes.PercentLengthType, basis: number): CoreTypes.dip;
|
|
911
|
+
diff --git a/ui/styling/css-transform.js b/ui/styling/css-transform.js
|
|
912
|
+
index 181e6e370d64d1b18bf867eec6d3af4b3f7612b1..35ac4c45a7295cb3603b8c7781013890a6f472bd 100644
|
|
913
|
+
--- a/ui/styling/css-transform.js
|
|
914
|
+
+++ b/ui/styling/css-transform.js
|
|
915
|
+
@@ -1,3 +1,5 @@
|
|
916
|
+
+import { PercentLength } from './length-shared';
|
|
917
|
+
+import { layout } from '../../utils/layout-helper';
|
|
918
|
+
import { radiansToDegrees } from '../../utils/number-utils';
|
|
919
|
+
import { decompose2DTransformMatrix, getTransformMatrix, matrixArrayToCssMatrix, multiplyAffine2d } from '../../matrix';
|
|
920
|
+
import { hasDuplicates } from '../../utils';
|
|
921
|
+
@@ -8,6 +10,7 @@ const IDENTITY_TRANSFORMATION = {
|
|
922
|
+
};
|
|
923
|
+
const TRANSFORM_SPLITTER = new RegExp(/\s*(.+?)\((.*?)\)/g);
|
|
924
|
+
const TRANSFORMATIONS = Object.freeze(['rotate', 'rotateX', 'rotateY', 'rotate3d', 'translate', 'translate3d', 'translateX', 'translateY', 'scale', 'scale3d', 'scaleX', 'scaleY']);
|
|
925
|
+
+const TRANSLATE_TRANSFORMATIONS = Object.freeze(['translate', 'translate3d', 'translateX', 'translateY']);
|
|
926
|
+
const STYLE_TRANSFORMATION_MAP = Object.freeze({
|
|
927
|
+
scale: (value) => ({ property: 'scale', value }),
|
|
928
|
+
scale3d: (value) => ({ property: 'scale', value }),
|
|
929
|
+
@@ -60,7 +63,18 @@ export function transformConverter(text) {
|
|
930
|
+
if (text === 'none' || text === '' || !transformations.length) {
|
|
931
|
+
return IDENTITY_TRANSFORMATION;
|
|
932
|
+
}
|
|
933
|
+
- const usedTransforms = transformations.map((t) => t.property);
|
|
934
|
+
+ let usedTransforms = transformations.map((t) => t.property);
|
|
935
|
+
+ if (hasDuplicates(usedTransforms)) {
|
|
936
|
+
+ // Percent translate values can't be resolved to a concrete value at
|
|
937
|
+
+ // parse time (they depend on the view's size), so duplicate translate
|
|
938
|
+
+ // functions are merged axis-wise instead of going through the matrix
|
|
939
|
+
+ // multiplication below.
|
|
940
|
+
+ const duplicated = usedTransforms.filter((property, index) => usedTransforms.indexOf(property) !== index);
|
|
941
|
+
+ if (duplicated.every((property) => property === 'translate')) {
|
|
942
|
+
+ mergeTranslateTransformations(transformations);
|
|
943
|
+
+ usedTransforms = transformations.map((t) => t.property);
|
|
944
|
+
+ }
|
|
945
|
+
+ }
|
|
946
|
+
if (!hasDuplicates(usedTransforms)) {
|
|
947
|
+
const fullTransformations = { ...IDENTITY_TRANSFORMATION };
|
|
948
|
+
transformations.forEach((transform) => {
|
|
949
|
+
@@ -68,10 +82,39 @@ export function transformConverter(text) {
|
|
950
|
+
});
|
|
951
|
+
return fullTransformations;
|
|
952
|
+
}
|
|
953
|
+
- const affineMatrix = transformations.map(getTransformMatrix).reduce(multiplyAffine2d);
|
|
954
|
+
+ const affineMatrix = transformations.map(normalizeTransformation).map(getTransformMatrix).reduce(multiplyAffine2d);
|
|
955
|
+
const cssMatrix = matrixArrayToCssMatrix(affineMatrix);
|
|
956
|
+
return decompose2DTransformMatrix(cssMatrix);
|
|
957
|
+
}
|
|
958
|
+
+/**
|
|
959
|
+
+ * Whether a translate value is a percentage that has to be resolved
|
|
960
|
+
+ * against the element's own size.
|
|
961
|
+
+ */
|
|
962
|
+
+export function isPercentTranslate(value) {
|
|
963
|
+
+ return typeof value === 'object' && value !== null && value.unit === '%';
|
|
964
|
+
+}
|
|
965
|
+
+/**
|
|
966
|
+
+ * Resolves a translate axis value to dips. Percentage units are resolved
|
|
967
|
+
+ * against the given basis, which is the element's own size along that axis.
|
|
968
|
+
+ * @param value The translate axis value as a PercentLengthType.
|
|
969
|
+
+ * @param basis The element's size in dips along the translated axis.
|
|
970
|
+
+ */
|
|
971
|
+
+export function resolveTranslate(value, basis) {
|
|
972
|
+
+ if (typeof value === 'number') {
|
|
973
|
+
+ return value;
|
|
974
|
+
+ }
|
|
975
|
+
+ if (typeof value !== 'object' || value === null) {
|
|
976
|
+
+ return 0;
|
|
977
|
+
+ }
|
|
978
|
+
+ switch (value.unit) {
|
|
979
|
+
+ case 'px':
|
|
980
|
+
+ return layout.toDeviceIndependentPixels(value.value);
|
|
981
|
+
+ case '%':
|
|
982
|
+
+ return basis * value.value;
|
|
983
|
+
+ default:
|
|
984
|
+
+ return value.value;
|
|
985
|
+
+ }
|
|
986
|
+
+}
|
|
987
|
+
function isTransformType(propertyName) {
|
|
988
|
+
return TRANSFORMATIONS.indexOf(propertyName) !== -1;
|
|
989
|
+
}
|
|
990
|
+
@@ -91,20 +134,78 @@ function parseTransformString(text) {
|
|
991
|
+
return matches;
|
|
992
|
+
}
|
|
993
|
+
function convertTransformValue(property, rawValue) {
|
|
994
|
+
+ if (property === 'rotate' || property === 'rotateX' || property === 'rotateY') {
|
|
995
|
+
+ const x = parseFloat(rawValue);
|
|
996
|
+
+ return rawValue.slice(-3) === 'rad' ? radiansToDegrees(x) : x;
|
|
997
|
+
+ }
|
|
998
|
+
+ if (TRANSLATE_TRANSFORMATIONS.indexOf(property) !== -1) {
|
|
999
|
+
+ const values = rawValue.split(',').map(PercentLength.parse);
|
|
1000
|
+
+ const x = values[0];
|
|
1001
|
+
+ const y = property === 'translate' ? (values[1] ?? IDENTITY_TRANSFORMATION.translate.y) : (values[1] ?? x);
|
|
1002
|
+
+ return { x, y };
|
|
1003
|
+
+ }
|
|
1004
|
+
const values = rawValue.split(',').map(parseFloat);
|
|
1005
|
+
const x = values[0];
|
|
1006
|
+
- let y = values[1];
|
|
1007
|
+
- let z = values[2];
|
|
1008
|
+
- if (property === 'translate') {
|
|
1009
|
+
- y ?? (y = IDENTITY_TRANSFORMATION.translate.y);
|
|
1010
|
+
+ const y = values[1] ?? x;
|
|
1011
|
+
+ const z = values[2] ?? y;
|
|
1012
|
+
+ return { x, y, z };
|
|
1013
|
+
+}
|
|
1014
|
+
+function mergeTranslateTransformations(transformations) {
|
|
1015
|
+
+ const xValues = [];
|
|
1016
|
+
+ const yValues = [];
|
|
1017
|
+
+ for (let i = transformations.length - 1; i >= 0; i--) {
|
|
1018
|
+
+ const transformation = transformations[i];
|
|
1019
|
+
+ if (transformation.property === 'translate') {
|
|
1020
|
+
+ const value = transformation.value;
|
|
1021
|
+
+ xValues.unshift(value.x);
|
|
1022
|
+
+ yValues.unshift(value.y);
|
|
1023
|
+
+ transformations.splice(i, 1);
|
|
1024
|
+
+ }
|
|
1025
|
+
}
|
|
1026
|
+
- else {
|
|
1027
|
+
- y ?? (y = x);
|
|
1028
|
+
- z ?? (z = y);
|
|
1029
|
+
+ transformations.unshift({ property: 'translate', value: { x: mergeTranslateAxis(xValues), y: mergeTranslateAxis(yValues) } });
|
|
1030
|
+
+}
|
|
1031
|
+
+function mergeTranslateAxis(values) {
|
|
1032
|
+
+ const nonZero = values.filter((value) => !isZeroTranslate(value));
|
|
1033
|
+
+ if (nonZero.length === 0) {
|
|
1034
|
+
+ return 0;
|
|
1035
|
+
}
|
|
1036
|
+
- if (property === 'rotate' || property === 'rotateX' || property === 'rotateY') {
|
|
1037
|
+
- return rawValue.slice(-3) === 'rad' ? radiansToDegrees(x) : x;
|
|
1038
|
+
+ if (nonZero.length === 1) {
|
|
1039
|
+
+ return nonZero[0];
|
|
1040
|
+
}
|
|
1041
|
+
- return { x, y, z };
|
|
1042
|
+
+ // Values in the same unit can be summed without losing the unit.
|
|
1043
|
+
+ const unit = typeof nonZero[0] === 'object' && nonZero[0] !== null ? nonZero[0].unit : null;
|
|
1044
|
+
+ if (unit !== null && nonZero.every((value) => typeof value === 'object' && value !== null && value.unit === unit)) {
|
|
1045
|
+
+ return { unit, value: nonZero.reduce((sum, value) => sum + value.value, 0) };
|
|
1046
|
+
+ }
|
|
1047
|
+
+ // Mixed units can't be combined into a single static value; coerce them
|
|
1048
|
+
+ // to their numeric value like the old parseFloat-based parsing did.
|
|
1049
|
+
+ return nonZero.reduce((sum, value) => sum + translateValueToNumber(value), 0);
|
|
1050
|
+
+}
|
|
1051
|
+
+function isZeroTranslate(value) {
|
|
1052
|
+
+ if (typeof value === 'number') {
|
|
1053
|
+
+ return value === 0;
|
|
1054
|
+
+ }
|
|
1055
|
+
+ if (typeof value !== 'object' || value === null) {
|
|
1056
|
+
+ return true;
|
|
1057
|
+
+ }
|
|
1058
|
+
+ return value.value === 0;
|
|
1059
|
+
+}
|
|
1060
|
+
+function translateValueToNumber(value) {
|
|
1061
|
+
+ if (typeof value === 'number') {
|
|
1062
|
+
+ return value;
|
|
1063
|
+
+ }
|
|
1064
|
+
+ if (typeof value !== 'object' || value === null) {
|
|
1065
|
+
+ return 0;
|
|
1066
|
+
+ }
|
|
1067
|
+
+ // A % value stores its fraction (e.g. -50% => -0.5); the pre-unit-aware
|
|
1068
|
+
+ // parser produced the raw number (-50), which matrix composition keeps.
|
|
1069
|
+
+ return value.unit === '%' ? value.value * 100 : value.value;
|
|
1070
|
+
+}
|
|
1071
|
+
+function normalizeTransformation(transformation) {
|
|
1072
|
+
+ if (transformation.property === 'translate') {
|
|
1073
|
+
+ const { x, y } = transformation.value;
|
|
1074
|
+
+ return { property: 'translate', value: { x: translateValueToNumber(x), y: translateValueToNumber(y) } };
|
|
1075
|
+
+ }
|
|
1076
|
+
+ return transformation;
|
|
1077
|
+
}
|
|
1078
|
+
//# sourceMappingURL=css-transform.js.map
|
|
1079
|
+
|
|
1080
|
+
diff --git a/ui/styling/font.android.js b/ui/styling/font.android.js
|
|
1081
|
+
index a275f112af0ef85433c983cbce31f043b3aa7599..c270115eeb24a2fbf4d33eea08e6dca8fbd5df4e 100644
|
|
1082
|
+
--- a/ui/styling/font.android.js
|
|
1083
|
+
+++ b/ui/styling/font.android.js
|
|
1084
|
+
@@ -38,7 +38,7 @@ export class Font extends FontBase {
|
|
1085
|
+
Font.default = new Font(undefined, undefined);
|
|
1086
|
+
function computeFontCacheKey(fontFamily, font) {
|
|
1087
|
+
const sep = ':';
|
|
1088
|
+
- return [fontFamily, String(FontVariationSettings.toString(font.fontVariationSettings)).replace(/'/g, '').replace(/[\s,]/g, '_')].join(sep);
|
|
1089
|
+
+ return [fontFamily, String(getNumericFontWeight(font.fontWeight)), String(FontVariationSettings.toString(font.fontVariationSettings)).replace(/'/g, '').replace(/[\s,]/g, '_')].join(sep);
|
|
1090
|
+
}
|
|
1091
|
+
function loadFontFromFile(fontFamily, font) {
|
|
1092
|
+
const cacheKey = SDK_VERSION >= 26 ? computeFontCacheKey(fontFamily, font) : fontFamily;
|
|
1093
|
+
@@ -71,8 +71,26 @@ function loadFontFromFile(fontFamily, font) {
|
|
1094
|
+
if (SDK_VERSION >= 26) {
|
|
1095
|
+
const builder = new android.graphics.Typeface.Builder(fontAssetPath);
|
|
1096
|
+
if (builder) {
|
|
1097
|
+
- builder.setFontVariationSettings(font.fontVariationSettings?.length ? FontVariationSettings.toString(font.fontVariationSettings) : '');
|
|
1098
|
+
- result = builder.build();
|
|
1099
|
+
+ const explicitSettings = FontVariationSettings.toString(font.fontVariationSettings) || '';
|
|
1100
|
+
+ const variationSettings = font.fontVariationSettings?.length ? [...font.fontVariationSettings] : [];
|
|
1101
|
+
+ const hasWeightAxis = variationSettings.some(({ axis }) => axis.toLowerCase() === 'wght');
|
|
1102
|
+
+ if (!hasWeightAxis) {
|
|
1103
|
+
+ variationSettings.push({ axis: 'wght', value: getNumericFontWeight(font.fontWeight) });
|
|
1104
|
+
+ }
|
|
1105
|
+
+ try {
|
|
1106
|
+
+ builder.setFontVariationSettings(FontVariationSettings.toString(variationSettings) || '');
|
|
1107
|
+
+ result = builder.build();
|
|
1108
|
+
+ }
|
|
1109
|
+
+ catch (e) {
|
|
1110
|
+
+ if (hasWeightAxis) {
|
|
1111
|
+
+ throw e;
|
|
1112
|
+
+ }
|
|
1113
|
+
+ }
|
|
1114
|
+
+ if (!result && !hasWeightAxis) {
|
|
1115
|
+
+ const fallbackBuilder = new android.graphics.Typeface.Builder(fontAssetPath);
|
|
1116
|
+
+ fallbackBuilder.setFontVariationSettings(explicitSettings);
|
|
1117
|
+
+ result = fallbackBuilder.build();
|
|
1118
|
+
+ }
|
|
1119
|
+
}
|
|
1120
|
+
else {
|
|
1121
|
+
result = android.graphics.Typeface.createFromFile(fontAssetPath);
|
|
1122
|
+
diff --git a/ui/styling/style/index.d.ts b/ui/styling/style/index.d.ts
|
|
1123
|
+
index 6146930bd639001c4f27bc80cbf6237f0abb43bd..05259a5a3d4483900da37debea6a3fcbb48d02d2 100644
|
|
1124
|
+
--- a/ui/styling/style/index.d.ts
|
|
1125
|
+
+++ b/ui/styling/style/index.d.ts
|
|
1126
|
+
@@ -52,8 +52,8 @@ export declare class Style extends Observable {
|
|
1127
|
+
perspective: number;
|
|
1128
|
+
scaleX: number;
|
|
1129
|
+
scaleY: number;
|
|
1130
|
+
- translateX: CoreTypes.dip;
|
|
1131
|
+
- translateY: CoreTypes.dip;
|
|
1132
|
+
+ translateX: CoreTypes.PercentLengthType;
|
|
1133
|
+
+ translateY: CoreTypes.PercentLengthType;
|
|
1134
|
+
clipPath: string | ClipPathFunction;
|
|
1135
|
+
color: Color;
|
|
1136
|
+
tintColor: Color;
|
|
1137
|
+
diff --git a/ui/styling/style-properties.d.ts b/ui/styling/style-properties.d.ts
|
|
1138
|
+
index 4d4b15f1397bca6403029acb6615a40f872419b9..6c930a1de6e3f4d28371f94e9eb7fcb57d0df4dd 100644
|
|
1139
|
+
--- a/ui/styling/style-properties.d.ts
|
|
1140
|
+
+++ b/ui/styling/style-properties.d.ts
|
|
1141
|
+
@@ -31,8 +31,8 @@ export declare const rotateYProperty: CssAnimationProperty<Style, number>;
|
|
1142
|
+
export declare const perspectiveProperty: CssAnimationProperty<Style, number>;
|
|
1143
|
+
export declare const scaleXProperty: CssAnimationProperty<Style, number>;
|
|
1144
|
+
export declare const scaleYProperty: CssAnimationProperty<Style, number>;
|
|
1145
|
+
-export declare const translateXProperty: CssAnimationProperty<Style, CoreTypes.FixedLengthType>;
|
|
1146
|
+
-export declare const translateYProperty: CssAnimationProperty<Style, CoreTypes.FixedLengthType>;
|
|
1147
|
+
+export declare const translateXProperty: CssAnimationProperty<Style, CoreTypes.PercentLengthType>;
|
|
1148
|
+
+export declare const translateYProperty: CssAnimationProperty<Style, CoreTypes.PercentLengthType>;
|
|
1149
|
+
export declare const backgroundInternalProperty: CssProperty<Style, Background>;
|
|
1150
|
+
export declare const backgroundImageProperty: CssProperty<Style, string | LinearGradient>;
|
|
1151
|
+
export declare const backgroundColorProperty: CssAnimationProperty<Style, Color>;
|
|
1152
|
+
diff --git a/ui/styling/style-properties.js b/ui/styling/style-properties.js
|
|
1153
|
+
index 0f34471ac6f2fa146dafdd23e3c4290864c11c1b..95214a3c4ff5a40eff8af44e61888db02e78d448 100644
|
|
1154
|
+
--- a/ui/styling/style-properties.js
|
|
1155
|
+
+++ b/ui/styling/style-properties.js
|
|
1156
|
+
@@ -6,7 +6,7 @@ import { Font, parseFont, FontStyle, FontWeight, FontVariationSettings } from '.
|
|
1157
|
+
import { Background } from './background';
|
|
1158
|
+
import { Trace } from '../../trace';
|
|
1159
|
+
import { CoreTypes } from '../../core-types';
|
|
1160
|
+
-import { Length, FixedLength, PercentLength } from './length-shared';
|
|
1161
|
+
+import { Length, PercentLength } from './length-shared';
|
|
1162
|
+
import { parseBackground } from '../../css/parser';
|
|
1163
|
+
import { LinearGradient } from './linear-gradient';
|
|
1164
|
+
import { parseCSSShadow } from './css-shadow';
|
|
1165
|
+
@@ -564,16 +564,16 @@ export const translateXProperty = new CssAnimationProperty({
|
|
1166
|
+
name: 'translateX',
|
|
1167
|
+
cssName: 'translateX',
|
|
1168
|
+
defaultValue: 0,
|
|
1169
|
+
- equalityComparer: FixedLength.equals,
|
|
1170
|
+
- valueConverter: FixedLength.parse,
|
|
1171
|
+
+ equalityComparer: PercentLength.equals,
|
|
1172
|
+
+ valueConverter: PercentLength.parse,
|
|
1173
|
+
});
|
|
1174
|
+
translateXProperty.register(Style);
|
|
1175
|
+
export const translateYProperty = new CssAnimationProperty({
|
|
1176
|
+
name: 'translateY',
|
|
1177
|
+
cssName: 'translateY',
|
|
1178
|
+
defaultValue: 0,
|
|
1179
|
+
- equalityComparer: FixedLength.equals,
|
|
1180
|
+
- valueConverter: FixedLength.parse,
|
|
1181
|
+
+ equalityComparer: PercentLength.equals,
|
|
1182
|
+
+ valueConverter: PercentLength.parse,
|
|
1183
|
+
});
|
|
1184
|
+
translateYProperty.register(Style);
|
|
1185
|
+
const transformProperty = new ShorthandProperty({
|
|
1186
|
+
@@ -589,7 +589,7 @@ const transformProperty = new ShorthandProperty({
|
|
1187
|
+
const rotateY = this.rotateY;
|
|
1188
|
+
let result = '';
|
|
1189
|
+
if (translateX !== 0 || translateY !== 0) {
|
|
1190
|
+
- result += `translate(${translateX}, ${translateY}) `;
|
|
1191
|
+
+ result += `translate(${PercentLength.convertToString(translateX)}, ${PercentLength.convertToString(translateY)}) `;
|
|
1192
|
+
}
|
|
1193
|
+
if (scaleX !== 1 || scaleY !== 1) {
|
|
1194
|
+
result += `scale(${scaleX}, ${scaleY}) `;
|
|
1195
|
+
diff --git a/ui/styling/style-scope.d.ts b/ui/styling/style-scope.d.ts
|
|
1196
|
+
index d6f026616cc33cf02f312a5e4f3b6effd71b5dda..321217d036b2fc726c88bf2076d82dcc62e6917e 100644
|
|
1197
|
+
--- a/ui/styling/style-scope.d.ts
|
|
1198
|
+
+++ b/ui/styling/style-scope.d.ts
|
|
1199
|
+
@@ -8,7 +8,7 @@ import { Keyframes, KeyframeAnimationInfo, KeyframeAnimation } from '../animatio
|
|
1200
|
+
*/
|
|
1201
|
+
export declare function mergeCssSelectors(): void;
|
|
1202
|
+
export declare function mergeCssKeyframes(): void;
|
|
1203
|
+
-export declare function _populateRules(nodes: ReworkCSS.Node[], rulesets: RuleSet[], keyframes: Keyframes[], mediaQueryString?: string | string[]): void;
|
|
1204
|
+
+export declare function _populateRules(nodes: ReworkCSS.Node[], rulesets: RuleSet[], keyframes: Keyframes[], mediaQueryString?: string | string[], layerPath?: number[], layerPrefix?: string): void;
|
|
1205
|
+
export declare function removeTaggedAdditionalCSS(tag: string | number): boolean;
|
|
1206
|
+
export declare function addTaggedAdditionalCSS(cssText: string, tag?: string | number): boolean;
|
|
1207
|
+
export declare const loadAppCSS: any;
|
|
1208
|
+
diff --git a/ui/styling/style-scope.js b/ui/styling/style-scope.js
|
|
1209
|
+
index e75c7c8010e23917a7138c7351243aab0bad1f49..7cf9244c0290a76b186c15f13cc94ca754dfa9bb 100644
|
|
1210
|
+
--- a/ui/styling/style-scope.js
|
|
1211
|
+
+++ b/ui/styling/style-scope.js
|
|
1212
|
+
@@ -344,6 +344,33 @@ __decorate([
|
|
1213
|
+
__metadata("design:paramtypes", [String, String]),
|
|
1214
|
+
__metadata("design:returntype", String)
|
|
1215
|
+
], CSSSource, "resolveCSSPathFromURL", null);
|
|
1216
|
+
+// Cascade-layer registry: qualified name -> first-seen ordinal, shared across
|
|
1217
|
+
+// every stylesheet feeding the cascade (layer order is document-wide per spec).
|
|
1218
|
+
+// '~' synthesizes names for anonymous layers, which authors cannot reference —
|
|
1219
|
+
+// the char is illegal in a CSS ident, so they never collide with named layers.
|
|
1220
|
+
+const cascadeLayerOrdinals = new Map();
|
|
1221
|
+
+let cascadeLayerCount = 0;
|
|
1222
|
+
+let anonymousLayerCount = 0;
|
|
1223
|
+
+function layerOrdinal(name) {
|
|
1224
|
+
+ let ordinal = cascadeLayerOrdinals.get(name);
|
|
1225
|
+
+ if (ordinal === undefined) {
|
|
1226
|
+
+ ordinal = cascadeLayerCount++;
|
|
1227
|
+
+ cascadeLayerOrdinals.set(name, ordinal);
|
|
1228
|
+
+ }
|
|
1229
|
+
+ return ordinal;
|
|
1230
|
+
+}
|
|
1231
|
+
+// Rank path for `name` nested under the layer at prefixPath/prefixName. Dotted
|
|
1232
|
+
+// names register each ancestor on the way down, so a top-level `@layer a.b`
|
|
1233
|
+
+// refers to the same layer as `@layer a { @layer b }`.
|
|
1234
|
+
+function layerPathFor(name, prefixPath, prefixName) {
|
|
1235
|
+
+ const path = [...prefixPath];
|
|
1236
|
+
+ let qualified = prefixName;
|
|
1237
|
+
+ for (const segment of name.split('.')) {
|
|
1238
|
+
+ qualified = qualified ? `${qualified}.${segment}` : segment;
|
|
1239
|
+
+ path.push(layerOrdinal(qualified));
|
|
1240
|
+
+ }
|
|
1241
|
+
+ return path;
|
|
1242
|
+
+}
|
|
1243
|
+
function populateRulesFromImports(nodes, rulesets, keyframes) {
|
|
1244
|
+
const imports = nodes.filter((r) => r.type === 'import');
|
|
1245
|
+
if (!imports.length) {
|
|
1246
|
+
@@ -354,6 +381,11 @@ function populateRulesFromImports(nodes, rulesets, keyframes) {
|
|
1247
|
+
const urlMatch = importItem && importItem.match(pattern);
|
|
1248
|
+
return urlMatch && urlMatch[2];
|
|
1249
|
+
};
|
|
1250
|
+
+ const layerFromImportObject = (importObject) => {
|
|
1251
|
+
+ const importItem = importObject['import'];
|
|
1252
|
+
+ const layerMatch = importItem && importItem.match(/\blayer\b(?:\(\s*([^)]*?)\s*\))?/);
|
|
1253
|
+
+ return layerMatch ? layerMatch[1] ?? '' : null;
|
|
1254
|
+
+ };
|
|
1255
|
+
const sourceFromImportObject = (importObject) => importObject['position'] && importObject['position']['source'];
|
|
1256
|
+
const toUrlSourcePair = (importObject) => ({
|
|
1257
|
+
url: urlFromImportObject(importObject),
|
|
1258
|
+
@@ -361,17 +393,25 @@ function populateRulesFromImports(nodes, rulesets, keyframes) {
|
|
1259
|
+
});
|
|
1260
|
+
const getCssFile = ({ url, source }) => (source ? CSSSource.fromFileImport(url, source) : CSSSource.fromURI(url));
|
|
1261
|
+
const cssFiles = imports
|
|
1262
|
+
- .map(toUrlSourcePair)
|
|
1263
|
+
+ .map((importObject) => ({ ...toUrlSourcePair(importObject), layer: layerFromImportObject(importObject) }))
|
|
1264
|
+
.filter(({ url }) => !!url)
|
|
1265
|
+
- .map(getCssFile);
|
|
1266
|
+
- for (const cssFile of cssFiles) {
|
|
1267
|
+
+ .map(({ url, source, layer }) => ({ cssFile: getCssFile({ url, source }), layer }));
|
|
1268
|
+
+ for (const { cssFile, layer } of cssFiles) {
|
|
1269
|
+
if (cssFile) {
|
|
1270
|
+
+ if (layer !== null) {
|
|
1271
|
+
+ // @import "x.css" layer(name) — the imported sheet joins the named
|
|
1272
|
+
+ // layer; its own layers become nested sublayers of it.
|
|
1273
|
+
+ const importPath = [layerOrdinal(layer.trim() || `~import-${anonymousLayerCount++}`)];
|
|
1274
|
+
+ for (const ruleset of cssFile.selectors) {
|
|
1275
|
+
+ ruleset.layerPath = [...importPath, ...(ruleset.layerPath ?? [])];
|
|
1276
|
+
+ }
|
|
1277
|
+
+ }
|
|
1278
|
+
rulesets.push(...cssFile.selectors);
|
|
1279
|
+
keyframes.push(...cssFile.keyframes);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
-export function _populateRules(nodes, rulesets, keyframes, mediaQueryString) {
|
|
1284
|
+
+export function _populateRules(nodes, rulesets, keyframes, mediaQueryString, layerPath, layerPrefix) {
|
|
1285
|
+
for (const node of nodes) {
|
|
1286
|
+
if (isKeyframe(node)) {
|
|
1287
|
+
const keyframeRule = {
|
|
1288
|
+
@@ -396,11 +436,32 @@ export function _populateRules(nodes, rulesets, keyframes, mediaQueryString) {
|
|
1289
|
+
else {
|
|
1290
|
+
compositeMediaQuery = node.media;
|
|
1291
|
+
}
|
|
1292
|
+
- _populateRules(node.rules, rulesets, keyframes, compositeMediaQuery);
|
|
1293
|
+
+ _populateRules(node.rules, rulesets, keyframes, compositeMediaQuery, layerPath, layerPrefix);
|
|
1294
|
+
+ }
|
|
1295
|
+
+ else if (isLayer(node)) {
|
|
1296
|
+
+ const name = (node.layer ?? '').trim();
|
|
1297
|
+
+ if (node.rules) {
|
|
1298
|
+
+ // Block at-rule: a single name, or anonymous when the prelude is empty.
|
|
1299
|
+
+ const qualified = name ? (layerPrefix ? `${layerPrefix}.${name}` : name) : `${layerPrefix ?? ''}~${anonymousLayerCount++}`;
|
|
1300
|
+
+ const childPath = name ? layerPathFor(name, layerPath ?? [], layerPrefix ?? '') : [...(layerPath ?? []), layerOrdinal(qualified)];
|
|
1301
|
+
+ _populateRules(node.rules, rulesets, keyframes, mediaQueryString, childPath, qualified);
|
|
1302
|
+
+ }
|
|
1303
|
+
+ else {
|
|
1304
|
+
+ // Statement at-rule: `@layer a, b;` pre-declares order only.
|
|
1305
|
+
+ for (const declared of name.split(',')) {
|
|
1306
|
+
+ const declaredName = declared.trim();
|
|
1307
|
+
+ if (declaredName) {
|
|
1308
|
+
+ layerPathFor(declaredName, layerPath ?? [], layerPrefix ?? '');
|
|
1309
|
+
+ }
|
|
1310
|
+
+ }
|
|
1311
|
+
+ }
|
|
1312
|
+
}
|
|
1313
|
+
else if (isRule(node)) {
|
|
1314
|
+
const ruleset = fromAstNode(node);
|
|
1315
|
+
ruleset.mediaQueryString = mediaQueryString;
|
|
1316
|
+
+ if (layerPath?.length) {
|
|
1317
|
+
+ ruleset.layerPath = layerPath;
|
|
1318
|
+
+ }
|
|
1319
|
+
rulesets.push(ruleset);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
@@ -1263,6 +1324,9 @@ function isMedia(node) {
|
|
1323
|
+
function isKeyframe(node) {
|
|
1324
|
+
return node.type === 'keyframes';
|
|
1325
|
+
}
|
|
1326
|
+
+function isLayer(node) {
|
|
1327
|
+
+ return node.type === 'layer';
|
|
1328
|
+
+}
|
|
1329
|
+
function isRule(node) {
|
|
1330
|
+
return node.type === 'rule';
|
|
1331
|
+
}
|
|
1332
|
+
diff --git a/ui/tab-view/index.android.js b/ui/tab-view/index.android.js
|
|
1333
|
+
index e195b7564af964c333870fbb027c9aaac3335751..7df6fcb99fc0341afb137be4a297337f4fa7bf3e 100644
|
|
1334
|
+
--- a/ui/tab-view/index.android.js
|
|
1335
|
+
+++ b/ui/tab-view/index.android.js
|
|
1336
|
+
@@ -368,7 +368,10 @@ export class TabView extends TabViewBase {
|
|
1337
|
+
onItemsChanged(oldItems, newItems) {
|
|
1338
|
+
super.onItemsChanged(oldItems, newItems);
|
|
1339
|
+
if (oldItems) {
|
|
1340
|
+
- oldItems.forEach((item, i, arr) => {
|
|
1341
|
+
+ oldItems.forEach((item) => {
|
|
1342
|
+
+ if (newItems && newItems.indexOf(item) >= 0) {
|
|
1343
|
+
+ return;
|
|
1344
|
+
+ }
|
|
1345
|
+
item.index = 0;
|
|
1346
|
+
item.tabItemSpec = null;
|
|
1347
|
+
item.setNativeView(null);
|
|
1348
|
+
diff --git a/ui/tab-view/index.ios.js b/ui/tab-view/index.ios.js
|
|
1349
|
+
index c25ff0c66166b9dedd8b284981fc566ad5aa0230..e162b5d59e358965ae88e9b31ad1d1378a595995 100644
|
|
1350
|
+
--- a/ui/tab-view/index.ios.js
|
|
1351
|
+
+++ b/ui/tab-view/index.ios.js
|
|
1352
|
+
@@ -622,6 +622,11 @@ export class TabView extends TabViewBase {
|
|
1353
|
+
[itemsProperty.setNative](value) {
|
|
1354
|
+
this.setViewControllers(value);
|
|
1355
|
+
selectedIndexProperty.coerce(this);
|
|
1356
|
+
+ // Items added to a loaded TabView were loaded before their controllers existed.
|
|
1357
|
+
+ const selectedItem = value === null || value === void 0 ? void 0 : value[this.selectedIndex];
|
|
1358
|
+
+ if (selectedItem) {
|
|
1359
|
+
+ selectedItem.loadView(selectedItem.view);
|
|
1360
|
+
+ }
|
|
1361
|
+
}
|
|
1362
|
+
[tabTextFontSizeProperty.getDefault]() {
|
|
1363
|
+
return null;
|
|
1364
|
+
diff --git a/ui/tab-view/tab-view-common.d.ts b/ui/tab-view/tab-view-common.d.ts
|
|
1365
|
+
index 35d1ba1f2479bbbf64cd4b1acb9563e0f823fd4e..e96b3085d75549d06d2c2e9cae183887e8e1adcc 100644
|
|
1366
|
+
--- a/ui/tab-view/tab-view-common.d.ts
|
|
1367
|
+
+++ b/ui/tab-view/tab-view-common.d.ts
|
|
1368
|
+
@@ -66,6 +66,7 @@ export declare class TabViewBase extends View implements TabViewDefinition, AddC
|
|
1369
|
+
eachChild(callback: (child: ViewBase) => boolean): void;
|
|
1370
|
+
eachChildView(callback: (child: View) => boolean): void;
|
|
1371
|
+
onItemsChanged(oldItems: TabViewItemDefinition[], newItems: TabViewItemDefinition[]): void;
|
|
1372
|
+
+ _isChildPresented(child: ViewBase): boolean;
|
|
1373
|
+
onSelectedIndexChanged(oldIndex: number, newIndex: number): void;
|
|
1374
|
+
}
|
|
1375
|
+
export interface TabViewBase {
|
|
1376
|
+
diff --git a/ui/tab-view/tab-view-common.js b/ui/tab-view/tab-view-common.js
|
|
1377
|
+
index 66672f1fa5ccb31f06a83a2a21bfe1e5c668712f..1eb3676f0346d7ee21ab7ff1c1b78292da641463 100644
|
|
1378
|
+
--- a/ui/tab-view/tab-view-common.js
|
|
1379
|
+
+++ b/ui/tab-view/tab-view-common.js
|
|
1380
|
+
@@ -144,21 +144,33 @@ let TabViewBase = TabViewBase_1 = class TabViewBase extends View {
|
|
1381
|
+
}
|
|
1382
|
+
onItemsChanged(oldItems, newItems) {
|
|
1383
|
+
if (oldItems) {
|
|
1384
|
+
- oldItems.forEach((item) => this._removeView(item));
|
|
1385
|
+
+ oldItems.forEach((item) => {
|
|
1386
|
+
+ if (!newItems || newItems.indexOf(item) < 0) {
|
|
1387
|
+
+ this._removeView(item);
|
|
1388
|
+
+ }
|
|
1389
|
+
+ });
|
|
1390
|
+
}
|
|
1391
|
+
if (newItems) {
|
|
1392
|
+
newItems.forEach((item) => {
|
|
1393
|
+
if (!item.view) {
|
|
1394
|
+
throw new Error(`TabViewItem must have a view.`);
|
|
1395
|
+
}
|
|
1396
|
+
+ // An item kept across the change stays loaded; tearing it down would unload its view.
|
|
1397
|
+
+ if (item.parent === this) {
|
|
1398
|
+
+ return;
|
|
1399
|
+
+ }
|
|
1400
|
+
// A view can only have one parent, and _addView throws if it already has one.
|
|
1401
|
+
- if (item.parent && item.parent !== this) {
|
|
1402
|
+
+ if (item.parent) {
|
|
1403
|
+
item.parent._removeView(item);
|
|
1404
|
+
}
|
|
1405
|
+
this._addView(item);
|
|
1406
|
+
});
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
+ _isChildPresented(child) {
|
|
1410
|
+
+ const items = this.items;
|
|
1411
|
+
+ return !items || items[this.selectedIndex] === child;
|
|
1412
|
+
+ }
|
|
1413
|
+
onSelectedIndexChanged(oldIndex, newIndex) {
|
|
1414
|
+
// to be overridden in platform specific files
|
|
1415
|
+
this.notify({
|