From 20839b8a00e90a5dc6066ee5ee06484fd4d19d36 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Tue, 18 Oct 2022 16:34:27 +0200 Subject: [PATCH 1/9] fix: start aligning transform --- Example/ios/Podfile.lock | 39 +++++++++++++++++--- src/ReactNativeSVG.web.ts | 55 +++++------------------------ src/elements/Pattern.tsx | 3 +- src/lib/extract/extractGradient.ts | 6 ++-- src/lib/extract/extractTransform.ts | 9 +++-- src/lib/extract/types.ts | 39 ++++++++++---------- 6 files changed, 73 insertions(+), 78 deletions(-) diff --git a/Example/ios/Podfile.lock b/Example/ios/Podfile.lock index 83c077110..9d7c06d1c 100644 --- a/Example/ios/Podfile.lock +++ b/Example/ios/Podfile.lock @@ -368,7 +368,34 @@ PODS: - React-jsi (= 0.70.0) - React-logger (= 0.70.0) - React-perflogger (= 0.70.0) - - RNSVG (13.2.0): + - RNReanimated (2.10.0): + - DoubleConversion + - FBLazyVector + - FBReactNativeSpec + - glog + - RCT-Folly + - RCTRequired + - RCTTypeSafety + - React-callinvoker + - React-Core + - React-Core/DevSupport + - React-Core/RCTWebSocket + - React-CoreModules + - React-cxxreact + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-RCTActionSheet + - React-RCTAnimation + - React-RCTBlob + - React-RCTImage + - React-RCTLinking + - React-RCTNetwork + - React-RCTSettings + - React-RCTText + - ReactCommon/turbomodule/core + - Yoga + - RNSVG (13.4.0): - React-Core - SocketRocket (0.6.0) - Yoga (1.14.0) @@ -434,6 +461,7 @@ DEPENDENCIES: - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - RNReanimated (from `../node_modules/react-native-reanimated`) - RNSVG (from `../node_modules/react-native-svg`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -522,6 +550,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" ReactCommon: :path: "../node_modules/react-native/ReactCommon" + RNReanimated: + :path: "../node_modules/react-native-reanimated" RNSVG: :path: "../node_modules/react-native-svg" Yoga: @@ -530,7 +560,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: a7c83b31436843459a1961bfd74b96033dc77234 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 - DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662 + DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: 6c76fe46345039d5cf0549e9ddaf5aa169630a4a FBReactNativeSpec: 1a270246542f5c52248cb26a96db119cfe3cb760 Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 @@ -543,7 +573,7 @@ SPEC CHECKSUMS: Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541 FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 - glog: 476ee3e89abb49e07f822b48323c51c57124b572 + glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b hermes-engine: 8e84f1284180801c1a1b241f443ba64f931ff561 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c @@ -574,7 +604,8 @@ SPEC CHECKSUMS: React-RCTVibration: 5499b77c0fd57f346a5f0b36bb79fdb020d17d3e React-runtimeexecutor: 80c195ffcafb190f531fdc849dc2d19cb4bb2b34 ReactCommon: de55f940495d7bf87b5d7bf55b5b15cdd50d7d7b - RNSVG: 07037623c36f12e41312730622d5f6b3656227ca + RNReanimated: 60e291d42c77752a0f6d6f358387bdf225a87c6e + RNSVG: 07dbd870b0dcdecc99b3a202fa37c8ca163caec2 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: 82c9e8f652789f67d98bed5aef9d6653f71b04a9 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/src/ReactNativeSVG.web.ts b/src/ReactNativeSVG.web.ts index 20af248e0..dad016a3b 100644 --- a/src/ReactNativeSVG.web.ts +++ b/src/ReactNativeSVG.web.ts @@ -11,7 +11,7 @@ import { ColumnMajorTransformMatrix, NumberArray, NumberProp, - TransformObject, + TransformProps, } from './lib/extract/types'; import SvgTouchableMixin from './lib/SvgTouchableMixin'; import { resolve } from './lib/resolve'; @@ -49,7 +49,7 @@ interface BaseProps { pressRetentionOffset?: EdgeInsetsProp; rejectResponderTermination?: boolean; - transform: ColumnMajorTransformMatrix | string | TransformObject; + transform: TransformProps['transform']; translate: NumberArray; translateX: NumberProp; translateY: NumberProp; @@ -124,7 +124,8 @@ const prepare = ( onResponderRelease?: (e: GestureResponderEvent) => void; onResponderTerminate?: (e: GestureResponderEvent) => void; onResponderTerminationRequest?: (e: GestureResponderEvent) => boolean; - transform?: ColumnMajorTransformMatrix | string | TransformObject; + transform?: ColumnMajorTransformMatrix | string; + 'transform-origin'?: string; style?: {}; ref?: {}; } = { @@ -143,48 +144,11 @@ const prepare = ( ...rest, }; - const transformArray = []; + const transformArray: string[] = []; if (Array.isArray(transform) && transform.length === 6) { transformArray.push(`matrix(${transform.join(' ')})`); - } else if (typeof transform === 'object') { - for (const key in transform) { - const value = transform[key]; - // non standard SVG transforms - if (key === 'translateX' || key === 'x') { - transformArray.push(`translate(${value} 0)`); - } else if (key === 'translateY' || key === 'y') { - transformArray.push(`translate(0 ${value})`); - } else if (key === 'originX') { - transformArray.push(`translate(${-value} 0)`); - } else if (key === 'originY') { - transformArray.push(`translate(0 ${-value})`); - } else if (key === 'origin') { - if (Array.isArray(value)) { - transformArray.push(`translate(${value.join(' ')})`); - } else { - transformArray.push(`translate(${value})`); - } - } else if (key === 'scaleX') { - transformArray.push(`scaleX(${value} 1)`); - } else if (key === 'scaleY') { - transformArray.push(`scaleX(1 ${value})`); - } else if (key === 'skew') { - if (Array.isArray(value) && value.length === 2) { - transformArray.push(`skewX(${value[0]})`); - transformArray.push(`skewY(${value[1]})`); - } else { - throw new Error('Skew prop expect array of numbers'); - } - } else { - if (Array.isArray(value)) { - transformArray.push(`${key}(${value.join(' ')})`); - } else { - transformArray.push(`${key}(${transform[key]})`); - } - } - } - } else { + } else if (typeof transform === 'string') { transformArray.push(transform); } @@ -211,10 +175,9 @@ const prepare = ( transformArray.push(`skewY(${skewY})`); } if (origin != null) { - transformArray.push(`translate(${origin})`); - } - if (originX != null || originY != null) { - transformArray.push(`translate(${-originX || 0}, ${-originY || 0})`); + clean['transform-origin'] = origin.toString().replace(',', ' '); + } else if (originX != null || originY != null) { + clean['transform-origin'] = `${originX || 0} ${originY || 0}`; } if (transformArray.length) { diff --git a/src/elements/Pattern.tsx b/src/elements/Pattern.tsx index 0746cd5f0..a85c25c40 100644 --- a/src/elements/Pattern.tsx +++ b/src/elements/Pattern.tsx @@ -12,7 +12,7 @@ import Shape from './Shape'; import { RNSVGPattern } from './NativeComponents'; import { stringifyPropsForFabric } from '../lib/extract/extractProps'; -export interface PatternProps { +export interface PatternProps extends TransformProps { children?: ReactNode; id?: string; x?: NumberProp; @@ -24,7 +24,6 @@ export interface PatternProps { patternContentUnits?: Units; viewBox?: string; preserveAspectRatio?: string; - transform?: ColumnMajorTransformMatrix | string | TransformProps; } export default class Pattern extends Shape { diff --git a/src/lib/extract/extractGradient.ts b/src/lib/extract/extractGradient.ts index 5014b10cc..ed85d73f7 100644 --- a/src/lib/extract/extractGradient.ts +++ b/src/lib/extract/extractGradient.ts @@ -3,7 +3,7 @@ import { processColor } from 'react-native'; import extractOpacity from './extractOpacity'; import extractTransform from './extractTransform'; -import { TransformProps } from './types'; +import { ColumnMajorTransformMatrix, TransformProps } from './types'; import units from '../units'; const percentReg = /^([+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)(%?)$/; @@ -41,8 +41,8 @@ export default function extractGradient( props: { id?: string; children?: ReactElement[]; - transform?: number[] | string | TransformProps; - gradientTransform?: number[] | string | TransformProps; + transform?: ColumnMajorTransformMatrix | string | TransformProps; + gradientTransform?: ColumnMajorTransformMatrix | string | TransformProps; gradientUnits?: 'objectBoundingBox' | 'userSpaceOnUse'; } & TransformProps, parent: {}, diff --git a/src/lib/extract/extractTransform.ts b/src/lib/extract/extractTransform.ts index b85ff1a1c..608994878 100644 --- a/src/lib/extract/extractTransform.ts +++ b/src/lib/extract/extractTransform.ts @@ -1,6 +1,11 @@ import { append, appendTransform, identity, reset, toArray } from '../Matrix2D'; import { parse } from './transform'; -import { NumberProp, TransformedProps, TransformProps } from './types'; +import { + ColumnMajorTransformMatrix, + NumberProp, + TransformedProps, + TransformProps, +} from './types'; function appendTransformProps(props: TransformedProps) { const { x, y, originX, originY, scaleX, scaleY, rotation, skewX, skewY } = @@ -165,7 +170,7 @@ export function transformToMatrix( } export default function extractTransform( - props: number[] | string | TransformProps, + props: ColumnMajorTransformMatrix | string | TransformProps, ) { if (Array.isArray(props)) { return props; diff --git a/src/lib/extract/types.ts b/src/lib/extract/types.ts index 4e242eff6..de48e6df7 100644 --- a/src/lib/extract/types.ts +++ b/src/lib/extract/types.ts @@ -5,6 +5,7 @@ import { LayoutChangeEvent, } from 'react-native'; import React from 'react'; +// import type {TransformsStyle} from 'react-native'; export type NumberProp = string | number; export type NumberArray = NumberProp[] | NumberProp; @@ -162,24 +163,6 @@ export interface FontProps extends FontObject { font?: FontObject; } -export interface TransformObject { - translate?: NumberArray; - translateX?: NumberProp; - translateY?: NumberProp; - origin?: NumberArray; - originX?: NumberProp; - originY?: NumberProp; - scale?: NumberArray; - scaleX?: NumberProp; - scaleY?: NumberProp; - skew?: NumberArray; - skewX?: NumberProp; - skewY?: NumberProp; - rotation?: NumberProp; - x?: NumberArray; - y?: NumberArray; -} - /* ColumnMajorTransformMatrix @@ -204,9 +187,23 @@ export type ColumnMajorTransformMatrix = [ number, ]; -export interface TransformProps extends TransformObject { - transform?: ColumnMajorTransformMatrix | string | TransformObject; - // | TransformsStyle['transform']; // not used since it causes type problems +export interface TransformProps { + translate?: NumberArray; + translateX?: NumberProp; + translateY?: NumberProp; + origin?: NumberArray; + originX?: NumberProp; + originY?: NumberProp; + scale?: NumberArray; + scaleX?: NumberProp; + scaleY?: NumberProp; + skew?: NumberArray; + skewX?: NumberProp; + skewY?: NumberProp; + rotation?: NumberProp; + x?: NumberArray; + y?: NumberArray; + transform?: ColumnMajorTransformMatrix | string; // | TransformsStyle['transform']; // not used since it causes type problems } export interface TransformedProps { From a9022e85dc6170466b7dcf6e43f00739446d3c81 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Thu, 20 Oct 2022 15:13:03 +0200 Subject: [PATCH 2/9] fix: bring back option of react native transform array to transform prop --- src/elements/LinearGradient.tsx | 8 +--- src/elements/Mask.tsx | 4 +- src/elements/Pattern.tsx | 9 +--- src/elements/RadialGradient.tsx | 8 +--- src/elements/Shape.tsx | 7 ++- src/elements/TSpan.tsx | 3 +- src/elements/Text.tsx | 3 +- src/elements/TextPath.tsx | 3 +- src/lib/extract/extractGradient.ts | 6 +-- src/lib/extract/extractProps.ts | 7 +-- src/lib/extract/extractTransform.ts | 68 ++++++++++++++++++++++------- src/lib/extract/types.ts | 7 ++- 12 files changed, 81 insertions(+), 52 deletions(-) diff --git a/src/elements/LinearGradient.tsx b/src/elements/LinearGradient.tsx index 88793138f..b100d804a 100644 --- a/src/elements/LinearGradient.tsx +++ b/src/elements/LinearGradient.tsx @@ -1,10 +1,6 @@ import React, { ReactElement } from 'react'; import extractGradient from '../lib/extract/extractGradient'; -import { - ColumnMajorTransformMatrix, - NumberProp, - Units, -} from '../lib/extract/types'; +import { NumberProp, TransformProps, Units } from '../lib/extract/types'; import Shape from './Shape'; import { RNSVGLinearGradient } from './NativeComponents'; import { stringifyPropsForFabric } from '../lib/extract/extractProps'; @@ -16,7 +12,7 @@ export interface LinearGradientProps { y1?: NumberProp; y2?: NumberProp; gradientUnits?: Units; - gradientTransform?: ColumnMajorTransformMatrix | string; + gradientTransform?: TransformProps['transform']; id?: string; } diff --git a/src/elements/Mask.tsx b/src/elements/Mask.tsx index e8108ceab..1b4f45ed1 100644 --- a/src/elements/Mask.tsx +++ b/src/elements/Mask.tsx @@ -5,9 +5,9 @@ import { withoutXY, } from '../lib/extract/extractProps'; import { - ColumnMajorTransformMatrix, CommonPathProps, NumberProp, + TransformProps, } from '../lib/extract/types'; import units from '../lib/units'; import Shape from './Shape'; @@ -22,7 +22,7 @@ export interface MaskProps extends CommonPathProps { y?: NumberProp; width?: NumberProp; height?: NumberProp; - maskTransform?: ColumnMajorTransformMatrix | string; + maskTransform?: TransformProps['transform']; maskUnits?: TMaskUnits; maskContentUnits?: TMaskUnits; } diff --git a/src/elements/Pattern.tsx b/src/elements/Pattern.tsx index a85c25c40..35ff3b57e 100644 --- a/src/elements/Pattern.tsx +++ b/src/elements/Pattern.tsx @@ -1,12 +1,7 @@ import React, { ReactNode } from 'react'; import extractTransform from '../lib/extract/extractTransform'; import extractViewBox from '../lib/extract/extractViewBox'; -import { - ColumnMajorTransformMatrix, - NumberProp, - TransformProps, - Units, -} from '../lib/extract/types'; +import { NumberProp, TransformProps, Units } from '../lib/extract/types'; import units from '../lib/units'; import Shape from './Shape'; import { RNSVGPattern } from './NativeComponents'; @@ -19,7 +14,7 @@ export interface PatternProps extends TransformProps { y?: NumberProp; width?: NumberProp; height?: NumberProp; - patternTransform?: ColumnMajorTransformMatrix | string; + patternTransform?: TransformProps['transform']; patternUnits?: Units; patternContentUnits?: Units; viewBox?: string; diff --git a/src/elements/RadialGradient.tsx b/src/elements/RadialGradient.tsx index 6925bc1ed..e444d903a 100644 --- a/src/elements/RadialGradient.tsx +++ b/src/elements/RadialGradient.tsx @@ -1,10 +1,6 @@ import React, { ReactElement } from 'react'; import extractGradient from '../lib/extract/extractGradient'; -import { - ColumnMajorTransformMatrix, - NumberProp, - Units, -} from '../lib/extract/types'; +import { NumberProp, TransformProps, Units } from '../lib/extract/types'; import Shape from './Shape'; import { RNSVGRadialGradient } from './NativeComponents'; import { stringifyPropsForFabric } from '../lib/extract/extractProps'; @@ -19,7 +15,7 @@ export interface RadialGradientProps { cy?: NumberProp; r?: NumberProp; gradientUnits?: Units; - gradientTransform?: ColumnMajorTransformMatrix | string; + gradientTransform?: TransformProps['transform']; id?: string; } diff --git a/src/elements/Shape.tsx b/src/elements/Shape.tsx index 1273360c8..7b7ff2d01 100644 --- a/src/elements/Shape.tsx +++ b/src/elements/Shape.tsx @@ -1,7 +1,10 @@ import { Component } from 'react'; import SvgTouchableMixin from '../lib/SvgTouchableMixin'; import { NativeModules, findNodeHandle, NativeMethods } from 'react-native'; -import { TransformProps } from '../lib/extract/types'; +import { + ColumnMajorTransformMatrix, + TransformProps, +} from '../lib/extract/types'; const { RNSVGRenderableManager } = NativeModules; export interface SVGBoundingBoxOptions { @@ -241,7 +244,7 @@ export default class Shape

extends Component

{ }; setNativeProps = ( props: Object & { - matrix?: [number, number, number, number, number, number]; + matrix?: ColumnMajorTransformMatrix; } & TransformProps, ) => { this.root && this.root.setNativeProps(props); diff --git a/src/elements/TSpan.tsx b/src/elements/TSpan.tsx index 82fb149d0..f415a486c 100644 --- a/src/elements/TSpan.tsx +++ b/src/elements/TSpan.tsx @@ -5,6 +5,7 @@ import extractText, { setTSpan, TextChild } from '../lib/extract/extractText'; import { pickNotNil } from '../lib/util'; import Shape from './Shape'; import { + ColumnMajorTransformMatrix, CommonPathProps, FontProps, NumberArray, @@ -28,7 +29,7 @@ export default class TSpan extends Shape { setNativeProps = ( props: Object & { - matrix?: number[]; + matrix?: ColumnMajorTransformMatrix; style?: [] | {}; } & TransformProps, ) => { diff --git a/src/elements/Text.tsx b/src/elements/Text.tsx index fbe987283..9f8778b47 100644 --- a/src/elements/Text.tsx +++ b/src/elements/Text.tsx @@ -3,6 +3,7 @@ import extractText from '../lib/extract/extractText'; import extractProps, { propsAndStyles } from '../lib/extract/extractProps'; import extractTransform from '../lib/extract/extractTransform'; import { + ColumnMajorTransformMatrix, NumberArray, NumberProp, TextSpecificProps, @@ -29,7 +30,7 @@ export default class Text extends Shape { setNativeProps = ( props: Object & { - matrix?: number[]; + matrix?: ColumnMajorTransformMatrix; style?: [] | {}; } & TransformProps, ) => { diff --git a/src/elements/TextPath.tsx b/src/elements/TextPath.tsx index d5e9ecdf1..0b68e85b1 100644 --- a/src/elements/TextPath.tsx +++ b/src/elements/TextPath.tsx @@ -2,6 +2,7 @@ import React, { Component } from 'react'; import extractTransform from '../lib/extract/extractTransform'; import { withoutXY } from '../lib/extract/extractProps'; import { + ColumnMajorTransformMatrix, NumberProp, TextPathMethod, TextPathMidLine, @@ -31,7 +32,7 @@ export default class TextPath extends Shape { setNativeProps = ( props: Object & { - matrix?: number[]; + matrix?: ColumnMajorTransformMatrix; style?: [] | {}; } & TransformProps, ) => { diff --git a/src/lib/extract/extractGradient.ts b/src/lib/extract/extractGradient.ts index ed85d73f7..49843cee4 100644 --- a/src/lib/extract/extractGradient.ts +++ b/src/lib/extract/extractGradient.ts @@ -3,7 +3,7 @@ import { processColor } from 'react-native'; import extractOpacity from './extractOpacity'; import extractTransform from './extractTransform'; -import { ColumnMajorTransformMatrix, TransformProps } from './types'; +import { TransformProps } from './types'; import units from '../units'; const percentReg = /^([+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)(%?)$/; @@ -41,8 +41,8 @@ export default function extractGradient( props: { id?: string; children?: ReactElement[]; - transform?: ColumnMajorTransformMatrix | string | TransformProps; - gradientTransform?: ColumnMajorTransformMatrix | string | TransformProps; + transform?: TransformProps['transform']; + gradientTransform?: TransformProps['transform']; gradientUnits?: 'objectBoundingBox' | 'userSpaceOnUse'; } & TransformProps, parent: {}, diff --git a/src/lib/extract/extractProps.ts b/src/lib/extract/extractProps.ts index 41c703b82..084abfd52 100644 --- a/src/lib/extract/extractProps.ts +++ b/src/lib/extract/extractProps.ts @@ -1,6 +1,6 @@ import extractFill from './extractFill'; import extractStroke from './extractStroke'; -import { props2transform, transformToMatrix } from './extractTransform'; +import extractTransform from './extractTransform'; import extractResponder from './extractResponder'; import extractOpacity from './extractOpacity'; import { idPattern } from '../util'; @@ -49,7 +49,6 @@ export default function extractProps( display?: string; opacity?: NumberProp; onLayout?: () => void; - transform?: number[] | string | TransformProps; } & TransformProps & ResponderProps & StrokeProps & @@ -69,7 +68,6 @@ export default function extractProps( markerStart = marker, markerMid = marker, markerEnd = marker, - transform, } = props; const extracted: extractedProps = {}; @@ -82,8 +80,7 @@ export default function extractProps( extracted.propList = inherited; } - const transformProps = props2transform(props); - const matrix = transformToMatrix(transformProps, transform); + const matrix = extractTransform(props); if (matrix !== null) { extracted.matrix = matrix; } diff --git a/src/lib/extract/extractTransform.ts b/src/lib/extract/extractTransform.ts index 608994878..23b6c038c 100644 --- a/src/lib/extract/extractTransform.ts +++ b/src/lib/extract/extractTransform.ts @@ -1,3 +1,4 @@ +import { TransformsStyle } from 'react-native'; import { append, appendTransform, identity, reset, toArray } from '../Matrix2D'; import { parse } from './transform'; import { @@ -63,9 +64,33 @@ function universal2axis( return [x || defaultValue || 0, y || defaultValue || 0]; } +function transformsArrayToProps( + transformObjectsArray: TransformsStyle['transform'], +) { + const props: TransformProps = {}; + transformObjectsArray?.forEach((transformObject) => { + const keys = Object.keys(transformObject); + if (keys.length !== 1) { + console.error( + 'You must specify exactly one property per transform object.', + ); + } + const key = keys[0] as keyof TransformProps; + const value = transformObject[key as keyof typeof transformObject]; + props[key] = value; + }); + return props; +} + export function props2transform( - props: TransformProps, + props: TransformProps | undefined, ): TransformedProps | null { + if (!props) { + return null; + } + const extractedProps = Array.isArray(props) + ? transformsArrayToProps(props) + : props; const { rotation, translate, @@ -82,7 +107,7 @@ export function props2transform( skewY, x, y, - } = props; + } = extractedProps; if ( rotation == null && translate == null && @@ -132,8 +157,8 @@ export function props2transform( export function transformToMatrix( props: TransformedProps | null, - transform: number[] | string | TransformProps | void | null | undefined, -): [number, number, number, number, number, number] | null { + transform: TransformProps['transform'], +): ColumnMajorTransformMatrix | null { if (!props && !transform) { return null; } @@ -143,16 +168,21 @@ export function transformToMatrix( if (transform) { if (Array.isArray(transform)) { if (typeof transform[0] === 'number') { + const columnMatrix = transform as ColumnMajorTransformMatrix; append( - transform[0], - transform[1], - transform[2], - transform[3], - transform[4], - transform[5], + columnMatrix[0], + columnMatrix[1], + columnMatrix[2], + columnMatrix[3], + columnMatrix[4], + columnMatrix[5], + ); + } else { + const transformProps = props2transform( + transformsArrayToProps(transform as TransformsStyle['transform']), ); + transformProps && appendTransformProps(transformProps); } - // noop for react-native transform arrays, let animated handle them } else if (typeof transform === 'string') { try { const t = parse(transform); @@ -170,10 +200,10 @@ export function transformToMatrix( } export default function extractTransform( - props: ColumnMajorTransformMatrix | string | TransformProps, -) { - if (Array.isArray(props)) { - return props; + props: TransformProps | TransformProps['transform'], +): ColumnMajorTransformMatrix | null { + if (Array.isArray(props) && typeof props[0] === 'number') { + return props as ColumnMajorTransformMatrix; } if (typeof props === 'string') { try { @@ -184,5 +214,11 @@ export default function extractTransform( return identity; } } - return transformToMatrix(props2transform(props), props.transform); + // this type is not correct since props can be of type TransformsStyle['transform'] too + // but it satisfies TS and should not produce any type errors + const transformProps = props as TransformProps; + return transformToMatrix( + props2transform(transformProps), + transformProps?.transform, + ); } diff --git a/src/lib/extract/types.ts b/src/lib/extract/types.ts index de48e6df7..f459f4143 100644 --- a/src/lib/extract/types.ts +++ b/src/lib/extract/types.ts @@ -5,7 +5,7 @@ import { LayoutChangeEvent, } from 'react-native'; import React from 'react'; -// import type {TransformsStyle} from 'react-native'; +import type { TransformsStyle } from 'react-native'; export type NumberProp = string | number; export type NumberArray = NumberProp[] | NumberProp; @@ -203,7 +203,10 @@ export interface TransformProps { rotation?: NumberProp; x?: NumberArray; y?: NumberArray; - transform?: ColumnMajorTransformMatrix | string; // | TransformsStyle['transform']; // not used since it causes type problems + transform?: + | ColumnMajorTransformMatrix + | string + | TransformsStyle['transform']; } export interface TransformedProps { From 36bb521c99547fb511bb363f97c3ad7af8014320 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Thu, 20 Oct 2022 15:58:23 +0200 Subject: [PATCH 3/9] fix: remove maskTransform since it does nothing --- .../main/java/com/horcrux/svg/MaskView.java | 31 ---------------- .../java/com/horcrux/svg/RenderableView.java | 35 +++++++++---------- .../horcrux/svg/RenderableViewManager.java | 5 --- .../RNSVGMaskManagerDelegate.java | 3 -- .../RNSVGMaskManagerInterface.java | 1 - apple/Elements/RNSVGMask.h | 1 - apple/Elements/RNSVGMask.mm | 16 --------- apple/ViewManagers/RNSVGMaskManager.mm | 1 - src/elements/Mask.tsx | 3 -- src/fabric/MaskNativeComponent.ts | 1 - src/index.js.flow | 1 - 11 files changed, 17 insertions(+), 81 deletions(-) diff --git a/android/src/main/java/com/horcrux/svg/MaskView.java b/android/src/main/java/com/horcrux/svg/MaskView.java index 8b974fce9..c91503aa5 100644 --- a/android/src/main/java/com/horcrux/svg/MaskView.java +++ b/android/src/main/java/com/horcrux/svg/MaskView.java @@ -9,13 +9,8 @@ package com.horcrux.svg; import android.annotation.SuppressLint; -import android.graphics.Matrix; -import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.common.ReactConstants; -import javax.annotation.Nullable; @SuppressLint("ViewConstructor") class MaskView extends GroupView { @@ -32,14 +27,6 @@ class MaskView extends GroupView { @SuppressWarnings({"FieldCanBeLocal", "unused"}) private Brush.BrushUnits mMaskContentUnits; - private static final float[] sRawMatrix = - new float[] { - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - }; - private Matrix mMatrix = null; - public MaskView(ReactContext reactContext) { super(reactContext); } @@ -128,24 +115,6 @@ public void setMaskContentUnits(int maskContentUnits) { invalidate(); } - public void setMaskTransform(@Nullable ReadableArray matrixArray) { - if (matrixArray != null) { - int matrixSize = PropHelper.toMatrixData(matrixArray, sRawMatrix, mScale); - if (matrixSize == 6) { - if (mMatrix == null) { - mMatrix = new Matrix(); - } - mMatrix.setValues(sRawMatrix); - } else if (matrixSize != -1) { - FLog.w(ReactConstants.TAG, "RNSVG: Transform matrices must be of size 6"); - } - } else { - mMatrix = null; - } - - invalidate(); - } - @Override void saveDefinition() { if (mName != null) { diff --git a/android/src/main/java/com/horcrux/svg/RenderableView.java b/android/src/main/java/com/horcrux/svg/RenderableView.java index 2aa196cdf..3cb4df9c0 100644 --- a/android/src/main/java/com/horcrux/svg/RenderableView.java +++ b/android/src/main/java/com/horcrux/svg/RenderableView.java @@ -27,9 +27,8 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableType; -import com.facebook.react.uimanager.PointerEvents; import com.facebook.react.touch.ReactHitSlopView; - +import com.facebook.react.uimanager.PointerEvents; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.regex.Matcher; @@ -37,7 +36,7 @@ import javax.annotation.Nullable; @SuppressWarnings({"WeakerAccess", "RedundantSuppression"}) -abstract public class RenderableView extends VirtualView implements ReactHitSlopView { +public abstract class RenderableView extends VirtualView implements ReactHitSlopView { RenderableView(ReactContext reactContext) { super(reactContext); @@ -96,23 +95,23 @@ abstract public class RenderableView extends VirtualView implements ReactHitSlop private static final Pattern regex = Pattern.compile("[0-9.-]+"); - @Nullable - public Rect getHitSlopRect() { - /* - * In order to make the isTouchPointInView fail we need to return a very improbable Rect for the View - * This way an SVG with box_none carrying its last descendent with box_none will have the expected behavior of just having events on the actual painted area - */ - if (mPointerEvents == PointerEvents.BOX_NONE) { - return new Rect(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); - } - return null; + @Nullable + public Rect getHitSlopRect() { + /* + * In order to make the isTouchPointInView fail we need to return a very improbable Rect for the View + * This way an SVG with box_none carrying its last descendent with box_none will have the expected behavior of just having events on the actual painted area + */ + if (mPointerEvents == PointerEvents.BOX_NONE) { + return new Rect(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); } + return null; + } - @Override - public void setId(int id) { - super.setId(id); - RenderableViewManager.setRenderableView(id, this); - } + @Override + public void setId(int id) { + super.setId(id); + RenderableViewManager.setRenderableView(id, this); + } public void setVectorEffect(int vectorEffect) { this.vectorEffect = vectorEffect; diff --git a/android/src/main/java/com/horcrux/svg/RenderableViewManager.java b/android/src/main/java/com/horcrux/svg/RenderableViewManager.java index 72180eebb..5614f4138 100644 --- a/android/src/main/java/com/horcrux/svg/RenderableViewManager.java +++ b/android/src/main/java/com/horcrux/svg/RenderableViewManager.java @@ -1714,11 +1714,6 @@ public void setMaskUnits(MaskView node, int maskUnits) { public void setMaskContentUnits(MaskView node, int maskContentUnits) { node.setMaskContentUnits(maskContentUnits); } - - @ReactProp(name = "maskTransform") - public void setMaskTransform(MaskView node, @Nullable ReadableArray matrixArray) { - node.setMaskTransform(matrixArray); - } } static class ForeignObjectManager extends GroupViewManagerAbstract diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGMaskManagerDelegate.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGMaskManagerDelegate.java index 849f8ed52..8730b0a1f 100644 --- a/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGMaskManagerDelegate.java +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGMaskManagerDelegate.java @@ -167,9 +167,6 @@ public void setProperty(T view, String propName, @Nullable Object value) { case "maskContentUnits": mViewManager.setMaskContentUnits(view, value == null ? 0 : ((Double) value).intValue()); break; - case "maskTransform": - mViewManager.setMaskTransform(view, (ReadableArray) value); - break; default: super.setProperty(view, propName, value); } diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGMaskManagerInterface.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGMaskManagerInterface.java index a5627bd44..c799c1645 100644 --- a/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGMaskManagerInterface.java +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGMaskManagerInterface.java @@ -56,5 +56,4 @@ public interface RNSVGMaskManagerInterface { void setWidth(T view, @Nullable Double value); void setMaskUnits(T view, int value); void setMaskContentUnits(T view, int value); - void setMaskTransform(T view, @Nullable ReadableArray value); } diff --git a/apple/Elements/RNSVGMask.h b/apple/Elements/RNSVGMask.h index a710c76b9..bea4e4d75 100644 --- a/apple/Elements/RNSVGMask.h +++ b/apple/Elements/RNSVGMask.h @@ -10,6 +10,5 @@ @property (nonatomic, strong) RNSVGLength *maskheight; @property (nonatomic, assign) RNSVGUnits maskUnits; @property (nonatomic, assign) RNSVGUnits maskContentUnits; -@property (nonatomic, assign) CGAffineTransform maskTransform; @end diff --git a/apple/Elements/RNSVGMask.mm b/apple/Elements/RNSVGMask.mm index 7c58b13bf..e8381854b 100644 --- a/apple/Elements/RNSVGMask.mm +++ b/apple/Elements/RNSVGMask.mm @@ -53,15 +53,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & } self.maskUnits = newProps.maskUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; self.maskContentUnits = newProps.maskUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; - if (newProps.maskTransform.size() == 6) { - self.maskTransform = CGAffineTransformMake( - newProps.maskTransform.at(0), - newProps.maskTransform.at(1), - newProps.maskTransform.at(2), - newProps.maskTransform.at(3), - newProps.maskTransform.at(4), - newProps.maskTransform.at(5)); - } setCommonGroupProps(newProps, self); _props = std::static_pointer_cast(props); @@ -76,7 +67,6 @@ - (void)prepareForRecycle _maskwidth = nil; _maskUnits = kRNSVGUnitsObjectBoundingBox; _maskContentUnits = kRNSVGUnitsObjectBoundingBox; - _maskTransform = CGAffineTransformIdentity; } #endif // RN_FABRIC_ENABLED @@ -151,12 +141,6 @@ - (void)setMaskContentUnits:(RNSVGUnits)maskContentUnits [self invalidate]; } -- (void)setMaskTransform:(CGAffineTransform)maskTransform -{ - _maskTransform = maskTransform; - [self invalidate]; -} - @end #ifdef RN_FABRIC_ENABLED diff --git a/apple/ViewManagers/RNSVGMaskManager.mm b/apple/ViewManagers/RNSVGMaskManager.mm index bcc532570..8dbe8e7c4 100644 --- a/apple/ViewManagers/RNSVGMaskManager.mm +++ b/apple/ViewManagers/RNSVGMaskManager.mm @@ -30,6 +30,5 @@ - (RNSVGMask *)node } RCT_EXPORT_VIEW_PROPERTY(maskUnits, RNSVGUnits) RCT_EXPORT_VIEW_PROPERTY(maskContentUnits, RNSVGUnits) -RCT_EXPORT_VIEW_PROPERTY(maskTransform, CGAffineTransform) @end diff --git a/src/elements/Mask.tsx b/src/elements/Mask.tsx index 1b4f45ed1..c039c2931 100644 --- a/src/elements/Mask.tsx +++ b/src/elements/Mask.tsx @@ -22,7 +22,6 @@ export interface MaskProps extends CommonPathProps { y?: NumberProp; width?: NumberProp; height?: NumberProp; - maskTransform?: TransformProps['transform']; maskUnits?: TMaskUnits; maskContentUnits?: TMaskUnits; } @@ -40,7 +39,6 @@ export default class Mask extends Shape { render() { const { props } = this; const { - maskTransform, transform, x, y, @@ -57,7 +55,6 @@ export default class Mask extends Shape { height, }); const maskProps = { - maskTransform: extractTransform(maskTransform || transform || props), maskUnits: maskUnits !== undefined ? units[maskUnits] : 0, maskContentUnits: maskContentUnits !== undefined ? units[maskContentUnits] : 1, diff --git a/src/fabric/MaskNativeComponent.ts b/src/fabric/MaskNativeComponent.ts index 9a27bc08c..a32edcab4 100644 --- a/src/fabric/MaskNativeComponent.ts +++ b/src/fabric/MaskNativeComponent.ts @@ -78,7 +78,6 @@ interface NativeProps width?: string; maskUnits?: Int32; maskContentUnits?: Int32; - maskTransform?: ReadonlyArray; } export default codegenNativeComponent('RNSVGMask'); diff --git a/src/index.js.flow b/src/index.js.flow index 0550ba5b0..a43420087 100644 --- a/src/index.js.flow +++ b/src/index.js.flow @@ -442,7 +442,6 @@ export type MaskProps = { y?: NumberProp, width?: NumberProp, height?: NumberProp, - maskTransform?: ColumnMajorTransformMatrix | string, maskUnits?: Units, maskContentUnits?: Units, ... From fb97a0c6596fa11239ade44a12815f397492eefa Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Thu, 20 Oct 2022 16:23:39 +0200 Subject: [PATCH 4/9] fix: remove unused prop --- src/elements/Mask.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/elements/Mask.tsx b/src/elements/Mask.tsx index c039c2931..0288a8f75 100644 --- a/src/elements/Mask.tsx +++ b/src/elements/Mask.tsx @@ -1,5 +1,4 @@ import React, { ReactNode } from 'react'; -import extractTransform from '../lib/extract/extractTransform'; import { stringifyPropsForFabric, withoutXY, @@ -7,7 +6,6 @@ import { import { CommonPathProps, NumberProp, - TransformProps, } from '../lib/extract/types'; import units from '../lib/units'; import Shape from './Shape'; @@ -39,7 +37,6 @@ export default class Mask extends Shape { render() { const { props } = this; const { - transform, x, y, width, From f3f94deb55f498e231d7df14d353d5af09a59148 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Thu, 20 Oct 2022 16:36:56 +0200 Subject: [PATCH 5/9] chore: format --- src/elements/Mask.tsx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/elements/Mask.tsx b/src/elements/Mask.tsx index 0288a8f75..d524c6af9 100644 --- a/src/elements/Mask.tsx +++ b/src/elements/Mask.tsx @@ -3,10 +3,7 @@ import { stringifyPropsForFabric, withoutXY, } from '../lib/extract/extractProps'; -import { - CommonPathProps, - NumberProp, -} from '../lib/extract/types'; +import { CommonPathProps, NumberProp } from '../lib/extract/types'; import units from '../lib/units'; import Shape from './Shape'; import { RNSVGMask } from './NativeComponents'; @@ -36,15 +33,8 @@ export default class Mask extends Shape { render() { const { props } = this; - const { - x, - y, - width, - height, - maskUnits, - maskContentUnits, - children, - } = props; + const { x, y, width, height, maskUnits, maskContentUnits, children } = + props; const strigifiedMaskProps = stringifyPropsForFabric({ x, y, From 13f10ba9f379531a113ebce8afd190630f89c82f Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Thu, 20 Oct 2022 17:44:16 +0200 Subject: [PATCH 6/9] feat: add rn transform style parsing on web --- src/ReactNativeSVG.web.ts | 150 ++++++++++++++++------------ src/lib/extract/extractTransform.ts | 2 +- 2 files changed, 85 insertions(+), 67 deletions(-) diff --git a/src/ReactNativeSVG.web.ts b/src/ReactNativeSVG.web.ts index dad016a3b..011a99ee0 100644 --- a/src/ReactNativeSVG.web.ts +++ b/src/ReactNativeSVG.web.ts @@ -1,20 +1,15 @@ -// @ts-ignore import * as React from 'react'; import { GestureResponderEvent, // @ts-ignore unstable_createElement as ucE, - // @ts-ignore createElement as cE, + TransformsStyle, } from 'react-native'; -import { - ColumnMajorTransformMatrix, - NumberArray, - NumberProp, - TransformProps, -} from './lib/extract/types'; +import { NumberArray, NumberProp, TransformProps } from './lib/extract/types'; import SvgTouchableMixin from './lib/SvgTouchableMixin'; import { resolve } from './lib/resolve'; +import { transformsArrayToProps } from './lib/extract/extractTransform'; const createElement = cE || ucE; @@ -49,19 +44,19 @@ interface BaseProps { pressRetentionOffset?: EdgeInsetsProp; rejectResponderTermination?: boolean; - transform: TransformProps['transform']; - translate: NumberArray; - translateX: NumberProp; - translateY: NumberProp; - scale: NumberArray; - scaleX: NumberProp; - scaleY: NumberProp; - rotation: NumberArray; - skewX: NumberProp; - skewY: NumberProp; - origin: NumberArray; - originX: NumberProp; - originY: NumberProp; + transform?: TransformProps['transform']; + translate?: NumberArray; + translateX?: NumberProp; + translateY?: NumberProp; + scale?: NumberArray; + scaleX?: NumberProp; + scaleY?: NumberProp; + rotation?: NumberProp; + skewX?: NumberProp; + skewY?: NumberProp; + origin?: NumberArray; + originX?: NumberProp; + originY?: NumberProp; fontStyle?: string; fontWeight?: NumberProp; @@ -71,6 +66,10 @@ interface BaseProps { | React.RefCallback | React.MutableRefObject; style: Iterable<{}>; + + // different tranform props + gradientTransform: TransformProps['transform']; + patternTransform: TransformProps['transform']; } const hasTouchableProperty = (props: BaseProps) => @@ -80,6 +79,62 @@ const camelCaseToDashed = (camelCase: string) => { return camelCase.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()); }; +function stringifyTransformProps(transformProps: TransformProps) { + const transformArray = []; + if (transformProps.translate != null) { + transformArray.push(`translate(${transformProps.translate})`); + } + if (transformProps.translateX != null || transformProps.translateY != null) { + transformArray.push( + `translate(${transformProps.translateX || 0}, ${ + transformProps.translateY || 0 + })`, + ); + } + if (transformProps.scale != null) { + transformArray.push(`scale(${transformProps.scale})`); + } + if (transformProps.scaleX != null || transformProps.scaleY != null) { + transformArray.push( + `scale(${transformProps.scaleX || 1}, ${transformProps.scaleY || 1})`, + ); + } + // rotation maps to rotate, not to collide with the text rotate attribute (which acts per glyph rather than block) + if (transformProps.rotation != null) { + transformArray.push(`rotate(${transformProps.rotation})`); + } + if (transformProps.skewX != null) { + transformArray.push(`skewX(${transformProps.skewX})`); + } + if (transformProps.skewY != null) { + transformArray.push(`skewY(${transformProps.skewY})`); + } + return transformArray; +} + +function parseTransformProp( + transform: TransformProps['transform'], + props?: BaseProps, +) { + const transformArray: string[] = []; + + if (Array.isArray(transform)) { + if (typeof transform[0] === 'number') { + transformArray.push(`matrix(${transform.join(' ')})`); + } else { + const stringifiedProps = transformsArrayToProps( + transform as TransformsStyle['transform'], + ); + transformArray.push(...stringifyTransformProps(stringifiedProps)); + } + } else if (typeof transform === 'string') { + transformArray.push(transform); + } + + props && transformArray.push(...stringifyTransformProps(props)); + return transformArray.length ? transformArray.join(' ') : undefined; +} + /** * `react-native-svg` supports additional props that aren't defined in the spec. * This function replaces them in a spec conforming manner. @@ -95,15 +150,6 @@ const prepare = ( ) => { const { transform, - translate, - translateX, - translateY, - scale, - scaleX, - scaleY, - rotation, - skewX, - skewY, origin, originX, originY, @@ -113,7 +159,8 @@ const prepare = ( fontStyle, style, forwardedRef, - // @ts-ignore + gradientTransform, + patternTransform, ...rest } = props; @@ -124,7 +171,9 @@ const prepare = ( onResponderRelease?: (e: GestureResponderEvent) => void; onResponderTerminate?: (e: GestureResponderEvent) => void; onResponderTerminationRequest?: (e: GestureResponderEvent) => boolean; - transform?: ColumnMajorTransformMatrix | string; + transform?: string; + gradientTransform?: string; + patternTransform?: string; 'transform-origin'?: string; style?: {}; ref?: {}; @@ -144,45 +193,15 @@ const prepare = ( ...rest, }; - const transformArray: string[] = []; - - if (Array.isArray(transform) && transform.length === 6) { - transformArray.push(`matrix(${transform.join(' ')})`); - } else if (typeof transform === 'string') { - transformArray.push(transform); - } - - if (translate != null) { - transformArray.push(`translate(${translate})`); - } - if (translateX != null || translateY != null) { - transformArray.push(`translate(${translateX || 0}, ${translateY || 0})`); - } - if (scale != null) { - transformArray.push(`scale(${scale})`); - } - if (scaleX != null || scaleY != null) { - transformArray.push(`scale(${scaleX || 1}, ${scaleY || 1})`); - } - // rotation maps to rotate, not to collide with the text rotate attribute (which acts per glyph rather than block) - if (rotation != null) { - transformArray.push(`rotate(${rotation})`); - } - if (skewX != null) { - transformArray.push(`skewX(${skewX})`); - } - if (skewY != null) { - transformArray.push(`skewY(${skewY})`); - } if (origin != null) { clean['transform-origin'] = origin.toString().replace(',', ' '); } else if (originX != null || originY != null) { clean['transform-origin'] = `${originX || 0} ${originY || 0}`; } - if (transformArray.length) { - clean.transform = transformArray.join(' '); - } + clean.transform = parseTransformProp(transform, props); + clean.gradientTransform = parseTransformProp(gradientTransform); + clean.patternTransform = parseTransformProp(patternTransform); clean.ref = (el: SVGElement | null) => { self.elementRef.current = el; @@ -212,7 +231,6 @@ const prepare = ( if (fontStyle != null) { styles.fontStyle = fontStyle; } - clean.style = resolve(style, styles); return clean; diff --git a/src/lib/extract/extractTransform.ts b/src/lib/extract/extractTransform.ts index 23b6c038c..155188a4e 100644 --- a/src/lib/extract/extractTransform.ts +++ b/src/lib/extract/extractTransform.ts @@ -64,7 +64,7 @@ function universal2axis( return [x || defaultValue || 0, y || defaultValue || 0]; } -function transformsArrayToProps( +export function transformsArrayToProps( transformObjectsArray: TransformsStyle['transform'], ) { const props: TransformProps = {}; From 868961f330a45e85b1d1cd8d8824427524cd913d Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Thu, 20 Oct 2022 17:54:59 +0200 Subject: [PATCH 7/9] fix: bring same ordering of props on web --- src/ReactNativeSVG.web.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ReactNativeSVG.web.ts b/src/ReactNativeSVG.web.ts index 011a99ee0..b28630267 100644 --- a/src/ReactNativeSVG.web.ts +++ b/src/ReactNativeSVG.web.ts @@ -118,6 +118,8 @@ function parseTransformProp( ) { const transformArray: string[] = []; + props && transformArray.push(...stringifyTransformProps(props)); + if (Array.isArray(transform)) { if (typeof transform[0] === 'number') { transformArray.push(`matrix(${transform.join(' ')})`); @@ -131,7 +133,6 @@ function parseTransformProp( transformArray.push(transform); } - props && transformArray.push(...stringifyTransformProps(props)); return transformArray.length ? transformArray.join(' ') : undefined; } From 353e87bb5acfac142ae2ed4b8e77214030172373 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Tue, 25 Oct 2022 12:56:38 +0200 Subject: [PATCH 8/9] fix: typo in pattern --- apple/Elements/RNSVGPattern.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apple/Elements/RNSVGPattern.mm b/apple/Elements/RNSVGPattern.mm index 3bd7a0535..663630e9d 100644 --- a/apple/Elements/RNSVGPattern.mm +++ b/apple/Elements/RNSVGPattern.mm @@ -52,7 +52,8 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const & self.patternwidth = [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.width)]; } self.patternUnits = newProps.patternUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; - self.patternContentUnits = newProps.patternUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; + self.patternContentUnits = + newProps.patternContentUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse; if (newProps.patternTransform.size() == 6) { self.patternTransform = CGAffineTransformMake( newProps.patternTransform.at(0), From d722aa880cb6c0b08d58cc43132d336733dc1f57 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Tue, 25 Oct 2022 12:57:48 +0200 Subject: [PATCH 9/9] feat: add transforms to examples --- Example/src/App.tsx | 1 + Example/src/examples.tsx | 2 + Example/src/examples/Transforms.tsx | 134 ++++++++++++++++++++++ FabricExample/ios/Podfile.lock | 4 +- FabricExample/src/App.tsx | 1 + FabricExample/src/examples.tsx | 2 + FabricExample/src/examples/Transforms.tsx | 134 ++++++++++++++++++++++ 7 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 Example/src/examples/Transforms.tsx create mode 100644 FabricExample/src/examples/Transforms.tsx diff --git a/Example/src/App.tsx b/Example/src/App.tsx index 0212df79d..fa2019600 100644 --- a/Example/src/App.tsx +++ b/Example/src/App.tsx @@ -113,6 +113,7 @@ const names: (keyof typeof examples)[] = [ 'PanResponder', 'Reusable', 'Reanimated', + 'Transforms', ]; const initialState = { diff --git a/Example/src/examples.tsx b/Example/src/examples.tsx index 64a80e950..8d39d3540 100644 --- a/Example/src/examples.tsx +++ b/Example/src/examples.tsx @@ -16,6 +16,7 @@ import * as Reusable from './examples/Reusable'; import * as TouchEvents from './examples/TouchEvents'; import * as PanResponder from './examples/PanResponder'; import * as Reanimated from './examples/Reanimated'; +import * as Transforms from './examples/Transforms'; export { Svg, @@ -36,4 +37,5 @@ export { Reusable, PanResponder, Reanimated, + Transforms, }; diff --git a/Example/src/examples/Transforms.tsx b/Example/src/examples/Transforms.tsx new file mode 100644 index 000000000..7316a5c4a --- /dev/null +++ b/Example/src/examples/Transforms.tsx @@ -0,0 +1,134 @@ +import React, {Component} from 'react'; +import {Platform} from 'react-native'; + +import { + Svg, + Circle, + Rect, + Pattern, + RadialGradient, + Stop, + SvgXml, +} from 'react-native-svg'; + +const patternXml = ` + + + + + + + + +`; + +class PatternTransformExample extends Component { + static title = 'Pattern transform'; + render() { + return ( + <> + + + + + + + + + + + {Platform.OS !== 'web' && ( + + )} + + ); + } +} + +class GradientTransformExample extends Component { + static title = 'Gradient transform'; + render() { + return ( + + + + + + + + + + + + + + + + ); + } +} + +const icon = ( + + + + + + +); + +const samples = [PatternTransformExample, GradientTransformExample]; + +export {icon, samples}; diff --git a/FabricExample/ios/Podfile.lock b/FabricExample/ios/Podfile.lock index 42c743fd9..689aca659 100644 --- a/FabricExample/ios/Podfile.lock +++ b/FabricExample/ios/Podfile.lock @@ -697,7 +697,7 @@ PODS: - React-jsi (= 0.70.0) - React-logger (= 0.70.0) - React-perflogger (= 0.70.0) - - RNSVG (13.2.0): + - RNSVG (13.4.0): - RCT-Folly - RCTRequired - RCTTypeSafety @@ -927,7 +927,7 @@ SPEC CHECKSUMS: React-rncore: 8858fe6b719170c20c197a8fd2dd53507bdae04b React-runtimeexecutor: 80c195ffcafb190f531fdc849dc2d19cb4bb2b34 ReactCommon: de55f940495d7bf87b5d7bf55b5b15cdd50d7d7b - RNSVG: fa7f6f437c90eea1fbc3d142a40365d561824ab3 + RNSVG: 8ef4c60d9378eab6996a3f006dfb5784e6dab302 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: 82c9e8f652789f67d98bed5aef9d6653f71b04a9 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/FabricExample/src/App.tsx b/FabricExample/src/App.tsx index 7ed84db50..c55fe8c45 100644 --- a/FabricExample/src/App.tsx +++ b/FabricExample/src/App.tsx @@ -112,6 +112,7 @@ const names = [ 'TouchEvents', 'PanResponder', 'Reusable', + 'Transforms', ]; const initialState = { diff --git a/FabricExample/src/examples.tsx b/FabricExample/src/examples.tsx index a1d56f38b..908ed89b1 100644 --- a/FabricExample/src/examples.tsx +++ b/FabricExample/src/examples.tsx @@ -15,6 +15,7 @@ import * as Image from './examples/Image'; import * as Reusable from './examples/Reusable'; import * as TouchEvents from './examples/TouchEvents'; import * as PanResponder from './examples/PanResponder'; +import * as Transforms from './examples/Transforms'; export { Svg, @@ -34,4 +35,5 @@ export { TouchEvents, Reusable, PanResponder, + Transforms, }; diff --git a/FabricExample/src/examples/Transforms.tsx b/FabricExample/src/examples/Transforms.tsx new file mode 100644 index 000000000..7316a5c4a --- /dev/null +++ b/FabricExample/src/examples/Transforms.tsx @@ -0,0 +1,134 @@ +import React, {Component} from 'react'; +import {Platform} from 'react-native'; + +import { + Svg, + Circle, + Rect, + Pattern, + RadialGradient, + Stop, + SvgXml, +} from 'react-native-svg'; + +const patternXml = ` + + + + + + + + +`; + +class PatternTransformExample extends Component { + static title = 'Pattern transform'; + render() { + return ( + <> + + + + + + + + + + + {Platform.OS !== 'web' && ( + + )} + + ); + } +} + +class GradientTransformExample extends Component { + static title = 'Gradient transform'; + render() { + return ( + + + + + + + + + + + + + + + + ); + } +} + +const icon = ( + + + + + + +); + +const samples = [PatternTransformExample, GradientTransformExample]; + +export {icon, samples};