react-native-smooth-clip-view 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,12 +13,17 @@ native-owned timing or spring motion without animating Yoga layout. A regular
13
13
  Reanimated `View` with `overflow: 'hidden'` remains the simpler choice when
14
14
  layout-thread work and interruption snapshots are not concerns.
15
15
 
16
+ ## Demo
17
+
18
+ https://github.com/user-attachments/assets/899235b3-de69-46d7-b6db-61bc54d80df8
19
+
16
20
  ## Requirements
17
21
 
18
22
  - React Native 0.86 or newer with the New Architecture
19
23
  - React 19.2 or newer
20
24
  - React Native Reanimated 4.5 or newer
21
25
  - React Native Worklets 0.10.1 or newer
26
+ - Android API 24 or newer
22
27
 
23
28
  ```sh
24
29
  npm install react-native-smooth-clip-view react-native-reanimated react-native-worklets
@@ -1,7 +1,7 @@
1
1
  buildscript {
2
2
  ext.SmoothClipView = [
3
3
  kotlinVersion: "2.0.21",
4
- minSdkVersion: 33,
4
+ minSdkVersion: 24,
5
5
  compileSdkVersion: 36,
6
6
  targetSdkVersion: 36
7
7
  ]
@@ -76,10 +76,7 @@ android {
76
76
  }
77
77
 
78
78
  defaultConfig {
79
- // Outline.setPath only guarantees arbitrary path clipping from API 33.
80
- // Keep this as a hard library floor: allowing a consuming root project to
81
- // override it lower would make the per-corner/continuous path silently
82
- // unsupported at runtime.
79
+ // API 24-32 clip child drawing directly; API 33+ use path outlines.
83
80
  minSdkVersion SmoothClipView.minSdkVersion
84
81
  targetSdkVersion getExtOrDefault("targetSdkVersion")
85
82
  // C++ resolves SmoothClipView by name and calls its presentation setters via
@@ -22,7 +22,25 @@ import kotlin.math.abs
22
22
  import kotlin.math.pow
23
23
 
24
24
  class SmoothClipView(context: ThemedReactContext) : ReactViewGroup(context) {
25
- private val clipContainer = ReactViewGroup(context)
25
+ private val clipPath = Path()
26
+ private val supportsPathOutlineClipping =
27
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
28
+ private val clipContainer: ReactViewGroup =
29
+ if (supportsPathOutlineClipping) {
30
+ ReactViewGroup(context)
31
+ } else {
32
+ object : ReactViewGroup(context) {
33
+ override fun dispatchDraw(canvas: Canvas) {
34
+ val saveCount = canvas.save()
35
+ canvas.clipPath(clipPath)
36
+ try {
37
+ super.dispatchDraw(canvas)
38
+ } finally {
39
+ canvas.restoreToCount(saveCount)
40
+ }
41
+ }
42
+ }
43
+ }
26
44
  internal val contentContainer = ReactViewGroup(context)
27
45
  private var requestedX = 0f
28
46
  private var requestedY = 0f
@@ -54,7 +72,6 @@ class SmoothClipView(context: ThemedReactContext) : ReactViewGroup(context) {
54
72
  private var clipBottomRightRadius = 0f
55
73
  private var clipBottomLeftRadius = 0f
56
74
  private var clipCurveCode = CLIP_CURVE_CIRCULAR
57
- private val clipPath = Path()
58
75
  private var boxShadowPath: Path? = null
59
76
  private var boxShadowPaint: Paint? = null
60
77
  private var clipIsEmpty = true
@@ -75,17 +92,23 @@ class SmoothClipView(context: ThemedReactContext) : ReactViewGroup(context) {
75
92
  return
76
93
  }
77
94
 
78
- // Outline.setRoundRect only accepts integer edges. The raw path
79
- // keeps sub-pixel coordinates and off-host geometry intact.
80
- outline.setPath(clipPath)
95
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
96
+ // Outline.setRoundRect only accepts integer edges. The raw path
97
+ // keeps sub-pixel coordinates and off-host geometry intact.
98
+ outline.setPath(clipPath)
99
+ } else {
100
+ outline.setEmpty()
101
+ }
81
102
  }
82
103
  }
83
104
 
84
105
  init {
85
106
  clipContainer.addView(contentContainer)
86
107
  super.addView(clipContainer)
87
- clipContainer.outlineProvider = clipOutlineProvider
88
- clipContainer.clipToOutline = true
108
+ if (supportsPathOutlineClipping) {
109
+ clipContainer.outlineProvider = clipOutlineProvider
110
+ clipContainer.clipToOutline = true
111
+ }
89
112
  clipToOutline = false
90
113
  setWillNotDraw(false)
91
114
  visibility = INVISIBLE
@@ -479,7 +502,11 @@ class SmoothClipView(context: ThemedReactContext) : ReactViewGroup(context) {
479
502
  }
480
503
  }
481
504
  rebuildBoxShadowPath()
482
- clipContainer.invalidateOutline()
505
+ if (supportsPathOutlineClipping) {
506
+ clipContainer.invalidateOutline()
507
+ } else {
508
+ clipContainer.invalidate()
509
+ }
483
510
  if (requestedShadowEnabled) invalidate()
484
511
  }
485
512
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-smooth-clip-view",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Layout-free animated rounded clipping for React Native Fabric",
5
5
  "main": "./lib/module/index.js",
6
6
  "module": "./lib/module/index.js",