react-native-skelo 0.0.2 → 0.0.3

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Shubhanshu
3
+ Copyright (c) 2026 Shubhanshu Barnwal <connect@shubhanshubb.dev> (https://shubhanshubb.dev)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -29,11 +29,12 @@ While `loading`, Skelo reads the tree and its styles and renders a matching skel
29
29
  ## Installation
30
30
 
31
31
  ```bash
32
- npm install react-native-skelo
33
- npm install react-native-reanimated react-native-linear-gradient
32
+ npm install react-native-skelo react-native-reanimated
34
33
  ```
35
34
 
36
- That's all you need for the basic (inline) and `styles` usage.
35
+ That's all you need for the basic (inline) and `styles` usage. The shimmer uses
36
+ React Native's built-in `experimental_backgroundImage` gradient (New
37
+ Architecture) — no gradient library required.
37
38
 
38
39
  ### To enable `deep` mode (optional)
39
40
 
@@ -160,7 +161,8 @@ Also exported: `withSkeleton`, `SkeletonIgnore`, `StyleSkeleton`, the primitives
160
161
 
161
162
  ## Requirements
162
163
 
163
- - React Native (Fabric / New Architecture recommended)
164
+ - React Native New Architecture recommended (the shimmer's
165
+ `experimental_backgroundImage` gradient needs it)
164
166
  - `react-native-reanimated` ≥ 3
165
167
  - `react-reconciler` (optional, for `deep`) — must match your React version
166
168
 
@@ -8,23 +8,7 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
10
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
- /**
12
- * Pulse animation component using Reanimated 3
13
- *
14
- * Creates a subtle breathing/pulsing effect using:
15
- * - Shared values for performance
16
- * - Worklets for 60 FPS on UI thread
17
- * - Opacity animation for pulse effect
18
- *
19
- * @example
20
- * ```tsx
21
- * <PulseAnimation
22
- * width={200}
23
- * height={20}
24
- * borderRadius={4}
25
- * />
26
- * ```
27
- */
11
+ // Breathing opacity loop on the UI thread with Reanimated.
28
12
  function PulseAnimation({
29
13
  width,
30
14
  height,
@@ -34,24 +18,16 @@ function PulseAnimation({
34
18
  style,
35
19
  children
36
20
  }) {
37
- // Shared value for opacity (0 to 1)
38
21
  const opacity = (0, _reactNativeReanimated.useSharedValue)(1);
39
22
  (0, _react.useEffect)(() => {
40
- // Start infinite pulse animation
41
- // Sequence: fade out -> fade in
42
23
  opacity.value = (0, _reactNativeReanimated.withRepeat)((0, _reactNativeReanimated.withSequence)((0, _reactNativeReanimated.withTiming)(0.5, {
43
24
  duration: duration / 2,
44
25
  easing: _reactNativeReanimated.Easing.inOut(_reactNativeReanimated.Easing.ease)
45
26
  }), (0, _reactNativeReanimated.withTiming)(1, {
46
27
  duration: duration / 2,
47
28
  easing: _reactNativeReanimated.Easing.inOut(_reactNativeReanimated.Easing.ease)
48
- })), -1,
49
- // Infinite repeat
50
- false // Don't reverse
51
- );
29
+ })), -1, false);
52
30
  }, [duration, opacity]);
53
-
54
- // Animated style for pulse effect
55
31
  const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
56
32
  'worklet';
57
33
 
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","PulseAnimation","width","height","baseColor","duration","borderRadius","style","children","opacity","useSharedValue","useEffect","value","withRepeat","withSequence","withTiming","easing","Easing","inOut","ease","animatedStyle","useAnimatedStyle","createElement","View","styles","container","backgroundColor","StyleSheet","create","overflow"],"sourceRoot":"../../../src","sources":["animations/PulseAnimation.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","PulseAnimation","width","height","baseColor","duration","borderRadius","style","children","opacity","useSharedValue","useEffect","value","withRepeat","withSequence","withTiming","easing","Easing","inOut","ease","animatedStyle","useAnimatedStyle","createElement","View","styles","container","backgroundColor","StyleSheet","create","overflow"],"sourceRoot":"../../../src","sources":["animations/PulseAnimation.tsx"],"mappings":"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","ignoreList":[]}
@@ -7,25 +7,10 @@ exports.ShimmerAnimation = ShimmerAnimation;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
- var _reactNativeLinearGradient = require("react-native-linear-gradient");
11
10
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
12
- /**
13
- * Shimmer animation component using Reanimated 3
14
- *
15
- * Creates a smooth left-to-right shimmer effect using:
16
- * - Shared values for performance
17
- * - Worklets for 60 FPS on UI thread
18
- * - Linear gradient for shimmer effect
19
- *
20
- * @example
21
- * ```tsx
22
- * <ShimmerAnimation
23
- * width={200}
24
- * height={20}
25
- * borderRadius={4}
26
- * />
27
- * ```
28
- */
11
+ // Shimmer with no gradient library: the sweeping overlay uses React Native's
12
+ // built-in `experimental_backgroundImage` CSS gradient (New Architecture),
13
+ // animated on the UI thread with Reanimated.
29
14
  function ShimmerAnimation({
30
15
  width,
31
16
  height,
@@ -36,33 +21,37 @@ function ShimmerAnimation({
36
21
  style,
37
22
  children
38
23
  }) {
39
- // Shared value for animation progress (0 to 1)
40
24
  const progress = (0, _reactNativeReanimated.useSharedValue)(0);
25
+ const [measuredWidth, setMeasuredWidth] = (0, _react.useState)(0);
41
26
  (0, _react.useEffect)(() => {
42
- // Start infinite shimmer animation
43
27
  progress.value = (0, _reactNativeReanimated.withRepeat)((0, _reactNativeReanimated.withTiming)(1, {
44
28
  duration,
45
29
  easing: _reactNativeReanimated.Easing.linear
46
- }), -1,
47
- // Infinite repeat
48
- false // Don't reverse
49
- );
30
+ }), -1, false);
50
31
  }, [duration, progress]);
