react-native-windows 0.79.5 → 0.80.0-preview.10
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/.flowconfig +12 -3
- package/Directory.Build.props +11 -2
- package/Folly/TEMP_UntilFollyUpdate/json/json.cpp +1 -1
- package/Libraries/Alert/Alert.d.ts +4 -1
- package/Libraries/Alert/Alert.js +3 -0
- package/Libraries/Alert/Alert.windows.js +3 -0
- package/Libraries/Alert/RCTAlertManager.js +17 -0
- package/Libraries/Animated/Animated.js.flow +1 -3
- package/Libraries/Animated/AnimatedEvent.js +4 -3
- package/Libraries/Animated/AnimatedExports.js +2 -2
- package/Libraries/Animated/AnimatedExports.js.flow +140 -0
- package/Libraries/Animated/AnimatedImplementation.js +2 -123
- package/Libraries/Animated/Easing.js +13 -15
- package/Libraries/Animated/animations/Animation.js +8 -4
- package/Libraries/Animated/components/AnimatedFlatList.js +7 -6
- package/Libraries/Animated/components/AnimatedScrollView.js +48 -42
- package/Libraries/Animated/components/AnimatedSectionList.js +11 -7
- package/Libraries/Animated/createAnimatedComponent.js +105 -57
- package/Libraries/Animated/nodes/AnimatedNode.js +4 -3
- package/Libraries/Animated/nodes/AnimatedProps.js +46 -26
- package/Libraries/Animated/nodes/AnimatedValue.js +16 -7
- package/Libraries/Animated/nodes/AnimatedValueXY.js +3 -1
- package/Libraries/AppState/AppState.js +7 -2
- package/Libraries/BatchedBridge/MessageQueue.js +2 -2
- package/Libraries/BatchedBridge/NativeModules.js +2 -0
- package/Libraries/Blob/BlobManager.js +1 -0
- package/Libraries/Blob/FileReader.js +219 -8
- package/Libraries/Blob/URL.js +37 -12
- package/Libraries/Blob/URLSearchParams.js +106 -31
- package/Libraries/Blob/URLSearchParams.js.flow +12 -7
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +1 -1
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.windows.js +1 -1
- package/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.js +17 -0
- package/Libraries/Components/ActivityIndicator/ActivityIndicator.js +1 -0
- package/Libraries/Components/Button.d.ts +3 -0
- package/Libraries/Components/Button.js +1 -1
- package/Libraries/Components/Button.windows.js +27 -1
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +1 -3
- package/Libraries/{NewAppScreen/components/Colors.js → Components/DrawerAndroid/DrawerLayoutAndroid.ios.js} +6 -10
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js +6 -66
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js.flow +18 -0
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroidFallback.js +71 -0
- package/Libraries/Components/Flyout/Flyout.js +11 -0
- package/Libraries/Components/Keyboard/Keyboard.js +5 -3
- package/Libraries/Components/Keyboard/KeyboardAvoidingView.js +6 -3
- package/Libraries/Components/Keyboard/KeyboardExt.js.map +1 -1
- package/Libraries/Components/Popup/Popup.js +11 -0
- package/Libraries/Components/Pressable/Pressable.js +20 -4
- package/Libraries/Components/Pressable/Pressable.windows.js +20 -4
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.js +25 -3
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroidTypes.js +29 -20
- package/Libraries/Components/RefreshControl/RefreshControl.js +1 -1
- package/Libraries/Components/RefreshControl/RefreshControl.windows.js +1 -1
- package/Libraries/Components/ScrollView/ScrollView.d.ts +3 -3
- package/Libraries/Components/ScrollView/ScrollView.js +132 -122
- package/Libraries/Components/ScrollView/ScrollView.windows.js +131 -122
- package/Libraries/Components/StaticRenderer.js +1 -1
- package/Libraries/Components/Switch/Switch.d.ts +3 -0
- package/Libraries/Components/Switch/Switch.js +8 -4
- package/Libraries/Components/Switch/Switch.windows.js +17 -4
- package/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js +2 -1
- package/Libraries/Components/TextInput/RCTTextInputViewConfig.js +2 -4
- package/Libraries/Components/TextInput/TextInput.d.ts +70 -33
- package/Libraries/Components/TextInput/TextInput.flow.js +100 -51
- package/Libraries/Components/TextInput/TextInput.flow.windows.js +1246 -0
- package/Libraries/Components/TextInput/TextInput.js +88 -1027
- package/Libraries/Components/TextInput/TextInput.windows.js +104 -1092
- package/Libraries/Components/TextInput/TextInputState.js +1 -1
- package/Libraries/Components/TextInput/TextInputState.windows.js +1 -1
- package/Libraries/Components/TextInput/WindowsTextInputNativeComponent.js +2 -1
- package/Libraries/{Modal/ModalInjection.js → Components/ToastAndroid/ToastAndroid.ios.js} +3 -5
- package/Libraries/Components/ToastAndroid/ToastAndroid.js +4 -32
- package/Libraries/Components/ToastAndroid/ToastAndroid.js.flow +109 -0
- package/Libraries/Components/ToastAndroid/ToastAndroidFallback.js +45 -0
- package/Libraries/Components/Touchable/Touchable.js +5 -5
- package/Libraries/Components/Touchable/Touchable.windows.js +5 -5
- package/Libraries/Components/Touchable/TouchableBounce.js +14 -7
- package/Libraries/Components/Touchable/TouchableBounce.windows.js +14 -7
- package/Libraries/Components/Touchable/TouchableHighlight.js +10 -7
- package/Libraries/Components/Touchable/TouchableHighlight.windows.js +10 -7
- package/Libraries/Components/Touchable/TouchableNativeFeedback.js +6 -6
- package/Libraries/Components/Touchable/TouchableNativeFeedback.windows.js +6 -6
- package/Libraries/Components/Touchable/TouchableOpacity.js +13 -6
- package/Libraries/Components/Touchable/TouchableOpacity.windows.js +13 -6
- package/Libraries/Components/View/View.js +18 -21
- package/Libraries/Components/View/View.windows.js +39 -41
- package/Libraries/Components/View/ViewAccessibility.d.ts +8 -0
- package/Libraries/Components/View/ViewAccessibility.js +25 -1
- package/Libraries/Components/View/ViewAccessibility.windows.js +9 -1
- package/Libraries/Components/View/ViewPropTypes.js +49 -3
- package/Libraries/Components/View/ViewPropTypes.windows.js +50 -2
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Core/setUpReactDevTools.js +5 -5
- package/Libraries/Debugging/DebuggingOverlayRegistry.js +3 -3
- package/Libraries/EventEmitter/NativeEventEmitter.js +9 -4
- package/Libraries/Image/AssetSourceResolver.js +17 -4
- package/Libraries/Image/AssetSourceResolver.windows.js +17 -4
- package/Libraries/Image/Image.d.ts +26 -10
- package/Libraries/Image/Image.js +17 -0
- package/Libraries/Image/Image.js.flow +5 -5
- package/Libraries/Image/Image.windows.js +13 -1
- package/Libraries/Image/ImageBackground.js +2 -0
- package/Libraries/Image/ImageInjection.js +1 -1
- package/Libraries/Image/ImageProps.js +22 -17
- package/Libraries/Image/ImageSource.js +3 -1
- package/Libraries/Image/ImageSourceUtils.js +4 -2
- package/Libraries/Image/ImageTypes.flow.js +1 -1
- package/Libraries/Interaction/InteractionManager.d.ts +13 -0
- package/Libraries/Interaction/InteractionManager.js +1 -1
- package/Libraries/Interaction/PanResponder.js +3 -3
- package/Libraries/Interaction/TaskQueue.js +1 -0
- package/Libraries/LayoutAnimation/LayoutAnimation.js +2 -2
- package/Libraries/Linking/Linking.js +1 -1
- package/Libraries/Lists/FlatList.d.ts +2 -2
- package/Libraries/Lists/FlatList.js +8 -11
- package/Libraries/Lists/SectionList.js +39 -42
- package/Libraries/Lists/SectionListModern.js +25 -34
- package/Libraries/Lists/VirtualizedList.js +1 -0
- package/Libraries/Lists/VirtualizedSectionList.js +1 -0
- package/Libraries/LogBox/Data/LogBoxData.js +1 -1
- package/Libraries/LogBox/LogBoxNotificationContainer.js +1 -1
- package/Libraries/Modal/Modal.js +33 -7
- package/Libraries/Modal/Modal.windows.js +33 -10
- package/Libraries/NativeComponent/BaseViewConfig.android.js +2 -0
- package/Libraries/NativeComponent/BaseViewConfig.ios.js +2 -0
- package/Libraries/NativeComponent/BaseViewConfig.js +17 -0
- package/Libraries/NativeComponent/BaseViewConfig.windows.js +3 -0
- package/Libraries/NativeComponent/PlatformBaseViewConfig.js +2 -2
- package/Libraries/NativeModules/specs/NativeDevMenu.js +2 -2
- package/Libraries/Network/RCTNetworking.android.js +1 -1
- package/Libraries/Network/RCTNetworking.ios.js +1 -1
- package/Libraries/Network/RCTNetworking.js +17 -0
- package/Libraries/Network/RCTNetworking.js.flow +1 -1
- package/Libraries/Network/RCTNetworking.windows.js +1 -1
- package/Libraries/Network/XMLHttpRequest.js +781 -10
- package/Libraries/Performance/Systrace.js +7 -7
- package/Libraries/Pressability/Pressability.js +1 -1
- package/Libraries/Pressability/Pressability.windows.js +1 -1
- package/Libraries/ReactNative/AppContainer-dev.js +5 -4
- package/Libraries/ReactNative/AppRegistry.flow.js +49 -0
- package/Libraries/ReactNative/AppRegistry.js +2 -322
- package/Libraries/ReactNative/AppRegistry.js.flow +23 -0
- package/Libraries/ReactNative/AppRegistryImpl.js +316 -0
- package/Libraries/ReactNative/FabricUIManager.js +10 -0
- package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent.js +2 -4
- package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstance.js +1 -4
- package/Libraries/ReactNative/RendererImplementation.js +10 -5
- package/Libraries/ReactNative/getNativeComponentAttributes.js +1 -0
- package/Libraries/ReactNative/renderApplication.js +9 -0
- package/Libraries/ReactPrivate/ReactNativePrivateInterface.js +3 -3
- package/Libraries/ReactPrivate/ReactNativePrivateInterface.js.flow +51 -0
- package/Libraries/Renderer/implementations/ReactFabric-dev.js +4840 -4748
- package/Libraries/Renderer/implementations/ReactFabric-prod.js +4947 -4829
- package/Libraries/Renderer/implementations/ReactFabric-profiling.js +3998 -3888
- package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +5005 -4948
- package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +2744 -2652
- package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +5020 -4933
- package/Libraries/Renderer/shims/ReactNativeTypes.js +3 -3
- package/Libraries/Settings/Settings.ios.js +1 -0
- package/Libraries/Settings/Settings.js +13 -19
- package/Libraries/Settings/SettingsFallback.js +33 -0
- package/Libraries/StyleSheet/PlatformColorValueTypes.js +15 -0
- package/Libraries/StyleSheet/PlatformColorValueTypesIOS.js +6 -0
- package/Libraries/StyleSheet/Rect.js +1 -0
- package/Libraries/StyleSheet/StyleSheet.js +31 -200
- package/Libraries/StyleSheet/StyleSheet.js.flow +188 -0
- package/Libraries/StyleSheet/StyleSheetExports.js +210 -0
- package/Libraries/StyleSheet/StyleSheetExports.js.flow +112 -0
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +1 -1
- package/Libraries/StyleSheet/StyleSheetTypes.js +130 -52
- package/Libraries/StyleSheet/flattenStyle.js +14 -4
- package/Libraries/StyleSheet/private/_TransformStyle.js +49 -21
- package/Libraries/StyleSheet/processBackgroundImage.js +670 -214
- package/Libraries/Text/Text.d.ts +2 -5
- package/Libraries/Text/Text.js +3 -3
- package/Libraries/Text/Text.windows.js +3 -3
- package/Libraries/Text/TextNativeComponent.js +0 -4
- package/Libraries/Text/TextProps.js +5 -33
- package/Libraries/Text/TextProps.windows.js +5 -32
- package/Libraries/Types/CodegenTypesNamespace.d.ts +45 -0
- package/Libraries/{Blob/__mocks__/BlobModule.js → Types/CodegenTypesNamespace.js} +4 -6
- package/Libraries/Types/CoreEventTypes.d.ts +6 -1
- package/Libraries/Types/CoreEventTypes.js +1 -1
- package/Libraries/Types/CoreEventTypes.windows.js +1 -1
- package/Libraries/Utilities/Appearance.js +2 -0
- package/Libraries/Utilities/BackHandler.js +17 -0
- package/Libraries/Utilities/DeviceInfo.js +2 -0
- package/Libraries/Utilities/Dimensions.js +1 -1
- package/Libraries/Utilities/Platform.js +17 -0
- package/Libraries/Utilities/PlatformTypes.js +11 -3
- package/Libraries/Utilities/ReactNativeTestTools.js +2 -2
- package/Libraries/Utilities/codegenNativeCommands.d.ts +18 -0
- package/Libraries/Utilities/codegenNativeComponent.d.ts +26 -0
- package/Libraries/WebSocket/WebSocket.js +313 -8
- package/Libraries/vendor/core/ErrorUtils.js +28 -2
- package/Libraries/vendor/emitter/EventEmitter.js +6 -2
- package/Microsoft.ReactNative/CompositionSwitcher.idl +3 -0
- package/Microsoft.ReactNative/Fabric/AbiComponentDescriptor.cpp +0 -6
- package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +248 -6
- package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +55 -160
- package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +30 -9
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +36 -0
- package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +36 -33
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +22 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +3 -0
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +46 -0
- package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +4 -1
- package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +11 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.cpp +37 -5
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +177 -25
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +4 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.cpp +29 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.h +2 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +17 -34
- package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +225 -0
- package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +23 -0
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +9 -3
- package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +2 -0
- package/Microsoft.ReactNative/Fabric/ImageManager.cpp +1 -1
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +16 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h +1 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +9 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +1 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +4 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.cpp +64 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.h +11 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.cpp +36 -96
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.h +1 -1
- package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +29 -0
- package/Microsoft.ReactNative/Modules/SampleTurboModule.cpp +4 -0
- package/Microsoft.ReactNative/Modules/SampleTurboModule.h +3 -0
- package/Microsoft.ReactNative/TurboModulesProvider.h +1 -1
- package/Microsoft.ReactNative/Utils/ThemeUtils.cpp +49 -0
- package/Microsoft.ReactNative/Utils/ThemeUtils.h +31 -0
- package/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.h +1 -1
- package/Microsoft.ReactNative.Cxx/JSI/LongLivedJsiValue.h +1 -1
- package/PropertySheets/Generated/PackageVersion.g.props +4 -4
- package/PropertySheets/JSEngine.props +1 -1
- package/PropertySheets/React.Cpp.props +4 -0
- package/PropertySheets/Warnings.props +45 -0
- package/README.md +6 -2
- package/ReactCommon/ReactCommon.vcxproj +9 -4
- package/ReactCommon/ReactCommon.vcxproj.filters +6 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/CxxNativeModule.cpp +253 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp +5 -2
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp +4 -8
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/TraceSection.h +184 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/NetworkIOAgent.cpp +22 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/NetworkIOAgent.h +2 -4
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModuleWithJSIBindings.cpp +27 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +3 -2
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/AccessibilityPrimitives.h +1 -1
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/AccessibilityProps.cpp +308 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/core/DynamicEventPayload.cpp +42 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/css/CSSTokenizer.h +7 -51
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp +10 -5
- package/Scripts/creaternwapp.cmd +9 -3
- package/Scripts/rnw-dependencies.ps1 +16 -3
- package/Shared/Shared.vcxitems +3 -2
- package/Shared/Shared.vcxitems.filters +2 -1
- package/codegen/NativeAnimatedModuleSpec.g.h +2 -0
- package/codegen/NativeAnimatedTurboModuleSpec.g.h +2 -0
- package/codegen/NativePerformanceSpec.g.h +14 -0
- package/codegen/NativeReactNativeFeatureFlagsSpec.g.h +151 -127
- package/codegen/NativeSampleTurboModuleSpec.g.h +14 -8
- package/codegen/react/components/rnwcore/EventEmitters.cpp +48 -48
- package/codegen/rnwcoreJSI-generated.cpp +159 -129
- package/codegen/rnwcoreJSI.h +534 -408
- package/index.js +51 -331
- package/index.windows.js +70 -352
- package/interface.js +0 -4
- package/jest/resolver.js +31 -0
- package/jest/setup.js +6 -2
- package/package.json +29 -28
- package/src/private/animated/NativeAnimatedHelper.js +21 -8
- package/src/private/animated/createAnimatedPropsHook.js +11 -16
- package/src/private/animated/createAnimatedPropsMemoHook.js +1 -2
- package/src/private/components/{SafeAreaView_INTERNAL_DO_NOT_USE.js → safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE.js} +6 -6
- package/src/private/components/{HScrollViewNativeComponents.js → scrollview/HScrollViewNativeComponents.js} +8 -8
- package/src/private/components/scrollview/VScrollViewNativeComponents.js +25 -0
- package/src/private/{devmenu → devsupport/devmenu}/DevMenu.js +1 -1
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/BorderBox.js +3 -3
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/BoxInspector.js +6 -5
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/ElementBox.js +8 -6
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/ElementProperties.js +11 -10
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/Inspector.js +14 -12
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/InspectorOverlay.js +5 -4
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/InspectorPanel.js +9 -8
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/NetworkOverlay.js +10 -9
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/ReactDevToolsOverlay.js +7 -7
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/StyleInspector.js +7 -6
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/XHRInterceptor.js +2 -2
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/getInspectorDataForViewAtPoint.js +4 -4
- package/src/private/{inspector → devsupport/devmenu/elementinspector}/resolveBoxStyle.js +1 -1
- package/src/private/{inspector → devsupport/devmenu/perfmonitor}/PerformanceOverlay.js +6 -5
- package/src/private/{specs_DEPRECATED/modules → devsupport/devmenu/specs}/NativeDevMenu.js +2 -2
- package/src/private/{debugging → devsupport/rndevtools}/ReactDevToolsSettingsManager.android.js +1 -1
- package/src/private/{debugging → devsupport/rndevtools}/ReactDevToolsSettingsManager.ios.js +1 -1
- package/src/private/{debugging → devsupport/rndevtools}/ReactDevToolsSettingsManager.windows.js +1 -1
- package/src/private/{debugging → devsupport/rndevtools}/setUpFuseboxReactDevToolsDispatcher.js +1 -1
- package/src/private/{fusebox → devsupport/rndevtools}/specs/NativeReactDevToolsRuntimeSettingsModule.js +2 -2
- package/src/private/{specs_DEPRECATED/modules → devsupport/rndevtools/specs}/NativeReactDevToolsSettingsManager.js +2 -2
- package/src/private/featureflags/ReactNativeFeatureFlags.js +82 -80
- package/src/private/featureflags/ReactNativeFeatureFlagsBase.js +12 -1
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +17 -13
- package/src/private/renderer/errorhandling/ErrorHandlers.js +2 -2
- package/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeSampleTurboModule.js +3 -0
- package/src/private/styles/composeStyles.js +12 -5
- package/src/private/types/HostComponent.js +1 -1
- package/src/private/types/HostInstance.js +67 -1
- package/src/private/webapis/dom/nodes/ReactNativeElement.js +2 -5
- package/src/private/webapis/dom/nodes/ReadOnlyNode.js +5 -18
- package/src/private/webapis/dom/nodes/internals/NodeInternals.js +6 -0
- package/src/private/webapis/performance/Performance.js +1 -3
- package/src/private/webapis/performance/PerformanceEntry.js +6 -1
- package/src/private/webapis/performance/internals/RawPerformanceEntry.js +3 -0
- package/src/private/webapis/performance/specs/NativePerformance.js +10 -1
- package/src/types/globals.d.ts +42 -0
- package/stubs/double-conversion/double-conversion.h +3 -1
- package/templates/cpp-app/template.config.js +2 -1
- package/templates/cpp-app/windows/MyApp/MyApp.vcxproj +4 -0
- package/templates/cpp-lib/example/metro.config.js +1 -1
- package/templates/cpp-lib/windows/MyLib/MyLib.vcxproj +4 -0
- package/templates/old/generateWrapper.js +1 -1
- package/templates/old/uwp-cpp-app/template.config.js +1 -1
- package/types/index.d.ts +6 -3
- package/types/public/ReactNativeTypes.d.ts +2 -2
- package/Libraries/BatchedBridge/__mocks__/MessageQueueTestConfig.js +0 -38
- package/Libraries/BatchedBridge/__mocks__/MessageQueueTestModule.js +0 -22
- package/Libraries/Blob/FileReader_new.js +0 -231
- package/Libraries/Blob/FileReader_old.js +0 -186
- package/Libraries/Blob/__mocks__/FileReaderModule.js +0 -20
- package/Libraries/Components/RefreshControl/__mocks__/RefreshControlMock.js +0 -32
- package/Libraries/Core/__mocks__/ErrorUtils.js +0 -33
- package/Libraries/Core/__mocks__/NativeExceptionsManager.js +0 -19
- package/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js +0 -49
- package/Libraries/Events/CustomEvent.js +0 -32
- package/Libraries/Events/EventPolyfill.js +0 -239
- package/Libraries/Lists/__flowtests__/FlatList-flowtest.js +0 -118
- package/Libraries/Lists/__flowtests__/SectionList-flowtest.js +0 -134
- package/Libraries/Network/XMLHttpRequest_new.js +0 -794
- package/Libraries/Network/XMLHttpRequest_old.js +0 -701
- package/Libraries/NewAppScreen/components/DebugInstructions.js +0 -41
- package/Libraries/NewAppScreen/components/DebugInstructions.windows.js +0 -30
- package/Libraries/NewAppScreen/components/Header.js +0 -77
- package/Libraries/NewAppScreen/components/HermesBadge.js +0 -53
- package/Libraries/NewAppScreen/components/LearnMoreLinks.js +0 -148
- package/Libraries/NewAppScreen/components/ReloadInstructions.js +0 -39
- package/Libraries/NewAppScreen/components/ReloadInstructions.windows.js +0 -31
- package/Libraries/NewAppScreen/components/logo.png +0 -0
- package/Libraries/NewAppScreen/index.js +0 -25
- package/Libraries/StyleSheet/__flowtests__/StyleSheet-flowtest.js +0 -58
- package/Libraries/Utilities/__mocks__/BackHandler.js +0 -45
- package/Libraries/Utilities/__mocks__/GlobalPerformanceLogger.js +0 -16
- package/Libraries/Utilities/__mocks__/PixelRatio.js +0 -25
- package/Libraries/WebSocket/WebSocketEvent.js +0 -30
- package/Libraries/WebSocket/WebSocket_new.js +0 -325
- package/Libraries/WebSocket/WebSocket_old.js +0 -297
- package/Libraries/WebSocket/__mocks__/event-target-shim.js +0 -27
- package/Libraries/__flowtests__/ReactNativeTypes-flowtest.js +0 -30
- package/Libraries/vendor/emitter/__flowtests__/EventEmitter-flowtest.js +0 -81
- package/jest/__tests__/setup-test.js +0 -18
- package/src/private/components/VScrollViewNativeComponents.js +0 -25
- package/src/private/utilities/ensureInstance.js +0 -21
- package/src/private/webapis/performance/specs/__mocks__/NativePerformanceMock.js +0 -267
- package/types/modules/LaunchScreen.d.ts +0 -18
- /package/src/private/{devmenu → devsupport/devmenu}/DevMenu.d.ts +0 -0
- /package/src/private/{debugging → devsupport/rndevtools}/FuseboxSessionObserver.js +0 -0
|
@@ -11,24 +11,31 @@
|
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
13
|
import type {ProcessedColorValue} from './processColor';
|
|
14
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
BackgroundImageValue,
|
|
16
|
+
RadialGradientPosition,
|
|
17
|
+
RadialGradientShape,
|
|
18
|
+
RadialGradientSize,
|
|
19
|
+
} from './StyleSheetTypes';
|
|
15
20
|
|
|
16
21
|
const processColor = require('./processColor').default;
|
|
17
|
-
|
|
22
|
+
|
|
23
|
+
// Linear Gradient
|
|
24
|
+
const LINEAR_GRADIENT_DIRECTION_REGEX =
|
|
18
25
|
/^to\s+(?:top|bottom|left|right)(?:\s+(?:top|bottom|left|right))?/i;
|
|
19
|
-
const
|
|
26
|
+
const LINEAR_GRADIENT_ANGLE_UNIT_REGEX =
|
|
27
|
+
/^([+-]?\d*\.?\d+)(deg|grad|rad|turn)$/i;
|
|
28
|
+
const LINEAR_GRADIENT_DEFAULT_DIRECTION: LinearGradientDirection = {
|
|
29
|
+
type: 'angle',
|
|
30
|
+
value: 180,
|
|
31
|
+
};
|
|
20
32
|
|
|
21
33
|
type LinearGradientDirection =
|
|
22
34
|
| {type: 'angle', value: number}
|
|
23
35
|
| {type: 'keyword', value: string};
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
type
|
|
27
|
-
// percentage or pixel value
|
|
28
|
-
type ColorStopPosition = number | string | null;
|
|
29
|
-
|
|
30
|
-
type ParsedGradientValue = {
|
|
31
|
-
type: 'linearGradient',
|
|
37
|
+
type LinearGradientBackgroundImage = {
|
|
38
|
+
type: 'linear-gradient',
|
|
32
39
|
direction: LinearGradientDirection,
|
|
33
40
|
colorStops: $ReadOnlyArray<{
|
|
34
41
|
color: ColorStopColor,
|
|
@@ -36,261 +43,682 @@ type ParsedGradientValue = {
|
|
|
36
43
|
}>,
|
|
37
44
|
};
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
// Radial Gradient
|
|
47
|
+
const DEFAULT_RADIAL_SHAPE = 'ellipse';
|
|
48
|
+
const DEFAULT_RADIAL_SIZE = 'farthest-corner';
|
|
49
|
+
// center
|
|
50
|
+
const DEFAULT_RADIAL_POSITION: RadialGradientPosition = {
|
|
51
|
+
top: '50%',
|
|
52
|
+
left: '50%',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
type RadialGradientBackgroundImage = {
|
|
56
|
+
type: 'radial-gradient',
|
|
57
|
+
shape: RadialGradientShape,
|
|
58
|
+
size: RadialGradientSize,
|
|
59
|
+
position: RadialGradientPosition,
|
|
60
|
+
colorStops: $ReadOnlyArray<{
|
|
61
|
+
color: ColorStopColor,
|
|
62
|
+
position: ColorStopPosition,
|
|
63
|
+
}>,
|
|
42
64
|
};
|
|
43
65
|
|
|
66
|
+
// null color indicate that the transition hint syntax is used. e.g. red, 20%, blue
|
|
67
|
+
type ColorStopColor = ProcessedColorValue | null;
|
|
68
|
+
// percentage or pixel value
|
|
69
|
+
type ColorStopPosition = number | string | null;
|
|
70
|
+
|
|
71
|
+
type ParsedBackgroundImageValue =
|
|
72
|
+
| LinearGradientBackgroundImage
|
|
73
|
+
| RadialGradientBackgroundImage;
|
|
74
|
+
|
|
44
75
|
export default function processBackgroundImage(
|
|
45
|
-
backgroundImage: ?($ReadOnlyArray<
|
|
46
|
-
): $ReadOnlyArray<
|
|
47
|
-
let result: $ReadOnlyArray<
|
|
76
|
+
backgroundImage: ?($ReadOnlyArray<BackgroundImageValue> | string),
|
|
77
|
+
): $ReadOnlyArray<ParsedBackgroundImageValue> {
|
|
78
|
+
let result: $ReadOnlyArray<ParsedBackgroundImageValue> = [];
|
|
48
79
|
if (backgroundImage == null) {
|
|
49
80
|
return result;
|
|
50
81
|
}
|
|
51
82
|
|
|
52
83
|
if (typeof backgroundImage === 'string') {
|
|
53
|
-
result =
|
|
84
|
+
result = parseBackgroundImageCSSString(backgroundImage.replace(/\n/g, ' '));
|
|
54
85
|
} else if (Array.isArray(backgroundImage)) {
|
|
55
86
|
for (const bgImage of backgroundImage) {
|
|
56
|
-
const processedColorStops
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
if (positions != null && positions.length > 0) {
|
|
89
|
-
for (const position of positions) {
|
|
90
|
-
if (
|
|
91
|
-
typeof position === 'number' ||
|
|
92
|
-
(typeof position === 'string' && position.endsWith('%'))
|
|
93
|
-
) {
|
|
94
|
-
processedColorStops.push({
|
|
95
|
-
color: processedColor,
|
|
96
|
-
position,
|
|
97
|
-
});
|
|
98
|
-
} else {
|
|
99
|
-
// If a position is invalid, return an empty array and do not apply gradient. Same as web.
|
|
100
|
-
return [];
|
|
101
|
-
}
|
|
87
|
+
const processedColorStops = processColorStops(bgImage);
|
|
88
|
+
if (processedColorStops == null) {
|
|
89
|
+
// If a color stop is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (bgImage.type === 'linear-gradient') {
|
|
94
|
+
let direction: LinearGradientDirection =
|
|
95
|
+
LINEAR_GRADIENT_DEFAULT_DIRECTION;
|
|
96
|
+
const bgDirection =
|
|
97
|
+
bgImage.direction != null ? bgImage.direction.toLowerCase() : null;
|
|
98
|
+
|
|
99
|
+
if (bgDirection != null) {
|
|
100
|
+
if (LINEAR_GRADIENT_ANGLE_UNIT_REGEX.test(bgDirection)) {
|
|
101
|
+
const parsedAngle = getAngleInDegrees(bgDirection);
|
|
102
|
+
if (parsedAngle != null) {
|
|
103
|
+
direction = {
|
|
104
|
+
type: 'angle',
|
|
105
|
+
value: parsedAngle,
|
|
106
|
+
};
|
|
107
|
+
} else {
|
|
108
|
+
// If an angle is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
} else if (LINEAR_GRADIENT_DIRECTION_REGEX.test(bgDirection)) {
|
|
112
|
+
const parsedDirection = getDirectionForKeyword(bgDirection);
|
|
113
|
+
if (parsedDirection != null) {
|
|
114
|
+
direction = parsedDirection;
|
|
115
|
+
} else {
|
|
116
|
+
// If a direction is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
117
|
+
return [];
|
|
102
118
|
}
|
|
103
119
|
} else {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
position: null,
|
|
107
|
-
});
|
|
120
|
+
// If a direction is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
121
|
+
return [];
|
|
108
122
|
}
|
|
109
123
|
}
|
|
110
|
-
}
|
|
111
124
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
result = result.concat({
|
|
126
|
+
type: 'linear-gradient',
|
|
127
|
+
direction,
|
|
128
|
+
colorStops: processedColorStops,
|
|
129
|
+
});
|
|
130
|
+
} else if (bgImage.type === 'radial-gradient') {
|
|
131
|
+
let shape: RadialGradientShape = DEFAULT_RADIAL_SHAPE;
|
|
132
|
+
let size: RadialGradientSize = DEFAULT_RADIAL_SIZE;
|
|
133
|
+
let position: RadialGradientPosition = {...DEFAULT_RADIAL_POSITION};
|
|
134
|
+
|
|
135
|
+
if (bgImage.shape != null) {
|
|
136
|
+
if (bgImage.shape === 'circle' || bgImage.shape === 'ellipse') {
|
|
137
|
+
shape = bgImage.shape;
|
|
124
138
|
} else {
|
|
125
|
-
// If
|
|
139
|
+
// If the shape is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
126
140
|
return [];
|
|
127
141
|
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (bgImage.size != null) {
|
|
145
|
+
if (
|
|
146
|
+
typeof bgImage.size === 'string' &&
|
|
147
|
+
(bgImage.size === 'closest-side' ||
|
|
148
|
+
bgImage.size === 'closest-corner' ||
|
|
149
|
+
bgImage.size === 'farthest-side' ||
|
|
150
|
+
bgImage.size === 'farthest-corner')
|
|
151
|
+
) {
|
|
152
|
+
size = bgImage.size;
|
|
153
|
+
} else if (
|
|
154
|
+
typeof bgImage.size === 'object' &&
|
|
155
|
+
bgImage.size.x != null &&
|
|
156
|
+
bgImage.size.y != null
|
|
157
|
+
) {
|
|
158
|
+
size = {
|
|
159
|
+
x: bgImage.size.x,
|
|
160
|
+
y: bgImage.size.y,
|
|
161
|
+
};
|
|
132
162
|
} else {
|
|
133
|
-
// If
|
|
163
|
+
// If the size is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
134
164
|
return [];
|
|
135
165
|
}
|
|
136
|
-
} else {
|
|
137
|
-
// If a direction is invalid, return an empty array and do not apply any gradient. Same as web.
|
|
138
|
-
return [];
|
|
139
166
|
}
|
|
140
|
-
}
|
|
141
167
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
168
|
+
if (bgImage.position != null) {
|
|
169
|
+
position = bgImage.position;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
result = result.concat({
|
|
173
|
+
type: 'radial-gradient',
|
|
174
|
+
shape,
|
|
175
|
+
size,
|
|
176
|
+
position,
|
|
177
|
+
colorStops: processedColorStops,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
147
180
|
}
|
|
148
181
|
}
|
|
149
182
|
|
|
150
183
|
return result;
|
|
151
184
|
}
|
|
152
185
|
|
|
153
|
-
function
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
186
|
+
function processColorStops(bgImage: BackgroundImageValue): $ReadOnlyArray<{
|
|
187
|
+
color: ColorStopColor,
|
|
188
|
+
position: ColorStopPosition,
|
|
189
|
+
}> | null {
|
|
190
|
+
const processedColorStops: Array<{
|
|
191
|
+
color: ColorStopColor,
|
|
192
|
+
position: ColorStopPosition,
|
|
193
|
+
}> = [];
|
|
194
|
+
|
|
195
|
+
for (let index = 0; index < bgImage.colorStops.length; index++) {
|
|
196
|
+
const colorStop = bgImage.colorStops[index];
|
|
197
|
+
const positions = colorStop.positions;
|
|
198
|
+
// Color transition hint syntax (red, 20%, blue)
|
|
199
|
+
if (
|
|
200
|
+
colorStop.color == null &&
|
|
201
|
+
Array.isArray(positions) &&
|
|
202
|
+
positions.length === 1
|
|
203
|
+
) {
|
|
204
|
+
const position = positions[0];
|
|
205
|
+
if (
|
|
206
|
+
typeof position === 'number' ||
|
|
207
|
+
(typeof position === 'string' && position.endsWith('%'))
|
|
208
|
+
) {
|
|
209
|
+
processedColorStops.push({
|
|
210
|
+
color: null,
|
|
211
|
+
position,
|
|
212
|
+
});
|
|
176
213
|
} else {
|
|
177
|
-
// If
|
|
178
|
-
return
|
|
214
|
+
// If a position is invalid, return null and do not apply gradient. Same as web.
|
|
215
|
+
return null;
|
|
179
216
|
}
|
|
180
|
-
} else
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
|
|
217
|
+
} else {
|
|
218
|
+
const processedColor = processColor(colorStop.color);
|
|
219
|
+
if (processedColor == null) {
|
|
220
|
+
// If a color is invalid, return null and do not apply gradient. Same as web.
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
if (positions != null && positions.length > 0) {
|
|
224
|
+
for (const position of positions) {
|
|
225
|
+
if (
|
|
226
|
+
typeof position === 'number' ||
|
|
227
|
+
(typeof position === 'string' && position.endsWith('%'))
|
|
228
|
+
) {
|
|
229
|
+
processedColorStops.push({
|
|
230
|
+
color: processedColor,
|
|
231
|
+
position,
|
|
232
|
+
});
|
|
233
|
+
} else {
|
|
234
|
+
// If a position is invalid, return null and do not apply gradient. Same as web.
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
185
238
|
} else {
|
|
186
|
-
|
|
187
|
-
|
|
239
|
+
processedColorStops.push({
|
|
240
|
+
color: processedColor,
|
|
241
|
+
position: null,
|
|
242
|
+
});
|
|
188
243
|
}
|
|
189
244
|
}
|
|
245
|
+
}
|
|
190
246
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
247
|
+
return processedColorStops;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function parseBackgroundImageCSSString(
|
|
251
|
+
cssString: string,
|
|
252
|
+
): $ReadOnlyArray<ParsedBackgroundImageValue> {
|
|
253
|
+
const gradients = [];
|
|
254
|
+
const bgImageStrings = splitGradients(cssString);
|
|
255
|
+
|
|
256
|
+
for (const bgImageString of bgImageStrings) {
|
|
257
|
+
const bgImage = bgImageString.toLowerCase();
|
|
258
|
+
const gradientRegex = /^(linear|radial)-gradient\(((?:\([^)]*\)|[^()])*)\)/;
|
|
259
|
+
|
|
260
|
+
const match = gradientRegex.exec(bgImage);
|
|
261
|
+
if (match) {
|
|
262
|
+
const [, type, gradientContent] = match;
|
|
263
|
+
const isRadial = type.toLowerCase() === 'radial';
|
|
264
|
+
const gradient = isRadial
|
|
265
|
+
? parseRadialGradientCSSString(gradientContent)
|
|
266
|
+
: parseLinearGradientCSSString(gradientContent);
|
|
267
|
+
|
|
268
|
+
if (gradient != null) {
|
|
269
|
+
gradients.push(gradient);
|
|
204
270
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return gradients;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function parseRadialGradientCSSString(
|
|
277
|
+
gradientContent: string,
|
|
278
|
+
): RadialGradientBackgroundImage | null {
|
|
279
|
+
let shape: RadialGradientShape = DEFAULT_RADIAL_SHAPE;
|
|
280
|
+
let size: RadialGradientSize = DEFAULT_RADIAL_SIZE;
|
|
281
|
+
let position: RadialGradientPosition = {...DEFAULT_RADIAL_POSITION};
|
|
282
|
+
|
|
283
|
+
// split the content by commas, but not if inside parentheses (for color values)
|
|
284
|
+
const parts = gradientContent.split(/,(?![^(]*\))/);
|
|
285
|
+
// first part may contain shape, size, and position
|
|
286
|
+
// [ <radial-shape> || <radial-size> ]? [ at <position> ]?
|
|
287
|
+
const firstPartStr = parts[0].trim();
|
|
288
|
+
const remainingParts = [...parts];
|
|
289
|
+
let hasShapeSizeOrPositionString = false;
|
|
290
|
+
let hasExplicitSingleSize = false;
|
|
291
|
+
let hasExplicitShape = false;
|
|
292
|
+
const firstPartTokens = firstPartStr.split(/\s+/);
|
|
293
|
+
|
|
294
|
+
// firstPartTokens is the shape, size, and position
|
|
295
|
+
while (firstPartTokens.length > 0) {
|
|
296
|
+
let token = firstPartTokens.shift();
|
|
297
|
+
if (token == null) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
let tokenTrimmed = token.toLowerCase().trim();
|
|
215
301
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
302
|
+
if (tokenTrimmed === 'circle' || tokenTrimmed === 'ellipse') {
|
|
303
|
+
shape = tokenTrimmed === 'circle' ? 'circle' : 'ellipse';
|
|
304
|
+
hasShapeSizeOrPositionString = true;
|
|
305
|
+
hasExplicitShape = true;
|
|
306
|
+
} else if (
|
|
307
|
+
tokenTrimmed === 'closest-corner' ||
|
|
308
|
+
tokenTrimmed === 'farthest-corner' ||
|
|
309
|
+
tokenTrimmed === 'closest-side' ||
|
|
310
|
+
tokenTrimmed === 'farthest-side'
|
|
311
|
+
) {
|
|
312
|
+
size = tokenTrimmed;
|
|
313
|
+
hasShapeSizeOrPositionString = true;
|
|
314
|
+
} else if (tokenTrimmed.endsWith('px') || tokenTrimmed.endsWith('%')) {
|
|
315
|
+
let sizeX = getPositionFromCSSValue(tokenTrimmed);
|
|
316
|
+
if (sizeX == null) {
|
|
317
|
+
// If a size is invalid, return null and do not apply any gradient. Same as web.
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
if (typeof sizeX === 'number' && sizeX < 0) {
|
|
321
|
+
// If a size is invalid, return null and do not apply any gradient. Same as web.
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
hasShapeSizeOrPositionString = true;
|
|
325
|
+
size = {x: sizeX, y: sizeX};
|
|
326
|
+
token = firstPartTokens.shift();
|
|
327
|
+
if (token == null) {
|
|
328
|
+
hasExplicitSingleSize = true;
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
tokenTrimmed = token.toLowerCase().trim();
|
|
332
|
+
if (tokenTrimmed.endsWith('px') || tokenTrimmed.endsWith('%')) {
|
|
333
|
+
const sizeY = getPositionFromCSSValue(tokenTrimmed);
|
|
334
|
+
if (sizeY == null) {
|
|
335
|
+
// If a size is invalid, return null and do not apply any gradient. Same as web.
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
if (typeof sizeY === 'number' && sizeY < 0) {
|
|
339
|
+
// If a size is invalid, return null and do not apply any gradient. Same as web.
|
|
340
|
+
return null;
|
|
219
341
|
}
|
|
342
|
+
size = {x: sizeX, y: sizeY};
|
|
343
|
+
} else {
|
|
344
|
+
hasExplicitSingleSize = true;
|
|
345
|
+
}
|
|
346
|
+
} else if (tokenTrimmed === 'at') {
|
|
347
|
+
let top: string | number;
|
|
348
|
+
let left: string | number;
|
|
349
|
+
let right: string | number;
|
|
350
|
+
let bottom: string | number;
|
|
351
|
+
hasShapeSizeOrPositionString = true;
|
|
220
352
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
});
|
|
225
|
-
colorStops.push({
|
|
226
|
-
color: processedColor,
|
|
227
|
-
position: position2,
|
|
228
|
-
});
|
|
353
|
+
if (firstPartTokens.length === 0) {
|
|
354
|
+
// If 'at' is not followed by a position, return null and do not apply any gradient. Same as web.
|
|
355
|
+
return null;
|
|
229
356
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
return [];
|
|
357
|
+
|
|
358
|
+
// 1. [ left | center | right | top | bottom | <length-percentage> ]
|
|
359
|
+
if (firstPartTokens.length === 1) {
|
|
360
|
+
token = firstPartTokens.shift();
|
|
361
|
+
if (token == null) {
|
|
362
|
+
// If 'at' is not followed by a position, return null and do not apply any gradient. Same as web.
|
|
363
|
+
return null;
|
|
238
364
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
365
|
+
tokenTrimmed = token.toLowerCase().trim();
|
|
366
|
+
if (tokenTrimmed === 'left') {
|
|
367
|
+
left = '0%';
|
|
368
|
+
top = '50%';
|
|
369
|
+
} else if (tokenTrimmed === 'center') {
|
|
370
|
+
left = '50%';
|
|
371
|
+
top = '50%';
|
|
372
|
+
} else if (tokenTrimmed === 'right') {
|
|
373
|
+
left = '100%';
|
|
374
|
+
top = '50%';
|
|
375
|
+
} else if (tokenTrimmed === 'top') {
|
|
376
|
+
left = '50%';
|
|
377
|
+
top = '0%';
|
|
378
|
+
} else if (tokenTrimmed === 'bottom') {
|
|
379
|
+
left = '50%';
|
|
380
|
+
top = '100%';
|
|
381
|
+
} else if (tokenTrimmed.endsWith('px') || tokenTrimmed.endsWith('%')) {
|
|
382
|
+
const value = getPositionFromCSSValue(tokenTrimmed);
|
|
383
|
+
if (value == null) {
|
|
384
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
left = value;
|
|
388
|
+
top = '50%';
|
|
242
389
|
}
|
|
243
|
-
colorStops.push({
|
|
244
|
-
color: processedColor,
|
|
245
|
-
position,
|
|
246
|
-
});
|
|
247
390
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const
|
|
252
|
-
if (
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
391
|
+
|
|
392
|
+
if (firstPartTokens.length === 2) {
|
|
393
|
+
const t1 = firstPartTokens.shift();
|
|
394
|
+
const t2 = firstPartTokens.shift();
|
|
395
|
+
if (t1 == null || t2 == null) {
|
|
396
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const token1 = t1.toLowerCase().trim();
|
|
401
|
+
const token2 = t2.toLowerCase().trim();
|
|
402
|
+
|
|
403
|
+
// 2. [ left | center | right ] && [ top | center | bottom ]
|
|
404
|
+
const horizontalPositions = ['left', 'center', 'right'];
|
|
405
|
+
const verticalPositions = ['top', 'center', 'bottom'];
|
|
406
|
+
|
|
407
|
+
if (
|
|
408
|
+
horizontalPositions.includes(token1) &&
|
|
409
|
+
verticalPositions.includes(token2)
|
|
410
|
+
) {
|
|
411
|
+
left =
|
|
412
|
+
token1 === 'left' ? '0%' : token1 === 'center' ? '50%' : '100%';
|
|
413
|
+
top = token2 === 'top' ? '0%' : token2 === 'center' ? '50%' : '100%';
|
|
414
|
+
} else if (
|
|
415
|
+
verticalPositions.includes(token1) &&
|
|
416
|
+
horizontalPositions.includes(token2)
|
|
417
|
+
) {
|
|
418
|
+
left =
|
|
419
|
+
token2 === 'left' ? '0%' : token2 === 'center' ? '50%' : '100%';
|
|
420
|
+
top = token1 === 'top' ? '0%' : token1 === 'center' ? '50%' : '100%';
|
|
421
|
+
}
|
|
422
|
+
// 3. [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ]
|
|
423
|
+
else {
|
|
424
|
+
if (token1 === 'left') {
|
|
425
|
+
left = '0%';
|
|
426
|
+
} else if (token1 === 'center') {
|
|
427
|
+
left = '50%';
|
|
428
|
+
} else if (token1 === 'right') {
|
|
429
|
+
left = '100%';
|
|
430
|
+
} else if (token1.endsWith('px') || token1.endsWith('%')) {
|
|
431
|
+
const value = getPositionFromCSSValue(token1);
|
|
432
|
+
if (value == null) {
|
|
433
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
left = value;
|
|
437
|
+
} else {
|
|
438
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
439
|
+
return null;
|
|
263
440
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
441
|
+
|
|
442
|
+
if (token2 === 'top') {
|
|
443
|
+
top = '0%';
|
|
444
|
+
} else if (token2 === 'center') {
|
|
445
|
+
top = '50%';
|
|
446
|
+
} else if (token2 === 'bottom') {
|
|
447
|
+
top = '100%';
|
|
448
|
+
} else if (token2.endsWith('px') || token2.endsWith('%')) {
|
|
449
|
+
const value = getPositionFromCSSValue(token2);
|
|
450
|
+
if (value == null) {
|
|
451
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
top = value;
|
|
455
|
+
} else {
|
|
456
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
457
|
+
return null;
|
|
273
458
|
}
|
|
274
|
-
colorStops.push({
|
|
275
|
-
color: processedColor,
|
|
276
|
-
position: null,
|
|
277
|
-
});
|
|
278
459
|
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// 4. [ [ left | right ] <length-percentage> ] && [ [ top | bottom ] <length-percentage> ]
|
|
463
|
+
if (firstPartTokens.length === 4) {
|
|
464
|
+
const t1 = firstPartTokens.shift();
|
|
465
|
+
const t2 = firstPartTokens.shift();
|
|
466
|
+
const t3 = firstPartTokens.shift();
|
|
467
|
+
const t4 = firstPartTokens.shift();
|
|
468
|
+
|
|
469
|
+
if (t1 == null || t2 == null || t3 == null || t4 == null) {
|
|
470
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
const token1 = t1.toLowerCase().trim();
|
|
474
|
+
const token2 = t2.toLowerCase().trim();
|
|
475
|
+
const token3 = t3.toLowerCase().trim();
|
|
476
|
+
const token4 = t4.toLowerCase().trim();
|
|
477
|
+
const keyword1 = token1;
|
|
478
|
+
const value1 = getPositionFromCSSValue(token2);
|
|
479
|
+
const keyword2 = token3;
|
|
480
|
+
const value2 = getPositionFromCSSValue(token4);
|
|
481
|
+
if (value1 == null || value2 == null) {
|
|
482
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (keyword1 === 'left') {
|
|
487
|
+
left = value1;
|
|
488
|
+
} else if (keyword1 === 'right') {
|
|
489
|
+
right = value1;
|
|
490
|
+
} else if (keyword1 === 'top') {
|
|
491
|
+
top = value1;
|
|
492
|
+
} else if (keyword1 === 'bottom') {
|
|
493
|
+
bottom = value1;
|
|
494
|
+
} else {
|
|
495
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (keyword2 === 'left') {
|
|
500
|
+
left = value2;
|
|
501
|
+
} else if (keyword2 === 'right') {
|
|
502
|
+
right = value2;
|
|
503
|
+
} else if (keyword2 === 'top') {
|
|
504
|
+
top = value2;
|
|
505
|
+
} else if (keyword2 === 'bottom') {
|
|
506
|
+
bottom = value2;
|
|
507
|
+
} else {
|
|
508
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (top != null && left != null) {
|
|
514
|
+
position = {
|
|
515
|
+
top,
|
|
516
|
+
left,
|
|
517
|
+
};
|
|
518
|
+
} else if (bottom != null && right != null) {
|
|
519
|
+
position = {
|
|
520
|
+
bottom,
|
|
521
|
+
right,
|
|
522
|
+
};
|
|
523
|
+
} else if (top != null && right != null) {
|
|
524
|
+
position = {
|
|
525
|
+
top,
|
|
526
|
+
right,
|
|
527
|
+
};
|
|
528
|
+
} else if (bottom != null && left != null) {
|
|
529
|
+
position = {
|
|
530
|
+
bottom,
|
|
531
|
+
left,
|
|
532
|
+
};
|
|
279
533
|
} else {
|
|
280
|
-
// If a
|
|
281
|
-
return
|
|
534
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
535
|
+
return null;
|
|
282
536
|
}
|
|
283
|
-
|
|
537
|
+
// 'at' comes at the end of first part of radial gradient syntax;
|
|
538
|
+
break;
|
|
284
539
|
}
|
|
285
540
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
541
|
+
// if there is no shape, size, or position string found in first token, break
|
|
542
|
+
// if might be a color stop
|
|
543
|
+
if (!hasShapeSizeOrPositionString) {
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
291
546
|
}
|
|
292
547
|
|
|
293
|
-
|
|
548
|
+
if (hasShapeSizeOrPositionString) {
|
|
549
|
+
remainingParts.shift();
|
|
550
|
+
|
|
551
|
+
if (!hasExplicitShape && hasExplicitSingleSize) {
|
|
552
|
+
shape = 'circle';
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
if (hasExplicitSingleSize && hasExplicitShape && shape === 'ellipse') {
|
|
556
|
+
// If a single size is explicitly set and the shape is an ellipse, return null and do not apply any gradient. Same as web.
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const colorStops = parseColorStopsCSSString(remainingParts);
|
|
562
|
+
if (colorStops == null) {
|
|
563
|
+
// If color stops are invalid, return null and do not apply any gradient. Same as web.
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return {
|
|
568
|
+
type: 'radial-gradient',
|
|
569
|
+
shape,
|
|
570
|
+
size,
|
|
571
|
+
position,
|
|
572
|
+
colorStops,
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function parseLinearGradientCSSString(
|
|
577
|
+
gradientContent: string,
|
|
578
|
+
): LinearGradientBackgroundImage | null {
|
|
579
|
+
const parts = gradientContent.split(',');
|
|
580
|
+
let direction: LinearGradientDirection = LINEAR_GRADIENT_DEFAULT_DIRECTION;
|
|
581
|
+
const trimmedDirection = parts[0].trim().toLowerCase();
|
|
582
|
+
|
|
583
|
+
if (LINEAR_GRADIENT_ANGLE_UNIT_REGEX.test(trimmedDirection)) {
|
|
584
|
+
const parsedAngle = getAngleInDegrees(trimmedDirection);
|
|
585
|
+
if (parsedAngle != null) {
|
|
586
|
+
direction = {
|
|
587
|
+
type: 'angle',
|
|
588
|
+
value: parsedAngle,
|
|
589
|
+
};
|
|
590
|
+
parts.shift();
|
|
591
|
+
} else {
|
|
592
|
+
// If an angle is invalid, return null and do not apply any gradient. Same as web.
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
} else if (LINEAR_GRADIENT_DIRECTION_REGEX.test(trimmedDirection)) {
|
|
596
|
+
const parsedDirection = getDirectionForKeyword(trimmedDirection);
|
|
597
|
+
if (parsedDirection != null) {
|
|
598
|
+
direction = parsedDirection;
|
|
599
|
+
parts.shift();
|
|
600
|
+
} else {
|
|
601
|
+
// If a direction is invalid, return null and do not apply any gradient. Same as web.
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
const colorStops = parseColorStopsCSSString(parts);
|
|
607
|
+
if (colorStops == null) {
|
|
608
|
+
// If a color stop is invalid, return null and do not apply any gradient. Same as web.
|
|
609
|
+
return null;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
return {
|
|
613
|
+
type: 'linear-gradient',
|
|
614
|
+
direction,
|
|
615
|
+
colorStops,
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
function parseColorStopsCSSString(parts: Array<string>): Array<{
|
|
620
|
+
color: ColorStopColor,
|
|
621
|
+
position: ColorStopPosition,
|
|
622
|
+
}> | null {
|
|
623
|
+
const colorStopsString = parts.join(',');
|
|
624
|
+
const colorStops: Array<{
|
|
625
|
+
color: ColorStopColor,
|
|
626
|
+
position: ColorStopPosition,
|
|
627
|
+
}> = [];
|
|
628
|
+
// split by comma, but not if it's inside a parentheses. e.g. red, rgba(0, 0, 0, 0.5), green => ["red", "rgba(0, 0, 0, 0.5)", "green"]
|
|
629
|
+
const stops = colorStopsString.split(/,(?![^(]*\))/);
|
|
630
|
+
let prevStop = null;
|
|
631
|
+
for (let i = 0; i < stops.length; i++) {
|
|
632
|
+
const stop = stops[i];
|
|
633
|
+
const trimmedStop = stop.trim().toLowerCase();
|
|
634
|
+
// Match function like pattern or single words
|
|
635
|
+
const colorStopParts = trimmedStop.match(/\S+\([^)]*\)|\S+/g);
|
|
636
|
+
if (colorStopParts == null) {
|
|
637
|
+
// If a color stop is invalid, return null and do not apply any gradient. Same as web.
|
|
638
|
+
return null;
|
|
639
|
+
}
|
|
640
|
+
// Case 1: [color, position, position]
|
|
641
|
+
if (colorStopParts.length === 3) {
|
|
642
|
+
const color = colorStopParts[0];
|
|
643
|
+
const position1 = getPositionFromCSSValue(colorStopParts[1]);
|
|
644
|
+
const position2 = getPositionFromCSSValue(colorStopParts[2]);
|
|
645
|
+
const processedColor = processColor(color);
|
|
646
|
+
if (processedColor == null) {
|
|
647
|
+
// If a color is invalid, return null and do not apply any gradient. Same as web.
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if (position1 == null || position2 == null) {
|
|
652
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
colorStops.push({
|
|
657
|
+
color: processedColor,
|
|
658
|
+
position: position1,
|
|
659
|
+
});
|
|
660
|
+
colorStops.push({
|
|
661
|
+
color: processedColor,
|
|
662
|
+
position: position2,
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
// Case 2: [color, position]
|
|
666
|
+
else if (colorStopParts.length === 2) {
|
|
667
|
+
const color = colorStopParts[0];
|
|
668
|
+
const position = getPositionFromCSSValue(colorStopParts[1]);
|
|
669
|
+
const processedColor = processColor(color);
|
|
670
|
+
if (processedColor == null) {
|
|
671
|
+
// If a color is invalid, return null and do not apply any gradient. Same as web.
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
if (position == null) {
|
|
675
|
+
// If a position is invalid, return null and do not apply any gradient. Same as web.
|
|
676
|
+
return null;
|
|
677
|
+
}
|
|
678
|
+
colorStops.push({
|
|
679
|
+
color: processedColor,
|
|
680
|
+
position,
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
// Case 3: [color]
|
|
684
|
+
// Case 4: [position] => transition hint syntax
|
|
685
|
+
else if (colorStopParts.length === 1) {
|
|
686
|
+
const position = getPositionFromCSSValue(colorStopParts[0]);
|
|
687
|
+
if (position != null) {
|
|
688
|
+
// handle invalid transition hint syntax. transition hint syntax must have color before and after the position. e.g. red, 20%, blue
|
|
689
|
+
if (
|
|
690
|
+
(prevStop != null &&
|
|
691
|
+
prevStop.length === 1 &&
|
|
692
|
+
getPositionFromCSSValue(prevStop[0]) != null) ||
|
|
693
|
+
i === stops.length - 1 ||
|
|
694
|
+
i === 0
|
|
695
|
+
) {
|
|
696
|
+
// If the last stop is a transition hint syntax, return null and do not apply any gradient. Same as web.
|
|
697
|
+
return null;
|
|
698
|
+
}
|
|
699
|
+
colorStops.push({
|
|
700
|
+
color: null,
|
|
701
|
+
position,
|
|
702
|
+
});
|
|
703
|
+
} else {
|
|
704
|
+
const processedColor = processColor(colorStopParts[0]);
|
|
705
|
+
if (processedColor == null) {
|
|
706
|
+
// If a color is invalid, return null and do not apply any gradient. Same as web.
|
|
707
|
+
return null;
|
|
708
|
+
}
|
|
709
|
+
colorStops.push({
|
|
710
|
+
color: processedColor,
|
|
711
|
+
position: null,
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
} else {
|
|
715
|
+
// If a color stop is invalid, return null and do not apply any gradient. Same as web.
|
|
716
|
+
return null;
|
|
717
|
+
}
|
|
718
|
+
prevStop = colorStopParts;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
return colorStops;
|
|
294
722
|
}
|
|
295
723
|
|
|
296
724
|
function getDirectionForKeyword(direction?: string): ?LinearGradientDirection {
|
|
@@ -330,7 +758,7 @@ function getAngleInDegrees(angle?: string): ?number {
|
|
|
330
758
|
if (angle == null) {
|
|
331
759
|
return null;
|
|
332
760
|
}
|
|
333
|
-
const match = angle.match(
|
|
761
|
+
const match = angle.match(LINEAR_GRADIENT_ANGLE_UNIT_REGEX);
|
|
334
762
|
if (!match) {
|
|
335
763
|
return null;
|
|
336
764
|
}
|
|
@@ -361,3 +789,31 @@ function getPositionFromCSSValue(position: string) {
|
|
|
361
789
|
return position;
|
|
362
790
|
}
|
|
363
791
|
}
|
|
792
|
+
|
|
793
|
+
function splitGradients(input: string) {
|
|
794
|
+
const result = [];
|
|
795
|
+
let current = '';
|
|
796
|
+
let depth = 0;
|
|
797
|
+
|
|
798
|
+
for (let i = 0; i < input.length; i++) {
|
|
799
|
+
const char = input[i];
|
|
800
|
+
|
|
801
|
+
if (char === '(') {
|
|
802
|
+
depth++;
|
|
803
|
+
} else if (char === ')') {
|
|
804
|
+
depth--;
|
|
805
|
+
} else if (char === ',' && depth === 0) {
|
|
806
|
+
result.push(current.trim());
|
|
807
|
+
current = '';
|
|
808
|
+
continue;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
current += char;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
if (current.trim() !== '') {
|
|
815
|
+
result.push(current.trim());
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
return result;
|
|
819
|
+
}
|