@octane-xplat/nativescript-mason-core 0.0.1 → 1.0.0-beta.1
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 +201 -0
- package/README.md +198 -2
- package/artifact-inventory.json +774 -0
- package/box-shadow.d.ts +10 -0
- package/box-shadow.js +48 -0
- package/common.d.ts +485 -0
- package/common.js +2659 -0
- package/css-colors.d.ts +17 -0
- package/css-colors.js +54 -0
- package/css-environment.d.ts +49 -0
- package/css-environment.js +309 -0
- package/css-filter.d.ts +17 -0
- package/css-filter.js +140 -0
- package/css-keyframes.d.ts +41 -0
- package/css-keyframes.js +437 -0
- package/css-math.d.ts +34 -0
- package/css-math.js +300 -0
- package/css-shorthands.d.ts +65 -0
- package/css-shorthands.js +673 -0
- package/css-transform.d.ts +6 -0
- package/css-transform.js +100 -0
- package/diagnostics.d.ts +51 -0
- package/diagnostics.js +52 -0
- package/display-density.d.ts +9 -0
- package/display-density.js +20 -0
- package/fonts.d.ts +20 -0
- package/fonts.js +88 -0
- package/foreign-layout.d.ts +6 -0
- package/foreign-layout.js +151 -0
- package/gradient-stops.d.ts +25 -0
- package/gradient-stops.js +112 -0
- package/index.android.d.ts +11 -0
- package/index.android.js +9 -0
- package/index.d.ts +12 -0
- package/index.ios.d.ts +11 -0
- package/index.ios.js +9 -0
- package/ios-host-README.md +124 -0
- package/layout-types.d.ts +192 -0
- package/mask.d.ts +54 -0
- package/mask.js +26 -0
- package/native-environment.android.d.ts +3 -0
- package/native-environment.android.js +69 -0
- package/native-environment.d.ts +3 -0
- package/native-environment.ios.d.ts +3 -0
- package/native-environment.ios.js +65 -0
- package/native-types-README.md +51 -0
- package/package.json +47 -6
- package/panel-helpers.d.ts +3 -0
- package/panel-helpers.js +8 -0
- package/platforms/android/MasonCore.aar +0 -0
- package/platforms/android/include.gradle +6 -0
- package/platforms/android/manifest.json +73 -0
- package/platforms/ios/FontManager.LICENSE +201 -0
- package/platforms/ios/MasonCore.xcframework/Info.plist +43 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Headers/Mason.h +25 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Headers/MasonCore-Swift.h +1739 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Headers/mason_native.h +601 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Info.plist +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/MasonCore +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Modules/MasonCore.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Modules/MasonCore.swiftmodule/arm64-apple-ios.abi.json +100095 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Modules/MasonCore.swiftmodule/arm64-apple-ios.private.swiftinterface +3174 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Modules/MasonCore.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Modules/MasonCore.swiftmodule/arm64-apple-ios.swiftinterface +3174 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/Modules/module.modulemap +9 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/SDWebImage_SDWebImage.bundle/Info.plist +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64/MasonCore.framework/SDWebImage_SDWebImage.bundle/PrivacyInfo.xcprivacy +23 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Headers/Mason.h +25 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Headers/MasonCore-Swift.h +1739 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Headers/mason_native.h +601 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Info.plist +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/MasonCore +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Modules/MasonCore.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Modules/MasonCore.swiftmodule/arm64-apple-ios-simulator.abi.json +100095 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Modules/MasonCore.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +3174 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Modules/MasonCore.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Modules/MasonCore.swiftmodule/arm64-apple-ios-simulator.swiftinterface +3174 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/Modules/module.modulemap +9 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/SDWebImage_SDWebImage.bundle/Info.plist +0 -0
- package/platforms/ios/MasonCore.xcframework/ios-arm64-simulator/MasonCore.framework/SDWebImage_SDWebImage.bundle/PrivacyInfo.xcprivacy +23 -0
- package/platforms/ios/Package.resolved +24 -0
- package/platforms/ios/SDWebImage.LICENSE +20 -0
- package/platforms/ios/build.xcconfig +4 -0
- package/platforms/ios/device-manifest.json +213 -0
- package/platforms/ios/include/FontManager/NSCFontDescriptors.h +36 -0
- package/platforms/ios/include/FontManager/NSCFontFace.h +98 -0
- package/platforms/ios/include/FontManager/NSCFontFaceSet.h +73 -0
- package/platforms/ios/include/FontManager/NSCFontManagerUmbrella.h +7 -0
- package/platforms/ios/include/FontManager/NSCFontParser.h +22 -0
- package/platforms/ios/include/FontManager/NSCFontRegex.h +4 -0
- package/platforms/ios/include/FontManager/NSCFontResolver.h +43 -0
- package/platforms/ios/include/FontManager/NSCFontStyle.h +27 -0
- package/platforms/ios/include/FontManager/NSCFontTypes.h +41 -0
- package/platforms/ios/include/SDWebImage/NSButton+WebCache.h +340 -0
- package/platforms/ios/include/SDWebImage/NSData+ImageContentType.h +63 -0
- package/platforms/ios/include/SDWebImage/NSImage+Compatibility.h +67 -0
- package/platforms/ios/include/SDWebImage/SDAnimatedImage.h +136 -0
- package/platforms/ios/include/SDWebImage/SDAnimatedImagePlayer.h +113 -0
- package/platforms/ios/include/SDWebImage/SDAnimatedImageRep.h +33 -0
- package/platforms/ios/include/SDWebImage/SDAnimatedImageView+WebCache.h +168 -0
- package/platforms/ios/include/SDWebImage/SDAnimatedImageView.h +125 -0
- package/platforms/ios/include/SDWebImage/SDCallbackQueue.h +59 -0
- package/platforms/ios/include/SDWebImage/SDDiskCache.h +146 -0
- package/platforms/ios/include/SDWebImage/SDGraphicsImageRenderer.h +84 -0
- package/platforms/ios/include/SDWebImage/SDImageAPNGCoder.h +19 -0
- package/platforms/ios/include/SDWebImage/SDImageAWebPCoder.h +23 -0
- package/platforms/ios/include/SDWebImage/SDImageCache.h +482 -0
- package/platforms/ios/include/SDWebImage/SDImageCacheConfig.h +153 -0
- package/platforms/ios/include/SDWebImage/SDImageCacheDefine.h +179 -0
- package/platforms/ios/include/SDWebImage/SDImageCachesManager.h +81 -0
- package/platforms/ios/include/SDWebImage/SDImageCoder.h +347 -0
- package/platforms/ios/include/SDWebImage/SDImageCoderHelper.h +251 -0
- package/platforms/ios/include/SDWebImage/SDImageCodersManager.h +58 -0
- package/platforms/ios/include/SDWebImage/SDImageFrame.h +44 -0
- package/platforms/ios/include/SDWebImage/SDImageGIFCoder.h +22 -0
- package/platforms/ios/include/SDWebImage/SDImageGraphics.h +28 -0
- package/platforms/ios/include/SDWebImage/SDImageHEICCoder.h +25 -0
- package/platforms/ios/include/SDWebImage/SDImageIOAnimatedCoder.h +65 -0
- package/platforms/ios/include/SDWebImage/SDImageIOCoder.h +30 -0
- package/platforms/ios/include/SDWebImage/SDImageLoader.h +146 -0
- package/platforms/ios/include/SDWebImage/SDImageLoadersManager.h +40 -0
- package/platforms/ios/include/SDWebImage/SDImageTransformer.h +283 -0
- package/platforms/ios/include/SDWebImage/SDMemoryCache.h +78 -0
- package/platforms/ios/include/SDWebImage/SDWebImage.h +91 -0
- package/platforms/ios/include/SDWebImage/SDWebImageCacheKeyFilter.h +35 -0
- package/platforms/ios/include/SDWebImage/SDWebImageCacheSerializer.h +39 -0
- package/platforms/ios/include/SDWebImage/SDWebImageCompat.h +102 -0
- package/platforms/ios/include/SDWebImage/SDWebImageDefine.h +420 -0
- package/platforms/ios/include/SDWebImage/SDWebImageDownloader.h +320 -0
- package/platforms/ios/include/SDWebImage/SDWebImageDownloaderConfig.h +113 -0
- package/platforms/ios/include/SDWebImage/SDWebImageDownloaderDecryptor.h +52 -0
- package/platforms/ios/include/SDWebImage/SDWebImageDownloaderOperation.h +191 -0
- package/platforms/ios/include/SDWebImage/SDWebImageDownloaderRequestModifier.h +72 -0
- package/platforms/ios/include/SDWebImage/SDWebImageDownloaderResponseModifier.h +72 -0
- package/platforms/ios/include/SDWebImage/SDWebImageError.h +33 -0
- package/platforms/ios/include/SDWebImage/SDWebImageIndicator.h +119 -0
- package/platforms/ios/include/SDWebImage/SDWebImageManager.h +290 -0
- package/platforms/ios/include/SDWebImage/SDWebImageOperation.h +27 -0
- package/platforms/ios/include/SDWebImage/SDWebImageOptionsProcessor.h +78 -0
- package/platforms/ios/include/SDWebImage/SDWebImagePrefetcher.h +168 -0
- package/platforms/ios/include/SDWebImage/SDWebImageTransition.h +131 -0
- package/platforms/ios/include/SDWebImage/UIButton+WebCache.h +402 -0
- package/platforms/ios/include/SDWebImage/UIImage+ExtendedCacheData.h +24 -0
- package/platforms/ios/include/SDWebImage/UIImage+ForceDecode.h +52 -0
- package/platforms/ios/include/SDWebImage/UIImage+GIF.h +26 -0
- package/platforms/ios/include/SDWebImage/UIImage+MemoryCacheCost.h +27 -0
- package/platforms/ios/include/SDWebImage/UIImage+Metadata.h +104 -0
- package/platforms/ios/include/SDWebImage/UIImage+MultiFormat.h +81 -0
- package/platforms/ios/include/SDWebImage/UIImage+Transform.h +164 -0
- package/platforms/ios/include/SDWebImage/UIImageView+HighlightedWebCache.h +142 -0
- package/platforms/ios/include/SDWebImage/UIImageView+WebCache.h +209 -0
- package/platforms/ios/include/SDWebImage/UIView+WebCache.h +131 -0
- package/platforms/ios/include/SDWebImage/UIView+WebCacheOperation.h +52 -0
- package/platforms/ios/include/SDWebImage/UIView+WebCacheState.h +63 -0
- package/platforms/ios/include/module.modulemap +2 -0
- package/platforms/ios/manifest.json +132 -0
- package/platforms/ios/simulator-manifest.json +213 -0
- package/plugin-README.md +234 -0
- package/properties.d.ts +154 -0
- package/properties.js +2456 -0
- package/pseudo.d.ts +9 -0
- package/pseudo.js +57 -0
- package/scroll/index.android.d.ts +15 -0
- package/scroll/index.android.js +72 -0
- package/scroll/index.d.ts +5 -0
- package/scroll/index.ios.d.ts +18 -0
- package/scroll/index.ios.js +106 -0
- package/style.d.ts +768 -0
- package/style.js +7167 -0
- package/symbols.d.ts +25 -0
- package/symbols.js +41 -0
- package/tree/index.android.d.ts +11 -0
- package/tree/index.android.js +42 -0
- package/tree/index.d.ts +15 -0
- package/tree/index.ios.d.ts +26 -0
- package/tree/index.ios.js +53 -0
- package/typings/android-declarations.d.ts +4 -0
- package/typings/android.d.ts +9730 -0
- package/typings/manifest.json +45 -0
- package/typings/native.d.ts +5 -0
- package/typings/objc!FontManager.d.ts +389 -0
- package/typings/objc!MasonCore.d.ts +2472 -0
- package/typings/objc!SDWebImage.d.ts +3378 -0
- package/units.d.ts +29 -0
- package/units.js +44 -0
- package/utils/index.android.d.ts +211 -0
- package/utils/index.android.js +595 -0
- package/utils/index.ios.d.ts +222 -0
- package/utils/index.ios.js +790 -0
- package/view/index.android.d.ts +13 -0
- package/view/index.android.js +74 -0
- package/view/index.d.ts +2 -0
- package/view/index.ios.d.ts +24 -0
- package/view/index.ios.js +157 -0
package/css-keyframes.js
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import { CoreTypes, unsetValue } from '@nativescript/core';
|
|
2
|
+
import { KeyframeAnimation } from '@nativescript/core/ui/animation/keyframe-animation';
|
|
3
|
+
import { tokenizeCss } from './css-shorthands';
|
|
4
|
+
import { rotateProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty } from '@nativescript/core/ui/styling/style-properties';
|
|
5
|
+
const animatable = new Map();
|
|
6
|
+
/** Lets keyframes animate [property] with [interpolate]; [initial] is its CSS initial value. */
|
|
7
|
+
export function registerKeyframeProperty(property, interpolate, initial) {
|
|
8
|
+
animatable.set(property.name, { property, interpolate, initial });
|
|
9
|
+
}
|
|
10
|
+
// What core's native Animation plays. A keyframe interval with none of these is skipped by core
|
|
11
|
+
// at once, so its time would be lost.
|
|
12
|
+
const CORE_ANIMATED = ['backgroundColor', 'scale', 'translate', 'rotate', 'opacity', 'width', 'height'];
|
|
13
|
+
const NUMERIC = /^([+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?)([a-z]+|%)?$/i;
|
|
14
|
+
function component(token) {
|
|
15
|
+
const match = NUMERIC.exec(token);
|
|
16
|
+
return match ? { number: parseFloat(match[1]), unit: match[2] ?? '' } : { keyword: token };
|
|
17
|
+
}
|
|
18
|
+
function format(c) {
|
|
19
|
+
if (c.keyword !== undefined) {
|
|
20
|
+
return c.keyword;
|
|
21
|
+
}
|
|
22
|
+
return `${Math.round(c.number * 10000) / 10000}${c.unit}`;
|
|
23
|
+
}
|
|
24
|
+
function mix(a, b, t) {
|
|
25
|
+
if (a.number === undefined || b.number === undefined) {
|
|
26
|
+
return a.keyword === b.keyword ? a : null;
|
|
27
|
+
}
|
|
28
|
+
// A unitless 0 takes the other side's unit, as `0` does in CSS lengths.
|
|
29
|
+
const unit = a.unit || (a.number === 0 ? b.unit : a.unit);
|
|
30
|
+
const otherUnit = b.unit || (b.number === 0 ? unit : b.unit);
|
|
31
|
+
if (unit !== otherUnit) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return { number: a.number + (b.number - a.number) * t, unit };
|
|
35
|
+
}
|
|
36
|
+
/** Layers of a list-valued property, each split into whitespace tokens. */
|
|
37
|
+
function layers(value) {
|
|
38
|
+
const result = [[]];
|
|
39
|
+
for (const token of tokenizeCss(value)) {
|
|
40
|
+
if (token === ',') {
|
|
41
|
+
result.push([]);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
result[result.length - 1].push(token);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
const POSITION_KEYWORD = { left: 0, top: 0, center: 50, right: 100, bottom: 100 };
|
|
50
|
+
const VERTICAL = new Set(['top', 'bottom']);
|
|
51
|
+
const HORIZONTAL = new Set(['left', 'right']);
|
|
52
|
+
/** One `<position>` as [x, y], or null for the 3- and 4-value edge-offset forms. */
|
|
53
|
+
function position(tokens) {
|
|
54
|
+
const read = (token) => (token in POSITION_KEYWORD ? { number: POSITION_KEYWORD[token], unit: '%' } : component(token));
|
|
55
|
+
if (tokens.length === 1) {
|
|
56
|
+
return VERTICAL.has(tokens[0]) ? [read('center'), read(tokens[0])] : [read(tokens[0]), read('center')];
|
|
57
|
+
}
|
|
58
|
+
if (tokens.length === 2) {
|
|
59
|
+
const [a, b] = tokens;
|
|
60
|
+
return VERTICAL.has(a) || HORIZONTAL.has(b) ? [read(b), read(a)] : [read(a), read(b)];
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/** One `<bg-size>` as [width, height]; `cover` and `contain` stay single keywords. */
|
|
65
|
+
function size(tokens) {
|
|
66
|
+
if (tokens.length === 1) {
|
|
67
|
+
return tokens[0] === 'cover' || tokens[0] === 'contain' ? [{ keyword: tokens[0] }] : [component(tokens[0]), { keyword: 'auto' }];
|
|
68
|
+
}
|
|
69
|
+
return tokens.length === 2 ? tokens.map(component) : null;
|
|
70
|
+
}
|
|
71
|
+
function listInterpolator(parse) {
|
|
72
|
+
return (from, to, t) => {
|
|
73
|
+
const a = layers(from).map(parse);
|
|
74
|
+
const b = layers(to).map(parse);
|
|
75
|
+
// Values that can't be mixed flip halfway, as CSS does for discrete animation.
|
|
76
|
+
const discrete = () => (t < 0.5 ? from : to);
|
|
77
|
+
if (a.length !== b.length) {
|
|
78
|
+
return discrete();
|
|
79
|
+
}
|
|
80
|
+
const out = [];
|
|
81
|
+
for (let i = 0; i < a.length; i++) {
|
|
82
|
+
const x = a[i];
|
|
83
|
+
const y = b[i];
|
|
84
|
+
if (!x || !y || x.length !== y.length) {
|
|
85
|
+
return discrete();
|
|
86
|
+
}
|
|
87
|
+
const mixed = x.map((c, j) => mix(c, y[j], t));
|
|
88
|
+
if (mixed.some((c) => c === null)) {
|
|
89
|
+
return discrete();
|
|
90
|
+
}
|
|
91
|
+
out.push(mixed.map(format).join(' '));
|
|
92
|
+
}
|
|
93
|
+
return out.join(', ');
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** Interpolates `<position>` lists (`mask-position`, `background-position`). */
|
|
97
|
+
export const interpolatePositionList = listInterpolator(position);
|
|
98
|
+
/** Interpolates `<bg-size>` lists (`mask-size`, `background-size`). */
|
|
99
|
+
export const interpolateSizeList = listInterpolator(size);
|
|
100
|
+
// ---------------------------------------------------------------------------------------------
|
|
101
|
+
// Timing
|
|
102
|
+
function cubicBezier(x1, y1, x2, y2) {
|
|
103
|
+
const sample = (a1, a2, s) => ((1 - 3 * a2 + 3 * a1) * s + (3 * a2 - 6 * a1)) * s * s + 3 * a1 * s;
|
|
104
|
+
const slope = (a1, a2, s) => 3 * (1 - 3 * a2 + 3 * a1) * s * s + 2 * (3 * a2 - 6 * a1) * s + 3 * a1;
|
|
105
|
+
return (t) => {
|
|
106
|
+
if (t <= 0 || t >= 1) {
|
|
107
|
+
return t;
|
|
108
|
+
}
|
|
109
|
+
// Newton's method for the curve parameter at x = t, then bisection if it stalls.
|
|
110
|
+
let s = t;
|
|
111
|
+
for (let i = 0; i < 8; i++) {
|
|
112
|
+
const error = sample(x1, x2, s) - t;
|
|
113
|
+
if (Math.abs(error) < 1e-6) {
|
|
114
|
+
return sample(y1, y2, s);
|
|
115
|
+
}
|
|
116
|
+
const d = slope(x1, x2, s);
|
|
117
|
+
if (Math.abs(d) < 1e-6) {
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
s -= error / d;
|
|
121
|
+
}
|
|
122
|
+
let lo = 0;
|
|
123
|
+
let hi = 1;
|
|
124
|
+
s = t;
|
|
125
|
+
for (let i = 0; i < 30; i++) {
|
|
126
|
+
const x = sample(x1, x2, s);
|
|
127
|
+
if (Math.abs(x - t) < 1e-6) {
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
if (x < t) {
|
|
131
|
+
lo = s;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
hi = s;
|
|
135
|
+
}
|
|
136
|
+
s = (lo + hi) / 2;
|
|
137
|
+
}
|
|
138
|
+
return sample(y1, y2, s);
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const NAMED_CURVES = {
|
|
142
|
+
[CoreTypes.AnimationCurve.ease]: [0.25, 0.1, 0.25, 1],
|
|
143
|
+
[CoreTypes.AnimationCurve.easeIn]: [0.42, 0, 1, 1],
|
|
144
|
+
[CoreTypes.AnimationCurve.easeOut]: [0, 0, 0.58, 1],
|
|
145
|
+
[CoreTypes.AnimationCurve.easeInOut]: [0.42, 0, 0.58, 1],
|
|
146
|
+
};
|
|
147
|
+
/** Core's keyframe curve as an easing function; `linear`, `spring` and unknown curves are linear. */
|
|
148
|
+
export function easing(curve) {
|
|
149
|
+
if (curve && typeof curve === 'object' && typeof curve.x1 === 'number') {
|
|
150
|
+
return cubicBezier(curve.x1, curve.y1, curve.x2, curve.y2);
|
|
151
|
+
}
|
|
152
|
+
const named = NAMED_CURVES[curve];
|
|
153
|
+
return named ? cubicBezier(...named) : (t) => t;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The value of [track] at [time] ms into an iteration of [total] ms. [curveAt] gives the timing
|
|
157
|
+
* function of the interval starting at a time. A missing first or last keyframe uses [base], the
|
|
158
|
+
* element's own value, as CSS does.
|
|
159
|
+
*/
|
|
160
|
+
export function sampleTrack(track, base, total, time, curveAt) {
|
|
161
|
+
const stops = track.stops;
|
|
162
|
+
const points = [];
|
|
163
|
+
if (stops[0][0] > 0) {
|
|
164
|
+
points.push([0, base]);
|
|
165
|
+
}
|
|
166
|
+
points.push(...stops);
|
|
167
|
+
if (stops[stops.length - 1][0] < total) {
|
|
168
|
+
points.push([total, base]);
|
|
169
|
+
}
|
|
170
|
+
if (time <= points[0][0]) {
|
|
171
|
+
return points[0][1];
|
|
172
|
+
}
|
|
173
|
+
for (let i = 1; i < points.length; i++) {
|
|
174
|
+
const [end, to] = points[i];
|
|
175
|
+
if (time <= end) {
|
|
176
|
+
const [start, from] = points[i - 1];
|
|
177
|
+
const span = end - start;
|
|
178
|
+
const t = span > 0 ? curveAt(start)((time - start) / span) : 1;
|
|
179
|
+
return track.interpolate(from, to, t);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return points[points.length - 1][1];
|
|
183
|
+
}
|
|
184
|
+
// ---------------------------------------------------------------------------------------------
|
|
185
|
+
// Playing alongside core
|
|
186
|
+
const driver_ = Symbol('mason:keyframeDriver');
|
|
187
|
+
const tracks_ = Symbol('mason:keyframeTracks');
|
|
188
|
+
const nextFrame = typeof requestAnimationFrame === 'function' ? (callback) => requestAnimationFrame(callback) : (callback) => setTimeout(callback, 16);
|
|
189
|
+
class KeyframeDriver {
|
|
190
|
+
constructor(view, tracks, total, delay, iterations, forwards, segments) {
|
|
191
|
+
this.view = view;
|
|
192
|
+
this.tracks = tracks;
|
|
193
|
+
this.total = total;
|
|
194
|
+
this.delay = delay;
|
|
195
|
+
this.iterations = iterations;
|
|
196
|
+
this.forwards = forwards;
|
|
197
|
+
this.stopped = false;
|
|
198
|
+
this.startTime = 0;
|
|
199
|
+
this.intervalEnds = [];
|
|
200
|
+
this.curves = [];
|
|
201
|
+
/** The curve of the interval starting at [start]: the first one ending after it. */
|
|
202
|
+
this.curveAt = (start) => {
|
|
203
|
+
// Skips the 0.01 ms interval core gives a 0% keyframe.
|
|
204
|
+
const index = this.intervalEnds.findIndex((end) => end > start + 1);
|
|
205
|
+
return this.curves[index === -1 ? this.curves.length - 1 : index];
|
|
206
|
+
};
|
|
207
|
+
const style = view.style;
|
|
208
|
+
this.bases = tracks.map((track) => {
|
|
209
|
+
const value = style[track.property.name];
|
|
210
|
+
return typeof value === 'string' && value.trim() ? value : animatable.get(track.property.name).initial;
|
|
211
|
+
});
|
|
212
|
+
// Core has already moved each keyframe's timing function onto the interval that keyframe
|
|
213
|
+
// starts, so an interval's own curve is the one to use.
|
|
214
|
+
let time = 0;
|
|
215
|
+
for (const segment of segments) {
|
|
216
|
+
time += segment.duration;
|
|
217
|
+
this.intervalEnds.push(time);
|
|
218
|
+
this.curves.push(easing(segment.curve));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
start(onFinish) {
|
|
222
|
+
this.startTime = Date.now();
|
|
223
|
+
const tick = () => {
|
|
224
|
+
if (this.stopped) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const elapsed = Date.now() - this.startTime - this.delay;
|
|
228
|
+
if (elapsed < 0) {
|
|
229
|
+
nextFrame(tick);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const iteration = this.total > 0 ? Math.floor(elapsed / this.total) : this.iterations;
|
|
233
|
+
if (iteration >= this.iterations) {
|
|
234
|
+
this.apply(this.total);
|
|
235
|
+
this.finish(!this.forwards);
|
|
236
|
+
onFinish();
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
this.apply(elapsed - iteration * this.total);
|
|
240
|
+
nextFrame(tick);
|
|
241
|
+
};
|
|
242
|
+
tick();
|
|
243
|
+
}
|
|
244
|
+
apply(time) {
|
|
245
|
+
const style = this.view.style;
|
|
246
|
+
this.tracks.forEach((track, i) => {
|
|
247
|
+
const value = sampleTrack(track, this.bases[i], this.total, time, this.curveAt);
|
|
248
|
+
if (style[track.property.keyframe] !== value) {
|
|
249
|
+
style[track.property.keyframe] = value;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
finish(reset) {
|
|
254
|
+
this.stopped = true;
|
|
255
|
+
if (reset) {
|
|
256
|
+
const style = this.view.style;
|
|
257
|
+
for (const track of this.tracks) {
|
|
258
|
+
style[track.property.keyframe] = unsetValue;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** Takes MasonKit's properties out of core's keyframe intervals, as tracks with stop times. */
|
|
264
|
+
function extractTracks(segments) {
|
|
265
|
+
const byName = new Map();
|
|
266
|
+
let time = 0;
|
|
267
|
+
for (const segment of segments) {
|
|
268
|
+
time += segment.duration;
|
|
269
|
+
for (const [name, entry] of animatable) {
|
|
270
|
+
if (name in segment) {
|
|
271
|
+
let track = byName.get(name);
|
|
272
|
+
if (!track) {
|
|
273
|
+
track = { property: entry.property, interpolate: entry.interpolate, stops: [] };
|
|
274
|
+
byName.set(name, track);
|
|
275
|
+
}
|
|
276
|
+
// Core gives a 0% keyframe a 0.01 ms interval; it is still the start.
|
|
277
|
+
track.stops.push([segment === segments[0] && segment.duration <= 1 ? 0 : time, String(segment[name])]);
|
|
278
|
+
delete segment[name];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return { tracks: [...byName.values()], total: time };
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Keeps every interval timed for core: an interval left with nothing core can animate is
|
|
286
|
+
* skipped at once, so it holds the previous interval's values instead.
|
|
287
|
+
*/
|
|
288
|
+
function holdEmptyIntervals(segments) {
|
|
289
|
+
let previous = {};
|
|
290
|
+
for (const segment of segments) {
|
|
291
|
+
const present = CORE_ANIMATED.filter((name) => name in segment);
|
|
292
|
+
if (present.length === 0) {
|
|
293
|
+
Object.assign(segment, previous);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
previous = { ...previous, ...Object.fromEntries(present.map((name) => [name, segment[name]])) };
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Windows: core's native animation of scale/rotate/translate never shows on a Mason view (see
|
|
302
|
+
* ViewBase.updateNativeTransform), so they become per-frame tracks of the View properties.
|
|
303
|
+
*/
|
|
304
|
+
function splitTransforms(segments) {
|
|
305
|
+
for (const segment of segments) {
|
|
306
|
+
if (segment.rotate && typeof segment.rotate === 'object')
|
|
307
|
+
segment.rotate = segment.rotate.z ?? 0;
|
|
308
|
+
if (segment.scale && typeof segment.scale === 'object') {
|
|
309
|
+
segment.scaleX = segment.scale.x;
|
|
310
|
+
segment.scaleY = segment.scale.y;
|
|
311
|
+
delete segment.scale;
|
|
312
|
+
}
|
|
313
|
+
if (segment.translate && typeof segment.translate === 'object') {
|
|
314
|
+
segment.translateX = segment.translate.x;
|
|
315
|
+
segment.translateY = segment.translate.y;
|
|
316
|
+
delete segment.translate;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function interpolateNumber(from, to, t) {
|
|
321
|
+
const a = parseFloat(from) || 0;
|
|
322
|
+
const b = parseFloat(to) || 0;
|
|
323
|
+
return String(a + (b - a) * t);
|
|
324
|
+
}
|
|
325
|
+
if (false) {
|
|
326
|
+
registerKeyframeProperty(rotateProperty, interpolateNumber, '0');
|
|
327
|
+
registerKeyframeProperty(scaleXProperty, interpolateNumber, '1');
|
|
328
|
+
registerKeyframeProperty(scaleYProperty, interpolateNumber, '1');
|
|
329
|
+
registerKeyframeProperty(translateXProperty, interpolateNumber, '0');
|
|
330
|
+
registerKeyframeProperty(translateYProperty, interpolateNumber, '0');
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Windows: View.animate()'s scale, rotate and translate, played per frame on the View properties
|
|
334
|
+
* (core's storyboards target a transform that doesn't show on a Mason view).
|
|
335
|
+
*/
|
|
336
|
+
export function animateTransforms(view, options) {
|
|
337
|
+
const v = view;
|
|
338
|
+
const tracks = [];
|
|
339
|
+
const add = (name, to, initial) => {
|
|
340
|
+
if (typeof to === 'number' && Number.isFinite(to))
|
|
341
|
+
tracks.push({ name, from: typeof v[name] === 'number' ? v[name] : initial, to });
|
|
342
|
+
};
|
|
343
|
+
const rotate = options.rotate;
|
|
344
|
+
add('rotate', typeof rotate === 'object' ? rotate?.z : rotate, 0);
|
|
345
|
+
add('scaleX', options.scale?.x, 1);
|
|
346
|
+
add('scaleY', options.scale?.y, 1);
|
|
347
|
+
add('translateX', options.translate?.x, 0);
|
|
348
|
+
add('translateY', options.translate?.y, 0);
|
|
349
|
+
const duration = typeof options.duration === 'number' ? options.duration : 300;
|
|
350
|
+
const delay = typeof options.delay === 'number' ? options.delay : 0;
|
|
351
|
+
const iterations = typeof options.iterations === 'number' && options.iterations > 0 ? options.iterations : 1;
|
|
352
|
+
const curve = easing(options.curve);
|
|
353
|
+
let stopped = false;
|
|
354
|
+
let resolve;
|
|
355
|
+
const done = new Promise((r) => (resolve = r));
|
|
356
|
+
const set = (t) => {
|
|
357
|
+
for (const track of tracks)
|
|
358
|
+
v[track.name] = track.from + (track.to - track.from) * t;
|
|
359
|
+
};
|
|
360
|
+
const start = Date.now();
|
|
361
|
+
const tick = () => {
|
|
362
|
+
if (stopped)
|
|
363
|
+
return;
|
|
364
|
+
const elapsed = Date.now() - start - delay;
|
|
365
|
+
if (elapsed < 0) {
|
|
366
|
+
nextFrame(tick);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const iteration = duration > 0 ? Math.floor(elapsed / duration) : iterations;
|
|
370
|
+
if (iteration >= iterations) {
|
|
371
|
+
set(1);
|
|
372
|
+
resolve();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
set(curve((elapsed - iteration * duration) / duration));
|
|
376
|
+
nextFrame(tick);
|
|
377
|
+
};
|
|
378
|
+
tick();
|
|
379
|
+
return {
|
|
380
|
+
done,
|
|
381
|
+
cancel: () => {
|
|
382
|
+
stopped = true;
|
|
383
|
+
resolve();
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
let installed = false;
|
|
388
|
+
/** Installs the keyframe hooks once. */
|
|
389
|
+
export function installKeyframes() {
|
|
390
|
+
if (installed) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
installed = true;
|
|
394
|
+
const proto = KeyframeAnimation.prototype;
|
|
395
|
+
const play = proto.play;
|
|
396
|
+
const cancel = proto.cancel;
|
|
397
|
+
proto.play = function (view) {
|
|
398
|
+
// The keyframe intervals are shared by every play of this animation, so take the tracks
|
|
399
|
+
// out once.
|
|
400
|
+
if (this[tracks_] === undefined) {
|
|
401
|
+
if (false)
|
|
402
|
+
splitTransforms(this.animations);
|
|
403
|
+
this[tracks_] = extractTracks(this.animations);
|
|
404
|
+
if (this[tracks_].tracks.length) {
|
|
405
|
+
holdEmptyIntervals(this.animations);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
const { tracks, total } = this[tracks_];
|
|
409
|
+
if (!tracks.length) {
|
|
410
|
+
return play.call(this, view);
|
|
411
|
+
}
|
|
412
|
+
const hasCoreWork = this.animations.some((segment) => CORE_ANIMATED.some((name) => name in segment));
|
|
413
|
+
let finishDriver;
|
|
414
|
+
const driverDone = new Promise((resolve) => (finishDriver = resolve));
|
|
415
|
+
const driver = new KeyframeDriver(view, tracks, total, this.delay ?? 0, this.iterations ?? 1, !!this._isForwards, this.animations);
|
|
416
|
+
this[driver_] = driver;
|
|
417
|
+
driver.start(() => finishDriver());
|
|
418
|
+
if (!hasCoreWork) {
|
|
419
|
+
this._isPlaying = true;
|
|
420
|
+
return driverDone.then(() => {
|
|
421
|
+
this._isPlaying = false;
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
return Promise.all([play.call(this, view), driverDone]).then(() => undefined);
|
|
425
|
+
};
|
|
426
|
+
proto.cancel = function () {
|
|
427
|
+
const driver = this[driver_];
|
|
428
|
+
if (driver) {
|
|
429
|
+
driver.finish(true);
|
|
430
|
+
this[driver_] = undefined;
|
|
431
|
+
}
|
|
432
|
+
if (this._nativeAnimations?.length || !driver) {
|
|
433
|
+
return cancel.call(this);
|
|
434
|
+
}
|
|
435
|
+
this._isPlaying = false;
|
|
436
|
+
};
|
|
437
|
+
}
|
package/css-math.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `calc()`, `min()`, `max()` and `clamp()` evaluated with Mason's units. Lengths resolve to CSS px
|
|
3
|
+
* as read; a pure `%` result stays a percentage, `%` mixed with a length is left unresolved.
|
|
4
|
+
*/
|
|
5
|
+
/** `n<unit>` in CSS px, a percentage (e.g. `em` on `font-size`), or undefined if unresolvable. */
|
|
6
|
+
export type CssUnitResolver = (n: number, unit: string) => number | {
|
|
7
|
+
percent: number;
|
|
8
|
+
} | undefined;
|
|
9
|
+
export type CssMathResult = {
|
|
10
|
+
kind: 'length';
|
|
11
|
+
px: number;
|
|
12
|
+
} | {
|
|
13
|
+
kind: 'percent';
|
|
14
|
+
percent: number;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'number';
|
|
17
|
+
value: number;
|
|
18
|
+
};
|
|
19
|
+
/** Whether `value` is a single math function, e.g. `calc(1rem + 2px)`. */
|
|
20
|
+
export declare function isCssMathFunction(value: string): boolean;
|
|
21
|
+
/** Whether `value` holds a math function anywhere. */
|
|
22
|
+
export declare function hasCssMathFunction(value: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Evaluate one math function, e.g. `clamp(1rem, 2.5vw, 2rem)`, or undefined
|
|
25
|
+
* when it isn't one, doesn't parse, or mixes `%` with a length.
|
|
26
|
+
*/
|
|
27
|
+
export declare function evaluateCssMath(value: string, resolveUnit: CssUnitResolver): CssMathResult | undefined;
|
|
28
|
+
/** A result as CSS text: `12px`, `50%` or `1.5`. */
|
|
29
|
+
export declare function cssMathText(result: CssMathResult): string;
|
|
30
|
+
/**
|
|
31
|
+
* Replace every math function in `value` that resolves with its result, leaving the rest as is:
|
|
32
|
+
* `0 0 calc(0.5rem + 1px) red` becomes `0 0 9px red`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function substituteCssMath(value: string, resolveUnit: CssUnitResolver): string;
|