react-native-varia 0.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.
Files changed (44) hide show
  1. package/README.md +53 -0
  2. package/bin/cli.js +200 -0
  3. package/lib/components/Badge.tsx +96 -0
  4. package/lib/components/Button.tsx +131 -0
  5. package/lib/components/CircleProgress.tsx +180 -0
  6. package/lib/components/Divider.tsx +43 -0
  7. package/lib/components/GradientBackground.tsx +68 -0
  8. package/lib/components/GradientText.tsx +121 -0
  9. package/lib/components/Icon.tsx +13 -0
  10. package/lib/components/IconWrapper.tsx +109 -0
  11. package/lib/components/Input.tsx +120 -0
  12. package/lib/components/Link.tsx +87 -0
  13. package/lib/components/Modal.tsx +157 -0
  14. package/lib/components/ReText.tsx +124 -0
  15. package/lib/components/Slider.tsx +334 -0
  16. package/lib/components/Slideshow.tsx +317 -0
  17. package/lib/components/SlidingDrawer.tsx +307 -0
  18. package/lib/components/Spinner.tsx +44 -0
  19. package/lib/components/Switch.tsx +224 -0
  20. package/lib/components/Text.tsx +107 -0
  21. package/lib/components/index.tsx +83 -0
  22. package/lib/mixins.ts +180 -0
  23. package/lib/patterns/index.tsx +426 -0
  24. package/lib/theme/Badge.recipe.tsx +68 -0
  25. package/lib/theme/Button.recipe-old.tsx +67 -0
  26. package/lib/theme/Button.recipe.tsx +83 -0
  27. package/lib/theme/CircleProgress.recipe.tsx +42 -0
  28. package/lib/theme/GradientBackground.recipe.tsx +38 -0
  29. package/lib/theme/GradientText.recipe.tsx +49 -0
  30. package/lib/theme/Icon.recipe.tsx +122 -0
  31. package/lib/theme/IconWrapper.recipe.tsx +121 -0
  32. package/lib/theme/Input.recipe.tsx +110 -0
  33. package/lib/theme/Link.recipe.tsx +51 -0
  34. package/lib/theme/Modal.recipe.tsx +34 -0
  35. package/lib/theme/ReText.recipe.tsx +7 -0
  36. package/lib/theme/Slider.recipe.tsx +226 -0
  37. package/lib/theme/Slideshow.recipe.tsx +142 -0
  38. package/lib/theme/SlidingDrawer.recipe.tsx +91 -0
  39. package/lib/theme/Spinner.recipe.tsx +8 -0
  40. package/lib/theme/Switch.recipe.tsx +70 -0
  41. package/lib/theme/Text.recipe.tsx +10 -0
  42. package/lib/types.ts +70 -0
  43. package/lib/utils.ts +80 -0
  44. package/package.json +18 -0
