@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/properties.js
ADDED
|
@@ -0,0 +1,2456 @@
|
|
|
1
|
+
import { environmentStyleValue, cssEnvironmentShorthand } from './css-environment';
|
|
2
|
+
import { CssProperty, CssAnimationProperty, InheritedCssProperty, backgroundColorProperty, Style, ShorthandProperty, Length as CoreLength, fontSizeProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, PercentLength as CorePercentLength, Trace, CoreTypes, unsetValue, verticalAlignmentProperty, textShadowProperty, Font, Property, makeParser, makeValidator, marginTopProperty, marginRightProperty, marginBottomProperty, marginLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty, borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty, minWidthProperty, minHeightProperty, widthProperty, heightProperty, lineHeightProperty, letterSpacingProperty, } from '@nativescript/core';
|
|
3
|
+
import { isMasonView_, touchAction_ } from './symbols';
|
|
4
|
+
/** Marks a Style whose size accessors already resolve Mason's units. */
|
|
5
|
+
const MASON_SIZE_UNITS = Symbol('mason:size-units');
|
|
6
|
+
import { beginStyleWrite, cssLengthToDip, endStyleWrite, isSizingKeyword, parseAspectRatio } from './style';
|
|
7
|
+
import { isCssMathFunction } from './css-math';
|
|
8
|
+
import { alignItemsProperty, alignSelfProperty, flexDirectionProperty, flexGrowProperty, flexShrinkProperty, flexWrapProperty, justifyContentProperty } from '@nativescript/core/ui/layouts/flexbox-layout';
|
|
9
|
+
import { parseCSSShadow } from '@nativescript/core/ui/styling/css-shadow';
|
|
10
|
+
import { installKeyframes, interpolatePositionList, interpolateSizeList, registerKeyframeProperty } from './css-keyframes';
|
|
11
|
+
import { borderTopLeftRadiusProperty, borderTopRightRadiusProperty, borderBottomRightRadiusProperty, borderBottomLeftRadiusProperty, borderTopColorProperty, borderRightColorProperty, borderBottomColorProperty, borderLeftColorProperty } from '@nativescript/core/ui/styling/style-properties';
|
|
12
|
+
import { BORDER_WIDTH_KEYWORDS, passThrough, splitBorder, splitBorderSide, splitBorderStyle, splitBorderStyleStartEnd, splitBorderWidthStartEnd, splitBorderColorStartEnd, splitInsetStartEnd, splitMarginStartEnd, splitPaddingStartEnd, splitBackground, splitMask, splitMaskBorder, splitWebkitMask, webkitMaskBox, webkitMaskComposite, splitBorderColor, splitBorderRadius, splitBorderWidth, splitFlex, splitFlexFlow, splitGap, splitMargin, splitOverflow, splitPadding } from './css-shorthands';
|
|
13
|
+
import { cssLength, isCssLength, toCamelCase } from './css-shorthands';
|
|
14
|
+
import { splitListStyle, splitPlace } from './css-shorthands';
|
|
15
|
+
function getViewStyle(view) {
|
|
16
|
+
const ret = (__ANDROID__ ? view?.get() : view?.deref());
|
|
17
|
+
// Undefined for a plain NativeScript view (and for a cleared ref): only mason's
|
|
18
|
+
// own view classes define `_styleHelper`.
|
|
19
|
+
return ret?._styleHelper;
|
|
20
|
+
}
|
|
21
|
+
/** Mason views write these in setNative, which core runs after valueChanged; one write is enough. */
|
|
22
|
+
function appliedInSetNative(target, property) {
|
|
23
|
+
const ref = target?.viewRef;
|
|
24
|
+
const view = ref ? (__ANDROID__ ? ref.get() : ref.deref()) : undefined;
|
|
25
|
+
return !!(view && view[isMasonView_] && view[property.setNative]);
|
|
26
|
+
}
|
|
27
|
+
// Mason parses CSS values itself, so for its own elements the raw declaration is
|
|
28
|
+
// passed straight through; anything else has to go through core's parser first.
|
|
29
|
+
//
|
|
30
|
+
// This asks specifically whether the view *is* a mason element, not whether it
|
|
31
|
+
// sits inside one. A plain NativeScript view parented into a mason tree has no
|
|
32
|
+
// mason style buffer — its value still has to be converted for core, or core's
|
|
33
|
+
// own setNative gets a string it can't use. See "Mixing with plain NativeScript
|
|
34
|
+
// views" in MASON_CONTEXT.md.
|
|
35
|
+
//
|
|
36
|
+
// `isMasonView_` is a plain marker set in the mason view constructors. Don't
|
|
37
|
+
// reach for `_styleHelper` here: its getter lazily builds the native view, and a
|
|
38
|
+
// valueConverter can run long before that should happen.
|
|
39
|
+
function isMasonView(style) {
|
|
40
|
+
if (style && style.viewRef) {
|
|
41
|
+
const view = __ANDROID__ ? style.viewRef.get() : style.viewRef.deref();
|
|
42
|
+
return !!(view && view[isMasonView_]);
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const CSS_WIDE_KEYWORDS = new Set(['initial', 'inherit', 'unset', 'revert']);
|
|
47
|
+
export function shorthandConverter({ cssName, longhands, split }) {
|
|
48
|
+
return (value) => {
|
|
49
|
+
const text = typeof value === 'number' ? String(value) : value;
|
|
50
|
+
if (typeof text !== 'string') {
|
|
51
|
+
// Core 9.1 probes with unsetValue to learn the longhands, which a var()
|
|
52
|
+
// declaration needs all of.
|
|
53
|
+
return longhands.map((property) => [property, value]);
|
|
54
|
+
}
|
|
55
|
+
const trimmed = text.trim();
|
|
56
|
+
if (!trimmed || CSS_WIDE_KEYWORDS.has(trimmed)) {
|
|
57
|
+
return longhands.map((property) => [property, trimmed]);
|
|
58
|
+
}
|
|
59
|
+
const parts = (['padding', 'margin', 'border-width'].includes(cssName) &&
|
|
60
|
+
cssEnvironmentShorthand(trimmed, split, longhands.length)) || split(trimmed);
|
|
61
|
+
return longhands.map((property, i) => [property, parts[i]]);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function masonShorthandProperty(entry, getter = () => undefined) {
|
|
65
|
+
return new ShorthandProperty({
|
|
66
|
+
name: toCamelCase(entry.cssName),
|
|
67
|
+
cssName: entry.cssName,
|
|
68
|
+
getter,
|
|
69
|
+
converter: shorthandConverter(entry),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export const textProperty = new Property({
|
|
73
|
+
name: 'text',
|
|
74
|
+
});
|
|
75
|
+
export const displayProperty = new CssProperty({
|
|
76
|
+
name: 'display',
|
|
77
|
+
cssName: 'display',
|
|
78
|
+
defaultValue: 'block',
|
|
79
|
+
valueChanged: (target, oldValue, newValue) => {
|
|
80
|
+
if (appliedInSetNative(target, displayProperty))
|
|
81
|
+
return;
|
|
82
|
+
const view = getViewStyle(target.viewRef);
|
|
83
|
+
if (view && newValue) {
|
|
84
|
+
view.display = newValue;
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
valueConverter: function (value) {
|
|
88
|
+
if (typeof value === 'number') {
|
|
89
|
+
switch (value) {
|
|
90
|
+
case 0:
|
|
91
|
+
return 'none';
|
|
92
|
+
case 1:
|
|
93
|
+
return 'flex';
|
|
94
|
+
case 2:
|
|
95
|
+
return 'grid';
|
|
96
|
+
case 3:
|
|
97
|
+
return 'block';
|
|
98
|
+
case 4:
|
|
99
|
+
return 'inline';
|
|
100
|
+
case 5:
|
|
101
|
+
return 'inline-block';
|
|
102
|
+
case 6:
|
|
103
|
+
return 'inline-flex';
|
|
104
|
+
case 7:
|
|
105
|
+
return 'inline-grid';
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
switch (value) {
|
|
109
|
+
case 'none':
|
|
110
|
+
case 'flex':
|
|
111
|
+
case 'grid':
|
|
112
|
+
case 'block':
|
|
113
|
+
case 'inline':
|
|
114
|
+
case 'inline-block':
|
|
115
|
+
case 'inline-flex':
|
|
116
|
+
case 'inline-grid':
|
|
117
|
+
return value;
|
|
118
|
+
// The legacy boxes `line-clamp` utilities ask for.
|
|
119
|
+
case '-webkit-box':
|
|
120
|
+
return 'block';
|
|
121
|
+
case '-webkit-inline-box':
|
|
122
|
+
return 'inline-block';
|
|
123
|
+
default:
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
export const filterProperty = new CssProperty({
|
|
129
|
+
name: 'filter',
|
|
130
|
+
cssName: 'filter',
|
|
131
|
+
});
|
|
132
|
+
export const borderColorProperty = new CssProperty({
|
|
133
|
+
name: 'borderColor',
|
|
134
|
+
cssName: 'border-color',
|
|
135
|
+
});
|
|
136
|
+
export const backgroundProperty = new CssProperty({
|
|
137
|
+
name: 'background',
|
|
138
|
+
cssName: 'background',
|
|
139
|
+
});
|
|
140
|
+
export const backgroundImageProperty = new CssProperty({
|
|
141
|
+
name: 'backgroundImage',
|
|
142
|
+
cssName: 'background-image',
|
|
143
|
+
});
|
|
144
|
+
export const backgroundRepeatProperty = new CssProperty({
|
|
145
|
+
name: 'backgroundRepeat',
|
|
146
|
+
cssName: 'background-repeat',
|
|
147
|
+
valueChanged(target, oldValue, newValue) {
|
|
148
|
+
const view = getViewStyle(target.viewRef);
|
|
149
|
+
if (view) {
|
|
150
|
+
view.backgroundRepeat = newValue;
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
export const backgroundPositionProperty = new CssProperty({
|
|
155
|
+
name: 'backgroundPosition',
|
|
156
|
+
cssName: 'background-position',
|
|
157
|
+
valueChanged(target, oldValue, newValue) {
|
|
158
|
+
const view = getViewStyle(target.viewRef);
|
|
159
|
+
if (view) {
|
|
160
|
+
view.backgroundPosition = newValue;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
export const backgroundSizeProperty = new CssProperty({
|
|
165
|
+
name: 'backgroundSize',
|
|
166
|
+
cssName: 'background-size',
|
|
167
|
+
valueChanged(target, oldValue, newValue) {
|
|
168
|
+
const view = getViewStyle(target.viewRef);
|
|
169
|
+
if (view) {
|
|
170
|
+
view.backgroundSize = newValue;
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
export const backgroundClipProperty = new CssProperty({
|
|
175
|
+
name: 'backgroundClip',
|
|
176
|
+
cssName: 'background-clip',
|
|
177
|
+
valueChanged(target, oldValue, newValue) {
|
|
178
|
+
const view = getViewStyle(target.viewRef);
|
|
179
|
+
if (view) {
|
|
180
|
+
view.backgroundClip = newValue;
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
function overflowConverter(value) {
|
|
185
|
+
if (typeof value === 'number') {
|
|
186
|
+
switch (value) {
|
|
187
|
+
case 0:
|
|
188
|
+
return 'visible';
|
|
189
|
+
case 1:
|
|
190
|
+
return 'clip';
|
|
191
|
+
case 2:
|
|
192
|
+
return 'hidden';
|
|
193
|
+
case 3:
|
|
194
|
+
return 'scroll';
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
switch (value) {
|
|
198
|
+
case 'visible':
|
|
199
|
+
case 'hidden':
|
|
200
|
+
case 'clip':
|
|
201
|
+
case 'scroll':
|
|
202
|
+
case 'auto':
|
|
203
|
+
return value;
|
|
204
|
+
default:
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
export const overflowXProperty = new CssProperty({
|
|
209
|
+
name: 'overflowX',
|
|
210
|
+
cssName: 'overflow-x',
|
|
211
|
+
defaultValue: 'visible',
|
|
212
|
+
valueConverter: overflowConverter,
|
|
213
|
+
valueChanged: (target, oldValue, newValue) => {
|
|
214
|
+
if (newValue && appliedInSetNative(target, overflowXProperty))
|
|
215
|
+
return;
|
|
216
|
+
const view = getViewStyle(target.viewRef);
|
|
217
|
+
if (view) {
|
|
218
|
+
if (newValue) {
|
|
219
|
+
view.overflowX = newValue;
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
// Revert to old value if newValue is invalid
|
|
223
|
+
target.overflowX = oldValue;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
export const overflowYProperty = new CssProperty({
|
|
229
|
+
name: 'overflowY',
|
|
230
|
+
cssName: 'overflow-y',
|
|
231
|
+
defaultValue: 'visible',
|
|
232
|
+
valueConverter: overflowConverter,
|
|
233
|
+
valueChanged(target, oldValue, newValue) {
|
|
234
|
+
if (newValue && appliedInSetNative(target, overflowYProperty))
|
|
235
|
+
return;
|
|
236
|
+
const view = getViewStyle(target.viewRef);
|
|
237
|
+
if (view) {
|
|
238
|
+
if (newValue) {
|
|
239
|
+
view.overflowY = newValue;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
// Revert to old value if newValue is invalid
|
|
243
|
+
target.overflowY = oldValue;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
const overflowShorthand = { cssName: 'overflow', longhands: [overflowXProperty, overflowYProperty], split: splitOverflow };
|
|
249
|
+
export const overflowProperty = masonShorthandProperty(overflowShorthand, function () {
|
|
250
|
+
if (this.overflowX === this.overflowY) {
|
|
251
|
+
return this.overflowX;
|
|
252
|
+
}
|
|
253
|
+
return `${this.overflowX} ${this.overflowY}`;
|
|
254
|
+
});
|
|
255
|
+
export const paddingProperty = new CssProperty({
|
|
256
|
+
name: 'padding',
|
|
257
|
+
cssName: 'padding',
|
|
258
|
+
});
|
|
259
|
+
// These four style-buffer fields were consumed by the natives all along but had
|
|
260
|
+
// no JS or CSS path to them: reserved StyleKeys nobody ever wrote. Same shape of
|
|
261
|
+
// gap as `list-style-type`. (`text-indent` and `font-variant-numeric` are
|
|
262
|
+
// deliberately left out — their offsets exist but nothing reads them yet, so
|
|
263
|
+
// exposing them would write bytes into the void.)
|
|
264
|
+
export const whiteSpaceProperty = new CssProperty({
|
|
265
|
+
name: 'whiteSpace',
|
|
266
|
+
cssName: 'white-space',
|
|
267
|
+
defaultValue: 'normal',
|
|
268
|
+
valueChanged(target, oldValue, newValue) {
|
|
269
|
+
const view = getViewStyle(target.viewRef);
|
|
270
|
+
if (view) {
|
|
271
|
+
view.whiteSpace = newValue;
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
/**
|
|
276
|
+
* CSS `touch-action` as the pan flags native scroll views read: 1 = pan-x,
|
|
277
|
+
* 2 = pan-y, 4 = pinch-zoom. A Mason scroll view only starts a drag along an
|
|
278
|
+
* axis every element from the touched one up to it allows, as browsers do.
|
|
279
|
+
*/
|
|
280
|
+
export function parseTouchAction(value) {
|
|
281
|
+
const v = String(value ?? 'auto')
|
|
282
|
+
.trim()
|
|
283
|
+
.toLowerCase();
|
|
284
|
+
if (v === 'auto' || v === '')
|
|
285
|
+
return 7;
|
|
286
|
+
if (v === 'none')
|
|
287
|
+
return 0;
|
|
288
|
+
if (v === 'manipulation')
|
|
289
|
+
return 7;
|
|
290
|
+
let flags = 0;
|
|
291
|
+
for (const part of v.split(/\s+/)) {
|
|
292
|
+
if (part === 'pan-x' || part === 'pan-left' || part === 'pan-right')
|
|
293
|
+
flags |= 1;
|
|
294
|
+
else if (part === 'pan-y' || part === 'pan-up' || part === 'pan-down')
|
|
295
|
+
flags |= 2;
|
|
296
|
+
else if (part === 'pinch-zoom')
|
|
297
|
+
flags |= 4;
|
|
298
|
+
}
|
|
299
|
+
return flags;
|
|
300
|
+
}
|
|
301
|
+
export const touchActionProperty = new CssProperty({
|
|
302
|
+
name: 'touchAction',
|
|
303
|
+
cssName: 'touch-action',
|
|
304
|
+
defaultValue: 'auto',
|
|
305
|
+
valueChanged(target, oldValue, newValue) {
|
|
306
|
+
const ref = target?.viewRef;
|
|
307
|
+
const view = ref ? (__ANDROID__ ? ref.get() : ref.deref()) : undefined;
|
|
308
|
+
if (view && view[isMasonView_]) {
|
|
309
|
+
view[touchAction_] = parseTouchAction(newValue);
|
|
310
|
+
view._applyTouchAction?.();
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
export const objectFitProperty = new CssProperty({
|
|
315
|
+
name: 'objectFit',
|
|
316
|
+
cssName: 'object-fit',
|
|
317
|
+
defaultValue: 'fill',
|
|
318
|
+
valueChanged(target, oldValue, newValue) {
|
|
319
|
+
const view = getViewStyle(target.viewRef);
|
|
320
|
+
if (view) {
|
|
321
|
+
view.objectFit = newValue;
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
export const textJustifyProperty = new CssProperty({
|
|
326
|
+
name: 'textJustify',
|
|
327
|
+
cssName: 'text-justify',
|
|
328
|
+
defaultValue: 'auto',
|
|
329
|
+
valueChanged(target, oldValue, newValue) {
|
|
330
|
+
const view = getViewStyle(target.viewRef);
|
|
331
|
+
if (view) {
|
|
332
|
+
view.textJustify = newValue;
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
export const backgroundPositionXProperty = new CssProperty({
|
|
337
|
+
name: 'backgroundPositionX',
|
|
338
|
+
cssName: 'background-position-x',
|
|
339
|
+
valueChanged(target, oldValue, newValue) {
|
|
340
|
+
const view = getViewStyle(target.viewRef);
|
|
341
|
+
if (view) {
|
|
342
|
+
view.backgroundPositionX = newValue;
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
export const backgroundPositionYProperty = new CssProperty({
|
|
347
|
+
name: 'backgroundPositionY',
|
|
348
|
+
cssName: 'background-position-y',
|
|
349
|
+
valueChanged(target, oldValue, newValue) {
|
|
350
|
+
const view = getViewStyle(target.viewRef);
|
|
351
|
+
if (view) {
|
|
352
|
+
view.backgroundPositionY = newValue;
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
export const backgroundOriginProperty = new CssProperty({
|
|
357
|
+
name: 'backgroundOrigin',
|
|
358
|
+
cssName: 'background-origin',
|
|
359
|
+
valueChanged(target, oldValue, newValue) {
|
|
360
|
+
const view = getViewStyle(target.viewRef);
|
|
361
|
+
if (view) {
|
|
362
|
+
view.backgroundOrigin = newValue;
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
export const backgroundAttachmentProperty = new CssProperty({
|
|
367
|
+
name: 'backgroundAttachment',
|
|
368
|
+
cssName: 'background-attachment',
|
|
369
|
+
valueChanged(target, oldValue, newValue) {
|
|
370
|
+
const view = getViewStyle(target.viewRef);
|
|
371
|
+
if (view) {
|
|
372
|
+
view.backgroundAttachment = newValue;
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
export const backgroundBlendModeProperty = new CssProperty({
|
|
377
|
+
name: 'backgroundBlendMode',
|
|
378
|
+
cssName: 'background-blend-mode',
|
|
379
|
+
valueChanged(target, oldValue, newValue) {
|
|
380
|
+
const view = getViewStyle(target.viewRef);
|
|
381
|
+
if (view) {
|
|
382
|
+
view.backgroundBlendMode = newValue;
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
export const textDecorationLineProperty = new CssProperty({
|
|
387
|
+
name: 'textDecorationLine',
|
|
388
|
+
cssName: 'text-decoration-line',
|
|
389
|
+
valueChanged(target, oldValue, newValue) {
|
|
390
|
+
const view = getViewStyle(target.viewRef);
|
|
391
|
+
if (view) {
|
|
392
|
+
view.textDecorationLine = newValue;
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
export const textDecorationStyleProperty = new CssProperty({
|
|
397
|
+
name: 'textDecorationStyle',
|
|
398
|
+
cssName: 'text-decoration-style',
|
|
399
|
+
valueChanged(target, oldValue, newValue) {
|
|
400
|
+
const view = getViewStyle(target.viewRef);
|
|
401
|
+
if (view) {
|
|
402
|
+
view.textDecorationStyle = newValue;
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
export const textDecorationColorProperty = new CssProperty({
|
|
407
|
+
name: 'textDecorationColor',
|
|
408
|
+
cssName: 'text-decoration-color',
|
|
409
|
+
valueChanged(target, oldValue, newValue) {
|
|
410
|
+
const view = getViewStyle(target.viewRef);
|
|
411
|
+
if (view) {
|
|
412
|
+
view.textDecorationColor = newValue;
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
export const textDecorationThicknessProperty = new CssProperty({
|
|
417
|
+
name: 'textDecorationThickness',
|
|
418
|
+
cssName: 'text-decoration-thickness',
|
|
419
|
+
valueChanged(target, oldValue, newValue) {
|
|
420
|
+
const view = getViewStyle(target.viewRef);
|
|
421
|
+
if (view) {
|
|
422
|
+
view.textDecorationThickness = newValue;
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
});
|
|
426
|
+
// `font-family` had no path at all: FONT_FAMILY_STATE exists with no value slot
|
|
427
|
+
// (the natives keep the family on a FontFace, not in the buffer), and core's
|
|
428
|
+
// fontInternalProperty.setNative hook in common.ts is Windows-only. So on both
|
|
429
|
+
// mobile platforms this was unsettable from CSS *and* from TS.
|
|
430
|
+
export const fontFamilyProperty = new CssProperty({
|
|
431
|
+
name: 'fontFamily',
|
|
432
|
+
cssName: 'font-family',
|
|
433
|
+
valueChanged(target, oldValue, newValue) {
|
|
434
|
+
const view = getViewStyle(target.viewRef);
|
|
435
|
+
if (view) {
|
|
436
|
+
view.fontFamily = newValue;
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
// ---------------------------------------------------------------------------
|
|
441
|
+
// Registering alongside @nativescript/core
|
|
442
|
+
// ---------------------------------------------------------------------------
|
|
443
|
+
//
|
|
444
|
+
// `CssProperty.register()` installs its accessors with Object.defineProperty, so
|
|
445
|
+
// for a CSS name core already owns the last registration wins outright — and
|
|
446
|
+
// masonkit registers after core. That silently shadowed core's handling of
|
|
447
|
+
// `margin`, `padding`, `background`, `background-*`, `border-color`,
|
|
448
|
+
// `border-radius`, `box-shadow`, `transform`, `vertical-align`, `text-overflow`,
|
|
449
|
+
// `align-content`, `flex` and `flex-flow` for **every view in the app**, mason's
|
|
450
|
+
// or not: a plain StackLayout with `margin: 10` in a stylesheet got nothing,
|
|
451
|
+
// because mason's property only implements setNative on mason's own ViewBase.
|
|
452
|
+
//
|
|
453
|
+
// So instead of replacing core's accessor, keep both and pick at assignment
|
|
454
|
+
// time: a mason view gets mason's, anything else keeps core's untouched.
|
|
455
|
+
// Foreign-only grid shorthands invert the selection to preserve existing Mason
|
|
456
|
+
// direct setters while foreign views use core's longhand priority machinery.
|
|
457
|
+
function registerAlongsideCore(property, target = 'mason') {
|
|
458
|
+
const proto = Style.prototype;
|
|
459
|
+
const keys = [property.name, property.cssName, property.cssLocalName].filter((key) => typeof key === 'string' && key.length > 0);
|
|
460
|
+
const core = new Map();
|
|
461
|
+
for (const key of keys) {
|
|
462
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, key);
|
|
463
|
+
if (descriptor)
|
|
464
|
+
core.set(key, descriptor);
|
|
465
|
+
}
|
|
466
|
+
property.register(Style);
|
|
467
|
+
for (const [key, coreDescriptor] of core) {
|
|
468
|
+
const masonDescriptor = Object.getOwnPropertyDescriptor(proto, key);
|
|
469
|
+
if (!masonDescriptor)
|
|
470
|
+
continue;
|
|
471
|
+
Object.defineProperty(proto, key, {
|
|
472
|
+
enumerable: masonDescriptor.enumerable ?? true,
|
|
473
|
+
configurable: true,
|
|
474
|
+
get() {
|
|
475
|
+
const descriptor = isMasonView(this) === (target === 'mason') ? masonDescriptor : coreDescriptor;
|
|
476
|
+
return descriptor.get?.call(this);
|
|
477
|
+
},
|
|
478
|
+
set(value) {
|
|
479
|
+
const descriptor = isMasonView(this) === (target === 'mason') ? masonDescriptor : coreDescriptor;
|
|
480
|
+
descriptor.set?.call(this, value);
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
registerAlongsideCore(paddingProperty);
|
|
486
|
+
export const marginProperty = new CssProperty({
|
|
487
|
+
name: 'margin',
|
|
488
|
+
cssName: 'margin',
|
|
489
|
+
});
|
|
490
|
+
export const scrollBarWidthProperty = new CssProperty({
|
|
491
|
+
name: 'scrollBarWidth',
|
|
492
|
+
cssName: 'scrollbar-width',
|
|
493
|
+
defaultValue: 0,
|
|
494
|
+
valueConverter: parseFloat,
|
|
495
|
+
});
|
|
496
|
+
// Core keeps these parsers private, so the fallbacks below have to restate them.
|
|
497
|
+
// The value lists mirror @nativescript/core exactly — flexbox-layout-common's
|
|
498
|
+
// FlexWrap and text-base-common's textAlignment/textTransform converters.
|
|
499
|
+
const FlexWrapParse = makeParser(makeValidator('nowrap', 'wrap', 'wrap-reverse'));
|
|
500
|
+
const FlexDirectionParse = makeParser(makeValidator('row', 'row-reverse', 'column', 'column-reverse'));
|
|
501
|
+
const TextAlignmentParse = makeParser(makeValidator('left', 'center', 'right', 'justify'));
|
|
502
|
+
const TextTransformParse = makeParser(makeValidator('none', 'capitalize', 'uppercase', 'lowercase'));
|
|
503
|
+
/**
|
|
504
|
+
* Narrow one of @nativescript/core's own properties so mason views get mason's
|
|
505
|
+
* handling and every other view keeps core's, untouched. `overrideHandlers`
|
|
506
|
+
* replaces core's handlers outright, so the fallback to core's own handling
|
|
507
|
+
* has to be named explicitly.
|
|
508
|
+
*/
|
|
509
|
+
function overrideForMasonViews(property, options) {
|
|
510
|
+
const handlers = {
|
|
511
|
+
valueChanged(target, _oldValue, newValue) {
|
|
512
|
+
if (appliedInSetNative(target, property))
|
|
513
|
+
return;
|
|
514
|
+
const masonStyle = getViewStyle(target.viewRef);
|
|
515
|
+
// No mason style means a plain NativeScript view: core's setNative owns
|
|
516
|
+
// it, so leave the value exactly as core produced it.
|
|
517
|
+
if (!masonStyle) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
options.apply(masonStyle, newValue);
|
|
521
|
+
},
|
|
522
|
+
};
|
|
523
|
+
if (options.coreConverter) {
|
|
524
|
+
handlers.valueConverter = function (value) {
|
|
525
|
+
// Mason parses CSS itself, so its own elements get the raw declaration.
|
|
526
|
+
return isMasonView(this) ? value : options.coreConverter(value);
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
property.overrideHandlers(handlers);
|
|
530
|
+
}
|
|
531
|
+
const rawDeclarations = new WeakMap();
|
|
532
|
+
/** Plain views keep core's number; a mason view also records the raw declaration so its units survive. */
|
|
533
|
+
function keepRawDeclarationForMasonViews(property, coreConverter) {
|
|
534
|
+
property.overrideHandlers({
|
|
535
|
+
valueConverter(value) {
|
|
536
|
+
const converted = coreConverter(value);
|
|
537
|
+
if (isMasonView(this)) {
|
|
538
|
+
let raw = rawDeclarations.get(this);
|
|
539
|
+
if (!raw) {
|
|
540
|
+
raw = new Map();
|
|
541
|
+
rawDeclarations.set(this, raw);
|
|
542
|
+
}
|
|
543
|
+
raw.set(property.name, { converted, raw: value });
|
|
544
|
+
}
|
|
545
|
+
return converted;
|
|
546
|
+
},
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
/** The declaration behind `value` if it came from this view's own CSS, else `value`. */
|
|
550
|
+
export function masonRawDeclaration(style, propertyName, value) {
|
|
551
|
+
const raw = rawDeclarations.get(style)?.get(propertyName);
|
|
552
|
+
if (!raw) {
|
|
553
|
+
return value;
|
|
554
|
+
}
|
|
555
|
+
if (Object.is(raw.converted, value)) {
|
|
556
|
+
return raw.raw;
|
|
557
|
+
}
|
|
558
|
+
rawDeclarations.get(style).delete(propertyName);
|
|
559
|
+
return value;
|
|
560
|
+
}
|
|
561
|
+
keepRawDeclarationForMasonViews(lineHeightProperty, (v) => parseFloat(v));
|
|
562
|
+
keepRawDeclarationForMasonViews(letterSpacingProperty, (v) => parseFloat(v));
|
|
563
|
+
overrideForMasonViews(flexDirectionProperty, {
|
|
564
|
+
coreConverter: FlexDirectionParse,
|
|
565
|
+
apply: (style, value) => {
|
|
566
|
+
style.flexDirection = value;
|
|
567
|
+
},
|
|
568
|
+
});
|
|
569
|
+
overrideForMasonViews(flexWrapProperty, {
|
|
570
|
+
coreConverter: FlexWrapParse,
|
|
571
|
+
apply: (style, value) => {
|
|
572
|
+
style.flexWrap = value;
|
|
573
|
+
},
|
|
574
|
+
});
|
|
575
|
+
flexGrowProperty.overrideHandlers({
|
|
576
|
+
name: 'flexGrow',
|
|
577
|
+
cssName: 'flex-grow',
|
|
578
|
+
valueChanged(target, oldValue, newValue) {
|
|
579
|
+
if (typeof newValue === 'number' && !isNaN(newValue) && appliedInSetNative(target, flexGrowProperty))
|
|
580
|
+
return;
|
|
581
|
+
const view = getViewStyle(target.viewRef);
|
|
582
|
+
if (view) {
|
|
583
|
+
// 0 is a valid flex-grow; don't treat it as falsy/invalid
|
|
584
|
+
if (typeof newValue === 'number' && !isNaN(newValue)) {
|
|
585
|
+
view.flexGrow = newValue;
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
// Revert to old value if newValue is invalid
|
|
589
|
+
// @ts-ignore
|
|
590
|
+
target.flexGrow = oldValue;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
});
|
|
595
|
+
fontSizeProperty.overrideHandlers({
|
|
596
|
+
name: 'fontSize',
|
|
597
|
+
cssName: 'font-size',
|
|
598
|
+
valueConverter: function (value) {
|
|
599
|
+
if (isMasonView(this)) {
|
|
600
|
+
return value;
|
|
601
|
+
}
|
|
602
|
+
return parseFloat(value);
|
|
603
|
+
},
|
|
604
|
+
valueChanged(target, oldValue, newValue) {
|
|
605
|
+
if (newValue && appliedInSetNative(target, fontSizeProperty))
|
|
606
|
+
return;
|
|
607
|
+
const view = getViewStyle(target.viewRef);
|
|
608
|
+
if (view) {
|
|
609
|
+
if (newValue) {
|
|
610
|
+
if (typeof newValue === 'string') {
|
|
611
|
+
// @ts-ignore
|
|
612
|
+
if (isCssMathFunction(newValue)) {
|
|
613
|
+
// Mason's setter evaluates calc()/min()/max()/clamp() itself.
|
|
614
|
+
view.fontSize = newValue;
|
|
615
|
+
// @ts-ignore
|
|
616
|
+
}
|
|
617
|
+
else if (newValue.indexOf('%') !== -1) {
|
|
618
|
+
view.fontSize = {
|
|
619
|
+
value: parseFloat(newValue) / 100,
|
|
620
|
+
unit: '%',
|
|
621
|
+
};
|
|
622
|
+
// @ts-ignore
|
|
623
|
+
}
|
|
624
|
+
else if (newValue.indexOf('dip') !== -1) {
|
|
625
|
+
view.fontSize = parseFloat(newValue);
|
|
626
|
+
// @ts-ignore
|
|
627
|
+
}
|
|
628
|
+
else if (newValue.indexOf('px') !== -1) {
|
|
629
|
+
view.fontSize = {
|
|
630
|
+
value: parseFloat(newValue),
|
|
631
|
+
unit: 'px',
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
else {
|
|
635
|
+
view.fontSize = parseFloat(newValue);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
view.fontSize = newValue;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
// Revert to old value if newValue is invalid
|
|
644
|
+
// @ts-ignore
|
|
645
|
+
target.fontSize = oldValue;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
// fallback to core behavior
|
|
650
|
+
const currentFont = target.fontInternal || Font.default;
|
|
651
|
+
if (currentFont.fontSize !== newValue) {
|
|
652
|
+
const newFont = currentFont.withFontSize(newValue);
|
|
653
|
+
target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
});
|
|
658
|
+
export const rowGapProperty = new CssProperty({
|
|
659
|
+
name: 'rowGap',
|
|
660
|
+
cssName: 'row-gap',
|
|
661
|
+
defaultValue: 0,
|
|
662
|
+
// @ts-ignore
|
|
663
|
+
valueConverter: masonGapConverter,
|
|
664
|
+
// @ts-ignore
|
|
665
|
+
equalityComparer: masonLengthEquals,
|
|
666
|
+
valueChanged(target, oldValue, newValue) {
|
|
667
|
+
if (appliedInSetNative(target, rowGapProperty))
|
|
668
|
+
return;
|
|
669
|
+
const view = getViewStyle(target.viewRef);
|
|
670
|
+
if (view) {
|
|
671
|
+
view.rowGap = newValue;
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
});
|
|
675
|
+
export const columnGapProperty = new CssProperty({
|
|
676
|
+
name: 'columnGap',
|
|
677
|
+
cssName: 'column-gap',
|
|
678
|
+
defaultValue: 0,
|
|
679
|
+
// @ts-ignore
|
|
680
|
+
valueConverter: masonGapConverter,
|
|
681
|
+
// @ts-ignore
|
|
682
|
+
equalityComparer: masonLengthEquals,
|
|
683
|
+
valueChanged(target, oldValue, newValue) {
|
|
684
|
+
if (appliedInSetNative(target, columnGapProperty))
|
|
685
|
+
return;
|
|
686
|
+
const view = getViewStyle(target.viewRef);
|
|
687
|
+
if (view) {
|
|
688
|
+
view.columnGap = newValue;
|
|
689
|
+
}
|
|
690
|
+
},
|
|
691
|
+
});
|
|
692
|
+
/** A gap longhand as CSS text: CSS text as is, a number in px, a core length as `<n><unit>`. */
|
|
693
|
+
function gapText(value) {
|
|
694
|
+
if (typeof value === 'number') {
|
|
695
|
+
return `${value}px`;
|
|
696
|
+
}
|
|
697
|
+
if (value && typeof value === 'object') {
|
|
698
|
+
const { value: amount, unit } = value;
|
|
699
|
+
return unit === '%' ? `${Math.round((amount ?? 0) * 1e6) / 1e4}%` : `${amount ?? 0}${unit === 'dip' ? 'px' : (unit ?? 'px')}`;
|
|
700
|
+
}
|
|
701
|
+
return String(value ?? '');
|
|
702
|
+
}
|
|
703
|
+
function gapGetter() {
|
|
704
|
+
if (this.rowGap === this.columnGap) {
|
|
705
|
+
return this.rowGap;
|
|
706
|
+
}
|
|
707
|
+
const row = gapText(this.rowGap);
|
|
708
|
+
const column = gapText(this.columnGap);
|
|
709
|
+
// Two equal parses are different objects.
|
|
710
|
+
return row === column ? row : `${row} ${column}`;
|
|
711
|
+
}
|
|
712
|
+
const gapShorthand = { cssName: 'gap', longhands: [rowGapProperty, columnGapProperty], split: splitGap };
|
|
713
|
+
const gridGapShorthand = { ...gapShorthand, cssName: 'grid-gap' };
|
|
714
|
+
export const gridGapProperty = masonShorthandProperty(gridGapShorthand, gapGetter);
|
|
715
|
+
export const gapProperty = masonShorthandProperty(gapShorthand, gapGetter);
|
|
716
|
+
export const gridRowGapProperty = new ShorthandProperty({
|
|
717
|
+
name: 'gridRowGap',
|
|
718
|
+
cssName: 'grid-row-gap',
|
|
719
|
+
getter: function () {
|
|
720
|
+
return this.rowGap;
|
|
721
|
+
},
|
|
722
|
+
converter(value) {
|
|
723
|
+
return [[rowGapProperty, value]];
|
|
724
|
+
},
|
|
725
|
+
});
|
|
726
|
+
export const gridColumnGapProperty = new ShorthandProperty({
|
|
727
|
+
name: 'gridColumnGap',
|
|
728
|
+
cssName: 'grid-column-gap',
|
|
729
|
+
getter: function () {
|
|
730
|
+
return this.columnGap;
|
|
731
|
+
},
|
|
732
|
+
converter(value) {
|
|
733
|
+
return [[columnGapProperty, value]];
|
|
734
|
+
},
|
|
735
|
+
});
|
|
736
|
+
overrideForMasonViews(textAlignmentProperty, {
|
|
737
|
+
coreConverter: TextAlignmentParse,
|
|
738
|
+
apply: (style, value) => {
|
|
739
|
+
style.textAlignment = value;
|
|
740
|
+
},
|
|
741
|
+
});
|
|
742
|
+
overrideForMasonViews(textTransformProperty, {
|
|
743
|
+
coreConverter: TextTransformParse,
|
|
744
|
+
apply: (style, value) => {
|
|
745
|
+
style.textTransform = value;
|
|
746
|
+
},
|
|
747
|
+
});
|
|
748
|
+
function masonLengthParse(value) {
|
|
749
|
+
try {
|
|
750
|
+
return CoreLength.parse(value);
|
|
751
|
+
}
|
|
752
|
+
catch (e) {
|
|
753
|
+
return undefined;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
function masonLengthPercentParse(value) {
|
|
757
|
+
try {
|
|
758
|
+
return CorePercentLength.parse(value);
|
|
759
|
+
}
|
|
760
|
+
catch (e) {
|
|
761
|
+
return undefined;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
/** Lengths in units core's parsers read as bare numbers. */
|
|
765
|
+
const UNITS_CORE_MISREADS = /^[+-]?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?(r?em|pt|vw|vh|vmin|vmax|dppx)$/i;
|
|
766
|
+
/** CSS text for a length in a unit core can't parse (rem, em, vw), else undefined. */
|
|
767
|
+
function masonLengthText(value) {
|
|
768
|
+
if (typeof value !== 'string') {
|
|
769
|
+
return undefined;
|
|
770
|
+
}
|
|
771
|
+
const t = value.trim();
|
|
772
|
+
// Core can't evaluate math functions either; Mason's setter does.
|
|
773
|
+
return UNITS_CORE_MISREADS.test(t) || isCssMathFunction(t) ? t : undefined;
|
|
774
|
+
}
|
|
775
|
+
/** `left`/`top`/`right`/`bottom`: Mason's units, else core's parse (`%`, `auto`). */
|
|
776
|
+
function masonInsetConverter(value) {
|
|
777
|
+
return (masonLengthText(value) ?? masonLengthPercentParse(value));
|
|
778
|
+
}
|
|
779
|
+
/** `row-gap`/`column-gap`: as the insets, but anything unparsable is 0. */
|
|
780
|
+
function masonGapConverter(value) {
|
|
781
|
+
const text = masonLengthText(value);
|
|
782
|
+
if (text !== undefined) {
|
|
783
|
+
return text;
|
|
784
|
+
}
|
|
785
|
+
const parsed = masonLengthPercentParse(value);
|
|
786
|
+
if (parsed === undefined || typeof parsed === 'string') {
|
|
787
|
+
return 0;
|
|
788
|
+
}
|
|
789
|
+
return parsed;
|
|
790
|
+
}
|
|
791
|
+
/** Compares CSS text as text: core's `PercentLength.equals` calls any two strings equal. */
|
|
792
|
+
function masonLengthEquals(a, b) {
|
|
793
|
+
if (typeof a === 'string' || typeof b === 'string') {
|
|
794
|
+
return a === b;
|
|
795
|
+
}
|
|
796
|
+
return CorePercentLength.equals(a, b);
|
|
797
|
+
}
|
|
798
|
+
/** As `masonSizeConverter`, for Mason's own max-* properties (core has none). */
|
|
799
|
+
function masonMaxSizeConverter(value) {
|
|
800
|
+
const resolved = masonSizeValue(value);
|
|
801
|
+
return (resolved ?? masonLengthPercentParse(value));
|
|
802
|
+
}
|
|
803
|
+
export const maxWidthProperty = new CssProperty({
|
|
804
|
+
name: 'maxWidth',
|
|
805
|
+
cssName: 'max-width',
|
|
806
|
+
defaultValue: 'auto',
|
|
807
|
+
// @ts-ignore
|
|
808
|
+
equalityComparer: CorePercentLength.equals,
|
|
809
|
+
// masonLengthParse has no '%' handling; match width/height's converter.
|
|
810
|
+
// @ts-ignore
|
|
811
|
+
valueConverter: masonMaxSizeConverter,
|
|
812
|
+
valueChanged: (target, oldValue, newValue) => {
|
|
813
|
+
if (appliedInSetNative(target, maxWidthProperty))
|
|
814
|
+
return;
|
|
815
|
+
const view = getViewStyle(target.viewRef);
|
|
816
|
+
if (view) {
|
|
817
|
+
view.maxWidth = newValue;
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
Trace.write(`${newValue} not set to view's property because ".viewRef" is cleared`, Trace.categories.Style, Trace.messageType.warn);
|
|
821
|
+
}
|
|
822
|
+
},
|
|
823
|
+
});
|
|
824
|
+
export const maxHeightProperty = new CssProperty({
|
|
825
|
+
name: 'maxHeight',
|
|
826
|
+
cssName: 'max-height',
|
|
827
|
+
defaultValue: 'auto',
|
|
828
|
+
// @ts-ignore
|
|
829
|
+
equalityComparer: CorePercentLength.equals,
|
|
830
|
+
// @ts-ignore
|
|
831
|
+
valueConverter: masonMaxSizeConverter,
|
|
832
|
+
valueChanged(target, oldValue, newValue) {
|
|
833
|
+
if (appliedInSetNative(target, maxHeightProperty))
|
|
834
|
+
return;
|
|
835
|
+
const view = getViewStyle(target.viewRef);
|
|
836
|
+
if (view) {
|
|
837
|
+
view.maxHeight = newValue;
|
|
838
|
+
}
|
|
839
|
+
},
|
|
840
|
+
});
|
|
841
|
+
// Core's minWidth/minHeight already route into this Style via setNative
|
|
842
|
+
// (common.ts), so no new CssProperty is needed — just fix the '%' handling.
|
|
843
|
+
// Core's min-width/min-height converter is Length.parse, which has no '%'
|
|
844
|
+
// handling; mason needs percentages. Core's own valueChanged (which sets
|
|
845
|
+
// effectiveMinWidth) is deliberately left in place for both kinds of view, so
|
|
846
|
+
// only the converter is narrowed — a plain view must still get a plain Length,
|
|
847
|
+
// or core's Length.toDevicePixels mis-reads a percentage.
|
|
848
|
+
/**
|
|
849
|
+
* Resolve a size value with Mason's own length parser before core sees it.
|
|
850
|
+
*
|
|
851
|
+
* `width`/`height`/`min-*` reach core's `PercentLength.parse` first, which
|
|
852
|
+
* misreads `100vh`/`1rem` as a bare dip count and `px` as a device pixel
|
|
853
|
+
* rather than Mason's CSS pixel. Resolve every unit Mason understands here
|
|
854
|
+
* as the equivalent dip; percentages, `auto` and keywords fall through
|
|
855
|
+
* untouched.
|
|
856
|
+
*/
|
|
857
|
+
function masonSizeValue(value) {
|
|
858
|
+
const dip = cssLengthToDip(value);
|
|
859
|
+
return dip === undefined ? undefined : { value: dip, unit: 'dip' };
|
|
860
|
+
}
|
|
861
|
+
function masonMinSizeConverter(value) {
|
|
862
|
+
if (isMasonView(this)) {
|
|
863
|
+
const resolved = masonSizeValue(value);
|
|
864
|
+
if (resolved) {
|
|
865
|
+
return resolved;
|
|
866
|
+
}
|
|
867
|
+
return masonLengthPercentParse(value);
|
|
868
|
+
}
|
|
869
|
+
return CoreLength.parse(value);
|
|
870
|
+
}
|
|
871
|
+
minWidthProperty.overrideHandlers({
|
|
872
|
+
name: 'minWidth',
|
|
873
|
+
cssName: 'min-width',
|
|
874
|
+
// @ts-ignore
|
|
875
|
+
equalityComparer: CorePercentLength.equals,
|
|
876
|
+
// @ts-ignore
|
|
877
|
+
valueConverter: masonMinSizeConverter,
|
|
878
|
+
});
|
|
879
|
+
minHeightProperty.overrideHandlers({
|
|
880
|
+
name: 'minHeight',
|
|
881
|
+
cssName: 'min-height',
|
|
882
|
+
// @ts-ignore
|
|
883
|
+
equalityComparer: CorePercentLength.equals,
|
|
884
|
+
// @ts-ignore
|
|
885
|
+
valueConverter: masonMinSizeConverter,
|
|
886
|
+
});
|
|
887
|
+
/**
|
|
888
|
+
* Rewrite a size declaration for mason views before core parses it.
|
|
889
|
+
*
|
|
890
|
+
* `width`/`height` are `CssAnimationProperty`s with no `overrideHandlers`, so
|
|
891
|
+
* mason can't narrow their converter the way it does for `min-*`. Rewriting
|
|
892
|
+
* the declaration itself works instead: `100vh` becomes its resolved dip
|
|
893
|
+
* count, which core's parser then reads correctly (and, deliberately, so
|
|
894
|
+
* does a bare `px`, which core reads as a device pixel but mason as a CSS
|
|
895
|
+
* pixel).
|
|
896
|
+
*/
|
|
897
|
+
function masonLengthDeclaration(value) {
|
|
898
|
+
if (typeof value !== 'string') {
|
|
899
|
+
return value;
|
|
900
|
+
}
|
|
901
|
+
const keyword = sizingKeywordLength(value);
|
|
902
|
+
if (keyword) {
|
|
903
|
+
return keyword;
|
|
904
|
+
}
|
|
905
|
+
const dip = cssLengthToDip(value);
|
|
906
|
+
// A bare number is a dip to core and a CSS pixel to mason — the same size.
|
|
907
|
+
return dip === undefined ? value : String(dip);
|
|
908
|
+
}
|
|
909
|
+
/** Core throws on sizing keywords; a negative length reads as auto to core and carries the keyword as its unit. */
|
|
910
|
+
function sizingKeywordLength(value) {
|
|
911
|
+
return isSizingKeyword(value) ? { unit: value.trim(), value: -2 } : undefined;
|
|
912
|
+
}
|
|
913
|
+
const MASON_SIZE_KEYS = [widthProperty, heightProperty, minWidthProperty, minHeightProperty, maxWidthProperty, maxHeightProperty].flatMap((property) => [property.name, property.cssName, property.cssLocalName]).filter((key) => typeof key === 'string' && key.length > 0);
|
|
914
|
+
/**
|
|
915
|
+
* The stylesheet-facing accessor a `CssAnimationProperty` installs is
|
|
916
|
+
* non-configurable, so it can't be overridden on `Style.prototype`. Shadow it
|
|
917
|
+
* on a prototype between `Style.prototype` and each mason view's Style.
|
|
918
|
+
*/
|
|
919
|
+
const masonStyleProtos = new WeakMap();
|
|
920
|
+
function masonStyleProto(proto) {
|
|
921
|
+
let masonProto = masonStyleProtos.get(proto);
|
|
922
|
+
if (masonProto) {
|
|
923
|
+
return masonProto;
|
|
924
|
+
}
|
|
925
|
+
masonProto = Object.create(proto);
|
|
926
|
+
for (const key of new Set(MASON_SIZE_KEYS)) {
|
|
927
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, key);
|
|
928
|
+
const set = descriptor?.set;
|
|
929
|
+
const get = descriptor?.get;
|
|
930
|
+
if (!set) {
|
|
931
|
+
continue;
|
|
932
|
+
}
|
|
933
|
+
Object.defineProperty(masonProto, key, {
|
|
934
|
+
enumerable: false,
|
|
935
|
+
configurable: true,
|
|
936
|
+
get,
|
|
937
|
+
set(value) {
|
|
938
|
+
beginStyleWrite(this, key, value);
|
|
939
|
+
try {
|
|
940
|
+
set.call(this, masonLengthDeclaration(environmentStyleValue(this, key, value)));
|
|
941
|
+
}
|
|
942
|
+
finally {
|
|
943
|
+
endStyleWrite();
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
Object.defineProperty(masonProto, MASON_SIZE_UNITS, { value: true, enumerable: false });
|
|
949
|
+
masonStyleProtos.set(proto, masonProto);
|
|
950
|
+
return masonProto;
|
|
951
|
+
}
|
|
952
|
+
export function installMasonSizeUnits(style) {
|
|
953
|
+
if (!style || style[MASON_SIZE_UNITS]) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
Object.setPrototypeOf(style, masonStyleProto(Object.getPrototypeOf(style)));
|
|
957
|
+
}
|
|
958
|
+
export const insetProperty = new ShorthandProperty({
|
|
959
|
+
name: 'inset',
|
|
960
|
+
cssName: 'inset',
|
|
961
|
+
getter: function () {
|
|
962
|
+
if (this.top === this.right && this.top === this.bottom && this.top === this.left) {
|
|
963
|
+
if (typeof this.top === 'string') {
|
|
964
|
+
if (this.top === 'auto') {
|
|
965
|
+
return this.top;
|
|
966
|
+
}
|
|
967
|
+
const value = CorePercentLength.parse(this.top);
|
|
968
|
+
if (Number.isNaN(value)) {
|
|
969
|
+
return this.top;
|
|
970
|
+
}
|
|
971
|
+
else {
|
|
972
|
+
return CorePercentLength.convertToString(value);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (CorePercentLength.equals(this.top, this.right) && CorePercentLength.equals(this.top, this.bottom) && CorePercentLength.equals(this.top, this.left)) {
|
|
977
|
+
return this.top;
|
|
978
|
+
}
|
|
979
|
+
return `${CorePercentLength.convertToString(this.paddingTop)} ${CorePercentLength.convertToString(this.paddingRight)} ${CorePercentLength.convertToString(this.paddingBottom)} ${CorePercentLength.convertToString(this.paddingLeft)}`;
|
|
980
|
+
},
|
|
981
|
+
converter: convertToInsets,
|
|
982
|
+
});
|
|
983
|
+
function parseShorthandPositioning(value) {
|
|
984
|
+
const arr = value.split(/[ ,]+/);
|
|
985
|
+
let top;
|
|
986
|
+
let right;
|
|
987
|
+
let bottom;
|
|
988
|
+
let left;
|
|
989
|
+
if (arr.length === 1) {
|
|
990
|
+
top = arr[0];
|
|
991
|
+
right = arr[0];
|
|
992
|
+
bottom = arr[0];
|
|
993
|
+
left = arr[0];
|
|
994
|
+
}
|
|
995
|
+
else if (arr.length === 2) {
|
|
996
|
+
top = arr[0];
|
|
997
|
+
bottom = arr[0];
|
|
998
|
+
right = arr[1];
|
|
999
|
+
left = arr[1];
|
|
1000
|
+
}
|
|
1001
|
+
else if (arr.length === 3) {
|
|
1002
|
+
top = arr[0];
|
|
1003
|
+
right = arr[1];
|
|
1004
|
+
left = arr[1];
|
|
1005
|
+
bottom = arr[2];
|
|
1006
|
+
}
|
|
1007
|
+
else if (arr.length === 4) {
|
|
1008
|
+
top = arr[0];
|
|
1009
|
+
right = arr[1];
|
|
1010
|
+
bottom = arr[2];
|
|
1011
|
+
left = arr[3];
|
|
1012
|
+
}
|
|
1013
|
+
else {
|
|
1014
|
+
throw new Error('Expected 1, 2, 3 or 4 parameters. Actual: ' + value);
|
|
1015
|
+
}
|
|
1016
|
+
return {
|
|
1017
|
+
top: top,
|
|
1018
|
+
right: right,
|
|
1019
|
+
bottom: bottom,
|
|
1020
|
+
left: left,
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
function convertToInsets(value) {
|
|
1024
|
+
if (typeof value === 'string' && value !== 'auto') {
|
|
1025
|
+
const thickness = parseShorthandPositioning(value);
|
|
1026
|
+
return [
|
|
1027
|
+
[topProperty, masonInsetConverter(thickness.top)],
|
|
1028
|
+
[rightProperty, masonInsetConverter(thickness.right)],
|
|
1029
|
+
[bottomProperty, masonInsetConverter(thickness.bottom)],
|
|
1030
|
+
[leftProperty, masonInsetConverter(thickness.left)],
|
|
1031
|
+
];
|
|
1032
|
+
}
|
|
1033
|
+
else {
|
|
1034
|
+
return [
|
|
1035
|
+
[topProperty, value],
|
|
1036
|
+
[rightProperty, value],
|
|
1037
|
+
[bottomProperty, value],
|
|
1038
|
+
[leftProperty, value],
|
|
1039
|
+
];
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
export const leftProperty = new CssProperty({
|
|
1043
|
+
name: 'left',
|
|
1044
|
+
cssName: 'left',
|
|
1045
|
+
defaultValue: 'auto',
|
|
1046
|
+
// @ts-ignore
|
|
1047
|
+
equalityComparer: masonLengthEquals,
|
|
1048
|
+
// @ts-ignore
|
|
1049
|
+
valueConverter: masonInsetConverter,
|
|
1050
|
+
valueChanged(target, oldValue, newValue) {
|
|
1051
|
+
if (appliedInSetNative(target, leftProperty))
|
|
1052
|
+
return;
|
|
1053
|
+
const view = getViewStyle(target.viewRef);
|
|
1054
|
+
if (view) {
|
|
1055
|
+
view.left = newValue;
|
|
1056
|
+
}
|
|
1057
|
+
},
|
|
1058
|
+
});
|
|
1059
|
+
export const rightProperty = new CssProperty({
|
|
1060
|
+
name: 'right',
|
|
1061
|
+
cssName: 'right',
|
|
1062
|
+
defaultValue: 'auto',
|
|
1063
|
+
// @ts-ignore
|
|
1064
|
+
equalityComparer: masonLengthEquals,
|
|
1065
|
+
// @ts-ignore
|
|
1066
|
+
valueConverter: masonInsetConverter,
|
|
1067
|
+
valueChanged(target, oldValue, newValue) {
|
|
1068
|
+
if (appliedInSetNative(target, rightProperty))
|
|
1069
|
+
return;
|
|
1070
|
+
const view = getViewStyle(target.viewRef);
|
|
1071
|
+
if (view) {
|
|
1072
|
+
view.right = newValue;
|
|
1073
|
+
}
|
|
1074
|
+
},
|
|
1075
|
+
});
|
|
1076
|
+
export const topProperty = new CssProperty({
|
|
1077
|
+
name: 'top',
|
|
1078
|
+
cssName: 'top',
|
|
1079
|
+
defaultValue: 'auto',
|
|
1080
|
+
// @ts-ignore
|
|
1081
|
+
equalityComparer: masonLengthEquals,
|
|
1082
|
+
// @ts-ignore
|
|
1083
|
+
valueConverter: masonInsetConverter,
|
|
1084
|
+
valueChanged(target, oldValue, newValue) {
|
|
1085
|
+
if (appliedInSetNative(target, topProperty))
|
|
1086
|
+
return;
|
|
1087
|
+
const view = getViewStyle(target.viewRef);
|
|
1088
|
+
if (view) {
|
|
1089
|
+
view.top = newValue;
|
|
1090
|
+
}
|
|
1091
|
+
},
|
|
1092
|
+
});
|
|
1093
|
+
export const bottomProperty = new CssProperty({
|
|
1094
|
+
name: 'bottom',
|
|
1095
|
+
cssName: 'bottom',
|
|
1096
|
+
defaultValue: 'auto',
|
|
1097
|
+
// @ts-ignore
|
|
1098
|
+
equalityComparer: masonLengthEquals,
|
|
1099
|
+
// @ts-ignore
|
|
1100
|
+
valueConverter: masonInsetConverter,
|
|
1101
|
+
valueChanged(target, oldValue, newValue) {
|
|
1102
|
+
if (appliedInSetNative(target, bottomProperty))
|
|
1103
|
+
return;
|
|
1104
|
+
const view = getViewStyle(target.viewRef);
|
|
1105
|
+
if (view) {
|
|
1106
|
+
view.bottom = newValue;
|
|
1107
|
+
}
|
|
1108
|
+
},
|
|
1109
|
+
});
|
|
1110
|
+
export const positionProperty = new CssProperty({
|
|
1111
|
+
name: 'position',
|
|
1112
|
+
cssName: 'position',
|
|
1113
|
+
defaultValue: 'static',
|
|
1114
|
+
valueChanged(target, oldValue, newValue) {
|
|
1115
|
+
if (appliedInSetNative(target, positionProperty))
|
|
1116
|
+
return;
|
|
1117
|
+
const view = getViewStyle(target.viewRef);
|
|
1118
|
+
if (view) {
|
|
1119
|
+
view.position = newValue;
|
|
1120
|
+
}
|
|
1121
|
+
},
|
|
1122
|
+
});
|
|
1123
|
+
export const boxSizingProperty = new CssProperty({
|
|
1124
|
+
name: 'boxSizing',
|
|
1125
|
+
cssName: 'box-sizing',
|
|
1126
|
+
defaultValue: 'border-box',
|
|
1127
|
+
valueChanged(target, oldValue, newValue) {
|
|
1128
|
+
if (newValue && appliedInSetNative(target, boxSizingProperty))
|
|
1129
|
+
return;
|
|
1130
|
+
const view = getViewStyle(target.viewRef);
|
|
1131
|
+
if (view) {
|
|
1132
|
+
if (newValue) {
|
|
1133
|
+
view.boxSizing = newValue;
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
// Revert to old value if newValue is invalid
|
|
1137
|
+
target.boxSizing = oldValue;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
valueConverter(value) {
|
|
1142
|
+
switch (value) {
|
|
1143
|
+
case 'content-box':
|
|
1144
|
+
case 'border-box':
|
|
1145
|
+
return value;
|
|
1146
|
+
default:
|
|
1147
|
+
return undefined;
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
});
|
|
1151
|
+
export const borderRadiusProperty = new CssProperty({
|
|
1152
|
+
name: 'borderRadius',
|
|
1153
|
+
cssName: 'border-radius',
|
|
1154
|
+
});
|
|
1155
|
+
// Core's alignItems/alignSelf validator rejects Box Alignment keywords
|
|
1156
|
+
// ("start"/"end") masonkit's own Style setter accepts fine; bypass it for
|
|
1157
|
+
// Mason views/children like alignContent/justifyContent already do below.
|
|
1158
|
+
export const AlignItemsIsValid = makeValidator('normal', 'start', 'end', 'flex-start', 'flex-end', 'center', 'baseline', 'stretch');
|
|
1159
|
+
export const AlignItemsParse = makeParser(AlignItemsIsValid);
|
|
1160
|
+
export const AlignSelfIsValid = makeValidator('normal', 'start', 'end', 'flex-start', 'flex-end', 'center', 'baseline', 'stretch');
|
|
1161
|
+
export const AlignSelfParse = makeParser(AlignSelfIsValid);
|
|
1162
|
+
alignItemsProperty.overrideHandlers({
|
|
1163
|
+
name: 'alignItems',
|
|
1164
|
+
cssName: 'align-items',
|
|
1165
|
+
valueConverter: function (value) {
|
|
1166
|
+
if (isMasonView(this)) {
|
|
1167
|
+
return value;
|
|
1168
|
+
}
|
|
1169
|
+
return AlignItemsParse(value);
|
|
1170
|
+
},
|
|
1171
|
+
valueChanged(target, oldValue, newValue) {
|
|
1172
|
+
if (newValue && appliedInSetNative(target, alignItemsProperty))
|
|
1173
|
+
return;
|
|
1174
|
+
const view = getViewStyle(target.viewRef);
|
|
1175
|
+
if (view) {
|
|
1176
|
+
if (newValue) {
|
|
1177
|
+
view.alignItems = newValue;
|
|
1178
|
+
}
|
|
1179
|
+
else {
|
|
1180
|
+
// Revert to old value if newValue is invalid
|
|
1181
|
+
// @ts-ignore
|
|
1182
|
+
target.alignItems = oldValue;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
},
|
|
1186
|
+
});
|
|
1187
|
+
alignSelfProperty.overrideHandlers({
|
|
1188
|
+
name: 'alignSelf',
|
|
1189
|
+
cssName: 'align-self',
|
|
1190
|
+
valueConverter: function (value) {
|
|
1191
|
+
if (isMasonView(this)) {
|
|
1192
|
+
return value;
|
|
1193
|
+
}
|
|
1194
|
+
return AlignSelfParse(value);
|
|
1195
|
+
},
|
|
1196
|
+
valueChanged(target, oldValue, newValue) {
|
|
1197
|
+
if (newValue && appliedInSetNative(target, alignSelfProperty))
|
|
1198
|
+
return;
|
|
1199
|
+
const view = getViewStyle(target.viewRef);
|
|
1200
|
+
if (view) {
|
|
1201
|
+
if (newValue) {
|
|
1202
|
+
view.alignSelf = newValue;
|
|
1203
|
+
}
|
|
1204
|
+
else {
|
|
1205
|
+
// Revert to old value if newValue is invalid
|
|
1206
|
+
// @ts-ignore
|
|
1207
|
+
target.alignSelf = oldValue;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
},
|
|
1211
|
+
});
|
|
1212
|
+
export const AlignContentIsValid = makeValidator('flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly', 'stretch', 'normal', 'start', 'end');
|
|
1213
|
+
export const AlignContentParse = makeParser(AlignContentIsValid);
|
|
1214
|
+
export const alignContentProperty = new CssProperty({
|
|
1215
|
+
name: 'alignContent',
|
|
1216
|
+
cssName: 'align-content',
|
|
1217
|
+
defaultValue: 'normal',
|
|
1218
|
+
valueConverter: function (value) {
|
|
1219
|
+
if (isMasonView(this)) {
|
|
1220
|
+
return value;
|
|
1221
|
+
}
|
|
1222
|
+
return AlignContentParse(value);
|
|
1223
|
+
},
|
|
1224
|
+
valueChanged(target, oldValue, newValue) {
|
|
1225
|
+
if (newValue && appliedInSetNative(target, alignContentProperty))
|
|
1226
|
+
return;
|
|
1227
|
+
const view = getViewStyle(target.viewRef);
|
|
1228
|
+
if (view) {
|
|
1229
|
+
if (newValue) {
|
|
1230
|
+
view.alignContent = newValue;
|
|
1231
|
+
}
|
|
1232
|
+
else {
|
|
1233
|
+
// Revert to old value if newValue is invalid
|
|
1234
|
+
// @ts-ignore
|
|
1235
|
+
target.alignContent = oldValue;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
},
|
|
1239
|
+
});
|
|
1240
|
+
export const justifyItemsProperty = new CssProperty({
|
|
1241
|
+
name: 'justifyItems',
|
|
1242
|
+
cssName: 'justify-items',
|
|
1243
|
+
defaultValue: 'normal',
|
|
1244
|
+
valueChanged(target, oldValue, newValue) {
|
|
1245
|
+
if (newValue && appliedInSetNative(target, justifyItemsProperty))
|
|
1246
|
+
return;
|
|
1247
|
+
const view = getViewStyle(target.viewRef);
|
|
1248
|
+
if (view) {
|
|
1249
|
+
if (newValue) {
|
|
1250
|
+
view.justifyItems = newValue;
|
|
1251
|
+
}
|
|
1252
|
+
else {
|
|
1253
|
+
// Revert to old value if newValue is invalid
|
|
1254
|
+
// @ts-ignore
|
|
1255
|
+
target.justifyItems = oldValue;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1259
|
+
});
|
|
1260
|
+
export const justifySelfProperty = new CssProperty({
|
|
1261
|
+
name: 'justifySelf',
|
|
1262
|
+
cssName: 'justify-self',
|
|
1263
|
+
defaultValue: 'normal',
|
|
1264
|
+
valueChanged(target, oldValue, newValue) {
|
|
1265
|
+
if (newValue && appliedInSetNative(target, justifySelfProperty))
|
|
1266
|
+
return;
|
|
1267
|
+
const view = getViewStyle(target.viewRef);
|
|
1268
|
+
if (view) {
|
|
1269
|
+
if (newValue) {
|
|
1270
|
+
view.justifySelf = newValue;
|
|
1271
|
+
}
|
|
1272
|
+
else {
|
|
1273
|
+
// Revert to old value if newValue is invalid
|
|
1274
|
+
// @ts-ignore
|
|
1275
|
+
target.justifySelf = oldValue;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
},
|
|
1279
|
+
});
|
|
1280
|
+
export const placeShorthands = [
|
|
1281
|
+
{ cssName: 'place-items', longhands: [alignItemsProperty, justifyItemsProperty], split: splitPlace },
|
|
1282
|
+
{ cssName: 'place-content', longhands: [alignContentProperty, justifyContentProperty], split: splitPlace },
|
|
1283
|
+
{ cssName: 'place-self', longhands: [alignSelfProperty, justifySelfProperty], split: splitPlace },
|
|
1284
|
+
];
|
|
1285
|
+
for (const entry of placeShorthands) {
|
|
1286
|
+
masonShorthandProperty(entry).register(Style);
|
|
1287
|
+
}
|
|
1288
|
+
export const JustifyContentIsValid = makeValidator('flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly', 'stretch', 'normal', 'start', 'end');
|
|
1289
|
+
export const JustifyContentParse = makeParser(JustifyContentIsValid);
|
|
1290
|
+
justifyContentProperty.overrideHandlers({
|
|
1291
|
+
name: 'justifyContent',
|
|
1292
|
+
cssName: 'justify-content',
|
|
1293
|
+
valueConverter: function (value) {
|
|
1294
|
+
if (isMasonView(this)) {
|
|
1295
|
+
return value;
|
|
1296
|
+
}
|
|
1297
|
+
return JustifyContentParse(value);
|
|
1298
|
+
},
|
|
1299
|
+
valueChanged(target, oldValue, newValue) {
|
|
1300
|
+
if (newValue && appliedInSetNative(target, justifyContentProperty))
|
|
1301
|
+
return;
|
|
1302
|
+
const view = getViewStyle(target.viewRef);
|
|
1303
|
+
if (view) {
|
|
1304
|
+
if (newValue) {
|
|
1305
|
+
view.justifyContent = newValue;
|
|
1306
|
+
}
|
|
1307
|
+
else {
|
|
1308
|
+
// Revert to old value if newValue is invalid
|
|
1309
|
+
// @ts-ignore
|
|
1310
|
+
target.justifyContent = oldValue;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
},
|
|
1314
|
+
});
|
|
1315
|
+
export const flexBasisProperty = new CssProperty({
|
|
1316
|
+
name: 'flexBasis',
|
|
1317
|
+
cssName: 'flex-basis',
|
|
1318
|
+
defaultValue: 'auto',
|
|
1319
|
+
// @ts-ignore
|
|
1320
|
+
equalityComparer: masonLengthEquals,
|
|
1321
|
+
// @ts-ignore
|
|
1322
|
+
valueConverter: (value) => (isSizingKeyword(value) ? value.trim() : masonInsetConverter(value)),
|
|
1323
|
+
valueChanged(target, oldValue, newValue) {
|
|
1324
|
+
if (appliedInSetNative(target, flexBasisProperty))
|
|
1325
|
+
return;
|
|
1326
|
+
const view = getViewStyle(target.viewRef);
|
|
1327
|
+
if (view) {
|
|
1328
|
+
view.flexBasis = newValue;
|
|
1329
|
+
}
|
|
1330
|
+
},
|
|
1331
|
+
});
|
|
1332
|
+
export const aspectRatioProperty = new CssProperty({
|
|
1333
|
+
name: 'aspectRatio',
|
|
1334
|
+
cssName: 'aspect-ratio',
|
|
1335
|
+
defaultValue: Number.NaN,
|
|
1336
|
+
// Without this the raw declaration reached the buffer's setFloat32, where the
|
|
1337
|
+
// `<ratio>` form (`2 / 3`) coerces to NaN — i.e. no ratio at all.
|
|
1338
|
+
// @ts-ignore
|
|
1339
|
+
valueConverter: parseAspectRatio,
|
|
1340
|
+
valueChanged(target, oldValue, newValue) {
|
|
1341
|
+
if (appliedInSetNative(target, aspectRatioProperty))
|
|
1342
|
+
return;
|
|
1343
|
+
const view = getViewStyle(target.viewRef);
|
|
1344
|
+
if (view) {
|
|
1345
|
+
view.aspectRatio = newValue;
|
|
1346
|
+
}
|
|
1347
|
+
},
|
|
1348
|
+
});
|
|
1349
|
+
export const gridAutoRowsProperty = new CssProperty({
|
|
1350
|
+
name: 'gridAutoRows',
|
|
1351
|
+
cssName: 'grid-auto-rows',
|
|
1352
|
+
defaultValue: '',
|
|
1353
|
+
valueChanged(target, oldValue, newValue) {
|
|
1354
|
+
if (appliedInSetNative(target, gridAutoRowsProperty))
|
|
1355
|
+
return;
|
|
1356
|
+
const view = getViewStyle(target.viewRef);
|
|
1357
|
+
if (view) {
|
|
1358
|
+
view.gridAutoRows = newValue;
|
|
1359
|
+
}
|
|
1360
|
+
},
|
|
1361
|
+
});
|
|
1362
|
+
export const gridAutoColumnsProperty = new CssProperty({
|
|
1363
|
+
name: 'gridAutoColumns',
|
|
1364
|
+
cssName: 'grid-auto-columns',
|
|
1365
|
+
defaultValue: '',
|
|
1366
|
+
valueChanged(target, oldValue, newValue) {
|
|
1367
|
+
if (appliedInSetNative(target, gridAutoColumnsProperty))
|
|
1368
|
+
return;
|
|
1369
|
+
const view = getViewStyle(target.viewRef);
|
|
1370
|
+
if (view) {
|
|
1371
|
+
view.gridAutoColumns = newValue;
|
|
1372
|
+
}
|
|
1373
|
+
},
|
|
1374
|
+
});
|
|
1375
|
+
export const gridAutoFlowProperty = new CssProperty({
|
|
1376
|
+
name: 'gridAutoFlow',
|
|
1377
|
+
cssName: 'grid-auto-flow',
|
|
1378
|
+
defaultValue: 'row',
|
|
1379
|
+
valueChanged(target, oldValue, newValue) {
|
|
1380
|
+
if (appliedInSetNative(target, gridAutoFlowProperty))
|
|
1381
|
+
return;
|
|
1382
|
+
const view = getViewStyle(target.viewRef);
|
|
1383
|
+
if (view) {
|
|
1384
|
+
view.gridAutoFlow = newValue;
|
|
1385
|
+
}
|
|
1386
|
+
},
|
|
1387
|
+
});
|
|
1388
|
+
export const gridAreaProperty = new CssProperty({
|
|
1389
|
+
name: 'gridArea',
|
|
1390
|
+
cssName: 'grid-area',
|
|
1391
|
+
defaultValue: '',
|
|
1392
|
+
valueChanged(target, oldValue, newValue) {
|
|
1393
|
+
if (appliedInSetNative(target, gridAreaProperty))
|
|
1394
|
+
return;
|
|
1395
|
+
const view = getViewStyle(target.viewRef);
|
|
1396
|
+
if (view) {
|
|
1397
|
+
view.gridArea = newValue;
|
|
1398
|
+
}
|
|
1399
|
+
},
|
|
1400
|
+
});
|
|
1401
|
+
export const gridColumnStartProperty = new CssProperty({
|
|
1402
|
+
name: 'gridColumnStart',
|
|
1403
|
+
cssName: 'grid-column-start',
|
|
1404
|
+
defaultValue: 'auto',
|
|
1405
|
+
valueChanged(target, oldValue, newValue) {
|
|
1406
|
+
if (appliedInSetNative(target, gridColumnStartProperty))
|
|
1407
|
+
return;
|
|
1408
|
+
const view = getViewStyle(target.viewRef);
|
|
1409
|
+
if (view) {
|
|
1410
|
+
view.gridColumnStart = newValue;
|
|
1411
|
+
}
|
|
1412
|
+
},
|
|
1413
|
+
});
|
|
1414
|
+
export const gridColumnEndProperty = new CssProperty({
|
|
1415
|
+
name: 'gridColumnEnd',
|
|
1416
|
+
cssName: 'grid-column-end',
|
|
1417
|
+
defaultValue: 'auto',
|
|
1418
|
+
valueChanged(target, oldValue, newValue) {
|
|
1419
|
+
if (appliedInSetNative(target, gridColumnEndProperty))
|
|
1420
|
+
return;
|
|
1421
|
+
const view = getViewStyle(target.viewRef);
|
|
1422
|
+
if (view) {
|
|
1423
|
+
view.gridColumnEnd = newValue;
|
|
1424
|
+
}
|
|
1425
|
+
},
|
|
1426
|
+
});
|
|
1427
|
+
export const gridColumnProperty = new CssProperty({
|
|
1428
|
+
name: 'gridColumn',
|
|
1429
|
+
cssName: 'grid-column',
|
|
1430
|
+
defaultValue: '',
|
|
1431
|
+
valueChanged(target, oldValue, newValue) {
|
|
1432
|
+
if (appliedInSetNative(target, gridColumnProperty))
|
|
1433
|
+
return;
|
|
1434
|
+
const view = getViewStyle(target.viewRef);
|
|
1435
|
+
if (view) {
|
|
1436
|
+
view.gridColumn = newValue;
|
|
1437
|
+
}
|
|
1438
|
+
},
|
|
1439
|
+
});
|
|
1440
|
+
export const gridRowStartProperty = new CssProperty({
|
|
1441
|
+
name: 'gridRowStart',
|
|
1442
|
+
cssName: 'grid-row-start',
|
|
1443
|
+
defaultValue: 'auto',
|
|
1444
|
+
valueChanged(target, oldValue, newValue) {
|
|
1445
|
+
if (appliedInSetNative(target, gridRowStartProperty))
|
|
1446
|
+
return;
|
|
1447
|
+
const view = getViewStyle(target.viewRef);
|
|
1448
|
+
if (view) {
|
|
1449
|
+
view.gridRowStart = newValue;
|
|
1450
|
+
}
|
|
1451
|
+
},
|
|
1452
|
+
});
|
|
1453
|
+
export const gridRowEndProperty = new CssProperty({
|
|
1454
|
+
name: 'gridRowEnd',
|
|
1455
|
+
cssName: 'grid-row-end',
|
|
1456
|
+
defaultValue: 'auto',
|
|
1457
|
+
valueChanged(target, oldValue, newValue) {
|
|
1458
|
+
if (appliedInSetNative(target, gridRowEndProperty))
|
|
1459
|
+
return;
|
|
1460
|
+
const view = getViewStyle(target.viewRef);
|
|
1461
|
+
if (view) {
|
|
1462
|
+
view.gridRowEnd = newValue;
|
|
1463
|
+
}
|
|
1464
|
+
},
|
|
1465
|
+
});
|
|
1466
|
+
export const gridRowProperty = new CssProperty({
|
|
1467
|
+
name: 'gridRow',
|
|
1468
|
+
cssName: 'grid-row',
|
|
1469
|
+
defaultValue: '',
|
|
1470
|
+
valueChanged(target, oldValue, newValue) {
|
|
1471
|
+
if (appliedInSetNative(target, gridRowProperty))
|
|
1472
|
+
return;
|
|
1473
|
+
const view = getViewStyle(target.viewRef);
|
|
1474
|
+
if (view) {
|
|
1475
|
+
view.gridRow = newValue;
|
|
1476
|
+
}
|
|
1477
|
+
},
|
|
1478
|
+
});
|
|
1479
|
+
export const gridTemplateAreasProperty = new CssProperty({
|
|
1480
|
+
name: 'gridTemplateAreas',
|
|
1481
|
+
cssName: 'grid-template-areas',
|
|
1482
|
+
defaultValue: null,
|
|
1483
|
+
valueChanged(target, oldValue, newValue) {
|
|
1484
|
+
if (appliedInSetNative(target, gridTemplateAreasProperty))
|
|
1485
|
+
return;
|
|
1486
|
+
const view = getViewStyle(target.viewRef);
|
|
1487
|
+
if (view) {
|
|
1488
|
+
view.gridTemplateAreas = newValue;
|
|
1489
|
+
}
|
|
1490
|
+
},
|
|
1491
|
+
});
|
|
1492
|
+
export const gridTemplateRowsProperty = new CssProperty({
|
|
1493
|
+
name: 'gridTemplateRows',
|
|
1494
|
+
cssName: 'grid-template-rows',
|
|
1495
|
+
defaultValue: null,
|
|
1496
|
+
valueChanged(target, oldValue, newValue) {
|
|
1497
|
+
if (appliedInSetNative(target, gridTemplateRowsProperty))
|
|
1498
|
+
return;
|
|
1499
|
+
const view = getViewStyle(target.viewRef);
|
|
1500
|
+
if (view) {
|
|
1501
|
+
view.gridTemplateRows = newValue;
|
|
1502
|
+
}
|
|
1503
|
+
},
|
|
1504
|
+
});
|
|
1505
|
+
export const gridTemplateColumnsProperty = new CssProperty({
|
|
1506
|
+
name: 'gridTemplateColumns',
|
|
1507
|
+
cssName: 'grid-template-columns',
|
|
1508
|
+
defaultValue: null,
|
|
1509
|
+
valueChanged(target, oldValue, newValue) {
|
|
1510
|
+
if (appliedInSetNative(target, gridTemplateColumnsProperty))
|
|
1511
|
+
return;
|
|
1512
|
+
const view = getViewStyle(target.viewRef);
|
|
1513
|
+
if (view) {
|
|
1514
|
+
view.gridTemplateColumns = newValue;
|
|
1515
|
+
}
|
|
1516
|
+
},
|
|
1517
|
+
});
|
|
1518
|
+
// @ts-ignore
|
|
1519
|
+
export const textWrapProperty = new CssProperty({
|
|
1520
|
+
name: 'textWrap',
|
|
1521
|
+
cssName: 'text-wrap',
|
|
1522
|
+
affectsLayout: true,
|
|
1523
|
+
defaultValue: 'wrap',
|
|
1524
|
+
valueChanged(target, oldValue, newValue) {
|
|
1525
|
+
if (appliedInSetNative(target, textWrapProperty))
|
|
1526
|
+
return;
|
|
1527
|
+
const view = target?.viewRef ? getViewStyle(target.viewRef) : target.view;
|
|
1528
|
+
if (view) {
|
|
1529
|
+
view.textWrap = newValue;
|
|
1530
|
+
}
|
|
1531
|
+
},
|
|
1532
|
+
});
|
|
1533
|
+
const flexFlowShorthand = { cssName: 'flex-flow', longhands: [flexDirectionProperty, flexWrapProperty], split: splitFlexFlow };
|
|
1534
|
+
const flexFlowProperty = masonShorthandProperty(flexFlowShorthand, function () {
|
|
1535
|
+
return `${this.flexDirection} ${this.flexWrap}`;
|
|
1536
|
+
});
|
|
1537
|
+
const flexShorthand = { cssName: 'flex', longhands: [flexGrowProperty, flexShrinkProperty, flexBasisProperty], split: splitFlex };
|
|
1538
|
+
const flexProperty = masonShorthandProperty(flexShorthand, function () {
|
|
1539
|
+
return `${this.flexGrow} ${this.flexShrink} ${this.flexBasis}`;
|
|
1540
|
+
});
|
|
1541
|
+
export const textOverFlowProperty = new CssProperty({
|
|
1542
|
+
name: 'textOverflow',
|
|
1543
|
+
cssName: 'text-overflow',
|
|
1544
|
+
defaultValue: 'clip',
|
|
1545
|
+
valueChanged(target, oldValue, newValue) {
|
|
1546
|
+
if (appliedInSetNative(target, textOverFlowProperty))
|
|
1547
|
+
return;
|
|
1548
|
+
const view = target?.viewRef ? getViewStyle(target.viewRef) : target.view;
|
|
1549
|
+
if (view) {
|
|
1550
|
+
view.textOverflow = newValue;
|
|
1551
|
+
}
|
|
1552
|
+
},
|
|
1553
|
+
});
|
|
1554
|
+
export const verticalAlignProperty = new CssProperty({
|
|
1555
|
+
name: 'verticalAlign',
|
|
1556
|
+
cssName: 'vertical-align',
|
|
1557
|
+
defaultValue: 'baseline',
|
|
1558
|
+
valueChanged: (target, oldValue, newValue) => {
|
|
1559
|
+
if (newValue && appliedInSetNative(target, verticalAlignProperty))
|
|
1560
|
+
return;
|
|
1561
|
+
const view = getViewStyle(target.viewRef);
|
|
1562
|
+
if (view) {
|
|
1563
|
+
if (newValue) {
|
|
1564
|
+
view.verticalAlign = newValue;
|
|
1565
|
+
}
|
|
1566
|
+
else {
|
|
1567
|
+
// Revert to old value if newValue is invalid
|
|
1568
|
+
target.verticalAlign = oldValue;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
},
|
|
1572
|
+
});
|
|
1573
|
+
verticalAlignmentProperty.overrideHandlers({
|
|
1574
|
+
name: 'verticalAlignment',
|
|
1575
|
+
cssName: 'vertical-align',
|
|
1576
|
+
valueConverter: function (value) {
|
|
1577
|
+
if (isMasonView(this)) {
|
|
1578
|
+
return value;
|
|
1579
|
+
}
|
|
1580
|
+
return CoreTypes.VerticalAlignmentText.parse(value);
|
|
1581
|
+
},
|
|
1582
|
+
valueChanged(target, oldValue, newValue) {
|
|
1583
|
+
const view = getViewStyle(target.viewRef);
|
|
1584
|
+
if (view) {
|
|
1585
|
+
if (newValue) {
|
|
1586
|
+
// @ts-ignore
|
|
1587
|
+
view.verticalAlign = newValue;
|
|
1588
|
+
}
|
|
1589
|
+
else {
|
|
1590
|
+
// Revert to old value if newValue is invalid
|
|
1591
|
+
// @ts-ignore
|
|
1592
|
+
target.verticalAlign = oldValue;
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
},
|
|
1596
|
+
});
|
|
1597
|
+
overrideForMasonViews(textShadowProperty, {
|
|
1598
|
+
coreConverter: parseCSSShadow,
|
|
1599
|
+
apply: (style, value) => {
|
|
1600
|
+
style.textShadow = value;
|
|
1601
|
+
},
|
|
1602
|
+
});
|
|
1603
|
+
export const floatProperty = new CssProperty({
|
|
1604
|
+
name: 'float',
|
|
1605
|
+
cssName: 'float',
|
|
1606
|
+
defaultValue: 'none',
|
|
1607
|
+
});
|
|
1608
|
+
export const clearProperty = new CssProperty({
|
|
1609
|
+
name: 'clear',
|
|
1610
|
+
cssName: 'clear',
|
|
1611
|
+
defaultValue: 'none',
|
|
1612
|
+
});
|
|
1613
|
+
export const cornerShapeProperty = new CssProperty({
|
|
1614
|
+
name: 'cornerShape',
|
|
1615
|
+
cssName: 'corner-shape',
|
|
1616
|
+
});
|
|
1617
|
+
export const boxShadowProperty = new CssProperty({
|
|
1618
|
+
name: 'boxShadow',
|
|
1619
|
+
cssName: 'box-shadow',
|
|
1620
|
+
});
|
|
1621
|
+
export const transformProperty = new CssProperty({
|
|
1622
|
+
name: 'transform',
|
|
1623
|
+
cssName: 'transform',
|
|
1624
|
+
});
|
|
1625
|
+
export const cornerShapeTopLeftProperty = new CssProperty({
|
|
1626
|
+
name: 'cornerShapeTopLeft',
|
|
1627
|
+
cssName: 'corner-shape-top-left',
|
|
1628
|
+
valueChanged(target, oldValue, newValue) {
|
|
1629
|
+
const view = getViewStyle(target.viewRef);
|
|
1630
|
+
if (view) {
|
|
1631
|
+
view.cornerShapeTopLeft = newValue;
|
|
1632
|
+
}
|
|
1633
|
+
},
|
|
1634
|
+
});
|
|
1635
|
+
export const cornerShapeTopRightProperty = new CssProperty({
|
|
1636
|
+
name: 'cornerShapeTopRight',
|
|
1637
|
+
cssName: 'corner-shape-top-right',
|
|
1638
|
+
valueChanged(target, oldValue, newValue) {
|
|
1639
|
+
const view = getViewStyle(target.viewRef);
|
|
1640
|
+
if (view) {
|
|
1641
|
+
view.cornerShapeTopRight = newValue;
|
|
1642
|
+
}
|
|
1643
|
+
},
|
|
1644
|
+
});
|
|
1645
|
+
export const cornerShapeBottomRightProperty = new CssProperty({
|
|
1646
|
+
name: 'cornerShapeBottomRight',
|
|
1647
|
+
cssName: 'corner-shape-bottom-right',
|
|
1648
|
+
valueChanged(target, oldValue, newValue) {
|
|
1649
|
+
const view = getViewStyle(target.viewRef);
|
|
1650
|
+
if (view) {
|
|
1651
|
+
view.cornerShapeBottomRight = newValue;
|
|
1652
|
+
}
|
|
1653
|
+
},
|
|
1654
|
+
});
|
|
1655
|
+
export const cornerShapeBottomLeftProperty = new CssProperty({
|
|
1656
|
+
name: 'cornerShapeBottomLeft',
|
|
1657
|
+
cssName: 'corner-shape-bottom-left',
|
|
1658
|
+
valueChanged(target, oldValue, newValue) {
|
|
1659
|
+
const view = getViewStyle(target.viewRef);
|
|
1660
|
+
if (view) {
|
|
1661
|
+
view.cornerShapeBottomLeft = newValue;
|
|
1662
|
+
}
|
|
1663
|
+
},
|
|
1664
|
+
});
|
|
1665
|
+
registerAlongsideCore(cornerShapeProperty);
|
|
1666
|
+
registerAlongsideCore(boxShadowProperty);
|
|
1667
|
+
registerAlongsideCore(transformProperty);
|
|
1668
|
+
cornerShapeTopLeftProperty.register(Style);
|
|
1669
|
+
cornerShapeTopRightProperty.register(Style);
|
|
1670
|
+
cornerShapeBottomRightProperty.register(Style);
|
|
1671
|
+
cornerShapeBottomLeftProperty.register(Style);
|
|
1672
|
+
clearProperty.register(Style);
|
|
1673
|
+
floatProperty.register(Style);
|
|
1674
|
+
registerAlongsideCore(verticalAlignProperty);
|
|
1675
|
+
registerAlongsideCore(textOverFlowProperty);
|
|
1676
|
+
registerAlongsideCore(flexProperty);
|
|
1677
|
+
registerAlongsideCore(flexFlowProperty);
|
|
1678
|
+
textWrapProperty.register(Style);
|
|
1679
|
+
gridTemplateColumnsProperty.register(Style);
|
|
1680
|
+
gridTemplateRowsProperty.register(Style);
|
|
1681
|
+
registerAlongsideCore(alignContentProperty);
|
|
1682
|
+
justifySelfProperty.register(Style);
|
|
1683
|
+
justifyItemsProperty.register(Style);
|
|
1684
|
+
gridTemplateAreasProperty.register(Style);
|
|
1685
|
+
gridRowProperty.register(Style);
|
|
1686
|
+
gridRowStartProperty.register(Style);
|
|
1687
|
+
gridRowEndProperty.register(Style);
|
|
1688
|
+
gridColumnProperty.register(Style);
|
|
1689
|
+
gridColumnEndProperty.register(Style);
|
|
1690
|
+
gridColumnStartProperty.register(Style);
|
|
1691
|
+
gridAreaProperty.register(Style);
|
|
1692
|
+
// Foreign grid shorthands must share core's effective longhands: independent
|
|
1693
|
+
// scalar properties lose CSS/local priority (including an explicit `auto`).
|
|
1694
|
+
// Preserve Mason's direct accessors; core 9.1 stylesheet expansion uses these
|
|
1695
|
+
// same longhands for both kinds of view.
|
|
1696
|
+
/** A lone `<custom-ident>` placement, which an omitted end copies instead of `auto`. */
|
|
1697
|
+
function isGridIdent(part) {
|
|
1698
|
+
return /^-?[A-Za-z_][\w-]*$/.test(part) && !/^(auto|span)$/i.test(part);
|
|
1699
|
+
}
|
|
1700
|
+
/** Splits `a / b / ...` into `count` longhands, filling omitted ones as CSS Grid does. */
|
|
1701
|
+
export function gridParts(value, count) {
|
|
1702
|
+
const parts = String(value)
|
|
1703
|
+
.split('/')
|
|
1704
|
+
.map((part) => part.trim());
|
|
1705
|
+
if (parts.length > count || parts.some((part) => !part))
|
|
1706
|
+
throw new Error(`Invalid grid placement: ${value}`);
|
|
1707
|
+
// Omitted ends copy their start (grid-area: row-start, column-start, row-end, column-end).
|
|
1708
|
+
for (let i = parts.length; i < count; i++) {
|
|
1709
|
+
const start = parts[i - (count === 4 ? 2 : 1)] ?? parts[0];
|
|
1710
|
+
parts.push(isGridIdent(start) ? start : 'auto');
|
|
1711
|
+
}
|
|
1712
|
+
return parts;
|
|
1713
|
+
}
|
|
1714
|
+
const gridPlacementShorthands = [
|
|
1715
|
+
{ cssName: 'grid-row', longhands: [gridRowStartProperty, gridRowEndProperty], split: (value) => gridParts(value, 2) },
|
|
1716
|
+
{ cssName: 'grid-column', longhands: [gridColumnStartProperty, gridColumnEndProperty], split: (value) => gridParts(value, 2) },
|
|
1717
|
+
{ cssName: 'grid-area', longhands: [gridRowStartProperty, gridColumnStartProperty, gridRowEndProperty, gridColumnEndProperty], split: (value) => gridParts(value, 4) },
|
|
1718
|
+
];
|
|
1719
|
+
for (const entry of gridPlacementShorthands) {
|
|
1720
|
+
const shorthand = masonShorthandProperty(entry, function () {
|
|
1721
|
+
return entry.longhands.map((property) => this[property.name]).join(' / ');
|
|
1722
|
+
});
|
|
1723
|
+
registerAlongsideCore(shorthand, 'foreign');
|
|
1724
|
+
}
|
|
1725
|
+
gridAutoFlowProperty.register(Style);
|
|
1726
|
+
gridAutoRowsProperty.register(Style);
|
|
1727
|
+
gridAutoColumnsProperty.register(Style);
|
|
1728
|
+
aspectRatioProperty.register(Style);
|
|
1729
|
+
flexBasisProperty.register(Style);
|
|
1730
|
+
registerAlongsideCore(borderRadiusProperty);
|
|
1731
|
+
boxSizingProperty.register(Style);
|
|
1732
|
+
positionProperty.register(Style);
|
|
1733
|
+
insetProperty.register(Style);
|
|
1734
|
+
leftProperty.register(Style);
|
|
1735
|
+
rightProperty.register(Style);
|
|
1736
|
+
topProperty.register(Style);
|
|
1737
|
+
bottomProperty.register(Style);
|
|
1738
|
+
registerAlongsideCore(maxWidthProperty);
|
|
1739
|
+
registerAlongsideCore(maxHeightProperty);
|
|
1740
|
+
gridRowGapProperty.register(Style);
|
|
1741
|
+
gridColumnGapProperty.register(Style);
|
|
1742
|
+
gridGapProperty.register(Style);
|
|
1743
|
+
registerAlongsideCore(gapProperty);
|
|
1744
|
+
registerAlongsideCore(rowGapProperty);
|
|
1745
|
+
registerAlongsideCore(columnGapProperty);
|
|
1746
|
+
scrollBarWidthProperty.register(Style);
|
|
1747
|
+
registerAlongsideCore(marginProperty);
|
|
1748
|
+
overflowProperty.register(Style);
|
|
1749
|
+
overflowXProperty.register(Style);
|
|
1750
|
+
overflowYProperty.register(Style);
|
|
1751
|
+
registerAlongsideCore(backgroundProperty);
|
|
1752
|
+
registerAlongsideCore(backgroundRepeatProperty);
|
|
1753
|
+
registerAlongsideCore(backgroundPositionProperty);
|
|
1754
|
+
registerAlongsideCore(backgroundSizeProperty);
|
|
1755
|
+
backgroundClipProperty.register(Style);
|
|
1756
|
+
backgroundPositionXProperty.register(Style);
|
|
1757
|
+
backgroundPositionYProperty.register(Style);
|
|
1758
|
+
backgroundOriginProperty.register(Style);
|
|
1759
|
+
backgroundAttachmentProperty.register(Style);
|
|
1760
|
+
backgroundBlendModeProperty.register(Style);
|
|
1761
|
+
filterProperty.register(Style);
|
|
1762
|
+
registerAlongsideCore(borderColorProperty);
|
|
1763
|
+
// New CSS properties
|
|
1764
|
+
export const objectPositionProperty = new CssProperty({
|
|
1765
|
+
name: 'objectPosition',
|
|
1766
|
+
cssName: 'object-position',
|
|
1767
|
+
defaultValue: '50% 50%',
|
|
1768
|
+
valueChanged(target, oldValue, newValue) {
|
|
1769
|
+
const view = getViewStyle(target.viewRef);
|
|
1770
|
+
if (view) {
|
|
1771
|
+
view.objectPosition = newValue;
|
|
1772
|
+
}
|
|
1773
|
+
},
|
|
1774
|
+
});
|
|
1775
|
+
// Per-side style longhands; `border-style`, `border` and `border-<side>` expand into them.
|
|
1776
|
+
export const borderTopStyleProperty = new CssProperty({
|
|
1777
|
+
name: 'borderTopStyle',
|
|
1778
|
+
cssName: 'border-top-style',
|
|
1779
|
+
defaultValue: 'none',
|
|
1780
|
+
});
|
|
1781
|
+
export const borderRightStyleProperty = new CssProperty({
|
|
1782
|
+
name: 'borderRightStyle',
|
|
1783
|
+
cssName: 'border-right-style',
|
|
1784
|
+
defaultValue: 'none',
|
|
1785
|
+
});
|
|
1786
|
+
export const borderBottomStyleProperty = new CssProperty({
|
|
1787
|
+
name: 'borderBottomStyle',
|
|
1788
|
+
cssName: 'border-bottom-style',
|
|
1789
|
+
defaultValue: 'none',
|
|
1790
|
+
});
|
|
1791
|
+
export const borderLeftStyleProperty = new CssProperty({
|
|
1792
|
+
name: 'borderLeftStyle',
|
|
1793
|
+
cssName: 'border-left-style',
|
|
1794
|
+
defaultValue: 'none',
|
|
1795
|
+
});
|
|
1796
|
+
export const borderImageProperty = new CssProperty({
|
|
1797
|
+
name: 'borderImage',
|
|
1798
|
+
cssName: 'border-image',
|
|
1799
|
+
valueChanged(target, oldValue, newValue) {
|
|
1800
|
+
const view = getViewStyle(target.viewRef);
|
|
1801
|
+
if (view) {
|
|
1802
|
+
view.borderImage = newValue;
|
|
1803
|
+
}
|
|
1804
|
+
},
|
|
1805
|
+
});
|
|
1806
|
+
export const fontStretchProperty = new CssProperty({
|
|
1807
|
+
name: 'fontStretch',
|
|
1808
|
+
cssName: 'font-stretch',
|
|
1809
|
+
defaultValue: 'normal',
|
|
1810
|
+
valueChanged(target, oldValue, newValue) {
|
|
1811
|
+
const view = getViewStyle(target.viewRef);
|
|
1812
|
+
if (view) {
|
|
1813
|
+
view.fontStretch = newValue;
|
|
1814
|
+
}
|
|
1815
|
+
},
|
|
1816
|
+
});
|
|
1817
|
+
export const fontFeatureSettingsProperty = new CssProperty({
|
|
1818
|
+
name: 'fontFeatureSettings',
|
|
1819
|
+
cssName: 'font-feature-settings',
|
|
1820
|
+
defaultValue: 'normal',
|
|
1821
|
+
valueChanged(target, oldValue, newValue) {
|
|
1822
|
+
const view = getViewStyle(target.viewRef);
|
|
1823
|
+
if (view) {
|
|
1824
|
+
view.fontFeatureSettings = newValue;
|
|
1825
|
+
}
|
|
1826
|
+
},
|
|
1827
|
+
});
|
|
1828
|
+
export const wordSpacingProperty = new CssProperty({
|
|
1829
|
+
name: 'wordSpacing',
|
|
1830
|
+
cssName: 'word-spacing',
|
|
1831
|
+
defaultValue: 'normal',
|
|
1832
|
+
valueChanged(target, oldValue, newValue) {
|
|
1833
|
+
const view = getViewStyle(target.viewRef);
|
|
1834
|
+
if (view) {
|
|
1835
|
+
view.wordSpacing = newValue;
|
|
1836
|
+
}
|
|
1837
|
+
},
|
|
1838
|
+
});
|
|
1839
|
+
export const hyphensProperty = new CssProperty({
|
|
1840
|
+
name: 'hyphens',
|
|
1841
|
+
cssName: 'hyphens',
|
|
1842
|
+
defaultValue: 'manual',
|
|
1843
|
+
valueChanged(target, oldValue, newValue) {
|
|
1844
|
+
const view = getViewStyle(target.viewRef);
|
|
1845
|
+
if (view) {
|
|
1846
|
+
view.hyphens = newValue;
|
|
1847
|
+
}
|
|
1848
|
+
},
|
|
1849
|
+
});
|
|
1850
|
+
export const textIndentProperty = new CssProperty({
|
|
1851
|
+
name: 'textIndent',
|
|
1852
|
+
cssName: 'text-indent',
|
|
1853
|
+
defaultValue: '0px',
|
|
1854
|
+
valueChanged(target, oldValue, newValue) {
|
|
1855
|
+
const view = getViewStyle(target.viewRef);
|
|
1856
|
+
if (view) {
|
|
1857
|
+
view.textIndent = newValue;
|
|
1858
|
+
}
|
|
1859
|
+
},
|
|
1860
|
+
});
|
|
1861
|
+
function setLineClamp(target, value) {
|
|
1862
|
+
const view = getViewStyle(target.viewRef);
|
|
1863
|
+
if (view) {
|
|
1864
|
+
view.lineClamp = (value ?? 'none');
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
export const lineClampProperty = new CssProperty({
|
|
1868
|
+
name: 'lineClamp',
|
|
1869
|
+
cssName: 'line-clamp',
|
|
1870
|
+
defaultValue: 'none',
|
|
1871
|
+
valueChanged: (target, oldValue, newValue) => setLineClamp(target, newValue),
|
|
1872
|
+
});
|
|
1873
|
+
// Tailwind's `line-clamp-*` pairs this with `display: -webkit-box`, read as block.
|
|
1874
|
+
export const webkitLineClampProperty = new CssProperty({
|
|
1875
|
+
name: 'webkitLineClamp',
|
|
1876
|
+
cssName: '-webkit-line-clamp',
|
|
1877
|
+
defaultValue: 'none',
|
|
1878
|
+
valueChanged: (target, oldValue, newValue) => setLineClamp(target, newValue),
|
|
1879
|
+
});
|
|
1880
|
+
export const transformOriginProperty = new CssProperty({
|
|
1881
|
+
name: 'transformOrigin',
|
|
1882
|
+
cssName: 'transform-origin',
|
|
1883
|
+
defaultValue: '50% 50%',
|
|
1884
|
+
valueChanged(target, oldValue, newValue) {
|
|
1885
|
+
const view = getViewStyle(target.viewRef);
|
|
1886
|
+
if (view) {
|
|
1887
|
+
view.transformOrigin = newValue;
|
|
1888
|
+
}
|
|
1889
|
+
},
|
|
1890
|
+
});
|
|
1891
|
+
export const backdropFilterProperty = new CssProperty({
|
|
1892
|
+
name: 'backdropFilter',
|
|
1893
|
+
cssName: 'backdrop-filter',
|
|
1894
|
+
valueChanged(target, oldValue, newValue) {
|
|
1895
|
+
const view = getViewStyle(target.viewRef);
|
|
1896
|
+
if (view) {
|
|
1897
|
+
view.backdropFilter = newValue;
|
|
1898
|
+
}
|
|
1899
|
+
},
|
|
1900
|
+
});
|
|
1901
|
+
// CSS masking. Android and iOS parse and draw these natively, the way they do backgrounds; the
|
|
1902
|
+
// `mask` shorthand is split into them here, like `background`.
|
|
1903
|
+
export const maskImageProperty = new CssProperty({
|
|
1904
|
+
name: 'maskImage',
|
|
1905
|
+
cssName: 'mask-image',
|
|
1906
|
+
valueChanged(target, oldValue, newValue) {
|
|
1907
|
+
const view = getViewStyle(target.viewRef);
|
|
1908
|
+
if (view) {
|
|
1909
|
+
view.maskImage = newValue;
|
|
1910
|
+
}
|
|
1911
|
+
},
|
|
1912
|
+
});
|
|
1913
|
+
export const maskSizeProperty = new CssAnimationProperty({
|
|
1914
|
+
name: 'maskSize',
|
|
1915
|
+
cssName: 'mask-size',
|
|
1916
|
+
valueConverter: (value) => value,
|
|
1917
|
+
valueChanged(target, oldValue, newValue) {
|
|
1918
|
+
const view = getViewStyle(target.viewRef);
|
|
1919
|
+
if (view) {
|
|
1920
|
+
view.maskSize = newValue;
|
|
1921
|
+
}
|
|
1922
|
+
},
|
|
1923
|
+
});
|
|
1924
|
+
export const maskPositionProperty = new CssAnimationProperty({
|
|
1925
|
+
name: 'maskPosition',
|
|
1926
|
+
cssName: 'mask-position',
|
|
1927
|
+
// Keyframes keep only declarations whose property has a converter; see css-keyframes.ts.
|
|
1928
|
+
valueConverter: (value) => value,
|
|
1929
|
+
valueChanged(target, oldValue, newValue) {
|
|
1930
|
+
const view = getViewStyle(target.viewRef);
|
|
1931
|
+
if (view) {
|
|
1932
|
+
view.maskPosition = newValue;
|
|
1933
|
+
}
|
|
1934
|
+
},
|
|
1935
|
+
});
|
|
1936
|
+
export const maskRepeatProperty = new CssProperty({
|
|
1937
|
+
name: 'maskRepeat',
|
|
1938
|
+
cssName: 'mask-repeat',
|
|
1939
|
+
valueChanged(target, oldValue, newValue) {
|
|
1940
|
+
const view = getViewStyle(target.viewRef);
|
|
1941
|
+
if (view) {
|
|
1942
|
+
view.maskRepeat = newValue;
|
|
1943
|
+
}
|
|
1944
|
+
},
|
|
1945
|
+
});
|
|
1946
|
+
export const maskOriginProperty = new CssProperty({
|
|
1947
|
+
name: 'maskOrigin',
|
|
1948
|
+
cssName: 'mask-origin',
|
|
1949
|
+
valueChanged(target, oldValue, newValue) {
|
|
1950
|
+
const view = getViewStyle(target.viewRef);
|
|
1951
|
+
if (view) {
|
|
1952
|
+
view.maskOrigin = newValue;
|
|
1953
|
+
}
|
|
1954
|
+
},
|
|
1955
|
+
});
|
|
1956
|
+
export const maskClipProperty = new CssProperty({
|
|
1957
|
+
name: 'maskClip',
|
|
1958
|
+
cssName: 'mask-clip',
|
|
1959
|
+
valueChanged(target, oldValue, newValue) {
|
|
1960
|
+
const view = getViewStyle(target.viewRef);
|
|
1961
|
+
if (view) {
|
|
1962
|
+
view.maskClip = newValue;
|
|
1963
|
+
}
|
|
1964
|
+
},
|
|
1965
|
+
});
|
|
1966
|
+
export const maskModeProperty = new CssProperty({
|
|
1967
|
+
name: 'maskMode',
|
|
1968
|
+
cssName: 'mask-mode',
|
|
1969
|
+
valueChanged(target, oldValue, newValue) {
|
|
1970
|
+
const view = getViewStyle(target.viewRef);
|
|
1971
|
+
if (view) {
|
|
1972
|
+
view.maskMode = newValue;
|
|
1973
|
+
}
|
|
1974
|
+
},
|
|
1975
|
+
});
|
|
1976
|
+
export const maskCompositeProperty = new CssProperty({
|
|
1977
|
+
name: 'maskComposite',
|
|
1978
|
+
cssName: 'mask-composite',
|
|
1979
|
+
valueChanged(target, oldValue, newValue) {
|
|
1980
|
+
const view = getViewStyle(target.viewRef);
|
|
1981
|
+
if (view) {
|
|
1982
|
+
view.maskComposite = newValue;
|
|
1983
|
+
}
|
|
1984
|
+
},
|
|
1985
|
+
});
|
|
1986
|
+
export const clipPathProperty = new CssProperty({
|
|
1987
|
+
name: 'clipPath',
|
|
1988
|
+
cssName: 'clip-path',
|
|
1989
|
+
valueChanged(target, oldValue, newValue) {
|
|
1990
|
+
const view = getViewStyle(target.viewRef);
|
|
1991
|
+
if (view) {
|
|
1992
|
+
view.clipPath = newValue;
|
|
1993
|
+
}
|
|
1994
|
+
},
|
|
1995
|
+
});
|
|
1996
|
+
export const maskBorderSourceProperty = new CssProperty({
|
|
1997
|
+
name: 'maskBorderSource',
|
|
1998
|
+
cssName: 'mask-border-source',
|
|
1999
|
+
valueChanged(target, oldValue, newValue) {
|
|
2000
|
+
const view = getViewStyle(target.viewRef);
|
|
2001
|
+
if (view) {
|
|
2002
|
+
view.maskBorderSource = newValue;
|
|
2003
|
+
}
|
|
2004
|
+
},
|
|
2005
|
+
});
|
|
2006
|
+
export const maskBorderSliceProperty = new CssProperty({
|
|
2007
|
+
name: 'maskBorderSlice',
|
|
2008
|
+
cssName: 'mask-border-slice',
|
|
2009
|
+
valueChanged(target, oldValue, newValue) {
|
|
2010
|
+
const view = getViewStyle(target.viewRef);
|
|
2011
|
+
if (view) {
|
|
2012
|
+
view.maskBorderSlice = newValue;
|
|
2013
|
+
}
|
|
2014
|
+
},
|
|
2015
|
+
});
|
|
2016
|
+
export const maskBorderWidthProperty = new CssProperty({
|
|
2017
|
+
name: 'maskBorderWidth',
|
|
2018
|
+
cssName: 'mask-border-width',
|
|
2019
|
+
valueChanged(target, oldValue, newValue) {
|
|
2020
|
+
const view = getViewStyle(target.viewRef);
|
|
2021
|
+
if (view) {
|
|
2022
|
+
view.maskBorderWidth = newValue;
|
|
2023
|
+
}
|
|
2024
|
+
},
|
|
2025
|
+
});
|
|
2026
|
+
export const maskBorderOutsetProperty = new CssProperty({
|
|
2027
|
+
name: 'maskBorderOutset',
|
|
2028
|
+
cssName: 'mask-border-outset',
|
|
2029
|
+
valueChanged(target, oldValue, newValue) {
|
|
2030
|
+
const view = getViewStyle(target.viewRef);
|
|
2031
|
+
if (view) {
|
|
2032
|
+
view.maskBorderOutset = newValue;
|
|
2033
|
+
}
|
|
2034
|
+
},
|
|
2035
|
+
});
|
|
2036
|
+
export const maskBorderRepeatProperty = new CssProperty({
|
|
2037
|
+
name: 'maskBorderRepeat',
|
|
2038
|
+
cssName: 'mask-border-repeat',
|
|
2039
|
+
valueChanged(target, oldValue, newValue) {
|
|
2040
|
+
const view = getViewStyle(target.viewRef);
|
|
2041
|
+
if (view) {
|
|
2042
|
+
view.maskBorderRepeat = newValue;
|
|
2043
|
+
}
|
|
2044
|
+
},
|
|
2045
|
+
});
|
|
2046
|
+
export const maskBorderModeProperty = new CssProperty({
|
|
2047
|
+
name: 'maskBorderMode',
|
|
2048
|
+
cssName: 'mask-border-mode',
|
|
2049
|
+
valueChanged(target, oldValue, newValue) {
|
|
2050
|
+
const view = getViewStyle(target.viewRef);
|
|
2051
|
+
if (view) {
|
|
2052
|
+
view.maskBorderMode = newValue;
|
|
2053
|
+
}
|
|
2054
|
+
},
|
|
2055
|
+
});
|
|
2056
|
+
// The -webkit- prefixed names older and autoprefixed CSS still uses, set on the same Style
|
|
2057
|
+
// properties. Composite operators and box keywords are translated to the standard ones.
|
|
2058
|
+
// Gradient-text CSS is usually written `-webkit-background-clip: text`.
|
|
2059
|
+
const webkitBackgroundClipProperty = new CssProperty({
|
|
2060
|
+
name: 'webkitBackgroundClip',
|
|
2061
|
+
cssName: '-webkit-background-clip',
|
|
2062
|
+
valueChanged(target, oldValue, newValue) {
|
|
2063
|
+
const view = getViewStyle(target.viewRef);
|
|
2064
|
+
if (view) {
|
|
2065
|
+
view.backgroundClip = newValue;
|
|
2066
|
+
}
|
|
2067
|
+
},
|
|
2068
|
+
});
|
|
2069
|
+
const webkitMaskImageProperty = new CssProperty({
|
|
2070
|
+
name: 'webkitMaskImage',
|
|
2071
|
+
cssName: '-webkit-mask-image',
|
|
2072
|
+
valueChanged(target, oldValue, newValue) {
|
|
2073
|
+
const view = getViewStyle(target.viewRef);
|
|
2074
|
+
if (view) {
|
|
2075
|
+
const value = newValue;
|
|
2076
|
+
view.maskImage = (typeof value === 'string' ? value : value);
|
|
2077
|
+
}
|
|
2078
|
+
},
|
|
2079
|
+
});
|
|
2080
|
+
const webkitMaskSizeProperty = new CssProperty({
|
|
2081
|
+
name: 'webkitMaskSize',
|
|
2082
|
+
cssName: '-webkit-mask-size',
|
|
2083
|
+
valueChanged(target, oldValue, newValue) {
|
|
2084
|
+
const view = getViewStyle(target.viewRef);
|
|
2085
|
+
if (view) {
|
|
2086
|
+
const value = newValue;
|
|
2087
|
+
view.maskSize = (typeof value === 'string' ? value : value);
|
|
2088
|
+
}
|
|
2089
|
+
},
|
|
2090
|
+
});
|
|
2091
|
+
const webkitMaskPositionProperty = new CssProperty({
|
|
2092
|
+
name: 'webkitMaskPosition',
|
|
2093
|
+
cssName: '-webkit-mask-position',
|
|
2094
|
+
valueChanged(target, oldValue, newValue) {
|
|
2095
|
+
const view = getViewStyle(target.viewRef);
|
|
2096
|
+
if (view) {
|
|
2097
|
+
const value = newValue;
|
|
2098
|
+
view.maskPosition = (typeof value === 'string' ? value : value);
|
|
2099
|
+
}
|
|
2100
|
+
},
|
|
2101
|
+
});
|
|
2102
|
+
const webkitMaskRepeatProperty = new CssProperty({
|
|
2103
|
+
name: 'webkitMaskRepeat',
|
|
2104
|
+
cssName: '-webkit-mask-repeat',
|
|
2105
|
+
valueChanged(target, oldValue, newValue) {
|
|
2106
|
+
const view = getViewStyle(target.viewRef);
|
|
2107
|
+
if (view) {
|
|
2108
|
+
const value = newValue;
|
|
2109
|
+
view.maskRepeat = (typeof value === 'string' ? value : value);
|
|
2110
|
+
}
|
|
2111
|
+
},
|
|
2112
|
+
});
|
|
2113
|
+
const webkitMaskOriginProperty = new CssProperty({
|
|
2114
|
+
name: 'webkitMaskOrigin',
|
|
2115
|
+
cssName: '-webkit-mask-origin',
|
|
2116
|
+
valueChanged(target, oldValue, newValue) {
|
|
2117
|
+
const view = getViewStyle(target.viewRef);
|
|
2118
|
+
if (view) {
|
|
2119
|
+
const value = newValue;
|
|
2120
|
+
view.maskOrigin = (typeof value === 'string' ? webkitMaskBox(value) : value);
|
|
2121
|
+
}
|
|
2122
|
+
},
|
|
2123
|
+
});
|
|
2124
|
+
const webkitMaskClipProperty = new CssProperty({
|
|
2125
|
+
name: 'webkitMaskClip',
|
|
2126
|
+
cssName: '-webkit-mask-clip',
|
|
2127
|
+
valueChanged(target, oldValue, newValue) {
|
|
2128
|
+
const view = getViewStyle(target.viewRef);
|
|
2129
|
+
if (view) {
|
|
2130
|
+
const value = newValue;
|
|
2131
|
+
view.maskClip = (typeof value === 'string' ? webkitMaskBox(value) : value);
|
|
2132
|
+
}
|
|
2133
|
+
},
|
|
2134
|
+
});
|
|
2135
|
+
const webkitMaskCompositeProperty = new CssProperty({
|
|
2136
|
+
name: 'webkitMaskComposite',
|
|
2137
|
+
cssName: '-webkit-mask-composite',
|
|
2138
|
+
valueChanged(target, oldValue, newValue) {
|
|
2139
|
+
const view = getViewStyle(target.viewRef);
|
|
2140
|
+
if (view) {
|
|
2141
|
+
const value = newValue;
|
|
2142
|
+
view.maskComposite = (typeof value === 'string' ? webkitMaskComposite(value) : value);
|
|
2143
|
+
}
|
|
2144
|
+
},
|
|
2145
|
+
});
|
|
2146
|
+
const maskShorthand = {
|
|
2147
|
+
cssName: 'mask',
|
|
2148
|
+
longhands: [maskImageProperty, maskPositionProperty, maskSizeProperty, maskRepeatProperty, maskOriginProperty, maskClipProperty, maskCompositeProperty, maskModeProperty],
|
|
2149
|
+
split: splitMask,
|
|
2150
|
+
};
|
|
2151
|
+
export const maskProperty = masonShorthandProperty(maskShorthand, function () {
|
|
2152
|
+
return this.maskImage;
|
|
2153
|
+
});
|
|
2154
|
+
const webkitMaskShorthand = { cssName: '-webkit-mask', longhands: maskShorthand.longhands, split: splitWebkitMask };
|
|
2155
|
+
const webkitMaskProperty = masonShorthandProperty(webkitMaskShorthand, function () {
|
|
2156
|
+
return this.maskImage;
|
|
2157
|
+
});
|
|
2158
|
+
const maskBorderShorthand = {
|
|
2159
|
+
cssName: 'mask-border',
|
|
2160
|
+
longhands: [maskBorderSourceProperty, maskBorderSliceProperty, maskBorderWidthProperty, maskBorderOutsetProperty, maskBorderRepeatProperty, maskBorderModeProperty],
|
|
2161
|
+
split: splitMaskBorder,
|
|
2162
|
+
};
|
|
2163
|
+
export const maskBorderProperty = masonShorthandProperty(maskBorderShorthand, function () {
|
|
2164
|
+
return this.maskBorderSource;
|
|
2165
|
+
});
|
|
2166
|
+
// WebKit's name for mask-border.
|
|
2167
|
+
const webkitMaskBoxImageShorthand = { cssName: '-webkit-mask-box-image', longhands: maskBorderShorthand.longhands, split: splitMaskBorder };
|
|
2168
|
+
const webkitMaskBoxImageProperty = masonShorthandProperty(webkitMaskBoxImageShorthand, function () {
|
|
2169
|
+
return this.maskBorderSource;
|
|
2170
|
+
});
|
|
2171
|
+
export const writingModeProperty = new CssProperty({
|
|
2172
|
+
name: 'writingMode',
|
|
2173
|
+
cssName: 'writing-mode',
|
|
2174
|
+
defaultValue: 'horizontal-tb',
|
|
2175
|
+
valueChanged(target, oldValue, newValue) {
|
|
2176
|
+
const view = getViewStyle(target.viewRef);
|
|
2177
|
+
if (view) {
|
|
2178
|
+
view.writingMode = newValue;
|
|
2179
|
+
}
|
|
2180
|
+
},
|
|
2181
|
+
});
|
|
2182
|
+
export const unicodeBidiProperty = new CssProperty({
|
|
2183
|
+
name: 'unicodeBidi',
|
|
2184
|
+
cssName: 'unicode-bidi',
|
|
2185
|
+
defaultValue: 'normal',
|
|
2186
|
+
valueChanged(target, oldValue, newValue) {
|
|
2187
|
+
const view = getViewStyle(target.viewRef);
|
|
2188
|
+
if (view) {
|
|
2189
|
+
view.unicodeBidi = newValue;
|
|
2190
|
+
}
|
|
2191
|
+
},
|
|
2192
|
+
});
|
|
2193
|
+
export const caretColorProperty = new CssProperty({
|
|
2194
|
+
name: 'caretColor',
|
|
2195
|
+
cssName: 'caret-color',
|
|
2196
|
+
defaultValue: 'auto',
|
|
2197
|
+
valueChanged(target, oldValue, newValue) {
|
|
2198
|
+
const view = getViewStyle(target.viewRef);
|
|
2199
|
+
if (view) {
|
|
2200
|
+
view.caretColor = newValue;
|
|
2201
|
+
}
|
|
2202
|
+
},
|
|
2203
|
+
});
|
|
2204
|
+
objectPositionProperty.register(Style);
|
|
2205
|
+
borderTopStyleProperty.register(Style);
|
|
2206
|
+
borderRightStyleProperty.register(Style);
|
|
2207
|
+
borderBottomStyleProperty.register(Style);
|
|
2208
|
+
borderLeftStyleProperty.register(Style);
|
|
2209
|
+
borderImageProperty.register(Style);
|
|
2210
|
+
fontStretchProperty.register(Style);
|
|
2211
|
+
fontFeatureSettingsProperty.register(Style);
|
|
2212
|
+
wordSpacingProperty.register(Style);
|
|
2213
|
+
hyphensProperty.register(Style);
|
|
2214
|
+
textIndentProperty.register(Style);
|
|
2215
|
+
lineClampProperty.register(Style);
|
|
2216
|
+
webkitLineClampProperty.register(Style);
|
|
2217
|
+
transformOriginProperty.register(Style);
|
|
2218
|
+
backdropFilterProperty.register(Style);
|
|
2219
|
+
maskImageProperty.register(Style);
|
|
2220
|
+
maskProperty.register(Style);
|
|
2221
|
+
// Keyframes can animate mask position and size; see css-keyframes.ts.
|
|
2222
|
+
registerKeyframeProperty(maskPositionProperty, interpolatePositionList, '0% 0%');
|
|
2223
|
+
registerKeyframeProperty(maskSizeProperty, interpolateSizeList, 'auto');
|
|
2224
|
+
installKeyframes();
|
|
2225
|
+
// Core has its own clip-path for plain views; MasonKit views draw theirs natively.
|
|
2226
|
+
registerAlongsideCore(clipPathProperty);
|
|
2227
|
+
maskBorderSourceProperty.register(Style);
|
|
2228
|
+
maskBorderSliceProperty.register(Style);
|
|
2229
|
+
maskBorderWidthProperty.register(Style);
|
|
2230
|
+
maskBorderOutsetProperty.register(Style);
|
|
2231
|
+
maskBorderRepeatProperty.register(Style);
|
|
2232
|
+
maskBorderModeProperty.register(Style);
|
|
2233
|
+
webkitBackgroundClipProperty.register(Style);
|
|
2234
|
+
webkitMaskImageProperty.register(Style);
|
|
2235
|
+
webkitMaskSizeProperty.register(Style);
|
|
2236
|
+
webkitMaskPositionProperty.register(Style);
|
|
2237
|
+
webkitMaskRepeatProperty.register(Style);
|
|
2238
|
+
webkitMaskOriginProperty.register(Style);
|
|
2239
|
+
webkitMaskClipProperty.register(Style);
|
|
2240
|
+
webkitMaskCompositeProperty.register(Style);
|
|
2241
|
+
webkitMaskProperty.register(Style);
|
|
2242
|
+
maskBorderProperty.register(Style);
|
|
2243
|
+
webkitMaskBoxImageProperty.register(Style);
|
|
2244
|
+
maskSizeProperty.register(Style);
|
|
2245
|
+
maskPositionProperty.register(Style);
|
|
2246
|
+
maskRepeatProperty.register(Style);
|
|
2247
|
+
maskOriginProperty.register(Style);
|
|
2248
|
+
maskClipProperty.register(Style);
|
|
2249
|
+
maskModeProperty.register(Style);
|
|
2250
|
+
maskCompositeProperty.register(Style);
|
|
2251
|
+
writingModeProperty.register(Style);
|
|
2252
|
+
unicodeBidiProperty.register(Style);
|
|
2253
|
+
caretColorProperty.register(Style);
|
|
2254
|
+
registerAlongsideCore(backgroundImageProperty);
|
|
2255
|
+
// Inherited, as in CSS, so a list's value reaches its items.
|
|
2256
|
+
export const listStyleTypeProperty = new InheritedCssProperty({
|
|
2257
|
+
name: 'listStyleType',
|
|
2258
|
+
cssName: 'list-style-type',
|
|
2259
|
+
});
|
|
2260
|
+
export const listStylePositionProperty = new InheritedCssProperty({
|
|
2261
|
+
name: 'listStylePosition',
|
|
2262
|
+
cssName: 'list-style-position',
|
|
2263
|
+
});
|
|
2264
|
+
listStyleTypeProperty.register(Style);
|
|
2265
|
+
listStylePositionProperty.register(Style);
|
|
2266
|
+
export const listStyleShorthand = { cssName: 'list-style', longhands: [listStyleTypeProperty, listStylePositionProperty], split: splitListStyle };
|
|
2267
|
+
export const listStyleProperty = masonShorthandProperty(listStyleShorthand, function () {
|
|
2268
|
+
const style = this;
|
|
2269
|
+
const parts = [style.listStyleType, style.listStylePosition].filter((part) => typeof part === 'string' && part);
|
|
2270
|
+
return parts.join(' ');
|
|
2271
|
+
});
|
|
2272
|
+
listStyleProperty.register(Style);
|
|
2273
|
+
// core owns `white-space` too (its Label honours nowrap), so dispatch.
|
|
2274
|
+
registerAlongsideCore(whiteSpaceProperty);
|
|
2275
|
+
objectFitProperty.register(Style);
|
|
2276
|
+
touchActionProperty.register(Style);
|
|
2277
|
+
textJustifyProperty.register(Style);
|
|
2278
|
+
textDecorationThicknessProperty.register(Style);
|
|
2279
|
+
textDecorationLineProperty.register(Style);
|
|
2280
|
+
textDecorationStyleProperty.register(Style);
|
|
2281
|
+
textDecorationColorProperty.register(Style);
|
|
2282
|
+
// Core validates `text-decoration` down to none/underline/line-through, so
|
|
2283
|
+
// overline, the error lines, styles, colors and thicknesses never reached
|
|
2284
|
+
// mason. Its own elements get the raw declaration; core keeps its parser.
|
|
2285
|
+
const TextDecorationParse = makeParser(makeValidator('none', 'underline', 'line-through', 'underline line-through'));
|
|
2286
|
+
textDecorationProperty.overrideHandlers({
|
|
2287
|
+
valueConverter: function (value) {
|
|
2288
|
+
return isMasonView(this) ? value : TextDecorationParse(value);
|
|
2289
|
+
},
|
|
2290
|
+
});
|
|
2291
|
+
// core owns `font-family` (through its Font shorthand), so this has to dispatch
|
|
2292
|
+
// rather than shadow it.
|
|
2293
|
+
// Windows keeps core's inherited font-family, whose fontInternal reaches common.ts and resolves app fonts.
|
|
2294
|
+
if (!false) {
|
|
2295
|
+
registerAlongsideCore(fontFamilyProperty);
|
|
2296
|
+
}
|
|
2297
|
+
displayProperty.register(Style);
|
|
2298
|
+
/**
|
|
2299
|
+
* A Mason view gets core's own parse with the CSS text attached (see
|
|
2300
|
+
* CssLength), so core's valueChanged and layout code read a finite length
|
|
2301
|
+
* while Mason's setNative parses the text. Core views keep core's converter.
|
|
2302
|
+
*/
|
|
2303
|
+
function keepCssOnMasonViews(longhands, core) {
|
|
2304
|
+
for (const property of longhands) {
|
|
2305
|
+
property.overrideHandlers({
|
|
2306
|
+
name: property.name,
|
|
2307
|
+
cssName: property.cssLocalName,
|
|
2308
|
+
valueConverter(value) {
|
|
2309
|
+
const css = core.keywords?.get(value.trim()) ?? value;
|
|
2310
|
+
return isMasonView(this) ? cssLength(css, core.converter) : core.converter(css);
|
|
2311
|
+
},
|
|
2312
|
+
// Core's parse reads `10%` and `10rem` alike, so the CSS text decides.
|
|
2313
|
+
equalityComparer: (a, b) => (isCssLength(a) || isCssLength(b) ? a?.css === b?.css : core.comparer(a, b)),
|
|
2314
|
+
});
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
const radiusLonghands = [borderTopLeftRadiusProperty, borderTopRightRadiusProperty, borderBottomRightRadiusProperty, borderBottomLeftRadiusProperty];
|
|
2318
|
+
const marginLonghands = [marginTopProperty, marginRightProperty, marginBottomProperty, marginLeftProperty];
|
|
2319
|
+
const paddingLonghands = [paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty];
|
|
2320
|
+
const borderWidthLonghands = [borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty];
|
|
2321
|
+
const borderColorLonghands = [borderTopColorProperty, borderRightColorProperty, borderBottomColorProperty, borderLeftColorProperty];
|
|
2322
|
+
// Core reads `50%` as 50 and skips a parsed 0 as equal to its default, so
|
|
2323
|
+
// `border-radius: 0` never reached a button's native 4px radius.
|
|
2324
|
+
keepCssOnMasonViews(radiusLonghands, { converter: CoreLength.parse, comparer: CoreLength.equals });
|
|
2325
|
+
keepCssOnMasonViews(marginLonghands, { converter: CorePercentLength.parse, comparer: CorePercentLength.equals });
|
|
2326
|
+
keepCssOnMasonViews(paddingLonghands, { converter: CoreLength.parse, comparer: CoreLength.equals });
|
|
2327
|
+
keepCssOnMasonViews(borderWidthLonghands, { converter: CoreLength.parse, comparer: CoreLength.equals, keywords: BORDER_WIDTH_KEYWORDS });
|
|
2328
|
+
/** The shorthands core registers; MasonKit builds these only to own core 9.1's parse-time split. */
|
|
2329
|
+
const coreShorthands = [
|
|
2330
|
+
{ cssName: 'border-radius', longhands: radiusLonghands, split: splitBorderRadius },
|
|
2331
|
+
{ cssName: 'margin', longhands: marginLonghands, split: splitMargin },
|
|
2332
|
+
{ cssName: 'padding', longhands: paddingLonghands, split: splitPadding },
|
|
2333
|
+
{ cssName: 'border-width', longhands: borderWidthLonghands, split: splitBorderWidth },
|
|
2334
|
+
{ cssName: 'border-color', longhands: borderColorLonghands, split: splitBorderColor },
|
|
2335
|
+
{
|
|
2336
|
+
cssName: 'background',
|
|
2337
|
+
longhands: [backgroundColorProperty, backgroundImageProperty, backgroundRepeatProperty, backgroundPositionProperty, backgroundSizeProperty, backgroundClipProperty, backgroundOriginProperty, backgroundAttachmentProperty],
|
|
2338
|
+
split: splitBackground,
|
|
2339
|
+
},
|
|
2340
|
+
];
|
|
2341
|
+
for (const entry of coreShorthands) {
|
|
2342
|
+
masonShorthandProperty(entry);
|
|
2343
|
+
}
|
|
2344
|
+
// `border`, `border-<side>` and `border-style` expand into the width, style and
|
|
2345
|
+
// color longhands, so the cascade resolves each longhand on its own.
|
|
2346
|
+
const SIDES = ['top', 'right', 'bottom', 'left'];
|
|
2347
|
+
/** A longhand's value as CSS text, for the shorthand getters. */
|
|
2348
|
+
function cssText(value) {
|
|
2349
|
+
if (value == null || value === unsetValue) {
|
|
2350
|
+
return '';
|
|
2351
|
+
}
|
|
2352
|
+
if (typeof value === 'string') {
|
|
2353
|
+
return value;
|
|
2354
|
+
}
|
|
2355
|
+
if (typeof value === 'number') {
|
|
2356
|
+
return `${value}px`;
|
|
2357
|
+
}
|
|
2358
|
+
if (isCssLength(value)) {
|
|
2359
|
+
return value.css;
|
|
2360
|
+
}
|
|
2361
|
+
const { hex, unit, value: amount } = value;
|
|
2362
|
+
if (typeof hex === 'string') {
|
|
2363
|
+
return hex;
|
|
2364
|
+
}
|
|
2365
|
+
if (typeof amount === 'number') {
|
|
2366
|
+
return unit === '%' ? `${amount * 100}%` : `${amount}px`;
|
|
2367
|
+
}
|
|
2368
|
+
return String(value);
|
|
2369
|
+
}
|
|
2370
|
+
const borderStyleLonghands = [borderTopStyleProperty, borderRightStyleProperty, borderBottomStyleProperty, borderLeftStyleProperty];
|
|
2371
|
+
const borderStyleShorthand = { cssName: 'border-style', longhands: borderStyleLonghands, split: splitBorderStyle };
|
|
2372
|
+
const borderShorthand = { cssName: 'border', longhands: [...borderWidthLonghands, ...borderStyleLonghands, ...borderColorLonghands], split: splitBorder };
|
|
2373
|
+
const borderSideShorthands = [0, 1, 2, 3].map((i) => ({
|
|
2374
|
+
cssName: `border-${SIDES[i]}`,
|
|
2375
|
+
longhands: [borderWidthLonghands[i], borderStyleLonghands[i], borderColorLonghands[i]],
|
|
2376
|
+
split: splitBorderSide,
|
|
2377
|
+
}));
|
|
2378
|
+
function sideValues(style, longhands) {
|
|
2379
|
+
return longhands.map(({ name }) => cssText(style[name]));
|
|
2380
|
+
}
|
|
2381
|
+
/** The shared value when every side agrees, else undefined. */
|
|
2382
|
+
function uniformSides(values) {
|
|
2383
|
+
return values.every((value) => value === values[0]) ? values[0] : undefined;
|
|
2384
|
+
}
|
|
2385
|
+
export const borderStyleProperty = masonShorthandProperty(borderStyleShorthand, function () {
|
|
2386
|
+
const styles = sideValues(this, borderStyleLonghands);
|
|
2387
|
+
return uniformSides(styles) ?? styles.join(' ');
|
|
2388
|
+
});
|
|
2389
|
+
export const borderProperty = masonShorthandProperty(borderShorthand, function () {
|
|
2390
|
+
const width = uniformSides(sideValues(this, borderWidthLonghands));
|
|
2391
|
+
const style = uniformSides(sideValues(this, borderStyleLonghands));
|
|
2392
|
+
const color = uniformSides(sideValues(this, borderColorLonghands));
|
|
2393
|
+
return width !== undefined && style !== undefined && color !== undefined ? [width, style, color].filter(Boolean).join(' ') : '';
|
|
2394
|
+
});
|
|
2395
|
+
function borderSideGetter(i) {
|
|
2396
|
+
return function () {
|
|
2397
|
+
return sideValues(this, [borderWidthLonghands[i], borderStyleLonghands[i], borderColorLonghands[i]]).filter(Boolean).join(' ');
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
export const borderTopProperty = masonShorthandProperty(borderSideShorthands[0], borderSideGetter(0));
|
|
2401
|
+
export const borderRightProperty = masonShorthandProperty(borderSideShorthands[1], borderSideGetter(1));
|
|
2402
|
+
export const borderBottomProperty = masonShorthandProperty(borderSideShorthands[2], borderSideGetter(2));
|
|
2403
|
+
export const borderLeftProperty = masonShorthandProperty(borderSideShorthands[3], borderSideGetter(3));
|
|
2404
|
+
borderStyleProperty.register(Style);
|
|
2405
|
+
borderProperty.register(Style);
|
|
2406
|
+
borderTopProperty.register(Style);
|
|
2407
|
+
borderRightProperty.register(Style);
|
|
2408
|
+
borderBottomProperty.register(Style);
|
|
2409
|
+
borderLeftProperty.register(Style);
|
|
2410
|
+
const LOGICAL_SIDES = [
|
|
2411
|
+
['block-start', 0],
|
|
2412
|
+
['inline-end', 1],
|
|
2413
|
+
['block-end', 2],
|
|
2414
|
+
['inline-start', 3],
|
|
2415
|
+
];
|
|
2416
|
+
/** `<prefix>-inline<suffix>`, `<prefix>-block<suffix>` and the four `-start`/`-end` sides. */
|
|
2417
|
+
function logicalSides(prefix, suffix, sides, splitAxis) {
|
|
2418
|
+
const inline = { cssName: `${prefix}-inline${suffix}`, longhands: [sides[3], sides[1]], split: splitAxis };
|
|
2419
|
+
const block = { cssName: `${prefix}-block${suffix}`, longhands: [sides[0], sides[2]], split: splitAxis };
|
|
2420
|
+
const perSide = LOGICAL_SIDES.map(([side, i]) => ({ cssName: `${prefix}-${side}${suffix}`, longhands: [sides[i]], split: passThrough }));
|
|
2421
|
+
return [inline, block, ...perSide];
|
|
2422
|
+
}
|
|
2423
|
+
const borderSideLonghands = (i) => [borderWidthLonghands[i], borderStyleLonghands[i], borderColorLonghands[i]];
|
|
2424
|
+
const logicalShorthands = [
|
|
2425
|
+
...logicalSides('margin', '', marginLonghands, splitMarginStartEnd),
|
|
2426
|
+
...logicalSides('padding', '', paddingLonghands, splitPaddingStartEnd),
|
|
2427
|
+
...logicalSides('inset', '', [topProperty, rightProperty, bottomProperty, leftProperty], splitInsetStartEnd),
|
|
2428
|
+
...logicalSides('border', '-width', borderWidthLonghands, splitBorderWidthStartEnd),
|
|
2429
|
+
...logicalSides('border', '-style', borderStyleLonghands, splitBorderStyleStartEnd),
|
|
2430
|
+
...logicalSides('border', '-color', borderColorLonghands, splitBorderColorStartEnd),
|
|
2431
|
+
// `border-inline: 1px solid` gives both sides the same border.
|
|
2432
|
+
{ cssName: 'border-inline', longhands: [...borderSideLonghands(3), ...borderSideLonghands(1)], split: (value) => [...splitBorderSide(value), ...splitBorderSide(value)] },
|
|
2433
|
+
{ cssName: 'border-block', longhands: [...borderSideLonghands(0), ...borderSideLonghands(2)], split: (value) => [...splitBorderSide(value), ...splitBorderSide(value)] },
|
|
2434
|
+
...LOGICAL_SIDES.map(([side, i]) => ({ cssName: `border-${side}`, longhands: borderSideLonghands(i), split: splitBorderSide })),
|
|
2435
|
+
// Corners are <block>-<inline>: start-start is top-left.
|
|
2436
|
+
{ cssName: 'border-start-start-radius', longhands: [borderTopLeftRadiusProperty], split: passThrough },
|
|
2437
|
+
{ cssName: 'border-start-end-radius', longhands: [borderTopRightRadiusProperty], split: passThrough },
|
|
2438
|
+
{ cssName: 'border-end-end-radius', longhands: [borderBottomRightRadiusProperty], split: passThrough },
|
|
2439
|
+
{ cssName: 'border-end-start-radius', longhands: [borderBottomLeftRadiusProperty], split: passThrough },
|
|
2440
|
+
{ cssName: 'inline-size', longhands: [widthProperty], split: passThrough },
|
|
2441
|
+
{ cssName: 'block-size', longhands: [heightProperty], split: passThrough },
|
|
2442
|
+
{ cssName: 'min-inline-size', longhands: [minWidthProperty], split: passThrough },
|
|
2443
|
+
{ cssName: 'min-block-size', longhands: [minHeightProperty], split: passThrough },
|
|
2444
|
+
{ cssName: 'max-inline-size', longhands: [maxWidthProperty], split: passThrough },
|
|
2445
|
+
{ cssName: 'max-block-size', longhands: [maxHeightProperty], split: passThrough },
|
|
2446
|
+
{ cssName: 'overflow-inline', longhands: [overflowXProperty], split: passThrough },
|
|
2447
|
+
{ cssName: 'overflow-block', longhands: [overflowYProperty], split: passThrough },
|
|
2448
|
+
];
|
|
2449
|
+
for (const entry of logicalShorthands) {
|
|
2450
|
+
masonShorthandProperty(entry, function () {
|
|
2451
|
+
const parts = entry.longhands.map((longhand) => cssText(this[longhand.name]));
|
|
2452
|
+
// The axis shorthands read back as one value when both sides agree.
|
|
2453
|
+
return entry.longhands.length === 2 && parts[0] === parts[1] ? parts[0] : parts.join(' ');
|
|
2454
|
+
}).register(Style);
|
|
2455
|
+
}
|
|
2456
|
+
export const masonShorthands = [...coreShorthands, ...gridPlacementShorthands, borderStyleShorthand, borderShorthand, ...borderSideShorthands, ...logicalShorthands, overflowShorthand, maskShorthand, webkitMaskShorthand, maskBorderShorthand, webkitMaskBoxImageShorthand, gapShorthand, gridGapShorthand, flexFlowShorthand, flexShorthand];
|