51
-
52
- // Animated style for shimmer overlay
32
+ const onLayout = event => {
33
+ const w = event.nativeEvent.layout.width;
34
+ setMeasuredWidth(prev => prev === w ? prev : w);
35
+ };
36
+ const containerWidth = typeof width === 'number' ? width : measuredWidth;
53
37
  const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
54
38
  'worklet';
55
39
 
56
- // Calculate shimmer position
57
- // Interpolate from -100% to 100% to create left-to-right sweep
58
- const translateX = (0, _reactNativeReanimated.interpolate)(progress.value, [0, 1], [-1, 1]);
40
+ const translateX = (0, _reactNativeReanimated.interpolate)(progress.value, [0, 1], [-containerWidth, containerWidth]);
59
41
  return {
60
42
  transform: [{
61
- translateX: translateX * (typeof width === 'number' ? width : 200)
43
+ translateX
62
44
  }]
63
45
  };
64
- }, [width]);
46
+ }, [containerWidth]);
47
+
48
+ // `experimental_backgroundImage` isn't in the ViewStyle types yet.
49
+ const gradientStyle = {
50
+ ..._reactNative.StyleSheet.absoluteFillObject,
51
+ experimental_backgroundImage: `linear-gradient(to right, ${baseColor}, ${highlightColor}, ${baseColor})`
52
+ };
65
53
  return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
54
+ onLayout: onLayout,
66
55
  style: [styles.container, {
67
56
  width,
68
57
  height,
@@ -70,34 +59,15 @@ function ShimmerAnimation({
70
59
  backgroundColor: baseColor
71
60
  }, style]
72
61
  }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
73
- style: [_reactNative.StyleSheet.absoluteFill, {
74
- overflow: 'hidden',
75
- borderRadius
76
- }]
77
- }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
78
- style: [styles.shimmer, {
79
- width: typeof width === 'number' ? width : '100%',
80
- height: '100%'
81
- }, animatedStyle]
82
- }, /*#__PURE__*/_react.default.createElement(_reactNativeLinearGradient.LinearGradient, {
83
- colors: [baseColor, highlightColor, highlightColor, baseColor],
84
- start: {
85
- x: 0,
86
- y: 0
87
- },
88
- end: {
89
- x: 1,
90
- y: 0
91
- },
92
- style: _reactNative.StyleSheet.absoluteFill
93
- }))), children);
62
+ pointerEvents: "none",
63
+ style: [_reactNative.StyleSheet.absoluteFill, animatedStyle]
64
+ }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
65
+ style: gradientStyle
66
+ })), children);
94
67
  }
95
68
  const styles = _reactNative.StyleSheet.create({
96
69
  container: {
97
70
  overflow: 'hidden'
98
- },
99
- shimmer: {
100
- position: 'absolute'
101
71
  }
102
72
  });
103
73
  //# sourceMappingURL=ShimmerAnimation.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_reactNativeLinearGradient","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ShimmerAnimation","width","height","baseColor","highlightColor","duration","borderRadius","style","children","progress","useSharedValue","useEffect","value","withRepeat","withTiming","easing","Easing","linear","animatedStyle","useAnimatedStyle","translateX","interpolate","transform","createElement","View","styles","container","backgroundColor","StyleSheet","absoluteFill","overflow","shimmer","LinearGradient","colors","start","x","y","end","create","position"],"sourceRoot":"../../../src","sources":["animations/ShimmerAnimation.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ShimmerAnimation","width","height","baseColor","highlightColor","duration","borderRadius","style","children","progress","useSharedValue","measuredWidth","setMeasuredWidth","useState","useEffect","value","withRepeat","withTiming","easing","Easing","linear","onLayout","event","w","nativeEvent","layout","prev","containerWidth","animatedStyle","useAnimatedStyle","translateX","interpolate","transform","gradientStyle","StyleSheet","absoluteFillObject","experimental_backgroundImage","createElement","View","styles","container","backgroundColor","pointerEvents","absoluteFill","create","overflow"],"sourceRoot":"../../../src","sources":["animations/ShimmerAnimation.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,23 +1,7 @@
1
1
  import React, { useEffect } from 'react';
2
2
  import { StyleSheet } from 'react-native';
3
3
  import Animated, { useSharedValue, useAnimatedStyle, withRepeat, withSequence, withTiming, Easing } from 'react-native-reanimated';
4
- /**
5
- * Pulse animation component using Reanimated 3
6
- *
7
- * Creates a subtle breathing/pulsing effect using:
8
- * - Shared values for performance
9
- * - Worklets for 60 FPS on UI thread
10
- * - Opacity animation for pulse effect
11
- *
12
- * @example
13
- * ```tsx
14
- * <PulseAnimation
15
- * width={200}
16
- * height={20}
17
- * borderRadius={4}
18
- * />
19
- * ```
20
- */
4
+ // Breathing opacity loop on the UI thread with Reanimated.
21
5
  export function PulseAnimation({
22
6
  width,
23
7
  height,
@@ -27,24 +11,16 @@ export function PulseAnimation({
27
11
  style,
28
12
  children
29
13
  }) {
30
- // Shared value for opacity (0 to 1)
31
14
  const opacity = useSharedValue(1);
32
15
  useEffect(() => {
33
- // Start infinite pulse animation
34
- // Sequence: fade out -> fade in
35
16
  opacity.value = withRepeat(withSequence(withTiming(0.5, {
36
17
  duration: duration / 2,
37
18
  easing: Easing.inOut(Easing.ease)
38
19
  }), withTiming(1, {
39
20
  duration: duration / 2,
40
21
  easing: Easing.inOut(Easing.ease)
41
- })), -1,
42
- // Infinite repeat
43
- false // Don't reverse
44
- );
22
+ })), -1, false);
45
23
  }, [duration, opacity]);
