24 Commits

Author SHA1 Message Date
Jakub Grzywacz c617dec1c5 fix: animated transform last frame (#2553)
# Summary

When using the Animated API for animations, it sends the last frame as
JavaScript-parsed (matrix) updates in addition to native (transform)
updates. ~~As a result, we need to ignore one of them.~~ I believe
there's no need to differentiate between native and JavaScript
updates—we can simply save both to the same value (mMatrix). By doing
so, we can avoid duplicating the transforms.

| Before | After |
|--------|--------|
| <video
src="https://github.com/user-attachments/assets/868cc778-4b88-4473-85b5-9665b4b241aa">
| <video
src="https://github.com/user-attachments/assets/c6d17b7b-7c9a-47c3-8286-2d9b5720f261">
|




## Test Plan

```jsx
import React, {useEffect} from 'react';
import {Animated, useAnimatedValue, View} from 'react-native';
import {Rect, Svg} from 'react-native-svg';

const AnimatedRect = Animated.createAnimatedComponent(Rect);
function AnimatedJumpIssue() {
  const animatedValue = useAnimatedValue(100);
  return (
    <>
      <View style={{borderColor: 'black', borderWidth: 1}}>
        <Svg height="100" width="400">
          <AnimatedRect
            x="0"
            y="0"
            width="100"
            height="100"
            fill="black"
            transform={[{translateX: animatedValue}]}
          />
        </Svg>
      </View>
      <Button
        title="Press me"
        onPress={() => {
          Animated.timing(animatedValue, {
            toValue: 200,
            duration: 3000,
            useNativeDriver: true,
          }).start();
        }}
      />
    </>
  );
}
```

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| Android |          |
| iOS |          |
| macOS |          |
2024-11-28 12:44:55 +01:00
Jakub Grzywacz d1d936a834 fix: resolve transforms on new architecture (#2542)
# Summary

Add `resolveTransforms` on `updateProps` to get correct matrix. It will
improve animating transformations, as Animated/Reanimated skips JS
`processTransform` and passes transformations directly.

## Test Plan

Animate `transform` prop in react-native style.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
2024-11-20 10:42:39 +01:00
Jakub Grzywacz 2a58016ec1 feat: get currentColor from caller instead of parent (#2521)
# Summary

Fixes #2520
When an element uses `currentColor`, it should look for color in its
caller, not in its parent.
Example: 
```svg
<Svg width="100" height="100" viewBox="0 0 100 100" color="red">
  <Defs color="blue">
    <G color="green">
      <Rect id="a" x="0" y="0" width="50" height="50" fill="currentColor"/>
    </G>
  </Defs>
  <G color="pink">
    <Use href="#a"/>												<!-- #1 -->
  </G>
  <Use href="#a" transform="translate(25 25)"/>						<!-- #2 -->
  <G color="green">
    <Use href="#a" transform="translate(50 50)"/>					<!-- #3 -->
  </G>
</Svg>
```

* `#1` should be **pink**
* `#2` should be **red**
* `#3` should be **green**


![image](https://github.com/user-attachments/assets/b7ba2ec6-ea05-4bcb-9f40-0cf024e5c749)

## Test Plan

Example app -> test -> Test2520

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |
2024-10-31 16:00:36 +01:00
Jakub Grzywacz 4637dee1e4 feat: FeComposite filter (#2433)
# Summary

<img width="324" alt="image"
src="https://github.com/user-attachments/assets/0a9b4a56-d093-49f7-aacd-c198ee00f256">

## Test Plan

Examples app -> Filters -> FeComposite

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| macOS   |    *      |
| Android |          |
| Web     |          |

_*_ macOS isn't working as:
* `CGBitmapContextCreateImage` always returns null
* FeFlood isn't aligned properly (will be fixed in the following PR)
2024-10-25 11:18:07 +02:00
Jakub Grzywacz 096fdc22a5 feat: FeBlend (#2489)
# Summary

Continuation of #2362 implementing `FeBlend` filter
https://www.w3.org/TR/SVG11/filters.html#feBlendElement

## Test Plan

Example app → Filters → `FeBlend`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| macOS   |     _*_      |
| Android |          |
| Web     |          |
2024-10-16 11:45:44 +02:00
Jakub Grzywacz ba54b15799 feat: FeFlood (#2487)
# Summary

Continuation of #2362 implementing `FeFlood` filter
https://www.w3.org/TR/SVG11/filters.html#feFloodElement

## Test Plan

Example app → Filters → `FeFlood`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| macOS   |     _*_      |
| Android |          |
| Web     |          |

_* `canvasWidth/canvasHeight` is incorrect on macOS, so there might be
some problems_
2024-10-15 09:35:13 +02:00
Jakub Grzywacz 9d9958264b feat: properly implement currentColor (#2466)
# Summary

Motivated by issue #2455, I decided to implement the `currentColor`
property in line with the specs
(https://www.w3.org/TR/SVG11/color.html#ColorProperty). This involves
adding the `color` property to all renderable nodes.

## Test Plan

Example app -> `Test2455`

<img width="344" alt="image"
src="https://github.com/user-attachments/assets/ccaf5a79-4097-49f8-8948-0158d9d9274c">

```svg
<Svg color="red" width="60" height="60" viewBox="0 0 24 24" fill="none">
  <Path d="M22.7927 11.1242C21.359 18.5187 12.0003 22.7782 12.0003 22.7782C12.0003 22.7782 2.64153 18.5187 1.20661 11.1242C0.326598 6.58719 2.24925 2.02329 7.13701 2.00007C10.7781 1.98296 12.0003 5.65211 12.0003 5.65211C12.0003 5.65211 13.2226 1.98173 16.8624 2.00007C21.7612 2.02329 23.6727 6.58841 22.7927 11.1242Z" fill="currentColor"/>
  <G color="green" fill="purple">
    <G>
      <Rect x="16" y="16" width="8" height="8" fill="currentColor"/>
      <G color="pink">
        <Rect x="0" y="16" width="8" height="8" color="gold" fill="currentColor"/>
        <Circle cx="12" cy="20" r="4" fill="currentColor"/>
      </G>
    </G>
  </G>
</Svg>
```
## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |          |
| MacOS   |          |
| Android |          |
2024-09-30 15:50:37 +02:00
Jakub Grzywacz ca1c35caa9 feat: introduce hitSlop prop (#2407)
# Summary

Explain the **motivation** for making this change: here are some points
to help you:

* What issues does the pull request solve? Please tag them so that they
will get automatically closed once the PR is merged
* What is the feature? (if applicable)
* How did you implement the solution?
* What areas of the library does it impact?

## Test Plan

Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes UI.

### What's required for testing (prerequisites)?

### What are the steps to reproduce (after prerequisites)?

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| MacOS   |          |
| Android |          |
| Web     |          |
2024-08-19 09:11:07 +02:00
Jakub Grzywacz b8b022c31e feat: add FeMerge and FeMergeNode filters (#2369)
# Summary

As mentioned in #2362
Introduce new filters:
* `FeMerge`
* `FeMergeNode`

## Example usage

```tsx
<Svg width="200" height="200">
  <Filter id="mergeWithOffset" width="180" height="180">
    <FeOffset dx="50" dy="50" result="test" />
    <FeOffset dx="100" dy="100" in="SourceGraphic" />
    <FeMerge>
      <FeMergeNode in="SourceGraphic" />
      <FeMergeNode in="test" />
      <FeMergeNode />
    </FeMerge>
  </Filter>
  <Rect
    x="0"
    y="0"
    width="100"
    height="100"
    stroke="black"
    fill="red"
    filter="url(#mergeWithOffset)"
  />
</Svg>
```

<img width="207" alt="image"
src="https://github.com/user-attachments/assets/9cb3ded6-f939-4b2b-8ece-df54e64fe898">

## Test Plan

`Example` app -> `Filters` -> `FeMerge`

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |

## Checklist

- [x] I have tested this on a device and a simulator
- [x] I added documentation in `README.md`
- [x] I updated the typed files (typescript)
2024-07-31 13:23:53 +02:00
Jakub Grzywacz 5807f2c1a6 feat: add FeOffset filter (#2361)
# Summary

Continuation of #2316
Introducing new filter `FeOffset`.

## Test Plan

Example app -> Filters -> FeOffset

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |

## Checklist

- [x] I have tested this on a device and a simulator
- [x] I added documentation in `README.md`
- [x] I updated the typed files (typescript)
2024-07-25 12:32:15 +02:00
Jakub Grzywacz 44254df9fb feat: add FeGaussianBlur filter (#2352)
# Summary

Continuation of #2316 
Introducing new filter `FeGaussianBlur`.

### Implementation notes

On Android there is no easy way to fully implement Gaussian blur, as
there is no native api for this. While a basic implementation is
possible with `RenderScript`, it does not allow for blur in one axis and
greater than `25`

## Test Plan

Example app -> Filters -> FeGaussianBlur

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |
2024-07-25 11:46:45 +02:00
Bohdan Artiukhov 67620f5b6a fix: macOS new architecture build (#2341)
# Summary
Based on recommendations from this
[proposition](https://github.com/software-mansion/react-native-svg/issues/2192#issuecomment-2177330499)
and added some changes now we can build macOS using the new
architecture.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| macOS     |         |

---------

Co-authored-by: Maciej Stosio <maciekstosio@users.noreply.github.com>
2024-07-23 15:34:32 +02:00
Jakub Grzywacz 08e92074b4 feat: filters support FeColorMatrix and FilterImage (#2316)
# Summary

Introducing the long-awaited **Filters** in `react-native-svg` 🎉

### Motivation

This PR is the beginning of bringing support of SVG Filters into
`react-native-svg`.

* **related issues**: This PR series will address the following issues:
#150, #176, #635, #883, #994, #996, #1216
* **feature overview**: This PR is a boilerplate for Filters
   * introducing `Filter` component and `FeColorMatrix` as a start. 
* It also introduces a new subdirectory called
`react-native-svg/filter-image` with a `FilterImage` component.

# Usage

## Filter and Fe...

Filters are compatible with the web familiar standard, so most things
should be compatible out-of-the-box and changes will be limited to using
a capital letter as it's component.

### Example

```tsx
import React from 'react';
import { FeColorMatrix, Filter, Rect, Svg } from 'react-native-svg';

export default () => {
  return (
    <Svg height="300" width="300">
      <Filter id="myFilter">
        <FeColorMatrix type="saturate" values="0.2" />
      </Filter>
      <Rect
        x="0"
        y="0"
        width="300"
        height="300"
        fill="red"
        filter="url(#myFilter)"
      />
    </Svg>
  );
};
```

![image](https://github.com/software-mansion/react-native-svg/assets/39670088/c36fb238-95f4-455d-b0aa-2a7d4038b828)

## Filter Image

`FilterImage` is a new component that is not strictly related to SVG.
Its behavior should be the same as a regular `Image` component from
React Native with one exception - the additional prop `filters`, which
accepts an array of filters to apply to the image.

### Example

```tsx
import React from 'react';
import { StyleSheet } from 'react-native';
import { FilterImage } from 'react-native-svg/filter-image';

const myImage = require('./myImage.jpg');

export default () => {
  return (
    <FilterImage
      style={styles.image}
      source={myImage}
      filters={[
        { name: 'colorMatrix', type: 'saturate', values: 0.2 },
        {
          name: 'colorMatrix',
          type: 'matrix',
          values: [
            0.2, 0.2, 0.2, 0, 0, 0.2, 0.2, 0.2, 0, 0, 0.2, 0.2, 0.2, 0, 0, 0, 0,
            0, 1, 0,
          ],
        },
      ]}
    />
  );
};
const styles = StyleSheet.create({
  image: {
    width: 200,
    height: 200,
  },
});
```


![image](https://github.com/software-mansion/react-native-svg/assets/39670088/666ed89f-68d8-491b-b97f-1eef112b7095)

## Test Plan

**Example App**: Updated the example app with various filter effects,
showcasing real-world usage.

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |

## Checklist

- [x] I have tested this on a device and a simulator
- [x] I added documentation in `README.md` and `USAGE.md`
- [x] I updated the typed files (typescript)
2024-07-11 11:17:35 +02:00
SergeyYurkevich 832522d1c1 feat: implement mask-type property (#2152)
# Summary

"mask-type: alpha" is not supported. 
resolve issue: #1790  

## Explanation

svg example:
```
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100" fill="none">
<g clip-path="url(#clip0_8_3)">
<rect width="100" height="100" fill="white"/>
<mask id="mask0_8_3" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
<circle cx="50" cy="50" r="50" fill="#000000"/>
</mask>
<g mask="url(#mask0_8_3)">
<rect x="-26" y="-78" width="209" height="263" fill="#252E74"/>
</g>
</g>
<defs>
<clipPath id="clip0_8_3">
<rect width="100" height="100" fill="white"/>
</clipPath>
</defs>
</svg>
```

Current behavior: 

![image](https://github.com/software-mansion/react-native-svg/assets/17138397/2dca6f46-fe8f-48f3-80f9-799563911e8b)

Expected behavior:

![image](https://github.com/software-mansion/react-native-svg/assets/17138397/fb49cf0b-d677-491f-8215-9c9b1d69080f)

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |        |
| Android |        |

## Checklist

<!-- Check completed item, when applicable, via: [X] -->

- [x] I have tested this on a device and a simulator
- [ ] I added documentation in `README.md`
- [x] I updated the typed files (typescript)
- [ ] I added a test for the API in the `__tests__` folder

---------

Co-authored-by: Sergey <s.yurkevich@logiclike.com>
Co-authored-by: Jakub Grzywacz <jakub.grzywacz@swmansion.com>
2024-07-05 15:11:48 +02:00
Bohdan Artiukhov c0ee3e9ca0 add onLoad prop to Image component (#2293)
# Summary

Closes #1442

We want to add new props to the Image Component.

## Test Plan

Added the Test component. 
Manually test that in Android and IOS platforms on new and old
Architectures.

### What are the steps to reproduce (after prerequisites)?

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |
2024-06-27 16:10:28 +02:00
Wojciech Lewicki a917baf2ec fix: remove unnecessary methods provided by superclasses for accessibility (#2013)
PR removing methods that seem unnecessary for the accessibility props since they are provided by superclasses. It was necessary to update fabric updateProps method though, since we don't call super there. Also added proper type definitions and removed unnecessary casts.
2023-03-27 15:18:59 +02:00
toter3 d03604797f add accessibility and testId props and virtual nodes to support e2e tests tools (#2001)
PR adding accessibility and testId props and virtual nodes to support e2e tests tools and provide general accessibility support.

Co-authored-by: yonatan.altaraz <yonatan.altaraz@khealth.ai>
Co-authored-by: galkahana <gal.kahana@hotmail.com>
2023-03-22 13:01:09 +01:00
Wojciech Lewicki 70192b233d feat: use transform parsing code from rn core (#1918)
PR changing the custom transform prop parsing algorithm to the one from RN core (facebook/react-native@2eccd59/React/Views/RCTConvert%2BTransform.m), which the current one was most probably taken from.
2022-11-15 14:07:24 +01:00
Wojciech Lewicki 1126079425 feat: use codegenNativeComponent to import native views (#1847)
Changed `requireNativeComponent` to `codegenNativeComponent` so that upcoming changes (Static View Configs, Bridgeless Mode and idk what more) in `react-native` are available in the library. Also, types and native components are now taken directly from `fabric` folder to make sure the values passed to the native components are the ones defined in props. It should work on all supported versions since `codegenNativeComponent` function exists from RN v. 0.61.0. Suggested by @RSNara and @cipolleschi

Reason for [`5394bbb` (#1847)](https://github.com/software-mansion/react-native-svg/pull/1847/commits/5394bbbced6c1838e67240997cf4621d7f783197): 
- on `Paper`, `Animated` uses `setNativeProps` method when we set `useNativeDriver`  to `false`, and does not rerender the component. Therefore, new transform lands only in `SvgView` and is parsed in `RCTViewManager.m` .
- on `Fabric`, the same code makes the components rerender. Due to this, information about new transform is passed to the `SvgView` child: `G` , making it apply translations from the transform in its `updateProps` method.
- other than `Animated` use-case, on both archs, if we just passed `transform` prop to `Svg` component, it would end up in double transformations now as well. All of those changes are due to https://github.com/software-mansion/react-native-svg/pull/1895, which added proper parsing of RN style `transform` prop (array of transformations objects) therefore making `G` properly handle `transform` prop passed from `Svg`.

Reason for [`19bcb24` (#1847)](https://github.com/software-mansion/react-native-svg/pull/1847/commits/19bcb2464b3a40a47e4396ea66f49d6a95bfc9bc): Same as https://github.com/software-mansion/react-native-screens/pull/1624
2022-11-03 15:47:29 +01:00
Wojciech Lewicki 6a5242f00b fix: proper transform prop handling (#1895)
PR aligning handling of transform prop between web and native and adding proper handling of transform prop on web.

origin prop is now treated as transform-origin since it seems like the current behavior of this prop on native platforms.
transform prop cannot be an object with transform properties since it does not provide order of transformations which would lead to undefined behavior so this option has been removed.
RN style of transform prop (array of rotation objects) can now be used
font-size on web seems to be 16px by default and it is 12 in library - maybe we should align it somehow
removed maskTransform prop since it does not exist in SVG standard and did nothing on native side
fixed typo in Fabric Pattern updateProps method
2022-10-25 15:55:17 +02:00
Wojciech Lewicki ee6e5da195 feat: transfer specs to ts and remove unnecessary props (#1865)
PR transfering Fabric specs to TS, removing unnecessary @ReactProp adnotations, unifying inheritance hierarchy across platforms, adding custom types for color and image source props so they are parsed by react-native.
2022-09-14 12:01:35 +02:00
Wojciech Lewicki 98c14b4f45 chore: add CI for JS, iOS and Android formatting (#1782)
Added CI workflow and local pre-commit hook for formatting and linting the newly added JS, iOS and Android code.
2022-08-16 12:00:32 +02:00
Wojciech Lewicki 8f1bda4856 feat: add Fabric on iOS without ComponentViews (#1821)
Version of #1754 without usage of ComponentViews. It seems like a more proper way, but introduces the necessity of clearing whole state of each component on recycling for it not to be used when view is recycled.

Still known problems:

We stringify props of type NumberProp since codegen only accepts props of a single type. It is the fastest way of dealing with it, but maybe there could be a better way to handle it.
Image resolving should be probably handled the same as in RN core
SvgView needs to set opaque = NO so it is does not have black background (it comes from the fact that RCTViewComponentView overrides backgroundColor setter which in turn somehow messes with the view being opaque). All other svg components do it already so maybe it is not such an issue.
transform prop won't work when set natively since it is not parsed in Fabric
2022-08-11 14:08:11 +02:00
Adam Gleitman a56d22a985 refactor: rename ios/ source folder to apple/ 2020-11-25 16:31:39 -08:00