react-native-glitter 0.3.0 → 1.0.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
@@ -164,6 +164,8 @@ function ControlledGlitter() {
164
164
  | `mode` | `'normal' \| 'expand' \| 'shrink'` | `'normal'` | Animation mode for the shimmer line |
165
165
  | `position` | `'top' \| 'center' \| 'bottom'` | `'center'` | Position where the line shrinks/expands (for shrink/expand modes) |
166
166
  | `direction` | `'left-to-right' \| 'right-to-left'` | `'left-to-right'` | Direction of the shimmer animation |
167
+ | `iterations` | `number` | `-1` | Number of animation cycles (-1 for infinite) |
168
+ | `onAnimationComplete` | `() => void` | - | Callback when all iterations complete |
167
169
 
168
170
  ## Examples
169
171
 
@@ -237,6 +239,26 @@ function ControlledGlitter() {
237
239
  </Glitter>
238
240
  ```
239
241
 
242
+ ### Limited Iterations with Callback
243
+
244
+ ```tsx
245
+ // Run 3 times then call onAnimationComplete
246
+ <Glitter
247
+ iterations={3}
248
+ onAnimationComplete={() => console.log('Done!')}
249
+ >
250
+ <View style={styles.box} />
251
+ </Glitter>
252
+
253
+ // Run once (useful for loading states)
254
+ <Glitter
255
+ iterations={1}
256
+ onAnimationComplete={() => setLoading(false)}
257
+ >
258
+ <View style={styles.skeleton} />
259
+ </Glitter>
260
+ ```
261
+
240
262
  ## TypeScript
241
263
 
242
264
  This library is written in TypeScript and includes type definitions:
@@ -48,24 +48,46 @@ function generateVerticalSegments(fadeRatioParam) {
48
48
  }
49
49
  return segments;
50
50
  }
51
- export function Glitter({ children, duration = 1500, delay = 400, color = 'rgba(255, 255, 255, 0.8)', angle = 20, shimmerWidth = 60, active = true, style, easing, mode = 'normal', position = 'center', direction = 'left-to-right', }) {
51
+ export function Glitter({ children, duration = 1500, delay = 400, color = 'rgba(255, 255, 255, 0.8)', angle = 20, shimmerWidth = 60, active = true, style, easing, mode = 'normal', position = 'center', direction = 'left-to-right', iterations = -1, onAnimationComplete, }) {
52
52
  const animatedValue = useRef(new Animated.Value(0)).current;
53
53
  const [containerWidth, setContainerWidth] = useState(0);
54
54
  const [containerHeight, setContainerHeight] = useState(0);
55
55
  const animationRef = useRef(null);
56
+ const iterationCount = useRef(0);
56
57
  const defaultEasing = Easing.bezier(0.4, 0, 0.2, 1);
57
58
  const startAnimation = useCallback(() => {
58
59
  if (!active || containerWidth === 0)
59
60
  return;
60
61
  animatedValue.setValue(0);
62
+ iterationCount.current = 0;
61
63
  const timing = Animated.timing(animatedValue, {
62
64
  toValue: 1,
63
65
  duration,
64
66
  useNativeDriver: true,
65
67
  easing: easing ?? defaultEasing,
66
68
  });
67
- animationRef.current = Animated.loop(Animated.sequence([timing, Animated.delay(delay)]));
68
- animationRef.current.start();
69
+ const singleIteration = Animated.sequence([timing, Animated.delay(delay)]);
70
+ const runIteration = () => {
71
+ animatedValue.setValue(0);
72
+ singleIteration.start(({ finished }) => {
73
+ if (finished) {
74
+ iterationCount.current += 1;
75
+ if (iterations === -1 || iterationCount.current < iterations) {
76
+ runIteration();
77
+ }
78
+ else {
79
+ onAnimationComplete?.();
80
+ }
81
+ }
82
+ });
83
+ };
84
+ if (iterations === -1) {
85
+ animationRef.current = Animated.loop(singleIteration);
86
+ animationRef.current.start();
87
+ }
88
+ else {
89
+ runIteration();
90
+ }
69
91
  return () => {
70
92
  animationRef.current?.stop();
71
93
  };
@@ -77,6 +99,8 @@ export function Glitter({ children, duration = 1500, delay = 400, color = 'rgba(
77
99
  animatedValue,
78
100
  easing,
79
101
  defaultEasing,
102
+ iterations,
103
+ onAnimationComplete,
80
104
  ]);
81
105
  useEffect(() => {
82
106
  const cleanup = startAnimation();
@@ -166,12 +190,14 @@ export function Glitter({ children, duration = 1500, delay = 400, color = 'rgba(
166
190
  ]
167
191
  : [{ translateY: startOffset }],
168
192
  },
169
- ], children: (isAnimated ? animatedSegments : normalSegments).map((segment, vIndex) => (_jsx(View, { style: {
170
- width: '100%',
171
- height: lineHeight * segment.heightRatio,
172
- backgroundColor: color,
173
- opacity: layer.opacity * segment.opacity,
174
- } }, vIndex))) }, layerIndex))) }) }))] }));
193
+ ], children: (isAnimated ? animatedSegments : normalSegments).map((segment, vIndex) => (_jsx(View, { style: [
194
+ styles.segment,
195
+ {
196
+ height: lineHeight * segment.heightRatio,
197
+ backgroundColor: color,
198
+ opacity: layer.opacity * segment.opacity,
199
+ },
200
+ ] }, vIndex))) }, layerIndex))) }) }))] }));
175
201
  }
176
202
  const styles = StyleSheet.create({
177
203
  container: {
@@ -193,5 +219,8 @@ const styles = StyleSheet.create({
193
219
  position: 'absolute',
194
220
  flexDirection: 'column',
195
221
  },
222
+ segment: {
223
+ width: '100%',
224
+ },
196
225
  });
197
226
  export default Glitter;
@@ -16,6 +16,8 @@ export interface GlitterProps {
16
16
  mode?: GlitterMode;
17
17
  position?: GlitterPosition;
18
18
  direction?: GlitterDirection;
19
+ iterations?: number;
20
+ onAnimationComplete?: () => void;
19
21
  }
20
- export declare function Glitter({ children, duration, delay, color, angle, shimmerWidth, active, style, easing, mode, position, direction, }: GlitterProps): ReactElement;
22
+ export declare function Glitter({ children, duration, delay, color, angle, shimmerWidth, active, style, easing, mode, position, direction, iterations, onAnimationComplete, }: GlitterProps): ReactElement;
21
23
  export default Glitter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-glitter",
3
- "version": "0.3.0",
3
+ "version": "1.0.1",
4
4
  "description": "A beautiful shimmer/glitter effect component for React Native. Add a sparkling diagonal shine animation to any component!",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
package/src/index.tsx CHANGED
@@ -35,6 +35,8 @@ export interface GlitterProps {
35
35
  mode?: GlitterMode;
36
36
  position?: GlitterPosition;
37
37
  direction?: GlitterDirection;
38
+ iterations?: number;
39
+ onAnimationComplete?: () => void;
38
40
  }
39
41
 
40
42
  function generateGlitterOpacities(count: number, peak: number = 1): number[] {
@@ -111,11 +113,16 @@ export function Glitter({
111
113
  mode = 'normal',
112
114
  position = 'center',
113
115
  direction = 'left-to-right',
116
+ iterations = -1,
117
+ onAnimationComplete,
114
118
  }: GlitterProps): ReactElement {
115
119
  const animatedValue = useRef(new Animated.Value(0)).current;
116
120
  const [containerWidth, setContainerWidth] = useState(0);
117
121
  const [containerHeight, setContainerHeight] = useState(0);
118
- const animationRef = useRef<ReturnType<typeof Animated.loop> | null>(null);
122
+ const animationRef = useRef<{ start: () => void; stop: () => void } | null>(
123
+ null
124
+ );
125
+ const iterationCount = useRef(0);
119
126
 
120
127
  const defaultEasing = Easing.bezier(0.4, 0, 0.2, 1);
121
128
 
@@ -123,6 +130,7 @@ export function Glitter({
123
130
  if (!active || containerWidth === 0) return;
124
131
 
125
132
  animatedValue.setValue(0);
133
+ iterationCount.current = 0;
126
134
 
127
135
  const timing = Animated.timing(animatedValue, {
128
136
  toValue: 1,
@@ -131,11 +139,28 @@ export function Glitter({
131
139
  easing: easing ?? defaultEasing,
132
140
  });
133
141
 
134
- animationRef.current = Animated.loop(
135
- Animated.sequence([timing, Animated.delay(delay)])
136
- );
142
+ const singleIteration = Animated.sequence([timing, Animated.delay(delay)]);
143
+
144
+ const runIteration = () => {
145
+ animatedValue.setValue(0);
146
+ singleIteration.start(({ finished }) => {
147
+ if (finished) {
148
+ iterationCount.current += 1;
149
+ if (iterations === -1 || iterationCount.current < iterations) {
150
+ runIteration();
151
+ } else {
152
+ onAnimationComplete?.();
153
+ }
154
+ }
155
+ });
156
+ };
137
157
 
138
- animationRef.current.start();
158
+ if (iterations === -1) {
159
+ animationRef.current = Animated.loop(singleIteration);
160
+ animationRef.current.start();
161
+ } else {
162
+ runIteration();
163
+ }
139
164
 
140
165
  return () => {
141
166
  animationRef.current?.stop();
@@ -148,6 +173,8 @@ export function Glitter({
148
173
  animatedValue,
149
174
  easing,
150
175
  defaultEasing,
176
+ iterations,
177
+ onAnimationComplete,
151
178
  ]);
152
179
 
153
180
  useEffect(() => {
@@ -273,12 +300,14 @@ export function Glitter({
273
300
  (segment, vIndex) => (
274
301
  <View
275
302
  key={vIndex}
276
- style={{
277
- width: '100%',
278
- height: lineHeight * segment.heightRatio,
279
- backgroundColor: color,
280
- opacity: layer.opacity * segment.opacity,
281
- }}
303
+ style={[
304
+ styles.segment,
305
+ {
306
+ height: lineHeight * segment.heightRatio,
307
+ backgroundColor: color,
308
+ opacity: layer.opacity * segment.opacity,
309
+ },
310
+ ]}
282
311
  />
283
312
  )
284
313
  )}
@@ -311,6 +340,9 @@ const styles = StyleSheet.create({
311
340
  position: 'absolute',
312
341
  flexDirection: 'column',
313
342
  },
343
+ segment: {
344
+ width: '100%',
345
+ },
314
346
  });
315
347
 
316
348
  export default Glitter;