diff --git a/apps/common-app/src/apps/css/examples/animations/screens/animatedProperties/svg/Polygon.tsx b/apps/common-app/src/apps/css/examples/animations/screens/animatedProperties/svg/Polygon.tsx index 0ca8b45c467..b1fd545ee7e 100644 --- a/apps/common-app/src/apps/css/examples/animations/screens/animatedProperties/svg/Polygon.tsx +++ b/apps/common-app/src/apps/css/examples/animations/screens/animatedProperties/svg/Polygon.tsx @@ -39,6 +39,8 @@ export default function PolygonExample() { name: 'Points', sections: [ { + description: + 'On the web, Polygon renders as an SVG `` whose `points` cannot be animated via CSS, so point animations work only on iOS and Android.', examples: [ { description: @@ -92,6 +94,7 @@ export default function PolygonExample() { title: 'Hexagon breathe', }, ], + labelTypes: ['iOS', 'Android'], title: 'Same Number of Points', }, { diff --git a/apps/common-app/src/apps/css/examples/animations/screens/animatedProperties/svg/Polyline.tsx b/apps/common-app/src/apps/css/examples/animations/screens/animatedProperties/svg/Polyline.tsx index f5a91424115..4611cc58bc7 100644 --- a/apps/common-app/src/apps/css/examples/animations/screens/animatedProperties/svg/Polyline.tsx +++ b/apps/common-app/src/apps/css/examples/animations/screens/animatedProperties/svg/Polyline.tsx @@ -40,6 +40,8 @@ export default function PolylineExample() { name: 'Points', sections: [ { + description: + 'On the web, Polyline renders as an SVG `` whose `points` cannot be animated via CSS, so point animations work only on iOS and Android.', examples: [ { description: @@ -94,6 +96,7 @@ export default function PolylineExample() { title: 'S-curve', }, ], + labelTypes: ['iOS', 'Android'], title: 'Same Number of Points', }, { diff --git a/packages/react-native-reanimated/src/css/svg/init.web.ts b/packages/react-native-reanimated/src/css/svg/init.web.ts index 81c53eb1647..d6a44caeff3 100644 --- a/packages/react-native-reanimated/src/css/svg/init.web.ts +++ b/packages/react-native-reanimated/src/css/svg/init.web.ts @@ -6,19 +6,17 @@ import { SVG_ELLIPSE_WEB_PROPERTIES_CONFIG, SVG_IMAGE_WEB_PROPERTIES_CONFIG, SVG_PATH_WEB_PROPERTIES_CONFIG, - SVG_POLYGON_WEB_PROPERTIES_CONFIG, - SVG_POLYLINE_WEB_PROPERTIES_CONFIG, SVG_RECT_WEB_PROPERTIES_CONFIG, } from './web'; -// Components that animate only the common appearance props on web: the container -// (G), and shapes whose geometry is an SVG attribute (Line endpoints, -// Pattern/Text/gradient coordinates) rather than a CSS property. They fall back -// to the shared common config. +// Components with no CSS-animatable geometry on web: any geometry they expose is +// an SVG attribute, not a CSS property. They fall back to the shared common config. const COMMON_ONLY_COMPONENTS = [ 'G', 'Line', 'Pattern', + 'Polygon', + 'Polyline', 'Text', 'LinearGradient', 'RadialGradient', @@ -29,8 +27,6 @@ export function initSvgCssSupport() { registerWebSvgPropsBuilder('Ellipse', SVG_ELLIPSE_WEB_PROPERTIES_CONFIG); registerWebSvgPropsBuilder('Image', SVG_IMAGE_WEB_PROPERTIES_CONFIG); registerWebSvgPropsBuilder('Path', SVG_PATH_WEB_PROPERTIES_CONFIG); - registerWebSvgPropsBuilder('Polygon', SVG_POLYGON_WEB_PROPERTIES_CONFIG); - registerWebSvgPropsBuilder('Polyline', SVG_POLYLINE_WEB_PROPERTIES_CONFIG); registerWebSvgPropsBuilder('Rect', SVG_RECT_WEB_PROPERTIES_CONFIG); for (const componentName of COMMON_ONLY_COMPONENTS) { diff --git a/packages/react-native-reanimated/src/css/svg/web/configs/polygon.ts b/packages/react-native-reanimated/src/css/svg/web/configs/polygon.ts deleted file mode 100644 index cd7194dabbb..00000000000 --- a/packages/react-native-reanimated/src/css/svg/web/configs/polygon.ts +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -// TODO: Fix me -// @ts-ignore RNSVG doesn't export types for web, see https://github.com/software-mansion/react-native-svg/pull/2801 -import type { PolygonProps } from 'react-native-svg'; - -import { pointsToPathD } from '../processors'; -import type { SvgStyleBuilderConfig } from './common'; -import { SVG_COMMON_WEB_PROPERTIES_CONFIG } from './common'; - -export const SVG_POLYGON_WEB_PROPERTIES_CONFIG: SvgStyleBuilderConfig = - { - ...SVG_COMMON_WEB_PROPERTIES_CONFIG, - points: { name: 'd', process: pointsToPathD(true) }, - }; diff --git a/packages/react-native-reanimated/src/css/svg/web/configs/polyline.ts b/packages/react-native-reanimated/src/css/svg/web/configs/polyline.ts deleted file mode 100644 index 23fe9006459..00000000000 --- a/packages/react-native-reanimated/src/css/svg/web/configs/polyline.ts +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -// TODO: Fix me -// @ts-ignore RNSVG doesn't export types for web, see https://github.com/software-mansion/react-native-svg/pull/2801 -import type { PolylineProps } from 'react-native-svg'; - -import { pointsToPathD } from '../processors'; -import type { SvgStyleBuilderConfig } from './common'; -import { SVG_COMMON_WEB_PROPERTIES_CONFIG } from './common'; - -export const SVG_POLYLINE_WEB_PROPERTIES_CONFIG: SvgStyleBuilderConfig = - { - ...SVG_COMMON_WEB_PROPERTIES_CONFIG, - points: { name: 'd', process: pointsToPathD(false) }, - }; diff --git a/packages/react-native-reanimated/src/css/svg/web/index.ts b/packages/react-native-reanimated/src/css/svg/web/index.ts index ee4153d9cda..290fc6a25b5 100644 --- a/packages/react-native-reanimated/src/css/svg/web/index.ts +++ b/packages/react-native-reanimated/src/css/svg/web/index.ts @@ -4,8 +4,6 @@ export * from './configs/common'; export * from './configs/ellipse'; export * from './configs/image'; export * from './configs/path'; -export * from './configs/polygon'; -export * from './configs/polyline'; export * from './configs/rect'; export * from './processors'; export * from './registry'; diff --git a/packages/react-native-reanimated/src/css/svg/web/processors/__tests__/polyPoints.test.ts b/packages/react-native-reanimated/src/css/svg/web/processors/__tests__/polyPoints.test.ts deleted file mode 100644 index 3d94ffb9533..00000000000 --- a/packages/react-native-reanimated/src/css/svg/web/processors/__tests__/polyPoints.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; -import { pointsToPathD } from '../polyPoints'; - -describe(pointsToPathD, () => { - test('closed builds a Polygon path (closed with Z)', () => { - expect(pointsToPathD(true)('0,0 10,10 20,0')).toBe( - 'path("M0,0 10,10 20,0Z")' - ); - }); - - test('open builds a Polyline path (no Z)', () => { - expect(pointsToPathD(false)('0,0 10,10')).toBe('path("M0,0 10,10")'); - }); -}); diff --git a/packages/react-native-reanimated/src/css/svg/web/processors/index.ts b/packages/react-native-reanimated/src/css/svg/web/processors/index.ts index d4e492e3133..2ba02e39bd1 100644 --- a/packages/react-native-reanimated/src/css/svg/web/processors/index.ts +++ b/packages/react-native-reanimated/src/css/svg/web/processors/index.ts @@ -1,5 +1,4 @@ 'use strict'; export * from './pathStructure'; -export * from './polyPoints'; export * from './strokeDashArray'; export * from './vectorEffect'; diff --git a/packages/react-native-reanimated/src/css/svg/web/processors/polyPoints.ts b/packages/react-native-reanimated/src/css/svg/web/processors/polyPoints.ts deleted file mode 100644 index 3061760890c..00000000000 --- a/packages/react-native-reanimated/src/css/svg/web/processors/polyPoints.ts +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -// RNSVG renders Polygon/Polyline as a on web, so their geometry animates -// via `d`: the configs alias `points` to `d` and build the CSS path() with this. -export const pointsToPathD = - (closed: boolean) => - (points: unknown): string => - `path("M${String(points)}${closed ? 'Z' : ''}")`; diff --git a/packages/react-native-reanimated/src/css/web/__tests__/animationParser.test.ts b/packages/react-native-reanimated/src/css/web/__tests__/animationParser.test.ts index 6b99f4a128b..244688d55a0 100644 --- a/packages/react-native-reanimated/src/css/web/__tests__/animationParser.test.ts +++ b/packages/react-native-reanimated/src/css/web/__tests__/animationParser.test.ts @@ -3,14 +3,12 @@ import { registerWebSvgPropsBuilder, SVG_COMMON_WEB_PROPERTIES_CONFIG, SVG_PATH_WEB_PROPERTIES_CONFIG, - SVG_POLYGON_WEB_PROPERTIES_CONFIG, } from '../../svg/web'; import { processKeyframeDefinitions } from '../animationParser'; beforeAll(() => { registerWebSvgPropsBuilder('TestStroke', SVG_COMMON_WEB_PROPERTIES_CONFIG); registerWebSvgPropsBuilder('Path', SVG_PATH_WEB_PROPERTIES_CONFIG); - registerWebSvgPropsBuilder('Polygon', SVG_POLYGON_WEB_PROPERTIES_CONFIG); }); describe(processKeyframeDefinitions, () => { @@ -23,18 +21,6 @@ describe(processKeyframeDefinitions, () => { expect(result).toContain('to { stroke-dasharray: 10px 20px 30px }'); }); - test('emits Polygon points as an animatable `d` path', () => { - const result = processKeyframeDefinitions( - { - from: { points: '0,0 10,10 20,0' }, - to: { points: '0,0 10,20 20,0' }, - }, - 'Polygon' - ); - expect(result).toContain('from { d: path("M0,0 10,10 20,0Z") }'); - expect(result).toContain('to { d: path("M0,0 10,20 20,0Z") }'); - }); - test('pads a trailing Z so an open->closed path morph interpolates', () => { const result = processKeyframeDefinitions( { from: { d: 'M0,0 L10,10' }, to: { d: 'M0,0 L20,5 Z' } }, diff --git a/packages/react-native-reanimated/src/css/web/managers/__tests__/CSSAnimationsManager.web.test.ts b/packages/react-native-reanimated/src/css/web/managers/__tests__/CSSAnimationsManager.web.test.ts index 940d321edd2..1c32d7f03df 100644 --- a/packages/react-native-reanimated/src/css/web/managers/__tests__/CSSAnimationsManager.web.test.ts +++ b/packages/react-native-reanimated/src/css/web/managers/__tests__/CSSAnimationsManager.web.test.ts @@ -2,7 +2,7 @@ import type { ReanimatedHTMLElement } from '../../../../ReanimatedModule/js-reanimated'; import { registerWebSvgPropsBuilder, - SVG_POLYGON_WEB_PROPERTIES_CONFIG, + SVG_PATH_WEB_PROPERTIES_CONFIG, } from '../../../svg/web'; import type { ExistingCSSAnimationProperties } from '../../../types'; import { processKeyframeDefinitions } from '../../animationParser'; @@ -82,23 +82,23 @@ describe('CSSAnimationsManager (web)', () => { }); test('builds SVG keyframes with the SVG props builder for SVG components', () => { - // Polygon aliases `points` -> `d` (path()), a transform only the SVG - // builder does - so this verifies the manager threads its componentName - // into the keyframe pipeline for SVG components (not just the generic one). - registerWebSvgPropsBuilder('Polygon', SVG_POLYGON_WEB_PROPERTIES_CONFIG); - const svgManager = new CSSAnimationsManager(element, 'Polygon'); + // Path wraps `d` in path() - a transform only the SVG builder does - so + // this verifies the manager threads its componentName into the keyframe + // pipeline for SVG components (not just the generic one). + registerWebSvgPropsBuilder('Path', SVG_PATH_WEB_PROPERTIES_CONFIG); + const svgManager = new CSSAnimationsManager(element, 'Path'); svgManager.update({ animationName: { - from: { points: '0,0 10,10 20,0' }, - to: { points: '0,0 10,20 20,0' }, + from: { d: 'M0,0 L10,10 L20,0' }, + to: { d: 'M0,0 L10,20 L20,0' }, }, animationDuration: 200, } as unknown as ExistingCSSAnimationProperties); expect(insertCSSAnimation).toHaveBeenCalledWith( element.style.animationName, - 'from { d: path("M0,0 10,10 20,0Z") } to { d: path("M0,0 10,20 20,0Z") }' + 'from { d: path("M0,0 L10,10 L20,0") } to { d: path("M0,0 L10,20 L20,0") }' ); }); diff --git a/packages/react-native-reanimated/src/css/web/managers/__tests__/CSSPseudoSelectorsManager.test.ts b/packages/react-native-reanimated/src/css/web/managers/__tests__/CSSPseudoSelectorsManager.test.ts index 91daa3ac075..037f2109480 100644 --- a/packages/react-native-reanimated/src/css/web/managers/__tests__/CSSPseudoSelectorsManager.test.ts +++ b/packages/react-native-reanimated/src/css/web/managers/__tests__/CSSPseudoSelectorsManager.test.ts @@ -3,7 +3,7 @@ import type { ReanimatedHTMLElement } from '../../../../ReanimatedModule/js-rean import { ANIMATION_NAME_PREFIX } from '../../../constants'; import { registerWebSvgPropsBuilder, - SVG_POLYGON_WEB_PROPERTIES_CONFIG, + SVG_PATH_WEB_PROPERTIES_CONFIG, } from '../../../svg/web'; import { insertPseudoSelectorCSS, @@ -173,26 +173,23 @@ describe(CSSPseudoSelectorsManager, () => { }); test('uses the SVG props builder for SVG components', () => { - // Polygon aliases `points` -> `d` and wraps it in path() - a transform only - // the SVG builder does, so it proves the SVG builder (not the generic one) - // is used for pseudo styles on SVG components. - registerWebSvgPropsBuilder( - 'TestPolygon', - SVG_POLYGON_WEB_PROPERTIES_CONFIG - ); + // Path wraps `d` in path() - a transform only the SVG builder does, so it + // proves the SVG builder (not the generic one) is used for pseudo styles on + // SVG components. + registerWebSvgPropsBuilder('TestPath', SVG_PATH_WEB_PROPERTIES_CONFIG); const element = createElement(); - const manager = new CSSPseudoSelectorsManager(element, 'TestPolygon'); + const manager = new CSSPseudoSelectorsManager(element, 'TestPath'); manager.update({ ':hover': { - selectorStyle: { points: '0,0 10,10 20,0' }, - defaultStyle: { points: '0,0 0,0 0,0' }, + selectorStyle: { d: 'M0,0 L10,10' }, + defaultStyle: { d: 'M0,0 L0,0' }, }, }); const rules = (insertMock.mock.calls[0][1] as string[]).join('\n'); expect(rules).toContain('d: path('); - expect(rules).not.toContain('points:'); + expect(rules).toContain('M0,0 L10,10'); }); test('skips inserting when called with null', () => {