From 05c33d32451675f53221a24888d05bcb962e0294 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Tue, 15 Nov 2022 12:38:40 +0100 Subject: [PATCH] chore: align examples (#1914) PR aligning example apps and fixing one bug. On web, if you don't pass a color to the elements, they are rendered with `black` fill. We recreate this behavior in examples, but maybe it should be the default behavior if `fill` is `undefined`. It would probably need to be changed on the native side somehow. Another fix is to parse `fill` prop in `setNativeProps` since Fabric support has been added and `fill` prop structure has been changed, it cannot be handled on the native side on `Android` due to complying to interfaces. Another fix is passing `transform` prop in `Svg` to `G` when it is not `react-native` style `transform` prop so it is always applied. It creates a problem mentioned in the comment in the code and should be addressed in later PRs. --- Example/src/examples/Path.tsx | 2 +- Example/src/examples/Reusable.tsx | 4 +-- Example/src/examples/Text.tsx | 4 +-- Example/src/examples/TouchEvents.tsx | 1 + Example/src/examples/Transforms.tsx | 24 ++++++++++++++ FabricExample/src/App.tsx | 1 - FabricExample/src/examples/PanResponder.tsx | 14 +++++---- FabricExample/src/examples/Path.tsx | 2 +- FabricExample/src/examples/Text.tsx | 4 +-- FabricExample/src/examples/TouchEvents.tsx | 10 +++--- TestsExample/App.js | 1 + TestsExample/src/Test1374.tsx | 35 +++++++++++++++++++++ src/elements/Shape.tsx | 8 ++++- src/elements/Svg.tsx | 15 +++++++-- src/lib/extract/extractFill.ts | 2 +- 15 files changed, 103 insertions(+), 24 deletions(-) create mode 100644 TestsExample/src/Test1374.tsx diff --git a/Example/src/examples/Path.tsx b/Example/src/examples/Path.tsx index 927c9637..e8ef10f2 100644 --- a/Example/src/examples/Path.tsx +++ b/Example/src/examples/Path.tsx @@ -6,7 +6,7 @@ class PathExample extends Component { render() { return ( - + - - + + diff --git a/Example/src/examples/Text.tsx b/Example/src/examples/Text.tsx index ed90199e..0223f948 100644 --- a/Example/src/examples/Text.tsx +++ b/Example/src/examples/Text.tsx @@ -144,7 +144,7 @@ class TSpanExample extends Component { render() { return ( - + tspan line 1 tspan line 2 @@ -163,7 +163,7 @@ class TSpanExample extends Component { 89a - + delta on text diff --git a/Example/src/examples/TouchEvents.tsx b/Example/src/examples/TouchEvents.tsx index a2014992..f8b70793 100644 --- a/Example/src/examples/TouchEvents.tsx +++ b/Example/src/examples/TouchEvents.tsx @@ -79,6 +79,7 @@ class GroupExample extends Component { Alert.alert('Pressed on G')} scale="1.4"> + + + + + + + + + + + {Platform.OS !== 'web' && ( )} diff --git a/FabricExample/src/App.tsx b/FabricExample/src/App.tsx index c55fe8c4..2f618af3 100644 --- a/FabricExample/src/App.tsx +++ b/FabricExample/src/App.tsx @@ -14,7 +14,6 @@ import { TouchableHighlight, TouchableOpacity, } from 'react-native'; -import {Modal} from 'react-native'; import {Svg, Circle, Line} from 'react-native-svg'; import * as examples from './examples'; diff --git a/FabricExample/src/examples/PanResponder.tsx b/FabricExample/src/examples/PanResponder.tsx index 9452673e..bd2c387a 100644 --- a/FabricExample/src/examples/PanResponder.tsx +++ b/FabricExample/src/examples/PanResponder.tsx @@ -1,20 +1,20 @@ import React, {PureComponent} from 'react'; import { - PanResponder, - View, Animated, + PanResponder, TouchableWithoutFeedback, + View, } from 'react-native'; -import {Svg, G, Text, Path, Polyline, Line} from 'react-native-svg'; +import {G, Line, Path, Polyline, Svg, Text} from 'react-native-svg'; const AnimatedSvg = Animated.createAnimatedComponent(Svg); const zeroDelta = {x: 0, y: 0}; class PanExample extends PureComponent { - static title = 'Bind PanResponder on the SVG Shape - It does not work on Fabric since it uses `setNativeProps`'; + static title = 'Bind PanResponder on the SVG Shape'; panXY: any; - constructor(props, context) { + constructor(props: {}, context: {}) { super(props, context); const xy = new Animated.ValueXY(); const {x: dx, y: dy} = xy; @@ -29,7 +29,9 @@ class PanExample extends PureComponent { xy.setOffset(offset); xy.setValue(zeroDelta); }, - onPanResponderMove: Animated.event([null, {dx, dy}]), + onPanResponderMove: Animated.event([null, {dx, dy}], { + useNativeDriver: false, + }), onPanResponderRelease: () => { xy.flattenOffset(); }, diff --git a/FabricExample/src/examples/Path.tsx b/FabricExample/src/examples/Path.tsx index 927c9637..9904432b 100644 --- a/FabricExample/src/examples/Path.tsx +++ b/FabricExample/src/examples/Path.tsx @@ -6,7 +6,7 @@ class PathExample extends Component { render() { return ( - + - + tspan line 1 tspan line 2 @@ -163,7 +163,7 @@ class TSpanExample extends Component { 89a - + delta on text diff --git a/FabricExample/src/examples/TouchEvents.tsx b/FabricExample/src/examples/TouchEvents.tsx index 507270f0..f8b70793 100644 --- a/FabricExample/src/examples/TouchEvents.tsx +++ b/FabricExample/src/examples/TouchEvents.tsx @@ -10,6 +10,7 @@ import { Defs, ClipPath, } from 'react-native-svg'; +import {Alert} from 'react-native'; class PressExample extends Component { static title = @@ -22,7 +23,7 @@ class PressExample extends Component { cy="50%" r="38%" fill="red" - onPress={() => alert('Press on Circle')} + onPress={() => Alert.alert('Press on Circle')} /> alert('Long press on Rect')} + onLongPress={() => Alert.alert('Long press on Rect')} /> @@ -75,14 +76,15 @@ class GroupExample extends Component { render() { return ( - alert('Pressed on G')} scale="1.4"> + Alert.alert('Pressed on G')} scale="1.4"> alert('Pressed on Text')}> + onPress={() => Alert.alert('Pressed on Text')}> H diff --git a/TestsExample/App.js b/TestsExample/App.js index e578a7e6..d7dd721f 100644 --- a/TestsExample/App.js +++ b/TestsExample/App.js @@ -2,6 +2,7 @@ import React from 'react'; import ColorTest from './src/ColorTest'; +import Test1374 from './src/Test1374'; import Test1718 from './src/Test1718'; import Test1813 from './src/Test1813'; import Test1845 from './src/Test1845'; diff --git a/TestsExample/src/Test1374.tsx b/TestsExample/src/Test1374.tsx new file mode 100644 index 00000000..07747597 --- /dev/null +++ b/TestsExample/src/Test1374.tsx @@ -0,0 +1,35 @@ +import * as React from 'react'; +import { View } from 'react-native'; +import Svg, {Circle, SvgXml} from 'react-native-svg'; + +export default function App() { + const svgXmlWithTransform = ` + +`; + const svgXmlWithEmptyStyle = ` + +`; + +const svgg = ` + + + + +`; + + return ( + + + + + + + + + ); +} diff --git a/src/elements/Shape.tsx b/src/elements/Shape.tsx index ec19dbe2..ef293b2c 100644 --- a/src/elements/Shape.tsx +++ b/src/elements/Shape.tsx @@ -1,6 +1,7 @@ import { Component } from 'react'; import SvgTouchableMixin from '../lib/SvgTouchableMixin'; -import { findNodeHandle, NativeMethods } from 'react-native'; +import extractBrush from '../lib/extract/extractBrush'; +import { ColorValue, findNodeHandle, NativeMethods } from 'react-native'; import { ColumnMajorTransformMatrix, TransformProps, @@ -249,8 +250,13 @@ export default class Shape

extends Component

{ setNativeProps = ( props: Object & { matrix?: ColumnMajorTransformMatrix; + fill?: ColorValue; } & TransformProps, ) => { + if (props.fill) { + // @ts-ignore TODO: native `fill` prop differs from the one passed in props + props.fill = extractBrush(props.fill); + } this.root?.setNativeProps(props); }; /* diff --git a/src/elements/Svg.tsx b/src/elements/Svg.tsx index d94bc4ec..478abda7 100644 --- a/src/elements/Svg.tsx +++ b/src/elements/Svg.tsx @@ -115,6 +115,7 @@ export default class Svg extends Shape { width, height, focusable, + transform, // Inherited G properties font, @@ -182,10 +183,18 @@ export default class Svg extends Shape { props.onLayout = onLayout; } - // transform should not be passed down since it is already used in svgView - // and would be doubled in G causing double transformations const gStyle = Object.assign({}, style) as ViewStyle; - gStyle.transform = undefined; + // if transform prop is of RN style's kind, we want `SvgView` to handle it + // since it can be done here. Otherwise, if transform is of `svg` kind, e.g. string, + // we want G element to parse it since `Svg` does not include parsing of those custom transforms. + // It is problematic due to fact that we either move the `Svg` or just its `G` child, and in the + // second case, when the `G` leaves the area of `Svg`, it will just disappear. + if (Array.isArray(transform) && typeof transform[0] === 'object') { + gStyle.transform = undefined; + } else { + props.transform = undefined; + gStyle.transform = transform; + } const RNSVGSvg = Platform.OS === 'android' ? RNSVGSvgAndroid : RNSVGSvgIOS; diff --git a/src/lib/extract/extractFill.ts b/src/lib/extract/extractFill.ts index 78842ee8..3070ab82 100644 --- a/src/lib/extract/extractFill.ts +++ b/src/lib/extract/extractFill.ts @@ -8,7 +8,7 @@ const fillRules: { evenodd: number; nonzero: number } = { nonzero: 1, }; -const defaultFill = processColor('black'); +const defaultFill = { type: 0, payload: processColor('black') }; export default function extractFill( o: extractedProps,