46
-
47
- // Animated style for pulse effect
48
24
  const animatedStyle = useAnimatedStyle(() => {
49
25
  'worklet';
50
26
 
@@ -1 +1 @@
1
- {"version":3,"names":["React","useEffect","StyleSheet","Animated","useSharedValue","useAnimatedStyle","withRepeat","withSequence","withTiming","Easing","PulseAnimation","width","height","baseColor","duration","borderRadius","style","children","opacity","value","easing","inOut","ease","animatedStyle","createElement","View","styles","container","backgroundColor","create","overflow"],"sourceRoot":"../../../src","sources":["animations/PulseAnimation.tsx"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,SAAS,QAAQ,OAAO;AAExC,SAASC,UAAU,QAAQ,cAAc;AACzC,OAAOC,QAAQ,IACbC,cAAc,EACdC,gBAAgB,EAChBC,UAAU,EACVC,YAAY,EACZC,UAAU,EACVC,MAAM,QACD,yBAAyB;AA+ChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAAC;EAC7BC,KAAK;EACLC,MAAM;EACNC,SAAS,GAAG,SAAS;EACrBC,QAAQ,GAAG,IAAI;EACfC,YAAY,GAAG,CAAC;EAChBC,KAAK;EACLC;AACU,CAAC,EAAE;EACb;EACA,MAAMC,OAAO,GAAGd,cAAc,CAAC,CAAC,CAAC;EAEjCH,SAAS,CAAC,MAAM;IACd;IACA;IACAiB,OAAO,CAACC,KAAK,GAAGb,UAAU,CACxBC,YAAY,CACVC,UAAU,CAAC,GAAG,EAAE;MACdM,QAAQ,EAAEA,QAAQ,GAAG,CAAC;MACtBM,MAAM,EAAEX,MAAM,CAACY,KAAK,CAACZ,MAAM,CAACa,IAAI;IAClC,CAAC,CAAC,EACFd,UAAU,CAAC,CAAC,EAAE;MACZM,QAAQ,EAAEA,QAAQ,GAAG,CAAC;MACtBM,MAAM,EAAEX,MAAM,CAACY,KAAK,CAACZ,MAAM,CAACa,IAAI;IAClC,CAAC,CACH,CAAC,EACD,CAAC,CAAC;IAAE;IACJ,KAAK,CAAC;IACR,CAAC;EACH,CAAC,EAAE,CAACR,QAAQ,EAAEI,OAAO,CAAC,CAAC;;EAEvB;EACA,MAAMK,aAAa,GAAGlB,gBAAgB,CAAC,MAAM;IAC3C,SAAS;;IAET,OAAO;MACLa,OAAO,EAAEA,OAAO,CAACC;IACnB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,oBACEnB,KAAA,CAAAwB,aAAA,CAACrB,QAAQ,CAACsB,IAAI;IACZT,KAAK,EAAE,CACLU,MAAM,CAACC,SAAS,EAChB;MACEhB,KAAK;MACLC,MAAM;MACNG,YAAY;MACZa,eAAe,EAAEf;IACnB,CAAC,EACDU,aAAa,EACbP,KAAK;EACL,GAEDC,QACY,CAAC;AAEpB;AAEA,MAAMS,MAAM,GAAGxB,UAAU,CAAC2B,MAAM,CAAC;EAC/BF,SAAS,EAAE;IACTG,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["React","useEffect","StyleSheet","Animated","useSharedValue","useAnimatedStyle","withRepeat","withSequence","withTiming","Easing","PulseAnimation","width","height","baseColor","duration","borderRadius","style","children","opacity","value","easing","inOut","ease","animatedStyle","createElement","View","styles","container","backgroundColor","create","overflow"],"sourceRoot":"../../../src","sources":["animations/PulseAnimation.tsx"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,SAAS,QAAQ,OAAO;AAExC,SAASC,UAAU,QAAQ,cAAc;AACzC,OAAOC,QAAQ,IACbC,cAAc,EACdC,gBAAgB,EAChBC,UAAU,EACVC,YAAY,EACZC,UAAU,EACVC,MAAM,QACD,yBAAyB;AAahC;AACA,OAAO,SAASC,cAAcA,CAAC;EAC7BC,KAAK;EACLC,MAAM;EACNC,SAAS,GAAG,SAAS;EACrBC,QAAQ,GAAG,IAAI;EACfC,YAAY,GAAG,CAAC;EAChBC,KAAK;EACLC;AACU,CAAC,EAAE;EACb,MAAMC,OAAO,GAAGd,cAAc,CAAC,CAAC,CAAC;EAEjCH,SAAS,CAAC,MAAM;IACdiB,OAAO,CAACC,KAAK,GAAGb,UAAU,CACxBC,YAAY,CACVC,UAAU,CAAC,GAAG,EAAE;MACdM,QAAQ,EAAEA,QAAQ,GAAG,CAAC;MACtBM,MAAM,EAAEX,MAAM,CAACY,KAAK,CAACZ,MAAM,CAACa,IAAI;IAClC,CAAC,CAAC,EACFd,UAAU,CAAC,CAAC,EAAE;MACZM,QAAQ,EAAEA,QAAQ,GAAG,CAAC;MACtBM,MAAM,EAAEX,MAAM,CAACY,KAAK,CAACZ,MAAM,CAACa,IAAI;IAClC,CAAC,CACH,CAAC,EACD,CAAC,CAAC,EACF,KACF,CAAC;EACH,CAAC,EAAE,CAACR,QAAQ,EAAEI,OAAO,CAAC,CAAC;EAEvB,MAAMK,aAAa,GAAGlB,gBAAgB,CAAC,MAAM;IAC3C,SAAS;;IACT,OAAO;MAAEa,OAAO,EAAEA,OAAO,CAACC;IAAM,CAAC;EACnC,CAAC,EAAE,EAAE,CAAC;EAEN,oBACEnB,KAAA,CAAAwB,aAAA,CAACrB,QAAQ,CAACsB,IAAI;IACZT,KAAK,EAAE,CACLU,MAAM,CAACC,SAAS,EAChB;MAAEhB,KAAK;MAAEC,MAAM;MAAEG,YAAY;MAAEa,eAAe,EAAEf;IAAU,CAAC,EAC3DU,aAAa,EACbP,KAAK;EACL,GAEDC,QACY,CAAC;AAEpB;AAEA,MAAMS,MAAM,GAAGxB,UAAU,CAAC2B,MAAM,CAAC;EAC/BF,SAAS,EAAE;IACTG,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC","ignoreList":[]}
@@ -1,24 +1,9 @@
1
- import React, { useEffect } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { StyleSheet, View } from 'react-native';
3
3
  import Animated, { useSharedValue, useAnimatedStyle, withRepeat, withTiming, interpolate, Easing } from 'react-native-reanimated';
4
- import { LinearGradient } from 'react-native-linear-gradient';
5
- /**
6
- * Shimmer animation component using Reanimated 3
7
- *
8
- * Creates a smooth left-to-right shimmer effect using:
9
- * - Shared values for performance
10
- * - Worklets for 60 FPS on UI thread
11
- * - Linear gradient for shimmer effect
12
- *
13
- * @example
14
- * ```tsx
15
- * <ShimmerAnimation
16
- * width={200}
17
- * height={20}
18
- * borderRadius={4}
19
- * />
20
- * ```
21
- */
4
+ // Shimmer with no gradient library: the sweeping overlay uses React Native's
5
+ // built-in `experimental_backgroundImage` CSS gradient (New Architecture),
6
+ // animated on the UI thread with Reanimated.
22
7
  export function ShimmerAnimation({
23
8
  width,
24
9
  height,
@@ -29,33 +14,37 @@ export function ShimmerAnimation({
29
14
  style,
30
15
  children
31
16
  }) {
32
- // Shared value for animation progress (0 to 1)
33
17
  const progress = useSharedValue(0);
18
+ const [measuredWidth, setMeasuredWidth] = useState(0);
34
19
  useEffect(() => {
35
- // Start infinite shimmer animation
36
20
  progress.value = withRepeat(withTiming(1, {
37
21
  duration,
38
22
  easing: Easing.linear
39
- }), -1,
40
- // Infinite repeat
41
- false // Don't reverse
42
- );
23
+ }), -1, false);
43
24
  }, [duration, progress]);
44
-
45
- // Animated style for shimmer overlay
25
+ const onLayout = event => {
26
+ const w = event.nativeEvent.layout.width;
27
+ setMeasuredWidth(prev => prev === w ? prev : w);
28
+ };
29
+ const containerWidth = typeof width === 'number' ? width : measuredWidth;
46
30
  const animatedStyle = useAnimatedStyle(() => {
47
31
  'worklet';
48
32
 
49
- // Calculate shimmer position
50
- // Interpolate from -100% to 100% to create left-to-right sweep
51
- const translateX = interpolate(progress.value, [0, 1], [-1, 1]);
33
+ const translateX = interpolate(progress.value, [0, 1], [-containerWidth, containerWidth]);
52
34
  return {
53
35
  transform: [{
54
- translateX: translateX * (typeof width === 'number' ? width : 200)
36
+ translateX
55
37
  }]
56
38
  };
57
- }, [width]);
39
+ }, [containerWidth]);
40
+
41
+ // `experimental_backgroundImage` isn't in the ViewStyle types yet.
42
+ const gradientStyle = {
43
+ ...StyleSheet.absoluteFillObject,
44
+ experimental_backgroundImage: `linear-gradient(to right, ${baseColor}, ${highlightColor}, ${baseColor})`
45
+ };
58
46
  return /*#__PURE__*/React.createElement(View, {
47
+ onLayout: onLayout,
59
48
  style: [styles.container, {
60
49
  width,
61
50
  height,
@@ -63,34 +52,15 @@ export function ShimmerAnimation({
63
52
  backgroundColor: baseColor
64
53
  }, style]
65
54
  }, /*#__PURE__*/React.createElement(Animated.View, {
66
- style: [StyleSheet.absoluteFill, {
67
- overflow: 'hidden',
68
- borderRadius
69
- }]
70
- }, /*#__PURE__*/React.createElement(Animated.View, {
71
- style: [styles.shimmer, {
72
- width: typeof width === 'number' ? width : '100%',
73
- height: '100%'
74
- }, animatedStyle]
75
- }, /*#__PURE__*/React.createElement(LinearGradient, {
76
- colors: [baseColor, highlightColor, highlightColor, baseColor],
77
- start: {
78
- x: 0,
79
- y: 0
80
- },
81
- end: {
82
- x: 1,
83
- y: 0
84
- },
85
- style: StyleSheet.absoluteFill
86
- }))), children);
55
+ pointerEvents: "none",
56
+ style: [StyleSheet.absoluteFill, animatedStyle]
57
+ }, /*#__PURE__*/React.createElement(View, {
58
+ style: gradientStyle
59
+ })), children);
87
60
  }
88
61
  const styles = StyleSheet.create({
89
62
  container: {
90
63
  overflow: 'hidden'
91
- },
92
- shimmer: {
93
- position: 'absolute'
94
64
  }
95
65
  });
96
66
  //# sourceMappingURL=ShimmerAnimation.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","useEffect","StyleSheet","View","Animated","useSharedValue","useAnimatedStyle","withRepeat","withTiming","interpolate","Easing","LinearGradient","ShimmerAnimation","width","height","baseColor","highlightColor","duration","borderRadius","style","children","progress","value","easing","linear","animatedStyle","translateX","transform","createElement","styles","container","backgroundColor","absoluteFill","overflow","shimmer","colors","start","x","y","end","create","position"],"sourceRoot":"../../../src","sources":["animations/ShimmerAnimation.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","useEffect","useState","StyleSheet","View","Animated","useSharedValue","useAnimatedStyle","withRepeat","withTiming","interpolate","Easing","ShimmerAnimation","width","height","baseColor","highlightColor","duration","borderRadius","style","children","progress","measuredWidth","setMeasuredWidth","value","easing","linear","onLayout","event","w","nativeEvent","layout","prev","containerWidth","animatedStyle","translateX","transform","gradientStyle","absoluteFillObject","experimental_backgroundImage","createElement","styles","container","backgroundColor","pointerEvents","absoluteFill","create","overflow"],"sourceRoot":"../../../src","sources":["animations/ShimmerAnimation.tsx"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAOlD,SAASC,UAAU,EAAEC,IAAI,QAAQ,cAAc;AAC/C,OAAOC,QAAQ,IACbC,cAAc,EACdC,gBAAgB,EAChBC,UAAU,EACVC,UAAU,EACVC,WAAW,EACXC,MAAM,QACD,yBAAyB;AAahC;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAAC;EAC/BC,KAAK;EACLC,MAAM;EACNC,SAAS,GAAG,SAAS;EACrBC,cAAc,GAAG,SAAS;EAC1BC,QAAQ,GAAG,IAAI;EACfC,YAAY,GAAG,CAAC;EAChBC,KAAK;EACLC;AACY,CAAC,EAAE;EACf,MAAMC,QAAQ,GAAGf,cAAc,CAAC,CAAC,CAAC;EAClC,MAAM,CAACgB,aAAa,EAAEC,gBAAgB,CAAC,GAAGrB,QAAQ,CAAC,CAAC,CAAC;EAErDD,SAAS,CAAC,MAAM;IACdoB,QAAQ,CAACG,KAAK,GAAGhB,UAAU,CACzBC,UAAU,CAAC,CAAC,EAAE;MAAEQ,QAAQ;MAAEQ,MAAM,EAAEd,MAAM,CAACe;IAAO,CAAC,CAAC,EAClD,CAAC,CAAC,EACF,KACF,CAAC;EACH,CAAC,EAAE,CAACT,QAAQ,EAAEI,QAAQ,CAAC,CAAC;EAExB,MAAMM,QAAQ,GAAIC,KAAwB,IAAK;IAC7C,MAAMC,CAAC,GAAGD,KAAK,CAACE,WAAW,CAACC,MAAM,CAAClB,KAAK;IACxCU,gBAAgB,CAACS,IAAI,IAAKA,IAAI,KAAKH,CAAC,GAAGG,IAAI,GAAGH,CAAE,CAAC;EACnD,CAAC;EAED,MAAMI,cAAc,GAAG,OAAOpB,KAAK,KAAK,QAAQ,GAAGA,KAAK,GAAGS,aAAa;EAExE,MAAMY,aAAa,GAAG3B,gBAAgB,CAAC,MAAM;IAC3C,SAAS;;IACT,MAAM4B,UAAU,GAAGzB,WAAW,CAC5BW,QAAQ,CAACG,KAAK,EACd,CAAC,CAAC,EAAE,CAAC,CAAC,EACN,CAAC,CAACS,cAAc,EAAEA,cAAc,CAClC,CAAC;IACD,OAAO;MAAEG,SAAS,EAAE,CAAC;QAAED;MAAW,CAAC;IAAE,CAAC;EACxC,CAAC,EAAE,CAACF,cAAc,CAAC,CAAC;;EAEpB;EACA,MAAMI,aAAa,GAAG;IACpB,GAAGlC,UAAU,CAACmC,kBAAkB;IAChCC,4BAA4B,EAAE,6BAA6BxB,SAAS,KAAKC,cAAc,KAAKD,SAAS;EACvG,CAAyB;EAEzB,oBACEf,KAAA,CAAAwC,aAAA,CAACpC,IAAI;IACHuB,QAAQ,EAAEA,QAAS;IACnBR,KAAK,EAAE,CACLsB,MAAM,CAACC,SAAS,EAChB;MAAE7B,KAAK;MAAEC,MAAM;MAAEI,YAAY;MAAEyB,eAAe,EAAE5B;IAAU,CAAC,EAC3DI,KAAK;EACL,gBAEFnB,KAAA,CAAAwC,aAAA,CAACnC,QAAQ,CAACD,IAAI;IACZwC,aAAa,EAAC,MAAM;IACpBzB,KAAK,EAAE,CAAChB,UAAU,CAAC0C,YAAY,EAAEX,aAAa;EAAE,gBAEhDlC,KAAA,CAAAwC,aAAA,CAACpC,IAAI;IAACe,KAAK,EAAEkB;EAAc,CAAE,CAChB,CAAC,EAEfjB,QACG,CAAC;AAEX;AAEA,MAAMqB,MAAM,GAAGtC,UAAU,CAAC2C,MAAM,CAAC;EAC/BJ,SAAS,EAAE;IACTK,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC","ignoreList":[]}
@@ -1,59 +1,15 @@
1
1
  import React from 'react';
2
2
  import type { DimensionValue, StyleProp, ViewStyle } from 'react-native';
3
3
  interface PulseProps {
4
- /**
5
- * Width of the pulse container
6
- */
7
4
  width?: DimensionValue;
8
- /**
9
- * Height of the pulse container
10
- */
11
5
  height?: DimensionValue;
12
- /**
13
- * Base color of the skeleton
14
- * @default '#E1E9EE'
15
- */
16
6
  baseColor?: string;
17
- /**
18
- * Highlight color for pulse
19
- * @default '#F2F8FC'
20
- */
21
7
  highlightColor?: string;
22
- /**
23
- * Animation duration in milliseconds
24
- * @default 1000
25
- */
26
8
  duration?: number;
27
- /**
28
- * Border radius
29
- */
30
9
  borderRadius?: number;
31
- /**
32
- * Additional styles
33
- */
34
10
  style?: StyleProp<ViewStyle>;
35
- /**
36
- * Child content (rendered inside pulse)
37
- */
38
11
  children?: React.ReactNode;
39
12
  }
40
- /**
41
- * Pulse animation component using Reanimated 3
42
- *
43
- * Creates a subtle breathing/pulsing effect using:
44
- * - Shared values for performance
45
- * - Worklets for 60 FPS on UI thread
46
- * - Opacity animation for pulse effect
47
- *
48
- * @example
49
- * ```tsx
50
- * <PulseAnimation
51
- * width={200}
52
- * height={20}
53
- * borderRadius={4}
54
- * />
55
- * ```
56
- */
57
13
  export declare function PulseAnimation({ width, height, baseColor, duration, borderRadius, style, children, }: PulseProps): React.JSX.Element;
58
14
  export {};
59
15
  //# sourceMappingURL=PulseAnimation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PulseAnimation.d.ts","sourceRoot":"","sources":["../../../src/animations/PulseAnimation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAWzE,UAAU,UAAU;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,MAAM,EACN,SAAqB,EACrB,QAAe,EACf,YAAgB,EAChB,KAAK,EACL,QAAQ,GACT,EAAE,UAAU,qBAiDZ"}
1
+ {"version":3,"file":"PulseAnimation.d.ts","sourceRoot":"","sources":["../../../src/animations/PulseAnimation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAWzE,UAAU,UAAU;IAClB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAGD,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,MAAM,EACN,SAAqB,EACrB,QAAe,EACf,YAAgB,EAChB,KAAK,EACL,QAAQ,GACT,EAAE,UAAU,qBAqCZ"}
@@ -1,59 +1,15 @@
1
1
  import React from 'react';
2
2
  import type { DimensionValue, StyleProp, ViewStyle } from 'react-native';
3
3
  interface ShimmerProps {
4
- /**
5
- * Width of the shimmer container
6
- */
7
4
  width?: DimensionValue;
8
- /**
9
- * Height of the shimmer container
10
- */
11
5
  height?: DimensionValue;
12
- /**
13
- * Base color of the skeleton
14
- * @default '#E1E9EE'
15
- */
16
6
  baseColor?: string;
17
- /**
18
- * Highlight color that shimmers across
19
- * @default '#F2F8FC'
20
- */
21
7
  highlightColor?: string;
22
- /**
23
- * Animation duration in milliseconds
24
- * @default 1500
25
- */
26
8
  duration?: number;
27
- /**
28
- * Border radius
29
- */
30
9
  borderRadius?: number;
31
- /**
32
- * Additional styles
33
- */
34
10
  style?: StyleProp<ViewStyle>;
35
- /**
36
- * Child content (rendered on top of shimmer)
37
- */
38
11
  children?: React.ReactNode;
39
12
  }
40
- /**
41
- * Shimmer animation component using Reanimated 3
42
- *
43
- * Creates a smooth left-to-right shimmer effect using:
44
- * - Shared values for performance
45
- * - Worklets for 60 FPS on UI thread
46
- * - Linear gradient for shimmer effect
47
- *
48
- * @example
49
- * ```tsx
50
- * <ShimmerAnimation
51
- * width={200}
52
- * height={20}
53
- * borderRadius={4}
54
- * />
55
- * ```
56
- */
57
13
  export declare function ShimmerAnimation({ width, height, baseColor, highlightColor, duration, borderRadius, style, children, }: ShimmerProps): React.JSX.Element;
58
14
  export {};
59
15
  //# sourceMappingURL=ShimmerAnimation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ShimmerAnimation.d.ts","sourceRoot":"","sources":["../../../src/animations/ShimmerAnimation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAYzE,UAAU,YAAY;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,MAAM,EACN,SAAqB,EACrB,cAA0B,EAC1B,QAAe,EACf,YAAgB,EAChB,KAAK,EACL,QAAQ,GACT,EAAE,YAAY,qBA2Ed"}
1
+ {"version":3,"file":"ShimmerAnimation.d.ts","sourceRoot":"","sources":["../../../src/animations/ShimmerAnimation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EACV,cAAc,EAEd,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AAWtB,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAKD,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,MAAM,EACN,SAAqB,EACrB,cAA0B,EAC1B,QAAe,EACf,YAAgB,EAChB,KAAK,EACL,QAAQ,GACT,EAAE,YAAY,qBAsDd"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-skelo",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Automatic skeleton loading for React Native. Write your UI once, Skelo builds the loading state automatically.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -88,7 +88,6 @@
88
88
  "peerDependencies": {
89
89
  "react": "*",
90
90
  "react-native": "*",
91
- "react-native-linear-gradient": ">=2.8.0",
92
91
  "react-native-reanimated": ">=3.0.0",
93
92
  "react-reconciler": ">=0.29.0"
94
93
  },
@@ -113,7 +112,6 @@
113
112
  "react": "18.2.0",
114
113
  "react-native": "0.73.1",
115
114
  "react-native-builder-bob": "^0.23.2",
116
- "react-native-linear-gradient": "^2.8.3",
117
115
  "react-native-reanimated": "^3.6.1",
118
116
  "react-reconciler": "^0.29.2",
119
117
  "react-test-renderer": "18.2.0",
@@ -129,7 +127,7 @@
129
127
  "<rootDir>/lib/"
130
128
  ],
131
129
  "transformIgnorePatterns": [
132
- "node_modules/(?!(@react-native|react-native|react-native-reanimated|react-native-linear-gradient)/)"
130
+ "node_modules/(?!(@react-native|react-native|react-native-reanimated)/)"
133
131
  ],
134
132
  "collectCoverageFrom": [
135
133
  "src/**/*.{ts,tsx}",
@@ -11,67 +11,17 @@ import Animated, {
11
11
  } from 'react-native-reanimated';
12
12
 
13
13
  interface PulseProps {
14
- /**
15
- * Width of the pulse container
16
- */
17
14
  width?: DimensionValue;
18
-
19
- /**
20
- * Height of the pulse container
21
- */
22
15
  height?: DimensionValue;
23
-
24
- /**
25
- * Base color of the skeleton
26
- * @default '#E1E9EE'
27
- */
28
16
  baseColor?: string;
29
-
30
- /**
31
- * Highlight color for pulse
32
- * @default '#F2F8FC'
33
- */
34
17
  highlightColor?: string;
35
-
36
- /**
37
- * Animation duration in milliseconds
38
- * @default 1000
39
- */
40
18
  duration?: number;
41
-
42
- /**
43
- * Border radius
44
- */
45
19
  borderRadius?: number;
46
-
47
- /**
48
- * Additional styles
49
- */
50
20
  style?: StyleProp<ViewStyle>;
51
-
52
- /**
53
- * Child content (rendered inside pulse)
54
- */
55
21
  children?: React.ReactNode;
56
22
  }
57
23
 
58
- /**
59
- * Pulse animation component using Reanimated 3
60
- *
61
- * Creates a subtle breathing/pulsing effect using:
62
- * - Shared values for performance
63
- * - Worklets for 60 FPS on UI thread
64
- * - Opacity animation for pulse effect
65
- *
66
- * @example
67
- * ```tsx
68
- * <PulseAnimation
69
- * width={200}
70
- * height={20}
71
- * borderRadius={4}
72
- * />
73
- * ```
74
- */
24
+ // Breathing opacity loop on the UI thread with Reanimated.
75
25
  export function PulseAnimation({
76
26
  width,
77
27
  height,
@@ -81,12 +31,9 @@ export function PulseAnimation({
81
31
  style,
82
32
  children,
83
33
  }: PulseProps) {
84
- // Shared value for opacity (0 to 1)
85
34
  const opacity = useSharedValue(1);
86
35
 
87
36
  useEffect(() => {
88
- // Start infinite pulse animation
89
- // Sequence: fade out -> fade in
90
37
  opacity.value = withRepeat(
91
38
  withSequence(
92
39
  withTiming(0.5, {
@@ -98,30 +45,21 @@ export function PulseAnimation({
98
45
  easing: Easing.inOut(Easing.ease),
99
46
  })
100
47
  ),
101
- -1, // Infinite repeat
102
- false // Don't reverse
48
+ -1,
49
+ false
103
50
  );
104
51
  }, [duration, opacity]);
105
52
 
106
- // Animated style for pulse effect
107
53
  const animatedStyle = useAnimatedStyle(() => {
108
54
  'worklet';
109
-
110
- return {
111
- opacity: opacity.value,
112
- };
55
+ return { opacity: opacity.value };
113
56
  }, []);
114
57
 
115
58
  return (
116
59
  <Animated.View
117
60
  style={[
118
61
  styles.container,
119
- {
120
- width,
121
- height,
122
- borderRadius,
123
- backgroundColor: baseColor,
124
- },
62
+ { width, height, borderRadius, backgroundColor: baseColor },
125
63
  animatedStyle,
126
64
  style,
127
65
  ]}
@@ -1,5 +1,10 @@
1
- import React, { useEffect } from 'react';
2
- import type { DimensionValue, StyleProp, ViewStyle } from 'react-native';
1
+ import React, { useEffect, useState } from 'react';
2
+ import type {
3
+ DimensionValue,
4
+ LayoutChangeEvent,
5
+ StyleProp,
6
+ ViewStyle,
7
+ } from 'react-native';
3
8
  import { StyleSheet, View } from 'react-native';
4
9
  import Animated, {
5
10
  useSharedValue,
@@ -9,70 +14,21 @@ import Animated, {
9
14
  interpolate,
10
15
  Easing,
11
16
  } from 'react-native-reanimated';
12
- import { LinearGradient } from 'react-native-linear-gradient';
13
17
 
14
18
  interface ShimmerProps {
15
- /**
16
- * Width of the shimmer container
17
- */
18
19
  width?: DimensionValue;
19
-
20
- /**
21
- * Height of the shimmer container
22
- */
23
20
  height?: DimensionValue;
24
-
25
- /**
26
- * Base color of the skeleton
27
- * @default '#E1E9EE'
28
- */
29
21
  baseColor?: string;
30
-
31
- /**
32
- * Highlight color that shimmers across
33
- * @default '#F2F8FC'
34
- */
35
22
  highlightColor?: string;
36
-
37
- /**
38
- * Animation duration in milliseconds
39
- * @default 1500
40
- */
41
23
  duration?: number;
42
-
43
- /**
44
- * Border radius
45
- */
46
24
  borderRadius?: number;
47
-
48
- /**
49
- * Additional styles
50
- */
51
25
  style?: StyleProp<ViewStyle>;
52
-
53
- /**
54
- * Child content (rendered on top of shimmer)
55
- */
56
26
  children?: React.ReactNode;
57
27
  }
58
28
 
59
- /**
60
- * Shimmer animation component using Reanimated 3
61
- *
62
- * Creates a smooth left-to-right shimmer effect using:
63
- * - Shared values for performance
64
- * - Worklets for 60 FPS on UI thread
65
- * - Linear gradient for shimmer effect
66
- *
67
- * @example
68
- * ```tsx
69
- * <ShimmerAnimation
70
- * width={200}
71
- * height={20}
72
- * borderRadius={4}
73
- * />
74
- * ```
75
- */
29
+ // Shimmer with no gradient library: the sweeping overlay uses React Native's
30
+ // built-in `experimental_backgroundImage` CSS gradient (New Architecture),
31
+ // animated on the UI thread with Reanimated.
76
32
  export function ShimmerAnimation({
77
33
  width,
78
34
  height,
@@ -83,77 +39,56 @@ export function ShimmerAnimation({
83
39
  style,
84
40
  children,
85
41
  }: ShimmerProps) {
86
- // Shared value for animation progress (0 to 1)
87
42
  const progress = useSharedValue(0);
43
+ const [measuredWidth, setMeasuredWidth] = useState(0);
88
44
 
89
45
  useEffect(() => {
90
- // Start infinite shimmer animation
91
46
  progress.value = withRepeat(
92
- withTiming(1, {
93
- duration,
94
- easing: Easing.linear,
95
- }),
96
- -1, // Infinite repeat
97
- false // Don't reverse
47
+ withTiming(1, { duration, easing: Easing.linear }),
48
+ -1,
49
+ false
98
50
  );
99
51
  }, [duration, progress]);
100
52
 
101
- // Animated style for shimmer overlay
53
+ const onLayout = (event: LayoutChangeEvent) => {
54
+ const w = event.nativeEvent.layout.width;
55
+ setMeasuredWidth(prev => (prev === w ? prev : w));
56
+ };
57
+
58
+ const containerWidth = typeof width === 'number' ? width : measuredWidth;
59
+
102
60
  const animatedStyle = useAnimatedStyle(() => {
103
61
  'worklet';
62
+ const translateX = interpolate(
63
+ progress.value,
64
+ [0, 1],
65
+ [-containerWidth, containerWidth]
66
+ );
67
+ return { transform: [{ translateX }] };
68
+ }, [containerWidth]);
104
69
 
105
- // Calculate shimmer position
106
- // Interpolate from -100% to 100% to create left-to-right sweep
107
- const translateX = interpolate(progress.value, [0, 1], [-1, 1]);
108
-
109
- return {
110
- transform: [{ translateX: translateX * (typeof width === 'number' ? width : 200) }],
111
- };
112
- }, [width]);
70
+ // `experimental_backgroundImage` isn't in the ViewStyle types yet.
71
+ const gradientStyle = {
72
+ ...StyleSheet.absoluteFillObject,
73
+ experimental_backgroundImage: `linear-gradient(to right, ${baseColor}, ${highlightColor}, ${baseColor})`,
74
+ } as unknown as ViewStyle;
113
75
 
114
76
  return (
115
77
  <View
78
+ onLayout={onLayout}
116
79
  style={[
117
80
  styles.container,
118
- {
119
- width,
120
- height,
121
- borderRadius,
122
- backgroundColor: baseColor,
123
- },
81
+ { width, height, borderRadius, backgroundColor: baseColor },
124
82
  style,
125
83
  ]}
126
84
  >
127
- {/* Shimmer gradient overlay */}
128
85
  <Animated.View
129
- style={[
130
- StyleSheet.absoluteFill,
131
- {
132
- overflow: 'hidden',
133
- borderRadius,
134
- },
135
- ]}
86
+ pointerEvents="none"
87
+ style={[StyleSheet.absoluteFill, animatedStyle]}
136
88
  >
137
- <Animated.View
138
- style={[
139
- styles.shimmer,
140
- {
141
- width: typeof width === 'number' ? width : '100%',
142
- height: '100%',
143
- },
144
- animatedStyle,
145
- ]}
146
- >
147
- <LinearGradient
148
- colors={[baseColor, highlightColor, highlightColor, baseColor]}
149
- start={{ x: 0, y: 0 }}
150
- end={{ x: 1, y: 0 }}
151
- style={StyleSheet.absoluteFill}
152
- />
153
- </Animated.View>
89
+ <View style={gradientStyle} />
154
90
  </Animated.View>
155
91
 
156
- {/* Child content */}
157
92
  {children}
158
93
  </View>
159
94
  );
@@ -163,7 +98,4 @@ const styles = StyleSheet.create({
163
98
  container: {
164
99
  overflow: 'hidden',
165
100
  },
166
- shimmer: {
167
- position: 'absolute',
168
- },
169
101
  });