@dryanovski/react-native-components 1.0.7 → 1.0.9
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/lib/module/components/Accordion/Accordion.js +58 -0
- package/lib/module/components/Accordion/Accordion.js.map +1 -0
- package/lib/module/components/Accordion/AccordionContext.js +12 -0
- package/lib/module/components/Accordion/AccordionContext.js.map +1 -0
- package/lib/module/components/Accordion/AccordionItem.js +50 -0
- package/lib/module/components/Accordion/AccordionItem.js.map +1 -0
- package/lib/module/components/Accordion/style.js +11 -0
- package/lib/module/components/Accordion/style.js.map +1 -0
- package/lib/module/components/Accordion/type.js +4 -0
- package/lib/module/components/Accordion/type.js.map +1 -0
- package/lib/module/components/Button/Button.js.map +1 -1
- package/lib/module/components/Button/DangerButton.js.map +1 -1
- package/lib/module/components/Button/GhostButton.js.map +1 -1
- package/lib/module/components/Button/PrimaryButton.js.map +1 -1
- package/lib/module/components/Button/SecondaryButton.js.map +1 -1
- package/lib/module/components/Collapse/Collapse.js +114 -0
- package/lib/module/components/Collapse/Collapse.js.map +1 -0
- package/lib/module/components/Collapse/index.js +5 -0
- package/lib/module/components/Collapse/index.js.map +1 -0
- package/lib/module/components/Collapse/types.js +4 -0
- package/lib/module/components/Collapse/types.js.map +1 -0
- package/lib/module/components/Divider/Divider.js +33 -0
- package/lib/module/components/Divider/Divider.js.map +1 -0
- package/lib/module/components/Divider/styles.js +2 -0
- package/lib/module/components/Divider/styles.js.map +1 -0
- package/lib/module/components/Divider/types.js +4 -0
- package/lib/module/components/Divider/types.js.map +1 -0
- package/lib/module/components/Layout/HStack.js +24 -0
- package/lib/module/components/Layout/HStack.js.map +1 -0
- package/lib/module/components/Layout/VStack.js +24 -0
- package/lib/module/components/Layout/VStack.js.map +1 -0
- package/lib/module/components/Layout/layout.types.js +4 -0
- package/lib/module/components/Layout/layout.types.js.map +1 -0
- package/lib/module/index.js +22 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/components/Accordion/Accordion.d.ts +4 -0
- package/lib/typescript/src/components/Accordion/Accordion.d.ts.map +1 -0
- package/lib/typescript/src/components/Accordion/AccordionContext.d.ts +12 -0
- package/lib/typescript/src/components/Accordion/AccordionContext.d.ts.map +1 -0
- package/lib/typescript/src/components/Accordion/AccordionItem.d.ts +5 -0
- package/lib/typescript/src/components/Accordion/AccordionItem.d.ts.map +1 -0
- package/lib/typescript/src/components/Accordion/style.d.ts +8 -0
- package/lib/typescript/src/components/Accordion/style.d.ts.map +1 -0
- package/lib/typescript/src/components/Accordion/type.d.ts +56 -0
- package/lib/typescript/src/components/Accordion/type.d.ts.map +1 -0
- package/lib/typescript/src/components/Button/Button.d.ts +0 -2
- package/lib/typescript/src/components/Button/Button.d.ts.map +1 -1
- package/lib/typescript/src/components/Button/DangerButton.d.ts.map +1 -1
- package/lib/typescript/src/components/Button/GhostButton.d.ts.map +1 -1
- package/lib/typescript/src/components/Button/PrimaryButton.d.ts.map +1 -1
- package/lib/typescript/src/components/Button/SecondaryButton.d.ts.map +1 -1
- package/lib/typescript/src/components/Button/types.d.ts +11 -0
- package/lib/typescript/src/components/Button/types.d.ts.map +1 -1
- package/lib/typescript/src/components/Collapse/Collapse.d.ts +14 -0
- package/lib/typescript/src/components/Collapse/Collapse.d.ts.map +1 -0
- package/lib/typescript/src/components/Collapse/index.d.ts +3 -0
- package/lib/typescript/src/components/Collapse/index.d.ts.map +1 -0
- package/lib/typescript/src/components/Collapse/types.d.ts +51 -0
- package/lib/typescript/src/components/Collapse/types.d.ts.map +1 -0
- package/lib/typescript/src/components/Divider/Divider.d.ts +5 -0
- package/lib/typescript/src/components/Divider/Divider.d.ts.map +1 -0
- package/lib/typescript/src/components/Divider/styles.d.ts +1 -0
- package/lib/typescript/src/components/Divider/styles.d.ts.map +1 -0
- package/lib/typescript/src/components/Divider/types.d.ts +31 -0
- package/lib/typescript/src/components/Divider/types.d.ts.map +1 -0
- package/lib/typescript/src/components/Layout/HStack.d.ts +4 -0
- package/lib/typescript/src/components/Layout/HStack.d.ts.map +1 -0
- package/lib/typescript/src/components/Layout/VStack.d.ts +4 -0
- package/lib/typescript/src/components/Layout/VStack.d.ts.map +1 -0
- package/lib/typescript/src/components/Layout/layout.types.d.ts +8 -0
- package/lib/typescript/src/components/Layout/layout.types.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +20 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +75 -0
- package/src/components/Accordion/AccordionContext.tsx +22 -0
- package/src/components/Accordion/AccordionItem.tsx +60 -0
- package/src/components/Accordion/style.ts +10 -0
- package/src/components/Accordion/type.ts +65 -0
- package/src/components/Button/Button.tsx +1 -3
- package/src/components/Button/DangerButton.tsx +2 -2
- package/src/components/Button/GhostButton.tsx +2 -2
- package/src/components/Button/PrimaryButton.tsx +2 -2
- package/src/components/Button/SecondaryButton.tsx +2 -2
- package/src/components/Button/types.ts +12 -0
- package/src/components/Collapse/Collapse.tsx +126 -0
- package/src/components/Collapse/index.ts +3 -0
- package/src/components/Collapse/types.ts +62 -0
- package/src/components/Divider/Divider.tsx +28 -0
- package/src/components/Divider/styles.ts +0 -0
- package/src/components/Divider/types.ts +36 -0
- package/src/components/Layout/HStack.tsx +19 -0
- package/src/components/Layout/VStack.tsx +19 -0
- package/src/components/Layout/layout.types.ts +9 -0
- package/src/index.tsx +22 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState, type FC } from 'react';
|
|
2
|
+
import { View, type LayoutChangeEvent } from 'react-native';
|
|
3
|
+
import Animated, {
|
|
4
|
+
useAnimatedStyle,
|
|
5
|
+
useSharedValue,
|
|
6
|
+
withSpring,
|
|
7
|
+
withTiming,
|
|
8
|
+
} from 'react-native-reanimated';
|
|
9
|
+
import type { CollapseProps } from './types';
|
|
10
|
+
|
|
11
|
+
const DEFAULT_ANIMATION = { type: 'timing' as const, duration: 100 };
|
|
12
|
+
const DEFAULT_SPRING = { damping: 20, stiffness: 300 };
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Collapse - A reusable component for smooth expand/collapse animations
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <Collapse isExpanded={isOpen}>
|
|
20
|
+
* <Text>Your content here</Text>
|
|
21
|
+
* </Collapse>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export const Collapse: FC<CollapseProps> = ({
|
|
25
|
+
isExpanded,
|
|
26
|
+
children,
|
|
27
|
+
animationConfig,
|
|
28
|
+
style,
|
|
29
|
+
contentStyle,
|
|
30
|
+
onMeasured,
|
|
31
|
+
}) => {
|
|
32
|
+
const [contentHeight, setContentHeight] = useState<number | null>(null);
|
|
33
|
+
const [shouldRender, setShouldRender] = useState(isExpanded);
|
|
34
|
+
const heightValue = useSharedValue<number | 'auto'>(isExpanded ? 'auto' : 0);
|
|
35
|
+
const opacityValue = useSharedValue(isExpanded ? 1 : 0);
|
|
36
|
+
|
|
37
|
+
const config = animationConfig || DEFAULT_ANIMATION;
|
|
38
|
+
const isSpring = config.type === 'spring';
|
|
39
|
+
const duration = config.duration || 100;
|
|
40
|
+
|
|
41
|
+
// Measure content height
|
|
42
|
+
const onLayout = useCallback(
|
|
43
|
+
(event: LayoutChangeEvent) => {
|
|
44
|
+
const { height } = event.nativeEvent.layout;
|
|
45
|
+
if (height > 0 && contentHeight !== height) {
|
|
46
|
+
setContentHeight(height);
|
|
47
|
+
onMeasured?.(height);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
[contentHeight, onMeasured]
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// Animate on expand/collapse
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
// Show component when expanding
|
|
56
|
+
if (isExpanded) {
|
|
57
|
+
setShouldRender(true);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Wait for measurement before animating
|
|
61
|
+
if (!contentHeight) {
|
|
62
|
+
heightValue.value = isExpanded ? 'auto' : 0;
|
|
63
|
+
opacityValue.value = isExpanded ? 1 : 0;
|
|
64
|
+
if (!isExpanded) setShouldRender(false);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Run animation
|
|
69
|
+
const targetHeight = isExpanded ? contentHeight : 0;
|
|
70
|
+
const targetOpacity = isExpanded ? 1 : 0;
|
|
71
|
+
|
|
72
|
+
if (isSpring) {
|
|
73
|
+
const springConfig = config.springConfig || DEFAULT_SPRING;
|
|
74
|
+
heightValue.value = withSpring(targetHeight, springConfig);
|
|
75
|
+
opacityValue.value = withSpring(targetOpacity, springConfig);
|
|
76
|
+
|
|
77
|
+
// Remove from DOM after collapse animation
|
|
78
|
+
if (!isExpanded) {
|
|
79
|
+
const stiffness = springConfig.stiffness || 300;
|
|
80
|
+
const damping = springConfig.damping || 20;
|
|
81
|
+
const settleTime = (1000 / stiffness) * damping * 10;
|
|
82
|
+
setTimeout(() => setShouldRender(false), settleTime);
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
const timingConfig =
|
|
86
|
+
'timingConfig' in config && config.timingConfig
|
|
87
|
+
? config.timingConfig
|
|
88
|
+
: { duration };
|
|
89
|
+
heightValue.value = withTiming(targetHeight, timingConfig);
|
|
90
|
+
opacityValue.value = withTiming(targetOpacity, timingConfig);
|
|
91
|
+
|
|
92
|
+
// Remove from DOM after collapse animation
|
|
93
|
+
if (!isExpanded) {
|
|
94
|
+
setTimeout(() => setShouldRender(false), duration);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}, [
|
|
98
|
+
isExpanded,
|
|
99
|
+
contentHeight,
|
|
100
|
+
isSpring,
|
|
101
|
+
duration,
|
|
102
|
+
config,
|
|
103
|
+
heightValue,
|
|
104
|
+
opacityValue,
|
|
105
|
+
]);
|
|
106
|
+
|
|
107
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
108
|
+
height: heightValue.value,
|
|
109
|
+
opacity: opacityValue.value,
|
|
110
|
+
overflow: 'hidden',
|
|
111
|
+
}));
|
|
112
|
+
|
|
113
|
+
if (!shouldRender) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<Animated.View style={[animatedStyle, style]}>
|
|
119
|
+
<View onLayout={onLayout} style={contentStyle}>
|
|
120
|
+
{children}
|
|
121
|
+
</View>
|
|
122
|
+
</Animated.View>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
Collapse.displayName = 'Collapse';
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
2
|
+
import type { WithSpringConfig, WithTimingConfig } from 'react-native-reanimated';
|
|
3
|
+
|
|
4
|
+
export type AnimationType = 'timing' | 'spring';
|
|
5
|
+
|
|
6
|
+
export type AnimationConfig = {
|
|
7
|
+
/**
|
|
8
|
+
* Type of animation to use.
|
|
9
|
+
* @default 'timing'
|
|
10
|
+
*/
|
|
11
|
+
type?: AnimationType;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Duration of the animation in milliseconds (for timing animation).
|
|
15
|
+
* @default 100
|
|
16
|
+
*/
|
|
17
|
+
duration?: number;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Timing animation configuration.
|
|
21
|
+
*/
|
|
22
|
+
timingConfig?: WithTimingConfig;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Spring animation configuration.
|
|
26
|
+
*/
|
|
27
|
+
springConfig?: WithSpringConfig;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type CollapseProps = {
|
|
31
|
+
/**
|
|
32
|
+
* Whether the content is expanded or collapsed.
|
|
33
|
+
*/
|
|
34
|
+
isExpanded: boolean;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Content to animate.
|
|
38
|
+
*/
|
|
39
|
+
children: React.ReactNode;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Animation configuration.
|
|
43
|
+
* @default { type: 'timing', duration: 100 }
|
|
44
|
+
*/
|
|
45
|
+
animationConfig?: AnimationConfig;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Style for the animated container.
|
|
49
|
+
*/
|
|
50
|
+
style?: StyleProp<ViewStyle>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Style for the content wrapper.
|
|
54
|
+
*/
|
|
55
|
+
contentStyle?: StyleProp<ViewStyle>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Callback when measurement is complete.
|
|
59
|
+
*/
|
|
60
|
+
onMeasured?: (height: number) => void;
|
|
61
|
+
};
|
|
62
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
import { View, type ViewStyle } from 'react-native';
|
|
3
|
+
import type { ViewRef } from '../../types/general.types';
|
|
4
|
+
import type { DividerProps } from './types';
|
|
5
|
+
|
|
6
|
+
export const Divider = forwardRef<ViewRef, DividerProps>((props, ref) => {
|
|
7
|
+
const {
|
|
8
|
+
thickness = 1,
|
|
9
|
+
color = '#c4c4c4',
|
|
10
|
+
orientation = 'horizontal',
|
|
11
|
+
length = '100%',
|
|
12
|
+
style,
|
|
13
|
+
...rest
|
|
14
|
+
} = props;
|
|
15
|
+
|
|
16
|
+
const dividerStyle = {
|
|
17
|
+
backgroundColor: color,
|
|
18
|
+
...(orientation === 'vertical'
|
|
19
|
+
? { width: thickness, height: length }
|
|
20
|
+
: { height: thickness, width: length }),
|
|
21
|
+
} as ViewStyle;
|
|
22
|
+
|
|
23
|
+
return <View ref={ref} style={[dividerStyle, style]} {...rest} />;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
Divider.displayName = 'Divider';
|
|
27
|
+
|
|
28
|
+
export default Divider;
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { StyleProp, ViewProps, ViewStyle } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export type DividerThickness = 1 | 5 | 10;
|
|
4
|
+
|
|
5
|
+
export type DividerOrientation = 'horizontal' | 'vertical';
|
|
6
|
+
|
|
7
|
+
export interface DividerProps extends ViewProps {
|
|
8
|
+
/**
|
|
9
|
+
* Style for the divider component.
|
|
10
|
+
* Optional.
|
|
11
|
+
*/
|
|
12
|
+
style?: StyleProp<ViewStyle>;
|
|
13
|
+
/**
|
|
14
|
+
* The thickness of the divider.
|
|
15
|
+
* @default 1
|
|
16
|
+
*/
|
|
17
|
+
thickness?: DividerThickness;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The color of the divider.
|
|
21
|
+
* @default '#000'
|
|
22
|
+
*/
|
|
23
|
+
color?: string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The orientation of the divider.
|
|
27
|
+
* @default 'horizontal'
|
|
28
|
+
*/
|
|
29
|
+
orientation?: DividerOrientation;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The length of the divider.
|
|
33
|
+
* @default '100%'
|
|
34
|
+
*/
|
|
35
|
+
length?: number | string;
|
|
36
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import type { ViewRef } from '../../types/general.types';
|
|
4
|
+
import Style from '../../utils/Style';
|
|
5
|
+
import type { HStackProps } from './layout.types';
|
|
6
|
+
|
|
7
|
+
export const HStack = forwardRef<ViewRef, HStackProps>((props, ref) => {
|
|
8
|
+
const { style, ...rest } = props;
|
|
9
|
+
|
|
10
|
+
return <View ref={ref} style={[elementStyle.base, style]} {...rest} />;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
HStack.displayName = 'HStack';
|
|
14
|
+
|
|
15
|
+
const elementStyle = Style.create({
|
|
16
|
+
base: {
|
|
17
|
+
flexDirection: 'row',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import type { ViewRef } from '../../types/general.types';
|
|
4
|
+
import Style from '../../utils/Style';
|
|
5
|
+
import type { VStackProps } from './layout.types';
|
|
6
|
+
|
|
7
|
+
export const VStack = forwardRef<ViewRef, VStackProps>((props, ref) => {
|
|
8
|
+
const { style, ...rest } = props;
|
|
9
|
+
|
|
10
|
+
return <View ref={ref} style={[elementStyle.base, style]} {...rest} />;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
VStack.displayName = 'VStack';
|
|
14
|
+
|
|
15
|
+
const elementStyle = Style.create({
|
|
16
|
+
base: {
|
|
17
|
+
flexDirection: 'column',
|
|
18
|
+
},
|
|
19
|
+
});
|
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
// Export Components
|
|
2
|
+
export * from './components/Accordion/Accordion';
|
|
3
|
+
export * from './components/Accordion/AccordionItem';
|
|
4
|
+
export * from './components/Collapse';
|
|
5
|
+
export * from './components/Button/Button';
|
|
6
|
+
export * from './components/Button/DangerButton';
|
|
7
|
+
export * from './components/Button/GhostButton';
|
|
8
|
+
export * from './components/Button/PrimaryButton';
|
|
9
|
+
export * from './components/Button/SecondaryButton';
|
|
2
10
|
export * from './components/Card/Card';
|
|
11
|
+
export * from './components/Divider/Divider';
|
|
12
|
+
export * from './components/Layout/HStack';
|
|
13
|
+
export * from './components/Layout/VStack';
|
|
14
|
+
export * from './components/Surface/Surface';
|
|
15
|
+
|
|
16
|
+
// types
|
|
17
|
+
export * from './components/Accordion/type';
|
|
18
|
+
export * from './components/Collapse/types';
|
|
19
|
+
export * from './components/Button/types';
|
|
20
|
+
export * from './components/Card/types';
|
|
21
|
+
export * from './components/Divider/types';
|
|
22
|
+
export * from './components/Layout/layout.types';
|
|
23
|
+
export * from './components/Surface/types';
|
|
24
|
+
export * from './types/general.types';
|
|
3
25
|
|
|
4
26
|
// Provider
|
|
5
27
|
export * from './providers/ThemeProvider';
|