@@ -0,0 +1,317 @@
1
+ import {
2
+ Children,
3
+ forwardRef,
4
+ type ReactNode,
5
+ useImperativeHandle,
6
+ useState,
7
+ } from 'react';
8
+ import { View } from 'react-native';
9
+ import Animated, {
10
+ useAnimatedReaction,
11
+ useAnimatedStyle,
12
+ useSharedValue,
13
+ withSpring,
14
+ withTiming,
15
+ } from 'react-native-reanimated';
16
+ import {runOnJS} from 'react-native-worklets';
17
+ import { StyleSheet, UnistylesVariants } from 'react-native-unistyles';
18
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
19
+ import { SlideshowStyles, SlideshowTokens } from '../theme/Slideshow.recipe';
20
+ import { SlidingDrawerTokens } from '../theme/SlidingDrawer.recipe';
21
+ // import type { SpringConfig } from 'react-native-reanimated/lib/typescript/animation/springUtils';
22
+ // import type {
23
+ // SlideshowAnimationVariants,
24
+ // SlideshowColorSchemeVariants,
25
+ // } from '../style/styles/types';
26
+ // import { type Tokens } from '../style/tokenManager';
27
+ // import { useTokens } from '../style/useTokens';
28
+
29
+ export type SlideshowRef = {
30
+ handleNext: () => void | null;
31
+ handlePrev: () => void | null;
32
+ };
33
+
34
+ type SlideshowVariants = UnistylesVariants<typeof SlideshowStyles>;
35
+
36
+ type SlideshowProps = SlideshowVariants & {
37
+ animation?: keyof typeof SlidingDrawerTokens.variants.animation;
38
+ // spacing?: SlideshowSlideContainerSpacing;
39
+ allowGestures?: boolean;
40
+ flex?: number;
41
+ onSlideChange?: (index: number) => void;
42
+ // slideContainerType?: SlideshowSlideContainerColorScheme;
43
+ slideContainerType?: any;
44
+ children: ReactNode;
45
+ ref?: React.RefObject<SlideshowRef>;
46
+ }
47
+
48
+ // const slideshowTokens = getTokens('slideshow');
49
+
50
+ /**
51
+ * Flex Wrapper
52
+ * @param colorScheme ? string: color scheme
53
+ * @param animation ? string: animation props
54
+ * @param allowGestures ? boolean: allow gestures
55
+ * @param flex ? number: flex value
56
+ * @param onSlideChange ? function: callback function
57
+ * @param slideContainerType ? color scheme
58
+ * @param children ? react children
59
+ * @param ref ? react ref
60
+ * @returns Slideshow react component
61
+ */
62
+ const Slideshow = ({
63
+ allowGestures = true,
64
+ flex = 1,
65
+ onSlideChange,
66
+ colorPalette,
67
+ animation = SlideshowTokens.defaultProps.animation,
68
+ spacing = 'none',
69
+ // slideContainerType = 'primary',
70
+ children,
71
+ ref
72
+ } : SlideshowProps,
73
+ ) => {
74
+ // const slideshowTokens = useTokens('slideshow')();
75
+
76
+ // const resolvedColorScheme =
77
+ // colorScheme ??
78
+ // (slideshowTokens.defaultProps
79
+ // .colorScheme as keyof SlideshowColorSchemeVariants);
80
+
81
+ // const resolvedAnimation =
82
+ // animation ??
83
+ // (SlideshowTokens.defaultProps.animation
84
+ // // as keyof SlideshowTokens.variants.animation
85
+ // );
86
+
87
+ // const resolvedSpacing =
88
+ // spacing ??
89
+ // (slideshowTokens.defaultProps
90
+ // .spacing as keyof SlideshowSlideContainerSpacing);
91
+
92
+ const slides = Children.toArray(children);
93
+ const NUM_PAGES = slides.length; // Total number of slides
94
+ const scalingFactor = 1 / NUM_PAGES;
95
+
96
+ // styles.useVariants({
97
+ // colorScheme: resolvedColorScheme,
98
+ // spacing,
99
+ // });
100
+
101
+ SlideshowStyles.useVariants({
102
+ colorPalette,
103
+ });
104
+
105
+ const [containerWidth, setContainerWidth] = useState(0); // To store the container width
106
+
107
+ const slideWidth = 100 / NUM_PAGES; // Each slide's width as a percentage
108
+ const translateX = useSharedValue(0); // Tracks the animated X position
109
+ const currentSlide = useSharedValue(0); // Tracks the current slide index
110
+
111
+ type AnimationType = 'withSpring' | 'withTiming';
112
+
113
+ const animations = {
114
+ withSpring,
115
+ withTiming,
116
+ };
117
+ const animationVariant =
118
+ SlideshowTokens.variants?.animation && animation
119
+ ? SlideshowTokens.variants.animation[animation]
120
+ : {
121
+ type: 'withSpring' as AnimationType, // Type assertion ensures 'withSpring' is a valid value
122
+ props: {
123
+ damping: 15,
124
+ stiffness: 100,
125
+ mass: 1,
126
+ },
127
+ };
128
+
129
+ const animateSlide = (destination: number) => {
130
+ 'worklet';
131
+
132
+ if (
133
+ animationVariant &&
134
+ animationVariant.type &&
135
+ animations[animationVariant.type]
136
+ ) {
137
+ translateX.value = animations[animationVariant.type](
138
+ destination,
139
+ animationVariant.props
140
+ );
141
+
142
+ // Optional callback for onSlideChange
143
+ if (onSlideChange) {
144
+ runOnJS(onSlideChange)((destination / 100) * NUM_PAGES * -1);
145
+ }
146
+ }
147
+ };
148
+
149
+ useAnimatedReaction(
150
+ () => currentSlide.value,
151
+ () => {
152
+ animateSlide(-currentSlide.value * slideWidth);
153
+ }
154
+ );
155
+
156
+ // Move to the previous slide
157
+ const handlePrev = () => {
158
+ 'worklet';
159
+ if (currentSlide.value > 0) {
160
+ currentSlide.value -= 1;
161
+ }
162
+ };
163
+ // Move to the next slide
164
+ const handleNext = () => {
165
+ 'worklet';
166
+ if (currentSlide.value < NUM_PAGES - 1) {
167
+ currentSlide.value += 1;
168
+ }
169
+ };
170
+
171
+ const context = useSharedValue({ x: 0, snapPoint: 0 });
172
+ const velocityThreshold = 500; // Velocity threshold in px/s
173
+
174
+ const slideGesture = Gesture.Pan()
175
+ .enabled(allowGestures)
176
+ .onBegin(() => {
177
+ context.value.x = translateX.value;
178
+ })
179
+ .onUpdate((e) => {
180
+ const pixelToPercentage =
181
+ (e.translationX / containerWidth) * 100 * scalingFactor; // Adjusted conversion (px to %)
182
+ translateX.value = context.value.x + pixelToPercentage;
183
+ })
184
+ .onEnd(({ velocityX, translationX }) => {
185
+ const pixelToPercentage =
186
+ (translationX / containerWidth) * 100 * scalingFactor;
187
+ const slideWidthPercentage = 100 / NUM_PAGES;
188
+
189
+ // Determine current slide index based on translateX
190
+ const currentIndex = Math.round(
191
+ -context.value.x / slideWidthPercentage
192
+ );
193
+
194
+ // Decide snapping based on velocity or distance
195
+ let targetIndex;
196
+ if (Math.abs(velocityX) > velocityThreshold) {
197
+ // Use velocity to decide direction
198
+ targetIndex = velocityX > 0 ? currentIndex - 1 : currentIndex + 1;
199
+ } else {
200
+ // Use the 50% distance rule
201
+ const crossedThreshold =
202
+ Math.abs(pixelToPercentage) > slideWidthPercentage / 2;
203
+ targetIndex =
204
+ crossedThreshold && pixelToPercentage < 0
205
+ ? currentIndex + 1
206
+ : crossedThreshold
207
+ ? currentIndex - 1
208
+ : currentIndex;
209
+ }
210
+
211
+ // Clamp to valid range
212
+ targetIndex = Math.max(0, Math.min(NUM_PAGES - 1, targetIndex));
213
+
214
+ // Animate to the target slide
215
+ animateSlide(-targetIndex * slideWidthPercentage);
216
+
217
+ // Update the currentSlide shared value
218
+ currentSlide.value = targetIndex;
219
+ });
220
+
221
+ // Animated style for the slides container
222
+ const animatedStyle = useAnimatedStyle(() => ({
223
+ transform: [{ translateX: `${translateX.value}%` }],
224
+ }));
225
+
226
+ useImperativeHandle(ref, () => ({
227
+ handlePrev,
228
+ handleNext,
229
+ }));
230
+
231
+ return (
232
+ <View style={styles.flex(flex)}>
233
+ <GestureDetector gesture={slideGesture}>
234
+ <View
235
+ //@ts-ignore
236
+ // TODO: fix type
237
+ style={[styles.container(
238
+ // slideshowTokens.variants
239
+ ),
240
+ SlideshowStyles.container
241
+ ]}
242
+ onLayout={(e) => setContainerWidth(e.nativeEvent.layout.width)}
243
+ >
244
+ <Animated.View
245
+ style={[
246
+ styles.slidesContainer(`${NUM_PAGES * 100}%`),
247
+ animatedStyle,
248
+ ]}
249
+ >
250
+ {slides.map((Slide, index) => (
251
+ <View
252
+ key={index}
253
+ style={[
254
+ styles.slide(
255
+ `${slideWidth}%`,
256
+ // SlideshowTokens.slideContainer.variants
257
+ ),
258
+ SlideshowStyles.slideContainer
259
+ ]}
260
+ >
261
+ {Slide}
262
+ </View>
263
+ ))}
264
+ </Animated.View>
265
+ </View>
266
+ </GestureDetector>
267
+ </View>
268
+ );
269
+ }
270
+
271
+ export default Slideshow;
272
+
273
+ // type SlideshowTokenType = ReturnType<Tokens['slideshow']>; // This is the return of the function
274
+ // type VariantsType = SlideshowTokenType['variants'];
275
+ // type SlideContainerType = SlideshowTokenType['slideContainer']['variants'];
276
+
277
+ const styles = StyleSheet.create({
278
+ flex: (flex) => ({
279
+ flex,
280
+ flexDirection: 'row',
281
+ }),
282
+ container: (
283
+ // variants: VariantsType
284
+ ) => ({
285
+ zIndex: 1,
286
+ width: '100%',
287
+ height: '100%',
288
+ overflow: 'hidden',
289
+ justifyContent: 'flex-start',
290
+ alignItems: 'flex-start',
291
+ backgroundColor: 'white',
292
+ borderRadius: 16,
293
+ // backgroundColor: slideshowTokens.baseStyles?.backgroundColor?.(theme),
294
+ // borderRadius: slideshowTokens.baseStyles?.borderRadius,
295
+ // variants: {
296
+ // colorScheme: variants.colorScheme as any,
297
+ // },
298
+ }),
299
+ slidesContainer: (width) => ({
300
+ flexDirection: 'row',
301
+ width,
302
+ flex: 1,
303
+ }),
304
+ slide: (width,
305
+ // variants: SlideContainerType
306
+ ) => ({
307
+ width,
308
+ flex: 1,
309
+ // height: '100%',
310
+ justifyContent: 'center',
311
+ alignItems: 'center',
312
+ // variants: {
313
+ // colorScheme: variants.colorScheme as any,
314
+ // spacing: variants.spacing as any,
315
+ // },
316
+ }),
317
+ });
@@ -0,0 +1,307 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
3
+ import React, { forwardRef, useImperativeHandle } from 'react';
4
+ import { StyleSheet, UnistylesVariants } from 'react-native-unistyles';
5
+ import Animated, {
6
+ useAnimatedStyle,
7
+ useSharedValue,
8
+ withSpring,
9
+ withTiming,
10
+ type SharedValue,
11
+ } from 'react-native-reanimated';
12
+ import {runOnJS} from 'react-native-worklets';
13
+ // import type { SpringConfig } from 'react-native-reanimated/lib/typescript/animation/springUtils';
14
+
15
+ // import type {
16
+ // SlidingDrawerAnimationVariants,
17
+ // SlidingDrawerColorSchemeVariants,
18
+ // } from '../style/styles/types';
19
+ // import { useTokens } from '../style/useTokens';
20
+ import {SlidingDrawerTokens, SlidingDrawerStyles} from '../theme/SlidingDrawer.recipe';
21
+
22
+ export type SlidingDrawerRef = {
23
+ snapTo: (point: number) => void | null;
24
+ expand: () => void | null;
25
+ collapse: () => void | null;
26
+ };
27
+
28
+ type SlidingDrawerVariants = UnistylesVariants<typeof SlidingDrawerStyles>;
29
+
30
+ type SlidingDrawerProps = SlidingDrawerVariants & {
31
+ // colorScheme?: keyof typeof SlidingDrawerTokens.variants.colorPalette;
32
+ animation?: keyof typeof SlidingDrawerTokens.variants.animation;
33
+ flex?: number;
34
+ direction?: 1 | -1;
35
+ onCollapse?: () => void;
36
+ onExpand?: () => void;
37
+ onSnap?: (point: number) => void;
38
+ snapPoints: number[];
39
+ axis: 'y' | 'x';
40
+ allowGestures?: boolean;
41
+ overlay?: boolean;
42
+ children?: React.ReactNode;
43
+ // style?: StyleProp<ViewStyle>;
44
+ // mixins?: StyleProp<ViewStyle> | StyleProp<ViewStyle>[];
45
+ ref?: React.RefObject<SlidingDrawerRef>;
46
+ }
47
+
48
+ const SlidingDrawer = ({
49
+ colorPalette,
50
+ animation = SlidingDrawerTokens.defaultProps.animation,
51
+ flex = 0,
52
+ direction = 1,
53
+ onCollapse,
54
+ onExpand,
55
+ onSnap,
56
+ snapPoints,
57
+ axis,
58
+ allowGestures = true,
59
+ overlay = false,
60
+ children,
61
+ // style,
62
+ // mixins,
63
+ ref
64
+ }: SlidingDrawerProps
65
+ ) => {
66
+ console.log("🚀 ~ ref:", ref)
67
+ // const slidingDrawerTokens = useTokens('slidingDrawer')();
68
+
69
+ // const resolvedColorScheme =
70
+ // colorScheme ??
71
+ // (slidingDrawerTokens.defaultProps
72
+ // .colorScheme as keyof SlidingDrawerColorSchemeVariants);
73
+
74
+ // const resolvedAnimation =
75
+ // animation ??
76
+ // (slidingDrawerTokens.defaultProps
77
+ // .animation as keyof SlidingDrawerAnimationVariants);
78
+
79
+ SlidingDrawerStyles.useVariants({
80
+ colorPalette,
81
+ // animation,
82
+ });
83
+
84
+ // Adjust points based on direction and axis
85
+ const points = snapPoints.map((point) => point * direction);
86
+
87
+ const translate = useSharedValue(points[0]);
88
+
89
+ const context: SharedValue<{
90
+ position: any;
91
+ snapPoint: number;
92
+ }> = useSharedValue({
93
+ position: points[0], // Default position
94
+ snapPoint: 0, // Default snapPoint
95
+ });
96
+
97
+ const changeDisplay = useSharedValue('none');
98
+ const opacity = useSharedValue(0);
99
+
100
+ const VELOCITY_THRESHOLD = 2000;
101
+
102
+ const updateCurrentSnapPoint = (snapPoint: number) => {
103
+ 'worklet';
104
+ context.value = { position: context.value.position, snapPoint };
105
+ };
106
+
107
+ const animations = {
108
+ withSpring,
109
+ withTiming,
110
+ };
111
+
112
+ const animationVariant =
113
+ SlidingDrawerTokens.variants.animation[animation];
114
+ // const animationVariant = variants.animation[animation];
115
+
116
+ console.log("🚀 ~ animationVariant:", animationVariant)
117
+
118
+ const snapTo = (destination: number) => {
119
+ 'worklet';
120
+
121
+ // Type guard to ensure animationVariant is not undefined
122
+ if (animationVariant && animationVariant.type) {
123
+ translate.value = animations[animationVariant.type](
124
+ points[destination],
125
+ animationVariant.props
126
+ );
127
+ updateCurrentSnapPoint(destination);
128
+ onSnap && runOnJS(onSnap)(destination);
129
+ }
130
+ };
131
+
132
+ const expand = () => {
133
+ snapTo(points.length - 1);
134
+ if (overlay) {
135
+ showOverlay();
136
+ }
137
+ onExpand && runOnJS(onExpand)();
138
+ };
139
+
140
+ const isCollapsed = () => {
141
+ 'worklet';
142
+ return context.value.snapPoint === 0;
143
+ };
144
+
145
+ const collapse = () => {
146
+ snapTo(0);
147
+ if (overlay) {
148
+ hideOverlay();
149
+ }
150
+ onCollapse && runOnJS(onCollapse)();
151
+ };
152
+
153
+ const hideOverlay = () => {
154
+ 'worklet';
155
+ changeDisplay.value = 'none';
156
+ opacity.value = withTiming(0, { duration: 200 });
157
+ };
158
+ const showOverlay = () => {
159
+ 'worklet';
160
+ changeDisplay.value = 'flex';
161
+ opacity.value = withTiming(1, { duration: 200 });
162
+ };
163
+
164
+ useImperativeHandle(ref, () => ({
165
+ expand,
166
+ collapse,
167
+ snapTo,
168
+ isCollapsed,
169
+ }));
170
+
171
+ // const endLimit = direction === 1 ? points[0] : points[points.length - 1];
172
+
173
+ const slideGesture = Gesture.Pan()
174
+ .enabled(allowGestures)
175
+ .onBegin(() => {
176
+ context.value.position = translate.value;
177
+ })
178
+ .onUpdate((event) => {
179
+ const delta = axis === 'y' ? event.translationY : event.translationX;
180
+ translate.value = delta + (context.value.position ?? 0);
181
+ })
182
+ .onEnd(({ velocityX, velocityY, translationX, translationY }) => {
183
+ const velocity = axis === 'y' ? velocityY : velocityX;
184
+ const translation = axis === 'y' ? translationY : translationX;
185
+
186
+ const forwardsThreshold =
187
+ // @ts-ignore
188
+ (points[context.value.snapPoint] +
189
+ // @ts-ignore
190
+ points[context.value.snapPoint + 1]) /
191
+ 2;
192
+ const backwardsThreshold =
193
+ // @ts-ignore
194
+ (points[context.value.snapPoint] +
195
+ // @ts-ignore
196
+ points[context.value.snapPoint - 1]) /
197
+ 2;
198
+
199
+ if (translation * direction < 0) {
200
+ if (
201
+ // @ts-ignore
202
+ ((direction === 1 && translate.value < forwardsThreshold) ||
203
+ // @ts-ignore
204
+ (direction === -1 && translate.value > forwardsThreshold) ||
205
+ velocity * direction < -VELOCITY_THRESHOLD) &&
206
+ context.value.snapPoint < points.length - 1
207
+ ) {
208
+ snapTo(context.value.snapPoint + 1);
209
+ } else {
210
+ snapTo(context.value.snapPoint);
211
+ }
212
+ } else {
213
+ if (
214
+ // @ts-ignore
215
+ ((direction === 1 && translate.value > backwardsThreshold) ||
216
+ // @ts-ignore
217
+ (direction === -1 && translate.value < backwardsThreshold) ||
218
+ velocity * direction > VELOCITY_THRESHOLD) &&
219
+ context.value.snapPoint > 0
220
+ ) {
221
+ snapTo(context.value.snapPoint - 1);
222
+ } else {
223
+ snapTo(context.value.snapPoint);
224
+ }
225
+ }
226
+ })
227
+ .onFinalize(() => {
228
+ if (overlay) {
229
+ if (isCollapsed()) {
230
+ hideOverlay();
231
+ } else {
232
+ showOverlay();
233
+ }
234
+ }
235
+ });
236
+
237
+ const blockAnimatedStyle = useAnimatedStyle(() => {
238
+ return {
239
+ transform: [
240
+ { [axis === 'y' ? 'translateY' : 'translateX']: translate.value },
241
+ ],
242
+ } as any;
243
+ });
244
+
245
+ const displayOverlayStyle = useAnimatedStyle(() => {
246
+ return {
247
+ display: changeDisplay.value,
248
+ opacity: opacity.value,
249
+ } as any;
250
+ });
251
+
252
+ return (
253
+ <>
254
+ {overlay && (
255
+ <Animated.View
256
+ style={[
257
+ {
258
+ ...StyleSheet.absoluteFillObject,
259
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
260
+ },
261
+ displayOverlayStyle,
262
+ ]}
263
+ />
264
+ )}
265
+ <GestureDetector gesture={slideGesture}>
266
+ <Animated.View
267
+ style={[
268
+ styles.container(flex, direction, axis, SlidingDrawerTokens),
269
+ blockAnimatedStyle,
270
+ SlidingDrawerStyles.container,
271
+ // style && styles.customStyle(style),
272
+ // mixins && mixins,
273
+ ]}
274
+ >
275
+ {children}
276
+ </Animated.View>
277
+ </GestureDetector>
278
+ </>
279
+ );
280
+ }
281
+ ;
282
+
283
+ export default SlidingDrawer;
284
+
285
+ const styles = StyleSheet.create({
286
+ container: (flex, direction, axis, slidingDrawerTokens): any => ({
287
+ position: flex === 0 ? 'absolute' : 'relative',
288
+ bottom: axis === 'y' && direction === 1 ? 0 : 'auto',
289
+ top: axis === 'y' && direction === -1 ? 0 : 'auto',
290
+ left: axis === 'x' ? 0 : 'auto',
291
+ flex: flex === 0 ? 1 : flex,
292
+ height: '100%',
293
+ width: '100%',
294
+ backgroundColor: slidingDrawerTokens.defaultProps.backgroundColor,
295
+ borderRadius: slidingDrawerTokens.defaultProps.borderRadius,
296
+ alignItems: 'center',
297
+ justifyContent: 'flex-start',
298
+ boxShadow: slidingDrawerTokens.defaultProps.boxShadow,
299
+ zIndex: 5,
300
+ // variants: {
301
+ // colorScheme: slidingDrawerTokens.variants.colorScheme,
302
+ // },
303
+ }),
304
+ customStyle: (style) => ({
305
+ ...style,
306
+ }),
307
+ });
@@ -0,0 +1,44 @@
1
+ import {
2
+ ActivityIndicator,
3
+ ColorValue,
4
+ type ActivityIndicatorProps,
5
+ type StyleProp,
6
+ type ViewStyle,
7
+ } from 'react-native'
8
+ import {withUnistyles} from 'react-native-unistyles'
9
+ import {ThemeColors} from '../style/types'
10
+ import {SpinnerTokens} from '../theme/Spinner.recipe'
11
+
12
+ interface SpinnerProps extends ActivityIndicatorProps {
13
+ color?: ThemeColors
14
+ size?: number
15
+ style?: StyleProp<ViewStyle>
16
+ mixins?: StyleProp<ViewStyle> | StyleProp<ViewStyle>[]
17
+ colors: Record<string, ColorValue>
18
+ }
19
+
20
+ const BaseSpinner = ({
21
+ size = SpinnerTokens.defaultProps.size,
22
+ color = SpinnerTokens.defaultProps.color,
23
+ style,
24
+ mixins,
25
+ colors,
26
+ ...props
27
+ }: SpinnerProps) => {
28
+ const resolvedColor = color && color in colors ? colors[color] : color
29
+
30
+ return (
31
+ <ActivityIndicator
32
+ color={resolvedColor}
33
+ size={size}
34
+ {...props}
35
+ style={[style && style, mixins && mixins]}
36
+ />
37
+ )
38
+ }
39
+
40
+ const Spinner = withUnistyles(BaseSpinner, theme => ({
41
+ colors: theme.colors,
42
+ }))
43
+
44
+ export default Spinner