react-native-glitter 1.0.4 → 1.0.5
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 +39 -0
- package/lib/module/index.js +21 -3
- package/lib/typescript/src/index.d.ts +13 -3
- package/package.json +1 -1
- package/src/index.tsx +63 -21
package/README.md
CHANGED
|
@@ -264,6 +264,44 @@ function ControlledGlitter() {
|
|
|
264
264
|
</Glitter>
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
+
## Ref API
|
|
268
|
+
|
|
269
|
+
You can control the animation programmatically using a ref:
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
import { useRef } from 'react';
|
|
273
|
+
import { Glitter, type GlitterRef } from 'react-native-glitter';
|
|
274
|
+
|
|
275
|
+
function MyComponent() {
|
|
276
|
+
const glitterRef = useRef<GlitterRef>(null);
|
|
277
|
+
|
|
278
|
+
const handleStart = () => glitterRef.current?.start();
|
|
279
|
+
const handleStop = () => glitterRef.current?.stop();
|
|
280
|
+
const handleRestart = () => glitterRef.current?.restart();
|
|
281
|
+
const checkStatus = () => console.log(glitterRef.current?.isAnimating());
|
|
282
|
+
|
|
283
|
+
return (
|
|
284
|
+
<>
|
|
285
|
+
<Glitter ref={glitterRef} active={false}>
|
|
286
|
+
<View style={styles.box} />
|
|
287
|
+
</Glitter>
|
|
288
|
+
<Button title="Start" onPress={handleStart} />
|
|
289
|
+
<Button title="Stop" onPress={handleStop} />
|
|
290
|
+
<Button title="Restart" onPress={handleRestart} />
|
|
291
|
+
</>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Ref Methods
|
|
297
|
+
|
|
298
|
+
| Method | Return | Description |
|
|
299
|
+
|--------|--------|-------------|
|
|
300
|
+
| `start()` | `void` | Start the shimmer animation |
|
|
301
|
+
| `stop()` | `void` | Stop the shimmer animation |
|
|
302
|
+
| `restart()` | `void` | Restart the animation from the beginning |
|
|
303
|
+
| `isAnimating()` | `boolean` | Check if animation is currently running |
|
|
304
|
+
|
|
267
305
|
## TypeScript
|
|
268
306
|
|
|
269
307
|
This library is written in TypeScript and includes type definitions:
|
|
@@ -272,6 +310,7 @@ This library is written in TypeScript and includes type definitions:
|
|
|
272
310
|
import {
|
|
273
311
|
Glitter,
|
|
274
312
|
type GlitterProps,
|
|
313
|
+
type GlitterRef,
|
|
275
314
|
type GlitterMode,
|
|
276
315
|
type GlitterPosition,
|
|
277
316
|
type GlitterDirection,
|
package/lib/module/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState, useCallback, useMemo, memo, } from 'react';
|
|
2
|
+
import { useEffect, useRef, useState, useCallback, useMemo, memo, useImperativeHandle, forwardRef, } from 'react';
|
|
3
3
|
import { View, Animated, StyleSheet, Easing, } from 'react-native';
|
|
4
4
|
function generateGlitterOpacities(count, peak = 1) {
|
|
5
5
|
const opacities = [];
|
|
@@ -52,7 +52,7 @@ const HEIGHT_MULTIPLIER = 1.5;
|
|
|
52
52
|
const NORMAL_FADE_RATIO = (HEIGHT_MULTIPLIER - 1) / HEIGHT_MULTIPLIER / 2;
|
|
53
53
|
const ANIMATED_SEGMENTS = generateVerticalSegments(0.25);
|
|
54
54
|
const NORMAL_SEGMENTS = generateVerticalSegments(NORMAL_FADE_RATIO);
|
|
55
|
-
function GlitterComponent({ 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, onAnimationStart, onAnimationComplete, testID, accessibilityLabel, accessible = true, }) {
|
|
55
|
+
function GlitterComponent({ 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, onAnimationStart, onAnimationComplete, testID, accessibilityLabel, accessible = true, }, ref) {
|
|
56
56
|
const animatedValue = useRef(new Animated.Value(0)).current;
|
|
57
57
|
const [containerWidth, setContainerWidth] = useState(0);
|
|
58
58
|
const [containerHeight, setContainerHeight] = useState(0);
|
|
@@ -68,6 +68,23 @@ function GlitterComponent({ children, duration = 1500, delay = 400, color = 'rgb
|
|
|
68
68
|
currentIterationRef.current?.stop();
|
|
69
69
|
currentIterationRef.current = null;
|
|
70
70
|
}, []);
|
|
71
|
+
const restartAnimation = useCallback(() => {
|
|
72
|
+
stopAnimation();
|
|
73
|
+
animatedValue.setValue(0);
|
|
74
|
+
// Trigger re-render to start animation
|
|
75
|
+
setContainerWidth((prev) => prev);
|
|
76
|
+
}, [stopAnimation, animatedValue]);
|
|
77
|
+
useImperativeHandle(ref, () => ({
|
|
78
|
+
start: () => {
|
|
79
|
+
if (!isAnimatingRef.current && containerWidth > 0) {
|
|
80
|
+
// Force start by triggering the effect
|
|
81
|
+
setContainerWidth((prev) => prev);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
stop: stopAnimation,
|
|
85
|
+
restart: restartAnimation,
|
|
86
|
+
isAnimating: () => isAnimatingRef.current,
|
|
87
|
+
}), [stopAnimation, restartAnimation, containerWidth]);
|
|
71
88
|
const startAnimation = useCallback(() => {
|
|
72
89
|
if (!active || containerWidth === 0)
|
|
73
90
|
return;
|
|
@@ -231,5 +248,6 @@ const styles = StyleSheet.create({
|
|
|
231
248
|
width: '100%',
|
|
232
249
|
},
|
|
233
250
|
});
|
|
234
|
-
|
|
251
|
+
const ForwardedGlitter = forwardRef(GlitterComponent);
|
|
252
|
+
export const Glitter = memo(ForwardedGlitter);
|
|
235
253
|
export default Glitter;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ReactNode
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
2
|
import { type StyleProp, type ViewStyle } from 'react-native';
|
|
3
3
|
export type GlitterMode = 'normal' | 'expand' | 'shrink';
|
|
4
4
|
export type GlitterPosition = 'top' | 'center' | 'bottom';
|
|
@@ -26,6 +26,16 @@ export interface GlitterProps {
|
|
|
26
26
|
/** Whether the component is accessible (default: true) */
|
|
27
27
|
accessible?: boolean;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
export
|
|
29
|
+
/** Ref methods exposed by Glitter component */
|
|
30
|
+
export interface GlitterRef {
|
|
31
|
+
/** Start the shimmer animation */
|
|
32
|
+
start: () => void;
|
|
33
|
+
/** Stop the shimmer animation */
|
|
34
|
+
stop: () => void;
|
|
35
|
+
/** Restart the shimmer animation from the beginning */
|
|
36
|
+
restart: () => void;
|
|
37
|
+
/** Check if animation is currently running */
|
|
38
|
+
isAnimating: () => boolean;
|
|
39
|
+
}
|
|
40
|
+
export declare const Glitter: import("react").NamedExoticComponent<GlitterProps & import("react").RefAttributes<GlitterRef>>;
|
|
31
41
|
export default Glitter;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-glitter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
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
|
@@ -5,8 +5,11 @@ import {
|
|
|
5
5
|
useCallback,
|
|
6
6
|
useMemo,
|
|
7
7
|
memo,
|
|
8
|
+
useImperativeHandle,
|
|
9
|
+
forwardRef,
|
|
8
10
|
type ReactNode,
|
|
9
11
|
type ReactElement,
|
|
12
|
+
type ForwardedRef,
|
|
10
13
|
} from 'react';
|
|
11
14
|
import {
|
|
12
15
|
View,
|
|
@@ -48,6 +51,18 @@ export interface GlitterProps {
|
|
|
48
51
|
accessible?: boolean;
|
|
49
52
|
}
|
|
50
53
|
|
|
54
|
+
/** Ref methods exposed by Glitter component */
|
|
55
|
+
export interface GlitterRef {
|
|
56
|
+
/** Start the shimmer animation */
|
|
57
|
+
start: () => void;
|
|
58
|
+
/** Stop the shimmer animation */
|
|
59
|
+
stop: () => void;
|
|
60
|
+
/** Restart the shimmer animation from the beginning */
|
|
61
|
+
restart: () => void;
|
|
62
|
+
/** Check if animation is currently running */
|
|
63
|
+
isAnimating: () => boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
51
66
|
function generateGlitterOpacities(count: number, peak: number = 1): number[] {
|
|
52
67
|
const opacities: number[] = [];
|
|
53
68
|
const center = (count - 1) / 2;
|
|
@@ -114,26 +129,29 @@ const NORMAL_FADE_RATIO = (HEIGHT_MULTIPLIER - 1) / HEIGHT_MULTIPLIER / 2;
|
|
|
114
129
|
const ANIMATED_SEGMENTS = generateVerticalSegments(0.25);
|
|
115
130
|
const NORMAL_SEGMENTS = generateVerticalSegments(NORMAL_FADE_RATIO);
|
|
116
131
|
|
|
117
|
-
function GlitterComponent(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
function GlitterComponent(
|
|
133
|
+
{
|
|
134
|
+
children,
|
|
135
|
+
duration = 1500,
|
|
136
|
+
delay = 400,
|
|
137
|
+
color = 'rgba(255, 255, 255, 0.8)',
|
|
138
|
+
angle = 20,
|
|
139
|
+
shimmerWidth = 60,
|
|
140
|
+
active = true,
|
|
141
|
+
style,
|
|
142
|
+
easing,
|
|
143
|
+
mode = 'normal',
|
|
144
|
+
position = 'center',
|
|
145
|
+
direction = 'left-to-right',
|
|
146
|
+
iterations = -1,
|
|
147
|
+
onAnimationStart,
|
|
148
|
+
onAnimationComplete,
|
|
149
|
+
testID,
|
|
150
|
+
accessibilityLabel,
|
|
151
|
+
accessible = true,
|
|
152
|
+
}: GlitterProps,
|
|
153
|
+
ref: ForwardedRef<GlitterRef>
|
|
154
|
+
): ReactElement {
|
|
137
155
|
const animatedValue = useRef(new Animated.Value(0)).current;
|
|
138
156
|
const [containerWidth, setContainerWidth] = useState(0);
|
|
139
157
|
const [containerHeight, setContainerHeight] = useState(0);
|
|
@@ -154,6 +172,29 @@ function GlitterComponent({
|
|
|
154
172
|
currentIterationRef.current = null;
|
|
155
173
|
}, []);
|
|
156
174
|
|
|
175
|
+
const restartAnimation = useCallback(() => {
|
|
176
|
+
stopAnimation();
|
|
177
|
+
animatedValue.setValue(0);
|
|
178
|
+
// Trigger re-render to start animation
|
|
179
|
+
setContainerWidth((prev) => prev);
|
|
180
|
+
}, [stopAnimation, animatedValue]);
|
|
181
|
+
|
|
182
|
+
useImperativeHandle(
|
|
183
|
+
ref,
|
|
184
|
+
() => ({
|
|
185
|
+
start: () => {
|
|
186
|
+
if (!isAnimatingRef.current && containerWidth > 0) {
|
|
187
|
+
// Force start by triggering the effect
|
|
188
|
+
setContainerWidth((prev) => prev);
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
stop: stopAnimation,
|
|
192
|
+
restart: restartAnimation,
|
|
193
|
+
isAnimating: () => isAnimatingRef.current,
|
|
194
|
+
}),
|
|
195
|
+
[stopAnimation, restartAnimation, containerWidth]
|
|
196
|
+
);
|
|
197
|
+
|
|
157
198
|
const startAnimation = useCallback(() => {
|
|
158
199
|
if (!active || containerWidth === 0) return;
|
|
159
200
|
|
|
@@ -404,6 +445,7 @@ const styles = StyleSheet.create({
|
|
|
404
445
|
},
|
|
405
446
|
});
|
|
406
447
|
|
|
407
|
-
|
|
448
|
+
const ForwardedGlitter = forwardRef(GlitterComponent);
|
|
449
|
+
export const Glitter = memo(ForwardedGlitter);
|
|
408
450
|
|
|
409
451
|
export default Glitter;
|